import argparse import base64 import json import os import random import re import string import sys import time from concurrent.futures import ThreadPoolExecutor, as_completed from io import BytesIO from typing import Callable, List import requests class MirrorManager: def __init__(self): self.hosts = [] def register_host( self, name: str, short: str ) -> Callable[[Callable[[BytesIO], List[str]]], Callable[[BytesIO], List[str]]]: def decorator(fun): self.hosts.append((name, short, fun)) return fun return decorator def main(): parser = argparse.ArgumentParser(description="Mirror files.") parser.add_argument("-all", action="store_true", help="Upload to every host.") for name, short, _ in mmanager.hosts: parser.add_argument(f"-{short}", action="store_true", help=f"Upload to {name}") parser.add_argument("file", help="name of the file to upload") args = parser.parse_args() fname = args.file if not os.path.isfile(fname): print(f"{repr(fname)} does not exist or is a directory!", file=sys.stderr) return 1 mirrors = {} futures = {} with ThreadPoolExecutor(max_workers=4) as thpool: for name, short, fun in mmanager.hosts: if args.all or getattr(args, short): futures[thpool.submit(fun, open(fname, "rb"))] = short for future in as_completed(futures.keys()): exc = future.exception() if exc: print(f"Uploading to {name} failed due to: {exc}", file=sys.stderr) continue mirrors[futures[future]] = future.result() print(json.dumps(mirrors)) mmanager = MirrorManager() @mmanager.register_host("anonfiles.com", "af") def host_anonfiles(fhandle: BytesIO) -> List[str]: j = requests.post( "https://api.anonfiles.com/upload", files={"file": fhandle} ).json() return [j["data"]["file"]["url"]["short"]] @mmanager.register_host("bayfiles.com", "bf") def host_bayfiles(fhandle: BytesIO) -> List[str]: j = requests.post("https://api.bayfiles.com/upload", files={"file": fhandle}).json() return [j["data"]["file"]["url"]["short"]] @mmanager.register_host("uptobox.com", "utb") def host_uptobox(fhandle: BytesIO) -> List[str]: j = requests.post( "https://www78.uptobox.com/upload", files={"files": fhandle}, ).json() return [j["files"][0]["url"]] re_1f = re.compile(r"https://1fichier.com/\?([a-z0-9]{18,})") @mmanager.register_host("1ficher.com", "1f") def host_1ficher(fhandle: BytesIO) -> List[str]: rid = "".join(random.choices(string.ascii_letters + string.digits, k=10)) fname = fhandle.name if hasattr(fhandle, "name") else "file.dat" r = requests.post( "https://up2.1fichier.com/upload.cgi", params={"id": rid}, files=[("file[]", (fname, fhandle, "application/octet-stream"))], data={ "send_ssl": "on", "domain": 0, "mail": "", "dpass": "", "user": "", "mails": "", "message": "", "submit": "Send", }, ) rg = re_1f.search(r.text) if rg is None: raise Exception("No download url in final response") return [rg.group(0)] @mmanager.register_host("siasky.net", "ss") def host_siasky(fhandle: BytesIO) -> List[str]: j = requests.post( "https://siasky.net/skynet/skyfile", files={"file": fhandle}, ).json() return ["https://siasky.net" + j["skylink"]] @mmanager.register_host("gofile.io", "go") def host_gofile(fhandle: BytesIO) -> List[str]: fname = fhandle.name if hasattr(fhandle, "name") else "file.dat" j = requests.get("https://api.gofile.io/createAccount").json() token = j["data"]["token"] j = requests.get( "https://api.gofile.io/getAccountDetails", params={"token": token} ).json() root_folder = j["data"]["rootFolder"] j = requests.put( "https://api.gofile.io/createFolder", data={"parentFolderId": root_folder, "token": token}, ).json() folder = j["data"]["id"] j = requests.get("https://api.gofile.io/getServer").json() server = j["data"]["server"] assert server.isalnum() # Let's try to avoid injection j = requests.put( "https://api.gofile.io/setFolderOption", data={"folderId": folder, "token": token, "option": "public", "value": "true"}, ).json() j = requests.post( f"https://{server}.gofile.io/uploadFile", data={"token": token, "folderId": folder}, files=[("file", (fname, fhandle, "application/octet-stream"))], ).json() return [j["data"]["downloadPage"]] @mmanager.register_host("download.gg", "dgg") def host_downloadgg(fhandle: BytesIO) -> List[str]: fname = fhandle.name if hasattr(fhandle, "name") else "file.dat" r = requests.post( "https://download.gg/server/upload.php", files=[("file[]", (fname, fhandle, "application/octet-stream"))], data={"send-id-gf": "undefined"}, ) return ["https://download.gg/file-" + r.text.replace("&", "_")] re_mir_token = re.compile(r"'token' : '([a-z0-9]{32})'") re_mir_files = re.compile(r"(https://www\.mirrored\.to/files/[A-Z0-9]+/[A-z0-9._]+)<") re_mir_hfiles = re.compile( r"https://www\.mirrored\.to/files/[A-Z0-9]+/\?hash=[0-9a-f]+&dl=[01]" ) re_mir_mirstats = re.compile( r"/mirstats\.php\?uid=[A-Z0-9]+&tmpID=[0-9a-f]+&fn=[A-z0-9.]+&ads=1&gp=1&su=0&pid=0&puid=0&fd=1&s=0&lang=[a-z]+&ftype=[A-z]+" ) re_mir_getlink = re.compile(r"/getlink/[A-Z0-9]+/[0-9]+/\?hid=[A-z0-9%]+&tid=[0-9a-f]+") re_mir_hosts = re.compile( r"f=(https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)) target=\"_blank\">" ) @mmanager.register_host("mirrored.to", "mir") def host_mirrored(fhandle: BytesIO) -> List[str]: fname = fhandle.name if hasattr(fhandle, "name") else "file.dat" fhandle.seek(0, 2) # Seek to the end of the file fsize = fhandle.tell() fhandle.seek(0) urls = [] for hosts in ( ( "gofileio", "downloadgg", "onefichier", "turbobit", "zippyshare", "usersdrive", "bayfiles", "anonfiles", "clicknupload", "uptobox", ), ( "dailyuploads", "uploadee", "dropapk", "mixdropco", "filesim", "megaupnet", "file-upload", "sendcm", "skynet", "pixeldrain", ), ): r = requests.get("https://www.mirrored.to/") rg = re_mir_token.search(r.text) if rg is None: raise Exception("No token found!") token = rg.group(1) r = requests.post( "https://www.mirrored.to/uploadify/uploadifive1.php", files=[("Filedata", (fname, fhandle, "application/octet-stream"))], data={"timestamp": "", "token": token}, ) if not r.ok and r.text: raise Exception("Failed to upload") # B64 ENCODE: # For each filename: # Enter name of file. Be sure to use format of filename listed in upload result as guide. It must be exact. Do not include quotes. # Paste this: #0# # Enter size of file in Bytes. For 1 MiB file, enter 1048576. This must be exact! # Paste this: ;0; # Example for 2 files: # First_File.7z#0#1234567;0;Second_File.7z#0#8901234;0; # Paste this: @e@#H# # Paste host list from box below. # onefichier;anonfiles;solidfiles # Paste this: ;#P##SC##T# # Enter some numbers. Example: 1625815023. It should be unique, as it is used for timestamp. data = base64.b64encode( f"{fname}#0#{fsize};0;@e@#H#{';'.join(hosts)};#P##SC##T#{int(time.time() * 1000)}".encode() ).decode() r = requests.get( "https://www.mirrored.to/upload_complete.php", params={"w": "1", "data": data}, ) rg = re_mir_files.search(r.text) if rg is None: raise Exception("No link to url list in upload_complete") files_url = rg.group(1) r = requests.get(files_url) rg = re_mir_hfiles.search(r.text) if rg is None: raise Exception("No hash link to list in files url") hfiles_url = rg.group(0) r = requests.get(hfiles_url) rg = re_mir_mirstats.search(r.text) if rg is None: raise Exception("No mirstats link in hfiles url") mirstats_url = "https://www.mirrored.to" + rg.group(0) for i in range(300): # Timeout to avoid waiting forever r = requests.get(mirstats_url) if "id_Uploading" not in r.text: break time.sleep(5) getlinks = re_mir_getlink.findall(r.text) for link in getlinks: r = requests.get("https://mirrored.to/" + link) rg = re_mir_hosts.search(r.text) if rg is None: continue # It's not worth trashing all other mirrors urls.append(rg.group(1)) return urls @mmanager.register_host("tusfiles.com", "tus") def host_tusfiles(fhandle: BytesIO) -> List[str]: fname = fhandle.name if hasattr(fhandle, "name") else "file.dat" j = requests.post( "https://cloud01.tusfiles.com/cgi-bin/upload.cgi", params={"upload_type": "file", "utype": "anon"}, files=[("file_0", (fname, fhandle, "application/octet-stream"))], data={ "sess_id": "", "utype": "anon", "link_pass": "", "link_rcpt": "", "link_pass": "", "keepalive": "1", }, ).json() return ["https://tusfiles.com/" + j[0]["file_code"]] if __name__ == "__main__": exit(main())