mirror of
https://github.com/wassname/chatGPTBox.git
synced 2026-06-27 17:47:56 +08:00
feat: add poe AI (Sage, GPT4, ClaudePlus, Claude, ChatGPT, Dragonfly)
This commit is contained in:
@@ -184,6 +184,10 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, callback) {
|
||||
test: /\.(jpg|png|svg)$/,
|
||||
type: 'asset/inline',
|
||||
},
|
||||
{
|
||||
test: /\.(graphql|gql)$/,
|
||||
loader: 'graphql-tag/loader',
|
||||
},
|
||||
isWithoutTiktoken
|
||||
? {
|
||||
test: /crop-text\.mjs$/,
|
||||
|
||||
Generated
+60
-2
@@ -10,6 +10,7 @@
|
||||
"@picocss/pico": "^1.5.7",
|
||||
"@primer/octicons-react": "^18.2.0",
|
||||
"countries-list": "^2.6.1",
|
||||
"diff": "^5.1.0",
|
||||
"eventsource-parser": "^0.1.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"github-markdown-css": "^5.2.0",
|
||||
@@ -17,6 +18,7 @@
|
||||
"i18next": "^22.4.13",
|
||||
"katex": "^0.16.4",
|
||||
"lodash-es": "^4.17.21",
|
||||
"md5": "^2.3.0",
|
||||
"parse5": "^6.0.1",
|
||||
"preact": "^10.13.1",
|
||||
"prop-types": "^15.8.1",
|
||||
@@ -51,6 +53,7 @@
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"fs-extra": "^11.1.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"jsdom": "^21.1.1",
|
||||
"less-loader": "^11.1.0",
|
||||
"mini-css-extract-plugin": "^2.7.5",
|
||||
@@ -2996,6 +2999,14 @@
|
||||
"resolved": "https://registry.npmmirror.com/character-entities/-/character-entities-2.0.2.tgz",
|
||||
"integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="
|
||||
},
|
||||
"node_modules/charenc": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/charenc/-/charenc-0.0.2.tgz",
|
||||
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
|
||||
@@ -3248,6 +3259,14 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/crypt": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/crypt/-/crypt-0.0.2.tgz",
|
||||
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/css-declaration-sorter": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz",
|
||||
@@ -4567,6 +4586,31 @@
|
||||
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/graphql": {
|
||||
"version": "16.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/graphql/-/graphql-16.6.0.tgz",
|
||||
"integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/graphql-tag": {
|
||||
"version": "2.12.6",
|
||||
"resolved": "https://registry.npmmirror.com/graphql-tag/-/graphql-tag-2.12.6.tgz",
|
||||
"integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/gzip-size": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/gzip-size/-/gzip-size-6.0.0.tgz",
|
||||
@@ -5749,6 +5793,21 @@
|
||||
"resolved": "https://registry.npmmirror.com/markdown-table/-/markdown-table-3.0.3.tgz",
|
||||
"integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw=="
|
||||
},
|
||||
"node_modules/md5": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/md5/-/md5-2.3.0.tgz",
|
||||
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
|
||||
"dependencies": {
|
||||
"charenc": "0.0.2",
|
||||
"crypt": "0.0.2",
|
||||
"is-buffer": "~1.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/md5/node_modules/is-buffer": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmmirror.com/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||
},
|
||||
"node_modules/mdast-util-definitions": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
|
||||
@@ -8637,8 +8696,7 @@
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.5.0.tgz",
|
||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"@picocss/pico": "^1.5.7",
|
||||
"@primer/octicons-react": "^18.2.0",
|
||||
"countries-list": "^2.6.1",
|
||||
"diff": "^5.1.0",
|
||||
"eventsource-parser": "^0.1.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"github-markdown-css": "^5.2.0",
|
||||
@@ -30,6 +31,7 @@
|
||||
"i18next": "^22.4.13",
|
||||
"katex": "^0.16.4",
|
||||
"lodash-es": "^4.17.21",
|
||||
"md5": "^2.3.0",
|
||||
"parse5": "^6.0.1",
|
||||
"preact": "^10.13.1",
|
||||
"prop-types": "^15.8.1",
|
||||
@@ -64,6 +66,7 @@
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"fs-extra": "^11.1.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"jsdom": "^21.1.1",
|
||||
"less-loader": "^11.1.0",
|
||||
"mini-css-extract-plugin": "^2.7.5",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import BingAIClient from '../clients/BingAIClient'
|
||||
import BingAIClient from '../clients/bing'
|
||||
import { getUserConfig } from '../../config/index.mjs'
|
||||
import { pushRecord, setAbortController } from './shared.mjs'
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { pushRecord, setAbortController } from './shared.mjs'
|
||||
import PoeAiClient from '../clients/poe'
|
||||
|
||||
/**
|
||||
* @param {Runtime.Port} port
|
||||
* @param {string} question
|
||||
* @param {Session} session
|
||||
* @param {string} modelName
|
||||
*/
|
||||
export async function generateAnswersWithPoeWebApi(port, question, session, modelName) {
|
||||
const bot = new PoeAiClient(session.poe_chatId)
|
||||
const { messageListener } = setAbortController(port, () => {
|
||||
bot.breakMsg()
|
||||
bot.close()
|
||||
})
|
||||
|
||||
let answer = ''
|
||||
await bot
|
||||
.ask(
|
||||
question,
|
||||
modelName,
|
||||
(msg) => {
|
||||
answer += msg
|
||||
port.postMessage({ answer: answer, done: false, session: null })
|
||||
},
|
||||
() => {
|
||||
if (bot.chatId) session.poe_chatId = bot.chatId
|
||||
|
||||
pushRecord(session, question, answer)
|
||||
console.debug('conversation history', { content: session.conversationRecords })
|
||||
port.onMessage.removeListener(messageListener)
|
||||
port.postMessage({ answer: answer, done: true, session: session })
|
||||
bot.close()
|
||||
},
|
||||
)
|
||||
.catch((err) => {
|
||||
port.onMessage.removeListener(messageListener)
|
||||
bot.close()
|
||||
throw err
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
mutation AddHumanMessageMutation(
|
||||
$chatId: BigInt!
|
||||
$bot: String!
|
||||
$query: String!
|
||||
$source: MessageSource
|
||||
$withChatBreak: Boolean! = false
|
||||
) {
|
||||
messageCreateWithStatus(
|
||||
chatId: $chatId
|
||||
bot: $bot
|
||||
query: $query
|
||||
source: $source
|
||||
withChatBreak: $withChatBreak
|
||||
) {
|
||||
message {
|
||||
id
|
||||
__typename
|
||||
messageId
|
||||
text
|
||||
linkifiedText
|
||||
authorNickname
|
||||
state
|
||||
vote
|
||||
voteReason
|
||||
creationTime
|
||||
suggestedReplies
|
||||
chat {
|
||||
id
|
||||
shouldShowDisclaimer
|
||||
}
|
||||
}
|
||||
messageLimit{
|
||||
canSend
|
||||
numMessagesRemaining
|
||||
resetTime
|
||||
shouldShowReminder
|
||||
}
|
||||
chatBreak {
|
||||
id
|
||||
__typename
|
||||
messageId
|
||||
text
|
||||
linkifiedText
|
||||
authorNickname
|
||||
state
|
||||
vote
|
||||
voteReason
|
||||
creationTime
|
||||
suggestedReplies
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
mutation AddMessageBreakMutation($chatId: BigInt!) {
|
||||
messageBreakCreate(chatId: $chatId) {
|
||||
message {
|
||||
id
|
||||
__typename
|
||||
messageId
|
||||
text
|
||||
linkifiedText
|
||||
authorNickname
|
||||
state
|
||||
vote
|
||||
voteReason
|
||||
creationTime
|
||||
suggestedReplies
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mutation AutoSubscriptionMutation($subscriptions: [AutoSubscriptionQuery!]!) {
|
||||
autoSubscribe(subscriptions: $subscriptions) {
|
||||
viewer {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fragment BioFragment on Viewer {
|
||||
id
|
||||
poeUser {
|
||||
id
|
||||
uid
|
||||
bio
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
subscription ChatAddedSubscription {
|
||||
chatAdded {
|
||||
...ChatFragment
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fragment ChatFragment on Chat {
|
||||
id
|
||||
chatId
|
||||
defaultBotNickname
|
||||
shouldShowDisclaimer
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
query ChatPaginationQuery($bot: String!, $before: String, $last: Int! = 10) {
|
||||
chatOfBot(bot: $bot) {
|
||||
id
|
||||
__typename
|
||||
messagesConnection(before: $before, last: $last) {
|
||||
pageInfo {
|
||||
hasPreviousPage
|
||||
}
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
__typename
|
||||
messageId
|
||||
text
|
||||
linkifiedText
|
||||
authorNickname
|
||||
state
|
||||
vote
|
||||
voteReason
|
||||
creationTime
|
||||
suggestedReplies
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
query ChatViewQuery($bot: String!) {
|
||||
chatOfBot(bot: $bot) {
|
||||
id
|
||||
chatId
|
||||
defaultBotNickname
|
||||
shouldShowDisclaimer
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mutation DeleteHumanMessagesMutation($messageIds: [BigInt!]!) {
|
||||
messagesDelete(messageIds: $messageIds) {
|
||||
viewer {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fragment HandleFragment on Viewer {
|
||||
id
|
||||
poeUser {
|
||||
id
|
||||
uid
|
||||
handle
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
mutation LoginWithVerificationCodeMutation(
|
||||
$verificationCode: String!
|
||||
$emailAddress: String
|
||||
$phoneNumber: String
|
||||
) {
|
||||
loginWithVerificationCode(
|
||||
verificationCode: $verificationCode
|
||||
emailAddress: $emailAddress
|
||||
phoneNumber: $phoneNumber
|
||||
) {
|
||||
status
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
subscription MessageAddedSubscription($chatId: BigInt!) {
|
||||
messageAdded(chatId: $chatId) {
|
||||
...MessageFragment
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
subscription MessageDeletedSubscription($chatId: BigInt!) {
|
||||
messageDeleted(chatId: $chatId) {
|
||||
id
|
||||
messageId
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fragment MessageFragment on Message {
|
||||
id
|
||||
__typename
|
||||
messageId
|
||||
text
|
||||
linkifiedText
|
||||
authorNickname
|
||||
state
|
||||
vote
|
||||
voteReason
|
||||
creationTime
|
||||
suggestedReplies
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mutation MessageRemoveVoteMutation($messageId: BigInt!) {
|
||||
messageRemoveVote(messageId: $messageId) {
|
||||
message {
|
||||
...MessageFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mutation MessageSetVoteMutation($messageId: BigInt!, $voteType: VoteType!, $reason: String) {
|
||||
messageSetVote(messageId: $messageId, voteType: $voteType, reason: $reason) {
|
||||
message {
|
||||
...MessageFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
mutation SendVerificationCodeForLoginMutation(
|
||||
$emailAddress: String
|
||||
$phoneNumber: String
|
||||
) {
|
||||
sendVerificationCode(
|
||||
verificationReason: login
|
||||
emailAddress: $emailAddress
|
||||
phoneNumber: $phoneNumber
|
||||
) {
|
||||
status
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
mutation ShareMessagesMutation(
|
||||
$chatId: BigInt!
|
||||
$messageIds: [BigInt!]!
|
||||
$comment: String
|
||||
) {
|
||||
messagesShare(chatId: $chatId, messageIds: $messageIds, comment: $comment) {
|
||||
shareCode
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
mutation SignupWithVerificationCodeMutation(
|
||||
$verificationCode: String!
|
||||
$emailAddress: String
|
||||
$phoneNumber: String
|
||||
) {
|
||||
signupWithVerificationCode(
|
||||
verificationCode: $verificationCode
|
||||
emailAddress: $emailAddress
|
||||
phoneNumber: $phoneNumber
|
||||
) {
|
||||
status
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mutation StaleChatUpdateMutation($chatId: BigInt!) {
|
||||
staleChatUpdate(chatId: $chatId) {
|
||||
message {
|
||||
...MessageFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
query SummarizePlainPostQuery($comment: String!) {
|
||||
summarizePlainPost(comment: $comment)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
query SummarizeQuotePostQuery($comment: String, $quotedPostId: BigInt!) {
|
||||
summarizeQuotePost(comment: $comment, quotedPostId: $quotedPostId)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
query SummarizeSharePostQuery($comment: String!, $chatId: BigInt!, $messageIds: [BigInt!]!) {
|
||||
summarizeSharePost(comment: $comment, chatId: $chatId, messageIds: $messageIds)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fragment UserSnippetFragment on PoeUser {
|
||||
id
|
||||
uid
|
||||
bio
|
||||
handle
|
||||
fullName
|
||||
viewerIsFollowing
|
||||
isPoeOnlyUser
|
||||
profilePhotoURLTiny: profilePhotoUrl(size: tiny)
|
||||
profilePhotoURLSmall: profilePhotoUrl(size: small)
|
||||
profilePhotoURLMedium: profilePhotoUrl(size: medium)
|
||||
profilePhotoURLLarge: profilePhotoUrl(size: large)
|
||||
isFollowable
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
query ViewerInfoQuery {
|
||||
viewer {
|
||||
id
|
||||
uid
|
||||
...ViewerStateFragment
|
||||
...BioFragment
|
||||
...HandleFragment
|
||||
hasCompletedMultiplayerNux
|
||||
poeUser {
|
||||
id
|
||||
...UserSnippetFragment
|
||||
}
|
||||
messageLimit{
|
||||
canSend
|
||||
numMessagesRemaining
|
||||
resetTime
|
||||
shouldShowReminder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
fragment ViewerStateFragment on Viewer {
|
||||
id
|
||||
__typename
|
||||
iosMinSupportedVersion: integerGate(gateName: "poe_ios_min_supported_version")
|
||||
iosMinEncouragedVersion: integerGate(
|
||||
gateName: "poe_ios_min_encouraged_version"
|
||||
)
|
||||
macosMinSupportedVersion: integerGate(
|
||||
gateName: "poe_macos_min_supported_version"
|
||||
)
|
||||
macosMinEncouragedVersion: integerGate(
|
||||
gateName: "poe_macos_min_encouraged_version"
|
||||
)
|
||||
showPoeDebugPanel: booleanGate(gateName: "poe_show_debug_panel")
|
||||
enableCommunityFeed: booleanGate(gateName: "enable_poe_shares_feed")
|
||||
linkifyText: booleanGate(gateName: "poe_linkify_response")
|
||||
enableSuggestedReplies: booleanGate(gateName: "poe_suggested_replies")
|
||||
removeInviteLimit: booleanGate(gateName: "poe_remove_invite_limit")
|
||||
enableInAppPurchases: booleanGate(gateName: "poe_enable_in_app_purchases")
|
||||
availableBots {
|
||||
nickname
|
||||
displayName
|
||||
profilePicture
|
||||
isDown
|
||||
disclaimer
|
||||
subtitle
|
||||
poweredBy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
subscription ViewerStateUpdatedSubscription {
|
||||
viewerStateUpdated {
|
||||
...ViewerStateFragment
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
// reference: https://github.com/muharamdani/poe
|
||||
|
||||
import { connectWs, disconnectWs, listenWs } from './websocket.js'
|
||||
import chatViewQuery from './graphql/ChatViewQuery.graphql'
|
||||
import addMessageBreakMutation from './graphql/AddMessageBreakMutation.graphql'
|
||||
import addHumanMessageMutation from './graphql/AddHumanMessageMutation.graphql'
|
||||
import Browser from 'webextension-polyfill'
|
||||
import md5 from 'md5'
|
||||
|
||||
const queries = {
|
||||
chatViewQuery: chatViewQuery.loc.source.body,
|
||||
addMessageBreakMutation: addMessageBreakMutation.loc.source.body,
|
||||
addHumanMessageMutation: addHumanMessageMutation.loc.source.body,
|
||||
}
|
||||
|
||||
export default class PoeAiClient {
|
||||
constructor(chatId = null) {
|
||||
this.headers = {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
Origin: 'https://poe.com',
|
||||
}
|
||||
this.settings = null
|
||||
this.ws = null
|
||||
this.chatId = chatId
|
||||
this.bot = null
|
||||
}
|
||||
|
||||
async ask(message, model, onMessage, onComplete) {
|
||||
if (!this.settings) {
|
||||
await this.getCredentials()
|
||||
}
|
||||
if (!this.bot) {
|
||||
await this.initBot(model || 'sage')
|
||||
}
|
||||
if (!this.chatId) {
|
||||
await this.getChatId(this.bot)
|
||||
}
|
||||
if (!this.ws) {
|
||||
this.ws = await connectWs(this.settings)
|
||||
await this.subscribe()
|
||||
listenWs(this.ws, onMessage, onComplete)
|
||||
}
|
||||
await this.sendMsg(message)
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (this.ws) {
|
||||
await disconnectWs(this.ws)
|
||||
this.ws = null
|
||||
}
|
||||
}
|
||||
|
||||
async getFormkey() {
|
||||
const encoded = (await (await fetch('https://poe.com')).text()).match(
|
||||
/<script>if\(.+\)throw new Error;(.+)<\/script>/,
|
||||
)[1]
|
||||
const codebook = encoded.match(/var .="([0-9a-f]+)"/)[1]
|
||||
const dict = Array.from(encoded.matchAll(/\[(\d+)\]=.\[(\d+)\]/g))
|
||||
let result = new Array(dict.length)
|
||||
dict.forEach(([, k, v]) => {
|
||||
result[k] = codebook[v]
|
||||
})
|
||||
return result.join('')
|
||||
}
|
||||
|
||||
async getCredentials() {
|
||||
this.headers['Cookie'] = (await Browser.cookies.getAll({ url: 'https://poe.com/' }))
|
||||
.map((cookie) => {
|
||||
return `${cookie.name}=${cookie.value}`
|
||||
})
|
||||
.join('; ')
|
||||
this.settings = await (
|
||||
await fetch('https://poe.com/api/settings', { headers: this.headers })
|
||||
).json()
|
||||
console.debug('poe settings', this.settings)
|
||||
if (this.settings.tchannelData.channel)
|
||||
this.headers['poe-tchannel'] = this.settings.tchannelData.channel
|
||||
|
||||
this.headers['poe-formkey'] = await this.getFormkey()
|
||||
console.debug('poe formkey', this.headers['poe-formkey'])
|
||||
}
|
||||
|
||||
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) {
|
||||
request = JSON.stringify(request)
|
||||
this.headers['poe-tag-id'] = md5(request + this.headers['poe-formkey'] + 'WpuLMiXEKKE98j56k')
|
||||
const response = await fetch('https://poe.com/api/gql_POST', {
|
||||
method: 'POST',
|
||||
headers: this.headers,
|
||||
body: request,
|
||||
})
|
||||
return await response.json()
|
||||
}
|
||||
|
||||
async getChatId(bot) {
|
||||
const {
|
||||
data: {
|
||||
chatOfBot: { chatId },
|
||||
},
|
||||
} = await this.makeRequest({
|
||||
query: queries.chatViewQuery,
|
||||
variables: {
|
||||
bot,
|
||||
},
|
||||
})
|
||||
this.chatId = chatId
|
||||
return chatId
|
||||
}
|
||||
|
||||
async initBot(bot) {
|
||||
if (bot === 'sage') {
|
||||
bot = 'capybara'
|
||||
} else if (bot === 'gpt-4') {
|
||||
bot = 'beaver'
|
||||
} else if (bot === 'claude+') {
|
||||
bot = 'a2_2'
|
||||
} else if (bot === 'claude') {
|
||||
bot = 'a2'
|
||||
} else if (bot === 'chatgpt') {
|
||||
bot = 'chinchilla'
|
||||
} else if (bot === 'dragonfly') {
|
||||
bot = 'nutria'
|
||||
}
|
||||
|
||||
this.bot = bot
|
||||
}
|
||||
|
||||
async breakMsg() {
|
||||
await this.makeRequest({
|
||||
query: queries.addMessageBreakMutation,
|
||||
variables: { chatId: this.chatId },
|
||||
})
|
||||
}
|
||||
|
||||
async sendMsg(query) {
|
||||
await this.makeRequest({
|
||||
query: queries.addHumanMessageMutation,
|
||||
variables: {
|
||||
bot: this.bot,
|
||||
chatId: this.chatId,
|
||||
query: query,
|
||||
source: null,
|
||||
withChatBreak: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import * as diff from 'diff'
|
||||
|
||||
const getSocketUrl = async (settings) => {
|
||||
settings = settings.tchannelData
|
||||
const tchRand = Math.floor(100000 + Math.random() * 900000) // They're surely using 6 digit random number for ws url.
|
||||
const socketUrl = `wss://tch${tchRand}.tch.quora.com`
|
||||
const boxName = settings.boxName
|
||||
const minSeq = settings.minSeq
|
||||
const channel = settings.channel
|
||||
const hash = settings.channelHash
|
||||
return `${socketUrl}/up/${boxName}/updates?min_seq=${minSeq}&channel=${channel}&hash=${hash}`
|
||||
}
|
||||
export const connectWs = async (settings) => {
|
||||
const url = await getSocketUrl(settings)
|
||||
const ws = new WebSocket(url)
|
||||
return new Promise((resolve) => {
|
||||
ws.onopen = () => {
|
||||
console.log('Connected to websocket')
|
||||
return resolve(ws)
|
||||
}
|
||||
})
|
||||
}
|
||||
export const disconnectWs = async (ws) => {
|
||||
return new Promise((resolve) => {
|
||||
ws.onclose = () => {
|
||||
return resolve(true)
|
||||
}
|
||||
ws.close()
|
||||
})
|
||||
}
|
||||
export const listenWs = async (ws, onMessage, onComplete) => {
|
||||
let previousText = ''
|
||||
return new Promise((resolve) => {
|
||||
let complete = false
|
||||
ws.onmessage = (e) => {
|
||||
let jsonData = JSON.parse(e.data)
|
||||
console.log(jsonData)
|
||||
if (jsonData.messages && jsonData.messages.length > 0) {
|
||||
const messages = JSON.parse(jsonData.messages[0])
|
||||
const dataPayload = messages.payload.data
|
||||
const text = dataPayload.messageAdded.text
|
||||
const state = dataPayload.messageAdded.state
|
||||
if (state !== 'complete') {
|
||||
const differences = diff.diffChars(previousText, text)
|
||||
let result = ''
|
||||
differences.forEach((part) => {
|
||||
if (part.added) {
|
||||
result += part.value
|
||||
}
|
||||
})
|
||||
previousText = text
|
||||
if (onMessage) onMessage(result)
|
||||
} else if (dataPayload.messageAdded.author !== 'human') {
|
||||
if (!complete) {
|
||||
complete = true
|
||||
if (onComplete) onComplete(text)
|
||||
return resolve(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { generateAnswersWithCustomApi } from './apis/custom-api.mjs'
|
||||
import { generateAnswersWithAzureOpenaiApi } from './apis/azure-openai-api.mjs'
|
||||
import { generateAnswersWithWaylaidwandererApi } from './apis/waylaidwanderer-api.mjs'
|
||||
import { generateAnswersWithPoeWebApi } from './apis/poe-web.mjs'
|
||||
import {
|
||||
azureOpenAiApiModelKeys,
|
||||
bingWebModelKeys,
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
githubThirdPartyApiModelKeys,
|
||||
gptApiModelKeys,
|
||||
Models,
|
||||
poeWebModelKeys,
|
||||
setAccessToken,
|
||||
} from '../config/index.mjs'
|
||||
import { config as menuConfig } from '../content-script/menu-tools'
|
||||
@@ -105,6 +107,13 @@ Browser.runtime.onConnect.addListener((port) => {
|
||||
await generateAnswersWithAzureOpenaiApi(port, session.question, session)
|
||||
} else if (githubThirdPartyApiModelKeys.includes(session.modelName)) {
|
||||
await generateAnswersWithWaylaidwandererApi(port, session.question, session)
|
||||
} else if (poeWebModelKeys.includes(session.modelName)) {
|
||||
await generateAnswersWithPoeWebApi(
|
||||
port,
|
||||
session.question,
|
||||
session,
|
||||
Models[session.modelName].value,
|
||||
)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
|
||||
+17
-2
@@ -13,7 +13,12 @@ import { isMobile } from '../utils/is-mobile.mjs'
|
||||
export const Models = {
|
||||
chatgptFree35: { value: 'text-davinci-002-render-sha', desc: 'ChatGPT (Web)' },
|
||||
chatgptPlus4: { value: 'gpt-4', desc: 'ChatGPT (Web, GPT-4)' },
|
||||
bingFree4: { value: 'gpt-4', desc: 'Bing (Web, GPT-4)' },
|
||||
bingFree4: { value: '', desc: 'Bing (Web, GPT-4)' },
|
||||
bingFreeSydney: { value: '', desc: 'Bing (Web, GPT-4, Sydney)' },
|
||||
poeAiWebSage: { value: 'sage', desc: 'Poe AI (Web, Sage)' },
|
||||
poeAiWebGPT4: { value: 'gpt-4', desc: 'Poe AI (Web, GPT-4)' },
|
||||
poeAiWebClaudePlus: { value: 'claude+', desc: 'Poe AI (Web, Claude+)' },
|
||||
poeAiWebClaude: { value: 'claude', desc: 'Poe AI (Web, Claude)' },
|
||||
chatgptApi35: { value: 'gpt-3.5-turbo', desc: 'ChatGPT (GPT-3.5-turbo)' },
|
||||
chatgptApi4_8k: { value: 'gpt-4', desc: 'ChatGPT (GPT-4-8k)' },
|
||||
chatgptApi4_32k: { value: 'gpt-4-32k', desc: 'ChatGPT (GPT-4-32k)' },
|
||||
@@ -21,15 +26,25 @@ export const Models = {
|
||||
customModel: { value: '', desc: 'Custom Model' },
|
||||
azureOpenAi: { value: '', desc: 'ChatGPT (Azure)' },
|
||||
waylaidwandererApi: { value: '', desc: 'Waylaidwanderer API (Github)' },
|
||||
poeAiWebChatGpt: { value: 'chatgpt', desc: 'Poe AI (Web, ChatGPT)' },
|
||||
poeAiWebDragonfly: { value: 'dragonfly', desc: 'Poe AI (Web, Dragonfly)' },
|
||||
}
|
||||
|
||||
export const chatgptWebModelKeys = ['chatgptFree35', 'chatgptPlus4']
|
||||
export const bingWebModelKeys = ['bingFree4']
|
||||
export const bingWebModelKeys = ['bingFree4', 'bingFreeSydney']
|
||||
export const gptApiModelKeys = ['gptApiDavinci']
|
||||
export const chatgptApiModelKeys = ['chatgptApi35', 'chatgptApi4_8k', 'chatgptApi4_32k']
|
||||
export const customApiModelKeys = ['customModel']
|
||||
export const azureOpenAiApiModelKeys = ['azureOpenAi']
|
||||
export const githubThirdPartyApiModelKeys = ['waylaidwandererApi']
|
||||
export const poeWebModelKeys = [
|
||||
'poeAiWebSage',
|
||||
'poeAiWebGPT4',
|
||||
'poeAiWebClaudePlus',
|
||||
'poeAiWebClaude',
|
||||
'poeAiWebChatGpt',
|
||||
'poeAiWebDragonfly',
|
||||
]
|
||||
|
||||
export const TriggerMode = {
|
||||
always: 'Always',
|
||||
|
||||
+2
-1
@@ -11,7 +11,8 @@
|
||||
},
|
||||
"host_permissions": [
|
||||
"https://*.openai.com/",
|
||||
"https://*.bing.com/"
|
||||
"https://*.bing.com/",
|
||||
"https://*.poe.com/"
|
||||
],
|
||||
"permissions": [
|
||||
"commands",
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
"unlimitedStorage",
|
||||
"tabs",
|
||||
"https://*.openai.com/",
|
||||
"https://*.bing.com/"
|
||||
"https://*.bing.com/",
|
||||
"https://*.poe.com/"
|
||||
],
|
||||
"optional_permissions": [
|
||||
"background"
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Models } from '../config/index.mjs'
|
||||
* @property {string|null} bingWeb_conversationId
|
||||
* @property {string|null} bingWeb_clientId
|
||||
* @property {string|null} bingWeb_invocationId
|
||||
* @property {number|null} poe_chatId
|
||||
*/
|
||||
/**
|
||||
* @param {string|null} question
|
||||
@@ -57,5 +58,8 @@ export function initSession({
|
||||
bingWeb_conversationId: null,
|
||||
bingWeb_clientId: null,
|
||||
bingWeb_invocationId: null,
|
||||
|
||||
// poe
|
||||
poe_chatId: null,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user