#!/usr/bin/python3
from sys import path, argv
path.append("..")
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()