mirror of
https://github.com/ap-pauloafonso/ratio-spoof.git
synced 2026-04-19 15:42:03 +00:00
seeder/leecher print info, fix grammar documentation
This commit is contained in:
parent
b263d18938
commit
c23b5261b1
2 changed files with 35 additions and 24 deletions
25
README.md
25
README.md
|
|
@ -1,13 +1,13 @@
|
|||
# ratio-spoof
|
||||
|
||||
ratio-spof is a cross-platform, free and open source tool to spoof private bittorrent trackers the amount downloaded or uploaded by the peer.
|
||||
|
||||
## Motivation
|
||||
Here in brazil, not everybody has a great upload speed, and most of the private trackers requires a ratio to be greater than or equal to 1 (e.g. if you downloaded 1gb you must upload 1gb as well) in order to survive. Plus, i have always been fascinated by the bittorrent protocol, [i even made a bittorrent webclient to learn a bit about it ](https://github.com/ap-pauloafonso/rwTorrent) so with the current global covid-19 lockdown i got some free time and decided to code my own simple cli tool to spoof bittorrent trackers.
|
||||
|
||||
## How does it works?
|
||||
The way that bittorrent protocol works is that there is no way that a tracker knows how much certain peer downloaded or uploaded, so it depends on the peer itself telling them how much they downloaded or uploaded.
|
||||
|
||||
With this protocol deisgn, ratio-spoof acts like a normal bittorrent client but without downloading or uploading anything, in fact it just tricks the tracker pretending that.
|
||||
The way that a bittorrent protocol works is that there is no way that a tracker knows how much certain peer downloaded or uploaded, so it depends on the peer itself telling them how much they downloaded or uploaded.
|
||||
|
||||
Ratio-spoof acts like a normal bittorrent client but without downloading or uploading anything, in fact it just tricks the tracker pretending that.
|
||||
|
||||
## Usage
|
||||
With a recent python3 version installed, you will be able to run it on linux/macos/windows.
|
||||
|
|
@ -33,23 +33,22 @@ required arguments:
|
|||
```
|
||||
./ratio-spoof -d 90% 100kbps -u 0% 1024kbps -t (torrentfile_path)
|
||||
```
|
||||
Will start "downloading" with the initial value of 90% of the torrent total size at 100 kbps speed until it reaches 100% mark.
|
||||
Will start "uploading" with the initial value of 0% of the torrent total size at 1024kbps (aka 1mb/s) indefinitely
|
||||
* Will start "downloading" with the initial value of 90% of the torrent total size at 100 kbps speed until it reaches 100% mark.
|
||||
* Will start "uploading" with the initial value of 0% of the torrent total size at 1024kbps (aka 1mb/s) indefinitely.
|
||||
|
||||
```
|
||||
./ratio-spoof -d 2gb 500kbps -u 1gb 1024kbps -t (torrentfile_path)
|
||||
```
|
||||
Will start "downloading" with the initial value of 2gb downloaded if possible at 500kbps speed until it reaches 100% mark.
|
||||
Will start "uploading" with the initial value of 1gb uplodead at 1024kbps (aka 1mb/s) indefinitely
|
||||
* Will start "downloading" with the initial value of 2gb downloaded if possible at 500kbps speed until it reaches 100% mark.
|
||||
* Will start "uploading" with the initial value of 1gb uplodead at 1024kbps (aka 1mb/s) indefinitely.
|
||||
|
||||
## Will i get cought using it ?
|
||||
Depends wether you use it carefuly, Its a hard task to catch cheaters, but if you start to uploading crazy amounts out of nowhere or seeding something with no active leecher you may be in risk.
|
||||
|
||||
A good strategy is to chose torrents with a lot of people on the swarn downloading and uploading.
|
||||
Depends wether you use it carefuly, Its a hard task to catch cheaters, but if you start uploading crazy amounts out of nowhere or seeding something with no active leecher on the swarm you may be in risk.
|
||||
|
||||
## Bittorrent client supported
|
||||
The currently emulation is hard coded to be a popular and accepted client qbittorrent v4.0.3.
|
||||
|
||||
## Motivation
|
||||
Here in brazil, not everybody has a great upload speed, and most of the private trackers requires a ratio to be equal or higher than 1 (e.g. if you downloaded 1gb you must upload 1gb as well) in order to survive. Plus, i always been facinated by the bittorrent protocol, [i even made a bittorrent webclient to learn a bit about it.](https://github.com/ap-pauloafonso/rwTorrent) and with the current global covid-19 lockdown i got some free time and decide to code my own simple cli tool to spoof bittorrent trackers.
|
||||
## Resources
|
||||
http://www.bittorrent.org/beps/bep_0003.html
|
||||
https://wiki.theory.org/index.php/BitTorrentSpecification
|
||||
|
||||
|
|
|
|||
|
|
@ -41,15 +41,17 @@ class RatioSpoofState():
|
|||
self.announce_history_deq = deque(maxlen=10)
|
||||
self.deq_count = 0
|
||||
self.numwant = 200
|
||||
self.seeders = None
|
||||
self.leechers = None
|
||||
self.__add_announce(current_downloaded, current_uploaded ,next_announce_left_b(current_downloaded, total_size))
|
||||
threading.Thread(daemon = True, target = (lambda: self.__print_state())).start()
|
||||
threading.Thread(daemon = True, target = (lambda: self.__decrease_timer())).start()
|
||||
|
||||
def start_announcing(self):
|
||||
announce_rate = self.__announce('started')
|
||||
announce_interval = self.__announce('started')
|
||||
threading.Thread(daemon = True, target = (lambda: self.__decrease_timer())).start()
|
||||
threading.Thread(daemon = True, target = (lambda: self.__print_state())).start()
|
||||
while True:
|
||||
self.__generate_next_announce(announce_rate)
|
||||
time.sleep(announce_rate)
|
||||
self.__generate_next_announce(announce_interval)
|
||||
time.sleep(announce_interval)
|
||||
self.__announce()
|
||||
|
||||
def __add_announce(self, current_downloaded, current_uploaded, left):
|
||||
|
|
@ -66,7 +68,7 @@ class RatioSpoofState():
|
|||
current_uploaded = next_announce_total_b(self.upload_speed,self.announce_history_deq[-1]['uploaded'], self.piece_size, self.announce_rate)
|
||||
current_left = next_announce_left_b(current_downloaded, self.total_size)
|
||||
self.__add_announce(current_downloaded,current_uploaded,current_left)
|
||||
|
||||
|
||||
def __announce(self, event = None):
|
||||
last_announce_data = self.announce_history_deq[-1]
|
||||
query_dict = build_query_string(self, last_announce_data, event)
|
||||
|
|
@ -77,17 +79,25 @@ class RatioSpoofState():
|
|||
for tier_list in self.announce_info['list_of_lists']:
|
||||
for item in tier_list:
|
||||
try:
|
||||
return tracker_announce_request(item, query_dict)
|
||||
announce_response = tracker_announce_request(item, query_dict)
|
||||
self.__update_seeders_and_leechers(announce_response)
|
||||
return announce_response['interval']
|
||||
except Exception as e : error = str(e)
|
||||
|
||||
else:
|
||||
url = self.announce_info['main']
|
||||
try:
|
||||
return tracker_announce_request(url, query_dict)
|
||||
announce_response = tracker_announce_request(url, query_dict)
|
||||
self.__update_seeders_and_leechers(announce_response)
|
||||
return announce_response['interval']
|
||||
except Exception as e : error = str(e)
|
||||
|
||||
raise Exception(f'Connection error with the tracker: {error}')
|
||||
|
||||
def __update_seeders_and_leechers(self, dict):
|
||||
self.seeders = dict['seeders']
|
||||
self.leechers = dict['leechers']
|
||||
|
||||
def __decrease_timer(self):
|
||||
while True:
|
||||
time.sleep(1)
|
||||
|
|
@ -102,10 +112,13 @@ class RatioSpoofState():
|
|||
|
||||
def __print_state(self):
|
||||
while True:
|
||||
clear_screen()
|
||||
print(' RATIO-SPOOF '.center(shutil.get_terminal_size().columns,'#'))
|
||||
print(f"""
|
||||
Torrent: {self.torrent_name}
|
||||
Tracker:{self.announce_info['main']}
|
||||
Tracker: {self.announce_info['main']}
|
||||
Seeders: {self.seeders if self.seeders !=None else 'not informed'}
|
||||
Leechers: {self.leechers if self.leechers !=None else 'not informed'}
|
||||
Download Speed: {self.download_speed}KB/s
|
||||
Upload Speed: {self.upload_speed}KB/s
|
||||
Size: {human_readable_size(self.total_size)}
|
||||
|
|
@ -115,7 +128,6 @@ class RatioSpoofState():
|
|||
for item in list(self.announce_history_deq)[:len(self.announce_history_deq)-1]:
|
||||
print(f'#{item["count"]} downloaded: {human_readable_size(item["downloaded"])}({item["percent"]}%) | left: {human_readable_size(item["left"])} | uploaded: {human_readable_size(item["uploaded"])} | announced')
|
||||
print(f'#{self.announce_history_deq[-1]["count"]} downloaded: {human_readable_size(self.announce_history_deq[-1]["downloaded"])}({self.announce_history_deq[-1]["percent"]}%) | left: {human_readable_size(self.announce_history_deq[-1]["left"])} | uploaded: {human_readable_size(self.announce_history_deq[-1]["uploaded"])} | next announce in :{str(datetime.timedelta(seconds=self.announce_current_timer))}')
|
||||
clear_screen()
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
|
|
@ -199,7 +211,7 @@ def tracker_announce_request(url, query_string):
|
|||
interval = decoded_response.get('interval',None)
|
||||
|
||||
if 'interval' is not None:
|
||||
return int(decoded_response['interval'])
|
||||
return { 'interval': int(decoded_response['interval']), 'seeders': decoded_response.get('complete'), 'leechers': decoded_response.get('incomplete') }
|
||||
else: raise Exception(json.dumps(decoded_response))
|
||||
|
||||
def build_query_string(state:RatioSpoofState, curent_info, event):
|
||||
|
|
|
|||
Loading…
Reference in a new issue