﻿# -*- coding: utf-8 -*-
#region imports
import atexit
import time
import pickle
import threading
import inspect
import traceback
import random
import requests
#from subprocess import *
import os
#os.system("pip install selenium-stealth")
#os.system("pip install selenium")
import json
import ctypes
import sys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import mysql.connector
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains
from selenium.common.exceptions import NoSuchElementException
from selenium_stealth import stealth
import colorama
from colorama import Fore, Back, Style
from datetime import datetime
import warnings
colorama.init()
warnings.filterwarnings("ignore")

config = {
  'user': 'su_ama',
  'password': '5@aC_Q?_3aGTc6[A',
  'host': '147.93.5.135',  
  'database': 'su_ma',
  'raise_on_warnings': False,
  'autocommit': True,
  'connect_timeout':20
}

#endregion
#region variables

# Constantes de erro
ERROR_CHALLENGE = 3
ERROR_SUSPENDED = 5
ERROR_AUTH = 3
ERROR_LOGIN = 3
ERROR_2FA = 5
ERROR_CHECKPOINT = 3

# Mapeamento de URLs para erros
URL_ERROR_MAP = {
    '/chall': (ERROR_CHALLENGE, 'Challenge detectado'),
    '/susp': (ERROR_SUSPENDED, 'Conta suspensa'),
    '/acco': (ERROR_LOGIN, 'Deslogado'),
    '/check': (ERROR_CHECKPOINT, 'Checkpoint detectado'),
    '/auth': (ERROR_AUTH, 'Erro de autenticação'),
    '/log': (ERROR_LOGIN, 'Erro de login'),
    '/two': (ERROR_2FA, '2FA requerido'),
    '/challenge': (ERROR_CHALLENGE, 'Challenge detectado')
}

Codigo_Maquina = int(input("Qual o codigo da maquina? (apenas numeros):"))
try:
    dbcon = mysql.connector.connect(**config)
    mycursor = dbcon.cursor(buffered=True,dictionary=True) 
    mycursor.execute("UPDATE maquina_"+str(Codigo_Maquina)+" SET logged=0")        
except:
    pass
Qntd_Navegador = 0
Qntd_Acoes = 0
Qntd_Scroll = 0
Fake_Account = ''
listOfProcessNames = list()
threads = []

def getConfig():
    try:
        global Qntd_Navegador
        global Qntd_Acoes
        global Qntd_Scroll
        global Fake_Account
        global Codigo_Maquina
        dbcon = mysql.connector.connect(**config)
        mycursor = dbcon.cursor(buffered=True,dictionary=True) 
        Query_GetAccount = "SELECT * from configs where maquina = "+str(Codigo_Maquina)+" OR maquina = 0 ORDER BY maquina DESC"
        #print(Fore.GREEN + "Iniciado maquina "+str(Codigo_Maquina) + Fore.WHITE)
        mycursor.execute(Query_GetAccount)            
        if mycursor.rowcount > 0:        
            rows = mycursor.fetchall() 
            Qntd_Navegador = rows[0]['navegadores']            
            Qntd_Acoes = rows[0]['acoes']
            Qntd_Scroll = rows[0]['rolagens']
            Fake_Account = rows[0]['usuariofake']
            print(Fore.YELLOW + "COBAIA "+str(Fake_Account) + Fore.WHITE)
    except:
        #print('Ocorreu alguma exceção no getConfig()')
        functionName = inspect.currentframe().f_code.co_name
        #print(str(functionName)+':  '+str(traceback.format_exc()))        
        return 0   

def verifyRequestPending(browser,account,contaid,counter):
    print("#verifyRequestPending")
    if check_exists_by_xpath(browser,"//*[contains(text(), 'request is pending')]"):
        if check_exists_by_xpath(browser,"//*[contains(text(), 'OK')]"):
            ok_button = browser.find_element("xpath","//button[contains(text(), 'OK')]")
            ActionChains(browser).move_to_element(ok_button).click().perform()
            print("clicou em OK - Request is pending")
            sleep(2)
            # Não chama recursivamente - apenas fecha o modal e continua
            

