9
9
import base64
10
10
import itertools
11
11
import logging
12
- from asyncio import CancelledError , Future , get_running_loop , sleep , wait_for
12
+ from asyncio import CancelledError , Future , sleep , wait_for
13
13
from binascii import hexlify
14
14
from collections import defaultdict
15
15
from collections .abc import Callable
27
27
from tribler .core .libtorrent .download_manager .download_state import DownloadState , DownloadStatus
28
28
from tribler .core .libtorrent .download_manager .stream import Stream
29
29
from tribler .core .libtorrent .torrent_file_tree import TorrentFileTree
30
- from tribler .core .libtorrent .torrentdef import MetainfoDict , TorrentDef , TorrentDefNoMetainfo
30
+ from tribler .core .libtorrent .torrentdef import TorrentDef
31
31
from tribler .core .libtorrent .torrents import check_handle , get_info_from_handle , require_handle
32
32
from tribler .core .notifier import Notification , Notifier
33
33
from tribler .tribler_config import TriblerConfigManager
36
36
from collections .abc import Awaitable
37
37
38
38
from tribler .core .libtorrent .download_manager .download_manager import DownloadManager
39
+ from tribler .core .libtorrent .torrentdef import MetainfoDict
39
40
40
41
Getter = Callable [[Any ], Any ]
41
42
@@ -162,15 +163,15 @@ def __init__(self, # noqa: PLR0913
162
163
elif config is None :
163
164
self .config = DownloadConfig .from_defaults (TriblerConfigManager ())
164
165
165
- self ._logger .debug ("Setup: %s" , hexlify (self .tdef .get_infohash () ).decode ())
166
+ self ._logger .debug ("Setup: %s" , hexlify (self .tdef .infohash ).decode ())
166
167
167
168
self .checkpoint ()
168
169
169
170
def __str__ (self ) -> str :
170
171
"""
171
172
Convert this download to a human-readable string.
172
173
"""
173
- return (f"Download(name={ self .tdef .get_name () } , "
174
+ return (f"Download(name={ self .tdef .name } , "
174
175
f"hops={ self .config .get_hops ():d} , "
175
176
f"checkpoint_disabled={ self .checkpoint_disabled :d} )" )
176
177
@@ -282,7 +283,7 @@ def get_atp(self) -> dict:
282
283
atp ["flags" ] = cast ("int" , atp ["flags" ]) | lt .add_torrent_params_flags_t .flag_upload_mode
283
284
284
285
resume_data = self .config .get_engineresumedata ()
285
- if not isinstance ( self .tdef , TorrentDefNoMetainfo ) :
286
+ if self .tdef . torrent_info is not None :
286
287
metainfo = self .tdef .get_metainfo ()
287
288
torrentinfo = lt .torrent_info (metainfo )
288
289
@@ -295,8 +296,8 @@ def get_atp(self) -> dict:
295
296
resume_data [b"save_path" ] = str (self .state_dir / save_path )
296
297
atp ["resume_data" ] = lt .bencode (resume_data )
297
298
else :
298
- atp ["url" ] = self .tdef .get_url () or "magnet:?xt=urn:btih:" + hexlify (self .tdef .get_infohash () ).decode ()
299
- atp ["name" ] = self .tdef .get_name_as_unicode ()
299
+ atp ["url" ] = self .tdef .atp . url or "magnet:?xt=urn:btih:" + hexlify (self .tdef .infohash ).decode ()
300
+ atp ["name" ] = self .tdef .atp . name
300
301
301
302
return atp
302
303
@@ -307,7 +308,7 @@ def on_add_torrent_alert(self, alert: lt.add_torrent_alert) -> None:
307
308
self ._logger .info ("On add torrent alert: %s" , repr (alert ))
308
309
309
310
if hasattr (alert , "error" ) and alert .error .value ():
310
- self ._logger .error ("Failed to add torrent (%s)" , self .tdef .get_name_as_unicode () )
311
+ self ._logger .error ("Failed to add torrent (%s)" , self .tdef .name )
311
312
raise RuntimeError (alert .error .message ())
312
313
if not alert .handle .is_valid ():
313
314
self ._logger .error ("Received invalid torrent handle" )
@@ -405,11 +406,11 @@ def on_state_changed_alert(self, alert: lt.state_changed_alert) -> None:
405
406
self .update_lt_status (self .handle .status ())
406
407
407
408
enable = alert .state == lt .torrent_status .seeding and self .config .get_hops () > 0
408
- self ._logger .debug ("Setting IP filter for %s to %s" , hexlify (self .tdef .get_infohash () ), enable )
409
+ self ._logger .debug ("Setting IP filter for %s to %s" , hexlify (self .tdef .infohash ), enable )
409
410
self .apply_ip_filter (enable )
410
411
411
412
# On a rare occasion we don't get a metadata_received_alert. If this is the case, post an alert manually.
412
- if alert .state == lt .torrent_status .downloading and isinstance ( self .tdef , TorrentDefNoMetainfo ) :
413
+ if alert .state == lt .torrent_status .downloading and self .tdef . torrent_info is None :
413
414
self .post_alert ("metadata_received_alert" )
414
415
415
416
def on_save_resume_data_alert (self , alert : lt .save_resume_data_alert ) -> None :
@@ -429,22 +430,22 @@ def on_save_resume_data_alert(self, alert: lt.save_resume_data_alert) -> None:
429
430
save_path = Path (resume_data [b"save_path" ].decode ()).absolute ()
430
431
resume_data [b"save_path" ] = str (save_path )
431
432
432
- if not isinstance ( self .tdef , TorrentDefNoMetainfo ) :
433
+ if self .tdef . torrent_info is not None :
433
434
self .config .set_metainfo (self .tdef .get_metainfo ())
434
435
else :
435
436
self .config .set_metainfo ({
436
- "infohash" : self .tdef .get_infohash () ,
437
- "name" : self .tdef .get_name_as_unicode () ,
438
- "url" : self .tdef .get_url ()
437
+ "infohash" : self .tdef .infohash ,
438
+ "name" : self .tdef .name ,
439
+ "url" : self .tdef .atp . url
439
440
})
440
441
self .config .set_engineresumedata (resume_data )
441
442
442
443
# Save it to file
443
444
# Note resume_data[b"info-hash"] can be b"\x00" * 32, so we use the tdef.
444
- basename = hexlify (self .tdef .get_infohash () ).decode () + ".conf"
445
+ basename = hexlify (self .tdef .infohash ).decode () + ".conf"
445
446
Path (self .download_manager .get_checkpoint_dir ()).mkdir (parents = True , exist_ok = True )
446
447
filename = self .download_manager .get_checkpoint_dir () / basename
447
- self .config .config ["download_defaults" ]["name" ] = self .tdef .get_name_as_unicode () # store name (for debugging)
448
+ self .config .config ["download_defaults" ]["name" ] = self .tdef .name # store name (for debugging)
448
449
try :
449
450
self .config .write (filename )
450
451
except OSError as e :
@@ -533,7 +534,8 @@ def on_metadata_received_alert(self, alert: lt.metadata_received_alert) -> None:
533
534
self .set_def (TorrentDef .load_from_dict (metadata ))
534
535
with suppress (RuntimeError ):
535
536
# Try to load the torrent info in the background if we have a loop.
536
- get_running_loop ().run_in_executor (None , self .tdef .load_torrent_info )
537
+ self .register_anonymous_task (f"Load torrent info for { self .tdef .infohash .hex ()} " ,
538
+ self .tdef .load_torrent_info )
537
539
except ValueError as ve :
538
540
self ._logger .exception (ve )
539
541
return
@@ -573,7 +575,7 @@ def on_torrent_removed_alert(self, alert: lt.torrent_removed_alert) -> None:
573
575
"""
574
576
self ._logger .info ("On torrent remove alert: %s" , repr (alert ))
575
577
576
- self ._logger .debug ("Removing %s" , self .tdef .get_name () )
578
+ self ._logger .debug ("Removing %s" , self .tdef .name )
577
579
self .handle = None
578
580
579
581
def on_torrent_checked_alert (self , alert : lt .torrent_checked_alert ) -> None :
@@ -600,8 +602,8 @@ def on_torrent_finished_alert(self, alert: lt.torrent_finished_alert) -> None:
600
602
self .checkpoint ()
601
603
downloaded = self .get_state ().total_download
602
604
if downloaded > 0 and self .notifier is not None :
603
- name = self .tdef .get_name_as_unicode ()
604
- infohash = self .tdef .get_infohash () .hex ()
605
+ name = self .tdef .name
606
+ infohash = self .tdef .infohash .hex ()
605
607
self .notifier .notify (Notification .torrent_finished , infohash = infohash , name = name , hidden = self .hidden )
606
608
607
609
if self .config .get_completed_dir () and self .config .get_completed_dir () != self .config .get_dest_dir ():
@@ -619,7 +621,7 @@ def update_lt_status(self, lt_status: lt.torrent_status) -> None:
619
621
# Notify the GUI if the status has changed
620
622
if self .notifier and not self .hidden and state .get_status () != old_status :
621
623
self .notifier .notify (Notification .torrent_status_changed ,
622
- infohash = hexlify (self .tdef .get_infohash () ).decode (),
624
+ infohash = hexlify (self .tdef .infohash ).decode (),
623
625
status = state .get_status ().name )
624
626
625
627
if state .get_status () == DownloadStatus .SEEDING :
@@ -639,7 +641,7 @@ def set_selected_files(self, selected_files: list[int] | None = None, prio: int
639
641
"""
640
642
if not force and self .stream is not None :
641
643
return None
642
- if not isinstance ( self .tdef , TorrentDefNoMetainfo ) and not self .get_share_mode ():
644
+ if self .tdef . torrent_info is not None and not self .get_share_mode ():
643
645
if selected_files is None :
644
646
selected_files = self .config .get_selected_files ()
645
647
else :
@@ -667,7 +669,7 @@ def move_storage(self, new_dir: Path) -> bool:
667
669
"""
668
670
Move the output files to a different location.
669
671
"""
670
- if not isinstance ( self .tdef , TorrentDefNoMetainfo ) :
672
+ if self .tdef . torrent_info is not None :
671
673
self .handle = cast ("lt.torrent_handle" , self .handle )
672
674
self .handle .move_storage (str (new_dir ))
673
675
self .config .set_dest_dir (new_dir )
@@ -679,7 +681,7 @@ def force_recheck(self) -> None:
679
681
"""
680
682
Force libtorrent to validate the files.
681
683
"""
682
- if not isinstance ( self .tdef , TorrentDefNoMetainfo ) :
684
+ if self .tdef . torrent_info is not None :
683
685
self .handle = cast ("lt.torrent_handle" , self .handle )
684
686
if self .get_state ().get_status () == DownloadStatus .STOPPED :
685
687
self .pause_after_next_hashcheck = True
@@ -813,7 +815,7 @@ def get_tracker_status(self) -> dict[str, tuple[int, str]]:
813
815
pex_peers += 1
814
816
815
817
ltsession = self .download_manager .get_session (self .config .get_hops ()).result ()
816
- public = self .tdef and not self .tdef .is_private ( )
818
+ public = not ( self .tdef and self . tdef . torrent_info and self .tdef .atp . ti . priv () )
817
819
818
820
result = self .tracker_status .copy ()
819
821
result ["[DHT]" ] = (dht_peers , "Working" if ltsession .is_dht_running () and public else "Disabled" )
@@ -841,7 +843,7 @@ def stop(self, user_stopped: bool | None = None) -> Awaitable[None]:
841
843
"""
842
844
Stop downloading the download.
843
845
"""
844
- self ._logger .debug ("Stopping %s" , self .tdef .get_name () )
846
+ self ._logger .debug ("Stopping %s" , self .tdef .name )
845
847
if self .stream is not None :
846
848
self .stream .close ()
847
849
if user_stopped is not None :
@@ -855,7 +857,7 @@ def resume(self) -> None:
855
857
"""
856
858
Resume downloading the download.
857
859
"""
858
- self ._logger .debug ("Resuming %s" , self .tdef .get_name () )
860
+ self ._logger .debug ("Resuming %s" , self .tdef .name )
859
861
860
862
self .config .set_user_stopped (False )
861
863
@@ -867,7 +869,7 @@ def get_content_dest(self) -> Path:
867
869
"""
868
870
Returns the file to which the downloaded content is saved.
869
871
"""
870
- return self .config .get_dest_dir () / self .tdef .get_name_as_unicode ()
872
+ return self .config .get_dest_dir () / self .tdef .name
871
873
872
874
def checkpoint (self ) -> Awaitable [None ]:
873
875
"""
@@ -884,15 +886,15 @@ def checkpoint(self) -> Awaitable[None]:
884
886
if not self .handle or not self .handle .is_valid ():
885
887
# Libtorrent hasn't received or initialized this download yet
886
888
# 1. Check if we have data for this infohash already (don't overwrite it if we do!)
887
- basename = hexlify (self .tdef .get_infohash () ).decode () + ".conf"
889
+ basename = hexlify (self .tdef .infohash ).decode () + ".conf"
888
890
filename = Path (self .download_manager .get_checkpoint_dir () / basename )
889
891
if not filename .is_file ():
890
892
# 2. If there is no saved data for this infohash, checkpoint it without data so we do not
891
893
# lose it when we crash or restart before the download becomes known.
892
894
resume_data = self .config .get_engineresumedata () or {
893
895
b"file-format" : b"libtorrent resume file" ,
894
896
b"file-version" : 1 ,
895
- b"info-hash" : self .tdef .get_infohash ()
897
+ b"info-hash" : self .tdef .infohash
896
898
}
897
899
self .post_alert ("save_resume_data_alert" , {"resume_data" : resume_data })
898
900
return succeed (None )
@@ -902,10 +904,10 @@ def set_def(self, tdef: TorrentDef) -> None:
902
904
"""
903
905
Set the torrent definition for this download.
904
906
"""
905
- if (isinstance ( self .tdef , TorrentDefNoMetainfo ) and not isinstance ( tdef , TorrentDefNoMetainfo )
906
- and len (self .tdef .infohash ) != 20 ):
907
+ if (self .tdef . torrent_info is None and tdef . torrent_info is not None
908
+ and len (self .tdef .atp . info_hash . to_bytes () ) != 20 ):
907
909
# We store SHA-1 conf files. v2 torrents start with SHA-256 infohashes.
908
- basename = hexlify (self .tdef .get_infohash ()).decode () + ".conf"
910
+ basename = hexlify (self .tdef .atp . info_hash . to_bytes ()).decode () + ".conf"
909
911
Path (self .download_manager .get_checkpoint_dir () / basename ).unlink (missing_ok = True )
910
912
self .tdef = tdef
911
913
0 commit comments