poe api gpt-4

pull/2/head
t.me/xtekky 1 year ago
parent 81e033023e
commit 1396122423

@ -1,5 +1,43 @@
working on it...
`poe` (use like openai pypi package) - gpt-4
Import poe:
```python
import poe
# poe.Account.create
# poe.Completion.create
# poe.StreamCompletion.create
```
Create Token (3-6s)
```python
token = poe.Account.create(logging = True)
print('token', token)
```
Streaming Response
```python
for response in poe.StreamingCompletion.create(model = 'gpt-4',
prompt = 'hello world',
token = token):
print(response.completion.choices[0].text, end="", flush=True)
```
Normal Response:
```python
response = poe.Completion.create(model = 'gpt-4',
prompt = 'hello world',
token = token)
print(response.completion.choices[0].text)
```
`t3nsor` (use like openai pypi package)
Import t3nsor:

@ -0,0 +1,214 @@
from poe.api import Client as PoeClient
from poe.mail import Mail
from tls_client import Session
from re import search, findall
from json import loads
from time import sleep, time
from pathlib import Path
from random import choice
from urllib import parse
class PoeResponse:
class Completion:
class Choices:
def __init__(self, choice: dict) -> None:
self.text = choice['text']
self.content = self.text.encode()
self.index = choice['index']
self.logprobs = choice['logprobs']
self.finish_reason = choice['finish_reason']
def __repr__(self) -> str:
return f'''<__main__.APIResponse.Completion.Choices(\n text = {self.text.encode()},\n index = {self.index},\n logprobs = {self.logprobs},\n finish_reason = {self.finish_reason})object at 0x1337>'''
def __init__(self, choices: dict) -> None:
self.choices = [self.Choices(choice) for choice in choices]
class Usage:
def __init__(self, usage_dict: dict) -> None:
self.prompt_tokens = usage_dict['prompt_tokens']
self.completion_tokens = usage_dict['completion_tokens']
self.total_tokens = usage_dict['total_tokens']
def __repr__(self):
return f'''<__main__.APIResponse.Usage(\n prompt_tokens = {self.prompt_tokens},\n completion_tokens = {self.completion_tokens},\n total_tokens = {self.total_tokens})object at 0x1337>'''
def __init__(self, response_dict: dict) -> None:
self.response_dict = response_dict
self.id = response_dict['id']
self.object = response_dict['object']
self.created = response_dict['created']
self.model = response_dict['model']
self.completion = self.Completion(response_dict['choices'])
self.usage = self.Usage(response_dict['usage'])
def json(self) -> dict:
return self.response_dict
class Account:
def create(proxy: None or str = None, logging: bool = False):
client = Session(client_identifier = "chrome110")
client.proxies = {
'http': f'http://{proxy}',
'https': f'http://{proxy}'} if proxy else None
mail = Mail(client.proxies)
mail_token = None
mail_address = mail.get_mail()
if logging: print('email', mail_address)
client.headers = {
"host" : "poe.com",
"connection" : "keep-alive",
"cache-control" : "max-age=0",
"sec-ch-ua" : "\"Microsoft Edge\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\"",
"sec-ch-ua-mobile" : "?0",
"sec-ch-ua-platform": "\"macOS\"",
"user-agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54",
"accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"sec-fetch-site" : "same-origin",
"sec-fetch-mode" : "navigate",
"sec-fetch-user" : "?1",
"sec-fetch-dest" : "document",
"accept-encoding" : "gzip, deflate, br",
"accept-language" : "en-GB,en;q=0.9,en-US;q=0.8",
"upgrade-insecure-requests": "1",
}
init = client.get('https://poe.com/login')
next_data = loads(search(r'json">(.+?)</script>', init.text).group(1))
client.headers["poe-formkey"] = next_data['props']['formkey']
client.headers["poe-tchannel"] = client.get('https://poe.com/api/settings').json()['tchannelData']['channel']
payload = {
"queryName": "MainSignupLoginSection_sendVerificationCodeMutation_Mutation",
"variables": {
"emailAddress": mail_address,
"phoneNumber" : None
},
"query": "mutation MainSignupLoginSection_sendVerificationCodeMutation_Mutation(\n $emailAddress: String\n $phoneNumber: String\n) {\n sendVerificationCode(verificationReason: login, emailAddress: $emailAddress, phoneNumber: $phoneNumber) {\n status\n errorMessage\n }\n}\n"
}
response = client.post('https://poe.com/api/gql_POST', json=payload)
if 'Bad Request' in response.text:
if logging: print('bad request, retrying...' , response.json())
Account.create(proxy = proxy, logging = logging)
if logging: print('send_code' ,response.json())
while True:
sleep(1)
inbox = mail.fetch_inbox()
for _ in inbox:
content = mail.get_message(_["id"])
mail_token = findall(r';">(\d{6,7})</div>', content['html'][0])[0]
if mail_token:
break
if logging: print('code', mail_token)
payload = {
"queryName": "SignupOrLoginWithCodeSection_signupWithVerificationCodeMutation_Mutation",
"variables": {
"verificationCode" : mail_token,
"emailAddress" : mail_address,
"phoneNumber" : None
},
"query": "mutation SignupOrLoginWithCodeSection_signupWithVerificationCodeMutation_Mutation(\n $verificationCode: String!\n $emailAddress: String\n $phoneNumber: String\n) {\n signupWithVerificationCode(verificationCode: $verificationCode, emailAddress: $emailAddress, phoneNumber: $phoneNumber) {\n status\n errorMessage\n }\n}\n"
}
response = client.post('https://poe.com/api/gql_POST', json = payload)
if logging: print('verify_code', response.json())
token = parse.unquote(client.cookies.get_dict()['p-b'])
with open(Path(__file__).resolve().parent / 'cookies.txt', 'a') as f:
f.write(f'{token}\n')
return token
def get():
cookies = open(Path(__file__).resolve().parent / 'cookies.txt', 'r').read().splitlines()
return choice(cookies)
class StreamingCompletion:
def create(
model : str = 'gpt-4',
prompt: str = 'hello world',
token : str = ''):
models = {
'sage' : 'capybara',
'gpt-4' : 'beaver',
'claude+': 'a2_2',
'claude' : 'a2',
'gpt-3.5': 'chinchilla'
}
client = PoeClient(token)
for chunk in client.send_message(models[model], prompt):
yield PoeResponse({
'id' : chunk["messageId"],
'object' : 'text_completion',
'created': chunk['creationTime'],
'model' : models[model],
'choices': [{
'text' : chunk["text_new"],
'index' : 0,
'logprobs' : None,
'finish_reason' : 'stop'
}],
'usage': {
'prompt_tokens' : len(prompt),
'completion_tokens' : len(chunk["text_new"]),
'total_tokens' : len(prompt) + len(chunk["text_new"])
}
})
class Completion:
def create(
model : str = 'gpt-4',
prompt: str = 'hello world',
token : str = ''):
models = {
'sage' : 'capybara',
'gpt-4' : 'beaver',
'claude+': 'a2_2',
'claude' : 'a2',
'gpt-3.5': 'chinchilla'
}
client = PoeClient(token)
for chunk in client.send_message(models[model], prompt):
pass
return PoeResponse({
'id' : chunk["messageId"],
'object' : 'text_completion',
'created': chunk['creationTime'],
'model' : models[model],
'choices': [{
'text' : chunk["text"],
'index' : 0,
'logprobs' : None,
'finish_reason' : 'stop'
}],
'usage': {
'prompt_tokens' : len(prompt),
'completion_tokens' : len(chunk["text"]),
'total_tokens' : len(prompt) + len(chunk["text"])
}
})

