Skip to content

Instantly share code, notes, and snippets.

@yacn
Last active May 15, 2021 10:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yacn/3ae8e208d329fa9351f4eac5ca2941f1 to your computer and use it in GitHub Desktop.
Save yacn/3ae8e208d329fa9351f4eac5ca2941f1 to your computer and use it in GitHub Desktop.
Script showing how to read deluge's torrent state. only tested on 1.3.15
#!/usr/bin/env python3
import argparse
import collections
import io
import os
import pickle
import sys
def existing_file(p):
if not p: return p
if not os.path.exists(p):
print(f"{p} does not exist")
sys.exit(1)
return p
parser = argparse.ArgumentParser()
parser.add_argument("--torrent-state-file", type=existing_file, help="path to deluge statefile to read", default=None)
parser.add_argument("--verbose", action="store_true", help="print out all <label>/<torrent_id> pairs", default=False)
"""
below copied from
https://github.com/deluge-torrent/deluge/blob/1.3-stable/deluge/core/torrentmanager.py
"""
class TorrentState:
def __init__(self,
torrent_id=None,
filename=None,
total_uploaded=0,
trackers=None,
compact=False,
paused=False,
save_path=None,
max_connections=-1,
max_upload_slots=-1,
max_upload_speed=-1.0,
max_download_speed=-1.0,
prioritize_first_last=False,
file_priorities=None,
queue=None,
auto_managed=True,
is_finished=False,
stop_ratio=2.00,
stop_at_ratio=False,
remove_at_ratio=False,
move_completed=False,
move_completed_path=None,
magnet=None,
time_added=-1
):
self.torrent_id = torrent_id
self.filename = filename
self.total_uploaded = total_uploaded
self.trackers = trackers
self.queue = queue
self.is_finished = is_finished
self.magnet = magnet
self.time_added = time_added
# Options
self.compact = compact
self.paused = paused
self.save_path = save_path
self.max_connections = max_connections
self.max_upload_slots = max_upload_slots
self.max_upload_speed = max_upload_speed
self.max_download_speed = max_download_speed
self.prioritize_first_last = prioritize_first_last
self.file_priorities = file_priorities
self.auto_managed = auto_managed
self.stop_ratio = stop_ratio
self.stop_at_ratio = stop_at_ratio
self.remove_at_ratio = remove_at_ratio
self.move_completed = move_completed
self.move_completed_path = move_completed_path
def __eq__(self, other):
return isinstance(other, TorrentState) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not self == other
class TorrentManagerState:
def __init__(self):
self.torrents = []
def __eq__(self, other):
return isinstance(other, TorrentManagerState) and self.torrents == other.torrents
def __ne__(self, other):
return not self == other
# my stuff
class LocalUnpickler(pickle.Unpickler):
"""
look for classes in this module
"""
def find_class(self, module, name):
return super().find_class(__name__, name)
def load_torrent_state(path):
with open(path, 'rb') as f:
return LocalUnpickler(f).load()
tracker_to_label = {
'tracker_a.com': 'a',
'tracker_b.org': 'b',
'tracker_c.net': 'c'
}
tracker_url_to_label = {}
label_to_torrents = {}
if __name__ == "__main__":
args = parser.parse_args()
if not args.torrent_state_file:
print("nothing to do")
sys.exit(0)
state = load_torrent_state(args.torrent_state_file)
for torrent in state.torrents:
if not torrent.trackers: continue
tracker_url = torrent.trackers[0]["url"]
if tracker_url not in tracker_url_to_label:
for t, label in tracker_to_label.items():
if t in tracker_url:
tracker_url_to_label[tracker_url] = label
label = tracker_url_to_label[tracker_url] if tracker_url in tracker_url_to_label else "public"
if label not in label_to_torrents:
label_to_torrents[label] = []
label_to_torrents[label].append(torrent)
for label, torrents in label_to_torrents.items():
print(f"{label}({len(torrents)})")
if args.verbose:
for torrent in torrents:
print(f"{label}/{torrent.torrent_id}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment