diff --git a/.gitignore b/.gitignore index 97481fc..a9604bd 100644 --- a/.gitignore +++ b/.gitignore @@ -10,10 +10,6 @@ sessions/ -# configurações dentro do programa - -state.json - # bytecode python __pycache__/ diff --git a/README.MD b/README.MD index af32124..9ab71e1 100644 --- a/README.MD +++ b/README.MD @@ -9,7 +9,7 @@ maturador de chips é um pequeno programa para "esquentar" contas do whatssap e ## Instalação -Se você é usuário Windows, pode fazer download do instalador x64 ou siga as instruções abaixo para executar o código-fonte da versão de codigo aberto: +Se você é usuário Windows, pode fazer download do instalador x64 ou siga as instruções abaixo para executar o código-fonte da versão de codigo aberto: - Clone o repositório @@ -48,6 +48,7 @@ python main.py - Definir troca de conta após X mensagens - Definir máximo de mensagens - Parar em caso de bloqueio +- Mensagens com ChatGpt - sem limite de instâncias - escolher nome instância - remover instância @@ -63,10 +64,27 @@ python main.py Este é o comando pyinstaller para gerar o executavel do maturador: ```shell -pyinstaller --noconfirm --onedir --windowed --icon "(pwd)/pages/assets/medias/icon.ico" --add-data "(pwd)/pages;pages/" --add-data "(pwd)/scripts;scripts/" --add-data "(pwd)/LICENSE;." --add-data "(pwd)/README.MD;." --add-data "(pwd)/user-agent;." --add-data "(pwd)/requirements.txt;." "(pwd)/main.py" +pyinstaller --noconfirm --onedir --windowed --icon "$(pwd)/pages/assets/medias/icon.ico" --add-data "$(pwd)/pages;pages/" --add-data "$(pwd)/scripts;scripts/" --add-data "$(pwd)/LICENSE;." --add-data "$(pwd)/gpt.py;." --add-data "$(pwd)/README.MD;." --add-data "$(pwd)/user-agent;." --add-data "$(pwd)/requirements.txt;." "$(pwd)/main.py" ``` +### Encontrar o cookie de sessão para API não oficial? + + +- 1 ° acesse o site bing e faça login usando uma conta miscrosoft. após login abra o *developer tools* presionando as teclas **CTRL + SHIFT + I** ou siga os passos na foto abaixo para realizar esta ação: + +![step1](https://i.ibb.co/TTSSXm1/passo-1.png) + + +- 2 ° busque no submenu que fica ao lado de *network*, a opção **Application** e clique sobre ela: + +![step2](https://i.ibb.co/Q8JZpPZ/passo-2.png) + +- 3 ° por ultimo encontre o cookie nomeado de **_U** e copie seu valor: + +![step3](https://i.ibb.co/rdBFNt4/passo-3.png) + + ## Licença diff --git a/accounts.py b/accounts.py index fbf212a..e3d9586 100644 --- a/accounts.py +++ b/accounts.py @@ -12,9 +12,11 @@ from PyQt5.QtWebEngineWidgets import (QWebEngineView, QWebEngineProfile, QWebEnginePage) from PyQt5.QtWebEngineCore import (QWebEngineUrlRequestInterceptor) +from PyQt5.QtWebChannel import QWebChannel from PyQt5.QtGui import (QIcon, QCursor) from PyQt5.QtCore import (QUrl, Qt) +from controller import Controller import shutil import json import os @@ -40,7 +42,6 @@ def javaScriptConsoleMessage(self, level, message, lineNumber, sourceID): except: pass - # interceptar as requisições que vem do WhatsApp web para filtrar # as que são feitas para enviar dados ao maturador, isso é necessário # pois o WhatsApp web bloqueia requisições feitas para domínios @@ -68,10 +69,9 @@ def interceptRequest(self, info): SIGNALS.account_blocked.emit(data) info.block(True) - class MainWindow(QMainWindow): def __init__(self): - self.controller = None + self.controller:Controller = None self._is_open = False super().__init__() self.webs_engine = [] @@ -234,11 +234,10 @@ def load_webviews(self): except FileNotFoundError: # a pasta de sessões ainda não existe return for sessionname in sessions: - webview = QWebEngineView() profile = QWebEngineProfile(f"storage{sessionname}", webview) session_dir = os.getcwd() + f"/sessions/{sessionname}" - + # apaga Service Worker porque está causando problema com a sessão service_Worker_path = os.path.join(session_dir, "Service Worker") @@ -261,7 +260,7 @@ def load_webviews(self): self.webviews.append(webview) webview.page().loadFinished.connect(lambda ok, session_name=sessionname : self.run_script(session_name)) - # injeta script login.js + # injeta script login.js e script do webchannel def run_script(self, session_name:str): for idx, key in enumerate(start=0, iterable=self.buttons.keys()): diff --git a/controller.py b/controller.py index 94f4b01..a850e45 100644 --- a/controller.py +++ b/controller.py @@ -170,4 +170,4 @@ def message_box(self, message, title) -> None: self.dashboard_window, title, message - ) \ No newline at end of file + ) \ No newline at end of file diff --git a/gpt.py b/gpt.py new file mode 100644 index 0000000..f6b35fe --- /dev/null +++ b/gpt.py @@ -0,0 +1,197 @@ +from openai import OpenAI +import random +import g4f +import sys + +sys.stdout = open("MaturadorLogs.txt", "a", encoding="utf-8") +sys.stderr = open("MaturadorLogs.txt", "a", encoding="utf-8") + +TOPICS = [ + "História mundial", + "Ciência", + "Cultura", + "Tecnologia", + "Política", + "Filosofia", + "Arte", + "Literatura", + "Geografia", + "Astronomia", + "Medicina", + "Música", + "Matemática", + "Biologia", + "Economia", + "Psicologia", + "Sociologia", + "Antropologia", + "Arqueologia", + "Educação", + "Religião", + "Esportes", + "Meio ambiente", + "Direito", + "Engenharia", + "Alimentação e nutrição", + "Moda", + "Cinema", + "Teatro", + "Fotografia", + "Dança", + "Agricultura", + "Energias renováveis", + "Jogos", + "Design", + "Saúde pública", + "Marketing", + "Administração", + "Linguística", + "Química", + "Física", + "Robótica", + "Inteligência artificial", + "Guerras mundiais", + "Revoluções", + "Movimentos sociais", + "Grandes descobrimentos", + "Colonização", + "Imperialismo", + "Revolução industrial", + "Revolução tecnológica", + "Guerra fria", + "Globalização", + "Mudanças climáticas", + "Exploração espacial", + "Avanços médicos", + "Invenções", + "Descobertas científicas", + "Grandes artistas", + "Grandes escritores", + "Grandes cientistas", + "Grandes filósofos", + "Grandes músicos", + "Grandes líderes políticos", + "Grandes inventores", + "Grandes exploradores", + "Grandes batalhas", + "Grandes catástrofes naturais", + "Grandes epidemias", + "Geopolítica", + "Inteligência emocional", + "Desenvolvimento sustentável", + "Economia comportamental", + "Criptomoedas", + "Inteligência de mercado", + "Tendências de consumo", + "Inovação tecnológica", + "Cibersegurança", + "Privacidade de dados", + "Bioética", + "Direitos humanos", + "Neurociência", + "Interação humano-computador", + "Robótica assistencial", + "Realidade virtual", + "Realidade aumentada", + "Nanotecnologia", + "Internet das coisas", + "Machine learning", + "Aprendizado profundo", + "Redes neurais", + "Computação quântica", + "Impressão 3D", + "Biotecnologia", + "Genética", + "Clonagem", + "Transplantes de órgãos", + "Neurotecnologia" + +] + +class GptGenerateMessage(): + def __init__(self) -> None: + g4f.check_version = False + self._last_message = None + self._last_question = None + self.client:OpenAI = None + + + def generate_question_by_unnoficial(self) -> str: + response = g4f.ChatCompletion.create( + model=g4f.models.gpt_4_turbo, + provider=g4f.Provider.Bing, + messages=[{"role": "user", "content": random.choice(["conte uma curiosidade sobre " + random.choice(TOPICS) , "me faça uma pergunta sobre " + random.choice(TOPICS)]) }], + stream=False) + return response + + def generate_response_by_unnoficial(self, question:str) -> str: + response = g4f.ChatCompletion.create( + model=g4f.models.gpt_4_turbo, + provider=g4f.Provider.Bing, + messages=[{"role": "user", "content": "uma pergunta para você: " + question}], + stream=False + + ) + return response + + def by_unnoficial(self) -> str|tuple[bool, str]: + try: + if random.choice([True, True, False]) and self._last_message: + self._last_message = self.generate_response_by_unnoficial(question=self._last_message) + return self._last_message + + self._last_message = self.generate_question_by_unnoficial() + return self.parser_message(self._last_message) + + except Exception as response_by_unnoficial_error: + return (False, str(response_by_unnoficial_error)) + + def generate_question_by_official(self) -> str: + response = self.client.chat.completions.create( + messages=[{"role": "user", "content": random.choice(["conte uma curiosidade sobre " + random.choice(TOPICS) , "me faça uma pergunta sobre " + random.choice(TOPICS)]),}], + model="gpt-3.5-turbo", + ) + return response + + def generate_response_by_official(self, question:str) -> str: + response = self.client.chat.completions.create( + messages=[{"role": "user","content": "uma pergunta para você: " + question,}], + model="gpt-3.5-turbo", + ) + return response.strip() + + def by_official(self) -> str|tuple[bool, str]: + try: + if random.choice([True, True, False]) and self._last_message: + self._last_message = self.generate_response_by_official(question=self._last_message) + return self._last_message + + self._last_message = self.generate_question_by_official() + return self.parser_message(self._last_message) + + except Exception as response_by_official_error: + return (False, str(response_by_official_error)) + + def set_bing_cookie(self, cookie:str) -> None: + g4f.set_cookies(".bing.com", {"_U": cookie}) + + + def ininialize_openai_client(self, token:str) -> None: + self.client = OpenAI(api_key=token) + + @staticmethod + def parser_message(text:str): + parsed_message = "" + for _ in text.split(): + parsed_message += " " + _.replace("**", "*") + return parsed_message \ + .replace("**Pergunta aleatória:**", "") \ + .replace("**Curiosidade Aleatória: ", "") \ + .replace("Olá, este é o Copilot. Eu sou um assistente de inteligência artificial que pode conversar com você sobre vários tópicos e criar conteúdo interessante.", "") \ + .replace( "Olá, este é o Copilot. Eu sou um assistente de inteligência artificial que pode conversar com você sobre vários tópicos e ajudá-lo com algumas tarefas.", "") \ + .replace( "Olá, Eu sou o Copilot.", "") \ + .replace("**Pergunta aleatória:**", "") \ + .replace("**Pergunta aleatória:**", "") \ + .replace("**Curiosidade Aleatória: ", "") \ + .replace("**Curiosidade Aleatória:**", "") \ + .replace( "Olá, este é o Copilot.", "") \ No newline at end of file diff --git a/main.py b/main.py index a91b1a1..796e5d6 100644 --- a/main.py +++ b/main.py @@ -26,6 +26,7 @@ class SignalReceive(QtCore.QObject): start_maturation = QtCore.pyqtSignal(dict, dict) # exibir um Qmessagebox message_box = QtCore.pyqtSignal(str, str) + # iniciar maturação wapp:WhatsApp = None @@ -37,7 +38,7 @@ def start_maturation(window, messages_file, phones,signals): # iniciar a aplicação -VERSION = "16.12.2023" +VERSION = "24.02.2024" if __name__ == "__main__": @@ -49,10 +50,10 @@ def start_maturation(window, messages_file, phones,signals): window = dashboard.MainWindow(accounts_page, signals, app, controller_instance) accounts_page.controller = controller_instance controller_instance.dashboard_window = window - + # conectar os sinais de pyqtsignal - signals.new_phone_number.connect(lambda account_data:( controller_instance.account_added(account_data) == window.webview.reload() if "/dashboard" in window.webview.url().toString() else None) if account_data else window.webview.reload()) + signals.new_phone_number.connect(lambda account_data: [controller_instance.account_added(account_data), window.webview.reload()] if account_data else window.webview.reload()) signals.start_maturation.connect(lambda messages_file, phones: start_maturation(window=window, messages_file=messages_file, phones=phones,signals=signals)) signals.stop_maturation.connect(lambda: threading.Thread(target=wapp.stop() if wapp else None, daemon=True).start()) signals.account_blocked.connect(lambda account_data: ( controller_instance.account_blocked(account_data) == wapp.set_account_block(phone=account_data["phone"]) )) diff --git a/pages/assets/css/dashboard.css b/pages/assets/css/dashboard.css index a7716a7..2afc89e 100644 --- a/pages/assets/css/dashboard.css +++ b/pages/assets/css/dashboard.css @@ -176,13 +176,11 @@ align-items: center; justify-content: center; } -.home-icon6 { - width: 24px; - height: 24px; -} + .home-link { transition: 0.3s; text-decoration: none; + bottom: 30px !important; } .home-link:hover { color: #000000; @@ -190,6 +188,7 @@ .home-link1 { transition: 0.3s; text-decoration: none; + bottom: 30px !important; } .home-link1:hover { color: #000000; @@ -559,7 +558,7 @@ border-color: #ffffff; border-style: hidden; padding-bottom: 1px; - background-color: #f9f9f9; + /* background-color: #f9f9f9; */ } .home-container08 { right: 0px; @@ -569,14 +568,7 @@ position: absolute; background-color: var(--dl-color-gray-500); } - .home-text31 { - top: 7px; - left: -178px; - color: #000000; - position: absolute; - font-size: 14px; - font-family: Arial; - } + .home-icon6 { fill: #D9D9D9; } @@ -659,4 +651,53 @@ a { cursor: pointer; +} + +#messagesmethod { + width: 100% ; + text-align: center; +} + +#messagesmethod > option { + font-size: 14px !important; + font-family: Arial, Helvetica, sans-serif !important; +} + +#GptKeyContext { + font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; + margin-top: 40px !important; + text-align: center; + position: absolute; + color: #15441f; + width: 100%; +} + +#GptKeyUnofficialContext { + font-family: Impact, Haettenschweiler, 'Arial Narrow Bold', sans-serif; + margin-top: 40px !important; + text-align: center; + position: absolute; + color: #1d383f; + width: 100%; +} + +.home-text31 { + background-color: white; + margin-top: 40px !important; + position: absolute; + text-align: center; + color: #000000; + width: 100%; +} + +.home-icon6 { + width: 24px; + height: 24px; + margin-top: 38px; + visibility: hidden; +} + +#fileInputLabel{ + width: 90%; + height: 22px; } \ No newline at end of file diff --git a/pages/assets/js/dashboard.js b/pages/assets/js/dashboard.js index 8289f6c..e436d49 100644 --- a/pages/assets/js/dashboard.js +++ b/pages/assets/js/dashboard.js @@ -4,11 +4,14 @@ const fileInputLabel = document.getElementById('fileInputLabel'); function update_user_config() { const ContinueOnBlock = document.querySelector("#ContinueOnBlock").checked ; + const ChangeAccountEveryMessages = document.querySelector("#ChangeAccountEveryMessages").value; + const messageInputMethod = document.querySelector("#messagesmethod").selectedOptions[0].value const ShutdownAfterCompletion = document.querySelector("#ShutdownAfterCompletion").checked ; const MinimumMessageInterval = document.querySelector("#MinimumMessageInterval").value; const MaximumMessageInterval = document.querySelector("#MaximumMessageInterval").value; - const ChangeAccountEveryMessages = document.querySelector("#ChangeAccountEveryMessages").value; const stopAfterMessages = document.querySelector("#stopAfterMessages").value; + const openAIToken = document.querySelector("#GptKeyContext").value + const AIUnofficialToken = document.querySelector("#GptKeyUnofficialContext").value const notValidValues = ['', '0' , 0]; // antes de enviar validar as informações @@ -23,6 +26,7 @@ function update_user_config() { || Number(ChangeAccountEveryMessages) < 0 || Number(stopAfterMessages) < 0 || Number(MaximumMessageInterval) <= Number(MinimumMessageInterval) + || notValidValues.includes(messageInputMethod) ) { $.notify("verifique os dados informados", "error"); @@ -38,7 +42,11 @@ function update_user_config() { "MaximumMessageInterval": MaximumMessageInterval, "ChangeAccountEveryMessages": ChangeAccountEveryMessages, "StopAfterMessages": stopAfterMessages, - "ShutdownAfterCompletion": ShutdownAfterCompletion + "ShutdownAfterCompletion": ShutdownAfterCompletion, + "messageInputMethod": messageInputMethod, + "AIUnofficialToken": AIUnofficialToken, + "openAIToken": openAIToken + }; controller.update_user_configs(JSON.stringify(dadosAtualizados)).then(response => { @@ -53,8 +61,9 @@ function update_user_config() { document.querySelector("#MinimumMessageInterval").addEventListener("change", update_user_config); document.querySelector("#MaximumMessageInterval").addEventListener("change", update_user_config); document.querySelector("#ChangeAccountEveryMessages").addEventListener("change", update_user_config); - document.querySelector("#stopAfterMessages").addEventListener("change", update_user_config); - + document.querySelector("#stopAfterMessages").addEventListener("change", update_user_config); + document.querySelector("#GptKeyContext").addEventListener("change", update_user_config); + document.querySelector("#GptKeyUnofficialContext").addEventListener("change", update_user_config); // abrir repositório do projeto @@ -104,17 +113,41 @@ document.querySelector(".start-maturador").addEventListener("click", () =>{ controller.start_maturation(); }) + // selecionar o método de entrada para mensagens + + document.querySelector("#messagesmethod").addEventListener("change", (select) => { + + if (select.target.selectedOptions[0].value === "byFile") { + document.querySelector("#GptKeyUnofficialContext").hidden = true; + document.querySelector(".home-icon6").style.visibility = "visible" + document.querySelector("#GptKeyContext").hidden = true; + fileInputLabel.hidden = false; + + } else if (select.target.selectedOptions[0].value === "byOpenAI") { + document.querySelector("#GptKeyUnofficialContext").hidden = true; + document.querySelector(".home-icon6").style.visibility = "hidden" + document.querySelector("#GptKeyContext").hidden = false; + fileInputLabel.hidden = true; + } + + else { + document.querySelector(".home-icon6").style.visibility = "hidden" + document.querySelector("#GptKeyUnofficialContext").hidden = false; + document.querySelector("#GptKeyContext").hidden = true; + fileInputLabel.hidden = true; + } + + }) + // selecionar o arquivo de mensagens - document.querySelector("#files").addEventListener("click", () => { - controller.select_file().then(response => - { + document.querySelector("#fileInputLabel").addEventListener("click", () => { + + controller.select_file().then(response => { response = JSON.parse(response) $.notify(response.message, { className: response.ok ? "success" : "error"}); document.querySelector("#fileInputLabel").textContent = response["filename"] } ) - - }) @@ -128,6 +161,10 @@ document.querySelector(".start-maturador").addEventListener("click", () =>{ document.querySelector("#stopAfterMessages").value = configs["StopAfterMessages"] document.querySelector("#MinimumMessageInterval").value = configs["MinimumMessageInterval"] document.querySelector("#MaximumMessageInterval").value = configs["MaximumMessageInterval"] + document.querySelector("#messagesmethod").selectedIndex = ["byFile", "byOpenAI", "byOpenAIUnofficial"].indexOf( configs["messageInputMethod"] ) + document.querySelector("#GptKeyUnofficialContext").value = configs["AIUnofficialToken"] + document.querySelector("#GptKeyContext").value = configs["openAIToken"] + document.querySelector("#messagesmethod").dispatchEvent(new Event("change")); fileInputLabel.textContent = configs["filename"] const accounts_container = document.querySelector(".home-container02") @@ -149,4 +186,11 @@ document.querySelector(".start-maturador").addEventListener("click", () =>{ }) -}) \ No newline at end of file +}) + +setTimeout(() => { + + document.querySelector("#messagesmethod").addEventListener("change", update_user_config); + + +}, 1000 * 1) diff --git a/pages/dashboard.html b/pages/dashboard.html index 3e243d7..00ea4bd 100644 --- a/pages/dashboard.html +++ b/pages/dashboard.html @@ -66,7 +66,7 @@