@ -0,0 +1,316 @@
# ading2210/poe-api: a reverse engineered Python API wrapepr for Quora's Poe
# Copyright (C) 2023 ading2210
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import requests
import re
import json
import random
import logging
import time
import queue
import threading
import websocket
from pathlib import Path
from urllib.parse import urlparse
parent_path = Path(__file__).resolve().parent
queries_path = parent_path / "graphql"
queries = {}
logging.basicConfig()
logger = logging.getLogger()
user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
def load_queries():
for path in queries_path.iterdir():
if path.suffix != ".graphql":
continue
with open(path) as f:
queries[path.stem] = f.read()
def generate_payload(query_name, variables):
return {
"query": queries[query_name],
"variables": variables
}
def request_with_retries(method, *args, **kwargs):
attempts = kwargs.get("attempts") or 10
url = args[0]
for i in range(attempts):
r = method(*args, **kwargs)
if r.status_code == 200:
return r
logger.warn(
f"Server returned a status code of {r.status_code} while downloading {url}. Retrying ({i+1}/{attempts})...")
raise RuntimeError(f"Failed to download {url} too many times.")
class Client:
gql_url = "https://poe.com/api/gql_POST"
gql_recv_url = "https://poe.com/api/receive_POST"
home_url = "https://poe.com"
settings_url = "https://poe.com/api/settings"
formkey = ""
next_data = {}
bots = {}
active_messages = {}
message_queues = {}
ws = None
ws_connected = False
def __init__(self, token, proxy=None):
self.proxy = proxy
self.session = requests.Session()
if proxy:
self.session.proxies = {
"http": self.proxy,
"https": self.proxy
}
logger.info(f"Proxy enabled: {self.proxy}")
self.session.cookies.set("p-b", token, domain="poe.com")
self.headers = {
"User-Agent": user_agent,
"Referrer": "https://poe.com/",
"Origin": "https://poe.com",
}
self.ws_domain = f"tch{random.randint(1, 1e6)}"
self.session.headers.update(self.headers)
self.next_data = self.get_next_data()
self.channel = self.get_channel_data()
self.connect_ws()
self.bots = self.get_bots()
self.bot_names = self.get_bot_names()
self.gql_headers = {
"poe-formkey": self.formkey,
"poe-tchannel": self.channel["channel"],
}
self.gql_headers = {**self.gql_headers, **self.headers}
self.subscribe()
def get_next_data(self):
logger.info("Downloading next_data...")
r = request_with_retries(self.session.get, self.home_url)
json_regex = r'<script id="__NEXT_DATA__" type="application\/json">(.+?)</script>'
json_text = re.search(json_regex, r.text).group(1)
next_data = json.loads(json_text)
self.formkey = next_data["props"]["formkey"]
self.viewer = next_data["props"]["pageProps"]["payload"]["viewer"]
return next_data
def get_bots(self):
viewer = self.next_data["props"]["pageProps"]["payload"]["viewer"]
if not "availableBots" in viewer:
raise RuntimeError("Invalid token.")
bot_list = viewer["availableBots"]
bots = {}
for bot in bot_list:
url = f'https://poe.com/_next/data/{self.next_data["buildId"]}/{bot["displayName"].lower()}.json'
logger.info("Downloading "+url)
r = request_with_retries(self.session.get, url)
chat_data = r.json()[
"pageProps"]["payload"]["chatOfBotDisplayName"]
bots[chat_data["defaultBotObject"]["nickname"]] = chat_data
return bots
def get_bot_names(self):
bot_names = {}
for bot_nickname in self.bots:
bot_obj = self.bots[bot_nickname]["defaultBotObject"]
bot_names[bot_nickname] = bot_obj["displayName"]
return bot_names
def get_channel_data(self, channel=None):
logger.info("Downloading channel data...")
r = request_with_retries(self.session.get, self.settings_url)
data = r.json()
self.formkey = data["formkey"]
return data["tchannelData"]
def get_websocket_url(self, channel=None):
if channel is None:
channel = self.channel
query = f'?min_seq={channel["minSeq"]}&channel={channel["channel"]}&hash={channel["channelHash"]}'
return f'wss://{self.ws_domain}.tch.{channel["baseHost"]}/up/{channel["boxName"]}/updates'+query
def send_query(self, query_name, variables):
# print(f'send_query: {query_name} {variables}')
for i in range(20):
payload = generate_payload(query_name, variables)
# print(f'query_payload: {query_name} {variables}')
r = request_with_retries(
self.session.post, self.gql_url, json=payload, headers=self.gql_headers)
data = r.json()
if data["data"] == None:
logger.warn(
f'{query_name} returned an error: {data["errors"][0]["message"]} | Retrying ({i+1}/20)')
time.sleep(2)
continue
return r.json()
raise RuntimeError(f'{query_name} failed too many times.')
def subscribe(self):
logger.info("Subscribing to mutations")
result = self.send_query("SubscriptionsMutation", {
"subscriptions": [
{
"subscriptionName": "messageAdded",
"query": queries["MessageAddedSubscription"]
},
{
"subscriptionName": "viewerStateUpdated",
"query": queries["ViewerStateUpdatedSubscription"]
}
]
})
def ws_run_thread(self):
kwargs = {}
if self.proxy:
proxy_parsed = urlparse(self.proxy)
kwargs = {
"proxy_type": proxy_parsed.scheme,
"http_proxy_host": proxy_parsed.hostname,
"http_proxy_port": proxy_parsed.port
}
self.ws.run_forever(**kwargs)
def connect_ws(self):
self.ws = websocket.WebSocketApp(
self.get_websocket_url(),
header={"User-Agent": user_agent},
on_message=self.on_message,
on_open=self.on_ws_connect,
on_error=self.on_ws_error
)
t = threading.Thread(target=self.ws_run_thread, daemon=True)
t.start()
while not self.ws_connected:
time.sleep(0.01)
def disconnect_ws(self):
if self.ws:
self.ws.close()
self.ws_connected = False
def on_ws_connect(self, ws):
self.ws_connected = True
def on_ws_error(self, ws, error):
logger.warn(f"Websocket returned error: {error}")
self.disconnect_ws()
self.connect_ws()
def on_message(self, ws, msg):
data = json.loads(msg)
message = json.loads(data["messages"][0])[
"payload"]["data"]["messageAdded"]
copied_dict = self.active_messages.copy()
for key, value in copied_dict.items():
# add the message to the appropriate queue
if value == message["messageId"] and key in self.message_queues:
self.message_queues[key].put(message)
return
# indicate that the response id is tied to the human message id
elif key != "pending" and value == None and message["state"] != "complete":
self.active_messages[key] = message["messageId"]
self.message_queues[key].put(message)
def send_message(self, chatbot, message, with_chat_break=False, timeout=20):
# if there is another active message, wait until it has finished sending
while None in self.active_messages.values():
time.sleep(0.01)
# None indicates that a message is still in progress
self.active_messages["pending"] = None
logger.info(f"Sending message to {chatbot}: {message}")
message_data = self.send_query("AddHumanMessageMutation", {
"bot": chatbot,
"query": message,
"chatId": self.bots[chatbot]["chatId"],
"source": None,
"withChatBreak": with_chat_break
})
del self.active_messages["pending"]
if not message_data["data"]["messageCreateWithStatus"]["messageLimit"]["canSend"]:
raise RuntimeError(f"Daily limit reached for {chatbot}.")
try:
human_message = message_data["data"]["messageCreateWithStatus"]
human_message_id = human_message["message"]["messageId"]
except TypeError:
raise RuntimeError(
f"An unknown error occured. Raw response data: {message_data}")
# indicate that the current message is waiting for a response
self.active_messages[human_message_id] = None
self.message_queues[human_message_id] = queue.Queue()
last_text = ""
message_id = None
while True:
try:
message = self.message_queues[human_message_id].get(
timeout=timeout)
except queue.Empty:
del self.active_messages[human_message_id]
del self.message_queues[human_message_id]
raise RuntimeError("Response timed out.")
# only break when the message is marked as complete
if message["state"] == "complete":
if last_text and message["messageId"] == message_id:
break
else:
continue
# update info about response
message["text_new"] = message["text"][len(last_text):]
last_text = message["text"]
message_id = message["messageId"]
yield message
del self.active_messages[human_message_id]
del self.message_queues[human_message_id]
load_queries()