def followFollowing(browser,account,contaid,counter = 0):
    try:
        global Qntd_Acoes
        global Qntd_Scroll
        print('Acessando o perfil de '+str(account))
        browser.get('https://inst.ws/?https://www.instagram.com/'+str(account))
        sleep(5)
        
        # Verifica erro de página após acessar perfil
        page_error = checkPageErrors(browser, contaid)
        if page_error:
            return 0
        
        #try:
        #    WebDriverWait(browser, 30).until(EC.presence_of_element_located((By.XPATH, ("//a[contains(@href,'/following')]"))))
        #except:
        #    print('Tempo para acessar o perfil excedido. CONEXAO LENTA')
        #    return 0
        if check_exists_by_xpath(browser,"//a[contains(@href,'/following')]"):
            print('Clicou em Following')
            try:
                if (browser.find_element(By.CSS_SELECTOR, "[aria-label='Dismiss']").is_displayed()):
                    ActionChains(browser).move_to_element(browser.find_element(By.CSS_SELECTOR, "[aria-label='Dismiss']")).click().perform()
                    sleep(2)

            except:
                pass
    
            followingbutton = browser.find_element("xpath","//a[contains(@href,'/following')]")
            ActionChains(browser).move_to_element(followingbutton).click().perform()
            sleep(5)
            print('Clicou novamente')
            #try:
            #     followingbutton = browser.find_element("xpath","//a[contains(@href,'/following')]")
            #     ActionChains(browser).move_to_element(followingbutton).click().perform()
            #     print('clicou novamente')
            #except:
            #     pass
            #sleep(3)
            #
            #classe = ''
            if check_exists_by_xpath(browser,"//span[@class='_ap3a _aaco _aacw _aacx _aad7 _aade']"): 
                classe = "//div[contains(@class, 'x9f619 x1n2onr6 x1ja2u2z xdt5ytf x2lah0s x193iq5w xeuugli xamitd3 x78zum5')]//div[text()='Follow']"
                classeUnfollow = "//div[contains(@class, 'x9f619 x1n2onr6 x1ja2u2z xdt5ytf x2lah0s x193iq5w xeuugli xamitd3 x78zum5')]//div[text()='Following']"
            else:
                print(Fore.RED + "Seguidores nao encontrados" + Fore.WHITE)
                accountError(contaid, 8, 'Seguidores não encontrados - Modal não carregou')
                time.sleep(2)
                return 0
            tryTime = 1
            # Encontra o container do popup/modal de Following
            try:
                fBody  = browser.find_element("xpath","//div[@class='_ap3a _aaco _aacw _aad6 _aade']")
            except:
                try:
                    fBody = browser.find_element("xpath","//div[@role='dialog']//div[contains(@style, 'overflow')]")
                except:
                    return 0
            
            scroll = 0
            while scroll < Qntd_Scroll:
                print('Descendo')
                browser.execute_script('arguments[0].scrollTop = arguments[0].scrollTop + arguments[0].offsetHeight;', fBody)
                time.sleep(tryTime)
                scroll += 1
            
            # USA O MÉTODO ANTIGO QUE FUNCIONAVA - busca do browser inteiro
            followlist = browser.find_elements("xpath",classe)
            unFollowList = browser.find_elements("xpath", classeUnfollow)
            
            ja_seguindo = len(unFollowList)
            falta_seguir = Qntd_Acoes - ja_seguindo
            
            print('Perfis com botao Follow: ', len(followlist))
            print('Perfis que o cobaia JA seguia antes (Following): ', ja_seguindo)
            print('Limite configurado para seguir: ', Qntd_Acoes)
            print('Falta seguir: ', falta_seguir)
            
            # Verifica se JÁ atingiu o limite configurado
            if ja_seguindo >= Qntd_Acoes:
                print(Fore.YELLOW + f'Ja esta seguindo {ja_seguindo} perfis - Limite de {Qntd_Acoes} ja atingido!' + Fore.WHITE)
                accountError(contaid, 6, f'Já seguia {ja_seguindo} de {Qntd_Acoes}')  # Erro 6 - Já atingiu o limite de follows
                return 1
            
            # Verifica se não tem nenhum botão Follow disponível
            if len(followlist) == 0:
                print(Fore.YELLOW + 'Nao tem nenhum botao Follow disponivel - todos ja sao Following' + Fore.WHITE)
                return 1
            
            # Inicializa contador de seguidos NESTA execução
            seguidos_agora = 0
                
            
            for follow in followlist:
                # Verifica se já seguiu o suficiente para completar o limite
                if seguidos_agora < falta_seguir:     
                    print('Seguindo ' + str(follow.text))
                    try:
                        # Pega o primeiro botão Follow
                        qtd_follow_antes = len(browser.find_elements("xpath",classe))
                        followbutton = browser.find_elements("xpath",classe)[0]
                        ActionChains(browser).move_to_element(followbutton).click().perform()    
                        time.sleep(round(random.uniform(3,5),4))
                        verifyRequestPending(browser,account,contaid,seguidos_agora)
                        
                        # Verifica se atingiu o limite máximo de follows
                        if 'max limit' in browser.page_source.lower() or 'following the max limit' in browser.page_source.lower():
                            print(Fore.RED + "Erro detectado: Limite maximo de follows atingido" + Fore.WHITE)
                            accountError(contaid, 7, 'Limite máximo do Instagram atingido')
                            return 0
                        
                        if 'Action Blocked' in browser.page_source or 'Try Again Later' in browser.page_source:
                            print(Fore.RED + "Erro detectado: Action Blocked - Try Again Later" + Fore.WHITE)
                            accountError(contaid, 4, 'Action Blocked - Try Again Later')
                            return 0
                        
                        # Conta quantos botões Follow existem DEPOIS de clicar
                        qtd_follow_depois = len(browser.find_elements("xpath",classe))
                        
                        # Verifica se realmente seguiu (se diminuiu a quantidade de botões Follow)
                        if qtd_follow_depois >= qtd_follow_antes:
                            # O botão ainda existe como "Follow", então não seguiu (já estava seguindo)
                            print('Ja seguia anteriormente - botao nao mudou')
                        else:
                            # Realmente seguiu (diminuiu a quantidade de botões Follow)
                            seguidos_agora+=1
                            print(Fore.GREEN + f'Seguiu com sucesso! Total seguidos AGORA: {seguidos_agora}' + Fore.WHITE)
                        
                        #time.sleep(round(random.uniform(5,20),3))
                    except:
                        print('Ja seguia anteriormente')        
                else:
                    break
            
            total_final = ja_seguindo + seguidos_agora
            print(Fore.CYAN + f"Terminou de seguir" + Fore.WHITE)
            print(Fore.CYAN + f"Seguiu AGORA: {seguidos_agora} | Total FINAL: {total_final}/{Qntd_Acoes}" + Fore.WHITE)

            return 1            
        else:
            print(Fore.RED + "Botao following nao encontrado" + Fore.WHITE)
            # Verifica se tem o erro específico do botão Following travado
            if check_exists_by_xpath(browser,"//button[@class=' _aswp _aswr _aswv _asw_ _asx2']//div[text()='Following']"):
                print(Fore.RED + "Erro detectado: Botao Following travado" + Fore.WHITE)
                accountError(contaid, 6, 'Botão Following travado')
            else:
                # Registra erro genérico se não encontrou o botão Following
                accountError(contaid, 8, 'Botão Following não encontrado no perfil')
            return 0            
    except Exception as err:
        #print(Fore.RED + "Chrome fechou sozinho" + Fore.WHITE)
        browser.save_screenshot('imagens/screenie.png')
        functionName = inspect.currentframe().f_code.co_name
        #print(str(functionName)+':  '+str(traceback.format_exc()))        
        return 0   

