def webCrawler(): #os.system('export PATH=$PATH:/path/t-/geckodriver') driver_executable_path="./geckodriver" driver = WhatsAPIDriver( driver_executable_path="./geckodriver") #driver.firstrun() print("Waiting for QR") driver.wait_for_login() print("Bot started") files = {} caminho = "./" path = './' today_date = "" file_name = "" while True: time.sleep(3) file_name = "AllMessages_" + today_date[-2:] + ".txt" file_t = open(caminho + file_name, 'a', 0) time.sleep(3) #try: msg_list = driver.get_unread(include_me=False, include_notifications=False, use_unread_count=False) if len(msg_list) == 0: continue for i in msg_list: if len(i.messages)>0: print >> file_t, i.chat for j in i.messages: date = get_date_from_message(j) if today_date != date: #update day today_date = date file_t.close() file_name = "AllMessages_" + today_date[-2:] + ".txt" file_t = open(caminho + file_name, 'a', 0) get_text_from_message(j, file_t) get_image_from_message(j) get_video_from_message(j) get_audio_from_message(j) #except Exception, err: # sys.stderr.write('ERROR: %sn' % str(err)) # if 'Message: Tried to run command without establishing a connection' in str(err): # webCrawler() file_t.close()
class WhatsAppAgent(object): def __init__(self): self.driver = WhatsAPIDriver(client=WhatsAppAgentConstants.BROWSER) logger.info("Waiting for successful QR Code scan...") self.driver.wait_for_login() logger.info("Logged in!") def get_all_chats(self): return self.driver.get_all_chats() def get_all_msgs_in_chat(self, chat=None): if chat is None: return [] return self.driver.get_all_messages_in_chat(chat) def get_msg_text(self, message=None): if message is None: return "" return message.safe_content def get_unread_msgs(self): for contact in self.driver.get_unread(): for message in contact.messages: if isinstance(message, Message): whatsAppMsg = WhatsAppAgentMessage( chatId=contact.chat.id, chatName=contact.chat.name, senderId="", senderName=message.sender.get_safe_name(), msgType="", msgData=message.safe_content, msgTime=message.timestamp) logger.debug("New message: %s", whatsAppMsg.readable_format()) def run(self): while True: time.sleep(WhatsAppAgentConstants.NEW_MSG_POLL) self.get_unread_msgs()
print("Bot started") allowed_chats = [ '*****@*****.**', '*****@*****.**', '*****@*****.**', #superb '*****@*****.**', #отбитые '*****@*****.**', '*****@*****.**', #йети чат '*****@*****.**' ] while True: rand_delay(1, 2) try: for contact in driver.get_unread(): #print ("DEBUG:", dir(contact)) for message in contact.messages: #try: chat_id = message.chat_id['_serialized'] print("DEBUG: got message!") print("DEBUG: chat_id {}!".format(chat_id)) #if chat_id.endswith('c.us') or ( chat_id.endswith('g.us') and chat_id in allowed_chats ): rand_delay(1, 2) process_message(driver, contact, message, chat_id) process_cron_jobs(driver, chat_id) #else: # print ("DEBUG: not allowed chat!") # process_message(driver, contact, message, chat_id, False, False) except Exception as e:
start_time = datetime.now() output_folder = 'output/' + start_time.strftime('%Y-%m-%d') + match_name sleep_time = 60 match_threshold = 80 submission_log = {} player_options = get_player_list() player_tallies = {player: 0 for player in player_options} # Main loop driver = WhatsAPIDriver(loadstyles=True) driver.wait_for_login() try: while True: messages_by_sender = driver.get_unread() print('{} berichten ontvangen. Verwerken...'.format( len(messages_by_sender))) for contact in messages_by_sender: for message in contact.messages: try: best_player_match, match_value = process.extractOne( message.content, player_options) print( 'Message received from: {}. Match value: {}. Text: {}'. format(message.sender.id["user"], match_value, message.content)) except AttributeError: best_player_match = "Player match failed: AtrributeError" match_value = 0 print(
def runReminder(): from webwhatsapi import WhatsAPIDriver print("Environment", os.environ) try: os.environ["SELENIUM"] except KeyError: print("Please set the environment variable SELENIUM to Selenium URL") sys.exit(1) from PIL import Image from resizeimage import resizeimage ##Save session on "/firefox_cache/localStorage.json". ##Create the directory "/firefox_cache", it's on .gitignore ##The "app" directory is internal to docker, it corresponds to the root of the project. ##The profile parameter requires a directory not a file. from pyzbar.pyzbar import decode dir_path = os.path.dirname(os.path.realpath(__file__)) print(")(AFYN)(ANY*FU(A*UKFA(E*FU*****************************)))") print(")(AFYN)(ANY*FU(A*UKFA(E*FU*****************************)))") print(")(AFYN)(ANY*FU(A*UKFA(E*FU*****************************)))") print(")(AFYN)(ANY*FU(A*UKFA(E*FU*****************************))),", dir_path) returned_value = os.system('export PATH="' + dir_path + ':$PATH"') # returns the exit code in unix profiledir = os.path.join(".", "firefox_cache") if not os.path.exists(profiledir): os.makedirs(profiledir) driver = WhatsAPIDriver(profile=profiledir, client="remote", command_executor=os.environ["SELENIUM"]) profiledir = os.path.join(".", "firefox_cache") if not os.path.exists(profiledir): os.makedirs(profiledir) driver = WhatsAPIDriver(profile=profiledir, client="remote", command_executor=os.environ["SELENIUM"]) import timg obj = timg.Renderer() print("Waiting for QR") driver.wait_for_login() print("Saving session") # from qrtools import qrtools # from PIL import Image # import zbarlight # qr = qrtools.QR() # # from PIL import Image # import os # import numpy as np # import pyboof as pb # # pb.init_memmap() #Optional # # class QR_Extractor: # # Src: github.com/lessthanoptimal/PyBoof/blob/master/examples/qrcode_detect.py # def __init__(self): # self.detector = pb.FactoryFiducial(np.uint8).qrcode() # # def extract(self, img_path): # if not os.path.isfile(img_path): # print('File not found:', img_path) # return None # image = pb.load_single_band(img_path, np.uint8) # self.detector.detect(image) # qr_codes = [] # for qr in self.detector.detections: # qr_codes.append({ # 'text': qr.message, # 'points': qr.bounds.convert_tuple() # }) # return qr_codes # qr_scanner = QR_Extractor() print("AAA") c = 0 s = 60 status = "NotLoggedIn" while status is not "LoggedIn": c += 1 print("status", status) # print("Checking qr, status", driver.get_status()) print("AAAAAAAAAAAAA") # img = driver.get_qr("static/img/newQR.png") im_path = os.path.join("newQR.png") pathlib.Path().absolute() os.system("cp newQR.png sample/static/img/newQR.png") img = driver.get_qr("newQR.png") # from PIL import Image print("BBBBBBBBBBBBBBB") decoded = decode(Image.open(im_path)) # print(decoded, "#######################") # print(decoded, "#######################") # print(decoded, "#######################") # print(decoded, "#######################") # print(decoded, "#######################") # print(decoded, "#######################") # print(decoded, "#######################") for barcode in decoded: print("@@@@@@@@@@@@@@@@@@@") # the barcode data is a bytes object so if we want to draw it # on our output image we need to convert it to a string first barcodeData = barcode.data.decode("utf-8") barcodeType = barcode.type # draw the barcode data and barcode type on the image text = "{} ({})".format(barcodeData, barcodeType) print(text) print("@@@@@@@@@@@@@@@@@@@") printQR(barcodeData) print("@@@@@@@@@@@@@@@@@@@X") status = driver.get_status() # output = qr_scanner.extract(img) # print(output,"!!!!!!!!!!!!!!!!WDIOUSICNOIUCJ)(Z*UCINJ)(ZP*DFJYUF)((P*SUD)(UASIDMUJ))") # print(qr.decode(img)) # print(qr.data) # print("BBBB2") # with open(img, 'r+b') as f: # with Image.open(f) as image: # cover = resizeimage.resize_cover(image, [57, 57]) # cover.save(img, image.format) # # # qr.decode(img) # print (qr.data) # print(retval,"!!!!!!!!!!!!!!!!!!!") # # print("CCC",img) # obj.load_image_from_file(img) # obj.resize(s,s) # s-=1 # print(obj) # obj.render(timg.Ansi24HblockMethod) # print("DDD",s,s,s,s) # time.sleep(10) # driver.save_firefox_profile(remove_old=False) # time.sleep(3) # try: # driver.reload_qr() # except: # print("refresh finised") print("Bot started") while True: time.sleep(.71) print("Checking for more messages, status", driver.get_status()) for contact in driver.get_unread(): for message in contact.messages: print(json.dumps(message.get_js_obj(), indent=4)) sender = message.get_js_obj( )["chat"]["contact"]["formattedName"] for contact in driver.get_contacts(): # print("CCCC",contact.get_safe_name() ) if sender in contact.get_safe_name(): chat = contact.get_chat() chat.send_message("Hi " + sender + " !!!*" + message + "*") print() print() print(sender) print() print() print("class", message.__class__.__name__) print("message", message) print("id", message.id) print("type", message.type) print("timestamp", message.timestamp) print("chat_id", message.chat_id) print("sender", message.sender) print("sender.id", message.sender.id) print("sender.safe_name", message.sender.get_safe_name()) if message.type == "chat": print("-- Chat") print("safe_content", message.safe_content) print("content", message.content) # contact.chat.send_message(message.safe_content) elif message.type == "image" or message.type == "video": print("-- Image or Video") print("filename", message.filename) print("size", message.size) print("mime", message.mime) print("caption", message.caption) print("client_url", message.client_url) message.save_media("./") else: print("-- Other")
epoch = 1 print('Making initial update') new_clues = get_clues_from_file(NEW_CHATFILE_NAME) old_clues = get_clues_from_file(OLD_CHATFILE_NAME) older_clues = get_clues_from_file(OLDER_CHATFILE_NAME) all_clues = make_unique(older_clues + old_clues + new_clues) push_clues_to_sheet(all_clues) print('Done') while True: time.sleep(TIME_BETWEEN_UPDATES) flag = False print("Beep " + str(epoch)) unread = driver.get_unread() for message_group in unread: if message_group.chat.id == GROUP_ID: flag = True with open(NEW_CHATFILE_NAME, 'a+') as chat_file: for m in message_group.messages: # Checking and updating sheet print(m) fmt_ts = format_timestamp(str(m.timestamp)) chat_file.write(fmt_ts) chat_file.write(" - ") chat_file.write(str(m.sender.get_safe_name())) chat_file.write(": ") chat_file.write(str(m.content)) chat_file.write("\n")
VALUES(%s, %s, %s, %s, %s, NOW(), %s ) RETURNING id;""" check_if_processed = """SELECT MAX(a.datetime) latest_process_time FROM (SELECT d.status, d.datetime FROM whatsapp.messages m, whatsapp.downloads d WHERE m.id=d.message_id AND m.origin_id=%s) a GROUP BY a.status HAVING status!='skipped' ORDER BY latest_process_time DESC LIMIT 1;""" reloaded_contacts = """SELECT id, sender_msisdn FROM whatsapp.load_earlier_messages WHERE receiver_msisdn=%s AND earlier_messages=True;""" activate_reload = """UPDATE whatsapp.load_earlier_messages SET reload_start=NOW() WHERE id=%s;""" deactivate_reload = """UPDATE whatsapp.load_earlier_messages SET earlier_messages=False, reload_end=NOW(), note=%s WHERE id=%s;""" while True: time.sleep(3) logging.info('Checking for more messages, status, ' + driver.get_status()) # Read unread messages logging.debug("Getting unread messages") for contact in driver.get_unread(use_unread_count=True, fetch_all_as_unread=True): logging.info(contact.chat) sender_msisdn = str(contact.chat.id).split('@')[0] dirName = create_directory(sender_msisdn) logging.info("Messages will be processed for " + sender_msisdn) process_messages(contact.messages, dirName) contact.chat.send_seen() logging.info("Sent seen request") # Define reloaded contacts and process them logging.debug("Getting reload contacts") with db_conn.cursor() as cur: cur.execute(reloaded_contacts, (str(mobile_number), )) reloaded_contacts_set = cur.fetchall() sender_msisdn_list = [i[1] for i in reloaded_contacts_set]
time.sleep(3) # Checks for new messages every 3 secs. pinger = pinger + 1 if (pinger % 600) == 0: # Notification every 30 min. (600 * 3 sec = 1800 sec) pinger = 0 send_message_to_master( "Resetting counter to {pingcount}. Driver status is '{status}'".format( pingcount=pinger, status=driver.get_status() ) ) print( "Checking for more messages, status. Pinger={pingcount}".format( pingcount=pinger ), driver.get_status(), ) for contact in driver.get_unread(include_me=True, include_notifications=True): for message in contact.messages: print(json.dumps(message.get_js_obj(), indent=4)) # Log full JSON to general log f = open("generallog.log", "a+", encoding="utf-8") f.write( "\n\n==========================================================================\nMessage received at {timestamp}\n".format( timestamp=str(datetime.datetime.now()) ) ) try: f.write(json.dumps(message.get_js_obj(), indent=4)) except: f.write("ERROR!! Unprintable JSON!") send_message_to_master("Unprintable JSON! Please check!") f.write("\n")
class Master(object): shares = [] db = { "masters":["972512170493", "972547932000"], "users":{"id":{"services":{"groupID":None}}}, "services":{"Reminders":{"dbID":None,"incomingTarget":None},"Proxy":{"dbID":None,"incomingTarget":None},"Danilator":{"dbID":None,"incomingTarget":None}}, "groups": {"id":"service"}, "id":"*****@*****.**"} services = {} ''' start master driver and log in ''' def __init__(self, profileDir = "/app/session/rprofile2"): Master.shares.append(self) self.db = Master.db # self.services = ServiceLoader.LoadServices(self) self.status = "INIT" self.lastQR = 0 self.driver = None self.masterService = None asyncInit = Thread(target = self.initAsync,args = [profileDir]) asyncInit.start() def initAsync(self, profileDir = "/app/session/rprofile2"): ''' init driver variables ''' if len(Master.shares) > 1: profileDir += "-"+str(len(Master.shares)) chrome_options = webdriver.ChromeOptions() chrome_options.binary_location = os.environ.get("GOOGLE_CHROME_BIN") chrome_options.add_argument("--headless") chrome_options.add_argument("--disable-dev-shm-usage") chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36") chrome_options.add_argument("user-data-dir="+profileDir); chrome_options.add_argument('--profile-directory='+profileDir) if not runLocal: self.driver = WhatsAPIDriver(profile = profileDir, client='chrome', chrome_options=chrome_options,username="******") else: self.driver = WhatsAPIDriver(username="******",profile=None) driver = self.driver ''' RUNNING MASTER SERVICE ''' self.masterService = MasterService(runLocal, self.db, self.services, self.driver, self) print(''' ::: waiting for login ::: ''') driver.wait_for_login() try: self.status = status = driver.get_status() except Exception as e: print(" ::: ERROR - Status Init ::: ","\n",e,e.args,"\n") ''' preping for qr ''' if status is not "LoggedIn": img = None triesCount = 0 maxtries = 40 while status is not "LoggedIn" and triesCount < maxtries: triesCount+=1 print("-------------------------------") print("status:",status,"tries:",triesCount,"/",maxtries) print("-------------------------------") self.lastQR += 1 try: img = driver.get_qr("static/img/QR"+str(self.lastQR)+".png") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ",str(img)[17:130]) except Exception as e: print(" ::: ERROR - QR Fetching ::: ","\n",e,e.args,"\n") # im_path = os.path.join("static/img/newQR.png") print(''' ::: rechecking status ::: ''') try: self.status = status = driver.get_status() except Exception as e : self.status = status = "XXXXXXXX" print(" ::: ERROR - Status Fetching ::: ","\n",e,e.args,"\n") if status is "LoggedIn": print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::: ::::: ''') print(''' :::: MASTER IS LOGGED IN! ::::: ''') print(''' :::: ::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') # if runLocal: # self.driver.save_firefox_profile(remove_old=False) ''' load DB ''' ## overwrite to init db initOverwrite = True if initOverwrite: self.backup(now = True) # driver.updateDB(self.db,number=self.db["id"]) lastDB = self.loadDB() self.db = lastDB self.db["init"] = time.time() self.db["backupInterval"] = 10*60 if runLocal: self.db["backupInterval"] = 0 self.db["backupDelay"] = 10 if runLocal: self.db["backupDelay"] = 3 self.db["lastBackup"] = 0 self.db["lastBackupServices"] = 0 self.backup() print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::: ::::: ''') print(''' :::: DATABASE LOADED ::::: ''') print(''' :::: ::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(self.db) print() self.services = ServiceLoader.LoadServices(self.send, self.backupService) self.initServicesDB() print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::: ::::: ''') print(''' :::: SERVICES LOADED ::::: ''') print(''' :::: ::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(self.services) print() # # ''' Load Services ''' # # print("SSSSSSSSSSSSSSSSSSSSs") # self.LoadServices() # # print("SSSSSSSSSSSSSSSSSSSSs") ''' process incoming ''' process = Thread(target = self.ProcessIncoming, args=[None]) process.start() else: print(" ::: ERROR - COULD NOT LOG IN ::: ","\n") def send(self, api, service, target, content): print("!!!!!!!!!!!!") if service in self.services: if self.services[service]["api"] is api: if target in self.db["groups"] and service.lower() == self.db["groups"][target].lower(): return self.driver.sendMessage(target,content) def Process(self,contact): for message in contact.messages: print("MMMMMMMMMM",message) if runLocal: chatID = message.chat_id["_serialized"] else: chatID = message.chat_id try: chat = self.driver.get_chat_from_id(chatID) except Exception as e: print(" ::: ERROR - _serialized chatID ::: "+chatID+" ::: ","\n",e,e.args,"\n") ''' incoming from: ''' ''' Personal Chat ''' senderName = message.get_js_obj()["chat"]["contact"]["formattedName"] senderID = message.sender.id fromGroup = False if "c" in chatID: ''' SEND TO MASTER SERVICE ''' self.masterService.Process(message) # # print( # ''' # =================================== # Incoming Messages from '''+senderID+" "+senderName+''' # =================================== # ''' # ) # if message.type == "chat": # text = message.content # # print("TTTTTXXXXXXXXXTTTTTTT",text) # ''' subscribe to service ''' # # ''' SENT FROM GROUP CHAT ''' # # if "%%%!%%%" in text: # target = text.split(u"%%%!%%%")[1] # self.driver.sendMessage(chatID,"Adding Service to DB: "+target) # self.db["services"][target] = {"dbID":None,"incomingTarget":None} # self.LoadServices() # # self.serviceFuncs["services"][target] = None # # self.backup(now = True) # else: # print("XXXXXXXXXXXXXXXXXXX") # print("XXXXXXXXXXXXXXXXXXX") # print("XXXXXXXXXXXXXXXXXXX") # # if text[0] is "=": # ''' person registering service with =''' # target = text[1:] # dbChanged = False # now = False # # ''' check target service in db ''' # serviceFound = False # for service in self.services: # print("______________ ----------"+service) # print("") # if not serviceFound and target.lower() == service.lower(): # target = service # ''' service found ''' # serviceFound = True # # if chatID not in self.db["users"]: # self.db["users"][chatID] = {} # dbChanged = True # ''' first time user ''' # # self.db["users"][senderID] = {'services': {'Reminders': {'groupID': None}}} # else: # pass # ''' known user ''' # # # foundChat = None # if service in self.db["users"][chatID]: # # serviceChat = self.db["users"][chatID][service] # # # self.driver.sendMessage(senderID,"You are already subscirbed to: "+target+" \nYou can unsubscribe with -"+target.lower()) # if serviceChat is not None: # try: # foundChat = self.driver.get_chat_from_id(serviceChat) # except: # print('chat could not be found') # # # chatName = target # welcome = "Thank you for Subscribing to "+target # try: # chatName = self.services[service]["obj"].name # welcome = "Thank you for Subscribing to "+chatName # welcome = self.services[service]["obj"].welcome # except: # pass # # if foundChat is not None: # check_participents = False # if check_participents: # if senderID in foundChat.get_participants_ids() or True: # '''##### check that user is participant ''' # self.driver.sendMessage(senderID,"You are already subscirbed to: "+chatName+" \nYou can unsubscribe with -"+target.lower()) # self.driver.sendMessage(serviceChat,"subscirbed to: "+chatName) # else: # foundChat = None # else: # self.driver.sendMessage(senderID,"You are already subscirbed to:\n"+chatName+" \n<Link>\nYou can unsubscribe with -"+target.lower()) # self.driver.sendMessage(serviceChat,"subscirbed to: "+chatName) # # # ''' create new group ''' # if foundChat is None: # groupName = service # if service in self.services and "obj" in self.services[service] and self.services[service]["obj"] is not None: # groupName = self.services[service]["obj"].name # # newGroup = self.driver.newGroup(newGroupName = groupName, number = "+"+senderID.split("@")[0], local = runLocal) # newGroupID = newGroup.id # self.newG = newGroupID # # self.db["users"][chatID][service] = newGroupID # self.db["groups"][newGroupID] = target # dbChanged = True # now = True # print( # ''' # =============================================== # ''' + senderID +" is NOW SUBSCRIBED TO "+ target +" :D "+''' # =============================================== # ''' # ) # # self.driver.sendMessage(senderID,"Thank you! you are now subscribed to: "+chatName+" \n<Link>\nPlease check your new group :)") # self.driver.sendMessage(newGroupID,welcome) # # self.driver.sendMessage(serviceChat,"subscirbed to: "+target) # # if not serviceFound: # self.driver.sendMessage(chatID,target+" : is not recognized as a service "+target) # print( # ''' # =============================================== # SERVICE '''+ target +" IS NOT AVAILABLE"+''' # =============================================== # ''' # ) # if dbChanged: # self.backup(now=now) # ''' Group Chat ''' elif "g" in chatID: fromGroup = True print( ''' =============================================== Incoming Messages in Group \"'''+senderName+" from "+senderID+''' =============================================== ''' ) if message.type == "chat": text = message.content ''' GOT REGISTRATION COMMAND ''' if text[0] is "=": foundService = None target = text[1:] ''' register group to service ''' for service in self.services: if target.lower() == service.lower(): foundService = service foundChat = False if chatID in self.db["groups"]: targetService = self.db["groups"][chatID] print("TTTTTTTTTTTTTTTTTTTT") print(targetService, service) if targetService is not None: if targetService.lower() == service.lower(): foundChat = True self.driver.sendMessage(chatID,"You are already subscirbed to: "+target+" \nYou can unsubscribe with -"+target.lower()) if not foundChat: print("SSSSSSSSSSSSSSSSSSSSSSsxxxxx") print("SSSSSSSSSSSSSSSSSSSSSSsxxxxx") print("SSSSSSSSSSSSSSSSSSSSSSsxxxxx") self.driver.sendMessage(chatID,"Subscribing to service: "+service) self.db["groups"][chatID] = service self.backup() if foundService is None: self.driver.sendMessage(chatID,"service: "+target+" Not Found") ''' Chat is not registered first time''' if chatID not in self.db["groups"]: # print("SSSSSSSSSSSSSSSSSSSSSS") self.driver.sendMessage(chatID,"This chat is not registered with any service yet\nYou can register it by sending =service_name") # print("JJJJJJJJJJJJJJ") self.db["groups"][chatID] = None # print("SSSSSSSSSSSSSSSSSSSSSS") self.backup() if self.db["groups"][chatID] is not None: ''' Chat is known ''' target = self.db["groups"][chatID] print("MMMMMMMMMMMMMMMM",target) ''' adding new user to service from group''' foundService = None for service in self.services: if target.lower() == service.lower(): foundService = service ''' CHAT IS REGISTERED TO SERVICE! ''' ''' PROCESS INCOMNG MESSAGE in SERVICE ''' if foundService is not None and text[0] is not "=": ''' this is where the magic happens - send to service''' if "obj" in self.services[foundService]: obj = self.services[foundService]["obj"] if obj is not None: #Get Nicknames self.ProcessServiceAsync(obj,{"origin":chatID, "user":senderID, "content":text}) # obj.process({"origin":chatID, "user":senderID, "content":text}) # self.ProcessServiceAsync(service,chatID,text) if foundService is None: self.driver.sendMessage(chatID,target+" : is not recognized as a service "+target) def ProcessIncoming(self, data): print( ''' =================================== Processing Incoming Messages =================================== ''' ) lastm = None loopc = 0 delay = 0.5 while True: # try: if True: if loopc % 20 == 0: ''' ::: rechecking status ::: ''' try: self.status = status = self.driver.get_status() print(" ::: status is",status,"::: ") except Exception as e: self.status = status = "XXXXXXXX" print(" ::: ERROR - Status Fetching ::: ","\n",e,e.args,"\n") ''' all unread messages ''' for contact in self.driver.get_unread(): self.Process(contact) ''' lastm = message print(json.dumps(message.get_js_obj(), indent=4)) for contact in self.driver.get_contacts(): # print("CCCC",contact.get_safe_name() ) if sender in contact.get_safe_name(): chat = contact.get_chat() # chat.send_message("Hi "+sender+" !!!*"+message.content+"*") print() print() print(sender) print() print() print("class", message.__class__.__name__) print("message", message) print("id", message.id) print("type", message.type) print("timestamp", message.timestamp) print("chat_id", message.chat_id) print("sender", message.sender) print("sender.id", message.sender.id) print("sender.safe_name", message.sender.get_safe_name()) if message.type == "chat": print("-- Chat") print("safe_content", message.safe_content) print("content", message.content) # Manager.process(message.sender.id,message.content) # contact.chat.send_message(message.safe_content) elif message.type == "image" or message.type == "video": print("-- Image or Video") print("filename", message.filename) print("size", message.size) print("mime", message.mime) print("caption", message.caption) print("client_url", message.client_url) message.save_media("./") else: print("-- Other type:",str(message.type)) print("PROCESSING MESSAGE:",message) ''' else: pass # except Exception as e: # print(" ::: ERROR - CHECKING MESSAGES ::: ","\n",e,e.args,"\n") loopc += 1; loopc = loopc % 120 time.sleep(delay) # class Master0(object): # print( # ''' # ::::::::::::::::::::::::::::::::: # ::::::::::::::::::::::::::::::::: # :::: :::: # :::: MASTER DRIVER :::: # :::: :::: # ::::::::::::::::::::::::::::::::: # ::::::::::::::::::::::::::::::::: # ''' # ) def initServicesDB(self): for service in self.services: # try: if True: if "servicesDB" not in self.db: self.db["servicesDB"] = {} if service not in self.db["servicesDB"]: self.db["servicesDB"][service] = {} if "dbID" not in self.db["servicesDB"][service]: self.db["servicesDB"][service]["dbID"] = None dbID = self.db["servicesDB"][service]["dbID"] ''' create new db group ''' db = {} if dbID is None: print("-------------------------------") print(" CREATING NEW DB GROUP "+service) print("-------------------------------") groupName = service newGroup = self.driver.newGroup(newGroupName = service+"_DB", number = "+"+self.db["masters"][1], local = runLocal) newGroupID = newGroup.id self.db["servicesDB"][service]["dbID"] = newGroupID db = {"init":True} self.driver.sendMessage(newGroupID, json.dumps(db)) self.backup() else: db = self.loadDB(dbID) print("-------------------------------") print("service: ",service," dbID: ",dbID) print("-------------------------------") print(db) # while() self.services[service]["obj"].updateDB(db) # except Exception as e: else: print(" ::: ERROR - LOAD SERVICES ::: ","\n",e,e.args,"\n") def LoadServices0(self): # load list of services for service in self.db["services"]: if "reminders".lower() == service.lower(): print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") ReminderService.go(sendDelegate=self.driver.sendMessage,backupDelegate=self.backupService) self.serviceFuncs["services"][service]=ReminderService.process groupName = "🔔 Reminders 🔔" self.serviceGroupNames[service] = groupName self.db["services"][service]["welcome"] = ReminderService.welcome self.db["services"][service]["groupName"] = groupName # self.serviceGroupNames[service] = "Reminders" if "danilator".lower() == service.lower(): print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") print("FFFFFFFFFFFFFFFFFFFFFFFFFFF") DanilatorService.go(sendDelegate=self.driver.sendMessage,backupDelegate=self.backupService) self.serviceFuncs["services"][service]=DanilatorService.process groupName = "💚 Danilator 💚" self.serviceGroupNames[service] = groupName self.db["services"][service]["welcome"] = DanilatorService.welcome self.db["services"][service]["groupName"] = groupName # self.serviceGroupNames[service] = "Danilator" try: if "dbID" not in self.db["services"][service]: self.db["services"][service]["dbID"] = None dbID = self.db["services"][service]["dbID"] ''' create new db group ''' if dbID is None: print("-------------------------------") print(" CREATING NEW DB GROUP "+service) print("-------------------------------") groupName = service newGroup = self.driver.newGroup(newGroupName = service+"_DB", number = "+"+self.db["masters"][1], local = runLocal) newGroupID = newGroup.id self.db["services"][service]["dbID"] = newGroupID self.driver.sendMessage(newGroupID, json.dumps({"init":True})) self.backup() else: print("-------------------------------") print("service: ",service," dbID: ",dbID) print("-------------------------------") except Exception as e: print(" ::: ERROR - LOAD SERVICES ::: ","\n",e,e.args,"\n") def initAsync0(self, profileDir = "/app/session/rprofile2"): ''' init driver variables ''' if len(Master.shares) > 1: profileDir += "-"+str(len(Master.shares)) chrome_options = webdriver.ChromeOptions() chrome_options.binary_location = os.environ.get("GOOGLE_CHROME_BIN") chrome_options.add_argument("--headless") chrome_options.add_argument("--disable-dev-shm-usage") chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36") chrome_options.add_argument("user-data-dir="+profileDir); chrome_options.add_argument('--profile-directory='+profileDir) if not runLocal: self.driver = WhatsAPIDriver(profile = profileDir, client='chrome', chrome_options=chrome_options,username="******") else: self.driver = WhatsAPIDriver(username="******",profile=None) driver = self.driver self.masterService = MasterService(runLocal, self.db, self.services, self.driver, self) print(''' ::: waiting for login ::: ''') driver.wait_for_login() try: self.status = status = driver.get_status() except Exception as e: print(" ::: ERROR - Status Init ::: ","\n",e,e.args,"\n") ''' preping for qr ''' if status is not "LoggedIn": img = None triesCount = 0 maxtries = 40 while status is not "LoggedIn" and triesCount < maxtries: triesCount+=1 print("-------------------------------") print("status:",status,"tries:",triesCount,"/",maxtries) print("-------------------------------") self.lastQR += 1 try: img = driver.get_qr("static/img/QR"+str(self.lastQR)+".png") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ") print("QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ",str(img)[17:130]) except Exception as e: print(" ::: ERROR - QR Fetching ::: ","\n",e,e.args,"\n") # im_path = os.path.join("static/img/newQR.png") print(''' ::: rechecking status ::: ''') try: self.status = status = driver.get_status() except Exception as e : self.status = status = "XXXXXXXX" print(" ::: ERROR - Status Fetching ::: ","\n",e,e.args,"\n") if status is "LoggedIn": print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::: ::::: ''') print(''' :::: MASTER IS LOGGED IN! ::::: ''') print(''' :::: ::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') # if runLocal: # self.driver.save_firefox_profile(remove_old=False) ''' load DB ''' ## overwrite to init db initOverwrite = False if initOverwrite: self.backup(now = True) # driver.updateDB(self.db,number=self.db["id"]) lastDB = self.loadDB() self.db = lastDB self.db["init"] = time.time() self.db["backupInterval"] = 10*60 if runLocal: self.db["backupInterval"] = 0 self.db["backupDelay"] = 10 if runLocal: self.db["backupDelay"] = 3 self.db["lastBackup"] = 0 self.db["lastBackupServices"] = 0 self.backup() print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::: ::::: ''') print(''' :::: DATABASE LOADED ::::: ''') print(''' :::: ::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(''' :::::::::::::::::::::::::::::::::::: ''') print(self.db) print() # ''' Load Services ''' # print("SSSSSSSSSSSSSSSSSSSSs") self.LoadServices() # print("SSSSSSSSSSSSSSSSSSSSs") ''' process incoming ''' process = Thread(target = self.ProcessIncoming, args=[None]) process.start() else: print(" ::: ERROR - COULD NOT LOG IN ::: ","\n") def loadDB(self, number = None): if number is None: number = self.db["id"] return self.driver.loadDB(number = number) def backupService(self, db = None, service = None, api = None): data = [db,service] # self.backupServiceAsync(data) if service in self.services: if self.services[service]["api"] is api: bT = Thread(target = self.backupServiceAsync,args = [data]) bT.start() def backupServiceAsync(self,data): time.sleep(self.db["backupDelay"]) db, service = data print("SSSSSSSSS",service,db) if time.time() - self.db["lastBackupServices"] < self.db["backupInterval"]: return False if service is None or len(service) == 0: return None backupChat = None if service in self.db["servicesDB"]: chatID = self.db["servicesDB"][service]["dbID"] if chatID is not None: bchat = None try: bchat = self.driver.getChat(chatID) except Exception as e: print(" ::: ERROR - COULD NOT GET BACKUPCHAT",e," ::: ","\n") if bchat is not None: print("FFFFFFFFFFFFFFFUCKKK") # self.driver.sendMessage(chatID,"FFFFFFFFFFFFFFFUCKKK") backupChat = chatID else: print(" ::: ERROR - SERVICE HAS NO BACKUPCHAT"+" ::: ","\n") if backupChat is not None: if db is not None: return self.driver.updateDB(db,number=backupChat) else: return self.loadDB(backupChat) else: print(" ::: ERROR - BackupChat NOT FOUND for :"+service+": service ::: \n") self.db["lastBackupServices"] = time.time() def backup(self, now = None): bT = Thread(target = self.backupAsync,args = [now]) bT.start() def backupAsync(self,data): now = data if now is None: time.sleep(self.db["backupDelay"]) if time.time() - self.db["lastBackup"] < self.db["backupInterval"]: return False self.db["lastBackup"] = time.time() return self.driver.updateDB(self.db,number=self.db["id"]) def ProcessServiceAsync(self, obj, info): serviceT = Thread(target = self.ProcessService, args = [[obj,info]]) serviceT.start() def ProcessService(self, data): # try: # service, chatID, text = data obj, info = data obj.process(info) # self.serviceFuncs["services"][service](chatID, text) # except Exception as e: # print(" ::: ERROR - Processing Service ::: ",serice,":::",chatID,":::",text,":::","\n",e,e.args,"\n") def ProcessIncoming0(self, data): print( ''' =================================== Processing Incoming Messages =================================== ''' ) lastm = None loopc = 0 delay = 0.5 while True: # try: if True: if loopc % 20 == 0: ''' ::: rechecking status ::: ''' try: self.status = status = self.driver.get_status() print(" ::: status is",status,"::: ") except Exception as e: self.status = status = "XXXXXXXX" print(" ::: ERROR - Status Fetching ::: ","\n",e,e.args,"\n") ''' all unread messages ''' for contact in self.driver.get_unread(): # print("MMMMMMMMMMXXX",contact) # print("MMMMMMMMMMXXX",contact) # print("MMMMMMMMMMXXX",contact) # print("MMMMMMMMMMXXX",contact) # print("MMMMMMMMMMXXX",contact) for message in contact.messages: print("MMMMMMMMMM",message) # print("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII") # pprint(vars(contact)) # print("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII") # pprint(vars(message)) # print("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII") # print("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII") # print("IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII") if runLocal: chatID = message.chat_id["_serialized"] else: chatID = message.chat_id try: chat = self.driver.get_chat_from_id(chatID) except Exception as e: print(" ::: ERROR - _serialized chatID ::: "+chatID+" ::: ","\n",e,e.args,"\n") ''' incoming from: ''' ''' Personal Chat ''' senderName = message.get_js_obj()["chat"]["contact"]["formattedName"] senderID = message.sender.id fromGroup = False if "c" in chatID: print( ''' =================================== Incoming Messages from '''+senderID+" "+senderName+''' =================================== ''' ) # ''' Group Chat ''' elif "g" in chatID: fromGroup = True print( ''' =============================================== Incoming Messages from \"'''+senderID+" in "+senderName+'''\" GROUP =============================================== ''' ) if message.type == "chat": text = message.content print("TTTTTXXXXXXXXXTTTTTTT",text) ''' subscribe to service ''' ''' SENT FROM GROUP CHAT ''' if "%%%!%%%" in text: print("YYYYYYYYYYYYYYYYYYYY") print("YYYYYYYYYYYYYYYYYYYY") print("YYYYYYYYYYYYYYYYYYYY") target = text.split(u"%%%!%%%")[1] self.driver.sendMessage(chatID,"Adding Service to DB: "+target) self.db["services"][target] = {"dbID":None,"incomingTarget":None} self.LoadServices() # self.serviceFuncs["services"][target] = None self.backup(now = True) else: print("XXXXXXXXXXXXXXXXXXX") print("XXXXXXXXXXXXXXXXXXX") print("XXXXXXXXXXXXXXXXXXX") if fromGroup is True: ''' GOT REGISTRATION COMMAND ''' if text[0] is "=": foundService = None target = text[1:] ''' register group to service ''' for service in self.db["services"]: if target.lower() == service.lower(): foundService = service foundChat = False if chatID in self.db["groups"]: targetService = self.db["groups"][chatID] print("TTTTTTTTTTTTTTTTTTTT") print(targetService, service) if targetService is not None: if targetService.lower() == service.lower(): foundChat = True self.driver.sendMessage(chatID,"You are already subscirbed to: "+target+" \nYou can unsubscribe with -"+target.lower()) if not foundChat: print("SSSSSSSSSSSSSSSSSSSSSSsxxxxx") print("SSSSSSSSSSSSSSSSSSSSSSsxxxxx") print("SSSSSSSSSSSSSSSSSSSSSSsxxxxx") self.driver.sendMessage(chatID,"Subscribing to service: "+service) self.db["groups"][chatID] = service self.backup() if foundService is None: self.driver.sendMessage(chatID,"service: "+target+" Not Found") ''' Chat is not registered first time''' if chatID not in self.db["groups"]: # print("SSSSSSSSSSSSSSSSSSSSSS") self.driver.sendMessage(chatID,"This chat is not registered with any service yet\nYou can register it by sending =service_name") # print("JJJJJJJJJJJJJJ") self.db["groups"][chatID] = None # print("SSSSSSSSSSSSSSSSSSSSSS") self.backup() elif self.db["groups"][chatID] is not None: ''' Chat is known ''' target = self.db["groups"][chatID] print("MMMMMMMMMMMMMMMM",target) ''' adding new user to service from group''' foundService = None for service in self.db["services"]: if target.lower() == service.lower(): foundService = service ''' CHAT IS REGISTERED TO SERVICE! ''' ''' PROCESS INCOMNG MESSAGE in SERVICE ''' if foundService is not None and text[0] is not "=": # self.driver.sendMessage(chatID,text+" ::: GONNA BE PROCESSED BY "+target) ''' this is where the magic happens - send to service''' self.ProcessServiceAsync(service,chatID,text) if foundService is None: self.driver.sendMessage(chatID,target+" : is not recognized as a service "+target) else: ''' service is None ''' self.driver.sendMessage(chatID,"You can register this chat by sending =service_name") elif text[0] is "=": ''' person registering service with =''' target = text[1:] dbChanged = False now = False ''' check target service in db ''' serviceFound = False for service in self.db["services"]: print("______________ ----------"+service) print("") if not serviceFound and target.lower() == service.lower(): ''' service found ''' serviceFound = True if chatID not in self.db["users"]: self.db["users"][chatID] = {'services': {}} dbChanged = True ''' first time user ''' # self.db["users"][senderID] = {'services': {'Reminders': {'groupID': None}}} else: ''' known user ''' foundChat = None if service in self.db["users"][chatID]["services"]: serviceChat = self.db["users"][chatID]["services"][service] # self.driver.sendMessage(senderID,"You are already subscirbed to: "+target+" \nYou can unsubscribe with -"+target.lower()) try: foundChat = self.driver.get_chat_from_id(serviceChat) except: print('chat could not be found') chatName = target welcome = "Thank you for Subscribing to "+target try: chatName = self.db["services"][service]["groupName"] welcome = "Thank you for Subscribing to "+chatName welcome = self.db["services"][service]["welcome"] except: pass if foundChat is not None: check_participents = False if check_participents: if senderID in foundChat.get_participants_ids() or True: '''##### check that user is participant ''' self.driver.sendMessage(senderID,"You are already subscirbed to: "+chatName+" \nYou can unsubscribe with -"+target.lower()) self.driver.sendMessage(serviceChat,"subscirbed to: "+chatName) else: foundChat = None else: self.driver.sendMessage(senderID,"You are already subscirbed to:\n"+chatName+" \nYou can unsubscribe with -"+target.lower()) self.driver.sendMessage(serviceChat,"subscirbed to: "+chatName) ''' create new group ''' if foundChat is None: groupName = service if service in self.serviceGroupNames: groupName = self.serviceGroupNames[service] newGroup = self.driver.newGroup(newGroupName = groupName, number = "+"+senderID.split("@")[0], local = runLocal) newGroupID = newGroup.id self.newG = newGroupID self.db["users"][chatID]['services'][service] = newGroupID self.db["groups"][newGroupID] = target dbChanged = True now = True print( ''' =============================================== ''' + senderID +" is NOW SUBSCRIBED TO "+ target +" :D "+''' =============================================== ''' ) self.driver.sendMessage(senderID,"Thank you! you are now subscribed to: "+chatName+" \nPlease check your new group :)") self.driver.sendMessage(newGroupID,welcome) # self.driver.sendMessage(serviceChat,"subscirbed to: "+target) if not serviceFound: self.driver.sendMessage(chatID,target+" : is not recognized as a service "+target) print( ''' =============================================== SERVICE '''+ target +" IS NOT AVAILABLE"+''' =============================================== ''' ) if dbChanged: self.backup(now=now) ''' lastm = message print(json.dumps(message.get_js_obj(), indent=4)) for contact in self.driver.get_contacts(): # print("CCCC",contact.get_safe_name() ) if sender in contact.get_safe_name(): chat = contact.get_chat() # chat.send_message("Hi "+sender+" !!!*"+message.content+"*") print() print() print(sender) print() print() print("class", message.__class__.__name__) print("message", message) print("id", message.id) print("type", message.type) print("timestamp", message.timestamp) print("chat_id", message.chat_id) print("sender", message.sender) print("sender.id", message.sender.id) print("sender.safe_name", message.sender.get_safe_name()) if message.type == "chat": print("-- Chat") print("safe_content", message.safe_content) print("content", message.content) # Manager.process(message.sender.id,message.content) # contact.chat.send_message(message.safe_content) elif message.type == "image" or message.type == "video": print("-- Image or Video") print("filename", message.filename) print("size", message.size) print("mime", message.mime) print("caption", message.caption) print("client_url", message.client_url) message.save_media("./") else: print("-- Other type:",str(message.type)) print("PROCESSING MESSAGE:",message) ''' else: pass # except Exception as e: # print(" ::: ERROR - CHECKING MESSAGES ::: ","\n",e,e.args,"\n") loopc += 1; loopc = loopc % 120 time.sleep(delay) def quit(self): self.driver.quit() def Nothing(data): print(":::Nothign::: DATA=",data)
from webwhatsapi import WhatsAPIDriver driver = WhatsAPIDriver(username="******") print('get_unread: ', driver.get_unread(include_me=True, include_notifications=True)) print('get_contacts: ', driver.get_contacts()) # print('save_firefox_profile: ', driver.save_firefox_profile()) getChatFrom = driver.get_chat_from_phone_number(628999871008) print('get_chat_from_phone_number: ', getChatFrom) # print('get_all_messages_in_chat: ', driver.get_all_messages_in_chat(getChatFrom.id, include_me=True, include_notifications=True)) print(driver.get_qr()) print('get_all_chats: ', driver.get_all_chats()) print(driver.wait_for_login()) # print('get_safe_name', driver.get_safe_name()) print('get_unread: ', driver.get_unread()) # print('view_unread: ', driver.view_unread())
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)
class Whatsapp(threading.Thread): def __init__(self, identifier): self.driver = WhatsAPIDriver(loadstyles=True) self.identifier = identifier self.messagesSent = 0 self.messageQueue = [] self.status = {} print("Waiting for QR") try: self.driver.wait_for_login() super(Whatsapp, self).__init__() self.setDaemon(True) except Exception as ex: print("Error", ex) print("New Browser Opened") def get_chat(self, phone): try: chat = self.driver.get_chat_from_phone_number(phone) except ChatNotFoundError: url = self.driver._URL+"/send?phone="+phone self.driver.driver.get(url) t.sleep(5) chat = self.driver.get_chat_from_phone_number(phone) return chat # Give timeout_after_sent to avoid being suspected as a spammer. # Assign high value after multithreading is implemented. def send_whatsapp_message(self, phone, message, chat_id=None): try: if chat_id is None: chat = self.get_chat(phone) self.driver.chat_send_message(chat.id, message) else: self.driver.send_message_to_id(chat_id, message) self.messagesSent += 1 except ChatNotFoundError: # This means the given number is invalid. Logger.warning("Invalid phone number: " + str(phone) + " will be deleted") c = Contact.objects.get(phone=phone) c.delete() raise ChatNotFoundError except Exception as e: # This means browser is still not available even after 5 seconds. # But the number is not invalid.(= valid) Logger.error(repr(e)) raise e def send_message_and_save_log(self): messages = Message.objects.all().filter(use=True).filter(broadcast=True) for m in messages: logs = Log.objects.all().filter(message_id=m.id).filter(sent=True) contacts_already_sent = [] for l in logs: contacts_already_sent.append(l.contact_id) contacts_to_send = Contact.objects.all().exclude(id__in=contacts_already_sent) if len(contacts_to_send) > 0: # Save the log first so that the same contact cannot be used in another browsers. for contact in contacts_to_send: newLogs = Log.objects.filter(message_id=m.id).filter(contact_id=contact.id).get_or_create(message_id=m.id, contact_id=contact.id, sent=False, sender_id=self.identifier, broadcasted=True) if len(newLogs) > 0: l = newLogs[0] try: print("Try to send message: [phone(", contact.id, ": ", contact.phone, "), text(", m.id, ": ", m.text, ")", sep="") # If no exception, update 'sent', 'sent_at' self.send_whatsapp_message(contact.phone, m.text) l.sent = True l.sent_at = now() l.save(update_fields=['sent', 'sent_at']) # The reason returning here is: once the message is sent to anyone of contacts, # then server should bring available contacts again, not iterating over the given list. # Otherwise, there is no way to control server immediately after insert new messages, contacts to DB. return except Exception as e: Logger.warning(repr(e)) # Wait when error occurred so that browser can be opened again. t.sleep(5) def poll_unread(self): try: if self.driver.is_logged_in(): # Spam only works when this server is used as a spammer. if apps.WhatsappConfig.spammer == 'true': try: self.send_message_and_save_log() except Exception as e: Logger.error(repr(e)) # Otherwise, this server will fetch unread messages and send webhook. else: data = [] try: Logger.debug("(" + self.identifier + "): get_unread()") for messageGroup in self.driver.get_unread(): unread_messages = [] for m in messageGroup.messages: unread_messages.append({ "content": m.content, "timestamp": "{timestamp}".format(timestamp=m.timestamp) }) data.append({ "chatId": messageGroup.chat.id, "unreadMessages": unread_messages }) except Exception as e: Logger.error(repr(e)) # Doesn't have to make a request when there is no unread message. if len(data) > 0: payload = {'data': data} webhook_url = apps.WhatsappConfig.api_endpoint + '/no_auth/whatsapp/webhook' try: print("Request:", webhook_url) r = requests.post(webhook_url, json=payload, timeout=3) print("Response:", r.text) except Exception as e: print("Tokotalk API(" + webhook_url + ") doesn't respond in 3 second", sep='') except Exception as e: Logger.error(repr(e)) def run(self): while True: try: self.poll_unread() except Exception as e: Logger.debug(repr(e) + ": POLL FAILED") # in case the interval is not set in .env interval = 5 if apps.WhatsappConfig.message_interval is not None: interval = int(apps.WhatsappConfig.message_interval) t.sleep(interval)
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}' />")
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)