from tiktok_captcha_solver import SeleniumSolver
import os
import time
import random
import threading
import requests
import cv2
from queue import Queue
import numpy as np
import pyautogui
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from stem.control import Controller
from stem import Signal
from pynput.keyboard import Controller as KeyboardController
import undetected_chromedriver as uc
from tiktok_captcha_solver import SeleniumSolver
from selenium_stealth import stealth
import tempfile
from selenium.common.exceptions import TimeoutException
def slide_slider(driver, slider_xpath, pixel_offset):
    slider = driver.find_element(By.XPATH, slider_xpath)
    actions = ActionChains(driver)
    
    # Daha agresif başlangıç
    actions.move_to_element_with_offset(slider, 10, 5).click_and_hold().pause(0.2)
    
    total = 0
    remaining = pixel_offset
    base_speed = pixel_offset * 0.20  # %20'den başla
    
    while total < pixel_offset:
        # Daha hafif yavaşlama (kuvveti 1.5'e düşürdüm)
        step = min(
            base_speed + (remaining**1.5 * 0.0002),  # Kuvvet ve çarpan azaltıldı
            remaining
        )
        
        # Daha büyük varyasyon
        step *= random.uniform(1.0, 1.2)  # +%20'ye kadar rastgele artış
        step = max(3, step)  # Minimum 3px
        
        # Son 15px'de mikro ayar
        if remaining < 15:
            step = random.uniform(1.5, 3.5)
        
        actions.move_by_offset(
            step + random.uniform(-0.2, 0.2),
            random.uniform(-0.1, 0.1)
        ).pause(random.uniform(0.02, 0.05))  # Daha kısa duraklamalar
        
        total += step
        remaining = pixel_offset - total
        base_speed *= 0.90  # Her adımda sadece %10 yavaşlat
    
    actions.release().perform()
    print(f"⚡ Slider {total:.2f}px kaydı (Hata: {abs(pixel_offset - total):.2f}px)")
# Klavye kontrolü için
keyboard = KeyboardController()
# Tor Proxy Ayarı
TOR_PROXY = "proxy ip"
def get_coords():
    while True:
        print(pyautogui.position())
def change_tor_ip():
    """Tor ağı üzerinden yeni bir IP adresi talep eder."""
    try:
        with Controller.from_port(port="int port") as controller:
            controller.authenticate(password="password")  # Tor şifreni buraya yaz
            controller.signal(Signal.NEWNYM)  # Yeni kimlik talep et
            print("Yeni Tor IP alındı!")
            time.sleep(5)  # Yeni IP'nin aktif olması için bekle
    except Exception as e:
        print(f"Tor IP değiştirilemedi! Hata: {e}")
def create_browser():
    global api_key
    """Chrome tarayıcısını başlatır ve Tor proxy'sini kullanır."""
    options = uc.ChromeOptions()
    options.add_argument("--disable-blink-features=AutomationControlled")
    options.add_argument(f"--proxy-server={TOR_PROXY}")  
    options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36")
    temp_profile_dir = tempfile.mkdtemp()  # Benzersiz, geçici bir dizin oluşturur
    options.add_argument(f"--user-data-dir={temp_profile_dir}")
    
    api_key = "xxxxxxapiley"
    
    try:
        return webdriver.Chrome(options=options)
    except Exception as e:
        print(f"Tarayıcı başlatılamadı! Hata: {e}")
        return None
def fake_keyboard_activity():
    """Sahte klavye hareketleri simüle eder (gerçek yazım yapmaz)."""
    fake_keys = ["a", "s", "d", "f", "j", "k", "l", "space", "enter", "ctrl", "alt"]
    while True:
        key = random.choice(fake_keys)
        
        time.sleep(random.uniform(10, 20))
def download_image(browser, xpath, filename):
    """Belirtilen xpath'teki resmi indirir veya screenshot alır ve kaydeder.
       Fotoğrafın src attribute'sinin dolu olup olmadığını 15 saniyeye kadar kontrol eder.
    """
    try:
        element = WebDriverWait(browser, 30).until(
            EC.presence_of_element_located((By.XPATH, xpath))
        )
        # 15 saniyeye kadar src attribute'sinin dolu olup olmadığını kontrol et
        timeout = 15
        poll_interval = 0.5
        waited = 0
        src = element.get_attribute("src")
        while (not src or src.strip() == "") and waited < timeout:
            time.sleep(poll_interval)
            waited += poll_interval
            src = element.get_attribute("src")
        
        if not src or src.strip() == "":
            raise Exception(f"{filename} için src attribute'si {timeout} saniyede hala boş!")
        
        file_path = f"/{filename}.png"
        if src.startswith("blob:"):
            element.screenshot(file_path)
            print(f"{filename}.png screenshot olarak kaydedildi!")
        else:
            response = requests.get(src)
            if response.status_code == 200:
                with open(file_path, "wb") as f:
                    f.write(response.content)
                print(f"{filename}.png kaydedildi!")
            else:
                print(f"{filename} indirilemedi, durum kodu: {response.status_code}")
    except Exception as e:
        print(f"{filename} indirilirken hata oluştu: {e}")
    except Exception as e:
        print(f"{filename} indirilirken hata oluştu: {e}")
