feat: add response timeout

* also switch to env vars
This commit is contained in:
Udit Karode 2023-04-09 19:22:30 +05:30
parent bb4800505b
commit 02d7adbdca
No known key found for this signature in database
GPG Key ID: 864BAA48465205F0
7 changed files with 108 additions and 45 deletions

11
.env.example Normal file
View File

@ -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=

View File

@ -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"
}
}

View File

@ -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<Update>, prompt: string) {
export async function ai(
ctx: Context<Update>,
prompt: string,
): Promise<void | Message> {
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<Update>, prompt: string) {
fmt`${bold`[${chats[chatId].index++}]`} Running prompt...`,
);
const bingRes = await bingChat.sendMessage(
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) {

18
src/config.ts Normal file
View File

@ -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<Context<Update>> = 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);

View File

@ -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();

View File

@ -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 = `
`;

View File

@ -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"