FOULAB / foubot9000

0 stars 0 forks source link

Next event view would be nice #3

Closed kryma-foulab closed 1 month ago

kryma-foulab commented 1 month ago

Something like this

#!/bin/python3
import logging
import re
import urllib.request
from datetime import datetime

logging.getLogger().setLevel(logging.ERROR)

TERM_W = 210
TERM_H = 64
ICS_PATH = "https://foulab.org/ical/foulab.ics"

def actual_length(s: str) -> int:
    base_len = len(s)
    return base_len - sum([len(m.group(0)) for m in re.finditer("\033.*?m", s)])

def horiz_center(s: str):
    return " " * ((TERM_W - actual_length(s)) // 2) + s

def get_ics():
    with urllib.request.urlopen(ICS_PATH) as response:
        return response.read().decode("utf-8")

def get_events() -> list[tuple[str, datetime]]:
    """Returns a list of (name, datetime) tuples."""
    ics = get_ics()
    events = []
    for m in re.finditer("^BEGIN:VEVENT\\s*$(.*?)^END:VEVENT\\s*$", ics, flags=re.DOTALL | re.MULTILINE):
        event = m.group(1)
        try:
            name = re.search("^SUMMARY:(.*)\\s*$", event, flags=re.MULTILINE).group(1)
            dt = re.search("^DTSTART(?:.*)?:(.*?)\\s*$", event, flags=re.MULTILINE).group(1)
            events.append((name, datetime.strptime(dt, "%Y%m%dT%H%M%S")))
        except Exception:
            logging.warning(f"Could not parse event {event}", exc_info=True)
    return events

def format_event(event: tuple[str, datetime] | None):
    if event is None:
        return horiz_center("\033[2;37mNo events yet...\033[0;0m")
    elif len(event[0]) > TERM_W - 2:
        return (
            horiz_center(f"\033[1;33m{event[0][:TERM_W - 5]}...") +
            "\n" +
            horiz_center(f"{event[1].strftime('%d %h %I:%M %P')}\033[0;0m")
        )
    return (
        horiz_center(f"\033[1;33m{event[0]}") +
        "\n" +
        horiz_center(f"{event[1].strftime('%d %h %I:%M %P')}\033[0;0m")
    )

try:
    for event in get_events():
        if datetime.now() < event[1]:
            break
    else:
        event = None
    print("\n" * (TERM_H // 2 - 2))
    print(horiz_center("EVENT COMING UP:"))
    print(format_event(event))
except Exception:
    print("\n" * (TERM_H // 2 - 2))
    print(horiz_center("\033[1;91mGETTING EVENTS FAILED\033[0;0m"))
    print(horiz_center("\033[1;31mUh oh! Contact Tech Support on Mattermost\033[0;0m"))
0x5c commented 1 month ago

Couldn't do it today, but notes for when I get to:

  1. Switch weather's Last updated: to Updated at
  2. Remove seconds, easier now with a7a768c5d3f46a0d5137725bf71ff827b438278b
0x5c commented 1 month ago

I finally got the preview on my computer to render fonts the same size as on the actual foubot. Here's what the script (with small modification) looks when added image (the cmatrix window was added manually; we still don't have what's needed to automatically handle a 3rd window)

The space for the title is very limited, and with the way some foulab events are titled in the ICS it's mostly unusable. I'm thinking of ditching the whole centering code and just let the terminal wrap the event's title, kinda like so:

23 Jul 08:00 pm: Demonstration of
Resilient Infrastructure Through Open
Sessions (aka Infrastructure Night)

I can try it with the terminal's default line wrap mechanism, but it most likely will wrap weirdly, cutting words at weird locations. I wonder if there's existing implementations that can consider a max number of lines, or if it's easy to make one. Maybe a plain character limit on the title combined with a normal word-wrap algo is enough?

classabbyamp commented 1 month ago

https://docs.python.org/3/library/textwrap.html

0x5c commented 1 month ago

Got it working :tada: image