def merge_images(background_path, overlay_path):
    import cv2
    import numpy as np
    # Resimleri yükle
    bg = cv2.imread(background_path, cv2.IMREAD_GRAYSCALE)
    ov = cv2.imread(overlay_path, cv2.IMREAD_GRAYSCALE)
    
    if bg is None or ov is None:
        raise FileNotFoundError("Resimler yüklenemedi!")
    # Kontur analizi
    _, thresh = cv2.threshold(ov, 50, 255, cv2.THRESH_BINARY)
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    if not contours:
        raise Exception("Kontur bulunamadı!")
    # Açı hesaplama
    c = max(contours, key=cv2.contourArea)
    rect = cv2.minAreaRect(c)
    angle = rect[-1]
    # Açıyı [0, 180) aralığına normalize et
    if rect[1][0] < rect[1][1]:  # Genişlik < Yükseklik
        angle += 90
    angle = abs(angle % 180)  # 0-180 arası pozitif değer
    print(f"Düzeltilmiş Açı: {angle:.2f}°")
    return calculate_pixel_offset(angle)
def calculate_pixel_offset(angle):
    MAX_SLIDER = 348
    KALIBRASYON = 0.957  # Yeni optimize değer
    OFFSET_DUZELTME = 3.2  # Manuel offset ayarı
    
    pixel_offset = (angle / 180) * MAX_SLIDER * KALIBRASYON + OFFSET_DUZELTME + 10
    
    print(f"Hassas Kaydırma: {pixel_offset:.2f}px")
    return max(0, min(pixel_offset, MAX_SLIDER))  # Sınırları garantile
def check_if_exists(mainphotopath,rotatephotopath):
    if os.path.exists(mainphotopath) and os.path.exists(rotatephotopath):
        return True
    else:
        False