def check_exists_by_name(browser,name):
        try:

            browser.find_element_by_id(name)

        except NoSuchElementException:

            return False

        return True
    
def check_exists_by_xpath(browser,name):
    try:

        browser.find_element("xpath",name)

    except NoSuchElementException:

        return False

    return True
    
def check_exists_by_class(browser,name):
    try:
        
        browser.find_element_by_class_name(name)

    except NoSuchElementException:

        return False

    return True                 

def checkModalActivity(browser):
    print('checkModalActivity>> Verificando se tem modal!')
    time.sleep(2)
    if 'div role="dialog"' in browser.page_source:
        print('checkModalActivity>> Tem um modal de dialogo!')
        time.sleep(2)
        if "Don't use this activity" in browser.page_source:
            print('checkModalActivity>> Fechando modal!')
            btnModal = browser.find_element(By.XPATH, '//*[contains(text(),"Don\'t use this activity")]')
            ActionChains(browser).move_to_element(btnModal).click().perform()
            time.sleep(2)
            browser.get('https://instagram.com/')
            time.sleep(2)
            # Verifica erro de página
            page_error = checkPageErrors(browser)
            if page_error:
                return page_error
   
def checkThisWasMe(browser):
    print('checkThisWasMe >> Verificando Fui Eu')
    time.sleep(2)
    
    try:
        WebDriverWait(browser, 3).until(
            EC.url_contains("challenge")
        )
        url_contains_substring = True
    except:
        url_contains_substring = False
    
    if url_contains_substring:
        
        try:
            btn = WebDriverWait(browser, 3).until(
                EC.element_to_be_clickable((
                    By.XPATH, 
                    '//div[@role="button" and (contains(., "This Was Me") or contains(., "It was me") or contains(., "Was Me"))]'
                ))
            )
            ActionChains(browser).move_to_element(btn).click().perform()
        except Exception as e:
            return  
        
        time.sleep(2)
        browser.get('https://instagram.com/')
        time.sleep(2)
        # Verifica erro de página
        page_error = checkPageErrors(browser)
        if page_error:
            return page_error
    
    
def checkDismiss(browser):
    print('checkCheckDismiss >> Verificando dismiss')
    time.sleep(2)
    #Dismiss
    if waitElementXpath(browser, '//*[contains(text(), "Dismiss")]', 3):
      btn = browser.find_element(By.XPATH, '//*[contains(text(),"Dismiss")]')
      ActionChains(browser).move_to_element(btn).click().perform()
      time.sleep(2)
      browser.get('https://instagram.com/')
      time.sleep(2)
      # Verifica erro de página
      page_error = checkPageErrors(browser)
      if page_error:
          return page_error
    
def checkWhatHappened(browser):
    print('checkWhatHappened >> Verificando alerta')
    sleep(2)
    #See why close in the x button
    if check_exists_by_xpath(browser, '//*[contains(text(), "See why")]'):
      btn = browser.find_element(By.XPATH, "//div[contains(@style, 'b_gpSL5AsEG')]")
      ActionChains(browser).move_to_element(btn).click().perform()
      sleep(2)
      browser.get('https://instagram.com/')
      sleep(2)
      # Verifica erro de página
      page_error = checkPageErrors(browser)
      if page_error:
          return page_error
      
def checkallowallcookie(browser):
    print('checkallowallcookie >> Verificando cookies by Instagram')
    time.sleep(2)
    #Dismiss
    if waitElementXpath(browser, '//*[contains(text(), "cookies by Instagram")]', 3):
      btn = browser.find_element(By.XPATH, '//*[contains(text(),"Allow all cookies")]')
      ActionChains(browser).move_to_element(btn).click().perform()
      time.sleep(2)
      browser.get('https://instagram.com/')
      time.sleep(2)
      # Verifica erro de página
      page_error = checkPageErrors(browser)
      if page_error:
          return page_error
def waitElementXpath(browser, xpath, timewait=3):
    try:
        wait = WebDriverWait(browser,timewait,poll_frequency=1)
        return wait.until(lambda  x: x.find_element(By.XPATH, xpath))
    except Exception as error:
        return False
def checkSuspect(browser):
    print('checkSuspect >> Verificando atividade suspeita')
    suspect = 'We suspect automated behavior on your account'
    time.sleep(2)
    #Suspect
    if waitElementXpath(browser, f"//*[contains(text(), '{suspect}')]", 3):
      print('Achou o erro suspect')
      btn = browser.find_element(By.XPATH, '//*[contains(text(),"Dismiss")]')
      ActionChains(browser).move_to_element(btn).click().perform()
      time.sleep(2)
      browser.get('https://instagram.com/')
      time.sleep(2)
      # Verifica erro de página
      page_error = checkPageErrors(browser)
      if page_error:
          return page_error
      return True
    print('NAO ACHOU o erro suspect')
    return False

