from rich.align import Align from rich.console import Console from rich.layout import Layout from rich.live import Live from rich.padding import Padding from rich.text import Text import json import random import requests import signal import time from denylist import get_deny_list denylist = get_deny_list() class Usr1Interrupt(Exception): def __init__(self, message): super().__init__(message) def handle_sigusr1(sig, frame): raise Usr1Interrupt("") signal.signal(signal.SIGUSR1, handle_sigusr1) def refresh_quotes(): res = None try: # Fetch quotes res = requests.get('https://mattermore.zeus.gent/quotes.json').json() assert len(res) > 150 res = res[-150:] except: pass if res is None: # Fallback: load last quotes try: with open('last_quotes.json') as f: res = json.load(f) except: assert False, "Failed to fetch quotes, and failed to load fallback json" else: try: # Fetched successfully # Save to disk for the fallback with open('last_quotes.json', 'w') as f: json.dump(res, f) except: pass # Only keep non-denied quotes res = [q for q in res if not any(denied in q['quote'] for denied in denylist)] return res def render_quote(quote): for i in range(len(quote['quote'])): l = Layout() l.split_column( Layout(f"Mattermost: ~{quote['channel']}", size=1), Layout(Align.center(Padding(quote['quote'][:i+1], (0, 4)), vertical="middle")), Layout(quote['created_at'][:10], size=1) ) yield l with Live( renderable=Layout(Align.center(Text("Yeet"), vertical="middle")), console=Console(highlighter=None), refresh_per_second=30 ) as live: first_it = True while True: try: quotes = refresh_quotes() for _ in range(500): for q in render_quote(random.choice(quotes) if not first_it else quotes[-1]): live.update(q) time.sleep(0.05) time.sleep(30) first_it = False except Usr1Interrupt: first_it = True pass