@ -0,0 +1 @@
SmPiNXZI9hBTuf3viz74PA==

@ -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,316 @@
query ChatListPaginationQuery(
$count: Int = 5
$cursor: String
$id: ID!
) {
node(id: $id) {
__typename
...ChatPageMain_chat_1G22uz
id
}
}
fragment BotImage_bot on Bot {
image {
__typename
... on LocalBotImage {
localName
}
... on UrlBotImage {
url
}
}
displayName
}
fragment ChatMessageDownvotedButton_message on Message {
...MessageFeedbackReasonModal_message
...MessageFeedbackOtherModal_message
}
fragment ChatMessageDropdownMenu_message on Message {
id
messageId
vote
text
linkifiedText
...chatHelpers_isBotMessage
}
fragment ChatMessageFeedbackButtons_message on Message {
id
messageId
vote
voteReason
...ChatMessageDownvotedButton_message
}
fragment ChatMessageInputView_chat on Chat {
id
chatId
defaultBotObject {
nickname
messageLimit {
dailyBalance
shouldShowRemainingMessageCount
}
id
}
shouldShowDisclaimer
...chatHelpers_useSendMessage_chat
...chatHelpers_useSendChatBreak_chat
}
fragment ChatMessageInputView_edges on MessageEdge {
node {
...chatHelpers_isChatBreak
...chatHelpers_isHumanMessage
state
text
id
}
}
fragment ChatMessageOverflowButton_message on Message {
text
...ChatMessageDropdownMenu_message
...chatHelpers_isBotMessage
}
fragment ChatMessageSuggestedReplies_SuggestedReplyButton_chat on Chat {
...chatHelpers_useSendMessage_chat
}
fragment ChatMessageSuggestedReplies_SuggestedReplyButton_message on Message {
messageId
}
fragment ChatMessageSuggestedReplies_chat on Chat {
...ChatWelcomeView_chat
...ChatMessageSuggestedReplies_SuggestedReplyButton_chat
}
fragment ChatMessageSuggestedReplies_message on Message {
suggestedReplies
...ChatMessageSuggestedReplies_SuggestedReplyButton_message
}
fragment ChatMessage_chat on Chat {
defaultBotObject {
...ChatPageDisclaimer_bot
messageLimit {
...ChatPageRateLimitedBanner_messageLimit
}
id
}
...ChatMessageSuggestedReplies_chat
...ChatWelcomeView_chat
}
fragment ChatMessage_message on Message {
id
messageId
text
author
linkifiedText
state
...ChatMessageSuggestedReplies_message
...ChatMessageFeedbackButtons_message
...ChatMessageOverflowButton_message
...chatHelpers_isHumanMessage
...chatHelpers_isBotMessage
...chatHelpers_isChatBreak
...chatHelpers_useTimeoutLevel
...MarkdownLinkInner_message
}
fragment ChatMessagesView_chat on Chat {
...ChatMessage_chat
...ChatWelcomeView_chat
defaultBotObject {
messageLimit {
...ChatPageRateLimitedBanner_messageLimit
}
id
}
}
fragment ChatMessagesView_edges on MessageEdge {
node {
id
messageId
creationTime
...ChatMessage_message
...chatHelpers_isBotMessage
...chatHelpers_isHumanMessage
...chatHelpers_isChatBreak
}
}
fragment ChatPageDeleteFooter_chat on Chat {
...MessageDeleteConfirmationModal_chat
}
fragment ChatPageDisclaimer_bot on Bot {
disclaimer
}
fragment ChatPageMain_chat_1G22uz on Chat {
id
chatId
...ChatMessageInputView_chat
...ChatPageShareFooter_chat
...ChatPageDeleteFooter_chat
...ChatMessagesView_chat
...MarkdownLinkInner_chat
...chatHelpers_useUpdateStaleChat_chat
...ChatSubscriptionPaywallContextWrapper_chat
messagesConnection(last: $count, before: $cursor) {
edges {
...ChatMessagesView_edges
...ChatMessageInputView_edges
...MarkdownLinkInner_edges
node {
...chatHelpers_useUpdateStaleChat_message
id
__typename
}
cursor
id
}
pageInfo {
hasPreviousPage
startCursor
}
id
}
}
fragment ChatPageRateLimitedBanner_messageLimit on MessageLimit {
numMessagesRemaining
}
fragment ChatPageShareFooter_chat on Chat {
chatId
}
fragment ChatSubscriptionPaywallContextWrapper_chat on Chat {
defaultBotObject {
messageLimit {
numMessagesRemaining
shouldShowRemainingMessageCount
}
...SubscriptionPaywallModal_bot
id
}
}
fragment ChatWelcomeView_ChatWelcomeButton_chat on Chat {
...chatHelpers_useSendMessage_chat
}
fragment ChatWelcomeView_chat on Chat {
...ChatWelcomeView_ChatWelcomeButton_chat
defaultBotObject {
displayName
id
}
}
fragment MarkdownLinkInner_chat on Chat {
id
chatId
defaultBotObject {
nickname
id
}
...chatHelpers_useSendMessage_chat
}
fragment MarkdownLinkInner_edges on MessageEdge {
node {
state
id
}
}
fragment MarkdownLinkInner_message on Message {
messageId
}
fragment MessageDeleteConfirmationModal_chat on Chat {
id
}
fragment MessageFeedbackOtherModal_message on Message {
id
messageId
}
fragment MessageFeedbackReasonModal_message on Message {
id
messageId
}
fragment SubscriptionPaywallModal_bot on Bot {
displayName
messageLimit {
dailyLimit
numMessagesRemaining
shouldShowRemainingMessageCount
resetTime
}
...BotImage_bot
}
fragment chatHelpers_isBotMessage on Message {
...chatHelpers_isHumanMessage
...chatHelpers_isChatBreak
}
fragment chatHelpers_isChatBreak on Message {
author
}
fragment chatHelpers_isHumanMessage on Message {
author
}
fragment chatHelpers_useSendChatBreak_chat on Chat {
id
chatId
defaultBotObject {
nickname
introduction
model
id
}
shouldShowDisclaimer
}
fragment chatHelpers_useSendMessage_chat on Chat {
id
chatId
defaultBotObject {
nickname
id
}
shouldShowDisclaimer
}
fragment chatHelpers_useTimeoutLevel on Message {
id
state
text
messageId
}
fragment chatHelpers_useUpdateStaleChat_chat on Chat {
chatId
...chatHelpers_useSendChatBreak_chat
}
fragment chatHelpers_useUpdateStaleChat_message on Message {
creationTime
...chatHelpers_isChatBreak
}

