159 lines
5 KiB
Python
159 lines
5 KiB
Python
#!/usr/bin/python3
|
|
import bare, pylast
|
|
import config as conf
|
|
import random as r
|
|
from logs import log
|
|
from typing import Any, Callable, NoReturn
|
|
from threading import Thread
|
|
from time import sleep
|
|
from traceback import format_exc
|
|
|
|
|
|
def is_dead(thr: Thread) -> bool:
|
|
thr.join(timeout=0)
|
|
return not thr.is_alive()
|
|
|
|
|
|
def threadWrapper(data: dict) -> NoReturn:
|
|
if not data["noWrap"]:
|
|
while 1:
|
|
if data["ignoreErrors"]:
|
|
try:
|
|
data["func"](*data["args"])
|
|
except Exception:
|
|
Err = format_exc()
|
|
for line in Err.split("\n"):
|
|
log(line, "Thread", "WARN")
|
|
else:
|
|
try:
|
|
data["func"](*data["args"])
|
|
except Exception:
|
|
Err = format_exc()
|
|
for line in Err.split("\n"):
|
|
log(line, "Thread", "CRASH")
|
|
exit(1)
|
|
sleep(data["interval"])
|
|
log("Threaded loop broken", "Thread", "FATAL")
|
|
else:
|
|
data["func"](*data["args"])
|
|
exit(1)
|
|
|
|
|
|
def startThread(data: dict) -> Thread:
|
|
t = Thread(target=threadWrapper, args=(data,))
|
|
t.daemon = True
|
|
t.start()
|
|
return t
|
|
|
|
|
|
def threadManager(
|
|
threads: dict[str, dict[str, Any]],
|
|
output: bool = False,
|
|
mgr: str = "TManager",
|
|
interval: int = 60,
|
|
) -> NoReturn:
|
|
if output:
|
|
log("Begin init of thread manager", mgr)
|
|
running = {}
|
|
for name in threads:
|
|
data = threads[name]
|
|
running[name] = startThread(data)
|
|
if output:
|
|
log("All threads running, starting checkup loop", mgr)
|
|
while 1:
|
|
sleep(interval)
|
|
if output:
|
|
log("Checking threads", mgr)
|
|
for name in running:
|
|
t = running[name]
|
|
if is_dead(t):
|
|
if output:
|
|
log(f"Thread {name} has died, restarting", mgr, "WARN")
|
|
data = threads[name]
|
|
running[name] = startThread(data)
|
|
log("Thread manager loop broken", mgr, "FATAL")
|
|
exit(1)
|
|
|
|
|
|
def radio(instance: bare.bot) -> NoReturn:
|
|
lastTrack = ""
|
|
complained = False
|
|
firstMiss = False
|
|
misses = 0
|
|
missChunk = 0
|
|
missCap = -5
|
|
perChunk = 10
|
|
debug = False # instance.server == "replirc"
|
|
while 1:
|
|
try:
|
|
newTrack = instance.lastfmLink.get_user("Firepup650").get_now_playing()
|
|
if newTrack:
|
|
if complained:
|
|
complained = False
|
|
misses = 0
|
|
missChunk = 0
|
|
elif misses > missCap:
|
|
missChunk += 1
|
|
if missChunk >= perChunk:
|
|
misses -= 1
|
|
missChunk = 0
|
|
thisTrack = newTrack.__str__()
|
|
if thisTrack != lastTrack:
|
|
lastTrack = thisTrack
|
|
instance.msg("f.sp " + thisTrack, "#fp-radio")
|
|
instance.sendraw(
|
|
f"TOPIC #fp-radio :Firepup radio ({thisTrack}) - https://open.spotify.com/playlist/4ctNy3O0rOwhhXIKyLvUZM"
|
|
)
|
|
elif not complained:
|
|
missChunk = 0
|
|
if misses < 0:
|
|
misses += 1
|
|
if debug:
|
|
instance.msg(
|
|
str(
|
|
{
|
|
"misses": misses,
|
|
"missChunk": missChunk,
|
|
"misses exceed or meet limit": misses <= missCap,
|
|
}
|
|
),
|
|
"#fp-radio-debug",
|
|
)
|
|
sleep(2)
|
|
continue
|
|
instance.msg(
|
|
"Firepup seems to have stopped the music by mistake :/", "#fp-radio"
|
|
)
|
|
instance.sendraw(
|
|
"TOPIC #fp-radio :Firepup radio (Offline) - https://open.spotify.com/playlist/4ctNy3O0rOwhhXIKyLvUZM"
|
|
)
|
|
complained = True
|
|
lastTrack = "null"
|
|
except Exception:
|
|
Err = format_exc()
|
|
for line in Err.split("\n"):
|
|
instance.log(line, "WARN")
|
|
if debug:
|
|
instance.msg(
|
|
str(
|
|
{
|
|
"misses": misses,
|
|
"missChunk": missChunk,
|
|
"misses exceed or meet limit": misses <= missCap,
|
|
}
|
|
),
|
|
"#fp-radio-debug",
|
|
)
|
|
sleep(2)
|
|
instance.log("Thread while loop broken", "FATAL")
|
|
exit(1)
|
|
|
|
def ping(instance: bare.bot) -> NoReturn:
|
|
while 1:
|
|
instance.sendraw("PING :keepalive")
|
|
sleep(30)
|
|
|
|
data: dict[str, dict[str, Any]] = {
|
|
"radio": {"noWrap": True, "func": radio, "passInstance": True},
|
|
"pingMon": {"noWrap": True, "func": ping, "passInstance": True}
|
|
}
|