machine_setup/ansible/roles/sway/files/waybar_custom_clock.py

109 lines
3.1 KiB
Python

#!/usr/bin/env python
#
# Custom waybar module for clocks. Implemented because the official clock module was downloading timezone definitions on every boot.
import datetime
import json
import sys
import time
from dataclasses import dataclass
from functools import lru_cache
from typing import Final, List, Optional
from zoneinfo import ZoneInfo
INTERVAL: Final[int] = 10
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
@dataclass
class Update:
text: Optional[str]
alt: Optional[str]
tooltip: Optional[str]
css_class: Optional[List[str]]
percentage: Optional[str]
def dump(self) -> str:
# Dump a dict because we can't name our member variable "class"
return json.dumps(
{
k: v
for k, v in {
"text": self.text,
"alt": self.alt,
"tooltip": self.tooltip,
"class": self.css_class,
"percentage": self.percentage,
}.items()
if v is not None
}
)
@lru_cache(maxsize=1)
def make_calendar(today: datetime.date, tz: datetime.tzinfo):
width: Final[int] = 20
start_of_month = today.replace(day=1)
month_header = today.strftime("%B %Y")
padding = width - len(month_header)
right_padding = " " * (padding // 2)
left_padding = right_padding + (" " if padding % 2 == 1 else "")
header = f"{left_padding}{month_header}{right_padding}"
days_of_week = "Su Mo Tu We Th Fr Sa"
timezone_str = str(tz)
# Make the grid
first_day_padding = " " * (
0 if start_of_month.weekday() == 6 else (3 * (1 + start_of_month.weekday())) - 1
)
output = f"{header}\n{days_of_week}\n{first_day_padding}"
print_day = start_of_month
while print_day.month == today.month:
if print_day.weekday() == 6:
output += "\n"
else:
output += " "
if print_day == today:
output += '<span foreground="#323232" background="#CCCCCC">'
output += f"{print_day.day: >2}"
if print_day == today:
output += "</span>"
print_day += datetime.timedelta(days=1)
output += f'\n<span size="small">{timezone_str}</span>'
return output
def main():
tz: Optional[datetime.tzinfo] = (
ZoneInfo(sys.argv[1]) if len(sys.argv) >= 2 else LOCAL_TIMEZONE
)
if tz is None:
raise Exception("Failed to detect timezone.")
next_update = time.time()
while True:
time_before_next_update = next_update - time.time()
if time_before_next_update > 0:
time.sleep(time_before_next_update)
next_update = time.time() + INTERVAL
now = datetime.datetime.now(tz=tz)
text = now.strftime("%Y-%m-%d %H:%M")
tooltip = make_calendar(now.date(), tz)
out = Update(
text=text,
alt="foo",
tooltip=f"<tt>{tooltip}</tt>",
css_class=["foo"],
percentage="100",
)
print(out.dump(), flush=True)
if __name__ == "__main__":
main()