@ -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,7 @@
mutation deleteMessageMutation(
$messageIds: [BigInt!]!
) {
messagesDelete(messageIds: $messageIds) {
edgeIds
}
}

@ -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,100 @@
subscription messageAdded (
$chatId: BigInt!
) {
messageAdded(chatId: $chatId) {
id
messageId
creationTime
state
...ChatMessage_message
...chatHelpers_isBotMessage
}
}
fragment ChatMessageDownvotedButton_message on Message {
...MessageFeedbackReasonModal_message
...MessageFeedbackOtherModal_message
}
fragment ChatMessageDropdownMenu_message on Message {
id
messageId
vote
text
linkifiedText
...chatHelpers_isBotMessage
}
fragment ChatMessageFeedbackButtons_message on Message {
id
messageId
vote
voteReason
...ChatMessageDownvotedButton_message
}
fragment ChatMessageOverflowButton_message on Message {
text
...ChatMessageDropdownMenu_message
...chatHelpers_isBotMessage
}
fragment ChatMessageSuggestedReplies_SuggestedReplyButton_message on Message {
messageId
}
fragment ChatMessageSuggestedReplies_message on Message {
suggestedReplies
...ChatMessageSuggestedReplies_SuggestedReplyButton_message
}
fragment ChatMessage_message on Message {
id
messageId
text
author
linkifiedText
state
...ChatMessageSuggestedReplies_message
...ChatMessageFeedbackButtons_message
...ChatMessageOverflowButton_message
...chatHelpers_isHumanMessage
...chatHelpers_isBotMessage
...chatHelpers_isChatBreak
...chatHelpers_useTimeoutLevel
...MarkdownLinkInner_message
}
fragment MarkdownLinkInner_message on Message {
messageId
}
fragment MessageFeedbackOtherModal_message on Message {
id
messageId
}
fragment MessageFeedbackReasonModal_message on Message {
id
messageId
}
fragment chatHelpers_isBotMessage on Message {
...chatHelpers_isHumanMessage
...chatHelpers_isChatBreak
}
fragment chatHelpers_isChatBreak on Message {
author
}
fragment chatHelpers_isHumanMessage on Message {
author
}
fragment chatHelpers_useTimeoutLevel on Message {
id
state
text
messageId
}

