summaryrefslogtreecommitdiffstats
path: root/radio/radio.py
blob: f3cbca82a8213d5a5e313badf80daff48b1adf60 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/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()