def checkgetstarted(browser): 
    print('checkgetstarted >> Verificando make a choice')
    time.sleep(2)

    # Verifique o texto principal "Make a choice about your ads"
    if waitElementXpath(browser, '//*[contains(text(), "Make a choice about your ads")]', 3):
        try:
            # Localiza o botão "Get started"
            btn = browser.find_element(By.XPATH, '//div[@role="button" and contains(text(),"Get started")]')
            if btn.is_displayed() and btn.is_enabled():
                # Role até o botão para garantir que ele está visível
                browser.execute_script("arguments[0].scrollIntoView();", btn)
                time.sleep(1)

                # Tentar clicar usando ActionChains
                ActionChains(browser).move_to_element(btn).click().perform()
                print("Botão 'Get started' clicado com sucesso.")
                
                # Delay para garantir que a página tenha tempo de atualizar
                time.sleep(3)

                # Verificar o botão "Use for free"
                if waitElementXpath(browser, '//*[contains(text(), "You need to make a choice to continue using Instagram")]', 5):
                    btn_use_free = browser.find_element(By.XPATH, '//span[text()="Use for free"]/..')  # Localiza o elemento pai que é um botão
                    
                    if btn_use_free.is_displayed() and btn_use_free.is_enabled():
                        # Rolando até o botão "Use for free"
                        browser.execute_script("arguments[0].scrollIntoView();", btn_use_free)
                        time.sleep(1)

                        try:
                            # Tentando clicar com ActionChains
                            ActionChains(browser).move_to_element(btn_use_free).click().perform()
                            print("Botão 'Use for free' clicado com sucesso.")
                        except Exception as e:
                            print(f"Erro ao clicar com ActionChains: {e}")

                        try:
                            # Tentando forçar o clique via JavaScript
                            browser.execute_script("arguments[0].click();", btn_use_free)
                            print("Botão 'Use for free' clicado com sucesso via JavaScript.")
                        except Exception as e:
                            print(f"Erro ao tentar clicar via JavaScript: {e}")
                        
                        # Verificar e clicar no botão "Agree"
                        time.sleep(2)
                        if waitElementXpath(browser, '//span[text()="Agree"]', 5):
                            btn_agree = browser.find_element(By.XPATH, '//span[text()="Agree"]/..')  # Localiza o elemento pai do botão
                            if btn_agree.is_displayed() and btn_agree.is_enabled():
                                # Rolando até o botão "Agree"
                                browser.execute_script("arguments[0].scrollIntoView();", btn_agree)
                                time.sleep(1)

                                try:
                                    # Tentando clicar com ActionChains
                                    ActionChains(browser).move_to_element(btn_agree).click().perform()
                                    print("Botão 'Agree' clicado com sucesso.")
                                except Exception as e:
                                    print(f"Erro ao clicar com ActionChains: {e}")

                                try:
                                    # Tentando forçar o clique via JavaScript
                                    browser.execute_script("arguments[0].click();", btn_agree)
                                    print("Botão 'Agree' clicado com sucesso via JavaScript.")
                                except Exception as e:
                                    print(f"Erro ao tentar clicar no botão 'Agree' via JavaScript: {e}")
                            else:
                                print("Botão 'Agree' não está disponível.")
                        else:
                            print("O botão 'Agree' não foi encontrado.")
                    else:
                        print("Botão 'Use for free' não está disponível.")
                else:
                    print("O botão 'Use for free' não foi encontrado.")
            else:
                print("Botão 'Get started' não está disponível.")
        except Exception as e:
            print(f"Erro ao tentar clicar no botão 'Get started': {e}")

        time.sleep(2)
        # Retorna para a página principal do Instagram
        browser.get('https://instagram.com/')
        time.sleep(2)
        # Verifica erro de página
        page_error = checkPageErrors(browser)
        if page_error:
            return page_error
    else:
        print("O texto 'Make a choice about your ads' não foi encontrado.")

      
def checkforfree(browser):
    print('checkforfree >> Verificando for free')
    time.sleep(2)
    #Dismiss
    if waitElementXpath(browser, '//*[contains(text(), "Use for free")]', 3):
      btn = browser.find_element(By.XPATH, '//*[contains(text(),"Use for free")]')
      ActionChains(browser).move_to_element(btn).click().perform()
      time.sleep(2)
      browser.get('https://instagram.com/')
      time.sleep(2)
      # Verifica erro de página
      page_error = checkPageErrors(browser)
      if page_error:
          return page_error

def checactivity2(browser):
    print('checactivity2 >> Verificando Activity')
    time.sleep(2)
    #checactivity2
    if waitElementXpath(browser, '//*[contains(text(), "t use this information")]', 3):
      btn = browser.find_element(By.XPATH, '//*[contains(text(),"t use this information")]')
      ActionChains(browser).move_to_element(btn).click().perform()
      time.sleep(2)
      browser.get('https://instagram.com/')
      time.sleep(2)
      # Verifica erro de página
      page_error = checkPageErrors(browser)
      if page_error:
          return page_error
    
      
def verificaLogin(browser):
    try:
      print("Verifica Login")
      
      # Verifica erro de página ANTES de verificar login
      if "This page isn't working" in browser.page_source or "ERR_TOO_MANY_REDIRECTS" in browser.page_source:
          print(Fore.RED + "Erro de página detectado em verificaLogin (ERR_TOO_MANY_REDIRECTS)" + Fore.WHITE)
          return False
      
      metodo1 = waitElementXpath(browser, '//div[contains(text(), "Log in")]', 5)
      time.sleep(1)
      metodo2 = waitElementXpath(browser, '//a[contains(text(), "Log In")]', 5)
      time.sleep(1)
      if metodo1 or metodo2:
          print('Usuario não logado')
          return False
      return True
    except Exception as err:
      print("Falha ao verificar o login")
      print(str(err))
      return False

      
	  