@ -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,9 @@
mutation subscriptionsMutation(
$subscriptions: [AutoSubscriptionQuery!]!
) {
autoSubscribe(subscriptions: $subscriptions) {
viewer {
id
}
}
}

@ -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,43 @@
subscription viewerStateUpdated {
viewerStateUpdated {
id
...ChatPageBotSwitcher_viewer
}
}
fragment BotHeader_bot on Bot {
displayName
messageLimit {
dailyLimit
}
...BotImage_bot
}
fragment BotImage_bot on Bot {
image {
__typename
... on LocalBotImage {
localName
}
... on UrlBotImage {
url
}
}
displayName
}
fragment BotLink_bot on Bot {
displayName
}
fragment ChatPageBotSwitcher_viewer on Viewer {
availableBots {
id
messageLimit {
dailyLimit
}
...BotLink_bot
...BotHeader_bot
}
allowUserCreatedBots: booleanGate(gateName: "enable_user_created_bots")
}

@ -0,0 +1,62 @@
from requests import Session
from string import ascii_letters
from random import choices
class Mail:
def __init__(self, proxies: dict = None) -> None:
self.client = Session()
self.client.proxies = None #proxies
self.client.headers = {
"host": "api.mail.tm",
"connection": "keep-alive",
"sec-ch-ua": "\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\"",
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"sec-ch-ua-mobile": "?0",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
"sec-ch-ua-platform": "\"macOS\"",
"origin": "https://mail.tm",
"sec-fetch-site": "same-site",
"sec-fetch-mode": "cors",
"sec-fetch-dest": "empty",
"referer": "https://mail.tm/",
"accept-encoding": "gzip, deflate, br",
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8"
}
def get_mail(self) -> str:
token = ''.join(choices(ascii_letters, k=10)).lower()
init = self.client.post("https://api.mail.tm/accounts", json={
"address" : f"{token}@bugfoo.com",
"password": token
})
if init.status_code == 201:
resp = self.client.post("https://api.mail.tm/token", json = {
**init.json(),
"password": token
})
self.client.headers['authorization'] = 'Bearer ' + resp.json()['token']
return f"{token}@bugfoo.com"
else:
raise Exception("Failed to create email")
def fetch_inbox(self):
return self.client.get(f"https://api.mail.tm/messages").json()["hydra:member"]
def get_message(self, message_id: str):
return self.client.get(f"https://api.mail.tm/messages/{message_id}").json()
def get_message_content(self, message_id: str):
return self.get_message(message_id)["text"]
# if __name__ == "__main__":
# client = Mail()
# client.get_mail()
Loading…
Cancel
Save