import os
import logging
import re
import threading
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk

# إعداد تسجيل الأخطاء
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def extract_domain(url: str) -> str:
    """
    تستخرج اسم الدومين من URL.
    """
    match = re.search(r'//(www\.)?([a-zA-Z0-9.-]+)', url)
    if match:
        return match.group(2)  # إرجاع الدومين الكامل
    return None

def is_valid_line(line: str) -> bool:
    """
    يتحقق مما إذا كانت السطر صالح أم لا.
    """
    return bool(re.match(r'https?://[^\s|]+\|[^|]+\|[^|]+', line))

def extract_credentials(line: str) -> (str, str):
    """
    تستخرج بيانات الاعتماد من سطر نصي.
    """
    match = re.search(r'(https?://[^\s|]+)\|([^|]+)\|([^|]+)', line)
    if match:
        url = match.group(1)  # الرابط
        username = match.group(2)  # اسم المستخدم
        password = match.group(3)  # كلمة المرور
        domain = extract_domain(url)  # استخراج الدومين
        return domain, f"{username}:{password}"
    return None, None

def save_credentials(credentials):
    """
    يحفظ بيانات الاعتماد في ملفات نصية منفصلة لكل موقع.
    """
    output_folder = 'extracted_credentials'
    os.makedirs(output_folder, exist_ok=True)

    if not credentials:
        logging.warning("لا توجد بيانات اعتماد لحفظها.")
        return

    for domain, creds in credentials.items():
        # استخدام اسم الدومين وتحويله لاسم صالح للملف
        domain_safe = re.sub(r'\W+', '_', domain)  # استبدال الشخصيات غير المسموح بها
        file_name = f"{domain_safe}.txt"  # اسم الملف
        file_path = os.path.join(output_folder, file_name)
        
        with open(file_path, 'a', encoding='utf-8') as file:  # إضافة "a" للسماح بإضافة بيانات جديدة دون حذف
            unique_creds = set(creds)  # إزالة التكرار
            file.writelines(f"{cred}\n" for cred in unique_creds)  # كتابة كل بيانات الاعتماد في الملف

        logging.info(f"تم حفظ بيانات الاعتماد للدومين: {domain} في الملف: {file_name}")

def process_chunk(lines, progress, countdown_label):
    """
    معالجة جزء من السطور.
    """
    credentials = {}
    for line in lines:
        if is_valid_line(line):
            domain, user_pass = extract_credentials(line)
            if domain and user_pass:
                if domain not in credentials:
                    credentials[domain] = []
                # إضافة بيانات الاعتماد فقط إذا لم تكن موجودة بالفعل
                if user_pass not in credentials[domain]:
                    credentials[domain].append(user_pass)

    save_credentials(credentials)
    progress['value'] += len(lines)  # تحديث شريط التقدم
    root.update_idletasks()

def process_combo_file(combo_file: str, progress: ttk.Progressbar, countdown_label: tk.Label, chunk_size: int = 5000):
    """
    يعالج ملف الكومبو ويستخرج بيانات الاعتماد.
    """
    try:
        with open(combo_file, 'r', encoding='utf-8') as file:
            lines = [line.strip() for line in file if line.strip()]  # قراءة السطور غير الفارغة
            total_lines = len(lines)
            progress['maximum'] = total_lines

            for start in range(0, total_lines, chunk_size):
                end = min(start + chunk_size, total_lines)
                process_chunk(lines[start:end], progress, countdown_label)

            messagebox.showinfo("الإشعار", "تم استخراج البيانات وحفظها بنجاح.")
    except FileNotFoundError:
        logging.error(f"لم يتم العثور على الملف: {combo_file}")
        messagebox.showerror("خطأ", f"لم يتم العثور على الملف: {combo_file}")
    except Exception as e:
        logging.error(f"حدث خطأ: {e}")
        messagebox.showerror("خطأ", f"حدث خطأ: {e}")

def upload_file():
    """
    دالة لرفع ملف.
    """
    file_path = filedialog.askopenfilename(title="اختر ملف الكومبو", filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
    if file_path:
        entry_file_path.delete(0, tk.END)  # حذف النص السابق
        entry_file_path.insert(0, file_path)  # إدخال المسار في الإدخال
        button_start.config(state=tk.NORMAL)  # تفعيل زر البدء

def start_process():
    """
    بدء العملية بشكل غير متزامن.
    """
    file_path = entry_file_path.get()
    if file_path:
        button_start.config(state=tk.DISABLED)  # تعطيل زر البدء
        button_upload.config(state=tk.DISABLED)  # تعطيل زر تحميل الملف
        
        progress['value'] = 0  # إعادة تعيين شريط التقدم
        countdown_label.config(text="الوقت المتبقي: ")  # إعادة تعيين العداد

        thread = threading.Thread(target=process_combo_file, args=(file_path, progress, countdown_label))
        thread.start()  # بدء العملية في الخيط الجديد

# إعداد واجهة المستخدم
root = tk.Tk()
root.title("استخراج بيانات الاعتماد")
root.geometry("400x250")
root.configure(bg="#f0f0f0")

# مكونات واجهة المستخدم
label_file_path = tk.Label(root, text="اختر ملف الكومبو:", bg="#f0f0f0", font=("Arial", 12))
label_file_path.pack(pady=10)

entry_file_path = tk.Entry(root, width=50)
entry_file_path.pack(pady=5)

button_upload = tk.Button(root, text="رفع ملف", command=upload_file, bg="#4CAF50", fg="white", font=("Arial", 12))
button_upload.pack(pady=10)

button_start = tk.Button(root, text="بدء", state=tk.DISABLED, command=start_process, bg="#2196F3", fg="white", font=("Arial", 12))
button_start.pack(pady=5)

progress = ttk.Progressbar(root, orient="horizontal", length=300, mode="determinate")
progress.pack(pady=10)

countdown_label = tk.Label(root, text="الوقت المتبقي: 0 سطر", bg="#f0f0f0", font=("Arial", 12))
countdown_label.pack(pady=10)

# تشغيل واجهة المستخدم
root.mainloop()               خلي يقبل كومبوهات كثير                      https://eshikshakosh.bihar.gov.in/login:10210703413:Esks@3626
https://bceceboard.bihar.gov.in/Secure/univer/public/registration:<PRESIDIO_ANONYMIZED_EMAIL_ADDRESS>:Sabita@123
https://udiseplus.gov.in/udiseprofile/:10210703406:jtk#23WR