def run(): print("Environment", os.environ) driver = WhatsAPIDriver(username="******") print("Waiting for QR") driver.wait_for_login() print("Bot started") driver.subscribe_new_messages(NewMessageObserver()) print("Waiting for new messages...") """ Locks the main thread while the subscription in running """ while True: time.sleep(60)
# encoding=utf8 import os, sys, time, json, datetime from orator import DatabaseManager, Model from webwhatsapi import WhatsAPIDriver from time import sleep profiledir=os.path.join(".","firefox_cache") pic_path=os.path.join(".","marketing.jpeg") wppDriver = WhatsAPIDriver(username="******", profile=profiledir) print("Waiting for QR") wppDriver.wait_for_login() print("Bot started") wppDriver.save_firefox_profile() config = { 'postgres': { 'driver': 'postgres', 'host': '35.247.235.153', 'database': 'tbc_wpp', 'user': '******', 'password': '******', } } db = DatabaseManager(config) Model.set_connection_resolver(db)
img_w, img_h = img.size offset = ((bg_w - img_w) // 2, (bg_h - img_h) // 2) background.paste(img, offset, img) background.save('goodqr.png', "PNG") imgur = pyimgur.Imgur(CLIENT_ID) uploaded_image = imgur.upload_image(PATH, title="WhatsApp QR Code") print("QR code has been uploaded to:\n" + str(uploaded_image.link) + "\nPlease scan the QR code to login.") else: pass z = 0 a = 0 try: while z == 0: try: driver.wait_for_login(timeout=5) except CannotSendRequest: z = 0 continue else: z = 1 except TimeoutException: try: while a == 0: try: print("Awaiting login... YOU HAVE 90 SECONDS TO DO SO.") driver.wait_for_login(timeout=90) except CannotSendRequest: a = 0 continue except TimeoutException:
import time from webwhatsapi import WhatsAPIDriver from webwhatsapi.objects.message import Message driver = WhatsAPIDriver(username='******', client='C:\\Users\\raosa\\Desktop\\PROJECTS\\chromedriver.exe') print("Waiting for QR") driver.wait_for_login() print("Bot started") while True: time.sleep(3) print('Checking for more messages') for contact in driver.get_unread(): for message in contact.messages: if isinstance(message, Message): # Currently works for text messages only. contact.chat.send_message(message.safe_content)
def checknumber(phoneNumberStr): # if (driver.check_number_status(phoneNumberStr + '@c.us').status == 200): if (driver.check_number_status(phoneNumberStr).status == 200): return True else: return False def createListOfNumbers(number): rs = number + " " + str(checknumber(number)) + "\n" file.write(rs) driver = WhatsAPIDriver() print("Waiting for QR") driver.wait_for_login() print("Bot started") number_array = [] for i in range(5410010, 5410020): number_array.append("97252" + str(i) + '@c.us') print(number_array) threads = [] counter = 0 while counter < len(number_array): if threading.active_count() > MAX_THREAD: time.sleep(0.1) else:
class WhatsappBot: def __init__(self, auto_run=False, auto_long_run=False, headless=False): self._chromedriver = os.environ.get( 'CHROMEDRIVE_PATH', os.path.join(os.path.dirname(__file__), "chromedriver")) self._profile_path = os.path.join(os.path.dirname(__file__), "chromeprofile") self._headless = headless self._driver = WhatsAPIDriver( username="******", client="chrome", profile=self._profile_path, executable_path=self._chromedriver, headless=self._headless, chrome_options=[ "user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36", ], heroku=self._headless) self._bot_actions = BotActions(self._driver) self._thread_pool = ThreadPoolExecutor(max_workers=2) self._threaded_users = [] if auto_long_run: self.keep_running() elif auto_run: self.run() def run(self) -> None: """ • Check if there's some user with status == 6 (if yes, generate sticker pack) • Listen to new messages Here we can either keep listening to new messages (long_run == True) or check just once. """ # Check for new messages self.check_for_unread_messages() # Check for users waiting the pack user_in_last_stage = User.find_users_in_last_stage() for user in user_in_last_stage: if user[0] not in self._threaded_users: self._thread_pool.submit(self.create_sticker_pack, user) self._threaded_users.append(user[0]) logging.info(f"{user[0]} added to queue.") else: logging.info(f"{user[0]} already in queue.") def keep_running(self) -> None: """ Keeps running with self.run() :return: """ while True: if not self._driver.is_logged_in(): self._driver.screenshot('scrsht.png') self._driver.wait_for_login() try: self.run() sleep(2) except TypeError as err: logging.critical(err) logging.critical("---RESTARTING---") def create_sticker_pack(self, user_info: tuple) -> bool: """Create a sticker pack using StickerSet class.""" wa_chat_id = user_info[0] package_title = user_info[1] tg_chat_id = user_info[2] logging.info(f"Running for {wa_chat_id}") # Get stickers messages stickers = self.list_user_unread_stickers(wa_chat_id) # Create sticker set sticker_set = StickerSet(tg_chat_id) name = sticker_set.create_new_sticker_set( package_title, stickers[0].save_media_buffer(True)) if not name: logging.error(f"Can't create {wa_chat_id} pack: name = {name}") return False # Populate sticker set for sticker in stickers[1:]: stts = sticker_set.add_sticker_to_set( tg_chat_id, name, sticker.save_media_buffer(True)) logging.info(f"Added a sticker to {name}: {stts}") # Send confirmation self._bot_actions.confirmation(wa_chat_id, name) logging.info(f"Finished {wa_chat_id}") # Remove user from threading if wa_chat_id in self._threaded_users: self._threaded_users.remove(wa_chat_id) return True def check_for_unread_messages(self) -> None: """ Check for unread messages and call actions :return: """ unread = self._driver.get_unread() for msg_group in unread: print(f'Message from <{msg_group.chat.id}>.') for message in msg_group.messages: self.process_incoming_message(message) def process_incoming_message(self, message: Message) -> None: # Message properties: https://gist.github.com/hellmrf/6e06fc374bb43de0868fbb57c223aecd if message.type == 'chat': print( f"[{message.chat_id} {message.timestamp}]: {message.content}") user_is_threaded = message.chat_id in self._threaded_users self.treat_message(message.chat_id, message.content, queued=user_is_threaded) elif User.get_stage(message.chat_id) == 0: self.treat_message(message.chat_id, "Hello") def list_user_unread_stickers(self, chat_id: str) -> List[Message]: messages: List[Message] = self._driver.get_all_messages_in_chat( chat_id) stickers = [ message for message in messages if message.type == 'sticker' ] return stickers @staticmethod def upload_sticker_from_message(tg_user_id: int, sticker_message: Message) -> str: sticker = sticker_message.save_media_buffer(True) return StickerSet.upload_sticker(tg_user_id, sticker) def treat_message(self, chat_id: str, message: str, queued=False) -> bool: return self._bot_actions.answer(chat_id, message, queued=queued) @staticmethod def convert_sticker_to_png_base64(sticker: BytesIO) -> str: """ Converts a sticker file (webp) to base64 string (png) :param sticker: the sticker to be converted :return: the base64 string """ file = BytesIO() img = Image.open(sticker) img.save(file, 'png') base64_content = base64.b64encode(file.getvalue()).decode() base64_string = 'data:image/png;base64,' + base64_content return base64_string # TODO: remove that @staticmethod def temp_save_to_txt(base64_string: str, suffix="") -> None: with open( f"/home/helitonmrf/Projects/WhatsGram_Stickers/test/sticker{suffix}.html", 'w') as fl: fl.write(f"<img src='{base64_string}' />")
from orator import DatabaseManager, Model from webwhatsapi import WhatsAPIDriver wppDriver = WhatsAPIDriver(username="******") print("Waiting for QR") wppDriver.wait_for_login() print("Bot started") config = { 'postgres': { 'driver': 'postgres', 'host': '35.247.235.153', 'database': 'tbc_wpp', 'user': '******', 'password': '******', } } db = DatabaseManager(config) Model.set_connection_resolver(db) class Driver(Model): __table__ = 'drivers' pass drivers = Driver.all() print("Buscando motoristas...")
class WPChannelBot(): def __init__(self): self.model = WPChannelBotModel() self.data = self.model.get_all() self.convs = self.model.get_convs() self.convs_state = self.model.get_convs_state() self.simple_steps = True self.log_file = "log/chatbot.log" self.cmd_wait_from = None self.cmd_wait = False self.profile = "profile" self.driver = None def start(self): print("Iniciando bot...") self.driver = WhatsAPIDriver(profile=self.profile) time.sleep(3) if not self.driver.get_status() == "LoggedIn": print("Carregando QRCode") self.driver.get_qr("qrcode.png") print("Escaneie o QRCode no arquivo qrcode.png") self.driver.wait_for_login() print("Bot iniciado") self.driver.save_firefox_profile() while True: time.sleep(1) for contact in self.driver.get_unread(include_me=False, include_notifications=True, use_unread_count=True): if len(contact.messages) == 1: for message in contact.messages: if isinstance(message, Message): self.new_message(message.content, contact) self.driver.chat_send_seen(contact.chat.id) time.sleep(3) else: contact.chat.send_message( "Fico confuso com muitas mensagens :S Por favor, envie uma de cada vez e espere eu responder tá?" ) contact.chat.send_message(CHANNEL_ASK_KEYWORD) def new_message(self, message, contact): if not self._is_cmd(message): if self.cmd_wait and contact.chat.id == self.cmd_wait_from: self._cmd_envio(message, contact.chat) elif not contact.chat.id in self.convs: self._proc_etapa(contact.chat.id, message, contact.chat, 2) else: for conv in self.convs_state: if conv['id'] == contact.chat.id: e = self._proc_etapa(contact.chat.id, message, contact.chat, conv['etapa']) conv['etapa'] = e self.model.conv_update(contact.chat.id, e) else: print("ADMINISTRADOR") self._run_cmd(message, contact.chat) def shutdown(self): print("Desconectando...") self.driver.close() time.sleep(3) print("Desconectado") def _already_user(self, id, chat): if isinstance(self.model.get(id), dict): chat.send_message( "Olá, você já está cadastrado neste canal. Assim que tiver novidade você vai receber!" ) return True else: return False def _is_keyword(self, content, chat): if content.lower() == CHANNEL_KEYWORD: return True else: chat.send_message(CHANNEL_ASK_KEYWORD) return False def _proc_etapa(self, id, content, chat, etapa): if etapa == 2: if not self._already_user(id, chat) and self._is_keyword( content, chat): # Efetua registros self.convs.append(id) self.convs_state.append({"id": id, "etapa": 4}) self.model.conv_add(id, 4) # Introdução do canal - Solicita nome chat.send_message(CHANNEL_INTRO) chat.send_message(CHANNEL_MSGS[0]) self._to_log("Iniciando cadastro: %s" % id) elif etapa == 4: # Armazena nome - Solicita cidade if self.simple_steps: self.data.append({"id": id, "nome": content}) # Salva no banco de dados self.model.add(id, content) chat.send_message((CHANNEL_MSGS[3] % content)) self._remove_convs(id) self._to_log("Finalizado cadastro: %s - %s" % (id, content)) else: self.data.append({ "id": id, "nome": content, "cidade": "", "bairro": "" }) chat.send_message(CHANNEL_MSGS[1]) # Salva no banco de dados self.model.add(id, content) self._to_log("Registrado nome: %s - %s" % (id, content)) return 6 elif etapa == 6: # Implementar veficação de validade de cidade # Verifica cidade - volta ao 5 : armazena cidade - solicita bairro ou passo for obj in self.data: if obj["id"] == id: obj["cidade"] = content self.model.update(id=id, cidade=content) chat.send_message(CHANNEL_MSGS[2]) self._to_log("Registrado cidade: %s - %s" % (id, content)) return 7 elif etapa == 7: # Implementar veficação de validade de bairro if content == "passo": # Finaliza caso não seja informado bairro chat.send_message((CHANNEL_MSGS[3] % self._get_conv_nome(id))) self._remove_convs(id) self._to_log("Finalizado cadastro: %s - %s" % (id, content)) else: # Armazena bairro - Finaliza cadastro for obj in self.data: if obj["id"] == id: obj["bairro"] = content self.model.update(id=id, bairro=content) chat.send_message( (CHANNEL_MSGS[3] % self._get_conv_nome(id))) self._remove_convs(id) self._to_log("Finalizado cadastro: %s - %s" % (id, content)) def _to_log(self, log): file = open(self.log_file, "a") file.write("\n>> %s " % log) file.close() return def _get_conv_nome(self, id): for obj in self.data: if obj["id"] == id: return obj["nome"] def _remove_convs(self, id): self.convs.remove(id) for conv in self.convs_state: if conv["id"] == id: self.convs_state.remove(conv) self.model.conv_delete(id) def _is_cmd(self, content): if content[:4] == "/cmd": return True else: return False def _run_cmd(self, content, chat): cmd = content[5:] if not self.model.check_admin(chat.id) == False: if cmd == "usuarios": self._cmd_usuarios(chat) elif cmd == "envio": self.cmd_wait = True self.cmd_wait_from = chat.id chat.send_message( "*ENVIE A SEGUIR A MENSAGEM A SER ENVIADA PARA O CANAL*") else: chat.send_message("*COMANDO NÃO RECONHECIDO*") elif self.model.check_admin(id=None, all=True) == False and cmd[:5] == "admin": print("Cadastrando novo admin") self.model.add_admin(chat.id, content[11:]) chat.send_message("*ADMINISTRADOR CADASTRADO*") else: chat.send_message(CHANNEL_ASK_KEYWORD) def _cmd_usuarios(self, chat): response = "*USUÁRIOS CADASTRADOS*\n\n" i = 0 users = self.model.get_all() for user in users: i += 1 response += "\n%d) %s - %s" % (i, user['id'], user['nome']) chat.send_message(response) def _cmd_envio(self, content, chat): i = 0 users = self.model.get_all() for user in users: i += 1 self.driver.send_message_to_id(user['id'], content) self.cmd_wait_from = None self.cmd_wait = False chat.send_message("*MENSAGEM ENVIADA PARA %d USUÁRIOS DO CANAL*" % i)
def run(self, profile_path="/data/firefox_cache"): profile_path = self.profile """ Faz a coleta das mensagens de grupos de Whatsapp de acordo com os parâmetros fornecidos na criação do objeto de coleta. Parâmetros ------------ profile_path : str Caminho para um profile alternativo do navegador utilizado na coleta. """ if not os.path.exists(self.data_path): os.makedirs(self.data_path) if not os.path.exists(profile_path): os.makedirs(profile_path) driver = WhatsAPIDriver(loadstyles=True, profile=profile_path, client="remote", command_executor=os.environ["SELENIUM"]) pathlib.Path(self.data_path + "mensagens").mkdir(parents=True, exist_ok=True) pathlib.Path(self.data_path + "image").mkdir(parents=True, exist_ok=True) pathlib.Path(self.data_path + "audio").mkdir(parents=True, exist_ok=True) pathlib.Path(self.data_path + "video").mkdir(parents=True, exist_ok=True) pathlib.Path(self.data_path + "mensagens_grupo").mkdir(parents=True, exist_ok=True) pathlib.Path(self.data_path + "notificacoes").mkdir(parents=True, exist_ok=True) pathlib.Path(self.data_path + "all_notificacoes").mkdir(parents=True, exist_ok=True) pathlib.Path("/data/mids").mkdir(parents=True, exist_ok=True) min_date = self.start_date max_date = self.end_date include_notf = self.collect_notifications looping = True if (self.collection_mode == 'period') and (min_date < '2020-01-01'): raise Exception("Can't start collection without a start and end" " date.") check_group_w = False check_group_b = False if len(self.group_whitelist) > 0: check_group_w = True if len(self.group_blacklist) > 0: check_group_b = True while looping: if self.collection_mode == 'continuous': looping = True else: looping = False try: print("Waiting for WhatsApp Web Login") driver.wait_for_login() print("Saving session") driver.save_firefox_profile(remove_old=False) print("Bot started") print('>>>>>>>>>>> Loading previous saved Messages') messagesID = self._get_load_messages() notificationsID = self._get_load_notifications() today_date = datetime.date.today().strftime("%Y-%m-%d") date_format = "%Y-%m-%d" file_name = self.data_path + "mensagens/mensagens_" + today_date + ".json" start_date = min_date print('>>>>>>>>>>>>Getting Groups Messages...', end=' ') chats = driver.get_all_chats() count = 0 all_chats = list(chats) print(' DONE! %d chats loaded!' % (len(all_chats))) random.shuffle(all_chats) for chat in (all_chats): # Does not collect direct messages, only group chats if not chat._js_obj['isGroup']: continue gid = chat.id gid = gid.split('@')[0] s_name = self._process_string(chat.name) if check_group_w and (gid not in self.group_whitelist): if check_group_w and (s_name not in self.group_whitelist): continue if check_group_b and (gid in self.group_blacklist or s_name in self.group_blacklist): print( 'Group', gid, str(s_name), 'in blacklist and will not be collected! Next group' ) continue # Skip group if it is on blacklist (can be name or groupID) if (s_name in self.group_blacklist or gid in self.group_blacklist): continue # PRINT CHAT INFORMATION members = chat._js_obj['groupMetadata']['participants'] timestamp = gid.split('-')[-1] date = convert_data_from_timestamp(float(timestamp)) str_date = date.strftime('%Y-%m-%d %H:%M:%S') chat_print = "<Group chat - {name}: {id}, {participants} " \ "participants - at {time}!!>".format( name=s_name, id=gid, participants=len(members), time=str_date) print('>>>>>Loading messages from', chat_print) if gid not in messagesID: messagesID[gid] = dict() messagesID[gid]['messages'] = set() messagesID[gid]['date'] = '2000-01-01' # PROCESS PREVIOUS LOADED MESSAGES ID AND LAST DATE if self.collection_mode == 'continuous': if messagesID[gid]['date'] > max_date: continue if messagesID[gid]['date'] > min_date: start_date = messagesID[gid]['date'] till_date = datetime.datetime.strptime( start_date, date_format) else: start_date = min_date till_date = datetime.datetime.strptime( start_date, date_format) # LOAD MESSAGES FROM WHATSAPP SINCE MIN_DATE messages = chat.load_earlier_messages_till(till_date) messages = driver.get_all_message_ids_in_chat( chat, include_notifications=include_notf) elif self.collection_mode == 'period': till_date = datetime.datetime.strptime( start_date, date_format) # LOAD MESSAGES FROM WHATSAPP SINCE MIN_DATE messages = chat.load_earlier_messages_till(till_date) messages = driver.get_all_message_ids_in_chat( chat, include_notifications=include_notf) elif self.collection_mode == 'unread': # LOAD UNREAD MESSAGES FROM WHATSAPP messages = chat.get_unread_messages( include_me=False, include_notifications=include_notf) print('>>>>>Total messages %d' % (len(messages))) count += 1 for msg in messages: count += 1 gid = gid.split('@')[0] mid = msg if self._is_notification(mid): if gid not in notificationsID.keys(): notificationsID[gid] = set() if mid.strip() in notificationsID[gid]: continue j = driver.get_message_by_id(mid) self._save_notification_(j, gid) continue if mid.strip() in messagesID[gid]['messages']: print('Message: %d >>> %s from %s was CHECKED' % (count, mid, gid)) continue else: try: j = driver.get_message_by_id(mid) except Exception as e: print('Error getting a message >>', e) continue if not j: continue if not self.check_user(j): continue try: date = self._get_date_from_message(j) except Exception: continue if (date > max_date) and (self.collection_mode == 'period'): break if (date < start_date): continue # Update day if today_date != date: today_date = date file_name = self.data_path + "mensagens/mensagens_" + today_date + ".json" if self.collect_images: try: self._get_image_from_message( j, self.data_path + "image") except Exception as ei: print('!!!!Error getting image!!!! ', ei) if self.collect_videos: try: self._get_video_from_message( j, self.data_path + "video") except Exception as ev: print('!!!!Error getting video!!!! ', ev) if self.collect_audios: try: self._get_audio_from_message( j, self.data_path + "audio") except Exception as ea: print('!!!!Error getting audio!!!! ', ea) if self.collect_messages: self._save_message(j, s_name, gid, mid, file_name) driver.close() except Exception as e: print(e) driver.close() raise Exception(e) if looping: print('Waiting code to start again...') time.sleep(3600)