1 import libtorrent as lt 2 import time 3 import os 4 5 # Global session object (consider managing this better in a full app) 6 ses = lt.session({'listen_interfaces': '0.0.0.0:6881'}) 7 downloads = {} 8 9 DEFAULT_SAVE_PATH = os.path.join(os.getcwd(), 'downloads') 10 if not os.path.exists(DEFAULT_SAVE_PATH): 11 os.makedirs(DEFAULT_SAVE_PATH) 12 13 def add_torrent(magnet_link, save_path=DEFAULT_SAVE_PATH): 14 """Adds a torrent using a magnet link.""" 15 params = { 16 'save_path': save_path, 17 'storage_mode': lt.storage_mode_t(2), # storage_mode_sparse 18 } 19 try: 20 handle = lt.add_magnet_uri(ses, magnet_link, params) 21 handle.set_sequential_download(True) # Good for streaming 22 downloads[handle.info_hash()] = handle 23 print(f"Torrent added: {handle.name() if handle.has_metadata() else 'Fetching metadata...'}") 24 return handle.info_hash() 25 except Exception as e: 26 print(f"Error adding torrent: {e}") 27 return None 28 29 def get_status(info_hash): 30 """Returns current status of a torrent""" 31 if info_hash not in downloads: 32 return {'error': 'Invalid info_hash'} 33 34 handle = downloads[info_hash]['handle'] 35 status = handle.status() 36 37 return { 38 'progress': round(status.progress * 100, 2), 39 'download_rate': status.download_rate, 40 'num_peers': status.num_peers, 41 'state': str(status.state).split('.')[1], 42 'name': status.name, 43 'total_size': status.total_wanted 44 } 45 46 def get_streamable_files(info_hash): 47 """Returns list of completed media files for streaming""" 48 if info_hash not in downloads: 49 return {'error': 'Invalid info_hash'} 50 51 handle = downloads[info_hash]['handle'] 52 status = handle.status() 53 54 if not status.is_seeding: 55 return {'status': 'Download not complete'} 56 57 save_path = downloads[info_hash]['save_path'] 58 torrent_info = handle.get_torrent_info() 59 files = [] 60 61 for idx in range(torrent_info.num_files()): 62 file_entry = torrent_info.file_at(idx) 63 if file_entry.size > 0: 64 files.append({ 65 'path': os.path.join(save_path, file_entry.path), 66 'size': file_entry.size, 67 'name': os.path.basename(file_entry.path) 68 }) 69 70 return {'files': files} 71 72 def get_all_torrents_status(): 73 """Gets the status of all active torrents.""" 74 return {str(info_hash): get_torrent_status(info_hash) for info_hash in downloads.keys()} 75 76 # Example usage (can be removed or moved to app.py) 77 if __name__ == '__main__': 78 # Replace with a real magnet link for testing 79 test_magnet = "magnet:?xt=urn:btih:YOUR_TORRENT_INFO_HASH_HERE" 80 info_hash = add_torrent(test_magnet) 81 82 if info_hash: 83 print(f"Added torrent with info_hash: {info_hash}") 84 while True: 85 status = get_torrent_status(info_hash) 86 print(f"Status: {status['status']}, Progress: {status['progress']:.2f}%, Peers: {status['num_peers']}") 87 if status['status'] == 'finished' or status['status'] == 'seeding': 88 print("Download finished!") 89 break 90 time.sleep(5) 91 else: 92 print("Failed to add torrent.")