diff --git a/apps/chat.js b/apps/chat.js index 1bea8a3..c2ec19a 100644 --- a/apps/chat.js +++ b/apps/chat.js @@ -9,6 +9,7 @@ import SydneyAIClient from '../utils/SydneyAIClient.js' import { PoeClient } from '../utils/poe/index.js' import AzureTTS from '../utils/tts/microsoft-azure.js' import VoiceVoxTTS from '../utils/tts/voicevox.js' +import Version from '../utils/version.js' import { render, renderUrl, @@ -183,7 +184,7 @@ export class chatgpt extends plugin { reg: toggleMode === 'at' ? '^[^#][sS]*' : '^#chat[^gpt][sS]*', /** 执行方法 */ fnc: 'chatgpt', - log: false + log: true }, { reg: '^#(chatgpt)?对话列表$', @@ -756,44 +757,49 @@ export class chatgpt extends plugin { * #chatgpt */ async chatgpt (e) { + let msg = Version.isTrss ? e.msg : e.raw_message let prompt if (this.toggleMode === 'at') { - if (!e.raw_message || e.msg?.startsWith('#')) { + if (!msg || e.msg?.startsWith('#')) { return false } - if (e.isGroup && !(e.atme || e.atBot)) { + if ((e.isGroup || e.group_id) && !(e.atme || e.atBot)) { return false } if (e.user_id == getUin(e)) return false - prompt = e.raw_message.trim() - if (e.isGroup && typeof this.e.group.getMemberMap === 'function') { - let mm = await this.e.group.getMemberMap() - let me = mm.get(getUin(e)) || {} - let card = me.card - let nickname = me.nickname - if (nickname && card) { - if (nickname.startsWith(card)) { - // 例如nickname是"滚筒洗衣机",card是"滚筒" - prompt = prompt.replace(`@${nickname}`, '').trim() - } else if (card.startsWith(nickname)) { - // 例如nickname是"十二",card是"十二|本月已发送1000条消息" - prompt = prompt.replace(`@${card}`, '').trim() - // 如果是好友,显示的还是昵称 - prompt = prompt.replace(`@${nickname}`, '').trim() - } else { - // 互不包含,分别替换 - if (nickname) { + prompt = msg.trim() + try { + if (e.isGroup && typeof this.e.group.getMemberMap === 'function') { + let mm = await this.e.group.getMemberMap() + let me = mm.get(getUin(e)) || {} + let card = me.card + let nickname = me.nickname + if (nickname && card) { + if (nickname.startsWith(card)) { + // 例如nickname是"滚筒洗衣机",card是"滚筒" prompt = prompt.replace(`@${nickname}`, '').trim() - } - if (card) { + } else if (card.startsWith(nickname)) { + // 例如nickname是"十二",card是"十二|本月已发送1000条消息" prompt = prompt.replace(`@${card}`, '').trim() + // 如果是好友,显示的还是昵称 + prompt = prompt.replace(`@${nickname}`, '').trim() + } else { + // 互不包含,分别替换 + if (nickname) { + prompt = prompt.replace(`@${nickname}`, '').trim() + } + if (card) { + prompt = prompt.replace(`@${card}`, '').trim() + } } + } else if (nickname) { + prompt = prompt.replace(`@${nickname}`, '').trim() + } else if (card) { + prompt = prompt.replace(`@${card}`, '').trim() } - } else if (nickname) { - prompt = prompt.replace(`@${nickname}`, '').trim() - } else if (card) { - prompt = prompt.replace(`@${card}`, '').trim() } + } catch (err) { + logger.warn(err) } } else { let ats = e.message.filter(m => m.type === 'at') @@ -1586,29 +1592,36 @@ export class chatgpt extends plugin { opt.qq = e.sender.user_id opt.nickname = e.sender.card opt.groupName = e.group.name - opt.botName = e.isGroup ? (e.group.pickMember(getUin(e)).card || e.group.pickMember(getUin(e)).nickname) : Bot.nickname + opt.botName = e.isGroup ? (e.group.pickMember(getUin(e)).card || e.group.pickMember(getUin(e)).nickname) : e.bot.nickname let master = (await getMasterQQ())[0] if (master && e.group) { opt.masterName = e.group.pickMember(parseInt(master)).card || e.group.pickMember(parseInt(master)).nickname } if (master && !e.group) { - opt.masterName = Bot.getFriendList().get(parseInt(master))?.nickname + opt.masterName = e.bot.getFriendList().get(parseInt(master))?.nickname } - let latestChat = await e.group.getChatHistory(0, 1) - let seq = latestChat[0].seq - let chats = [] - while (chats.length < Config.groupContextLength) { - let chatHistory = await e.group.getChatHistory(seq, 20) - chats.push(...chatHistory) + let latestChats = await e.group.getChatHistory(0, 1) + if (latestChats.length > 0) { + let latestChat = latestChats[0] + if (latestChat) { + let seq = latestChat.seq + let chats = [] + while (chats.length < Config.groupContextLength) { + let chatHistory = await e.group.getChatHistory(seq, 20) + chats.push(...chatHistory) + } + chats = chats.slice(0, Config.groupContextLength) + let mm = await e.group.getMemberMap() + chats.forEach(chat => { + let sender = mm.get(chat.sender.user_id) + if (sender) { + chat.sender = sender + } + }) + // console.log(chats) + opt.chats = chats + } } - chats = chats.slice(0, Config.groupContextLength) - let mm = await e.group.getMemberMap() - chats.forEach(chat => { - let sender = mm.get(chat.sender.user_id) - chat.sender = sender - }) - // console.log(chats) - opt.chats = chats } catch (err) { logger.warn('获取群聊聊天记录失败,本次对话不携带聊天记录', err) } @@ -1720,8 +1733,11 @@ export class chatgpt extends plugin { } } else { // 未登录用户maxConv目前为5或10,出验证码没救 - logger.warn(`token [${bingToken}] 无效或已过期`) + logger.warn(`token [${bingToken}] 无效或已过期,如确认token无误,请前往网页版必应对话一次`) + retry = 0 } + } else { + retry = 0 } } else if (message && typeof message === 'string' && message.indexOf('限流') > -1) { @@ -2027,13 +2043,13 @@ export class chatgpt extends plugin { opt.qq = e.sender.user_id opt.nickname = e.sender.card opt.groupName = e.group.name - opt.botName = e.isGroup ? (e.group.pickMember(getUin(e)).card || e.group.pickMember(getUin(e)).nickname) : Bot.nickname + opt.botName = e.isGroup ? (e.group.pickMember(getUin(e)).card || e.group.pickMember(getUin(e)).nickname) : e.bot.nickname let master = (await getMasterQQ())[0] if (master && e.group) { opt.masterName = e.group.pickMember(parseInt(master)).card || e.group.pickMember(parseInt(master)).nickname } if (master && !e.group) { - opt.masterName = Bot.getFriendList().get(parseInt(master))?.nickname + opt.masterName = e.bot.getFriendList().get(parseInt(master))?.nickname } let latestChat = await e.group.getChatHistory(0, 1) let seq = latestChat[0].seq @@ -2071,7 +2087,7 @@ export class chatgpt extends plugin { system += chats .map(chat => { let sender = chat.sender || {} - // if (sender.user_id === Bot.uin && chat.raw_message.startsWith('建议的回复')) { + // if (sender.user_id === e.bot.uin && chat.raw_message.startsWith('建议的回复')) { if (chat.raw_message.startsWith('建议的回复')) { // 建议的回复太容易污染设定导致对话太固定跑偏了 return '' @@ -2199,7 +2215,7 @@ export class chatgpt extends plugin { logger.mark(logger.green('【ChatGPT-Plugin】插件avocado-plugin未安装') + ',安装后可查看最近热映电影与体验可玩性更高的点歌工具。\n可前往 https://github.com/Qz-Sean/avocado-plugin 获取') } if (e.isGroup) { - let botInfo = await Bot.getGroupMemberInfo(e.group_id, getUin(e), true) + let botInfo = await e.bot.getGroupMemberInfo(e.group_id, getUin(e), true) if (botInfo.role !== 'member') { // 管理员才给这些工具 tools.push(...[new EditCardTool(), new JinyanTool(), new KickOutTool(), new HandleMessageMsgTool(), new SetTitleTool()]) @@ -2451,7 +2467,7 @@ export class chatgpt extends plugin { } if (bots.code === 0) { if (bots.data.pageList.length > 0) { - this.reply(await makeForwardMsg(this.e, bots.data.pageList.map(msg => `${msg.bot.botId} - ${msg.bot.botName}`))) + this.reply(await makeForwardMsg(this.e, bots.data.pageList.map(msg => `${msg.e.bot.botId} - ${msg.e.bot.botName}`))) } else { await e.reply('未查到相关助手', true) } diff --git a/apps/entertainment.js b/apps/entertainment.js index 870c578..fb8ff7f 100644 --- a/apps/entertainment.js +++ b/apps/entertainment.js @@ -296,7 +296,7 @@ ${translateLangLabels} let groupId = e.msg.replace(/^#chatgpt打招呼/, '') logger.info(groupId) groupId = parseInt(groupId) - if (groupId && !Bot.getGroupList().get(groupId)) { + if (groupId && !e.bot.getGroupList().get(groupId)) { await e.reply('机器人不在这个群里!') return } @@ -310,7 +310,7 @@ ${translateLangLabels} if (!groupId) { await e.reply(sendable) } else { - await Bot.sendGroupMsg(groupId, sendable) + await e.bot.sendGroupMsg(groupId, sendable) await e.reply('发送成功!') } } @@ -325,7 +325,7 @@ ${translateLangLabels} continue } let groupId = parseInt(element) - if (Bot.getGroupList().get(groupId)) { + if (this.e.bot.getGroupList().get(groupId)) { // 打招呼概率 if (Math.floor(Math.random() * 100) < Config.helloProbability) { let message = await generateHello() @@ -381,12 +381,12 @@ ${translateLangLabels} } } if (useSilk) { - await Bot.sendGroupMsg(groupId, await uploadRecord(audio)) + await this.e.bot.sendGroupMsg(groupId, await uploadRecord(audio)) } else { - await Bot.sendGroupMsg(groupId, segment.record(audio)) + await this.e.bot.sendGroupMsg(groupId, segment.record(audio)) } } else { - await Bot.sendGroupMsg(groupId, message) + await this.e.bot.sendGroupMsg(groupId, message) } } else { logger.info(`时机未到,这次就不打招呼给群聊${groupId}了`) diff --git a/apps/history.js b/apps/history.js index 5f6d5f2..c76b8e1 100644 --- a/apps/history.js +++ b/apps/history.js @@ -66,12 +66,12 @@ export class history extends plugin { let parentMessageId = previousConversation.parentMessageId let tmp = {} const previousCachedMessages = getMessagesForConversation(conversation.messages, parentMessageId) - .map((message) => { - return { - text: message.message, - author: message.role === 'User' ? 'user' : 'bot' - } - }) + .map((message) => { + return { + text: message.message, + author: message.role === 'User' ? 'user' : 'bot' + } + }) previousCachedMessages.forEach(m => { if (m.author === 'user') { tmp.prompt = m.text @@ -100,7 +100,7 @@ export class history extends plugin { }, bot: { qq: getUin(e), - name: Bot.nickname + name: e.bot.nickname }, chat }, {}) diff --git a/apps/management.js b/apps/management.js index 40b48b8..5837afe 100644 --- a/apps/management.js +++ b/apps/management.js @@ -990,7 +990,7 @@ Poe 模式会调用 Poe 中的 Claude-instant 进行对话。需要提供 Cookie } } else if (match) { const groupId = parseInt(match[1], 10) - if (Bot.getGroupList().get(groupId)) { + if (e.bot.getGroupList().get(groupId)) { if (await redis.get(`CHATGPT:SHUT_UP:${groupId}`)) { await redis.del(`CHATGPT:SHUT_UP:${groupId}`) await redis.set(`CHATGPT:SHUT_UP:${groupId}`, '1', { EX: time }) @@ -1040,7 +1040,7 @@ Poe 模式会调用 Poe 中的 Claude-instant 进行对话。需要提供 Cookie return false } const groupId = parseInt(match[1], 10) - if (Bot.getGroupList().get(groupId)) { + if (e.bot.getGroupList().get(groupId)) { if (await redis.get(`CHATGPT:SHUT_UP:${groupId}`)) { await redis.del(`CHATGPT:SHUT_UP:${groupId}`) await e.reply(`好的主人,我终于又可以在群${groupId}和大家聊天了`) diff --git a/utils/SydneyAIClient.js b/utils/SydneyAIClient.js index e2e3a07..f24a4fb 100644 --- a/utils/SydneyAIClient.js +++ b/utils/SydneyAIClient.js @@ -11,6 +11,7 @@ import { formatDate, getMasterQQ, isCN, getUserData } from './common.js' import delay from 'delay' import moment from 'moment' import { getProxy } from './proxy.js' +import Version from './version.js' if (!globalThis.fetch) { globalThis.fetch = fetch @@ -80,7 +81,7 @@ export default class SydneyAIClient { // 'x-ms-client-request-id': crypto.randomUUID(), // 'x-ms-useragent': 'azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.3 OS/macOS', // cookie: this.opts.cookies || `_U=${this.opts.userToken}`, - Referer: 'https://edgeservices.bing.com/edgesvc/chat?udsframed=1&form=SHORUN&clientscopes=chat,noheader,channelstable,', + Referer: 'https://edgeservices.bing.com/edgesvc/chat?udsframed=1&form=SHORUN&clientscopes=chat,noheader,channelstable,' // 'Referrer-Policy': 'origin-when-cross-origin', // Workaround for request being blocked due to geolocation // 'x-forwarded-for': '1.1.1.1' @@ -461,12 +462,10 @@ export default class SydneyAIClient { admin: '管理员' } if (chats) { - context += `以下是一段qq群内的对话,提供给你作为上下文,你在回答所有问题时必须优先考虑这些信息,结合这些上下文进行回答,这很重要!!!。" - ` + context += '以下是一段qq群内的对话,提供给你作为上下文,你在回答所有问题时必须优先考虑这些信息,结合这些上下文进行回答,这很重要!!!。"' context += chats .map(chat => { - let sender = chat.sender || {} - // if (sender.user_id === Bot.uin && chat.raw_message.startsWith('建议的回复')) { + let sender = chat.sender || chat || {} if (chat.raw_message.startsWith('建议的回复')) { // 建议的回复太容易污染设定导致对话太固定跑偏了 return '' @@ -655,7 +654,7 @@ export default class SydneyAIClient { text: replySoFar.join('') } // 获取到图片内容 - if (messages.some(obj => obj.contentType === "IMAGE")) { + if (messages.some(obj => obj.contentType === 'IMAGE')) { message.imageTag = messages.filter(m => m.contentType === 'IMAGE').map(m => m.text).join('') } message.text = messages.filter(m => m.author === 'bot' && m.contentType != 'IMAGE').map(m => m.text).join('') diff --git a/utils/common.js b/utils/common.js index 62181c8..8a54c0e 100644 --- a/utils/common.js +++ b/utils/common.js @@ -1,18 +1,20 @@ // import { remark } from 'remark' // import stripMarkdown from 'strip-markdown' -import {exec} from 'child_process' +import { exec } from 'child_process' import lodash from 'lodash' import fs from 'node:fs' import path from 'node:path' import buffer from 'buffer' import yaml from 'yaml' import puppeteer from '../../../lib/puppeteer/puppeteer.js' -import {Config} from './config.js' -import {convertSpeaker, generateVitsAudio, speakers as vitsRoleList} from './tts.js' -import VoiceVoxTTS, {supportConfigurations as voxRoleList} from './tts/voicevox.js' -import AzureTTS, {supportConfigurations as azureRoleList} from './tts/microsoft-azure.js' -import {translate} from './translate.js' +import common from '../../../lib/common/common.js' +import { Config } from './config.js' +import { convertSpeaker, generateVitsAudio, speakers as vitsRoleList } from './tts.js' +import VoiceVoxTTS, { supportConfigurations as voxRoleList } from './tts/voicevox.js' +import AzureTTS, { supportConfigurations as azureRoleList } from './tts/microsoft-azure.js' +import { translate } from './translate.js' import uploadRecord from './uploadRecord.js' +import Version from './version.js' // export function markdownToText (markdown) { // return remark() // .use(stripMarkdown) @@ -81,10 +83,13 @@ export async function tryTimes (promiseFn, maxTries = 10) { } export async function makeForwardMsg (e, msg = [], dec = '') { - let nickname = Bot.nickname + if (Version.isTrss) { + return common.makeForwardMsg(e, msg, dec) + } + let nickname = e.bot.nickname if (e.isGroup) { try { - let info = await Bot.getGroupMemberInfo(e.group_id, getUin(e)) + let info = await e.bot.getGroupMemberInfo(e.group_id, getUin(e)) nickname = info.card || info.nickname } catch (err) { console.error(`Failed to get group member info: ${err}`) @@ -127,9 +132,9 @@ export async function makeForwardMsg (e, msg = [], dec = '') { } } forwardMsg.data = forwardMsg.data - .replace(/\n/g, '') - .replace(/(.+?)<\/title>/g, '___') - .replace(/___+/, `<title color="#777777" size="26">${dec}`) + .replace(/\n/g, '') + .replace(/(.+?)<\/title>/g, '___') + .replace(/___+/, `<title color="#777777" size="26">${dec}`) if (!is_sign) { forwardMsg.data = forwardMsg.data .replace('转发的', '不可转发的') @@ -787,7 +792,7 @@ export async function getImageOcrText (e) { let resultArr = [] let eachImgRes = '' for (let i in img) { - const imgOCR = await Bot.imageOcr(img[i]) + const imgOCR = await e.bot.imageOcr(img[i]) for (let text of imgOCR.wordslist) { eachImgRes += (`${text?.words} \n`) } @@ -823,10 +828,17 @@ export function getMaxModelTokens (model = 'gpt-3.5-turbo') { export function getUin (e) { if (e?.bot?.uin) return e.bot.uin - if (Array.isArray(Bot.uin)) { - if (Config.trssBotUin && Bot.uin.indexOf(Config.trssBotUin) > -1) return Config.trssBotUin - else return Bot.uin[0] - } else return Bot.uin + if (e) { + if (Array.isArray(e.bot.uin)) { + if (Config.trssBotUin && e.bot.uin.indexOf(Config.trssBotUin) > -1) return Config.trssBotUin + else return e.bot.uin[0] + } else return e.bot.uin + } else { + if (Array.isArray(Bot.uin)) { + if (Config.trssBotUin && Bot.uin.indexOf(Config.trssBotUin) > -1) return Config.trssBotUin + else return Bot.uin[0] + } else return Bot.uin + } } /** @@ -919,7 +931,6 @@ export async function generateAzureAudio (pendingText, role = '随机', speaking let languagePrefix = azureRoleList.find(config => config.code === speaker).languageDetail.charAt(0) languagePrefix = languagePrefix.startsWith('E') ? '英' : languagePrefix pendingText = (await translate(pendingText, languagePrefix)).replace('\n', '') - } else { let role, languagePrefix role = azureRoleList[Math.floor(Math.random() * azureRoleList.length)] @@ -961,4 +972,3 @@ export function getUserSpeaker (userSetting) { return userSetting.ttsRoleVoiceVox || Config.voicevoxTTSSpeaker } } - diff --git a/utils/poe/index 2.js b/utils/poe/index 2.js deleted file mode 100644 index a01189a..0000000 --- a/utils/poe/index 2.js +++ /dev/null @@ -1,278 +0,0 @@ -import { readFileSync } from 'fs' -import { scrape } from './credential.js' -import fetch from 'node-fetch' -import crypto from 'crypto' -// used when test as a single file -// const _path = process.cwd() -const _path = process.cwd() + '/plugins/chatgpt-plugin/utils/poe' -const gqlDir = `${_path}/graphql` -const queries = { - // chatViewQuery: readFileSync(gqlDir + '/ChatViewQuery.graphql', 'utf8'), - addMessageBreakMutation: readFileSync(gqlDir + '/AddMessageBreakMutation.graphql', 'utf8'), - chatPaginationQuery: readFileSync(gqlDir + '/ChatPaginationQuery.graphql', 'utf8'), - addHumanMessageMutation: readFileSync(gqlDir + '/AddHumanMessageMutation.graphql', 'utf8'), - loginMutation: readFileSync(gqlDir + '/LoginWithVerificationCodeMutation.graphql', 'utf8'), - signUpWithVerificationCodeMutation: readFileSync(gqlDir + '/SignupWithVerificationCodeMutation.graphql', 'utf8'), - sendVerificationCodeMutation: readFileSync(gqlDir + '/SendVerificationCodeForLoginMutation.graphql', 'utf8') -} -const optionMap = [ - { title: 'Claude (Powered by Anthropic)', value: 'a2' }, - { title: 'Sage (Powered by OpenAI - logical)', value: 'capybara' }, - { title: 'Dragonfly (Powered by OpenAI - simpler)', value: 'nutria' }, - { title: 'ChatGPT (Powered by OpenAI - current)', value: 'chinchilla' }, - { title: 'Claude+', value: 'a2_2' }, - { title: 'GPT-4', value: 'beaver' } -] -export class PoeClient { - constructor (props) { - this.config = props - } - - headers = { - 'Content-Type': 'application/json', - Referrer: 'https://poe.com/', - Origin: 'https://poe.com', - 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36' - } - - chatId = 0 - bot = '' - - reConnectWs = false - - async setCredentials () { - let result = await scrape(this.config.quora_cookie) - console.log(result) - this.config.quora_formkey = result.appSettings.formkey - this.config.channel_name = result.channelName - this.config.app_settings = result.appSettings - - // set value - this.headers['poe-formkey'] = this.config.quora_formkey - this.headers['poe-tchannel'] = this.config.channel_name - this.headers.Cookie = this.config.quora_cookie - console.log(this.headers) - } - - async subscribe () { - const query = { - queryName: 'subscriptionsMutation', - variables: { - subscriptions: [ - { - subscriptionName: 'messageAdded', - query: 'subscription subscriptions_messageAdded_Subscription(\n $chatId: BigInt!\n) {\n messageAdded(chatId: $chatId) {\n id\n messageId\n creationTime\n state\n ...ChatMessage_message\n ...chatHelpers_isBotMessage\n }\n}\n\nfragment ChatMessageDownvotedButton_message on Message {\n ...MessageFeedbackReasonModal_message\n ...MessageFeedbackOtherModal_message\n}\n\nfragment ChatMessageDropdownMenu_message on Message {\n id\n messageId\n vote\n text\n ...chatHelpers_isBotMessage\n}\n\nfragment ChatMessageFeedbackButtons_message on Message {\n id\n messageId\n vote\n voteReason\n ...ChatMessageDownvotedButton_message\n}\n\nfragment ChatMessageOverflowButton_message on Message {\n text\n ...ChatMessageDropdownMenu_message\n ...chatHelpers_isBotMessage\n}\n\nfragment ChatMessageSuggestedReplies_SuggestedReplyButton_message on Message {\n messageId\n}\n\nfragment ChatMessageSuggestedReplies_message on Message {\n suggestedReplies\n ...ChatMessageSuggestedReplies_SuggestedReplyButton_message\n}\n\nfragment ChatMessage_message on Message {\n id\n messageId\n text\n author\n linkifiedText\n state\n ...ChatMessageSuggestedReplies_message\n ...ChatMessageFeedbackButtons_message\n ...ChatMessageOverflowButton_message\n ...chatHelpers_isHumanMessage\n ...chatHelpers_isBotMessage\n ...chatHelpers_isChatBreak\n ...chatHelpers_useTimeoutLevel\n ...MarkdownLinkInner_message\n}\n\nfragment MarkdownLinkInner_message on Message {\n messageId\n}\n\nfragment MessageFeedbackOtherModal_message on Message {\n id\n messageId\n}\n\nfragment MessageFeedbackReasonModal_message on Message {\n id\n messageId\n}\n\nfragment chatHelpers_isBotMessage on Message {\n ...chatHelpers_isHumanMessage\n ...chatHelpers_isChatBreak\n}\n\nfragment chatHelpers_isChatBreak on Message {\n author\n}\n\nfragment chatHelpers_isHumanMessage on Message {\n author\n}\n\nfragment chatHelpers_useTimeoutLevel on Message {\n id\n state\n text\n messageId\n}\n' - }, - { - subscriptionName: 'viewerStateUpdated', - query: 'subscription subscriptions_viewerStateUpdated_Subscription {\n viewerStateUpdated {\n id\n ...ChatPageBotSwitcher_viewer\n }\n}\n\nfragment BotHeader_bot on Bot {\n displayName\n ...BotImage_bot\n}\n\nfragment BotImage_bot on Bot {\n profilePicture\n displayName\n}\n\nfragment BotLink_bot on Bot {\n displayName\n}\n\nfragment ChatPageBotSwitcher_viewer on Viewer {\n availableBots {\n id\n ...BotLink_bot\n ...BotHeader_bot\n }\n}\n' - } - ] - }, - query: 'mutation subscriptionsMutation(\n $subscriptions: [AutoSubscriptionQuery!]!\n) {\n autoSubscribe(subscriptions: $subscriptions) {\n viewer {\n id\n }\n }\n}\n' - } - - await this.makeRequest(query) - } - - async makeRequest (request) { - let payload = JSON.stringify(request) - let baseString = payload + this.headers['poe-formkey'] + 'WpuLMiXEKKE98j56k' - const md5 = crypto.createHash('md5').update(baseString).digest('hex') - const response = await fetch('https://poe.com/api/gql_POST', { - method: 'POST', - headers: Object.assign(this.headers, { - 'poe-tag-id': md5, - 'content-type': 'application/json' - }), - body: payload - }) - let text = await response.text() - try { - let result = JSON.parse(text) - console.log({ result }) - return result - } catch (e) { - console.error(text) - throw e - } - } - - async getBot (displayName) { - let r - let retry = 10 - while (retry >= 0) { - let url = `https://poe.com/_next/data/${this.nextData.buildId}/${displayName}.json` - let r = await fetch(url, { - headers: this.headers - }) - let res = await r.text() - try { - let chatData = (JSON.parse(res)).pageProps.payload.chatOfBotDisplayName - return chatData - } catch (e) { - r = res - retry-- - } - } - throw new Error(r) - } - - async getChatId () { - let r = await fetch('https://poe.com', { - headers: this.headers - }) - let text = await r.text() - const jsonRegex = /