├── docs └── README.md ├── setup.py ├── README.md └── main.py /docs/README.md: -------------------------------------------------------------------------------- 1 | # نحوه استفاده از اتوایتا 2 | **اتوایتا** یک ابزار باز و متن‌باز است که برای اتوماسیون(خودکارسازی) فعالیت‌ها در پیام‌رسان ایتا است. 3 | 4 | **نکته**: توصیه می‌شود برای اجرای بهینه تر ابزار از مرورگر فایرفاکس استفاده شود. 5 | 6 | - [پیش نیاز‌ها]() 7 | - [فراخوانی ابزار در کد]() 8 | - [ورود به اکانت(لاگین)]() 9 | - [ارسال پیام متنی]() 10 | - [ارسال فایل(عکس، فیلم، ...)]() 11 | - [دریافت پیام]() 12 | - [ویرایش پیام]() 13 | - 14 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | libraries = [ 4 | "requests", 5 | "comtypes", 6 | "pillow", 7 | "selenium", 8 | "colorama", 9 | "soundcard", 10 | "soundfile", 11 | "pycaw", 12 | "requests" 13 | "pywin32" 14 | ] 15 | 16 | for library in libraries: 17 | print(f"Installing {library}...") 18 | os.system(f"pip install {library}") 19 | print(f"{library} installation finished.\n") 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoEitaa 2 | 3 | با تلاش شبانه روزی تیم [ایتابین](https://eitaa.com/eitaabin) ابزاری رو نوشتیم که برنامه نویسان پایتون بتوانند ربات خود را درون ایتا بسازند. ✨ 4 | 5 | ## 🤷‍♂️ منظورمان از ربات چیست؟ 6 | منظورمان از ربات یک برنامه ای است که میتواند کارهایی را درون ایتا به صورت خودکار انجام دهند. 7 | 8 | ## نکته 9 | 10 | برنامه نویسان پایتون میتوانند از این ابزار برای انجام فعالیت هایی درون ایتا استفاده کنند و بقیه کار که مربوط به فعالیت های ربات است (مثال: حل کردن مسائل ریاضی) باید توسط خود شما برنامه نویسی شود. 11 | 12 | 13 | این ابزار با زبان پایتون نوشته و ساخته شده است و توصیه می‌شود برای اجرای بهینه تر ابزار از سیستم عامل ویندوز استفاده شود⚠️ 14 | 15 | 16 | ربات میتواند در هر حسابی در ایتا فعال شود و هیچ محدودیتی ندارد !🔅 17 | 18 | ## نحوه استفاده 19 | 20 | بزودی داکیومنت این ابزار رو اضافه میکنیم 21 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from requests import * 2 | from comtypes import CoInitialize, CoUninitialize 3 | from time import * 4 | from sys import * 5 | import os 6 | import win32clipboard 7 | from PIL import Image 8 | from io import BytesIO 9 | from selenium import webdriver 10 | from selenium.webdriver.common.by import By 11 | from selenium.webdriver.common.action_chains import ActionChains 12 | from selenium.webdriver.common.keys import Keys 13 | from selenium.webdriver.common.by import By 14 | from selenium.webdriver.common.keys import Keys 15 | from selenium.webdriver import ActionChains 16 | from colorama import Fore 17 | import threading 18 | import pyperclip 19 | import requests 20 | import soundcard as sc 21 | import soundfile as sf 22 | from pycaw.pycaw import AudioUtilities, ISimpleAudioVolume, IAudioMeterInformation 23 | import json 24 | 25 | CoInitialize() 26 | 27 | class Bot: 28 | def __init__(self, headless: bool, autologin: bool, Browser: str = "2"): # همه کروم رو دارن 29 | options = webdriver.FirefoxOptions() 30 | if headless: 31 | options.add_argument('--headless') 32 | try: 33 | requests.get("https://web.eitaa.com/") #چک کردن وضعیت سرویس ایتا 34 | except: 35 | print(Fore.RED+"Eitaa Is Down Or System Is Offline!"+Fore.WHITE) 36 | return 37 | print(Fore.CYAN+"Bip... Bip... Starting!"+Fore.WHITE) 38 | if str(Browser) == "1": 39 | self.driver = webdriver.Firefox(options=options) 40 | elif str(Browser) == "2": 41 | self.driver = webdriver.Chrome(options=options) 42 | 43 | try: 44 | self.driver.get("https://web.eitaa.com/") 45 | except: 46 | return "Error in go_eitaa_web" 47 | def login(): 48 | while True: 49 | try: 50 | phone_input = self.driver.find_element(By.CSS_SELECTOR, "div.input-field:nth-child(2) > div:nth-child(1)") 51 | except: 52 | continue 53 | else: 54 | phone = input("What's your "+Fore.GREEN+"phone number"+Fore.WHITE+" for login in Eitaa? +") 55 | phone_input.send_keys(Keys.CONTROL + 'a') 56 | phone_input.send_keys(Keys.BACKSPACE) 57 | phone_input.send_keys(str(phone)) 58 | self.driver.find_element(By.CSS_SELECTOR, "button.btn-primary:nth-child(4)").click() 59 | break 60 | while True: 61 | try: 62 | code_input = self.driver.find_element(By.CSS_SELECTOR, "input.input-field-input") 63 | except: 64 | continue 65 | else: 66 | Otp_code = input("What's The "+Fore.GREEN+"OTP Code"+Fore.WHITE+" Sent you in Eitaa or sms? ") 67 | code_input.send_keys(str(Otp_code)) 68 | break 69 | while True: 70 | try: 71 | self.driver.find_element(By.CSS_SELECTOR, '#main-search') 72 | except: 73 | status = self.driver.find_element(By.XPATH, "/html/body/div[1]/div/div[2]/div[3]/div/div[3]/div/label/span") 74 | if str(status.text) == "کد نامعتبر است": 75 | Otp_code = input("OTP code is wrong try again!") 76 | exit() 77 | else: 78 | print("Waiting...", end="\r") 79 | continue 80 | else: 81 | os.system('cls') 82 | sleep(15.5) 83 | print(Fore.GREEN+"Login Successfully! Welcome!"+Fore.WHITE) 84 | flag = input("Should I Save your Account so you don't have to Login again? (y/n)") 85 | if flag == "y": 86 | data_auth = self.driver.execute_script(""" 87 | var items = {}; 88 | for (var i = 0; i < localStorage.length; i++) { 89 | var key = localStorage.key(i); 90 | items[key] = localStorage.getItem(key); 91 | } 92 | return items; 93 | """) 94 | self.data_account = data_auth # data_auth یک دیکشنری است 95 | 96 | eitaa_auth = self.data_account.get("eitaa_auth") 97 | if eitaa_auth is None: 98 | raise KeyError("'eitaa_auth' key not found in data_account") 99 | 100 | if isinstance(eitaa_auth, str): 101 | try: 102 | eitaa_auth_dict = json.loads(eitaa_auth) 103 | except json.JSONDecodeError as e: 104 | raise ValueError(f"Invalid JSON in eitaa_auth: {e}") 105 | elif isinstance(eitaa_auth, dict): 106 | eitaa_auth_dict = eitaa_auth 107 | else: 108 | raise TypeError(f"eitaa_auth must be dict or str, got {type(eitaa_auth)}") 109 | 110 | if "id" not in eitaa_auth_dict: 111 | raise KeyError("'id' not found in eitaa_auth dictionary") 112 | user_id = eitaa_auth_dict["id"] 113 | 114 | with open(f"login.json", "w") as file: 115 | json.dump(self.data_account, file, indent=4) 116 | print("Your Account Userid ==> "+str(user_id)) 117 | else: 118 | pass 119 | break 120 | 121 | if autologin: 122 | try: 123 | with open(f"login.json", "r") as file: 124 | account_data = json.load(file) 125 | script = "" 126 | for key, value in account_data.items(): 127 | escaped_key = json.dumps(key) 128 | escaped_value = json.dumps(value) 129 | script += f"localStorage.setItem({escaped_key}, {escaped_value});" 130 | self.driver.execute_script(script) 131 | self.driver.refresh() 132 | os.system('cls') 133 | sleep(15.5) 134 | except: 135 | try: 136 | requests.get("https://web.eitaa.com/") 137 | except: 138 | print(Fore.RED+"Eitaa Is Down Or System Is Offline!"+Fore.WHITE) 139 | return 140 | print(Fore.RED+"Login Data Not Found!"+Fore.WHITE+"\nLogin "+Fore.RED+"Without"+Fore.WHITE+" AutoLogin First!") #اتو لاگین اینجا مدیریت شده تا در صورت عدم وجود، لاگین بشه 141 | login() 142 | else: 143 | login() 144 | def list_active_sessions(self): 145 | 146 | sessions = AudioUtilities.GetAllSessions() 147 | active_sessions = [] 148 | 149 | print("Programs currently playing sound:") 150 | for session in sessions: 151 | if session.Process: 152 | process_name = session.Process.name() 153 | pid = session.Process.pid 154 | try: 155 | audio_meter = session._ctl.QueryInterface(IAudioMeterInformation) 156 | peak = audio_meter.GetPeakValue() 157 | 158 | if peak > 0: 159 | print(f"Program: {process_name}, PID: {pid}, Peak Volume: {peak:.2f}") 160 | active_sessions.append((session, process_name, pid)) 161 | except Exception as e: 162 | print(f"Could not retrieve audio info for {process_name}: {e}") 163 | 164 | return active_sessions 165 | 166 | def mute_sessions(self, active_sessions): 167 | for session, process_name, pid in active_sessions: 168 | try: 169 | volume = session._ctl.QueryInterface(ISimpleAudioVolume) 170 | print(f"Muting Program: {process_name}, PID: {pid}") 171 | volume.SetMasterVolume(0, None) 172 | except Exception as e: 173 | print(f"Could not mute {process_name}: {e}") 174 | 175 | def unmute_sessions(self, active_sessions): 176 | for session, process_name, pid in active_sessions: 177 | try: 178 | volume = session._ctl.QueryInterface(ISimpleAudioVolume) 179 | print(f"Unmuting Program: {process_name}, PID: {pid}") 180 | volume.SetMasterVolume(1, None) 181 | except Exception as e: 182 | print(f"Could not unmute {process_name}: {e}") 183 | 184 | 185 | def copy_to_clipboard(self, file_name): 186 | command = f"powershell Set-Clipboard -LiteralPath {file_name}" 187 | os.system(command) 188 | 189 | def save_audio(self, s): 190 | OUTPUT_FILE_NAME = "output.mp3" # file name. 191 | SAMPLE_RATE = 48000 # [Hz]. sampling rate. 192 | RECORD_SEC = int(s) # [sec]. duration recording audio. 193 | 194 | with sc.get_microphone(id=str(sc.default_speaker().name), include_loopback=True).recorder(samplerate=SAMPLE_RATE) as mic: 195 | # record audio with loopback from default speaker. 196 | data = mic.record(numframes=SAMPLE_RATE*RECORD_SEC) 197 | 198 | # change "data=data[:, 0]" to "data=data", if you would like to write audio as multiple-channels. 199 | sf.write(file=OUTPUT_FILE_NAME, data=data[:, 0], samplerate=SAMPLE_RATE) 200 | 201 | def scroll(self): 202 | self.driver.execute_script("window.scrollTo(0, window.scrollY + 30)") 203 | 204 | def send_to_clipboard(self, clip_type, data): 205 | win32clipboard.OpenClipboard() 206 | win32clipboard.EmptyClipboard() 207 | win32clipboard.SetClipboardData(clip_type, data) 208 | win32clipboard.CloseClipboard() 209 | 210 | def isMessageNew(self, msg1, msg2): 211 | if str(msg1) == str(msg2): 212 | return False 213 | else: 214 | return True 215 | 216 | def canSendToUser(self, chat_id): 217 | r = self.driver.execute_script("return appUsersManager.canSendToUser("+str(chat_id)+");") 218 | if str(r) == "true": 219 | return True 220 | elif str(r) == "None": 221 | return "None" 222 | else: 223 | return False 224 | 225 | def isUserOnline(self, chat_id): 226 | r = self.driver.execute_script("return appUsersManager.isUserOnlineVisible("+str(chat_id)+");") 227 | if str(r) == "true": 228 | return True 229 | else: 230 | return False 231 | 232 | def myId(self): 233 | r = self.driver.execute_script("return appImManager.myId;") 234 | return str(r) 235 | 236 | def getContactList(self): 237 | r = self.driver.execute_script("return appUsersManager.contactsList;") 238 | return str(r) 239 | 240 | def isContact(self, chat_id): 241 | r = self.driver.execute_script("return appUsersManager.isContact("+str(chat_id)+");") 242 | if str(r) == "true": 243 | return True 244 | else: 245 | return False 246 | 247 | def getPeerUsername(self, chat_id): 248 | r = self.driver.execute_script("return appPeersManager.getPeerUsername("+str(chat_id)+");") 249 | if str(r) == "true": 250 | return True 251 | else: 252 | return False 253 | 254 | def isAnyGroup(self, chat_id): 255 | r = self.driver.execute_script("return appPeersManager.isAnyGroup("+str(chat_id)+");") 256 | if str(r) == "true": 257 | return True 258 | else: 259 | return False 260 | 261 | def isUser(self, chat_id): 262 | if str(chat_id[0]) == "-": 263 | return False 264 | else: 265 | return True 266 | 267 | def getPeerSearchText(self, chat_id): 268 | r = self.driver.execute_script("return appPeersManager.getPeerSearchText("+str(chat_id)+");") 269 | return str(r) 270 | 271 | def getPeer(self, chat_id): 272 | r = self.driver.execute_script("return appPeersManager.getPeer("+str(chat_id)+");") 273 | return str(r) 274 | 275 | def getDialogType(self, chat_id): 276 | r = self.driver.execute_script("return appPeersManager.getDialogType("+str(chat_id)+");") 277 | return str(r) 278 | 279 | def canPinMessage(self, msg_id): 280 | r = self.driver.execute_script("return appPeersManager.canPinMessage("+str(msg_id)+");") 281 | if str(r) == "true": 282 | return True 283 | else: 284 | return False 285 | 286 | def canDeleteMessage(self, msg_id): 287 | r = self.driver.execute_script("return appMessagesManager.canDeleteMessage("+str(msg_id)+");") 288 | if str(r) == "true": 289 | return True 290 | else: 291 | return False 292 | 293 | def canEditMessage(self, msg_id): 294 | r = self.driver.execute_script("return appMessagesManager.canEditMessage("+str(msg_id)+");") 295 | if str(r) == "true": 296 | return True 297 | else: 298 | return False 299 | 300 | def canEditMessage(self, msg_id): 301 | r = self.driver.execute_script("return appMessagesManager.canForwardMessage("+str(msg_id)+");") 302 | if str(r) == "true": 303 | return True 304 | else: 305 | return False 306 | 307 | def back(self): 308 | self.driver.execute_script("appNavigationController.back()") 309 | 310 | def get_currentHash(self): 311 | r = self.driver.execute_script("return appNavigationController.currentHash;") 312 | return str(r) 313 | 314 | def chat_id(self): 315 | chat = self.driver.find_element(By.CSS_SELECTOR, "div.user-title > span:nth-child(1)") 316 | chatid = chat.get_attribute("data-peer-id") 317 | return str(chatid) 318 | 319 | def send_message(self, chat_id, text): 320 | global message_sent 321 | message_sent = True 322 | text = str(text) 323 | text = text.replace('""', '') 324 | text = text.replace("\n", "\\n") 325 | text = text.replace("\"", '\\"') 326 | self.driver.execute_script(f'appMessagesManager.sendText({chat_id}, "{text}")') 327 | sleep(0.5) 328 | try: 329 | res, map = self.onchatupdate() 330 | except: 331 | return None 332 | else: 333 | return res, map 334 | 335 | def reply_to_message(self, text, chatid, msg_id): 336 | global message_sent 337 | message_sent = True 338 | text = str(text) 339 | text = text.replace('""', '') 340 | text = text.replace("\n", "\\n") 341 | text = text.replace("\"", '\\"') 342 | self.driver.execute_script('appMessagesManager.sendText('+str(chatid)+', "'+str(text)+'", { replyToMsgId: '+str(msg_id)+' });') 343 | try: 344 | res, map = self.onchatupdate() 345 | except: 346 | return None 347 | else: 348 | return res, map 349 | 350 | def edit_message(self, textnew, message): 351 | action = ActionChains(self.driver) 352 | action.context_click(on_element = message) 353 | sleep(1) 354 | action.perform() 355 | sleep(1) 356 | try: 357 | edit = self.driver.find_element(By.CSS_SELECTOR, 'div.tgico-edit > div:nth-child(1)') 358 | except: 359 | return "Error in find_edit" 360 | try: 361 | edit.click() 362 | except: 363 | return "Error in click_edit" 364 | try: 365 | map = self.driver.find_element(By.CSS_SELECTOR, 'div.input-message-input:nth-child(1)') 366 | except: 367 | return "Error in find_message_box" 368 | map.send_keys(Keys.CONTROL + 'a') 369 | map.send_keys(Keys.BACKSPACE) 370 | map.send_keys(textnew) 371 | map.send_keys(Keys.ENTER) 372 | 373 | def forward_message(self, target, message, quote): 374 | action = ActionChains(self.driver) 375 | action.context_click(on_element = message) 376 | sleep(1) 377 | action.perform() 378 | sleep(1) 379 | try: 380 | if quote == True: 381 | forward = self.driver.find_element(By.CSS_SELECTOR, 'div.btn-menu-item:nth-child(18)') 382 | elif quote == False: 383 | forward = self.driver.find_element(By.CSS_SELECTOR, 'div.btn-menu-item:nth-child(19)') 384 | except: 385 | return "Error in find_forward" 386 | try: 387 | forward.click() 388 | except: 389 | return "Error in click_forward" 390 | textBox = self.driver.find_element(By.CSS_SELECTOR, '.selector-search-input') 391 | textBox.send_keys(target) 392 | textBox.send_keys(Keys.ENTER) 393 | sleep(1) 394 | try: 395 | forwardtarget = self.driver.find_element(By.CSS_SELECTOR, '.selector > div:nth-child(1) > div:nth-child(1) > ul:nth-child(1) > li:nth-child(1)') 396 | except: 397 | print("Not find a target") 398 | return 399 | forwardtarget.click() 400 | sleep(1) 401 | but = self.driver.find_element(By.CSS_SELECTOR, 'div.input-message-input:nth-child(1)') 402 | but.send_keys(Keys.ENTER) 403 | res, map = self.onchatupdate(self.driver) 404 | return res, map 405 | 406 | def pin_message(self, message): 407 | action = ActionChains(self.driver) 408 | action.context_click(on_element = message) 409 | sleep(1) 410 | action.perform() 411 | sleep(1) 412 | try: 413 | pinbox = self.driver.find_element(By.CSS_SELECTOR, 'div.btn-menu-item:nth-child(18) > div:nth-child(1)') 414 | except: 415 | return "Error in find_pin" 416 | try: 417 | pinbox.click() 418 | except: 419 | return "Error in click_pin" 420 | pin = self.driver.find_element(By.CSS_SELECTOR, 'button.btn:nth-child(1) > div:nth-child(1)') 421 | pin.click() 422 | sleep(2) 423 | 424 | def delete_message(self, message): 425 | action = ActionChains(self.driver) 426 | action.context_click(on_element = message) 427 | sleep(1) 428 | action.perform() 429 | sleep(1) 430 | try: 431 | deletebox = self.driver.find_element(By.CSS_SELECTOR, 'div.btn-menu-item:nth-child(26)') 432 | except: 433 | return "Error in find_delete" 434 | try: 435 | deletebox.click() 436 | except: 437 | return "Error in click_delete" 438 | delete = self.driver.find_element(By.CSS_SELECTOR, 'button.btn:nth-child(1) > div:nth-child(1)') 439 | delete.click() 440 | 441 | def search(self, x, text): 442 | search = self.driver.find_element(By.CSS_SELECTOR, '#main-search') 443 | sleep(3) 444 | search.click() 445 | button = self.driver.find_element(By.CSS_SELECTOR, "#search-container > div:nth-child(1) > div:nth-child(1) > nav:nth-child(1) > div:nth-child("+str(x)+")") 446 | button.click() 447 | searchbox = self.driver.find_element(By.XPATH, '/html/body/div[2]/div[1]/div[1]/div/div/div[1]/div[2]/input') 448 | sleep(4) 449 | searchbox.send_keys(text) 450 | sleep(1) 451 | tab = self.driver.find_element(By.CSS_SELECTOR, ".search-super-tabs > div:nth-child("+str(x)+")") 452 | tab.click() 453 | try: 454 | chat = self.driver.find_element(By.XPATH, "/html/body/div[2]/div[1]/div[1]/div/div/div[2]/div[2]/div[3]/div/div/div["+str(x)+"]/div/div[1]/ul/li[1]") 455 | except: 456 | return "Not Found !" 457 | else: 458 | try: 459 | message_id = chat.get_attribute("data-mid") 460 | except: 461 | chat.click() 462 | else: 463 | chat.click() 464 | return message_id 465 | 466 | def FindActiveFolderTabs(self): 467 | elements = self.driver.find_element(By.CSS_SELECTOR, '.menu-horizontal-div .menu-horizontal-div-item.rp') 468 | 469 | index = None 470 | for i, el in enumerate(elements): 471 | if 'active' in el.get_attribute('class'): 472 | index = i + 1 473 | break 474 | 475 | return int(index) 476 | 477 | def on_new_message(self, chat): 478 | try: 479 | chat = self.driver.find_element(By.CSS_SELECTOR, "li.chatlist-chat:nth-child("+str(chat)+")") 480 | except: 481 | return "not found chat" 482 | cp = chat.find_element(By.CLASS_NAME, "user-caption") 483 | sub = cp.find_element(By.CLASS_NAME, "dialog-subtitle") 484 | try: 485 | bubble = sub.find_element(By.CLASS_NAME, "dialog-subtitle-badge") 486 | bubbletext = str(bubble.get_attribute('innerHTML')) 487 | except: 488 | return None 489 | else: 490 | chatid = str(chat.get_attribute('data-peer-id')) 491 | chat.click() 492 | sleep(7.5) 493 | chat.click() 494 | sleep(1) 495 | response = {} 496 | for y in range(1, int(int(bubbletext)+1)): 497 | x = int(str("-"+str(y))) 498 | try: 499 | bubble = self.driver.find_elements(By.CLASS_NAME, "bubble")[int(x)] 500 | except: 501 | self.go_chat(chatid) 502 | sleep(10) 503 | try: 504 | bubble = self.driver.find_elements(By.CLASS_NAME, "bubble")[int(x)] 505 | except: 506 | break 507 | message_id = bubble.get_attribute("data-mid") 508 | chatbox = bubble.find_element(By.CLASS_NAME, "bubble-content-wrapper") 509 | day = chatbox.find_element(By.CLASS_NAME, "bubble-content") 510 | try: 511 | namebox = day.find_element(By.CLASS_NAME, "name") 512 | except: 513 | is_from = False 514 | else: 515 | is_from = True 516 | try: 517 | chatid_from = str(namebox.get_attribute('data-peer-id')) 518 | except: 519 | j = namebox.find_element(By.CLASS_NAME, "i18n").text 520 | if "هدایت شده از " in str(j): 521 | is_forward = True 522 | peer_title = namebox.find_element(By.CLASS_NAME, "peer-title") 523 | chatid_from = str(peer_title.get_attribute("data-peer-id")) 524 | name_from = str(peer_title.text) 525 | else: 526 | is_forward = False 527 | else: 528 | is_forward = False 529 | name_from = namebox.find_element(By.CLASS_NAME, "peer-title").text 530 | name = self.driver.find_element(By.CSS_SELECTOR, "div.user-title > span:nth-child(1)").text 531 | try: 532 | map=day.find_element(By.CLASS_NAME, "message") 533 | except: 534 | return "Error in find_message" 535 | try: 536 | doc = map.find_element(By.CLASS_NAME, "document-container") 537 | except: 538 | pass 539 | else: 540 | action = ActionChains(self.driver) 541 | action.context_click(on_element = map) 542 | sleep(1) 543 | action.perform() 544 | sleep(1) 545 | try: 546 | tigo_link = self.driver.find_element(By.CSS_SELECTOR, "div.tgico-link:nth-child(12)") 547 | except: 548 | link = "" 549 | else: 550 | tigo_link.click() 551 | sleep(0.1) 552 | link = str(pyperclip.paste()) 553 | doc2 = doc.find_element(By.CLASS_NAME, "document-wrapper") 554 | audio_element = doc2.find_element(By.TAG_NAME, "audio-element") 555 | btn_play = audio_element.find_element(By.CLASS_NAME, "audio-toggle") 556 | audio_time = audio_element.find_element(By.CLASS_NAME, "audio-time").text 557 | audio_time = str(audio_time).split(":") 558 | audio_time = (int(audio_time[0])*60)+int(audio_time[1]) 559 | active_sessions = self.list_active_sessions() 560 | self.mute_sessions(active_sessions) 561 | btn_play.click() 562 | self.save_audio(audio_time) 563 | self.unmute_sessions(active_sessions) 564 | audio = True 565 | try: 566 | attachment = day.find_element(By.CLASS_NAME, "attachment") 567 | except: 568 | media = False 569 | else: 570 | try: 571 | attachment.click() 572 | except: 573 | media = attachment.find_element(By.CLASS_NAME, "media-photo") 574 | media = media.get_attribute("src") 575 | else: 576 | sleep(0.5) 577 | media = self.driver.find_element(By.CSS_SELECTOR, ".media-viewer-aspecter > img:nth-child(1)") 578 | media = media.get_attribute("src") 579 | btn = self.driver.find_element(By.CLASS_NAME, "media-viewer-buttons") 580 | btn.find_element(By.CLASS_NAME, "tgico-close").click() 581 | try: 582 | video_time = attachment.find_element(By.CLASS_NAME, "video-time") 583 | except: 584 | is_video = False 585 | else: 586 | is_video = True 587 | video_time = str(video_time.text) 588 | try: 589 | reply = day.find_element(By.CLASS_NAME, "reply") 590 | except: 591 | reply = False 592 | else: 593 | reply = reply.find_element(By.CLASS_NAME, "reply-content") 594 | reply = reply.get_attribute("innerHTML") 595 | time_tgico = map.find_element(By.TAG_NAME, "span") 596 | time_inner = time_tgico.find_element(By.CLASS_NAME, "i18n").text 597 | if str(time_inner) == "": 598 | is_from_me = False 599 | else: 600 | is_from_me = True 601 | time = time_tgico.get_attribute("title") 602 | try: 603 | view_message = time_tgico.find_element(By.CLASS_NAME, "post-views").text 604 | except: 605 | view_message = False 606 | text = str(map.text) 607 | text = text.split("\n"+str(time_inner))[0] 608 | response2 = { 609 | "result"+str(x):{ 610 | "message_id":str(message_id), 611 | "link":str(link), 612 | "chat":{ 613 | "id":str(chatid), 614 | "title":str(name), 615 | "username":str(self.getPeerUsername(chatid)), 616 | "type":str(self.getDialogType(chatid)) 617 | }, 618 | } 619 | } 620 | if audio: 621 | new_data = { 622 | "audio":{ 623 | "output_file":"output.mp3", 624 | "audio_time":int(audio_time) 625 | } 626 | } 627 | response2["result"+str(x)].update(new_data) 628 | if media: 629 | new_data = { 630 | "media":{ 631 | "media-src": str(media) 632 | } 633 | } 634 | response2["result"+str(x)].update(new_data) 635 | if is_video: 636 | new_data = { 637 | "video":{ 638 | "video-time":str(video_time) 639 | } 640 | } 641 | response2["result"+str(x)]["media"].update(new_data) 642 | if is_from: 643 | new_data = { 644 | "from":{ 645 | "is_forward":is_forward, 646 | "id":str(chatid_from), 647 | "name":str(name_from), 648 | "username":str(self.getPeerUsername(chatid_from)), 649 | "type":str(self.getDialogType(chatid_from)) 650 | } 651 | } 652 | response2["result"+str(x)].update(new_data) 653 | if reply: 654 | new_data = { 655 | "reply":{ 656 | "reply-content": str(reply) 657 | } 658 | } 659 | response2["result"+str(x)].update(new_data) 660 | if view_message: 661 | new_data = { 662 | "date":str(time), 663 | "text":str(text), 664 | "view":str(view_message) 665 | } 666 | else: 667 | new_data = { 668 | "date":str(time), 669 | "text":str(text), 670 | "is_from_me":is_from_me 671 | } 672 | response2["result"+str(x)].update(new_data) 673 | response.update(response2) 674 | return response, map 675 | 676 | def on_all_message(self, chat): 677 | try: 678 | chat = self.driver.find_element(By.CSS_SELECTOR, "li.chatlist-chat:nth-child("+str(chat)+")") 679 | except: 680 | return "not found chat" 681 | cp = chat.find_element(By.CLASS_NAME, "user-caption") 682 | sub = cp.find_element(By.CLASS_NAME, "dialog-subtitle") 683 | try: 684 | bubble = sub.find_element(By.CLASS_NAME, "dialog-subtitle-badge") 685 | bubbletext = str(bubble.get_attribute('innerHTML')) 686 | except: 687 | pass 688 | chatid = str(chat.get_attribute('data-peer-id')) 689 | chat.click() 690 | sleep(7.5) 691 | chat.click() 692 | sleep(1) 693 | response = {} 694 | y = 0 695 | while True: 696 | y += 1 697 | x = int(str("-"+str(y))) 698 | try: 699 | bubble = self.driver.find_elements(By.CLASS_NAME, "bubble")[int(x)] 700 | except: 701 | self.go_chat(chatid) 702 | sleep(10) 703 | try: 704 | bubble = self.driver.find_elements(By.CLASS_NAME, "bubble")[int(x)] 705 | except: 706 | break 707 | message_id = bubble.get_attribute("data-mid") 708 | try: 709 | chatbox = bubble.find_element(By.CLASS_NAME, "bubble-content-wrapper") 710 | except: 711 | continue 712 | day = chatbox.find_element(By.CLASS_NAME, "bubble-content") 713 | try: 714 | namebox = day.find_element(By.CLASS_NAME, "name") 715 | except: 716 | is_from = False 717 | else: 718 | is_from = True 719 | try: 720 | chatid_from = str(namebox.get_attribute('data-peer-id')) 721 | except: 722 | j = namebox.find_element(By.CLASS_NAME, "i18n").text 723 | if "هدایت شده از " in str(j): 724 | is_forward = True 725 | peer_title = namebox.find_element(By.CLASS_NAME, "peer-title") 726 | chatid_from = str(peer_title.get_attribute("data-peer-id")) 727 | name_from = str(peer_title.text) 728 | else: 729 | is_forward = False 730 | else: 731 | is_forward = False 732 | name_from = namebox.find_element(By.CLASS_NAME, "peer-title").text 733 | name = self.driver.find_element(By.CSS_SELECTOR, "div.user-title > span:nth-child(1)").text 734 | try: 735 | map=day.find_element(By.CLASS_NAME, "message") 736 | except: 737 | return "Error in find_message" 738 | try: 739 | doc = map.find_element(By.CLASS_NAME, "document-container") 740 | except: 741 | pass 742 | else: 743 | action = ActionChains(self.driver) 744 | action.context_click(on_element = map) 745 | sleep(1) 746 | action.perform() 747 | sleep(1) 748 | try: 749 | tigo_link = self.driver.find_element(By.CSS_SELECTOR, "div.tgico-link:nth-child(12)") 750 | except: 751 | link = "" 752 | else: 753 | tigo_link.click() 754 | sleep(0.1) 755 | link = str(pyperclip.paste()) 756 | doc2 = doc.find_element(By.CLASS_NAME, "document-wrapper") 757 | audio_element = doc2.find_element(By.TAG_NAME, "audio-element") 758 | btn_play = audio_element.find_element(By.CLASS_NAME, "audio-toggle") 759 | audio_time = audio_element.find_element(By.CLASS_NAME, "audio-time").text 760 | audio_time = str(audio_time).split(":") 761 | audio_time = (int(audio_time[0])*60)+int(audio_time[1]) 762 | active_sessions = self.list_active_sessions() 763 | self.mute_sessions(active_sessions) 764 | btn_play.click() 765 | self.save_audio(audio_time) 766 | self.unmute_sessions(active_sessions) 767 | audio = True 768 | try: 769 | attachment = day.find_element(By.CLASS_NAME, "attachment") 770 | except: 771 | media = False 772 | else: 773 | media = attachment.find_element(By.CLASS_NAME, "media-photo") 774 | media = media.get_attribute("src") 775 | try: 776 | video_time = attachment.find_element(By.CLASS_NAME, "video-time") 777 | except: 778 | is_video = False 779 | else: 780 | is_video = True 781 | video_time = str(video_time.text) 782 | try: 783 | reply = day.find_element(By.CLASS_NAME, "reply") 784 | except: 785 | reply = False 786 | else: 787 | reply = reply.find_element(By.CLASS_NAME, "reply-content") 788 | reply = reply.get_attribute("innerHTML") 789 | time_tgico = map.find_element(By.TAG_NAME, "span") 790 | time_inner = time_tgico.find_element(By.CLASS_NAME, "inner").get_attribute("innerHTML").split("")[1] 791 | if str(time_inner) == "": 792 | is_from_me = False 793 | else: 794 | is_from_me = True 795 | time = time_tgico.get_attribute("title") 796 | try: 797 | view_message = time_tgico.find_element(By.CLASS_NAME, "post-views").text 798 | except: 799 | view_message = False 800 | text = str(map.text) 801 | response2 = { 802 | "result"+str(x):{ 803 | "message_id":str(message_id), 804 | "link":str(link), 805 | "chat":{ 806 | "id":str(chatid), 807 | "title":str(name), 808 | "username":str(self.getPeerUsername(chatid)), 809 | "type":str(self.getDialogType(chatid)) 810 | }, 811 | } 812 | } 813 | if audio: 814 | new_data = { 815 | "audio":{ 816 | "output_file":"output.mp3", 817 | "audio_time":int(audio_time) 818 | } 819 | } 820 | response2["result"+str(x)].update(new_data) 821 | if media: 822 | new_data = { 823 | "media":{ 824 | "media-src": str(media) 825 | } 826 | } 827 | response2["result"+str(x)].update(new_data) 828 | if is_video: 829 | new_data = { 830 | "video":{ 831 | "video-time":str(video_time) 832 | } 833 | } 834 | response2["result"+str(x)]["media"].update(new_data) 835 | if is_from: 836 | new_data = { 837 | "from":{ 838 | "is_forward":is_forward, 839 | "is_from_me":is_from_me, 840 | "id":str(chatid_from), 841 | "name":str(name_from), 842 | "username":str(self.getPeerUsername(chatid_from)), 843 | "type":str(self.getDialogType(chatid_from)) 844 | } 845 | } 846 | response2["result"+str(x)].update(new_data) 847 | if reply: 848 | new_data = { 849 | "reply":{ 850 | "reply-content": str(reply) 851 | } 852 | } 853 | response2["result"+str(x)].update(new_data) 854 | if view_message: 855 | new_data = { 856 | "date":str(time), 857 | "text":str(text), 858 | "view":str(view_message) 859 | } 860 | else: 861 | new_data = { 862 | "date":str(time), 863 | "text":str(text), 864 | "is_from_me":is_from_me 865 | } 866 | if bubbletext: 867 | if int(bubbletext) >= int(y): 868 | new_data = { 869 | "unread":True, 870 | } 871 | else: 872 | new_data = { 873 | "unread":False, 874 | } 875 | response2["result"+str(x)].update(new_data) 876 | response.update(response2) 877 | return response, map 878 | 879 | def get_info(self, chat_id): 880 | s = self.driver.find_element(By.CSS_SELECTOR, "div.sidebar-header:nth-child(2)") 881 | s.click() 882 | sleep(1) 883 | try: 884 | username = self.driver.find_element(By.CSS_SELECTOR, ".tgico-username") 885 | except: 886 | username = False 887 | else: 888 | username = str(username.text) 889 | try: 890 | bio = self.driver.find_element(By.CSS_SELECTOR, ".tgico-info") 891 | except: 892 | bio = False 893 | else: 894 | bio = str(bio.text) 895 | name = self.driver.find_element(By.CSS_SELECTOR, ".profile-name > span:nth-child(1)") 896 | name = str(name.text) 897 | status = self.driver.find_element(By.CSS_SELECTOR, ".profile-subtitle > span:nth-child(1)") 898 | status = str(status.text) 899 | try: 900 | phone = self.driver.find_element(By.CSS_SELECTOR, ".tgico-phone") 901 | except: 902 | phone = False 903 | else: 904 | phone = str(phone.text) 905 | result = { 906 | 'name':str(name), 907 | 'status':str(status), 908 | 'bio':str(bio), 909 | 'phone':str(phone), 910 | 'username':str(username), 911 | 'chat_id':str(chat_id), 912 | } 913 | return str(result) 914 | 915 | def sendChatActionThread(self): 916 | global message_sent 917 | message_sent = False 918 | try: 919 | map = self.driver.find_element(By.CSS_SELECTOR, 'div.input-message-input:nth-child(1)') 920 | except: 921 | return "Error in find_message_box" 922 | while not message_sent: 923 | map.send_keys("s") 924 | map.send_keys(Keys.CONTROL + 'a') 925 | map.send_keys(Keys.BACKSPACE) 926 | 927 | def sendChatAction(self, chatid): 928 | self.go_chat(chatid) 929 | thread = threading.Thread(target=self.sendChatActionThread) 930 | thread.start() 931 | 932 | def getMe(api): 933 | req = get("https://eitaayar.ir/api/"+api+"/getMe") 934 | return str(req.text) 935 | 936 | def create_channel(self, name:str, bio:str): 937 | menu = self.driver.find_element(By.CSS_SELECTOR, "#new-menu") 938 | menu.click() 939 | newchannel = self.driver.find_element(By.CSS_SELECTOR, ".tgico-newchannel") 940 | newchannel.click() 941 | sleep(1) 942 | name_channel = self.driver.find_element(By.CSS_SELECTOR, "div.input-wrapper:nth-child(2) > div:nth-child(1) > div:nth-child(1)") 943 | name_channel.send_keys(name) 944 | bio_channel = self.driver.find_element(By.CSS_SELECTOR, "div.input-wrapper:nth-child(2) > div:nth-child(2) > div:nth-child(1)") 945 | bio_channel.send_keys(bio) 946 | next = self.driver.find_element(By.CSS_SELECTOR, ".tgico-arrow_next") 947 | next.click() 948 | sleep(1) 949 | next2 = self.driver.find_element(By.CSS_SELECTOR, "button.btn-circle:nth-child(1)") 950 | sleep(1) 951 | next2.click() 952 | self.send_message(self.driver, ".") 953 | chat_id = chat_id(False, True, self.driver) 954 | result = { 955 | 'name':str(name), 956 | 'bio':str(bio), 957 | 'chat_id':str(chat_id), 958 | } 959 | return str(result) 960 | 961 | def folders_tabs(self, x): 962 | s = self.driver.find_element(By.CSS_SELECTOR, "#folders-tabs > div:nth-child("+str(x)+")") 963 | s.click() 964 | sleep(3.5) 965 | 966 | def contactMessage(self, map): 967 | try: 968 | c = map.find_element(By.CLASS_NAME, "contact") 969 | except: 970 | return False 971 | chat_id = c.get_attribute("data-peer-id") 972 | d = c.find_element(By.CLASS_NAME, "contact-details") 973 | name = d.find_element(By.CLASS_NAME, "contact-name") 974 | number = d.find_element(By.CLASS_NAME, "contact-number") 975 | return str(name.text), str(number.text), str(chat_id) 976 | 977 | def send_album(self, filepath, caption, Send_compressed): 978 | global message_sent 979 | message_sent = True 980 | n = 3 981 | for i in filepath: 982 | n += 1 983 | image = Image.open(i) 984 | output = BytesIO() 985 | image.convert("RGB").save(output, "BMP") 986 | data = output.getvalue()[14:] 987 | output.close() 988 | self.send_to_clipboard(win32clipboard.CF_DIB, data) 989 | map = self.driver.find_element(By.CSS_SELECTOR, 'div.input-message-input:nth-child(1)') 990 | map.send_keys(Keys.CONTROL + 'v') 991 | sleep(1) 992 | btn = self.driver.find_element(By.XPATH, "//span[contains(., 'ارسال به صورت فشرده')]") 993 | title = self.driver.find_element(By.CSS_SELECTOR, ".popup-title > span:nth-child(1)") 994 | if Send_compressed: 995 | if str(title.text) == "ارسال عکس": 996 | pass 997 | else: 998 | if str(title.text) == "ارسال عکس": 999 | btn.click() 1000 | try: 1001 | caption2 = self.driver.find_element(By.CSS_SELECTOR, "div.input-field-input") 1002 | caption2.click() 1003 | except: 1004 | caption2 = self.driver.find_element(By.CSS_SELECTOR, "div.input-field:nth-child("+str(n)+") > div:nth-child(1)") 1005 | caption2.click() 1006 | caption2.send_keys(caption) 1007 | send = self.driver.find_element(By.CSS_SELECTOR, "button.btn-primary:nth-child(3)") 1008 | send.click() 1009 | 1010 | def send_other(self, path, caption, Send_compressed): 1011 | global message_sent 1012 | message_sent = True 1013 | n = 3 1014 | for i in path: 1015 | self.copy_to_clipboard(str(i)) 1016 | map = self.driver.find_element(By.CSS_SELECTOR, 'div.input-message-input:nth-child(1)') 1017 | map.send_keys(Keys.CONTROL + 'v') 1018 | n += 1 1019 | sleep(1) 1020 | btn = self.driver.find_element(By.XPATH, "//span[contains(., 'ارسال به صورت فشرده')]") 1021 | title = self.driver.find_element(By.CSS_SELECTOR, ".popup-title > span:nth-child(1)") 1022 | if Send_compressed: 1023 | if str(title.text) == "ارسال عکس": 1024 | pass 1025 | else: 1026 | if str(title.text) == "ارسال عکس": 1027 | btn.click() 1028 | try: 1029 | caption2 = self.driver.find_element(By.CSS_SELECTOR, "div.input-field-input") 1030 | caption2.click() 1031 | except: 1032 | caption2 = self.driver.find_element(By.CSS_SELECTOR, "div.input-field:nth-child("+str(n)+") > div:nth-child(1)") 1033 | caption2.click() 1034 | caption2.send_keys(caption) 1035 | send = self.driver.find_element(By.CSS_SELECTOR, "button.btn-primary:nth-child(3)") 1036 | send.click() 1037 | 1038 | def onchatupdate(self): 1039 | chatid = self.chat_id() 1040 | try: 1041 | bubble = self.driver.find_elements(By.CLASS_NAME, "bubble")[-1] 1042 | except: 1043 | self.go_chat(chatid) 1044 | sleep(10) 1045 | try: 1046 | bubble = self.driver.find_elements(By.CLASS_NAME, "bubble")[-1] 1047 | except: 1048 | return None 1049 | message_id = bubble.get_attribute("data-mid") 1050 | chatbox = bubble.find_element(By.CLASS_NAME, "bubble-content-wrapper") 1051 | day = chatbox.find_element(By.CLASS_NAME, "bubble-content") 1052 | try: 1053 | namebox = day.find_element(By.CLASS_NAME, "name") 1054 | except: 1055 | is_from = False 1056 | else: 1057 | is_from = True 1058 | try: 1059 | chatid_from = str(namebox.get_attribute('data-peer-id')) 1060 | except: 1061 | j = namebox.find_element(By.CLASS_NAME, "i18n").text 1062 | if "هدایت شده از " in str(j): 1063 | is_forward = True 1064 | peer_title = namebox.find_element(By.CLASS_NAME, "peer-title") 1065 | chatid_from = str(peer_title.get_attribute("data-peer-id")) 1066 | name_from = str(peer_title.text) 1067 | else: 1068 | is_forward = False 1069 | else: 1070 | is_forward = False 1071 | name_from = namebox.find_element(By.CLASS_NAME, "peer-title").text 1072 | name = self.driver.find_element(By.CSS_SELECTOR, "div.user-title > span:nth-child(1)").text 1073 | try: 1074 | map=day.find_element(By.CLASS_NAME, "message") 1075 | except: 1076 | return "Error in find_message" 1077 | action = ActionChains(self.driver) 1078 | action.context_click(on_element = map) 1079 | sleep(1) 1080 | action.perform() 1081 | sleep(1) 1082 | try: 1083 | tigo_link = self.driver.find_element(By.CSS_SELECTOR, "div.tgico-link:nth-child(12)") 1084 | except: 1085 | link = "" 1086 | else: 1087 | tigo_link.click() 1088 | sleep(0.1) 1089 | link = str(pyperclip.paste()) 1090 | try: 1091 | attachment = day.find_element(By.CLASS_NAME, "attachment") 1092 | except: 1093 | media = False 1094 | else: 1095 | media = attachment.find_element(By.CLASS_NAME, "media-photo") 1096 | media = media.get_attribute("src") 1097 | try: 1098 | video_time = attachment.find_element(By.CLASS_NAME, "video-time") 1099 | except: 1100 | is_video = False 1101 | else: 1102 | is_video = True 1103 | video_time = str(video_time.text) 1104 | try: 1105 | reply = day.find_element(By.CLASS_NAME, "reply") 1106 | except: 1107 | reply = False 1108 | else: 1109 | reply = reply.find_element(By.CLASS_NAME, "reply-content") 1110 | reply = reply.get_attribute("innerHTML") 1111 | time_tgico = map.find_element(By.TAG_NAME, "span") 1112 | time_inner = time_tgico.find_element(By.CLASS_NAME, "i18n").text 1113 | if str(time_inner) == "": 1114 | is_from_me = False 1115 | else: 1116 | is_from_me = True 1117 | time = time_tgico.get_attribute("title") 1118 | try: 1119 | view_message = time_tgico.find_element(By.CLASS_NAME, "post-views").text 1120 | except: 1121 | view_message = False 1122 | text = str(map.text) 1123 | text = text.split("\n"+str(time_inner))[0] 1124 | response2 = { 1125 | "result":{ 1126 | "message_id":str(message_id), 1127 | "link":str(link), 1128 | "chat":{ 1129 | "id":str(chatid), 1130 | "title":str(name), 1131 | "username":str(self.getPeerUsername(chatid)), 1132 | "type":str(self.getDialogType(chatid)) 1133 | }, 1134 | } 1135 | } 1136 | if media: 1137 | new_data = { 1138 | "media":{ 1139 | "media-src": str(media) 1140 | } 1141 | } 1142 | response2["result"].update(new_data) 1143 | if is_video: 1144 | new_data = { 1145 | "video":{ 1146 | "video-time":str(video_time) 1147 | } 1148 | } 1149 | response2["result"]["media"].update(new_data) 1150 | if is_from: 1151 | new_data = { 1152 | "from":{ 1153 | "is_forward":is_forward, 1154 | "id":str(chatid_from), 1155 | "name":str(name_from), 1156 | "username":str(self.getPeerUsername(chatid_from)), 1157 | "type":str(self.getDialogType(chatid_from)) 1158 | } 1159 | } 1160 | response2["result"].update(new_data) 1161 | if reply: 1162 | new_data = { 1163 | "reply":{ 1164 | "reply-content": str(reply) 1165 | } 1166 | } 1167 | response2["result"].update(new_data) 1168 | if view_message: 1169 | new_data = { 1170 | "date":str(time), 1171 | "text":str(text), 1172 | "is_from_me":is_from_me, 1173 | "view":str(view_message) 1174 | } 1175 | else: 1176 | new_data = { 1177 | "date":str(time), 1178 | "text":str(text), 1179 | "is_from_me":is_from_me 1180 | } 1181 | response2["result"].update(new_data) 1182 | return response2, map 1183 | 1184 | def driver_command(text, command): 1185 | command = "//" + str(command) 1186 | if str(text) == str(command): 1187 | return True 1188 | else: 1189 | return False 1190 | 1191 | def get_user_photos(self): 1192 | bar = self.driver.find_element(By.CSS_SELECTOR, "div.sidebar-header:nth-child(2)") 1193 | bar.click() 1194 | b = 0 1195 | s = 0 1196 | d = "" 1197 | while b!=1: 1198 | s = s + 1 1199 | try: 1200 | photo = self.driver.find_element(By.CSS_SELECTOR, "div.profile-avatars-avatar:nth-child("+str(s)+") > img:nth-child(1)") 1201 | except: 1202 | b=1 1203 | l = photo.get_attribute('src') 1204 | d = d + str(l) + "," 1205 | return str(d) 1206 | 1207 | def ban_user(self): 1208 | s = self.driver.find_element(By.CSS_SELECTOR, "div.btn-icon:nth-child(6)") 1209 | s.click() 1210 | b = self.driver.find_element(By.CSS_SELECTOR, ".tgico-lock") 1211 | b.click() 1212 | 1213 | def add_user(self): 1214 | s = self.driver.find_element(By.CSS_SELECTOR, "div.btn-icon:nth-child(6)") 1215 | s.click() 1216 | b = self.driver.find_element(By.CSS_SELECTOR, ".tgico-adduser") 1217 | b.click() 1218 | 1219 | def delete_chat(self): 1220 | s = self.driver.find_element(By.CSS_SELECTOR, "div.btn-icon:nth-child(6)") 1221 | s.click() 1222 | b = self.driver.find_element(By.CSS_SELECTOR, "div.tgico-delete:nth-child(12)") 1223 | b.click() 1224 | 1225 | def edit_about(self, chat_id, text): 1226 | self.driver.execute_script('appChatsManager.editAbout('+str(chat_id)+', "'+str(text)+'")') 1227 | 1228 | def onsubtitlechat(self, chat): 1229 | chat = self.driver.find_element(By.CSS_SELECTOR, "li.chatlist-chat:nth-child("+str(chat)+")") 1230 | chatid = chat.get_attribute("data-peer-id") 1231 | cp = chat.find_element(By.CLASS_NAME, "user-caption") 1232 | sub = cp.find_element(By.CLASS_NAME, "dialog-subtitle") 1233 | dialog_title = cp.find_element(By.CLASS_NAME, "dialog-title") 1234 | user_title = dialog_title.find_element(By.CLASS_NAME, "user-title") 1235 | name = user_title.find_element(By.CLASS_NAME, "peer-title").text 1236 | dialog_title_details = dialog_title.find_element(By.CLASS_NAME, "dialog-title-details") 1237 | tigo = dialog_title_details.find_element(By.CLASS_NAME, "message-status").get_attribute("innerHTML") 1238 | if str(tigo) == "": 1239 | is_message_me = False 1240 | else: 1241 | is_message_me = True 1242 | subtitle = sub.find_element(By.CLASS_NAME, "user-last-message").text 1243 | message_time = dialog_title_details.find_element(By.CLASS_NAME, "message-time") 1244 | time = message_time.find_element(By.CLASS_NAME, "i18n").text 1245 | try: 1246 | bubble = sub.find_element(By.CLASS_NAME, "dialog-subtitle-badge") 1247 | bubbletext = str(bubble.get_attribute('innerHTML')) 1248 | except: 1249 | read = True 1250 | else: 1251 | read = False 1252 | return str(subtitle), str(chatid), str(name), is_message_me, str(time), read 1253 | 1254 | def get_message(self, message_id): 1255 | message = self.driver.find_element(By.XPATH, '//div[@data-mid="'+str(message_id)+'"]') 1256 | chatbox = message.find_elements(By.CLASS_NAME, "bubble-content-wrapper") 1257 | day = chatbox.find_element(By.CLASS_NAME, "bubble-content") 1258 | namebox = day.find_element(By.CLASS_NAME, "name") 1259 | name = namebox.find_element(By.CLASS_NAME, "peer-title").text 1260 | try: 1261 | map=day.find_element(By.CLASS_NAME, "message") 1262 | except: 1263 | return "Error in find_message" 1264 | text = str(map.text) 1265 | return str(text), str(name), str(message_id), map 1266 | 1267 | def messageIdtoMap(self, message_id): 1268 | message = self.driver.find_element(By.XPATH, '//div[@data-mid="'+str(message_id)+'"]') 1269 | chatbox = message.find_elements(By.CLASS_NAME, "bubble-content-wrapper") 1270 | day = chatbox.find_element(By.CLASS_NAME, "bubble-content") 1271 | try: 1272 | map=day.find_element(By.CLASS_NAME, "message") 1273 | except: 1274 | return "Error in find_message" 1275 | else: 1276 | return map 1277 | 1278 | def add_contact(self, num, name): 1279 | menu = self.driver.find_element(By.CSS_SELECTOR, "#new-menu") 1280 | menu.click() 1281 | newchannel = self.driver.find_element(By.CSS_SELECTOR, ".tgico-newprivate") 1282 | newchannel.click() 1283 | sleep(1) 1284 | bo2 = self.driver.find_element(By.CSS_SELECTOR, "button.btn-circle:nth-child(3) > div:nth-child(1)") 1285 | bo2.click() 1286 | num = str(num) 1287 | if num[0:3] == "098": 1288 | num = num[1:] 1289 | elif num[0] == "0": 1290 | num = "98" + num[1:] 1291 | elif num[0] == "+": 1292 | num = num.replace("+", "") 1293 | elif num[0:2] == "98": 1294 | pass 1295 | else: 1296 | return 1297 | bo2 = self.driver.find_element(By.CSS_SELECTOR, "button.btn-circle:nth-child(3) > div:nth-child(1)") 1298 | try: 1299 | bo2.click() 1300 | except: 1301 | pass 1302 | te = self.driver.find_element(By.CSS_SELECTOR, "div.input-field:nth-child(3) > div:nth-child(1)") 1303 | te.send_keys(Keys.CONTROL + 'a') 1304 | te.send_keys(Keys.BACKSPACE) 1305 | te.send_keys(num) 1306 | te1 = self.driver.find_element(By.CSS_SELECTOR, ".name-fields > div:nth-child(1) > div:nth-child(1)") 1307 | te1.send_keys(Keys.CONTROL + 'a') 1308 | te1.send_keys(Keys.BACKSPACE) 1309 | te1.send_keys(name) 1310 | bo3 = self.driver.find_element(By.CSS_SELECTOR, "button.btn-primary:nth-child(3)") 1311 | bo3.click() 1312 | sleep(1) 1313 | try: 1314 | rr = self.driver.find_element(By.CSS_SELECTOR, ".toast") 1315 | except: 1316 | te3 = self.driver.find_element(By.CSS_SELECTOR, "#contacts-container > div:nth-child(1) > div:nth-child(2) > input:nth-child(1)") 1317 | te3.send_keys(Keys.CONTROL + 'a') 1318 | te3.send_keys(Keys.BACKSPACE) 1319 | sleep(1) 1320 | te3.send_keys(name) 1321 | sleep(1) 1322 | for i in range(10): 1323 | try: 1324 | rr = self.driver.find_element(By.CSS_SELECTOR, "#contacts > li:nth-child("+str(i)+")") 1325 | except: 1326 | return 1327 | else: 1328 | rrr = self.driver.find_element(By.CSS_SELECTOR, "#contacts > li:nth-child("+str(i)+") > div:nth-child(3) > p:nth-child(1) > span:nth-child(1) > span:nth-child(2)").text 1329 | if str(name) == str(rrr): 1330 | chatid = rr.get_attribute("data-peer-id") 1331 | return str(chatid) 1332 | else: 1333 | continue 1334 | 1335 | def go_chat(self, id): 1336 | self.driver.get("https://web.eitaa.com/#"+str(id)) 1337 | sleep(3) 1338 | 1339 | def load_all_contacts(self, x): 1340 | n = 1 1341 | chatids = [] 1342 | for i in range(int(x)): 1343 | try: 1344 | contact = self.driver.find_element(By.CSS_SELECTOR, "#contacts > li:nth-child("+str(n)+")") 1345 | except: 1346 | self.driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") 1347 | continue 1348 | chatid = contact.get_attribute("data-peer-id") 1349 | chatids.append(str(chatid)) 1350 | n += 1 1351 | return chatids 1352 | 1353 | def go_settings(self): 1354 | t = self.driver.find_element(By.CSS_SELECTOR, "div.btn-icon:nth-child(2)") 1355 | t.click() 1356 | t2 = self.driver.find_element(By.CSS_SELECTOR, ".tgico-settings") 1357 | t2.click() 1358 | sleep(1) 1359 | 1360 | def go_edit_chat(self): 1361 | try: 1362 | tigo_edit = self.driver.find_element(By.CSS_SELECTOR, "button.tgico-edit") 1363 | tigo_edit.click() 1364 | except: 1365 | return 1366 | sleep(1) 1367 | 1368 | def edit_my_about(self, text): 1369 | sleep(0.2) 1370 | try: 1371 | t3 = self.driver.find_element(By.CSS_SELECTOR, "button.tgico-edit:nth-child(3)") 1372 | t3.click() 1373 | except: 1374 | return 1375 | sleep(1) 1376 | 1377 | def go_sidebar_chat(self): 1378 | tab_bar = self.driver.find_element(By.CSS_SELECTOR, ".content") 1379 | tab_bar.click() 1380 | sleep(1) 1381 | 1382 | def go_members(self): 1383 | t = self.driver.find_element(By.CSS_SELECTOR, "div.sidebar-slider-item:nth-child(2) > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(2)") 1384 | t.click() 1385 | sleep(1) 1386 | 1387 | def get_members(self, id, map): 1388 | n = 1 1389 | members = [] 1390 | 1391 | while True: 1392 | try: 1393 | t2 = self.driver.find_element(By.XPATH, "/html/body/div[2]/div/div[3]/div/div[3]/div[2]/div[2]/div/div/ul/li["+str(n)+"]") 1394 | except: 1395 | if map: 1396 | return members, map 1397 | else: 1398 | return members 1399 | chatid = t2.get_attribute("data-peer-id") 1400 | if id: 1401 | if id == chatid: 1402 | map = t2 1403 | members.append(str(chatid)) 1404 | n += 1 1405 | 1406 | def get_admins(self, id=None): 1407 | n = 1 1408 | admins = [] 1409 | 1410 | while True: 1411 | try: 1412 | t2 = self.driver.find_element(By.XPATH, "/html/body/div[2]/div[1]/div[3]/div/div[3]/div[2]/div[2]/div/div/ul/li["+str(n)+"]") 1413 | except: 1414 | if map: 1415 | return admins, map 1416 | else: 1417 | return admins 1418 | chatid = t2.get_attribute("data-peer-id") 1419 | if id: 1420 | if id == chatid: 1421 | map = t2 1422 | admins.append(str(chatid)) 1423 | n += 1 1424 | 1425 | def add_member(self, target): 1426 | t2 = self.driver.find_element(By.CSS_SELECTOR, "button.is-visible") 1427 | t2.click() 1428 | sleep(1) 1429 | 1430 | for i in target: 1431 | t3 = self.driver.find_element(By.CSS_SELECTOR, ".selector-search-input") 1432 | t3.send_keys(str(i)) 1433 | sleep(1) 1434 | 1435 | t4 = self.driver.find_element(By.CSS_SELECTOR, "div.chatlist-container:nth-child(3) > div:nth-child(1) > ul:nth-child(1) > li:nth-child(1)") 1436 | t4.click() 1437 | sleep(1) 1438 | 1439 | t5 = self.driver.find_element(By.CSS_SELECTOR, "button.btn-circle:nth-child(1)") 1440 | t5.click() 1441 | sleep(1) 1442 | 1443 | t6 = self.driver.find_element(By.CSS_SELECTOR, "button.btn:nth-child(1)") 1444 | t6.click() 1445 | 1446 | def promote_member(self, map, n): 1447 | map.click() 1448 | try: 1449 | t = self.driver.find_element(By.CSS_SELECTOR, ".tgico-promote").click() 1450 | except: 1451 | return 1452 | sleep(1) 1453 | 1454 | for i in n: 1455 | i += 3 1456 | t2 = self.driver.find_element(By.CSS_SELECTOR, "label.row:nth-child("+str(i)+") > div:nth-child(3) > div:nth-child(2) > label:nth-child(1) > div:nth-child(2)") 1457 | if i < 10: 1458 | t2.click().click() 1459 | elif i == 10: 1460 | t2.click() 1461 | else: 1462 | return 1463 | t3 = self.driver.find_element(By.CSS_SELECTOR, "div.sidebar-slider-item:nth-child(4) > div:nth-child(1) > button:nth-child(1)") 1464 | t3.click() 1465 | sleep(1) 1466 | 1467 | def delete_member(self, map): 1468 | map.click() 1469 | try: 1470 | t = self.driver.find_element(By.CSS_SELECTOR, "div.tgico-delete:nth-child(3)").click() 1471 | except: 1472 | return 1473 | 1474 | def edit_admin_rights(self, map, n): 1475 | map.click() 1476 | try: 1477 | t = self.driver.find_element(By.CSS_SELECTOR, "div.tgico-admin:nth-child(2)").click() 1478 | except: 1479 | return 1480 | sleep(1) 1481 | 1482 | for i in n: 1483 | i += 3 1484 | t2 = self.driver.find_element(By.CSS_SELECTOR, "label.row:nth-child("+str(i)+") > div:nth-child(3) > div:nth-child(2) > label:nth-child(1) > div:nth-child(2)") 1485 | if i < 10: 1486 | t2.click().click() 1487 | elif i == 10: 1488 | t2.click() 1489 | else: 1490 | return 1491 | t3 = self.driver.find_element(By.CSS_SELECTOR, "div.sidebar-slider-item:nth-child(4) > div:nth-child(1) > button:nth-child(1)") 1492 | t3.click() 1493 | sleep(1) 1494 | 1495 | def go_administrators(self): 1496 | t = self.driver.find_element(By.CSS_SELECTOR, "div.sidebar-slider-item:nth-child(2) > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(1)") 1497 | t.click() 1498 | sleep(1) 1499 | 1500 | def delete_admin(self, map): 1501 | map.click() 1502 | try: 1503 | t = self.driver.find_element(By.CSS_SELECTOR, "div.tgico-admin:nth-child(2)").click() 1504 | except: 1505 | return 1506 | 1507 | t2 = self.driver.find_element(By.CSS_SELECTOR, "button.tgico-deleteuser") 1508 | t2.click() 1509 | 1510 | def info_tabs(self): 1511 | self.go_settings() 1512 | self.driver.find_element(By.CSS_SELECTOR, "button.profile-button:nth-child(2)") 1513 | sleep(0.2) 1514 | response = {} 1515 | for i in range(2, 12): 1516 | tab = self.driver.find_element(By.CSS_SELECTOR, "div.sidebar-left-section-container:nth-child(5) > div:nth-child(1) > div:nth-child(2) > div:nth-child("+str(i)+")") 1517 | subtitle = tab.find_element(By.CLASS_NAME, "row-subtitle").text 1518 | title = tab.find_element(By.CLASS_NAME, "row-title").text 1519 | data = { 1520 | str(title):{ 1521 | "subtitle":str(subtitle) 1522 | } 1523 | } 1524 | data.update(data) 1525 | return response 1526 | 1527 | def Reset_to_Defaults_Tabs(self): 1528 | self.go_settings() 1529 | self.driver.find_element(By.CSS_SELECTOR, "button.profile-button:nth-child(2)") 1530 | sleep(0.2) 1531 | self.driver.find_element(By.CSS_SELECTOR, "button.btn-color-primary:nth-child(4)") 1532 | 1533 | def cleanup(): 1534 | CoUninitialize() 1535 | 1536 | 1537 | threading.Thread(target=cleanup).start() 1538 | --------------------------------------------------------------------------------