ig_bot/ig_messages.py

159 lines
6.3 KiB
Python
Raw Normal View History

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
import pytesseract
from PIL import Image
import yaml
import logging as log
log.basicConfig(
filename="log.txt",
filemode="a",
level=log.INFO,
format='%(asctime)s - %(name)s - %(levelname)s: %(message)s',
datefmt="%Y-%m-%d %H:%M:%S"
)
MAX_TIMEOUT = 7
def driver_init():
mobile_emulation = {
"deviceMetrics": { "width": 768, "height": 1024, "pixelRatio": 2 },
"userAgent": "Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1"
}
options = webdriver.ChromeOptions()
options.add_experimental_option("mobileEmulation", mobile_emulation)
# options.add_argument("--headless") # Uncomment to run headless
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
return driver
def read_files():
try:
with open("user_config.yaml", "r") as user_stream:
user_config = yaml.safe_load(user_stream)
with open("message_config.yaml", "r") as message_stream:
message_config = yaml.safe_load(message_stream)
# Example of validating expected keys:
if "username" not in user_config or "password" not in user_config:
log.error("User configuration file is missing username or password")
exit(1)
if "username" not in message_config or "message" not in message_config:
log.error("Message configuration file is missing target username or message")
exit(1)
return user_config, message_config
except FileNotFoundError as e:
log.error(f"Configuration file not found: {e}")
exit(1)
except yaml.YAMLError as exc:
log.error(f"Error parsing YAML file: {exc}")
exit(1)
def init(driver):
driver.get("https://www.instagram.com")
log.info("Directed to instagram.com")
def login(driver, user_config):
username = user_config["username"]
password = user_config["password"]
username_input = WebDriverWait(driver, MAX_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//input[@name='username']")))
username_input.send_keys(username)
password_input = WebDriverWait(driver, MAX_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//input[@name='password']")))
password_input.send_keys(password)
login_button = WebDriverWait(driver, MAX_TIMEOUT).until(EC.presence_of_element_located((By.XPATH, "//button[@type='submit']//div[text()='Log in']")))
login_button.click()
log.info("Login info entered, login button clicked")
def accept_cookies(driver):
try:
cookie_button = WebDriverWait(driver, MAX_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Allow all cookies']")))
cookie_button.click()
log.info("Cookies accepted")
WebDriverWait(driver, MAX_TIMEOUT).until(EC.invisibility_of_element_located((By.XPATH, "//button[text()='Allow all cookies']")))
except NoSuchElementException as exc:
log.warn("Accept cookies not needed")
def redirect_to_user_profile(driver, message_config):
driver.get("https://www.instagram.com/" + message_config["username"])
log.info("Redirected to user profile (instagram.com/" + message_config["username"] + ")")
def click_on_message(driver):
try:
message_button = WebDriverWait(driver, MAX_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//div[@role='button' and text()='Message']")))
message_button.click()
log.info("Clicked on \"Message\" button")
except NoSuchElementException as exc:
log.error("You don't have the necessary rights to message this user or there is no user with this username.")
def perform_ocr(image_path):
image = Image.open(image_path)
text = pytesseract.image_to_string(image)
return text
def click_on_message_and_capture(driver):
try:
message_button = WebDriverWait(driver, MAX_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//div[@role='button' and text()='Message']")))
message_button.click()
log.info("Clicked on 'Message' button")
time.sleep(5) # Wait for the message page to fully load or animations to complete
driver.save_screenshot("message_page.png")
log.info("Screenshot of the message page taken")
except NoSuchElementException as exc:
log.error("Message button not found or unable to capture the screen")
def not_save_info(driver):
not_save_login_info = WebDriverWait(driver, MAX_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//div[@role='button' and text()='Not Now']")))
not_save_login_info.click()
log.info("Saving info declined")
def decline_notifications(driver):
try:
notifications = WebDriverWait(driver, MAX_TIMEOUT).until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Not Now']")))
notifications.click()
log.info("Declined notifications")
except NoSuchElementException as exc:
log.warn("Declining notifications not needed")
def send_message(driver, message_config):
send_message_textbox = WebDriverWait(driver, MAX_TIMEOUT).until(EC.presence_of_element_located((By.XPATH, "//div[@role='textbox' and @aria-label='Message']")))
send_message_textbox.send_keys(message_config["message"])
WebDriverWait(driver, MAX_TIMEOUT).until(EC.presence_of_element_located((By.XPATH, "//div[@role='button' and text()='Send']")))
driver.find_element(By.XPATH, "//div[@role='button' and text()='Send']").click()
log.info("Message \"" + message_config["message"] + "\" sent successfully to user " + message_config["username"] + "\n\n")
if __name__ == "__main__":
driver = driver_init()
user_config, message_config = read_files()
init(driver)
accept_cookies(driver)
login(driver, user_config)
not_save_info(driver)
decline_notifications(driver)
redirect_to_user_profile(driver, message_config)
click_on_message_and_capture(driver)
ocr_text = perform_ocr("message_page.png")
print(ocr_text)
driver.close()