From c8e62965646dcebab56e7a41f381be957bcc18e7 Mon Sep 17 00:00:00 2001 From: DjLegolas Date: Sat, 26 Feb 2022 12:54:59 +0200 Subject: [PATCH] [Tracker] Add a status for all trackers in a torrent As part of the changes needed for a more informative trackers tab in the UIs, we need the info for each of the trackers in the torrent. For this, new status keys were added, and `tracker_status` is now considered deprecated. For tracker info, the keys are: `trackers_status` - a dict of tracker_url->{status, message} `trackers_peers` - a dict of tracker_url->number of peers in the tracker `trackers_status` will contain the status of the torrent and also the message from the relevant alert. --- deluge/core/torrent.py | 44 ++++++++++++++++++++++++++++++----- deluge/core/torrentmanager.py | 18 +++++++++----- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/deluge/core/torrent.py b/deluge/core/torrent.py index 1b52c86772..96e3231746 100644 --- a/deluge/core/torrent.py +++ b/deluge/core/torrent.py @@ -17,7 +17,7 @@ import os import socket import time -from typing import Optional, List +from typing import List, Optional from urllib.parse import urlparse from twisted.internet.defer import Deferred, DeferredList @@ -265,6 +265,8 @@ def __init__(self, handle, options, state=None, filename=None, magnet=None): self.state = None self.moving_storage_dest_path = None self.tracker_status = '' + self.trackers_status = {} + self.trackers_peers = {} self.tracker_host = None self.forcing_recheck = False self.forcing_recheck_paused = False @@ -648,11 +650,13 @@ def trackers(self, trackers: List['lt.announce_entry']) -> None: self._trackers = trackers self._trackers_last_update = time.time() - def set_tracker_status(self, status): + def set_tracker_status(self, status: str, tracker_url: str, message: str = ''): """Sets the tracker status. Args: - status (str): The tracker status. + status: The tracker status. + tracker_url: The tracker url. + message: The message from tracker error/warning alerts Emits: TorrentTrackerStatusEvent upon tracker status change. @@ -661,12 +665,35 @@ def set_tracker_status(self, status): self.tracker_host = None - if self.tracker_status != status: - self.tracker_status = status + if self.state == 'Paused': + return + + if self.trackers_status.get(tracker_url, {}).get('status') != status: + self.trackers_status[tracker_url] = { + 'status': status, + 'message': message, + } + self.tracker_status = f'{status}{f": {message}" if message else ""}' component.get('EventManager').emit( - TorrentTrackerStatusEvent(self.torrent_id, self.tracker_status) + TorrentTrackerStatusEvent( + self.torrent_id, + self.trackers_status[tracker_url], + ) ) + def set_tracker_peers(self, peers: int, tracker_url: str): + """Sets the tracker peers amount + + Args: + peers: The number of peers the tracker has. + tracker_url: The tracker url. + """ + if self.state == 'Paused': + return + + if self.trackers_peers.get(tracker_url) != peers: + self.trackers_peers[tracker_url] = peers + def merge_trackers(self, torrent_info): """Merges new trackers in torrent_info into torrent""" log.info( @@ -709,6 +736,8 @@ def update_state(self): self.state = 'Queued' elif session_paused or status.paused: self.state = 'Paused' + self.trackers_peers = {} + self.trackers_status = {} else: self.state = LT_TORRENT_STATE_MAP.get(str(status.state), str(status.state)) @@ -1201,7 +1230,10 @@ def _create_status_funcs(self): 'tracker': lambda: self.status.current_tracker, 'tracker_host': self.get_tracker_host, 'trackers': lambda: self.trackers, + # Deprecated: Use trackers_status 'tracker_status': lambda: self.tracker_status, + 'trackers_status': lambda: self.trackers_status, + 'trackers_peers': lambda: self.trackers_peers, 'upload_payload_rate': lambda: self.status.upload_payload_rate, 'comment': lambda: decode_bytes(self.torrent_info.comment()) if self.has_metadata diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index b506d932ff..f551708472 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -1347,7 +1347,9 @@ def on_alert_tracker_reply(self, alert): return # Set the tracker status for the torrent - torrent.set_tracker_status('Announce OK') + torrent.set_tracker_status('Announce OK', alert.url) + # Set the amount of peers of the tracker + torrent.set_tracker_peers(alert.num_peers, alert.url) # Check for peer information from the tracker, if none then send a scrape request. torrent.get_lt_status() @@ -1362,7 +1364,7 @@ def on_alert_tracker_announce(self, alert): return # Set the tracker status for the torrent - torrent.set_tracker_status('Announce Sent') + torrent.set_tracker_status('Announce Sent', alert.url) def on_alert_tracker_warning(self, alert): """Alert handler for libtorrent tracker_warning_alert""" @@ -1371,7 +1373,11 @@ def on_alert_tracker_warning(self, alert): except (RuntimeError, KeyError): return # Set the tracker status for the torrent - torrent.set_tracker_status('Warning: %s' % decode_bytes(alert.message())) + torrent.set_tracker_status( + 'Warning', + alert.url, + decode_bytes(alert.warning_message()), + ) def on_alert_tracker_error(self, alert): """Alert handler for libtorrent tracker_error_alert""" @@ -1384,7 +1390,7 @@ def on_alert_tracker_error(self, alert): if not error_message: error_message = decode_bytes(alert.error.message()) log.debug( - 'Tracker Error Alert: %s [%s]', decode_bytes(alert.message()), error_message + f'Tracker Error Alert: {decode_bytes(alert.message())} [{error_message}]' ) # libtorrent 1.2 added endpoint struct to each tracker. to prevent false updates # we will need to verify that at least one endpoint to the errored tracker is working @@ -1394,9 +1400,9 @@ def on_alert_tracker_error(self, alert): endpoint['last_error']['value'] == 0 for endpoint in tracker['endpoints'] ): - torrent.set_tracker_status('Announce OK') + torrent.set_tracker_status('Announce OK', alert.url) else: - torrent.set_tracker_status('Error: ' + error_message) + torrent.set_tracker_status('Error', alert.url, error_message) break def on_alert_storage_moved(self, alert):