def existsElement(browser, xpath):
    try:
        browser.find_element(By.XPATH, xpath)
    except Exception as ex:
        return False
    return True

def checkPageErrors(browser, contaid=None):
    """
    Verifica erros na página atual (ERR_TOO_MANY_REDIRECTS, This page isn't working, etc)
    Retorna código de erro se encontrar, ou None caso contrário
    """
    if "This page isn't working" in browser.page_source or "ERR_TOO_MANY_REDIRECTS" in browser.page_source:
        print(Fore.RED + "Esta pagina não esta funcionando (ERR_TOO_MANY_REDIRECTS)" + Fore.WHITE)
        if contaid:
            accountError(contaid, 3, "This page isn't working / ERR_TOO_MANY_REDIRECTS")
        return 3
    return None

def checkUrlForErrors(browser, contaid):
    """
    Verifica se a URL atual contém algum padrão de erro e registra no banco
    Retorna (error_code, error_text) se encontrar erro, ou (None, None) caso contrário
    """
    current_url = browser.current_url
    
    for url_pattern, (error_code, error_text) in URL_ERROR_MAP.items():
        if url_pattern in current_url:
            print(Fore.RED + f"Erro detectado na URL: {error_text}" + Fore.WHITE)
            accountError(contaid, error_code, error_text)
            return (error_code, error_text)
    
    return (None, None)

def loginAccount(browser, cookieaccount, contaid=None):
    global Fake_Account
    try:                                      
        browser.get('https://inst.ws/?https://www.instagram.com/')
        sleep(3)
        
        # Verifica erro de página logo após carregar
        page_error = checkPageErrors(browser, contaid)
        if page_error:
            return page_error
        
        print('Logando na conta')
        if cookieaccount != '':      
            cookieaccount.replace("': '", '": "').replace("', '", '", "').replace("{'", '{"').replace("'}", '"}').replace("': \"", '": "').replace("', \"", '", "').replace("\", '", '", "').replace("'", '\\"') 
            cookieaccount.replace('""','"')    
            #print(cookieaccount)
            #time.sleep(300)
            try: 
                cookies = json.loads(cookieaccount)
            except:                          
                print(Fore.RED + "Usuario com cookie invalido" + Fore.WHITE)
                #print(cookieaccount)
                return 0              
            for cookie in cookies:
                browser.add_cookie({k: cookie[k] for k in {'name','value','domain'}})
            browser.get('https://inst.ws/?https://www.instagram.com/explore/') 
            #sleep(2)
            
            # Verifica erro de página após carregar explore
            page_error = checkPageErrors(browser, contaid)
            if page_error:
                return page_error        
        cookies = browser.get_cookies() # returns list of dicts
        login_status = False
        for cookie in cookies:
            if cookie['name'] == 'sessionid':
                login_status = True
                break

        time.sleep(2)
        
        # Verifica erro de página logo após adicionar cookies
        page_error = checkPageErrors(browser, contaid)
        if page_error:
            return page_error
        
        # Verifica erros por URL antes de prosseguir
        if contaid:
            error_code, error_text = checkUrlForErrors(browser, contaid)
            if error_code:
                return error_code
