diff --git a/README.md b/README.md index 6a642df..a97d970 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,33 @@ Ratio.py is a small command line RatioMaster.Net like in Python3. It fakes upload stats of a torrent. Current emulators available are: * Transmission 2.92 +* qBittorrent 4.25 ## Requirements: 1. Python 3.x 2. pip install -r requirements.txt ## Usage: -```console -foo@bar:~/ratio.py$ python ratio.py -c configuration.json +``` +usage: ratio.py [-h] [-c CONFIGURATION] [-t TORRENT] [-u UPLOAD] [-C CLIENT] + +optional arguments: + -h, --help show this help message and exit + -c CONFIGURATION, --configuration CONFIGURATION + Configuration file + -t TORRENT, --torrent TORRENT + Torrent file + -u UPLOAD, --upload UPLOAD + Upload rate in kb/s + -C CLIENT, --client CLIENT + Client (transmission/qbittorrent) ``` ## Configuration example ```js { "torrent": "", - "upload": "" + "upload": "", + "client: """ } ``` diff --git a/code/process_torrent.py b/code/process_torrent.py index 9d897e1..0b8e905 100644 --- a/code/process_torrent.py +++ b/code/process_torrent.py @@ -1,5 +1,5 @@ from code.decoding_bencoded import bencoding -from code.torrentclientfactory import Transmission292 +from code.torrentclientfactory import Transmission292, Qbittorrent425 from code.pretty import pretty_data, pretty_GET from hashlib import sha1 @@ -19,7 +19,11 @@ class process_torrent(): def __init__(self, configuration): self.configuration = configuration self.open_torrent() - self.torrentclient = Transmission292(self.tracker_info_hash()) + + if configuration['client'] == 'transmission': + self.torrentclient = Transmission292(self.tracker_info_hash()) + elif configuration['client'] == 'qbittorrent': + self.torrentclient = Qbittorrent425(self.tracker_info_hash()) def open_torrent(self): torrent_file = self.configuration['torrent'] diff --git a/code/torrentclientfactory.py b/code/torrentclientfactory.py index a109c26..b12cab1 100644 --- a/code/torrentclientfactory.py +++ b/code/torrentclientfactory.py @@ -58,3 +58,61 @@ def generate_key(self): chars = 'ABCDEF' + string.digits key = self.id_generator(chars, 8) return key + +class Qbittorrent425(): + def __init__(self, info_hash): + self.name = "qBittorrent" + parameters = {} + # urlencoded 20-byte SHA1 hash of the value of the info key from the Metainfo file + parameters['info_hash'] = info_hash + # urlencoded 20-byte string used as a unique ID for the client + parameters["peer_id"] = self.generate_peer_id() + # The port number that the client is listening on + parameters["port"] = random.randint(1025, 65535) + # Number of peers that the client would like to receive from the tracker + parameters["numwant"] = 80 + # An additional identification that is not shared with any other peers + parameters["key"] = self.generate_key() + # Setting this to 1 indicates that the client accepts a compact response + parameters["compact"] = 0 + # Setting this to 1 indicates that the client accepts crypto + parameters["supportcrypto"] = 1 + self.parameters = parameters + + def get_headers(self): + headers = {} + headers['User-Agent'] = 'qBittorrent/4.25' + headers['Accept'] = '*/*' + headers['Accept-Encoding'] = 'Accept-Encoding: gzip;q=1.0, deflate, identity' + return headers + + def get_query(self, uploaded, downloaded, left=0, event=None): + # The total amount uploaded (since the client sent the 'started' event) + self.parameters["uploaded"] = uploaded + # The total amount downloaded (since the client sent the 'started' event) + self.parameters["downloaded"] = downloaded + # The number of bytes this client still has to download + self.parameters["left"] = left + # If specified, must be one of started, completed, stopped + if event: + self.parameters["event"] = event + params = '&'.join('{}={}'.format(k, v) + for k, v in self.parameters.items()) + return params + + def id_generator(self, chars, size): + id = '' + for _ in range(size): + id += random.choice(chars) + return id + + def generate_peer_id(self): + chars = string.ascii_lowercase + string.digits + rand_id = self.id_generator(chars, 12) + peer_id = "-qB425-" + rand_id + return peer_id + + def generate_key(self): + chars = 'ABCDEF' + string.digits + key = self.id_generator(chars, 8) + return key diff --git a/ratio.py b/ratio.py index 68e44d3..5c06574 100644 --- a/ratio.py +++ b/ratio.py @@ -5,8 +5,13 @@ def parse_args(): """Create the arguments""" - parser = argparse.ArgumentParser('\nratio.py -c ') + parser = argparse.ArgumentParser() + parser.add_argument("-c", "--configuration", help="Configuration file") + parser.add_argument("-t", "--torrent", help="Torrent file") + parser.add_argument("-u", "--upload", help="Upload rate in kb/s") + parser.add_argument("-C", "--client", help="Client (transmission/qbittorrent)") + return parser.parse_args() def load_configuration(configuration_file): @@ -16,6 +21,7 @@ def load_configuration(configuration_file): if 'torrent' not in configuration: return None + print(configuration) return configuration @@ -23,9 +29,13 @@ def load_configuration(configuration_file): args = parse_args() if args.configuration: configuration = load_configuration(args.configuration) + elif (args.torrent != None) and (args.upload) and (args.client): + configuration = {'torrent': args.torrent, + 'upload': args.upload, + 'client': args.client + } else: sys.exit() - if not configuration: sys.exit()