2023-04-23 21:38:47 +00:00
import json
from datetime import datetime
from hashlib import md5
from json import dumps
from pathlib import Path
from random import choice , choices , randint
from re import search , findall
from string import ascii_letters , digits
2023-04-26 22:40:02 +00:00
from typing import Optional , Union
2023-04-23 21:38:47 +00:00
from urllib . parse import unquote
import selenium . webdriver . support . expected_conditions as EC
2023-04-26 22:40:02 +00:00
from fake_useragent import UserAgent
2023-04-23 21:38:47 +00:00
from pypasser import reCaptchaV3
from requests import Session
2023-04-26 22:40:02 +00:00
from selenium . webdriver import Firefox , Chrome , FirefoxOptions , ChromeOptions
2023-04-23 21:38:47 +00:00
from selenium . webdriver . common . by import By
from selenium . webdriver . support . wait import WebDriverWait
from tls_client import Session as TLS
from quora . api import Client as PoeClient
from quora . mail import Emailnator
2023-04-16 16:10:37 +00:00
2023-04-26 22:40:02 +00:00
SELENIUM_WEB_DRIVER_ERROR_MSG = b ''' The error message you are receiving is due to the `geckodriver` executable not
being found in your system \' s PATH. To resolve this issue, you need to download the geckodriver and add its location
to your system \' s PATH. \n \n Here are the steps to resolve the issue: \n \n 1. Download the geckodriver for your platform
( Windows , macOS , or Linux ) from the following link : https : / / github . com / mozilla / geckodriver / releases \n \n2 . Extract the
downloaded archive and locate the geckodriver executable . \n \n3 . Add the geckodriver executable to your system \' s
PATH . \n \nFor macOS and Linux : \n \n - Open a terminal window . \n - Move the geckodriver executable to a directory that is
already in your PATH , or create a new directory and add it to your PATH : \n \n ` ` ` bash \n # Example: Move geckodriver to
/ usr / local / bin \nmv / path / to / your / geckodriver / usr / local / bin \n ` ` ` \n \n - If you created a new directory , add it to your
PATH : \n \n ` ` ` bash \n # Example: Add a new directory to PATH\nexport PATH=$PATH:/path/to/your/directory\n```\n\nFor
Windows : \n \n - Right - click on " My Computer " or " This PC " and select " Properties " . \n - Click on " Advanced system
settings " . \n - Click on the " Environment Variables " button. \n - In the " System variables " section, find the " Path "
variable , select it , and click " Edit " . \n - Click " New " and add the path to the directory containing the geckodriver
executable . \n \nAfter adding the geckodriver to your PATH , restart your terminal or command prompt and try running
your script again . The error should be resolved . '''
2023-04-22 09:57:45 +00:00
# from twocaptcha import TwoCaptcha
# solver = TwoCaptcha('72747bf24a9d89b4dcc1b24875efd358')
2023-04-23 21:38:47 +00:00
MODELS = {
2023-04-26 22:40:02 +00:00
' Sage ' : ' capybara ' ,
' GPT-4 ' : ' beaver ' ,
' Claude+ ' : ' a2_2 ' ,
' Claude-instant ' : ' a2 ' ,
' ChatGPT ' : ' chinchilla ' ,
' Dragonfly ' : ' nutria ' ,
' NeevaAI ' : ' hutia ' ,
2023-04-23 21:38:47 +00:00
}
2023-04-16 16:10:37 +00:00
def extract_formkey ( html ) :
2023-04-26 22:40:02 +00:00
script_regex = r ' <script>if \ (.+ \ )throw new Error;(.+)</script> '
2023-04-23 21:38:47 +00:00
script_text = search ( script_regex , html ) . group ( 1 )
key_regex = r ' var .= " ([0-9a-f]+) " , '
key_text = search ( key_regex , script_text ) . group ( 1 )
2023-04-26 22:40:02 +00:00
cipher_regex = r ' . \ [( \ d+) \ ]=. \ [( \ d+) \ ] '
2023-04-16 16:10:37 +00:00
cipher_pairs = findall ( cipher_regex , script_text )
2023-04-26 22:40:02 +00:00
formkey_list = [ ' ' ] * len ( cipher_pairs )
2023-04-16 16:10:37 +00:00
for pair in cipher_pairs :
formkey_index , key_index = map ( int , pair )
formkey_list [ formkey_index ] = key_text [ key_index ]
2023-04-26 22:40:02 +00:00
formkey = ' ' . join ( formkey_list )
2023-04-16 16:10:37 +00:00
return formkey
2023-04-11 16:44:29 +00:00
2023-04-23 21:38:47 +00:00
2023-03-29 20:10:42 +00:00
class PoeResponse :
class Completion :
class Choices :
def __init__ ( self , choice : dict ) - > None :
2023-04-26 22:40:02 +00:00
self . text = choice [ ' text ' ]
2023-04-23 21:38:47 +00:00
self . content = self . text . encode ( )
2023-04-26 22:40:02 +00:00
self . index = choice [ ' index ' ]
self . logprobs = choice [ ' logprobs ' ]
self . finish_reason = choice [ ' finish_reason ' ]
2023-04-23 21:38:47 +00:00
2023-03-29 20:10:42 +00:00
def __repr__ ( self ) - > str :
2023-04-26 22:40:02 +00:00
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> '''
2023-03-29 20:10:42 +00:00
def __init__ ( self , choices : dict ) - > None :
self . choices = [ self . Choices ( choice ) for choice in choices ]
class Usage :
def __init__ ( self , usage_dict : dict ) - > None :
2023-04-26 22:40:02 +00:00
self . prompt_tokens = usage_dict [ ' prompt_tokens ' ]
self . completion_tokens = usage_dict [ ' completion_tokens ' ]
self . total_tokens = usage_dict [ ' total_tokens ' ]
2023-03-29 20:10:42 +00:00
def __repr__ ( self ) :
2023-04-26 22:40:02 +00:00
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> '''
2023-04-23 21:38:47 +00:00
2023-03-29 20:10:42 +00:00
def __init__ ( self , response_dict : dict ) - > None :
2023-04-23 21:38:47 +00:00
self . response_dict = response_dict
2023-04-26 22:40:02 +00:00
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 ' ] )
2023-03-29 20:10:42 +00:00
def json ( self ) - > dict :
return self . response_dict
2023-04-11 16:44:29 +00:00
class ModelResponse :
def __init__ ( self , json_response : dict ) - > None :
2023-04-26 22:40:02 +00:00
self . id = json_response [ ' data ' ] [ ' poeBotCreate ' ] [ ' bot ' ] [ ' id ' ]
self . name = json_response [ ' data ' ] [ ' poeBotCreate ' ] [ ' bot ' ] [ ' displayName ' ]
self . limit = json_response [ ' data ' ] [ ' poeBotCreate ' ] [ ' bot ' ] [ ' messageLimit ' ] [ ' dailyLimit ' ]
self . deleted = json_response [ ' data ' ] [ ' poeBotCreate ' ] [ ' bot ' ] [ ' deletionState ' ]
2023-04-23 21:38:47 +00:00
2023-04-11 16:44:29 +00:00
class Model :
2023-04-26 22:40:02 +00:00
@staticmethod
2023-04-11 16:44:29 +00:00
def create (
2023-04-27 14:43:59 +00:00
token : str ,
model : str = ' gpt-3.5-turbo ' , # claude-instant
system_prompt : str = ' You are ChatGPT a large language model developed by Openai. Answer as consisely as possible ' ,
description : str = ' gpt-3.5 language model from openai, skidded by poe.com ' ,
handle : str = None ,
2023-04-23 21:38:47 +00:00
) - > ModelResponse :
2023-04-11 16:44:29 +00:00
models = {
2023-04-26 22:40:02 +00:00
' gpt-3.5-turbo ' : ' chinchilla ' ,
' claude-instant-v1.0 ' : ' a2 ' ,
' gpt-4 ' : ' beaver ' ,
2023-04-11 16:44:29 +00:00
}
2023-04-23 21:38:47 +00:00
2023-04-11 16:44:29 +00:00
if not handle :
2023-04-26 22:40:02 +00:00
handle = f ' gptx { randint ( 1111111 , 9999999 ) } '
2023-04-23 21:38:47 +00:00
2023-04-11 16:44:29 +00:00
client = Session ( )
2023-04-26 22:40:02 +00:00
client . cookies [ ' p-b ' ] = token
2023-04-23 21:38:47 +00:00
2023-04-26 22:40:02 +00:00
formkey = extract_formkey ( client . get ( ' https://poe.com ' ) . text )
settings = client . get ( ' https://poe.com/api/settings ' ) . json ( )
2023-04-11 16:44:29 +00:00
client . headers = {
2023-04-26 22:40:02 +00:00
' host ' : ' poe.com ' ,
' origin ' : ' https://poe.com ' ,
' referer ' : ' https://poe.com/ ' ,
' poe-formkey ' : formkey ,
' poe-tchannel ' : settings [ ' tchannelData ' ] [ ' channel ' ] ,
' user-agent ' : UserAgent ( ) . random ,
' connection ' : ' keep-alive ' ,
' sec-ch-ua ' : ' " Chromium " ;v= " 112 " , " Google Chrome " ;v= " 112 " , " Not:A-Brand " ;v= " 99 " ' ,
' sec-ch-ua-mobile ' : ' ?0 ' ,
' sec-ch-ua-platform ' : ' " macOS " ' ,
' content-type ' : ' application/json ' ,
' sec-fetch-site ' : ' same-origin ' ,
' sec-fetch-mode ' : ' cors ' ,
' sec-fetch-dest ' : ' empty ' ,
' accept ' : ' */* ' ,
' accept-encoding ' : ' gzip, deflate, br ' ,
' accept-language ' : ' en-GB,en-US;q=0.9,en;q=0.8 ' ,
2023-04-11 16:44:29 +00:00
}
2023-04-23 21:38:47 +00:00
payload = dumps (
2023-04-26 22:40:02 +00:00
separators = ( ' , ' , ' : ' ) ,
2023-04-23 21:38:47 +00:00
obj = {
2023-04-26 22:40:02 +00:00
' queryName ' : ' CreateBotMain_poeBotCreate_Mutation ' ,
' variables ' : {
' model ' : models [ model ] ,
' handle ' : handle ,
' prompt ' : system_prompt ,
' isPromptPublic ' : True ,
' introduction ' : ' ' ,
' description ' : description ,
' profilePictureUrl ' : ' https://qph.fs.quoracdn.net/main-qimg-24e0b480dcd946e1cc6728802c5128b6 ' ,
' apiUrl ' : None ,
' apiKey ' : ' ' . join ( choices ( ascii_letters + digits , k = 32 ) ) ,
' isApiBot ' : False ,
' hasLinkification ' : False ,
' hasMarkdownRendering ' : False ,
' hasSuggestedReplies ' : False ,
' isPrivateBot ' : False ,
2023-04-23 21:38:47 +00:00
} ,
2023-04-26 22:40:02 +00:00
' query ' : ' mutation CreateBotMain_poeBotCreate_Mutation( \n $model: String! \n $handle: String! \n $prompt: String! \n $isPromptPublic: Boolean! \n $introduction: String! \n $description: String! \n $profilePictureUrl: String \n $apiUrl: String \n $apiKey: String \n $isApiBot: Boolean \n $hasLinkification: Boolean \n $hasMarkdownRendering: Boolean \n $hasSuggestedReplies: Boolean \n $isPrivateBot: Boolean \n ) { \n poeBotCreate(model: $model, handle: $handle, promptPlaintext: $prompt, isPromptPublic: $isPromptPublic, introduction: $introduction, description: $description, profilePicture: $profilePictureUrl, apiUrl: $apiUrl, apiKey: $apiKey, isApiBot: $isApiBot, hasLinkification: $hasLinkification, hasMarkdownRendering: $hasMarkdownRendering, hasSuggestedReplies: $hasSuggestedReplies, isPrivateBot: $isPrivateBot) { \n status \n bot { \n id \n ...BotHeader_bot \n } \n } \n } \n \n fragment BotHeader_bot on Bot { \n displayName \n messageLimit { \n dailyLimit \n } \n ...BotImage_bot \n ...BotLink_bot \n ...IdAnnotation_node \n ...botHelpers_useViewerCanAccessPrivateBot \n ...botHelpers_useDeletion_bot \n } \n \n fragment BotImage_bot on Bot { \n displayName \n ...botHelpers_useDeletion_bot \n ...BotImage_useProfileImage_bot \n } \n \n fragment BotImage_useProfileImage_bot on Bot { \n image { \n __typename \n ... on LocalBotImage { \n localName \n } \n ... on UrlBotImage { \n url \n } \n } \n ...botHelpers_useDeletion_bot \n } \n \n fragment BotLink_bot on Bot { \n displayName \n } \n \n fragment IdAnnotation_node on Node { \n __isNode: __typename \n id \n } \n \n fragment botHelpers_useDeletion_bot on Bot { \n deletionState \n } \n \n fragment botHelpers_useViewerCanAccessPrivateBot on Bot { \n isPrivateBot \n viewerIsCreator \n } \n ' ,
2023-04-11 16:44:29 +00:00
} ,
2023-04-23 21:38:47 +00:00
)
2023-04-26 22:40:02 +00:00
base_string = payload + client . headers [ ' poe-formkey ' ] + ' WpuLMiXEKKE98j56k '
client . headers [ ' poe-tag-id ' ] = md5 ( base_string . encode ( ) ) . hexdigest ( )
2023-04-11 16:44:29 +00:00
2023-04-26 22:40:02 +00:00
response = client . post ( ' https://poe.com/api/gql_POST ' , data = payload )
2023-04-16 16:10:37 +00:00
2023-04-26 22:40:02 +00:00
if ' success ' not in response . text :
2023-04-23 21:38:47 +00:00
raise Exception (
2023-04-26 22:40:02 +00:00
'''
2023-04-11 16:44:29 +00:00
Bot creation Failed
! ! Important ! !
Bot creation was not enabled on this account
please use : quora . Account . create with enable_bot_creation set to True
2023-04-26 22:40:02 +00:00
'''
2023-04-23 21:38:47 +00:00
)
2023-04-11 16:44:29 +00:00
return ModelResponse ( response . json ( ) )
2023-04-22 09:57:45 +00:00
2023-03-29 20:10:42 +00:00
class Account :
2023-04-26 22:40:02 +00:00
@staticmethod
2023-04-23 21:38:47 +00:00
def create (
2023-04-27 14:43:59 +00:00
proxy : Optional [ str ] = None ,
logging : bool = False ,
enable_bot_creation : bool = False ,
2023-04-23 21:38:47 +00:00
) :
2023-04-26 22:40:02 +00:00
client = TLS ( client_identifier = ' chrome110 ' )
client . proxies = { ' http ' : f ' http:// { proxy } ' , ' https ' : f ' http:// { proxy } ' } if proxy else None
2023-04-16 16:10:37 +00:00
2023-04-23 21:38:47 +00:00
mail_client = Emailnator ( )
mail_address = mail_client . get_mail ( )
2023-03-29 20:10:42 +00:00
2023-04-23 21:38:47 +00:00
if logging :
2023-04-26 22:40:02 +00:00
print ( ' email ' , mail_address )
2023-03-29 20:10:42 +00:00
client . headers = {
2023-04-26 22:40:02 +00:00
' authority ' : ' poe.com ' ,
' accept ' : ' */* ' ,
' accept-language ' : ' en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3 ' ,
' content-type ' : ' application/json ' ,
' origin ' : ' https://poe.com ' ,
' poe-tag-id ' : ' null ' ,
' referer ' : ' https://poe.com/login ' ,
' sec-ch-ua ' : ' " Chromium " ;v= " 112 " , " Google Chrome " ;v= " 112 " , " Not:A-Brand " ;v= " 99 " ' ,
' sec-ch-ua-mobile ' : ' ?0 ' ,
' sec-ch-ua-platform ' : ' " macOS " ' ,
' sec-fetch-dest ' : ' empty ' ,
' sec-fetch-mode ' : ' cors ' ,
' sec-fetch-site ' : ' same-origin ' ,
' 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 ' ,
' poe-formkey ' : extract_formkey ( client . get ( ' https://poe.com/login ' ) . text ) ,
' poe-tchannel ' : client . get ( ' https://poe.com/api/settings ' ) . json ( ) [ ' tchannelData ' ] [ ' channel ' ] ,
2023-03-29 20:10:42 +00:00
}
2023-04-23 21:38:47 +00:00
token = reCaptchaV3 (
2023-04-26 22:40:02 +00:00
' https://www.recaptcha.net/recaptcha/enterprise/anchor?ar=1&k=6LflhEElAAAAAI_ewVwRWI9hsyV4mbZnYAslSvlG&co=aHR0cHM6Ly9wb2UuY29tOjQ0Mw..&hl=en&v=4PnKmGB9wRHh1i04o7YUICeI&size=invisible&cb=bi6ivxoskyal '
2023-04-23 21:38:47 +00:00
)
2023-04-22 09:57:45 +00:00
# token = solver.recaptcha(sitekey='6LflhEElAAAAAI_ewVwRWI9hsyV4mbZnYAslSvlG',
# url = 'https://poe.com/login?redirect_url=%2F',
# version = 'v3',
# enterprise = 1,
# invisible = 1,
# action = 'login',)['code']
2023-04-20 08:49:30 +00:00
2023-04-23 21:38:47 +00:00
payload = dumps (
2023-04-26 22:40:02 +00:00
separators = ( ' , ' , ' : ' ) ,
2023-04-23 21:38:47 +00:00
obj = {
2023-04-26 22:40:02 +00:00
' queryName ' : ' MainSignupLoginSection_sendVerificationCodeMutation_Mutation ' ,
' variables ' : {
' emailAddress ' : mail_address ,
' phoneNumber ' : None ,
' recaptchaToken ' : token ,
2023-04-23 21:38:47 +00:00
} ,
2023-04-26 22:40:02 +00:00
' query ' : ' mutation MainSignupLoginSection_sendVerificationCodeMutation_Mutation( \n $emailAddress: String \n $phoneNumber: String \n $recaptchaToken: String \n ) { \n sendVerificationCode(verificationReason: login, emailAddress: $emailAddress, phoneNumber: $phoneNumber, recaptchaToken: $recaptchaToken) { \n status \n errorMessage \n } \n } \n ' ,
2023-03-29 20:10:42 +00:00
} ,
2023-04-23 21:38:47 +00:00
)
2023-04-26 22:40:02 +00:00
base_string = payload + client . headers [ ' poe-formkey ' ] + ' WpuLMiXEKKE98j56k '
client . headers [ ' poe-tag-id ' ] = md5 ( base_string . encode ( ) ) . hexdigest ( )
2023-04-15 14:42:07 +00:00
2023-04-22 09:57:45 +00:00
print ( dumps ( client . headers , indent = 4 ) )
2023-03-29 20:10:42 +00:00
2023-04-26 22:40:02 +00:00
response = client . post ( ' https://poe.com/api/gql_POST ' , data = payload )
2023-03-29 20:10:42 +00:00
2023-04-26 22:40:02 +00:00
if ' automated_request_detected ' in response . text :
print ( ' please try using a proxy / wait for fix ' )
2023-03-29 20:10:42 +00:00
2023-04-26 22:40:02 +00:00
if ' Bad Request ' in response . text :
2023-04-23 21:38:47 +00:00
if logging :
2023-04-26 22:40:02 +00:00
print ( ' bad request, retrying... ' , response . json ( ) )
2023-04-23 21:38:47 +00:00
quit ( )
if logging :
2023-04-26 22:40:02 +00:00
print ( ' send_code ' , response . json ( ) )
2023-04-23 21:38:47 +00:00
mail_content = mail_client . get_message ( )
mail_token = findall ( r ' ; " >( \ d { 6,7})</div> ' , mail_content ) [ 0 ]
if logging :
2023-04-26 22:40:02 +00:00
print ( ' code ' , mail_token )
2023-04-23 21:38:47 +00:00
payload = dumps (
2023-04-26 22:40:02 +00:00
separators = ( ' , ' , ' : ' ) ,
2023-04-23 21:38:47 +00:00
obj = {
2023-04-26 22:40:02 +00:00
' queryName ' : ' SignupOrLoginWithCodeSection_signupWithVerificationCodeMutation_Mutation ' ,
' variables ' : {
' verificationCode ' : str ( mail_token ) ,
' emailAddress ' : mail_address ,
' phoneNumber ' : None ,
2023-04-23 21:38:47 +00:00
} ,
2023-04-26 22:40:02 +00:00
' 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 ' ,
2023-03-29 20:10:42 +00:00
} ,
2023-04-23 21:38:47 +00:00
)
2023-04-26 22:40:02 +00:00
base_string = payload + client . headers [ ' poe-formkey ' ] + ' WpuLMiXEKKE98j56k '
client . headers [ ' poe-tag-id ' ] = md5 ( base_string . encode ( ) ) . hexdigest ( )
2023-04-16 16:10:37 +00:00
2023-04-26 22:40:02 +00:00
response = client . post ( ' https://poe.com/api/gql_POST ' , data = payload )
2023-04-23 21:38:47 +00:00
if logging :
2023-04-26 22:40:02 +00:00
print ( ' verify_code ' , response . json ( ) )
2023-03-29 20:10:42 +00:00
2023-04-23 21:38:47 +00:00
def get ( self ) :
2023-04-26 22:40:02 +00:00
cookies = open ( Path ( __file__ ) . resolve ( ) . parent / ' cookies.txt ' , ' r ' ) . read ( ) . splitlines ( )
2023-03-29 20:10:42 +00:00
return choice ( cookies )
2023-04-23 21:38:47 +00:00
2023-03-29 20:10:42 +00:00
class StreamingCompletion :
2023-04-26 22:40:02 +00:00
@staticmethod
2023-03-29 20:10:42 +00:00
def create (
2023-04-27 14:43:59 +00:00
model : str = ' gpt-4 ' ,
custom_model : bool = None ,
prompt : str = ' hello world ' ,
token : str = ' ' ,
2023-04-23 21:38:47 +00:00
) :
_model = MODELS [ model ] if not custom_model else custom_model
2023-03-29 20:10:42 +00:00
client = PoeClient ( token )
2023-04-23 21:38:47 +00:00
2023-04-13 15:08:04 +00:00
for chunk in client . send_message ( _model , prompt ) :
2023-04-23 21:38:47 +00:00
yield PoeResponse (
{
2023-04-26 22:40:02 +00:00
' id ' : chunk [ ' messageId ' ] ,
' object ' : ' text_completion ' ,
' created ' : chunk [ ' creationTime ' ] ,
' model ' : _model ,
' choices ' : [
2023-04-23 21:38:47 +00:00
{
2023-04-26 22:40:02 +00:00
' text ' : chunk [ ' text_new ' ] ,
' index ' : 0 ,
' logprobs ' : None ,
' finish_reason ' : ' stop ' ,
2023-04-23 21:38:47 +00:00
}
] ,
2023-04-26 22:40:02 +00:00
' usage ' : {
' prompt_tokens ' : len ( prompt ) ,
' completion_tokens ' : len ( chunk [ ' text_new ' ] ) ,
' total_tokens ' : len ( prompt ) + len ( chunk [ ' text_new ' ] ) ,
2023-04-23 21:38:47 +00:00
} ,
2023-03-29 20:10:42 +00:00
}
2023-04-23 21:38:47 +00:00
)
2023-03-29 20:10:42 +00:00
class Completion :
def create (
2023-04-27 14:43:59 +00:00
model : str = ' gpt-4 ' ,
custom_model : str = None ,
prompt : str = ' hello world ' ,
token : str = ' ' ,
2023-04-23 21:38:47 +00:00
) :
2023-03-29 20:10:42 +00:00
models = {
2023-04-26 22:40:02 +00:00
' sage ' : ' capybara ' ,
' gpt-4 ' : ' beaver ' ,
' claude-v1.2 ' : ' a2_2 ' ,
' claude-instant-v1.0 ' : ' a2 ' ,
' gpt-3.5-turbo ' : ' chinchilla ' ,
2023-03-29 20:10:42 +00:00
}
2023-04-23 21:38:47 +00:00
2023-04-11 16:44:29 +00:00
_model = models [ model ] if not custom_model else custom_model
2023-04-23 21:38:47 +00:00
2023-03-29 20:10:42 +00:00
client = PoeClient ( token )
2023-04-23 21:38:47 +00:00
2023-04-13 15:08:04 +00:00
for chunk in client . send_message ( _model , prompt ) :
2023-03-29 20:10:42 +00:00
pass
2023-04-23 21:38:47 +00:00
return PoeResponse (
{
2023-04-26 22:40:02 +00:00
' id ' : chunk [ ' messageId ' ] ,
' object ' : ' text_completion ' ,
' created ' : chunk [ ' creationTime ' ] ,
' model ' : _model ,
' choices ' : [
2023-04-23 21:38:47 +00:00
{
2023-04-26 22:40:02 +00:00
' text ' : chunk [ ' text ' ] ,
' index ' : 0 ,
' logprobs ' : None ,
' finish_reason ' : ' stop ' ,
2023-04-23 21:38:47 +00:00
}
] ,
2023-04-26 22:40:02 +00:00
' usage ' : {
' prompt_tokens ' : len ( prompt ) ,
' completion_tokens ' : len ( chunk [ ' text ' ] ) ,
' total_tokens ' : len ( prompt ) + len ( chunk [ ' text ' ] ) ,
2023-04-23 21:38:47 +00:00
} ,
}
)
class Poe :
2023-04-26 22:40:02 +00:00
def __init__ (
2023-04-27 14:43:59 +00:00
self ,
model : str = ' ChatGPT ' ,
driver : str = ' firefox ' ,
download_driver : bool = False ,
driver_path : Optional [ str ] = None ,
cookie_path : str = ' ./quora/cookie.json ' ,
2023-04-26 22:40:02 +00:00
) :
2023-04-24 09:04:14 +00:00
# validating the model
if model and model not in MODELS :
2023-04-26 22:40:02 +00:00
raise RuntimeError ( ' Sorry, the model you provided does not exist. Please check and try again. ' )
2023-04-23 21:38:47 +00:00
self . model = MODELS [ model ]
2023-04-26 22:40:02 +00:00
self . cookie_path = cookie_path
self . cookie = self . __load_cookie ( driver , download_driver , driver_path = driver_path )
2023-04-23 21:38:47 +00:00
self . client = PoeClient ( self . cookie )
2023-04-26 22:40:02 +00:00
def __load_cookie ( self , driver : str , download_driver : bool , driver_path : Optional [ str ] = None ) - > str :
if ( cookie_file := Path ( self . cookie_path ) ) . exists ( ) :
2023-04-23 21:38:47 +00:00
with cookie_file . open ( ) as fp :
cookie = json . load ( fp )
2023-04-26 22:40:02 +00:00
if datetime . fromtimestamp ( cookie [ ' expiry ' ] ) < datetime . now ( ) :
cookie = self . __register_and_get_cookie ( driver , driver_path = driver_path )
2023-04-23 21:38:47 +00:00
else :
2023-04-26 22:40:02 +00:00
print ( ' Loading the cookie from file ' )
2023-04-23 21:38:47 +00:00
else :
2023-04-26 22:40:02 +00:00
cookie = self . __register_and_get_cookie ( driver , driver_path = driver_path )
2023-04-23 21:38:47 +00:00
2023-04-26 22:40:02 +00:00
return unquote ( cookie [ ' value ' ] )
2023-04-23 21:38:47 +00:00
2023-04-26 22:40:02 +00:00
def __register_and_get_cookie ( self , driver : str , driver_path : Optional [ str ] = None ) - > dict :
2023-04-23 21:38:47 +00:00
mail_client = Emailnator ( )
mail_address = mail_client . get_mail ( )
2023-04-26 22:40:02 +00:00
driver = self . __resolve_driver ( driver , driver_path = driver_path )
2023-04-23 21:38:47 +00:00
driver . get ( " https://www.poe.com " )
# clicking use email button
driver . find_element ( By . XPATH , ' //button[contains(text(), " Use email " )] ' ) . click ( )
2023-04-26 22:40:02 +00:00
email = WebDriverWait ( driver , 30 ) . until ( EC . presence_of_element_located ( ( By . XPATH , ' //input[@type= " email " ] ' ) ) )
2023-04-23 21:38:47 +00:00
email . send_keys ( mail_address )
driver . find_element ( By . XPATH , ' //button[text()= " Go " ] ' ) . click ( )
code = findall ( r ' ; " >( \ d { 6,7})</div> ' , mail_client . get_message ( ) ) [ 0 ]
print ( code )
verification_code = WebDriverWait ( driver , 30 ) . until (
EC . presence_of_element_located ( ( By . XPATH , ' //input[@placeholder= " Code " ] ' ) )
)
verification_code . send_keys ( code )
2023-04-26 22:40:02 +00:00
verify_button = EC . presence_of_element_located ( ( By . XPATH , ' //button[text()= " Verify " ] ' ) )
login_button = EC . presence_of_element_located ( ( By . XPATH , ' //button[text()= " Log In " ] ' ) )
2023-04-23 21:38:47 +00:00
WebDriverWait ( driver , 30 ) . until ( EC . any_of ( verify_button , login_button ) ) . click ( )
2023-04-26 22:40:02 +00:00
cookie = driver . get_cookie ( ' p-b ' )
2023-04-23 21:38:47 +00:00
2023-04-26 22:40:02 +00:00
with open ( self . cookie_path , ' w ' ) as fw :
2023-04-23 21:38:47 +00:00
json . dump ( cookie , fw )
driver . close ( )
return cookie
2023-04-26 22:40:02 +00:00
@classmethod
def __resolve_driver ( cls , driver : str , driver_path : Optional [ str ] = None ) - > Union [ Firefox , Chrome ] :
options = FirefoxOptions ( ) if driver == ' firefox ' else ChromeOptions ( )
options . add_argument ( ' -headless ' )
if driver_path :
options . binary_location = driver_path
try :
return Firefox ( options = options ) if driver == ' firefox ' else Chrome ( options = options )
except Exception :
raise Exception ( SELENIUM_WEB_DRIVER_ERROR_MSG )
2023-04-24 07:43:41 +00:00
def chat ( self , message : str , model : Optional [ str ] = None ) - > str :
2023-04-24 09:04:14 +00:00
if model and model not in MODELS :
2023-04-26 22:40:02 +00:00
raise RuntimeError ( ' Sorry, the model you provided does not exist. Please check and try again. ' )
2023-04-24 09:04:14 +00:00
model = MODELS [ model ] if model else self . model
2023-04-23 21:38:47 +00:00
response = None
2023-04-24 07:43:41 +00:00
for chunk in self . client . send_message ( model , message ) :
2023-04-26 22:40:02 +00:00
response = chunk [ ' text ' ]
2023-04-23 21:38:47 +00:00
return response
2023-04-24 07:43:41 +00:00
def create_bot (
2023-04-27 14:43:59 +00:00
self ,
name : str ,
/ ,
prompt : str = ' ' ,
base_model : str = ' ChatGPT ' ,
description : str = ' ' ,
2023-04-24 07:43:41 +00:00
) - > None :
if base_model not in MODELS :
2023-04-26 22:40:02 +00:00
raise RuntimeError ( ' Sorry, the base_model you provided does not exist. Please check and try again. ' )
2023-04-24 07:43:41 +00:00
response = self . client . create_bot (
handle = name ,
prompt = prompt ,
base_model = MODELS [ base_model ] ,
description = description ,
)
print ( f ' Successfully created bot with name: { response [ " bot " ] [ " displayName " ] } ' )
2023-04-24 08:22:43 +00:00
def list_bots ( self ) - > list :
return list ( self . client . bot_names . values ( ) )