##Esse código é do automatico
        
        if (existsElement(browser, "//*[text()='Add Your Birthday']")):
            print(Fore.RED + "Pediu aniversario" + Fore.WHITE)
            element = browser.find_element(By.XPATH, "//select[@title='Year:']/..")
            element.click()
            date = browser.find_element(By.XPATH, "//option[@title='2000']")
            date.click()
            time.sleep(round(random.uniform(2,4),4))
            btnNext = browser.find_element(
                By.XPATH, "//div[text()='Next']")
            ActionChains(browser).move_to_element(btnNext).click().perform()
            time.sleep(round(random.uniform(3,5),4))
            btnYes = browser.find_element(
                By.XPATH, "//button[text()='Yes']")
            ActionChains(browser).move_to_element(btnYes).click().perform()
            time.sleep(round(random.uniform(1,2),2))
    ##Comentario daqui pra cima
    
        #checkWhatHappened(browser)
        #checkgetstarted(browser)
        #checkModalActivity(browser)
        #checkThisWasMe(browser)
        #checkallowallcookie(browser)
        #checkforfree(browser)
        #checactivity2(browser)
        
        #checkDismiss(browser)
        
        
        logado = verificaLogin(browser)
        
        # Verifica erro de página IMEDIATAMENTE após verificar login
        page_error = checkPageErrors(browser, contaid)
        if page_error:
            return page_error
        
        if logado == False:
            return 3
        
        # Verifica erros por URL após verificação de login
        if contaid:
            error_code, error_text = checkUrlForErrors(browser, contaid)
            if error_code:
                return error_code
        
        # Verifica erro de página
        page_error = checkPageErrors(browser, contaid)
        if page_error:
            return page_error
        
        #VERIFICA SE Ja ESTA LOGADO NA CONTA              
        if browser.current_url.find('login') == -1 and browser.current_url.find('challenge') == -1 and browser.current_url.find('twofactor') == -1 and browser.current_url.find('two_factor') == -1 and browser.current_url.find('suspended') == -1:
            if browser.current_url.find('onetap') != -1:                
                if check_exists_by_xpath(browser,'//*[@id="react-root"]/section/main/div/div/div/section/div/button'):
                    OneTapButton = browser.find_element("xpath",'//*[@id="react-root"]/section/main/div/div/div/section/div/button')
                    ActionChains(browser).move_to_element(OneTapButton).click().perform()            
            if not (browser.current_url.find('challenge') != -1 or browser.current_url.find('twofactor') != -1 or browser.current_url.find('two_factor') != -1):                                                       
                print('Usuario ja estava logado')           
                checkModalActivity(browser)
                
                # Verifica erro de página após checkModalActivity
                page_error = checkPageErrors(browser, contaid)
                if page_error:
                    return page_error
                
                # Verifica erros por URL antes de retornar sucesso
                if contaid:
                    error_code, error_text = checkUrlForErrors(browser, contaid)
                    if error_code:
                        return error_code
                
                return 1 
        #SE JA ESTIVER LOGADO MAS TEM ALGUM ERRO NA VERIFICAÇÃO
        elif browser.current_url.find('challenge') != -1 or browser.current_url.find('twofactor') != -1 or browser.current_url.find('two_factor') != -1:                    
            QueryInfo = "UPDATE database_accounts SET error=3,errortext=%s WHERE id=%s"                                                          
            print('Teve algum erro na verificação com cookie')                           
            return 5                                            
        elif browser.current_url.find('login') != -1:                    
            QueryInfo = "UPDATE database_accounts SET error=3,errortext=%s WHERE id=%s"
            print(Fore.RED + "Cookie invalido" + Fore.WHITE)
            return 3

        time.sleep(2)

        if (existsElement(browser, "//*[contains(text(),'We suspended your')]")):
            print(Fore.RED + "Conta suspensa!" + Fore.WHITE)
            return 5
        if (existsElement(browser, "//*[contains(text(),'Dismiss')]")):
            print(Fore.RED + "Conta sendo recuperada!" + Fore.Blue)
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            challengebtn = browser.find_element(By.XPATH,"//button[text()='Dismiss']")
            ActionChains(browser).move_to_element(challengebtn).click().perform()
            return 5

        logado = verificaLogin(browser)
        
        # Verifica erro de página após segunda verificação de login
        page_error = checkPageErrors(browser, contaid)
        if page_error:
            return page_error
        
        if logado == False:
            return 3


        ##Comentario daqui pra baixo

        ##Esse código é o antigo (não funciona)
        
        #if (existsElement(browser, "//*[contains(text(),'Add Your Birthday')]")):
        #    print("Pediu aniversario")
        #    time.sleep(round(random.uniform(1,2),2))
        #    element = browser.find_element(By.XPATH, "//select[@title='Year:']/../..")
        #    element.click()
        #    date = browser.find_element(By.XPATH, "//option[@title='2000']")
        #    date.click()
        #    time.sleep(round(random.uniform(1,2),2))
        #    btnNext = browser.find_element(
        #        By.XPATH, "//button[@class='sqdOP  L3NKy   y3zKF   cB_4K  ']")
        #    ActionChains(browser).move_to_element(btnNext).click().perform()
        #    time.sleep(round(random.uniform(2,3),2))
        #    btnYes = browser.find_element(
        #        By.XPATH, "//button[@class='aOOlW  bIiDR  ']")
        #    ActionChains(bytearrayser).move_to_element(btnYes).click().perform()
        #time.sleep(round(random.uniform(1,2),2))


        

    
        return 0
    except Exception as err:           
        #print(Fore.RED + "Chrome fechou sozinho" + Fore.WHITE)
        browser.save_screenshot('imagens/screenie.png')
        functionName = inspect.currentframe().f_code.co_name,
        #print(str(functionName)+':  '+str(traceback.format_exc()))        
        return 0

def Initialize(accountline):
    try:
        global Fake_Account
        print(Fore.YELLOW + f"========================================" + Fore.WHITE)
        print(Fore.YELLOW + f"Iniciando conta ID: {accountline}" + Fore.WHITE)
        print(Fore.YELLOW + f"========================================" + Fore.WHITE)
        
        # Atualiza a ultima_acao no banco ao iniciar
        updateUltimaAcao(accountline)
        
        Account_Cookie = accountGet(accountline)
        browser = openBrowser()
        if browser != 0:
            loginconta = loginAccount(browser, Account_Cookie, accountline)
            if loginconta == 1:
                print(Fore.GREEN + f'Logado com sucesso na conta ID: {accountline}' + Fore.WHITE)                
                if followFollowing(browser,Fake_Account,accountline) == 1:
                    print(Fore.CYAN + "Concluido" + Fore.WHITE)
                    now = datetime.now()
                    current_time = now.strftime("%H:%M:%S")
                    print("Horario = ", current_time)
                    print("")            
                    print("")
        
                    # Reseta logged para 0 para permitir que rode novamente
                    resetLogged(accountline)
        
                    try:
                        browser.close()
                        browser.quit() 
                    except:
                        pass    
                    return 1
                else:
                    # Reseta logged para 0 mesmo se falhar
                    resetLogged(accountline)
                    
                    try:
                        browser.close()
                        browser.quit() 
                    except:
                        pass    
                    return 0
            else:
                # Reseta logged para 0 quando dá erro de login
                resetLogged(accountline)
                
                try:
                    browser.close()
                    browser.quit() 
                except:
                    pass    
                accountError(accountline,loginconta)
                return 0

        else:
            # Reseta logged para 0 quando navegador não abre
            resetLogged(accountline)
            print('Ocorreu um erro ao logar na conta')
            return 0

    except Exception as err:
        functionName = inspect.currentframe().f_code.co_name
        #print(str(functionName)+':  '+str(traceback.format_exc()))
        
        # Reseta logged para 0 quando dá exceção
        resetLogged(accountline)
        
        try:
            browser.close()
            browser.quit() 
        except:
            pass         
        return 0    