def watch_live(email, password):
    """Yeni IP alır, tarayıcıyı başlatır ve tüm işlemleri gerçekleştirir."""
    print("Yeni IP alınıyor...")
    change_tor_ip()
    browser = create_browser()
    sadcaptcha = SeleniumSolver(
    browser,
    api_key,
    mouse_step_size=1, # Adjust to change mouse speed
    mouse_step_delay_ms=10 # Adjust to change mouse speed
    )   
    if not browser:
        print("Tarayıcı açılamadı! 🚫")
        return
    browser.maximize_window()
    
    try:
        # Klavye aktivitesi thread'ini başlat
        keyboard_thread = threading.Thread(target=fake_keyboard_activity, daemon=True)
        keyboard_thread.start()
        # TikTok sayfasını aç
        browser.get("yayın linki")
        print("TikTok yayını açıldı! ✅")
        time.sleep(3)
        # Login butonunu bul ve tıkla
        wait = WebDriverWait(browser, 20)
        login_button = wait.until(EC.element_to_be_clickable((By.ID, "header-login-button")))
        ActionChains(browser).move_to_element(login_button).click().perform()
        print("Giriş butonuna tıklandı! ✅")
        time.sleep(5)
        # Phone butonu için yeni kontrol sistemi
        #HİKMET BURAYI YAPACAKSIN
        try:
            # Önce div4/div2'yi dene
            try:
                second_button = WebDriverWait(browser, 5).until(
                    EC.element_to_be_clickable((By.XPATH, '//*[@id="loginContainer"]/div/div/div/div[2]/div[2]'))
                )
                ActionChains(browser).move_to_element(second_button).click().perform()
            
            except Exception as e:
                try:
                    
                    ikinci_senaryo = WebDriverWait(browser, 6).until(
                    EC.element_to_be_clickable((By.XPATH, '//*[@id="loginContainer"]/div/div/div[1]/div/button[2]'))
                )
                    
                    ActionChains(browser).move_to_element(ikinci_senaryo).click().perform()
                   
                    
               
                    
                except:
                    try:
                        
                        first_button = WebDriverWait(browser, 6).until(
                        EC.element_to_be_clickable((By.XPATH, '//*[@id="loginContainer"]/div/div/div[4]/div/div[2]'))
                    )
                        print("div4/div2 butonu bulundu - özel işlem başlatılıyor")
                        
                        # İlk butona tıkla
                        ActionChains(browser).move_to_element(first_button).click().perform()
                        
                        second_button = WebDriverWait(browser, 5).until(
                        EC.element_to_be_clickable((By.XPATH, '//*[@id="loginContainer"]/div/div/div[4]/div[1]/div[2]'))
                )
                        ActionChains(browser).move_to_element(second_button).click().perform()
                        
                        
                    except:
                        
                        first_button = WebDriverWait(browser, 6).until(
                        EC.element_to_be_clickable((By.XPATH, '//*[@id="loginContainer"]/div/div/div[4]/div[1]/div[2]'))
                    )
                        print("div4/div2 butonu bulundu - özel işlem başlatılıyor")
                        ActionChains(browser).move_to_element(first_button).click().perform()
        except Exception as e:
            print(f"Phone buton tıklama hatası: {str(e)}")
            browser.quit()
            return
        #HİKMET BAK >>>>>>>>>>>>>>>> test ederken göreceksin genelde phone yaz diyor oranın sağ üstünde email ile gir diyor eğer öyle bir yer gelirse işte kod
        #burda devreye giriyor sen buranın  üst kısmını yapacaksın satır 231 ile bura arasını
        # Email ile giriş linkine tıkla
        wait = WebDriverWait(browser, 40)
        link = wait.until(EC.element_to_be_clickable((By.XPATH, '//a[@href="/login/phone-or-email/email"]')))
        link.click()
        print("E-mail ile giriş butonuna basıldı!")
        time.sleep(1)
        # Email ve şifre giriş
        wait = WebDriverWait(browser, 50)
        email_input = wait.until(EC.presence_of_element_located((By.XPATH, '//input[@placeholder="Email or username"]')))
        email_input.send_keys(email)
        time.sleep(3)
        password_input = wait.until(EC.presence_of_element_located((By.XPATH, '//input[@placeholder="Password"]')))
        password_input.send_keys(password)
        print("Bilgiler girildi! ✅")
        
        try:
            login_enter = WebDriverWait(browser, 5).until(
                        EC.element_to_be_clickable((By.XPATH, '//*[@id="loginContainer"]/div[2]/form/button')))
            
            login_enter.click()
            print("Giriş yap butonuna tıklandı! ✅")
        except:
            second_input_button = WebDriverWait(browser, 5).until(
                        EC.element_to_be_clickable((By.XPATH, '//*[@id="loginContainer"]/div/div/form/button')))
            second_input_button.click()
            print("butona basıldı")
            
        # Captcha çözümü
        print("Captcha bekleniyor...")
        wait = WebDriverWait(browser, 30)
        wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="captcha-verify-container-main-page"]/div[2]/div[1]/img[1]')))
        print("Captcha sayfası yüklendi, resimler indiriliyor...")
            
        verification_success = False
        sadcaptcha.solve_captcha_if_present(15,3)
        
        try:   
            verification_input = WebDriverWait(browser, 5).until(
            EC.visibility_of_element_located(
                        (By.XPATH, '//div[21]/div[2]/div[2]/div/div[1]/input | //div[20]/div[2]/div[2]/div/div[1]/input | //div[19]/div[2]/div[2]/div/div[1]/input')
                    )
            )
            print("✅ Captcha çözüldü, input kutusu görüldü!")
            verification_success = True
                   
        except:
            print("1")
                        
        # E-posta doğrulama adımına geç
        print("Captcha doğrulandı, e-posta kontrolüne geçiliyor...")
        time.sleep(1.5)
        browser.execute_script("window.open('webmail', '_blank');")
        WebDriverWait(browser, 10).until(lambda d: len(d.window_handles) > 1)
        browser.switch_to.window(browser.window_handles[-1])
        # E-posta girişi
        wait = WebDriverWait(browser, 50)
        email_input = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="rcmloginuser"]')))
        email_input.send_keys(email)
        
        password_input = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="rcmloginpwd"]')))
        password_input.send_keys(password)
        print("E-posta bilgileri girildi! ✅")
        login_enter = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="rcmloginsubmit"]')))
        login_enter.click()
        print("E-posta girişi yapıldı")
        time.sleep(1)
        # Doğrulama kodunu al
        element = browser.find_element(
            By.XPATH, "//*[@id='messagelist']/tbody/tr[1]//td[@class='subject']//span[@class='subject']//a//span"
        )
        verification_code = element.text[0:6]
        print(f"Doğrulama kodu alındı: {verification_code}")
        # TikTok sekmesine geri dön
        browser.switch_to.window(browser.window_handles[0])
        print("TikTok sekmesine dönüldü")
        global key_input
        # Doğrulama kodunu gir
        try:
            key_input = WebDriverWait(browser, 5).until(
                        EC.element_to_be_clickable((By.XPATH, '/html/body/div[20]/div[2]/div[2]/div/div[1]/input')))
            
        except:
            key_input = WebDriverWait(browser, 5).until(
                        EC.element_to_be_clickable((By.XPATH, '/html/body/div[21]/div[2]/div[2]/div/div[1]/input')))
            
        for char in verification_code:
            key_input.send_keys(char)
            time.sleep(random.uniform(0.08, 0.3))  # Rastgele yazma hızı
        browser.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", key_input)
        
        submit_button = WebDriverWait(browser, 5).until(
        EC.element_to_be_clickable((By.XPATH, 
            '/html/body/div[20]/div[2]/div[2]/button | '
            '/html/body/div[21]/div[2]/div[2]/button'
        ))
         )
        actions = ActionChains(browser)
        actions.move_to_element(submit_button)
        # Hafif bir düzensizlik ekle (butona tam odaklanmadan önce biraz dolaşabilir)
        actions.move_by_offset(random.uniform(-5, 5), random.uniform(-5, 5))
        actions.pause(random.uniform(0.3, 0.7))
        # Son dokunuş: Bazen butona çift dokunuş gibi görünen bir hareket yapabiliriz
        if random.random() < 0.2:
            actions.click().pause(random.uniform(0.1, 0.2))
        # Butona tıkla
        actions.click().perform()
                
        print("Doğrulama kodu gönderildi!")
        try:
            verify_puzzle = WebDriverWait(browser, 5).until(
                        EC.element_to_be_clickable((By.XPATH, '//*[@id="captcha-verify-container-main-page"]/div[2]/div[1]/img[1]')))
            sadcaptcha.solve_captcha_if_present(15,3)
            print("yayına girildi ✅")
        except:
            try:
                verify_puzzle = WebDriverWait(browser, 5).until(
                        EC.element_to_be_clickable((By.XPATH, '/html/body/div[20]/div[2]/div[2]/div[2]')))
                time.sleep(64)
                verify_puzzle.click()
                browser.switch_to.window(browser.window_handles[-1])
                element = browser.find_element(
            By.XPATH, "//*[@id='messagelist']/tbody/tr[1]//td[@class='subject']//span[@class='subject']//a//span"
            )
                verification_code = element.text[0:6]
                print(f"Doğrulama kodu alındı: {verification_code}")
                browser.switch_to.window(browser.window_handles[0])
                for char in verification_code:
                    key_input.send_keys(char)
                    time.sleep(random.uniform(0.1, 0.3))  # Rastgele yazma hızı
                browser.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", key_input)
                
               
                # Send butonuna tıkla/html/body/div[20]/div[2]/div[2]/button
                ActionChains(browser)\
                .move_to_element(submit_button)\
                .pause(random.uniform(0.3, 0.7))\
                .click()\
                .perform()
            
        
                print("Doğrulama kodu gönderildi! yayına girildi ✅")
            except:
                print("girildi ✅")
        while True:
            time.sleep(60)
    except Exception as e:
        print(f"İşlem sırasında hata oluştu: {e}")
        browser.quit()
