├── app ├── __init__.py ├── config.py ├── teraboximp.py ├── __main__.py └── teleboximp.py ├── .gitignore ├── requirements.txt ├── base.env ├── terabox ├── config.py └── __init__.py ├── telebox ├── config.py └── __init__.py ├── .github └── FUNDING.yml └── README.md /app/__init__.py: -------------------------------------------------------------------------------- 1 | """xd""" 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .env 3 | 4 | .idea/ 5 | 6 | __pycache__ 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | python-dotenv~=1.0.0 2 | config==0.5.1 3 | requests~=2.35.0 4 | requests-toolbelt==1.0.0 5 | tqdm>=4.66.3 6 | -------------------------------------------------------------------------------- /base.env: -------------------------------------------------------------------------------- 1 | # user variables 2 | USR_LIMIT_CONCURRENT=10 3 | 4 | TELEBOX_API= 5 | TELEBOX_BASEFOLDER= 6 | 7 | TERABOX_API= 8 | TERABOX_ROUTE= 9 | -------------------------------------------------------------------------------- /terabox/config.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | """Config vars module""" 3 | 4 | 5 | class Config(object): 6 | TERABOX_BASE = 'https://www.terabox.com/rest/2.0/xpan/file' 7 | TERABOX_UPLOAD = 'https://c-jp.terabox.com/rest/2.0/pcs/superfile2' 8 | TERABOX_CHUNK_SIZE = 1024 * 1024 * 4 # 4MB 9 | -------------------------------------------------------------------------------- /telebox/config.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | """Config vars module""" 3 | 4 | 5 | class Config(object): 6 | TELEBOX_BASE_URI = 'https://www.linkbox.to/' 7 | TELEBOX_SEARCH_FILE = 'api/open/file_search' 8 | TELEBOX_FOLDER_CREATE = 'api/open/folder_create' 9 | TELEBOX_FOLDER_DETAILS = 'api/open/folder_details' 10 | TELEBOX_UPLOAD_FASE1 = 'api/open/get_upload_url' 11 | TELEBOX_UPLOAD_FASE3 = 'api/open/folder_upload_file' 12 | -------------------------------------------------------------------------------- /app/config.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | """Config vars module""" 3 | from dotenv import load_dotenv 4 | import os 5 | 6 | load_dotenv() # take environment variables from .env. 7 | 8 | 9 | class Config(object): 10 | USR_LIMIT_CONCURRENT = os.environ.get('USR_LIMIT_CONCURRENT') 11 | TELEBOX_API = os.environ.get('TELEBOX_API') 12 | TELEBOX_BASEFOLDER = os.environ.get('TELEBOX_BASEFOLDER') 13 | TERABOX_API = os.environ.get('TERABOX_API') 14 | TERABOX_ROUTE = os.environ.get('TERABOX_ROUTE') 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: TheWNetwork # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /app/teraboximp.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | """Terabox Implementation module""" 3 | import logging 4 | import os 5 | import sys 6 | from concurrent.futures import ThreadPoolExecutor 7 | 8 | from datetime import datetime 9 | from terabox import Terabox 10 | from .config import Config 11 | 12 | 13 | class TeraboxImpl: 14 | terabox = None 15 | 16 | def __init__(self, arguments): 17 | self.terabox = Terabox(Config.TERABOX_API, Config.TERABOX_ROUTE) 18 | self.main(arguments) 19 | 20 | def upload_file_and_print_status(self, i, total, directory, file): 21 | print(f'{i + 1}/{total} - {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} - Uploading file: {file}') 22 | self.terabox.upload.invoke(directory + '/' + file) 23 | 24 | def main(self, arguments): 25 | print('Start Uploading....') 26 | file_list = os.listdir(arguments.dir) 27 | len_list = str(len(file_list)) 28 | with ThreadPoolExecutor(max_workers=int(Config.USR_LIMIT_CONCURRENT)) as executor: 29 | for i, file in enumerate(file_list): 30 | executor.submit(self.upload_file_and_print_status, i, len_list, arguments.dir, file) 31 | 32 | # for file in file_list: 33 | # i += 1 34 | # print(str(i) + '/' + str(len(file_list)) + ' - Uploading file: ' + file) 35 | # telebox.upload.upload_file(arguments.dir + '/' + directory + '/' + file, subfolder_pid) 36 | print('End Uploading....') 37 | -------------------------------------------------------------------------------- /app/__main__.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | """Main module""" 3 | import argparse 4 | 5 | from datetime import datetime 6 | 7 | from app.teleboximp import TeleboxImpl 8 | from app.teraboximp import TeraboxImpl 9 | 10 | if __name__ == '__main__': 11 | parser = argparse.ArgumentParser() 12 | 13 | parser.add_argument('--telebox', type=bool, help='Subir a Telebox', nargs='*') 14 | parser.add_argument('--terabox', type=bool, help='Subir a Terabox', nargs='*') 15 | parser.add_argument('--dir', type=str, help='Ruta donde se encuentra en tu equipo la carpeta con el nombre --foldername') 16 | parser.add_argument('--foldername', type=str, help='Indica el nombre de la carpeta a buscar. Recuerda que debe existir también en la ruta en la que usarás con el parametro --dir.') 17 | args = parser.parse_args() 18 | args.basefolder = None 19 | args.dir = args.dir.replace('\\', '\\\\') 20 | datetime1 = datetime.now() 21 | print(f'Current date is: {datetime1.strftime("%Y-%m-%d %H:%M:%S")}') 22 | 23 | if args.telebox != None: 24 | print('Telebox') 25 | TeleboxImpl(args) 26 | 27 | if args.terabox != None: 28 | print('Terabox') 29 | TeraboxImpl(args) 30 | 31 | datetime2 = datetime.now() 32 | print(f'Current date is: {datetime2.strftime("%Y-%m-%d %H:%M:%S")}') 33 | # Get the difference between the datetimes 34 | diff = abs(datetime2 - datetime1) 35 | # Extract days, hours, minutes, and seconds 36 | days, seconds = diff.days, diff.seconds 37 | hours = days * 24 + seconds // 3600 38 | minutes = (seconds % 3600) // 60 39 | seconds = (seconds % 60) 40 | 41 | print(f"Total Time: {str(hours).zfill(2)}:{str(minutes).zfill(2)}:{str(seconds).zfill(2)}") 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # twn-api-upload 2 | TheWNetwork bot to upload massively to a Telebox & Terabox folder. 3 | - Allow Pictures and Videos 4 | 5 | ## Preparation 6 | 1. ``pip install -Ur requirements.txt`` 7 | 8 | 2. Copy base.env to .env and fill all the gaps 9 | 10 | 3. How to get the values for the .env file: 11 | 12 | | Variable | Description | 13 | | --- | --- | 14 | | TELEBOX_API | Access to https://www.linkbox.to/admin/account and copy "Token" | 15 | | TELEBOX_BASEFOLDER | Access to https://www.linkbox.to/admin/my-files, search the folder you wanna use and copy the ID.
Do it copying from the url bar.
Will have a format-like: https://www.linkbox.to/admin/share-folder/12345678 (12345678 is the ID) | 16 | 17 | - ``python -m app --dir --filename `` 18 | 19 | > ``--telebox`` upload to telebox (you need to configrue the .env) [Working] 20 | > 21 | > ``--terabox`` upload to terabox (you need to configrue the .env) [MayNotWork] 22 | > 23 | > ``--dir`` is the path to the folder where the files are located 24 | > 25 | > ``--filename`` is the name of the folder to be uploaded. will be created if not exists on Telebox 26 | 27 | Imagine you have a folder named "FolderToUpload" that have a list of subfolders with names (can be recursive also). 28 | You must put on "filename" the folder you wanna upload. This folder WONT be created. (as you already created it on Linkbox) 29 | 30 | - Example: ``python -m app --telebox --dir /home/user/Downloads --filename FolderToUpload`` 31 | 32 | ### Notes 33 | Telebox speed is stupidly low, it may take a long time to upload large files. 34 | Also, the Telebox API does not give any information about how its working so, sorry 35 | 36 | ## Termux pre requisites 37 | - ``pkg update`` 38 | - ``pkg in python-numpy -y`` 39 | - ``pkg in opencv-python -y`` 40 | 41 | # DISCLAIMER OF SOFTWARE WARRANTY 42 | 43 | THEWNETWORK PROVIDES THE SOFTWARE TO YOU "AS IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 44 | 45 | THE USER IS SOLELY RESPONSIBLE FOR THE ACTIONS CARRIED OUT WITH THIS CODE AND THE COMPANY IS NOT RESPONSIBLE FOR ANY MANIPULATION, INVONVENIENCE, ERROR OR PROBLEM, BOTH LEGAL AND OF ANY OTHER TYPE THAT THE USER MAY SUFFER USING THE CODE. 46 | 47 | -------------------------------------------------------------------------------- /app/teleboximp.py: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | """Telebox Implementation module""" 3 | import logging 4 | import os 5 | import sys 6 | from concurrent.futures import ThreadPoolExecutor 7 | 8 | from datetime import datetime 9 | from telebox import Telebox 10 | from .config import Config 11 | 12 | 13 | class TeleboxImpl: 14 | telebox = None 15 | 16 | def __init__(self, arguments): 17 | self.telebox = Telebox(Config.TELEBOX_API, Config.TELEBOX_BASEFOLDER) 18 | self.main(arguments) 19 | 20 | def create_folder_if_not_exists(self, foldername, folder_id): 21 | if not (pid := self.telebox.search.folder_exists(foldername, folder_id)): 22 | # Folder not exists on telebox, create folder 23 | pid = self.telebox.folder.create(foldername, folder_id) 24 | return pid 25 | 26 | def upload_file_and_print_status(self, i, total, directory, file, subfolder_pid): 27 | print(f'{i + 1}/{total} - {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} - Uploading file: {file}') 28 | self.telebox.upload.upload_file(directory + '/' + file, subfolder_pid) 29 | 30 | def doit(self, file_list, len_list, directory, folder_pid) -> bool: 31 | has_directory: bool = False 32 | with ThreadPoolExecutor(max_workers=int(Config.USR_LIMIT_CONCURRENT)) as executor: 33 | for i, file in enumerate(file_list): 34 | if os.path.isfile(directory + '/' + file): 35 | executor.submit( 36 | TeleboxImpl.upload_file_and_print_status, 37 | self, 38 | i, 39 | len_list, 40 | directory, 41 | file, 42 | folder_pid 43 | ) 44 | if os.path.isdir(directory + '/' + file): 45 | has_directory = True 46 | return has_directory 47 | 48 | def main(self, arguments): 49 | logging.basicConfig(level=logging.ERROR) 50 | 51 | currentDir = arguments.dir 52 | currentName = arguments.foldername 53 | 54 | # Searching if the folder exists 55 | folder_pid = int(arguments.basefolder or Config.TELEBOX_BASEFOLDER) 56 | 57 | folder_data = self.telebox.search.search('', folder_pid)['data']['list'] 58 | 59 | print('Get Main Folder PID for folder ' + arguments.foldername + ' is ' + str(folder_pid)) 60 | if arguments.foldername != 'upload': 61 | self.doit(os.listdir(arguments.dir), str(len(os.listdir(arguments.dir))), arguments.dir, folder_pid) 62 | 63 | directories = [d for d in os.listdir(arguments.dir + '/' + arguments.foldername) if os.path.isdir(os.path.join(arguments.dir + '/' + arguments.foldername, d))] 64 | for directory in directories: 65 | 66 | # Create or get Folder IDs 67 | print('\n\n######################################') 68 | 69 | if folder_data: 70 | subfolder = list(filter(lambda d: d['name'] == directory, folder_data)) 71 | else: 72 | subfolder = None 73 | 74 | if not subfolder: 75 | # Not created yet 76 | subfolder_pid = self.create_folder_if_not_exists(directory, folder_pid) 77 | if subfolder_pid == -1: 78 | sys.exit("Execution stopped. Folder not created") 79 | else: 80 | subfolder_pid = subfolder[0]['id'] 81 | 82 | print('Creating or getting PID for folder: ' + currentName + '/' + directory + ' is ' + str(subfolder_pid)) 83 | 84 | # Upload Files to Telebox 85 | print('Start Uploading....') 86 | file_list = os.listdir(currentDir + '/' + currentName + '/' + directory) 87 | len_list = str(len(file_list)) 88 | ret: bool = self.doit(file_list, len_list, currentDir + '/' + currentName + '/' + directory, subfolder_pid) 89 | if ret: 90 | args2 = arguments 91 | args2.dir = currentDir + '/' + currentName 92 | args2.foldername = directory 93 | args2.basefolder = subfolder_pid 94 | self.main(args2) 95 | 96 | print('End Uploading....') 97 | -------------------------------------------------------------------------------- /terabox/__init__.py: -------------------------------------------------------------------------------- 1 | # telebox.py 2 | import sys 3 | 4 | import os 5 | from pathlib import Path 6 | 7 | import json 8 | import requests 9 | 10 | import hashlib 11 | 12 | from tqdm import tqdm 13 | 14 | from .config import Config 15 | from urllib.parse import urlencode 16 | 17 | 18 | class Terabox: 19 | 20 | def __init__(self, token, folder_location): 21 | self.token = token 22 | self.folder_location = folder_location 23 | self.connect = HttpClientService(Config.TERABOX_BASE, self.token) 24 | self.upload = Upload(self.connect, folder_location, Config.TERABOX_CHUNK_SIZE) 25 | 26 | 27 | class HttpClientService: 28 | 29 | def __init__(self, base_url, token): 30 | self.base_url = base_url 31 | self.token = token 32 | 33 | def post_direct(self, endpoint, get_params=None, post_params=None, headers=None): 34 | get_params["access_tokenx"] = self.token 35 | response = requests.post(f"{self.add_params_to_url(endpoint, get_params)}", data=post_params, headers=headers) 36 | response.raise_for_status() 37 | return response.json() 38 | 39 | def post(self, endpoint, get_params=None, post_params=None): 40 | return self.post_direct(f"{self.base_url}/{endpoint}", get_params, post_params) 41 | 42 | @staticmethod 43 | def add_params_to_url(url, get_params=None): 44 | if get_params: 45 | url += '?' + urlencode(get_params) 46 | return url 47 | 48 | 49 | class Upload: 50 | def __init__(self, connect, file_location, chunk_size): 51 | self.chunk_hashes = None 52 | self.size = None 53 | self.connect = connect 54 | self.file_location = file_location 55 | self.chunk_size = chunk_size 56 | 57 | def invoke(self, filename): 58 | print(f"Uploading file: {filename}") 59 | try: 60 | prepare_response = self.prepare(filename) 61 | if prepare_response['errno'] < 0: 62 | print(f"Error occurred while preparing file: {filename}") 63 | return False 64 | 65 | upload_response = self.upload(filename, prepare_response['request_id']) 66 | if not upload_response: 67 | print(f"Error occurred while uploading file: {filename}") 68 | return False 69 | 70 | complete_response = self.complete(filename, prepare_response['request_id']) 71 | if complete_response['errno'] < 0: 72 | print(f"Error occurred while completing file: {filename}") 73 | return False 74 | except Exception as e: 75 | print(f"Error occurred while uploading file: {filename}") 76 | print(e) 77 | return False 78 | return True 79 | 80 | def prepare(self, filename): 81 | self.size = os.path.getsize(filename) 82 | chunk_hashes = [] 83 | with open(filename, "rb") as f: 84 | while chunk := f.read(self.chunk_size): 85 | chunk_md5 = hashlib.md5(chunk).hexdigest() 86 | chunk_hashes.append(chunk_md5) 87 | 88 | # Call the Request method with all the MD5 blocks 89 | self.chunk_hashes = chunk_hashes 90 | return self.connect.post('', {'method': 'precreate'}, {'path': self.file_location, 'autoinit': 1, 'size': self.size, 'block_list': chunk_hashes}) 91 | 92 | def upload(self, filename, request_id): 93 | file_size = os.path.getsize(filename) 94 | 95 | # Open file in binary mode 96 | with (open(filename, 'rb') as file): 97 | chunk_no = 1 98 | while True: 99 | progress = tqdm(total=len(self.chunk_hashes), ncols=70) 100 | # read only specified bytes amount (chunk_size) 101 | chunk = file.read(self.chunk_size) 102 | if not chunk: 103 | break 104 | 105 | # Here you can make a request with the chunk 106 | # update 'YOUR_API_URL' with your actual API which will receive chunk data 107 | get = { 108 | 'method': 'upload', 109 | 'path': self.file_location, 110 | 'uploadid': request_id, 111 | 'partseq': chunk_no 112 | } 113 | 114 | headers = { 115 | 'Content-Range': f'bytes {chunk_no * self.chunk_size}-{(chunk_no + 1) * self.chunk_size - 1}/{file_size}', 116 | # specify additional headers as per requirement of your API 117 | } 118 | 119 | progress.update(1) 120 | response = self.connect.post_direct(Config.TERABOX_UPLOAD, get_params=get, post_params={'file': chunk}) 121 | 122 | print(response) 123 | #if response != 200: 124 | # print(f"Error occurred while uploading chunk: {chunk_no}") 125 | # return False 126 | 127 | chunk_no += 1 128 | 129 | return True 130 | 131 | def complete(self, filename, request_id): 132 | response = self.connect.post('', 133 | get_params={'method': 'create'}, 134 | post_params={'path': self.file_location, 'size': self.size, 'uploadid': request_id, 'block_list': self.chunk_hashes}) 135 | return response 136 | -------------------------------------------------------------------------------- /telebox/__init__.py: -------------------------------------------------------------------------------- 1 | # telebox.py 2 | import sys 3 | 4 | import os 5 | from pathlib import Path 6 | 7 | import requests 8 | from tqdm import tqdm 9 | from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor 10 | 11 | import hashlib 12 | from .config import Config 13 | 14 | 15 | class Telebox: 16 | """ 17 | The `Telebox` class represents a client to interact with the Telebox API. 18 | 19 | :param token: The access token required for authentication. 20 | :param folder_id: The ID of the folder to interact with. 21 | 22 | The class provides methods to connect, search, and perform various operations on the specified folder. 23 | 24 | Example usage: 25 | token = "your-access-token" 26 | folder_id = "your-folder-id" 27 | telebox = Telebox(token, folder_id) 28 | 29 | Methods: 30 | - connect: Connects to the Telebox server. 31 | - search: Searches for files in the specified folder. 32 | - folder: Retrieves information about the specified folder. 33 | 34 | Note: 35 | The class requires the Telebox library to be installed. 36 | 37 | """ 38 | 39 | def __init__(self, token, folder_id): 40 | self.token = token 41 | self.folder_id = folder_id 42 | self.connect = Connect(Config.TELEBOX_BASE_URI, self.token) 43 | self.search = Search(self.connect) 44 | self.folder = Folder(self.connect) 45 | self.upload = Upload(self.connect) 46 | # self.upload_auth = UploadAuthorization(self.connect) 47 | # self.folder_details = FolderDetails(self.folder_id, self.connect) 48 | # self.folder_upload = FolderUploadFile(self.folder_id, self.connect) 49 | 50 | 51 | class HttpClientService: 52 | """ 53 | .. class:: HttpClientService 54 | 55 | The HttpClientService class provides methods to make HTTP GET and POST requests. 56 | 57 | :param base_url: The base URL that will be used for all requests. 58 | :type base_url: str 59 | 60 | .. method:: __init__(base_url) 61 | 62 | Constructs a new HttpClientService object. 63 | 64 | :param base_url: The base URL that will be used for all requests. 65 | :type base_url: str 66 | 67 | .. method:: get(endpoint, params=None) 68 | 69 | Sends an HTTP GET request to the specified endpoint. 70 | 71 | :param endpoint: The endpoint to send the request to. 72 | :type endpoint: str 73 | 74 | :param params: (optional) The query parameters to include in the request. 75 | :type params: dict 76 | 77 | :return: The JSON response from the server. 78 | :rtype: dict 79 | 80 | :raises requests.exceptions.HTTPError: If the request fails. 81 | 82 | .. method:: post(endpoint, params=None) 83 | 84 | Sends an HTTP POST request to the specified endpoint. 85 | 86 | :param endpoint: The endpoint to send the request to. 87 | :type endpoint: str 88 | 89 | :param params: (optional) The query parameters to include in the request. 90 | :type params: dict 91 | 92 | :return: The JSON response from the server. 93 | :rtype: dict 94 | 95 | :raises requests.exceptions.HTTPError: If the request fails. 96 | """ 97 | 98 | def __init__(self, base_url): 99 | self.base_url = base_url 100 | 101 | def get(self, endpoint, params=None): 102 | response = requests.get(f"{self.base_url}{endpoint}", params=params) 103 | response.raise_for_status() 104 | return response.json() 105 | 106 | def post(self, endpoint, params=None): 107 | response = requests.post(f"{self.base_url}/{endpoint}", params=params) 108 | response.raise_for_status() 109 | return response.json() 110 | 111 | 112 | class Connect: 113 | """ 114 | Connect 115 | 116 | Class representing a connection to a remote server. 117 | 118 | Attributes: 119 | client (HttpClientService): The underlying HTTP client service. 120 | token (str): The authentication token. 121 | 122 | Methods: 123 | __init__(base_url, token) 124 | Initializes a new Connect instance. 125 | 126 | get_data(endpoint, params) 127 | Makes a GET request to the specified endpoint with the given parameters. 128 | 129 | post_data(endpoint, params) 130 | Makes a POST request to the specified endpoint with the given parameters. 131 | """ 132 | 133 | def __init__(self, base_url, token): 134 | self.client = HttpClientService(base_url) 135 | self.token = token 136 | 137 | def get_data(self, endpoint, params): 138 | params["token"] = self.token 139 | return self.client.get(endpoint, params) 140 | 141 | def post_data(self, endpoint, params): 142 | params["token"] = self.token 143 | return self.client.post(endpoint, params) 144 | 145 | 146 | class Search: 147 | """ 148 | Initialize a Search object. 149 | 150 | Args: 151 | connect: The connection object used for making API calls. 152 | 153 | Attributes: 154 | connect: The connection object used for making API calls. 155 | url: The URL of the search file. 156 | """ 157 | 158 | def __init__(self, connect): 159 | self.connect = connect 160 | self.url = Config.TELEBOX_SEARCH_FILE 161 | 162 | def search(self, filename, folder_id): 163 | return self.connect.get_data(self.url, {'pid': folder_id, 'name': filename, 'pageNo': 1, 'pageSize': 50}) 164 | 165 | def folder_exists(self, filename, folder_id): 166 | lot = self.search(filename, folder_id) 167 | if isinstance(lot['data']['list'], list) and len(lot['data']['list']) != 0: 168 | return lot['data']['list'][0]['id'] if lot['data']['list'][0]['type'] == 'dir' and lot['data']['list'][0]['pid'] == int(folder_id) else False 169 | return False 170 | 171 | 172 | class Upload: 173 | def __init__(self, connect): 174 | self.connect = connect 175 | 176 | def prepare(self, file_md5_of_pre_10m, file_size): 177 | return self.connect.get_data(Config.TELEBOX_UPLOAD_FASE1, {'fileMd5ofPre10m': file_md5_of_pre_10m, 'fileSize': file_size}) 178 | 179 | @staticmethod 180 | def upload(url, file): 181 | size = os.path.getsize(file) 182 | with open(file, "rb") as file: 183 | # Send the PUT request 184 | response = requests.put(url, data=file) 185 | return response 186 | 187 | def finish_upload(self, file_md5_of_pre_10m, file_size, pid, name): 188 | return self.connect.get_data(Config.TELEBOX_UPLOAD_FASE3, {'fileMd5ofPre10m': file_md5_of_pre_10m, 'fileSize': file_size, 'pid': pid, 'diyName': name}) 189 | 190 | def upload_file(self, file, folder_id): 191 | file_size = os.path.getsize(file) 192 | file_md5_of_pre_10m = self.get_md5_of_first_10mb(file) 193 | lot = self.prepare(file_md5_of_pre_10m, file_size) 194 | if lot['status'] == 600: 195 | return 1 196 | 197 | if lot['status'] != 1: 198 | sys.exit("Prepare: Execution stopped. Cannot upload files") 199 | 200 | url = lot['data']['signUrl'] 201 | self.upload(url, file) 202 | lotf = self.finish_upload(file_md5_of_pre_10m, file_size, folder_id, os.path.basename(file)) 203 | if lotf['status'] != 1: 204 | sys.exit("Finish Upload: Execution stopped. Cannot upload files") 205 | 206 | return lotf['data']['itemId'] 207 | 208 | @staticmethod 209 | def get_md5_of_first_10mb(file_path): 210 | md5_hash = hashlib.md5() 211 | 212 | with open(file_path, 'rb') as file: 213 | chunk = file.read(10 * 1024 * 1024) # read first 10MB 214 | if chunk: 215 | md5_hash.update(chunk) 216 | 217 | return md5_hash.hexdigest() 218 | 219 | 220 | class Folder: 221 | """ 222 | Class representing a folder. 223 | 224 | Args: 225 | connect: The connection object used to communicate with the server. 226 | 227 | Attributes: 228 | connect: The connection object used to communicate with the server. 229 | 230 | """ 231 | 232 | def __init__(self, connect): 233 | self.connect = connect 234 | 235 | def create(self, filename, destination_folder_id): 236 | lot = self.connect.get_data(Config.TELEBOX_FOLDER_CREATE, {'pid': int(destination_folder_id), 237 | 'name': filename, 238 | 'isShare': 0, 239 | 'canInvite': 1, 240 | 'canShare': 1, 241 | 'withBodyImg': 0, 242 | 'desc': 'TheWNetwork Telebox Mass Creator'}) 243 | if lot['status'] != 1: 244 | sys.exit("Execution stopped. Cannot create folders") 245 | 246 | return lot['data']['dirId'] 247 | 248 | def get_details(self, destination_folder_id): 249 | return self.connect.get_data(Config.TELEBOX_FOLDER_DETAILS, {'dirId': destination_folder_id}) 250 | --------------------------------------------------------------------------------