def infiniteRun(accountline):
    try:                
        Initialize(accountline) 
        time.sleep(10)
    except Exception as err:
        functionName = inspect.currentframe().f_code.co_name     
        #print(str(functionName)+':  '+str(traceback.format_exc()))         

def openBrowser(image = False,headless = False):
    try:        
        browser_profile = webdriver.ChromeOptions()    
        browser_profile.add_argument("--silent")
        browser_profile.add_argument('--no-sandbox')
        browser_profile.add_argument("--disable-popup-blocking")
        browser_profile.add_argument('--force-dark-mode')
        browser_profile.add_argument("--disable-notifications")
        #browser_profile.add_argument("--start-maximized")
        browser_profile.add_argument('--disable-infobars')
        browser_profile.add_argument("--mute-audio")
        browser_profile.add_argument("--disable-blink-features=AutomationControlled")
        browser_profile.add_argument("--disable-dev-shm-using") 
        browser_profile.add_argument('--allow-running-insecure-content')
        browser_profile.add_argument('--ignore-certificate-errors')
        browser_profile.add_argument("--disable-blink-features")
        #browser_profile.add_argument("--blink-settings=imagesEnabled=false")
        browser_profile.add_argument('--disable-gpu')
        browser_profile.add_argument("--disable-offline-load-stale-cache")
        browser_profile.add_argument("--disk-cache-size=0")
        browser_profile.add_argument('--dns-prefetch-disable')
        browser_profile.add_argument('--window-size=1100,620')
        browser_profile.add_argument('--enable-features=NetworkService, NetworkServiceInProcess')
        browser_profile.add_argument("--lang=en-US")
        #browser_profile.add_argument("--start-maximized")
        #browser_profile.add_argument('--force-device-scale-factor=0.6')
        browser_profile.add_argument('--no-proxy-server')
        browser_profile.add_argument('--disable-blink-features=AutomationControlled')
        browser_profile.add_experimental_option("detach", False)
        browser_profile.add_experimental_option("excludeSwitches", ["enable-logging" , "enable-automation"])
        browser_profile.add_experimental_option('useAutomationExtension', False)
        browser_profile.add_experimental_option('prefs', {'credentials_enable_service': False, 'profile': {'password_manager_enabled': False}})
        #browser_profile.add_argument("--profile-directory=Default")
     
        if headless == True:
            browser_profile.headless = True            
            if os.path.isfile(f"headlesshide.crx"):
                browser_profile.add_extension(f"headlesshide.crx")

        #print('parou aqui')
        #browser = webdriver.Chrome('chromedriver.exe', options=browser_profile)
        browser = webdriver.Chrome(options=browser_profile)
        
        stealth(browser,
            languages=["en-US", "en"],
            vendor="Google Inc.",
            platform="Win32",
            webgl_vendor="Intel Inc.",
            renderer="Intel Iris OpenGL Engine",
            fix_hairline=True,
        )
        browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """
                Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
                })

                "const newProto = navigator.__proto__;"
                "delete newProto.webdriver;"
                "navigator.__proto__ = newProto;"
            """
            })    
        BlockedURLs = ["graph.instagram.com/logging_client_events","www.instagram.com/ajax/bz","www.facebook.com/ajax/bz","www.instagram.com/logging/falco"]    
        #browser.execute_cdp_cmd('Network.setBlockedURLs', {"urls": BlockedURLs})              
        #browser.minimize_window()          
        return browser
    except Exception as err:
        functionName = inspect.currentframe().f_code.co_name      
        #print(str(functionName)+':  '+str(traceback.format_exc()))  
        return 0

def updateUltimaAcao(linenum):
    global Codigo_Maquina
    try:
        dbcon = mysql.connector.connect(**config)
        mycursor = dbcon.cursor(buffered=True,dictionary=True)         
    except:
        print('Ocorreu um erro ao conectar no DB')
        return 0
    try:
        Query_UpdateAcao = "UPDATE `maquina_"+str(Codigo_Maquina)+"` SET ultima_acao=NOW() WHERE id="+str(linenum)
        mycursor.execute(Query_UpdateAcao)
        print(Fore.CYAN + f"Ultima acao atualizada para conta ID: {linenum}" + Fore.WHITE)
        try:
            dbcon.close()
            mycursor.close()
        except:
            pass
        return 1
    except:
        print('Ocorreu um erro ao atualizar ultima_acao')
        return 0

def resetLogged(linenum):
    global Codigo_Maquina
    try:
        dbcon = mysql.connector.connect(**config)
        mycursor = dbcon.cursor(buffered=True,dictionary=True)         
    except:
        return 0
    try:
        Query_Reset = "UPDATE `maquina_"+str(Codigo_Maquina)+"` SET logged=0 WHERE id="+str(linenum)
        mycursor.execute(Query_Reset)
        try:
            dbcon.close()
            mycursor.close()
        except:
            pass
        return 1
    except:
        return 0

def accountError(linenum,error=3,errortext='Erro de login na conta'):
    global Codigo_Maquina
    try:
        dbcon = mysql.connector.connect(**config)
        mycursor = dbcon.cursor(buffered=True,dictionary=True)         
    except:
        print('Ocorreu um erro ao conectar no DB')
        return 0
    try:
        Query_GetAccount = "UPDATE `maquina_"+str(Codigo_Maquina)+"` SET error='"+str(error)+"',errortext='"+str(errortext)+"' WHERE id="+str(linenum)
        mycursor.execute(Query_GetAccount)            
        try:
            dbcon.close()
            mycursor.close()
        except:
            pass
        return 1
    except:
        #print('Ocorreu um erro ao obter as contas. (Essa maquina nao esta cadastrada no DB)')
        return 0

