Note 06/01/2026 14:13:35

import requests import re import json import os import concurrent.futures def handler(pd: "pipedream"): # ========================================== # ⚙️ CONFIGURATION SETTINGS # ========================================== CPANEL_URL = "https://cpanel.infinityfree.com" USERNAME = "your username here" # Consider using pd.inputs or Pipedream Env Vars PASSWORD = "your password here" DOMAINS_TO_BACKUP = [ "mydomain.infinityfree.me", ] DATABASES_TO_BACKUP = [ "if0_hello_world", ] TELEGRAM_BOT_TOKEN = "bot token from botfather" TELEGRAM_CHANNEL_ID = "-100something" # Standard Browser Headers HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.9', 'Upgrade-Insecure-Requests': '1' } # ========================================== # 🚀 CORE BACKUP LOGIC # ========================================== def send_to_telegram(filepath, filename): print(f"📤 Uploading {filename} to Telegram...") url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendDocument" # Pipedream Memory Trick: Keeping the file open in 'rb' mode forces # requests to stream the upload, keeping RAM usage near zero. with open(filepath, 'rb') as f: res = requests.post( url, data={'chat_id': TELEGRAM_CHANNEL_ID, 'caption': f"✅ Backup successful: {filename}"}, files={'document': (filename, f)} ) if res.status_code == 200: print(f"✅ Successfully sent {filename} to Telegram!") else: print(f"❌ Failed to send {filename}: {res.text}") def backup_domain(domain, fm_url, session): print(f"📦 Zipping and downloading domain: {domain}...") items = json.dumps([{"name": domain, "type": "dir", "fullPath": f"/{domain}"}]) payload = { 'action': 'downloadZip', 'items': items, 'basePath': '/', 'zipName': f'{domain}.zip' } res = session.post(fm_url, data=payload, stream=True) filename = f"{domain}.zip" filepath = f"/tmp/{filename}" # Speed Trick: Increased chunk size to 1MB (1024 * 1024) # Reduces loop overhead and CPU time on Pipedream with open(filepath, 'wb') as f: for chunk in res.iter_content(chunk_size=1048576): f.write(chunk) send_to_telegram(filepath, filename) os.remove(filepath) # Instantly free disk space def backup_database(db_name, sso_url, session): print(f"🗄️ Preparing database backup: {db_name}...") session.get(sso_url) export_page = f"https://php-myadmin.net/db_export.php?db={db_name}" res = session.get(export_page) token_match = re.search(r'name="token"\s+value="([a-f0-9]+)"', res.text) if not token_match: print(f"❌ Could not find CSRF token for {db_name}. Skipping.") return token = token_match.group(1) tables = re.findall(r'name="table_select\[\]"\s+value="([^"]+)"', res.text, re.IGNORECASE) payload = { 'db': db_name, 'token': token, 'export_type': 'database', 'export_method': 'quick', 'what': 'sql', 'structure_or_data_forced': '0', 'output_format': 'sendit', 'filename_template': '@DATABASE@', 'remember_template': 'on', 'charset': 'utf-8', 'compression': 'none', 'sql_compatibility': 'NONE', 'sql_structure_or_data': 'structure_and_data', 'sql_type': 'INSERT', 'sql_insert_syntax': 'both', 'sql_max_query_size': '50000', } if tables: payload['table_select[]'] = tables payload['table_structure[]'] = tables payload['table_data[]'] = tables print(f"⬇️ Downloading SQL for {db_name}...") res = session.post("https://php-myadmin.net/export.php", data=payload, stream=True) filename = f"{db_name}.sql" filepath = f"/tmp/{filename}" # Streaming with 1MB chunks with open(filepath, 'wb') as f: for chunk in res.iter_content(chunk_size=1048576): f.write(chunk) send_to_telegram(filepath, filename) os.remove(filepath) # ========================================== # 🔐 EXECUTION SEQUENCE # ========================================== print("🔐 Logging into cPanel...") # We create ONE session and pass it everywhere. This enables TCP connection pooling. session = requests.Session() session.headers.update(HEADERS) res = session.get(f"{CPANEL_URL}/login.php") csrf_match = re.search(r'name="seeesurf"\s+value="([^"]+)"', res.text) csrf = csrf_match.group(1) if csrf_match else "" res = session.post(f"{CPANEL_URL}/login.php", data={ 'uname': USERNAME, 'passwd': PASSWORD, 'seeesurf': csrf, 'theme': 'PaperLantern', 'login': 'Login', 'language': 'English' }) redirect_match = re.search(r"location\.href\s*=\s*['\"]([^'\"]+)['\"]", res.text) if not redirect_match: print("❌ Login failed. Check credentials.") return dashboard_url = f"{CPANEL_URL}/{redirect_match.group(1)}" res = session.get(dashboard_url) html_clean = res.text.replace('\\/', '/') fm_match = re.search(r'(https?://filemanager\.ai[^"\'\s>]+)', html_clean) fm_url = fm_match.group(1).replace('&', '&') if fm_match else None ttt_match = re.search(r'ttt=([-0-9a-zA-Z]+)', html_clean) ttt = ttt_match.group(1) if ttt_match else None db_sso_links = {} if ttt: res_db = session.get(f"{CPANEL_URL}/panel/indexpl.php?option=pma&ttt={ttt}") matches = re.findall(r'(https://php-myadmin\.net/login\.php\?2=[^"\'\s>]+)', res_db.text, re.IGNORECASE) for url in matches: url = url.replace('&', '&') db_match = re.search(r'&db=([^&"\']+)', url) if db_match: db_sso_links[db_match.group(1)] = url print("✅ Successfully authenticated! Starting high-speed parallel backups...") # Max workers set to 5 is perfect for avoiding Pipedream CPU throttling with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: futures = [] if fm_url: for domain in DOMAINS_TO_BACKUP: futures.append(executor.submit(backup_domain, domain, fm_url, session)) for db in DATABASES_TO_BACKUP: sso_url = db_sso_links.get(db) if sso_url: futures.append(executor.submit(backup_database, db, sso_url, session)) for future in concurrent.futures.as_completed(futures): try: future.result() except Exception as e: print(f"❌ Backup error: {e}") print("🎉 All backup processes completed!") return {"status": "success"}

Public Last updated: 2026-06-02 05:10:24 PM