#!/usr/bin/python3 from sys import path, argv from pathlib import Path path.append(Path(__file__).parent.parent.absolute()) from travnik import Torrent import inotify.adapters from threading import Thread from random import randrange from os import stat, path from time import sleep from pydub import AudioSegment from pydub.playback import play from socket import socket, AF_UNIX, AF_INET, SOCK_STREAM import libtorrent def random_file(torrent, save_path, endung=".flac"): def get_index_from_endung(chosen): for i in range(torrent.torrent_file().files().num_files()): if (torrent.torrent_file().files().file_path(i).endswith(endung)): if chosen == 0: return i break chosen -= 1 prios = [] for i in torrent.get_file_priorities(): prios.append(0) endungs = 0 for i in range(torrent.torrent_file().files().num_files()): if (torrent.torrent_file().files().file_path(i).endswith(endung)): endungs += 1 if endungs == 0: print("no more endungs") return False chosen = randrange(endungs) tries_left = endungs print(f"there are {endungs} {endung} files") while True: if tries_left == 0: print("no more tries") return False tries_left -= 1 try: p = save_path + "/" + torrent.torrent_file().files().file_path(get_index_from_endung(chosen)) print(f"trying path {p} with stat") stat(p) except FileNotFoundError: break else: chosen = (chosen + 1) % endungs; continue prios[get_index_from_endung(chosen)] = 4 torrent.prioritize_files(prios) print(f"random file {torrent.torrent_file().files().file_path(get_index_from_endung(chosen))} chosen to download") return True def watcher(session, torrents, s, d, active_torrents=10): i = inotify.adapters.Inotify() i.add_watch(d) for event in i.event_gen(yield_nones=False): (_, type_names, path, filename) = event if "IN_CLOSE_WRITE" in type_names and filename.endswith(".torrent"): t = Torrent() t.file(path + filename) for pth, size in t.paths(): if pth[-1].endswith(b'.flac'): info = libtorrent.torrent_info(path + filename) torr = session.add_torrent({"ti": info, "save_path": s}) random_file(torr, save_path=s); torrents.append(torr) if len(torrents) > active_torrents: session.remove_torrent(torrents[0]) del torrents[0] break def alerts(session, playstack, save_path, torrents): while True: session.wait_for_alert(86400*1000*21) for a in session.pop_alerts(): if a.category() & libtorrent.alert.category_t.error_notification: print(f"error notification alert from libtorrent: {a}") if type(a) == libtorrent.file_completed_alert: if a.handle.get_file_priorities()[a.index] != 4: continue playstack.append(a.handle.torrent_file().files().file_path(a.index)) if not random_file(a.handle, save_path): session.remove_torrent(a.handle) torrents.remove(a.handle) continue else: a.handle.resume() if type(a) in [libtorrent.external_ip_alert, libtorrent.listen_succeeded_alert, libtorrent.dht_get_peers_alert, libtorrent.dht_outgoing_get_peers_alert, libtorrent.dht_reply_alert, libtorrent.torrent_added_alert, libtorrent.state_changed_alert, libtorrent.torrent_resumed_alert, libtorrent.stats_alert, libtorrent.torrent_checked_alert, libtorrent.peer_connect_alert, libtorrent.alert, libtorrent.peer_disconnected_alert, libtorrent.incoming_connection_alert, libtorrent.block_downloading_alert, libtorrent.dht_bootstrap_alert, libtorrent.dht_announce_alert, libtorrent.block_finished_alert, libtorrent.piece_finished_alert, libtorrent.peer_unsnubbed_alert, libtorrent.peer_snubbed_alert, libtorrent.portmap_error_alert, libtorrent.block_timeout_alert, libtorrent.block_uploaded_alert, libtorrent.performance_alert, libtorrent.cache_flushed_alert]: continue print(f"{type(a)} | {a}") def stream(playstack, unix=None): if type(unix) is str: while True: # sock = socket(AF_INET, SOCK_STREAM) # sock.connect("tranzistor", 1234) sock = socket(AF_UNIX, SOCK_STREAM) sock.connect("/tmp/ls") sock.sendall(b"request.alive\r\n") sleep(1) data = sock.recv(256) a = data.split(b"\r")[0] if a == b"": sock.sendall(b"request.push " + bytes(playstack.pop(), encoding="utf-8")) sleep(1) else: while True: if len(playstack) == 0: sleep(1) continue song = AudioSegment.from_file(path.abspath(playstack.pop()), "flac") play(song) sleep(1) def progress(session, torrents): while True: for torr in torrents: s = torr.status() print(torr.torrent_file().name() + '\t%.2f%% complete (down: %.1f kB/s up: %.1f kB/s peers: %d) %s' % (s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, s.num_peers, s.state)) sleep(1) if __name__ == "__main__": session = libtorrent.session({"alert_mask": libtorrent.alert.category_t.all_categories}); torrents = [] playstack = [] save_path = "." torrents_path = "." unix = None if len(argv) > 1: save_path = argv[1] if len(argv) > 2: torrents_path = argv[2] if len(argv) > 3: unix = argv[3] w = Thread(target=watcher, args=(session, torrents, save_path, torrents_path)) a = Thread(target=alerts, args=(session, playstack, save_path, torrents)) p = Thread(target=progress, args=(session, torrents)) s = Thread(target=stream, args=(playstack, unix)) w.start() a.start() p.start() s.start() w.join() a.join() p.join() s.join()