def accountGet(linenum):
    global Codigo_Maquina
    try:
        dbcon = mysql.connector.connect(**config)
        mycursor = dbcon.cursor(buffered=True,dictionary=True)         
    except:
        print('Ocorreu um erro ao conectar no DB')
        return 0
    try:
        Query_GetAccount = "SELECT id,cookie_token FROM `maquina_"+str(Codigo_Maquina)+"` WHERE id="+str(linenum)
        #print(Fore.CYAN + "Iniciado maquina "+str(Codigo_Maquina) + Fore.WHITE)
        mycursor.execute(Query_GetAccount)            
        if mycursor.rowcount > 0:        
            rows = mycursor.fetchall() 
            CookieToken = rows[0]['cookie_token']
            mycursor.execute("UPDATE maquina_"+str(Codigo_Maquina)+" SET logged=1 WHERE id="+str(rows[0]['id']))
            try:
                dbcon.close()
                mycursor.close()
            except:
                pass
            return CookieToken
        else:
            try:
                dbcon.close()
                mycursor.close()
            except:
                pass
            return 0         
    except:
        print('Ocorreu um erro ao obter a contas. (Essa maquina nao esta cadastrada no DB)')
        return 0
    
    return 0

def accountCount():
    global Codigo_Maquina
    try:
        dbcon = mysql.connector.connect(**config)
        mycursor = dbcon.cursor(buffered=True,dictionary=True)         
    except:
        #print('Ocorreu um erro ao conectar no DB')
        print(Fore.RED + "SEM INTERNET" + Fore.WHITE)
        print(Fore.RED + "SEM INTERNET" + Fore.WHITE)
        print(Fore.RED + "SEM INTERNET" + Fore.WHITE)
        print(Fore.RED + "SEM INTERNET" + Fore.WHITE)
        print(Fore.RED + "SEM INTERNET" + Fore.WHITE)
        return 0
    try:
        # Busca contas ordenadas pela ultima_acao (NULL primeiro, depois as mais antigas)
        Query_GetAccount = "SELECT GROUP_CONCAT(id SEPARATOR ',') as contas from maquina_"+str(Codigo_Maquina)+" WHERE error = 0 and logged = 0 ORDER BY ultima_acao ASC"

        print(Fore.GREEN + "Iniciado maquina "+str(Codigo_Maquina) + Fore.WHITE)
        mycursor.execute(Query_GetAccount)            
        if mycursor.rowcount > 0:        
            rows = mycursor.fetchall() 
            Contas = rows[0]['contas']
            Contas = Contas.split(",")
            try:
                dbcon.close()
                mycursor.close()
            except:
                pass
            return Contas
        else:
            try:
                dbcon.close()
                mycursor.close()
            except:
                pass
            return 0           
    except:
        #print(Fore.YELLOW + "Ocorreu um erro ao obter as contas. (Essa maquina nao esta cadastrada no DB)" + Fore.WHITE)
        #print(str(traceback.format_exc()))
        return 0

def runTask():    
    try:    
        getConfig() 
        global threads
        global Qntd_Navegador
        global listOfProcessNames
        Qntd_Navegador1  = Qntd_Navegador
        #os.system('cls' if os.name == 'nt' else 'clear')
        Qnt_Contas = accountCount()
        try:
            len(Qnt_Contas)
            print('Quantidade de contas: '+str(len(Qnt_Contas)))
        except:
            print(Fore.CYAN + "Nao ha Contas disponiveis" + Fore.WHITE)
            time.sleep(5)
            return
        if Qntd_Navegador1 > len(Qnt_Contas):
            Qntd_Navegador1 = len(Qnt_Contas)
        print('Quantidade de navegadores: '+str(Qntd_Navegador1))
        
        # Cria lista local de threads para esta execução
        current_threads = []
        
        for i in range(Qntd_Navegador1):                        
            t = threading.Thread(name=str(i+1),target=infiniteRun, args=[Qnt_Contas[i]])
            #t.daemon = True
            t.start()
            current_threads.append(t)               
            num_threads = threading.activeCount()
            num_threads = num_threads - 1
            ctypes.windll.kernel32.SetConsoleTitleW("Versão 1.0 | Processos: "+str(num_threads)+" | Navegadores: "+str(len(listOfProcessNames)) + " | Maquina: "+str(Codigo_Maquina))
            #time.sleep(2) 
        
        # Aguarda apenas os threads desta execução
        for t in current_threads:
            t.join()
        
        # Limpa a lista global de threads após conclusão
        threads.clear()
            
    except Exception as err:
        functionName = inspect.currentframe().f_code.co_name
        #print(str(functionName)+':  '+str(traceback.format_exc()))

if __name__ == '__main__':                              
    try:        
        while True:
            runTask()         
            num_threads = threading.activeCount()
            num_threads = num_threads - 1                                                                 
            ctypes.windll.kernel32.SetConsoleTitleW("Versão 1.0 | Processos: "+str(num_threads)+" | Navegadores: "+str(len(listOfProcessNames)) + " | Maquina: "+str(Codigo_Maquina))
            time.sleep(1)
    except:
        functionName = inspect.currentframe().f_code.co_name
        #print(str(functionName)+':  '+str(traceback.format_exc()))
