From 02d7adbdca1884bcb4105df85ebf630f2dbe9bc3 Mon Sep 17 00:00:00 2001 From: Udit Karode Date: Sun, 9 Apr 2023 19:22:30 +0530 Subject: [PATCH] feat: add response timeout * also switch to env vars --- .env.example | 11 ++++++++++ package.json | 3 +++ src/ai.ts | 51 ++++++++++++++++++++++++++++++++------------ src/config.ts | 18 ++++++++++++++++ src/index.ts | 24 +++++++++++++-------- variables.example.ts | 22 ------------------- yarn.lock | 24 +++++++++++++++++++++ 7 files changed, 108 insertions(+), 45 deletions(-) create mode 100644 .env.example create mode 100644 src/config.ts delete mode 100644 variables.example.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..98702f0 --- /dev/null +++ b/.env.example @@ -0,0 +1,11 @@ +# Run `document.cookie` in the console on bing.com/chat +# and paste it here. You must be logged in and have +# access to Bing Chat! +BING_COOKIE= + +# The bot token you obtained from BotFather +TG_TOKEN= + +# A comma separated list of chat IDs you want to allow +# to allow usage in all chats, set this to "all" +ALLOWED_CHATS= diff --git a/package.json b/package.json index bab4c8e..b88d525 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "test": "tsx src/test.ts" }, "devDependencies": { + "@types/dotenv-safe": "^8.1.2", "@types/node": "^18.15.9", "prettier": "^2.8.7", "tsx": "^3.12.6", @@ -19,6 +20,8 @@ }, "dependencies": { "bing-chat": "^0.2.3", + "dotenv-safe": "^8.2.0", + "p-timeout": "^6.1.1", "telegraf": "^4.12.2" } } diff --git a/src/ai.ts b/src/ai.ts index d1c8c2f..ce8322e 100644 --- a/src/ai.ts +++ b/src/ai.ts @@ -1,14 +1,12 @@ import { done, firstPos, queue } from "./queue.js"; import { transformBingResponse } from "./transformers.js"; -import { BingChat, ChatMessage } from "bing-chat"; +import { ChatMessage } from "bing-chat"; import { Context } from "telegraf"; import { bold, fmt } from "telegraf/format"; import { Update } from "typegram"; -import { BING_COOKIE } from "../variables.js"; - -export const bingChat = new BingChat({ - cookie: BING_COOKIE.replaceAll('"', "").trim(), -}); +import { bingChat } from "./config.js"; +import pTimeout from "p-timeout"; +import { Message } from "telegraf/types"; const chats: Record< number, @@ -16,10 +14,21 @@ const chats: Record< > = {}; export const variants = ["creative", "balanced", "precise"]; + +const defaultTimeoutMs = 50 * 1000; const defaultVariant = "Balanced"; -export async function ai(ctx: Context, prompt: string) { +export async function ai( + ctx: Context, + prompt: string, +): Promise { try { + if (!prompt) { + return await ctx.reply( + "No prompt provided! Please read /help for more information.", + ); + } + const chatId = ctx.chat!.id; chats[chatId] ||= { index: 1 }; @@ -33,19 +42,33 @@ export async function ai(ctx: Context, prompt: string) { fmt`${bold`[${chats[chatId].index++}]`} Running prompt...`, ); - const bingRes = await bingChat.sendMessage( - prompt, - Object.assign({}, chats[chatId].res, { - variant: chats[chatId].variant ?? defaultVariant, - }), - ); + let bingRes: ChatMessage; + try { + bingRes = await pTimeout( + bingChat.sendMessage( + prompt, + Object.assign({}, chats[chatId].res, { + variant: chats[chatId].variant ?? defaultVariant, + }), + ), + { + milliseconds: defaultTimeoutMs, + message: `No response from Bing, waited ${ + defaultTimeoutMs / 1000 + } seconds`, + }, + ); + } catch (e) { + return await ctx.reply((e as Error).message || "Something went wrong"); + } + chats[chatId].res = bingRes; const tgRes = (() => { if (bingRes.text === prompt) { // Bing Chat often replies with the exact prompt // in case it's unable to continue the conversation. - return "Something went wrong. Starting a new chat with /newchat is recommended."; + return "Bing replied with the exact text as your prompt. This usually happens when the AI is unable to continue the conversation. Starting a new chat with /newchat is recommended."; } if (!bingRes.text) { diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..a48534e --- /dev/null +++ b/src/config.ts @@ -0,0 +1,18 @@ +import { BingChat } from "bing-chat"; +import dotenv from "dotenv-safe"; +import { Context, Telegraf } from "telegraf"; +import { Update } from "typegram"; + +dotenv.config(); + +export const bingChat = new BingChat({ cookie: process.env.BING_COOKIE! }); + +export const bot: Telegraf> = new Telegraf( + process.env.TG_TOKEN!, +); + +const allowedChatsConfig = process.env.ALLOWED_CHATS!; +export const allowedChats = + allowedChatsConfig.toLowerCase() === "all" + ? undefined + : allowedChatsConfig.split(",").map(Number).filter(Boolean); diff --git a/src/index.ts b/src/index.ts index bd543c8..4659e11 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,19 @@ import { bold, code, fmt, underline } from "telegraf/format"; -import { ALLOWED_CHAT_IDS, TG_TOKEN } from "../variables.js"; import { ai, getVariant, newChat, setVariant, variants } from "./ai.js"; import { checkOrigin } from "./check-origin.js"; import { message } from "telegraf/filters"; import { useNewReplies } from "telegraf/future"; -import { Telegraf } from "telegraf"; - -function args(cmd: string) { - return cmd.split(" ").splice(1).join(" "); -} +import { allowedChats, bot } from "./config.js"; async function main() { - const bot = new Telegraf(TG_TOKEN.trim()); bot.use(useNewReplies()); - if (typeof ALLOWED_CHAT_IDS != "string") { - bot.use(checkOrigin(ALLOWED_CHAT_IDS)); + if (allowedChats) { + console.log("Usage allowed in chats: "); + console.log(allowedChats); + bot.use(checkOrigin(allowedChats)); + } else { + console.log("Usage allowed in all chats"); } bot.command("ai", async ctx => { @@ -81,6 +79,10 @@ The variant command accepts the name of any of these 3 variants in a case-insens ); }); + bot.catch(err => { + console.log(err); + }); + bot.launch(); console.log("Bot running!"); console.log("Use ^C to stop"); @@ -90,4 +92,8 @@ The variant command accepts the name of any of these 3 variants in a case-insens process.once("SIGTERM", () => bot.stop("SIGTERM")); } +function args(cmd: string) { + return cmd.split(" ").splice(1).join(" "); +} + main(); diff --git a/variables.example.ts b/variables.example.ts deleted file mode 100644 index 91c0933..0000000 --- a/variables.example.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const ALLOWED_CHAT_IDS: string | number[] = (() => { - // If you want to allow usage in all chats, uncomment the line below: - // return "all"; - - return [ - // Enter the chat IDs you want to allow usage in here. - ]; -})(); - -// Enter 'document.cookie' in the console on bing.com, -// and paste the result here. You must be logged in to -// your Microsoft account and have access to Bing Chat. -// PS: don't worry about the newlines or double quotes (" "), they will be trimmed -export const BING_COOKIE = ` - -`; - -// Paste the bot token you got from BotFather in here. -// PS: don't worry about the newlines, they will be trimmed -export const TG_TOKEN = ` - -`; diff --git a/yarn.lock b/yarn.lock index 0b5a4e8..9d7aa39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -136,6 +136,13 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.13.tgz#eca2698440d931b5a0fb8a5a29388c17adcb6bf5" integrity sha512-pZ/NIgz861XaUPlIkPFjP55nJ4PJa0o/CD4zgeRb1Q9FVE+8GvdB6ifJcK05jRhny5hKExhnRFIdgHmmCYH8vg== +"@types/dotenv-safe@^8.1.2": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/dotenv-safe/-/dotenv-safe-8.1.2.tgz#72f126969f445af5654efd3167deabc2cbc6c24e" + integrity sha512-R/B/wIMda6lRE2P1H0vwSoJsV78IOkhccE4vIvmKZQNXOIjiU0QyJsUXwSotBxOPZFZ/oOnjCa3+kK5kVJwGyw== + dependencies: + dotenv "^8.2.0" + "@types/node@^18.15.9": version "18.15.11" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" @@ -185,6 +192,18 @@ debug@^4.3.4: dependencies: ms "2.1.2" +dotenv-safe@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/dotenv-safe/-/dotenv-safe-8.2.0.tgz#8d548c7318a62c09a66c4dc8c31864cc007c78ba" + integrity sha512-uWwWWdUQkSs5a3mySDB22UtNwyEYi0JtEQu+vDzIqr9OjbDdC2Ip13PnSpi/fctqlYmzkxCeabiyCAOROuAIaA== + dependencies: + dotenv "^8.2.0" + +dotenv@^8.2.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" + integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== + esbuild@~0.17.6: version "0.17.13" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.13.tgz#463066919a5567e8d1f4781004129da7fc8774b6" @@ -250,6 +269,11 @@ p-timeout@^4.1.0: resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-4.1.0.tgz#788253c0452ab0ffecf18a62dff94ff1bd09ca0a" integrity sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw== +p-timeout@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-6.1.1.tgz#bcee5e37d730f5474d973b6ff226751a1a5e6ff1" + integrity sha512-yqz2Wi4fiFRpMmK0L2pGAU49naSUaP23fFIQL2Y6YT+qDGPoFwpvgQM/wzc6F8JoenUkIlAFa4Ql7NguXBxI7w== + prettier@^2.8.7: version "2.8.7" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450"