From 70ffc8b068412154c34287a63e69692d59e4b981 Mon Sep 17 00:00:00 2001 From: Genesaret Johnes Date: Sun, 25 Feb 2024 15:55:44 +0700 Subject: [PATCH] feat-and-refine: Log & Docs Added feature : Logging, new command .log Refined Documentation --- README.md | 78 +++---------------- docs/CONFIGURATIONS.md | 2 + docs/INSTALLATION.md | 2 +- docs/QUICKSTART.md | 4 +- docs/README.md | 17 ++-- docs/REQUIREMENTS.md | 5 +- docs/USAGE.md | 29 ++++++- docs/_navbar.md | 3 +- src/command-hive.ts | 21 +++-- src/command-router.ts | 3 +- src/env.ts | 2 +- .../external/image-to-sticker-meme.ts | 9 ++- src/services/external/quote-v1.ts | 12 ++- src/services/external/textpro.ts | 19 +++-- src/services/internal/log.ts | 30 +++++++ src/utils/logger.ts | 65 ++++++++++++++++ 16 files changed, 192 insertions(+), 109 deletions(-) create mode 100644 src/services/internal/log.ts create mode 100644 src/utils/logger.ts diff --git a/README.md b/README.md index 8cc98fd..480f8fc 100644 --- a/README.md +++ b/README.md @@ -1,81 +1,23 @@ -

- +

