From c3c6f3e1a63681ded0502a5ef22baf187a8549b7 Mon Sep 17 00:00:00 2001 From: Krishnendu Das <86651039+itskdhere@users.noreply.github.com> Date: Sun, 12 Feb 2023 12:59:19 +0530 Subject: [PATCH] v2.4.0 - Added `onProgress` Typing Effect Some minor changes Beautification --- env.example => .env.example | 22 ++++++-- .github/note.md | 5 +- README.md | 13 ++++- index.js | 110 +++++++++++++++++++++--------------- package-lock.json | 4 +- package.json | 7 ++- 6 files changed, 102 insertions(+), 59 deletions(-) rename env.example => .env.example (65%) diff --git a/env.example b/.env.example similarity index 65% rename from env.example rename to .env.example index 5f7fad2..06d4932 100644 --- a/env.example +++ b/.env.example @@ -3,22 +3,32 @@ # ---------------------------------------:Environment Variables:------------------------------------ # -------------------------------------------------------------------------------------------------- # Discord BOT Credentials from "Discord Developer Portal" -DISCORD_CLIENT_ID=... -DISCORD_BOT_TOKEN=... +DISCORD_CLIENT_ID= +DISCORD_BOT_TOKEN= # -------------------------------------------------------------------------------------------------- # For 'Google' login type provide the Gmail-ID and the google account password of the Gmail-ID # For 'OpenAI' login type provide the email and password associated with your OpenAI account -EMAIL=... -PASSWORD=... +EMAIL= +PASSWORD= # -------------------------------------------------------------------------------------------------- # Login Type ( Value: 'google' or 'openai' ) -LOGIN_TYPE=... +LOGIN_TYPE= # -------------------------------------------------------------------------------------------------- # ChatGPT Account Type ( Value: 'free' or 'pro' ) -ACCOUNT_TYPE=... +ACCOUNT_TYPE= + +# -------------------------------------------------------------------------------------------------- +# Bot Typing Effect i.e Stream ChatGPT response in real-time ( Value: 'true' or 'false' ) +# TYPING_EFFECT=true + +# -------------------------------------------------------------------------------------------------- +# Change these if you know what you're doing +DISCORD_MAX_RESPONSE_LENGTH=2000 +UWU=true +CHATGPT_INITIAL_PROMPT=hi \ No newline at end of file diff --git a/.github/note.md b/.github/note.md index e0c0089..5954538 100644 --- a/.github/note.md +++ b/.github/note.md @@ -1,3 +1,6 @@ ## Important !! -To run This **CodeQL** WorkFlow goto `YOUR_REPO_URL/actions` \ No newline at end of file +### To Run These GitHub Actions WorkFlows: + +- Goto the `Actions` tab of your forked repo, i.e. `YOUR_REPO_URL/actions` +- Then click I `understand my workflows, go ahead and enable them` \ No newline at end of file diff --git a/README.md b/README.md index c3ad29b..8b9af26 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,9 @@ This BOT uses [ChatGPT-API v3](https://github.com/transitive-bullshit/chatgpt-ap ## ✨Features 🔥 Use slash command `/ask` to ask questions in any channel. - 💥 This uses **puppeteer** to automate the login process. Auto Solve CAPTCHA ✨ + ✨ ChatGPT onProgress Typing Effect. Chalk, Figlet & Gradient-String for decoration. + + 💥 This uses **puppeteer** to automate the login process. Auto Solve CAPTCHA. 🔑 Uses Single ChatGPT Conversation Thread per Session. @@ -44,7 +46,7 @@ This BOT uses [ChatGPT-API v3](https://github.com/transitive-bullshit/chatgpt-ap - [Node.js v18](https://nodejs.org/) - [Google Chrome](https://www.google.com/chrome/) - [OpenAI Account](https://chat.openai.com/) - - Atleast 1vCPU , 0.5GB RAM and 0.5GB Storage (For the **BOT Only**) + - Atleast 1vCPU , 0.5GB RAM and 0.5GB Storage for the Bot. ### Steps: 0. Create **New Application** [BOT] from [Discord Developer Portal](https://discord.com/developers/applications) and add this to your Discord Server with proper *Bot Permissions* and *Privileged Gateway Intents*. @@ -71,7 +73,12 @@ npm install ```bash npm run start ``` -6. Complete the **CAPTCHA** Manually *or* [Use This Automation](https://github.com/transitive-bullshit/chatgpt-api#captchas). If you're using Google Login then you can skip this step. +- *or,* During development: +```bash +npm run dev +``` + +6. Complete the **CAPTCHA** Manually *or* [Use This Automation](https://github.com/transitive-bullshit/chatgpt-api/tree/v3#captchas). 7. Use the BOT 🎉 diff --git a/index.js b/index.js index 4f572bf..dd99d2f 100644 --- a/index.js +++ b/index.js @@ -1,14 +1,13 @@ // Imports import dotenv from 'dotenv'; dotenv.config(); import { ChatGPTAPIBrowser } from 'chatgpt'; -import { Client, GatewayIntentBits, REST, Routes, Partials, ActivityType} from 'discord.js'; +import { Client, GatewayIntentBits, REST, Routes, Partials, ActivityType } from 'discord.js'; import axios from 'axios'; import chalk from 'chalk'; import figlet from 'figlet'; import gradient from 'gradient-string'; // Defines -const MAX_RESPONSE_LENGTH = 2000 // Discord Max 2000 Characters let res; // ChatGPT Thread Identifier // Discord Slash Commands Defines @@ -31,7 +30,7 @@ const commands = [ } ]; -// Initialize OpenAI Session & New ChatGPT Thread +// Initialize OpenAI Session async function initOpenAI() { const loginType = process.env.LOGIN_TYPE; const accountType = process.env.ACCOUNT_TYPE; @@ -77,7 +76,7 @@ async function initOpenAI() { } } -// Initialize Discord Application Commands +// Initialize Discord Application Commands & New ChatGPT Thread async function initDiscordCommands(api) { const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_BOT_TOKEN); try { @@ -90,26 +89,28 @@ async function initDiscordCommands(api) { } catch (error) { console.log(chalk.red(error)); } - - res = await api.sendMessage('Hi'); // Init New Thread + + res = await api.sendMessage(process.env.CHATGPT_INITIAL_PROMPT); // Init New Thread } -// Main Function (Execution Starts Here) +// Main Function (Execution Starts From Here) async function main() { - console.log(gradient.pastel.multiline(figlet.textSync('ChatGPT', { - font: 'univers', - horizontalLayout: 'default', - verticalLayout: 'default', - width: 100, - whitespaceBreak: true - }))); + if (process.env.UWU === 'true') { + console.log(gradient.pastel.multiline(figlet.textSync('ChatGPT', { + font: 'univers', + horizontalLayout: 'default', + verticalLayout: 'default', + width: 100, + whitespaceBreak: true + }))); + } - const chatGTP = await initOpenAI().catch(error => { - console.error(error) - process.exit() - }) + const api = await initOpenAI().catch(error => { + console.error(error); + process.exit(); + }); - await initDiscordCommands(chatGTP).catch(e => { console.log(e) }); + await initDiscordCommands(api).catch(e => { console.log(e) }); const client = new Client({ intents: [ @@ -139,12 +140,14 @@ async function main() { client.user.setActivity(interaction.user.tag, { type: ActivityType.Watching }); + interaction.channel.sendTyping(); + switch (interaction.commandName) { case "ask": - ask_Interaction_Handler(interaction) + ask_Interaction_Handler(interaction); break; case "ping": - ping_Interaction_Handler(interaction) + ping_Interaction_Handler(interaction); break; default: await interaction.reply({ content: 'Command Not Found' }); @@ -165,17 +168,17 @@ async function main() { console.log("UserId : " + interaction.user.id); console.log("User : " + interaction.user.tag); console.log("Question : " + question); - // TODO: send to DB + try { - await interaction.reply({ content: "ChatGPT Is Processing Your Question..." }); - askQuestion(question, async (content) => { + await interaction.reply({ content: `${client.user.username} Is Processing Your Question...` }); + askQuestion(question, interaction, async (content) => { console.log("Response : " + content.response); console.log("---------------End---------------"); - if (content.length >= MAX_RESPONSE_LENGTH) { - await interaction.editReply({ content: "The answer to this question is very long, so I will answer by dm." }); + if (content.length >= process.env.DISCORD_MAX_RESPONSE_LENGTH) { + await interaction.editReply({ content: "The answer to this question is very long, so I'll answer by DM." }); splitAndSendResponse(content.response, interaction.user); } else { - await interaction.editReply(`${interaction.user.tag}: ${question}\n\nChatGPT: ${content.response}`); + await interaction.editReply(`**${interaction.user.tag}:** ${question}\n**${client.user.username}:** ${content.response}\n`); } client.user.setActivity('/ask'); // TODO: send to DB @@ -185,36 +188,51 @@ async function main() { } } - function askQuestion(question, cb) { + function askQuestion(question, interaction, cb) { let tmr = setTimeout((e) => { cb("Oppss, something went wrong! (Timeout)") console.error(chalk.red(e)) - }, 100000) - - chatGTP.sendMessage(question, { - conversationId: res.conversationId, - parentMessageId: res.messageId - }).then((response) => { - clearTimeout(tmr) - res = response; - cb(response) - }).catch((err) => { - cb("Oppss, something went wrong! (Error)") - console.error(chalk.red("AskQuestion Error:" + err)) - }) + }, 100000); + + if (process.env.TYPING_EFFECT === 'true') { + api.sendMessage(question, { + conversationId: res.conversationId, + parentMessageId: res.messageId, + onProgress: (partialResponse) => { + interaction.editReply(`**${interaction.user.tag}:** ${question}\n**${client.user.username}:** ${partialResponse?.response}`); + } + }).then((response) => { + clearTimeout(tmr); + res = response; + cb(response); + }).catch((err) => { + cb("Oppss, something went wrong! (Error)"); + console.error(chalk.red("AskQuestion Error:" + err)); + }) + } else { + api.sendMessage(question, { + conversationId: res.conversationId, + parentMessageId: res.messageId + }).then((response) => { + clearTimeout(tmr); + res = response; + cb(response); + }).catch((err) => { + cb("Oppss, something went wrong! (Error)") + console.error(chalk.red("AskQuestion Error:" + err)) + }) + } } async function splitAndSendResponse(resp, user) { while (resp.length > 0) { - let end = Math.min(MAX_RESPONSE_LENGTH, resp.length) + let end = Math.min(process.env.DISCORD_MAX_RESPONSE_LENGTH, resp.length) await user.send(resp.slice(0, end)) resp = resp.slice(end, resp.length) } } } -main() // Call Main function - // Discord Rate Limit Check setInterval(() => { axios @@ -229,3 +247,7 @@ setInterval(() => { }); }, 30000); // Check Every 30 Second + +main() // Call Main function + +// ---EoC--- \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 40b90d8..8867653 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "chatgpt-discord-bot", - "version": "2.2.0", + "version": "2.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "chatgpt-discord-bot", - "version": "2.2.0", + "version": "2.3.0", "license": "MIT", "dependencies": { "@types/node": "^18.0.6", diff --git a/package.json b/package.json index 3130f0e..4f5c703 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chatgpt-discord-bot", - "version": "2.3.0", + "version": "2.4.0", "description": "ChatGPT Discord BOT", "author": "KD", "license": "MIT", @@ -9,7 +9,8 @@ "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "node index.js" + "start": "node index.js", + "dev": "node --watch index.js" }, "dependencies": { "@types/node": "^18.0.6", @@ -23,4 +24,4 @@ "node-fetch": "^3.2.6", "puppeteer": "^19.5.2" } -} +} \ No newline at end of file