diff --git a/crawl.py b/crawl.py index 11ffd04..ad09734 100755 --- a/crawl.py +++ b/crawl.py @@ -55,6 +55,7 @@ if ("https://" not in name): print(colored('No torrent named "' + name + '" on YggTorrent', 'blue')) sys.exit(1) else: + name = re.sub(r'\w*--seed\w*', '', name) research = unquote(name, errors='strict') # Allow only one torrent downling in same time, and remove oldest torrent if disk size is full. @@ -124,8 +125,7 @@ def downloadTorrent(): shutil.rmtree('data/tmp/torrents', ignore_errors=True) os.mkdir("data/tmp/torrents") scraper.download_from_torrent_url(research) -# os.popen(f'cd data/tmp/torrents/ && mv *.torrent {idTorrent}.torrent && mv *.torrent ../../torrents/') - os.popen(f'cd data/tmp/torrents/ && mv *.torrent {idTorrent.strip()}.torrent && mv {idTorrent.strip()}.torrent ../../torrents/') + os.popen(f'cd data/tmp/torrents/ && mv *.torrent ../../torrents/{idTorrent.strip()}.torrent') # Remove tracker def removeTracker(): @@ -143,7 +143,7 @@ if(scraper.login(login.user, login.passwd)): #Check if user can login print(colored("Login success", 'green')) rollingFiles() downloadTorrent() - removeTracker() if options.rmTracker else None + removeTracker() if options.rmTracker else time.sleep(2); os.replace(f'data/torrents/{idTorrent.strip()}.torrent.added', f'data/meta/{idTorrent.strip()}/{idTorrent.strip()}.torrent') else: print(colored("Login failed", 'red')) sys.exit(1) diff --git a/lib/ratiomaster/README.md b/lib/ratiomaster/README.md new file mode 100644 index 0000000..6a642df --- /dev/null +++ b/lib/ratiomaster/README.md @@ -0,0 +1,22 @@ +# Ratio.py + +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 + +## Requirements: +1. Python 3.x +2. pip install -r requirements.txt + +## Usage: +```console +foo@bar:~/ratio.py$ python ratio.py -c configuration.json +``` + +## Configuration example +```js +{ + "torrent": "", + "upload": "" +} +``` diff --git a/lib/ratiomaster/code/__init__.py b/lib/ratiomaster/code/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/ratiomaster/code/decoding_bencoded.py b/lib/ratiomaster/code/decoding_bencoded.py new file mode 100644 index 0000000..75be291 --- /dev/null +++ b/lib/ratiomaster/code/decoding_bencoded.py @@ -0,0 +1,90 @@ +import re +import logging +import binascii +class bencoding(): + + def __init__(self): + self.decimal_match = re.compile('\d') + self.data = b'' + self.dict = {} + + def get_dict(self, key): + if key not in self.dict: + return '' + start = self.dict[key][0] + end = self.dict[key][1] + return self.data[start:end] + + def get_item(self, chunks): + item = chunks[self.i] + self.i += 1 + if not type(item) == str: + item = bytes([item]) + try: + item = item.decode('utf-8') + except: + item = '\\x{}'.format(binascii.hexlify(item)) + return item + + def decoding_byte_string(self, chunks, item): + # logging.debug('decoding string') + num = '' + while self.decimal_match.search(item): + num += item + item = self.get_item(chunks) + line = '' + for i in range(int(num)): + line += self.get_item(chunks) + return line + + def decoding_integer(self, chunks): + # logging.debug('decoding integer') + item = self.get_item(chunks) + num = '' + while item != 'e': + num += item + item = self.get_item(chunks) + return int(num) + + def decoding_list(self, chunks): + # logging.debug('decoding list') + item = self.get_item(chunks) + list = [] + while item != 'e': + self.i -= 1 + list.append(self._dechunk(chunks)) + item = self.get_item(chunks) + return list + + def decoding_dictionnary(self, chunks): + # logging.debug('decoding dictionnary') + item = self.get_item(chunks) + hash = {} + while item != 'e': + self.i -= 1 + key = self._dechunk(chunks) + start = self.i + hash[key] = self._dechunk(chunks) + end = self.i + self.dict[key] = (start, end) + item = self.get_item(chunks) + return hash + + def _dechunk(self, chunks): + item = self.get_item(chunks) + if item == 'd': + return self.decoding_dictionnary(chunks) + elif item == 'l': + return self.decoding_list(chunks) + elif item == 'i': + return self.decoding_integer(chunks) + elif self.decimal_match.search(item): + return self.decoding_byte_string(chunks, item) + raise "Invalid input!" + + def bdecode(self, data): + self.data = data + chunks = list(self.data) + self.i = 0 + root = self._dechunk(chunks) + return root diff --git a/lib/ratiomaster/code/pretty.py b/lib/ratiomaster/code/pretty.py new file mode 100644 index 0000000..e5c8a39 --- /dev/null +++ b/lib/ratiomaster/code/pretty.py @@ -0,0 +1,28 @@ +import requests +from pprint import pformat + + +def get_headers(headers): + res = '' + for k, v in headers.items(): + res += '{}: {}\n'.format(k, v) + return res + + +def pretty_GET(url, headers, params): + req = requests.Request('GET', url, headers=headers, params=params) + s = requests.Session() + prepared = s.prepare_request(req) + p = '-----START-----\n' + p +=('{} {}\n{}'.format(prepared.method, prepared.url, + get_headers(prepared.headers), + ) + ) + if prepared.body: + pi += prepared.body + p += '------END------' + return p + + +def pretty_data(data): + return pformat(data) diff --git a/lib/ratiomaster/code/process_torrent.py b/lib/ratiomaster/code/process_torrent.py new file mode 100644 index 0000000..9d897e1 --- /dev/null +++ b/lib/ratiomaster/code/process_torrent.py @@ -0,0 +1,118 @@ +from code.decoding_bencoded import bencoding +from code.torrentclientfactory import Transmission292 +from code.pretty import pretty_data, pretty_GET + +from hashlib import sha1 +from urllib.parse import quote_plus +import requests +import logging +import random +from tqdm import tqdm +from time import sleep + +from struct import unpack + +logging.basicConfig(level=logging.DEBUG) + +class process_torrent(): + + def __init__(self, configuration): + self.configuration = configuration + self.open_torrent() + self.torrentclient = Transmission292(self.tracker_info_hash()) + + def open_torrent(self): + torrent_file = self.configuration['torrent'] + with open(torrent_file, 'rb') as tf: + data = tf.read() + self.b_enc = bencoding() + self.metainfo = self.b_enc.bdecode(data) + self.info = self.metainfo['info'] + if 'length' not in self.info: + self.info['length'] = 0 + for file in self.info['files']: + self.info['length'] += file['length'] + print(pretty_data(self.info['files'])) + + def tracker_info_hash(self): + raw_info = self.b_enc.get_dict('info') + hash_factory = sha1() + hash_factory.update(raw_info) + hashed = hash_factory.hexdigest() + sha = bytearray.fromhex(hashed) + return str(quote_plus(sha)) + + def send_request(self, params, headers): + url = self.metainfo['announce'] + print(pretty_GET(url, headers, params)) + while True: + try: + r = requests.get(url, params=params, headers=headers) + except requests.exceptions.ConnectionError as e: + sleep(1) + continue + break + return r.content + + def tracker_start_request(self): + tc = self.torrentclient + headers = tc.get_headers() + params = tc.get_query(uploaded=0, + downloaded=0, + event='started') + + print('----------- First Command to Tracker --------') + content = self.send_request(params, headers) + self.tracker_response_parser(content) + + def tracker_response_parser(self, tr_response): + b_enc = bencoding() + response = b_enc.bdecode(tr_response) + print('----------- Received Tracker Response --------') + print(pretty_data(response)) + raw_peers = b_enc.get_dict('peers') + i = 0 + peers = [] + while i') + parser.add_argument("-c", "--configuration", help="Configuration file") + return parser.parse_args() + +def load_configuration(configuration_file): + with open(configuration_file) as f: + configuration = json.load(f) + + if 'torrent' not in configuration: + return None + + return configuration + + +if __name__ == "__main__": + args = parse_args() + if args.configuration: + configuration = load_configuration(args.configuration) + else: + sys.exit() + + if not configuration: + sys.exit() + + to = process_torrent(configuration) + to.tracker_process() + diff --git a/lib/ratiomaster/requirements.txt b/lib/ratiomaster/requirements.txt new file mode 100644 index 0000000..5bb8c66 --- /dev/null +++ b/lib/ratiomaster/requirements.txt @@ -0,0 +1,2 @@ +requests +tqdm