# Tarayıcıyı çalıştır
# Thread sayısı ve hesap listesi
THREAD_COUNT = 10  # Aynı anda çalışacak tarayıcı sayısı
ACCOUNTS = [
    {"email":"zzzzz", "password":"pasword"},
    
    


]

MAX_RETRIES = 3
# Hesap kuyruğu ve tekrar deneme sayıları için dict
account_queue = Queue()
retry_counts = {}
def worker():
    while True:
        account = account_queue.get()
        email = account["email"]
        
        # Hesap için kaç kez denendiğini kontrol et
        if retry_counts[email] >= MAX_RETRIES:
            print(f"⛔ {email} için maksimum deneme sayısına ulaşıldı, işlem durduruldu!")
            account_queue.task_done()
            continue
        
        try:
            print(f"🌀 {email} için işlem başlatılıyor... ({retry_counts[email] + 1}. deneme)")
            watch_live(email, account['password'])
            print(f"✅ {email} işlemi başarılı!")
        except Exception as e:
            print(f"❌ {email} hata aldı: {str(e)} - Tekrar denenecek...")
            retry_counts[email] += 1
            account_queue.put(account)  # Hatadan sonra tekrar kuyruğa ekle
            time.sleep(2)  # Çakışmaları önlemek için kısa bir bekleme süresi
        finally:
            account_queue.task_done()
if __name__ == "__main__":
   
    
     # Paralel çalışacak thread sayısı
    # Retry sayacını sıfırla
    for acc in ACCOUNTS:
        retry_counts[acc["email"]] = 0
        account_queue.put(acc)
    # Thread'leri başlat
    for _ in range(THREAD_COUNT):
        threading.Thread(target=worker, daemon=True).start()
    # Tüm işlemler tamamlanana kadar bekle
    account_queue.join()
    print("🎉 Tüm hesaplar işlendi!")