-# WhatsApp Bot by Node.js + whatsapp-web.js -> Since this project still on development 🚧, I do not have any briliant names for it. Maybe soon, stay tuned ! +> This project still on development 🚧, so it might have a massive changes, stay tuned ! -Documentation Page : [Click Here ▶](https://gensart-ai.github.io/whatsapp-bot) -#### Just an automated WhatsApp reply system based on text sent that built under Node.js, with help of a library called [whatsapp-web.js](https://wwebjs.dev/). +#### WhatsApp bot powered by Node.js, with several daily commands that might be useful for you ! [![forthebadge](https://forthebadge.com/images/badges/made-with-javascript.png)](https://nodejs.org) [![forthebadge](https://forthebadge.com/images/badges/powered-by-electricity.png)](https://web.pln.co.id/tentang-kami/profil-perusahaan) [![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](http://forthebadge.com) -# Technology Used -node.js typescript - - -# Table of contents -- [Requirements](#requirements) -- [Installation](#installation) -- [Configurations](#configurations) -- [Quickstart](#quickstart) -- [Usage](#usage) -- [Contributing](#contributing) -- [License](#license) - -# Requirements -[(Back to top)](#table-of-contents) -This project requires **Node.js** to run, I use **Node v20.10** on Windows 10 and **Debian 11** too and it works fine. I haven't tested it yet on different version or environment than mine, but you may try it and report it to me, so I can update this details by you :). -Oh also, make sure you have installed **NPM** too. Usually **Node.js** includes **NPM** so you don't need to install it again. +# Technology Used +node.js typescript -**🔴 IMPORTANT NOTICE 🔴** -This project greatly having use of [whatsapp-web.js](https://wwebjs.dev/), and maybe **if you are running on a `no-gui` Linux image (Server, or Linux OS that do not installed GUI system)**, you may need to see and follow this page first : [Click Me](https://wwebjs.dev/guide/#installation-on-no-gui-systems) +# Overview +!> This application uses `whatsapp-web.js` as a primary library. Keep in mind if you want to use this app, you did already know that **WhatsApp terms & conditions do not allow any bots or automation** on its services. So, I do not responsible for any banning happen to your WhatsApp account by using this app. I strongly suggested you to use this app with your WhatsApp backup number. I use my second number for this and still safe until now. -# Installation -[(Back to top)](#table-of-contents) -First thing you do, clone this repo by using : -```bash -git clone https://github.com/gensart-ai/whatsapp-bot.git -``` -Do not know how to clone in GitHub ? maybe you can check this page for a quickstart : [Click Me!](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) +Current Stable Version : `1.0.1` +Look at the sidebar for more docs. +(Can't see the sidebar on mobile ? The button is on your bottom left screen :)) -After that, go to the repo root directory and do the command below to install the packages needed for the project : -```bash -npm i -``` And it's done. -# Configurations -[(Back to top)](#table-of-contents) -As the current version, I put some global configurations on a Typescript file in : `./src/env.ts`. You can change the bot name, imgBb keys, etc. - -For `imgBBKey`, you can retrieve the key from [here](https://api.imgbb.com/), but you may need to sign up first if you didn't have any ImgBB account before. - -# Quickstart -[(Back to top)](#table-of-contents) -If you have done the [Installation](#installation) and have checked the [Configurations](#configurations), you can open the terminal at root directory of the project and do the command below to build the `src` to JavaScript to `dist`: -```bash -npm run build -``` -After that, you can run the project using this command : -```bash -npm run serve -``` -If you succeed, you should see some message like this : -![WhatsApp QR Code shown on terminal](https://i.ibb.co/K5rzdxp/readme-quickstart-1.png) -The terminal will shows a QR Code to be scanned with your WhatsApp app (doing it like scanning for WhatsApp Web). And if project succeed the QR, it will output : -`System is online!` -And congrats, your WhatsApp number (that scan the QR) is successfully integrated with the project !🎉 -# Usage -[(Back to top)](#table-of-contents) -As of current version, you can send a message : `.help` to an associated WhatsApp number with the project, you can see the detail of features on there ! :) - -# Contributing -[(Back to top)](#table-of-contents) -Your contributions are always welcome! Please have a look at the [contribution guidelines](CONTRIBUTING.md). :tada: - -# License -[(Back to top)](#table-of-contents) -The MIT License (MIT) 2017 - [Genesaret Johnes](https://github.com/gensart-ai/). Please have a look at the [license](LICENSE.md) for more details. diff --git a/docs/CONFIGURATIONS.md b/docs/CONFIGURATIONS.md index 9127592..5fdd418 100644 --- a/docs/CONFIGURATIONS.md +++ b/docs/CONFIGURATIONS.md @@ -2,6 +2,8 @@ > 🚧 Do note that this project is still on development, it **might** have impact changes, including this configurations method. +!> Also note, that I think the current configuration method is considered **NOT SAFE**. Why ? because it still on development, and I need to record the changes to version control, and the environment data will be recorded too. *"Then why you use this ?"*, hehe, I build this while learning Node and TS environment too, so, maybe soon if I have any idea to secure it more safe, I'll do it. Though, you may provide some feedback / suggestion for this, I may be appreciate that 💖. + As of current version, I put some global configurations needed for the project on a Typescript file in : `./src/env.ts`. You can do several things below : diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 1867744..d2a90f3 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -11,4 +11,4 @@ After that, go to the repo root directory on your system and do the command belo npm i ``` -And you're done ! Next is for [configuration](./CONFIGURATIONS.md). \ No newline at end of file +And you're done ! Next is for [pre-configuration](./CONFIGURATIONS.md). \ No newline at end of file diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md index 74e2c22..89b6700 100644 --- a/docs/QUICKSTART.md +++ b/docs/QUICKSTART.md @@ -4,11 +4,11 @@ This project made in Typescript. If you have done the [Installation](./INSTALLAT ```terminal npm run build ``` -After that, you can run the project using this command (this command executes the compiled main point file in `dist/index.js`) : +After that, you can run the project using this command (this command executes the compiled main point file in `dist/index.js`) on the terminal : ```terminal npm run serve ``` -If you succeed, you should see some message like this : +If you succeed, you should see some message like this in your terminal : ![WhatsApp QR Code shown on terminal](https://i.ibb.co/K5rzdxp/readme-quickstart-1.png) The terminal will shows a QR Code to be scanned with your WhatsApp app (doing it like scanning for WhatsApp Web). And if project succeed the QR, it will output : ```terminal diff --git a/docs/README.md b/docs/README.md index 5beb584..a3184e9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,26 +1,21 @@ + +> This project still on development 🚧, so it might have a massive changes, stay tuned ! -# whatsapp-bot #### WhatsApp bot powered by Node.js, with several daily commands that might be useful for you ! [![forthebadge](https://forthebadge.com/images/badges/made-with-javascript.png)](https://nodejs.org) [![forthebadge](https://forthebadge.com/images/badges/powered-by-electricity.png)](https://web.pln.co.id/tentang-kami/profil-perusahaan) [![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](http://forthebadge.com) + # Technology Used node.js typescript -!> This application uses `whatsapp-web.js` as a primary library. Keep in mind if you want to use this app, you did already know that **WhatsApp terms & conditions do not allow any bots or automation** on its services. Make sure you use this app with your WhatsApp backup number to prevent banning to your primary WhatsApp account. I use my second number for this and still safe until now. +# Overview +!> This application uses `whatsapp-web.js` as a primary library. Keep in mind if you want to use this app, you did already know that **WhatsApp terms & conditions do not allow any bots or automation** on its services. So, I do not responsible for any banning happen to your WhatsApp account by using this app. I strongly suggested you to use this app with your WhatsApp backup number. I use my second number for this and still safe until now. -Current Stable Version : `1.0` +Current Stable Version : `1.0.1` Look at the sidebar for more docs. (Can't see the sidebar on mobile ? The button is on your bottom left screen :)) And it's done. - -# Contributing -[(Back to top)](#table-of-contents) -Your contributions are always welcome! Please have a look at the [contribution guidelines](CONTRIBUTING.md). :tada: - -# License -[(Back to top)](#table-of-contents) -The MIT License (MIT) 2017 - [Genesaret Johnes](https://github.com/gensart-ai/). Please have a look at the [license](LICENSE.md) for more details. diff --git a/docs/REQUIREMENTS.md b/docs/REQUIREMENTS.md index dc80c16..50c4306 100644 --- a/docs/REQUIREMENTS.md +++ b/docs/REQUIREMENTS.md @@ -4,12 +4,15 @@ You need : - Node.js v18++ - NPM installed on your device +- [ffmpeg](https://ffmpeg.org/) (Windows users may need this) - For multimedia support ## Long to short This project requires **Node.js** to run, I use **Node v20.10** on Windows 10 and **Debian 11** too and it works fine. I haven't tested it yet on different version or environment than mine, but you may try it and report it to me, so I can update this details by you :). You can use this [link](https://nodejs.org/en) to go to Node.js homepage for installation or more details. -Oh also, make sure you have installed **NPM** too. Usually **Node.js** includes **NPM** so you don't need to install it again. +Oh also, make sure you have installed **NPM** too. Usually **Node.js** includes **NPM** so you don't need to install it again. + +And i often experience errors when testing multimedia with this app on Windows 10 environment, but not on Debian 11. My assumption going to **ffmpeg** problem, maybe you can install that if you experience an error when dealing with multimedia thing. ## **🔴 IMPORTANT NOTICE 🔴** This project greatly having use of [whatsapp-web.js](https://wwebjs.dev/), and maybe **if you are running on a `no-gui` Linux image (Server, or Linux OS that did not installed GUI system)**, you may need to see and follow this page first : [Click Me](https://wwebjs.dev/guide/#installation-on-no-gui-systems) \ No newline at end of file diff --git a/docs/USAGE.md b/docs/USAGE.md index a01e0ab..823edf8 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -4,4 +4,31 @@ After the project is installed and configured, you can start the bot by running As of current version, I have built several built-in features in it too, some are these : -> Come Soon \ No newline at end of file +``` +*== Quotes ==* +.quotes +*== AI Feature ==* +.gemini - *TEMPORARY DISABLED* - +*== Translate ==* +.indotoeng [text indo] - Translate Indonesia to English +.engtoindo [text English] - Translate English to Indonesia +*== Media(Image/Short Video) to Sticker ==* +.s (send with the media with command as the caption) +.st (send with the media with command as the caption) +*== TextPro (Create styled-text in an image, add !sticker after the command to create as sticker) ==* +.neon +.lunar +.thunder +.shadow +.snow +.winter +.frozen +.artistic-typography +.gradient-neon +.blackpink +.sliced-effect +.red-batman +.neon-valentine +.neon-cube +.blackpink-logo +``` \ No newline at end of file diff --git a/docs/_navbar.md b/docs/_navbar.md index b8de381..09ab11d 100644 --- a/docs/_navbar.md +++ b/docs/_navbar.md @@ -1,2 +1 @@ -* Ever heard of me ? -* You must be mistaken :). \ No newline at end of file +* [SoraErlyana Repo GitHub](https://github.com/gensart-ai/whatsapp-bot) \ No newline at end of file diff --git a/src/command-hive.ts b/src/command-hive.ts index 3c0d679..6378ea3 100644 --- a/src/command-hive.ts +++ b/src/command-hive.ts @@ -1,18 +1,23 @@ import { Client, Message } from 'whatsapp-web.js' -import { getForismaticQuotes } from 'services/external/quote-v1' -import { textProSingleTextRouter } from 'services/external/textpro' -import commandGuide from 'services/internal/command-guide' -import imageToSticker from 'services/internal/image-to-sticker' -import { translateEnglishToIndo, translateIndoToEnglish } from './services/external/translate' -import { imageToStickerText } from './services/external/image-to-sticker-meme' -import { geminiTextOnly } from './services/external/gemini' +import { getForismaticQuotes } from '@services/external/quote-v1' +import { textProSingleTextRouter } from '@services/external/textpro' +import commandGuide from '@services/internal/command-guide' +import imageToSticker from '@services/internal/image-to-sticker' +import { translateEnglishToIndo, translateIndoToEnglish } from '@services/external/translate' +import { imageToStickerText } from '@services/external/image-to-sticker-meme' +import { geminiTextOnly } from '@services/external/gemini' +import { log } from '@services/internal/log' type Commands = { - [key: string] : (client: Client, message: Message) => any + [key: string]: (client: Client, message: Message) => any } type Executor = (client: Client, message: Message) => void const commands: Commands = { + + // ! Administrative commands + '.log': log, + // * Help '.help': commandGuide, diff --git a/src/command-router.ts b/src/command-router.ts index 01385f7..756d5fd 100644 --- a/src/command-router.ts +++ b/src/command-router.ts @@ -21,10 +21,11 @@ const routeCommand = async (client: Client, message: Message) => { if (extractedCommand in commands) { await commands[extractedCommand](client, message); } else { + const contact = await message.getContact(); wweb.sendMessage( client, message.from, - `${config.botShortName} tidak mengerti apa yang anda sampaikan :(. Harap ketik \`.help\` untuk mengetahui yang ${config.botShortName} pahami :)` + `${config.botShortName} tidak mengerti. Harap ketik \`.help\` untuk mengetahui yang ${config.botShortName} pahami, ${contact?.pushname ?? ''}!` ) } } diff --git a/src/env.ts b/src/env.ts index f0ccd9f..906828f 100644 --- a/src/env.ts +++ b/src/env.ts @@ -17,7 +17,7 @@ const environmentConfiguration: EnvironmentConfiguration = { botCodeName: 'SoraErlyana', imgBBKey: '8ceb73c518129ab2ca63c8cf9f7ea8a6', - googleAiStudioKey: 'AIzaSyBIMSDB4T7Gn7pfnTMLJHMp4qenjG0gN0Q' + googleAiStudioKey: '--' } export default environmentConfiguration \ No newline at end of file diff --git a/src/services/external/image-to-sticker-meme.ts b/src/services/external/image-to-sticker-meme.ts index 1d354ef..9c7066f 100644 --- a/src/services/external/image-to-sticker-meme.ts +++ b/src/services/external/image-to-sticker-meme.ts @@ -1,9 +1,10 @@ -import axios from 'axios' +import { Contact, MessageMedia } from 'whatsapp-web.js' +import axios, { AxiosError } from 'axios' import querystring from 'querystring' import config from '@/env' import * as wweb from '@utils/wweb' import { Executor } from '@/command-hive' -import { Contact, MessageMedia } from 'whatsapp-web.js' +import * as logger from '@utils/logger' type Meme = { image: string, @@ -154,6 +155,10 @@ const imageToStickerText: Executor = async (client, message) => { wweb.replyMessage(message, `${config.botShortName} perlu gambar untuk dijadikan stikernya, ${contact.pushname ?? ''}`) } } catch (error) { + const contact = await message.getContact(); + const err = error as AxiosError; + logger.logError('imageToStickerText - ' + err.message + ' by ' + contact?.pushname ?? 'unknown'); + wweb.replyMessage(message, `${config.botShortName} gagal memproses gambar yang anda tujukan, mohon coba lagi dengan mengirim gambar baru.`) } } diff --git a/src/services/external/quote-v1.ts b/src/services/external/quote-v1.ts index 8115b97..07ff31f 100644 --- a/src/services/external/quote-v1.ts +++ b/src/services/external/quote-v1.ts @@ -1,7 +1,8 @@ -import axios, { AxiosError } from 'axios'; -import { Executor } from '@/command-hive'; -import * as wweb from '@utils/wweb'; +import axios, { AxiosError } from 'axios' +import { Executor } from '@/command-hive' +import * as wweb from '@utils/wweb' import * as translate from '@utils/translation' +import * as logger from '@utils/logger' type Quote = { quote: string, @@ -31,7 +32,10 @@ const getForismaticQuotes: Executor = async (client, message) => { } } catch (e) { - const error = e as AxiosError | Error; + const contact = await message.getContact(); + const err = e as AxiosError | Error; + logger.logError('quoteV1Forismatic - ' + err.message + ' by ' + contact?.pushname ?? 'unknown'); + wweb.replyMessage(message, 'Gagal memuat quotes, silahkan coba lagi.') } } diff --git a/src/services/external/textpro.ts b/src/services/external/textpro.ts index 1c776e8..e4160ef 100644 --- a/src/services/external/textpro.ts +++ b/src/services/external/textpro.ts @@ -1,10 +1,11 @@ -import { AxiosError } from 'axios'; -import axiosInstance from 'utils/axios-instance'; -import { warningNoTextMessage, createTextProImage, TextProImageObject } from '@utils/textpro'; -import * as wweb from '@utils/wweb'; +import { Client, Contact, Message, MessageMedia } from 'whatsapp-web.js' +import { AxiosError } from 'axios' +import axiosInstance from '@utils/axios-instance' +import { warningNoTextMessage, createTextProImage, TextProImageObject } from '@utils/textpro' +import { Executor } from '@/command-hive' +import * as wweb from '@utils/wweb' +import * as logger from '@utils/logger' -import { Executor } from '@/command-hive'; -import { Client, Contact, Message, MessageMedia } from 'whatsapp-web.js'; /** * Routes textpro style based on the command. @@ -103,7 +104,11 @@ const textpro = async (client: Client, message: Message, url: string) => { wweb.replyMessage(message, new MessageMedia(image.mimetype, image.image)); } - } catch (e) { + } catch (error) { + const contact = await message.getContact(); + const err = error as AxiosError; + logger.logError('TextPro - ' + err.message + ' by ' + contact?.pushname ?? 'unknown'); + wweb.replyMessage(message, 'Gagal memproses gambar, silahkan coba lagi'); } } diff --git a/src/services/internal/log.ts b/src/services/internal/log.ts new file mode 100644 index 0000000..033b148 --- /dev/null +++ b/src/services/internal/log.ts @@ -0,0 +1,30 @@ +import { Executor } from '@/command-hive' +import * as logger from '@utils/logger' +import * as wweb from '@utils/wweb' +import config from '@/env' + +const log: Executor = async (client, message) => { + // Extract the commands + const text = message.body.split(' '); + const logType: string = text[1]; + let logFile: string; + + switch (logType) { + case 'error': + logFile = logger.ERROR_LOG_FILE; + default: + logFile = ''; + } + + const logs: string = logger.fetchLog(logFile); + + if (logs != '') { + wweb.replyMessage(message, logs) + } else { + wweb.replyMessage(message, `${config.botShortName} tidak melihat ada log saat ini.`) + } +} + +export { + log +} \ No newline at end of file diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..937c522 --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,65 @@ +import fs from 'fs' +import path from 'path' +import axios, { AxiosResponse } from 'axios' + +const LOGS_DIRECTORY: string = 'src/logs'; +const ERROR_LOG_FILE: string = 'error-log.txt'; + +type TimeResponse = { + year: number, + month: number, + day: number, + hour: number, + minute: number, + seconds: number +} + +/** + * Retrieve Indonesia time from timeapi.io + * @return {Promise} + */ +const retrieveIndonesiaTime = async (): Promise => { + try { + const response: AxiosResponse = await axios.get('https://timeapi.io/api/Time/current/zone?timeZone=Asia/Jakarta'); + const time: TimeResponse = response.data; + + return `${time.year}-${time.month}:${time.day} ${time.hour}:${time.minute}:${time.seconds}`; + } catch (error) { + return `NO_ESTABLISHED_TIME`; + } +} + +/** + * Log the error message to the file + * @param message The error message to be logged + */ +const logError = async (message: string) => { + const dateTime = await retrieveIndonesiaTime(); + message = `[${dateTime}] - ${message}\n` + + fs.appendFile(path.join(LOGS_DIRECTORY, ERROR_LOG_FILE), message, _ => { }); +} + +/** + * Get the log + * @param logFile Log file, take from available log files exported from logger + * @return {string} + */ +const fetchLog = (logFile: string): string => { + return fs.readFileSync(path.join(LOGS_DIRECTORY, logFile), 'utf-8'); +} + +/** + * Clear the reserved log file data + * @param logFile Log file, take from available log files exported from logger + */ +const clearLog = (logFile: string) => { + return fs.writeFileSync(path.join(LOGS_DIRECTORY, logFile), '', 'utf-8'); +} + +export { + logError, + fetchLog, + clearLog, + ERROR_LOG_FILE +} \ No newline at end of file