XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

updated poe api (gpt4)

fixed tls_client issue by switching to request Session, and update the poe api

76571f25
t.me/xtekky <98614666+xtekky@users.noreply.github.com>
提交于

代码差异

6 个文件 +246 -41
Modified poe/__init__.py +2 -3
@@ -1,6 +1,6 @@
1 1 from poe.api import Client as PoeClient
2 2 from poe.mail import Mail
3 from tls_client import Session
3 from requests import Session
4 4 from re import search, findall
5 5 from json import loads
6 6 from time import sleep, time
@@ -48,11 +48,10 @@ class PoeResponse:
48 48 def json(self) -> dict:
49 49 return self.response_dict
50 50
51
52 51 class Account:
53 52 def create(proxy: None or str = None, logging: bool = False):
54 53
55 client = Session(client_identifier = "chrome110")
54 client = Session()
56 55 client.proxies = {
57 56 'http': f'http://{proxy}',
58 57 'https': f'http://{proxy}'} if proxy else None
Modified poe/api.py +116 -31
@@ -22,6 +22,7 @@ import logging
22 22 import time
23 23 import queue
24 24 import threading
25 import traceback
25 26 import websocket
26 27 from pathlib import Path
27 28 from urllib.parse import urlparse
@@ -124,6 +125,15 @@ class Client:
124 125
125 126 return next_data
126 127
128 def get_bot(self, display_name):
129 url = f'https://poe.com/_next/data/{self.next_data["buildId"]}/{display_name}.json'
130 logger.info("Downloading "+url)
131
132 r = request_with_retries(self.session.get, url)
133
134 chat_data = r.json()["pageProps"]["payload"]["chatOfBotDisplayName"]
135 return chat_data
136
127 137 def get_bots(self):
128 138 viewer = self.next_data["props"]["pageProps"]["payload"]["viewer"]
129 139 if not "availableBots" in viewer:
@@ -132,13 +142,7 @@ class Client:
132 142
133 143 bots = {}
134 144 for bot in bot_list:
135 url = f'https://poe.com/_next/data/{self.next_data["buildId"]}/{bot["displayName"].lower()}.json'
136 logger.info("Downloading "+url)
137
138 r = request_with_retries(self.session.get, url)
139
140 chat_data = r.json()[
141 "pageProps"]["payload"]["chatOfBotDisplayName"]
145 chat_data = self.get_bot(bot["displayName"].lower())
142 146 bots[chat_data["defaultBotObject"]["nickname"]] = chat_data
143 147
144 148 return bots
@@ -165,11 +169,8 @@ class Client:
165 169 return f'wss://{self.ws_domain}.tch.{channel["baseHost"]}/up/{channel["boxName"]}/updates'+query
166 170
167 171 def send_query(self, query_name, variables):
168 # print(f'send_query: {query_name} {variables}')
169
170 172 for i in range(20):
171 173 payload = generate_payload(query_name, variables)
172 # print(f'query_payload: {query_name} {variables}')
173 174 r = request_with_retries(
174 175 self.session.post, self.gql_url, json=payload, headers=self.gql_headers)
175 176 data = r.json()
@@ -216,7 +217,8 @@ class Client:
216 217 header={"User-Agent": user_agent},
217 218 on_message=self.on_message,
218 219 on_open=self.on_ws_connect,
219 on_error=self.on_ws_error
220 on_error=self.on_ws_error,
221 on_close=self.on_ws_close
220 222 )
221 223 t = threading.Thread(target=self.ws_run_thread, daemon=True)
222 224 t.start()
@@ -231,27 +233,44 @@ class Client:
231 233 def on_ws_connect(self, ws):
232 234 self.ws_connected = True
233 235
236 def on_ws_close(self, ws, close_status_code):
237 self.ws_connected = False
238 logger.warn(f"Websocket closed with status {close_status_code}")
239
234 240 def on_ws_error(self, ws, error):
235 logger.warn(f"Websocket returned error: {error}")
236 241 self.disconnect_ws()
237 242 self.connect_ws()
238 243
239 244 def on_message(self, ws, msg):
240 data = json.loads(msg)
241 message = json.loads(data["messages"][0])[
242 "payload"]["data"]["messageAdded"]
243
244 copied_dict = self.active_messages.copy()
245 for key, value in copied_dict.items():
246 # add the message to the appropriate queue
247 if value == message["messageId"] and key in self.message_queues:
248 self.message_queues[key].put(message)
245 try:
246 data = json.loads(msg)
247
248 if not "messages" in data:
249 249 return
250 250
251 # indicate that the response id is tied to the human message id
252 elif key != "pending" and value == None and message["state"] != "complete":
253 self.active_messages[key] = message["messageId"]
254 self.message_queues[key].put(message)
251 for message_str in data["messages"]:
252 message_data = json.loads(message_str)
253 if message_data["message_type"] != "subscriptionUpdate":
254 continue
255 message = message_data["payload"]["data"]["messageAdded"]
256
257 copied_dict = self.active_messages.copy()
258 for key, value in copied_dict.items():
259 # add the message to the appropriate queue
260 if value == message["messageId"] and key in self.message_queues:
261 self.message_queues[key].put(message)
262 return
263
264 # indicate that the response id is tied to the human message id
265 elif key != "pending" and value == None and message["state"] != "complete":
266 self.active_messages[key] = message["messageId"]
267 self.message_queues[key].put(message)
268 return
269
270 except Exception:
271 logger.error(traceback.format_exc())
272 self.disconnect_ws()
273 self.connect_ws()
255 274
256 275 def send_message(self, chatbot, message, with_chat_break=False, timeout=20):
257 276 # if there is another active message, wait until it has finished sending
@@ -262,8 +281,11 @@ class Client:
262 281 self.active_messages["pending"] = None
263 282
264 283 logger.info(f"Sending message to {chatbot}: {message}")
265
266 message_data = self.send_query("AddHumanMessageMutation", {
284 # reconnect websocket
285 if not self.ws_connected:
286 self.disconnect_ws()
287 self.connect_ws()
288 message_data = self.send_query("SendMessageMutation", {
267 289 "bot": chatbot,
268 290 "query": message,
269 291 "chatId": self.bots[chatbot]["chatId"],
@@ -272,11 +294,11 @@ class Client:
272 294 })
273 295 del self.active_messages["pending"]
274 296
275 if not message_data["data"]["messageCreateWithStatus"]["messageLimit"]["canSend"]:
297 if not message_data["data"]["messageEdgeCreate"]["message"]:
276 298 raise RuntimeError(f"Daily limit reached for {chatbot}.")
277 299 try:
278 human_message = message_data["data"]["messageCreateWithStatus"]
279 human_message_id = human_message["message"]["messageId"]
300 human_message = message_data["data"]["messageEdgeCreate"]["message"]
301 human_message_id = human_message["node"]["messageId"]
280 302 except TypeError:
281 303 raise RuntimeError(
282 304 f"An unknown error occured. Raw response data: {message_data}")
@@ -313,4 +335,67 @@ class Client:
313 335 del self.active_messages[human_message_id]
314 336 del self.message_queues[human_message_id]
315 337
316 load_queries()
338 def send_chat_break(self, chatbot):
339 logger.info(f"Sending chat break to {chatbot}")
340 result = self.send_query("AddMessageBreakMutation", {
341 "chatId": self.bots[chatbot]["chatId"]
342 })
343 return result["data"]["messageBreakCreate"]["message"]
344
345 def get_message_history(self, chatbot, count=25, cursor=None):
346 logger.info(f"Downloading {count} messages from {chatbot}")
347
348 if cursor == None:
349 chat_data = self.get_bot(self.bot_names[chatbot])
350 if not chat_data["messagesConnection"]["edges"]:
351 return []
352 cursor = chat_data["messagesConnection"]["edges"][-1]["cursor"]
353
354 cursor = str(cursor)
355 if count > 50:
356 messages = self.get_message_history(
357 chatbot, count=50, cursor=cursor)
358 while count > 0:
359 new_cursor = messages[0]["cursor"]
360 new_messages = self.get_message_history(
361 chatbot, min(50, count), cursor=new_cursor)
362 messages = new_messages + messages
363 count -= 50
364 return messages
365
366 result = self.send_query("ChatListPaginationQuery", {
367 "count": count,
368 "cursor": cursor,
369 "id": self.bots[chatbot]["id"]
370 })
371 return result["data"]["node"]["messagesConnection"]["edges"]
372
373 def delete_message(self, message_ids):
374 logger.info(f"Deleting messages: {message_ids}")
375 if not type(message_ids) is list:
376 message_ids = [int(message_ids)]
377
378 result = self.send_query("DeleteMessageMutation", {
379 "messageIds": message_ids
380 })
381
382 def purge_conversation(self, chatbot, count=-1):
383 logger.info(f"Purging messages from {chatbot}")
384 last_messages = self.get_message_history(chatbot, count=50)[::-1]
385 while last_messages:
386 message_ids = []
387 for message in last_messages:
388 if count == 0:
389 break
390 count -= 1
391 message_ids.append(message["node"]["messageId"])
392
393 self.delete_message(message_ids)
394
395 if count == 0:
396 return
397 last_messages = self.get_message_history(chatbot, count=50)[::-1]
398 logger.info(f"No more messages left to delete.")
399
400
401 load_queries()
Modified poe/cookies.txt +6 -0
@@ -1 +1,7 @@
1 1 SmPiNXZI9hBTuf3viz74PA==
2 zw7RoKQfeEehiaelYMRWeA==
3 NEttgJ_rRQdO05Tppx6hFw==
4 3OnmC0r9njYdNWhWszdQJg==
5 8hZKR7MxwUTEHvO45TEViw==
6 Eea6BqK0AmosTKzoI3AAow==
7 pUEbtxobN_QUSpLIR8RGww==
Modified poe/graphql/ChatListPaginationQuery.graphql +69 -7
@@ -11,6 +11,12 @@ query ChatListPaginationQuery(
11 11 }
12 12
13 13 fragment BotImage_bot on Bot {
14 displayName
15 ...botHelpers_useDeletion_bot
16 ...BotImage_useProfileImage_bot
17 }
18
19 fragment BotImage_useProfileImage_bot on Bot {
14 20 image {
15 21 __typename
16 22 ... on LocalBotImage {
@@ -20,7 +26,7 @@ fragment BotImage_bot on Bot {
20 26 url
21 27 }
22 28 }
23 displayName
29 ...botHelpers_useDeletion_bot
24 30 }
25 31
26 32 fragment ChatMessageDownvotedButton_message on Message {
@@ -33,7 +39,7 @@ fragment ChatMessageDropdownMenu_message on Message {
33 39 messageId
34 40 vote
35 41 text
36 linkifiedText
42 author
37 43 ...chatHelpers_isBotMessage
38 44 }
39 45
@@ -54,6 +60,9 @@ fragment ChatMessageInputView_chat on Chat {
54 60 dailyBalance
55 61 shouldShowRemainingMessageCount
56 62 }
63 hasClearContext
64 isDown
65 ...botHelpers_useDeletion_bot
57 66 id
58 67 }
59 68 shouldShowDisclaimer
@@ -88,6 +97,10 @@ fragment ChatMessageSuggestedReplies_SuggestedReplyButton_message on Message {
88 97 fragment ChatMessageSuggestedReplies_chat on Chat {
89 98 ...ChatWelcomeView_chat
90 99 ...ChatMessageSuggestedReplies_SuggestedReplyButton_chat
100 defaultBotObject {
101 hasWelcomeTopics
102 id
103 }
91 104 }
92 105
93 106 fragment ChatMessageSuggestedReplies_message on Message {
@@ -97,10 +110,13 @@ fragment ChatMessageSuggestedReplies_message on Message {
97 110
98 111 fragment ChatMessage_chat on Chat {
99 112 defaultBotObject {
100 ...ChatPageDisclaimer_bot
113 hasWelcomeTopics
114 hasSuggestedReplies
115 disclaimerText
101 116 messageLimit {
102 117 ...ChatPageRateLimitedBanner_messageLimit
103 118 }
119 ...ChatPageDisclaimer_bot
104 120 id
105 121 }
106 122 ...ChatMessageSuggestedReplies_chat
@@ -114,6 +130,7 @@ fragment ChatMessage_message on Message {
114 130 author
115 131 linkifiedText
116 132 state
133 contentType
117 134 ...ChatMessageSuggestedReplies_message
118 135 ...ChatMessageFeedbackButtons_message
119 136 ...ChatMessageOverflowButton_message
@@ -122,12 +139,15 @@ fragment ChatMessage_message on Message {
122 139 ...chatHelpers_isChatBreak
123 140 ...chatHelpers_useTimeoutLevel
124 141 ...MarkdownLinkInner_message
142 ...IdAnnotation_node
125 143 }
126 144
127 145 fragment ChatMessagesView_chat on Chat {
128 146 ...ChatMessage_chat
129 147 ...ChatWelcomeView_chat
148 ...IdAnnotation_node
130 149 defaultBotObject {
150 hasWelcomeTopics
131 151 messageLimit {
132 152 ...ChatPageRateLimitedBanner_messageLimit
133 153 }
@@ -152,23 +172,42 @@ fragment ChatPageDeleteFooter_chat on Chat {
152 172 }
153 173
154 174 fragment ChatPageDisclaimer_bot on Bot {
155 disclaimer
175 disclaimerText
176 }
177
178 fragment ChatPageMainFooter_chat on Chat {
179 defaultBotObject {
180 ...ChatPageMainFooter_useAccessMessage_bot
181 id
182 }
183 ...ChatMessageInputView_chat
184 ...ChatPageShareFooter_chat
185 ...ChatPageDeleteFooter_chat
186 }
187
188 fragment ChatPageMainFooter_edges on MessageEdge {
189 ...ChatMessageInputView_edges
190 }
191
192 fragment ChatPageMainFooter_useAccessMessage_bot on Bot {
193 ...botHelpers_useDeletion_bot
194 ...botHelpers_useViewerCanAccessPrivateBot
156 195 }
157 196
158 197 fragment ChatPageMain_chat_1G22uz on Chat {
159 198 id
160 199 chatId
161 ...ChatMessageInputView_chat
162 200 ...ChatPageShareFooter_chat
163 201 ...ChatPageDeleteFooter_chat
164 202 ...ChatMessagesView_chat
165 203 ...MarkdownLinkInner_chat
166 204 ...chatHelpers_useUpdateStaleChat_chat
167 205 ...ChatSubscriptionPaywallContextWrapper_chat
206 ...ChatPageMainFooter_chat
168 207 messagesConnection(last: $count, before: $cursor) {
169 208 edges {
170 209 ...ChatMessagesView_edges
171 ...ChatMessageInputView_edges
210 ...ChatPageMainFooter_edges
172 211 ...MarkdownLinkInner_edges
173 212 node {
174 213 ...chatHelpers_useUpdateStaleChat_message
@@ -217,6 +256,11 @@ fragment ChatWelcomeView_chat on Chat {
217 256 }
218 257 }
219 258
259 fragment IdAnnotation_node on Node {
260 __isNode: __typename
261 id
262 }
263
220 264 fragment MarkdownLinkInner_chat on Chat {
221 265 id
222 266 chatId
@@ -263,6 +307,15 @@ fragment SubscriptionPaywallModal_bot on Bot {
263 307 ...BotImage_bot
264 308 }
265 309
310 fragment botHelpers_useDeletion_bot on Bot {
311 deletionState
312 }
313
314 fragment botHelpers_useViewerCanAccessPrivateBot on Bot {
315 isPrivateBot
316 viewerIsCreator
317 }
318
266 319 fragment chatHelpers_isBotMessage on Message {
267 320 ...chatHelpers_isHumanMessage
268 321 ...chatHelpers_isChatBreak
@@ -292,8 +345,8 @@ fragment chatHelpers_useSendMessage_chat on Chat {
292 345 id
293 346 chatId
294 347 defaultBotObject {
295 nickname
296 348 id
349 nickname
297 350 }
298 351 shouldShowDisclaimer
299 352 }
@@ -303,10 +356,19 @@ fragment chatHelpers_useTimeoutLevel on Message {
303 356 state
304 357 text
305 358 messageId
359 chat {
360 chatId
361 defaultBotNickname
362 id
363 }
306 364 }
307 365
308 366 fragment chatHelpers_useUpdateStaleChat_chat on Chat {
309 367 chatId
368 defaultBotObject {
369 contextClearWindowSecs
370 id
371 }
310 372 ...chatHelpers_useSendChatBreak_chat
311 373 }
312 374
Added poe/graphql/SendMessageMutation.graphql +40 -0
@@ -0,0 +1,40 @@
1 mutation chatHelpers_sendMessageMutation_Mutation(
2 $chatId: BigInt!
3 $bot: String!
4 $query: String!
5 $source: MessageSource
6 $withChatBreak: Boolean!
7 ) {
8 messageEdgeCreate(chatId: $chatId, bot: $bot, query: $query, source: $source, withChatBreak: $withChatBreak) {
9 chatBreak {
10 cursor
11 node {
12 id
13 messageId
14 text
15 author
16 suggestedReplies
17 creationTime
18 state
19 }
20 id
21 }
22 message {
23 cursor
24 node {
25 id
26 messageId
27 text
28 author
29 suggestedReplies
30 creationTime
31 state
32 chat {
33 shouldShowDisclaimer
34 id
35 }
36 }
37 id
38 }
39 }
40 }
Added testing/poe_test.py +13 -0
@@ -0,0 +1,13 @@
1 import poe
2 from time import sleep
3
4 token = poe.Account.create(proxy = 'xtekky:ogingoi2n3g@geo.iproyal.com:12321',logging = True)
5 print('token', token)
6
7 sleep(2)
8
9 for response in poe.StreamingCompletion.create(model = 'gpt-4',
10 prompt = 'hello world',
11 token = token):
12
13 print(response.completion.choices[0].text, end="", flush=True)