Skip to content

Instantly share code, notes, and snippets.

@jparise
Last active February 6, 2022 04:34
Show Gist options
  • Save jparise/f3142c58d3478ff1b236ee061f541724 to your computer and use it in GitHub Desktop.
Save jparise/f3142c58d3478ff1b236ee061f541724 to your computer and use it in GitHub Desktop.
Olympic Medal Standings for Vestaboard
#!/usr/bin/env python3
"""Olympic Medal Standings for Vestaboard"""
# pip install beautifulsoup4 vesta
import argparse
import logging
import time
from collections import namedtuple
from typing import List
import requests
import vesta
from bs4 import BeautifulSoup
Team = namedtuple("Row", "country gold silver bronze total")
def get_standings(limit=5):
resp = requests.get(
"https://olympics.com/beijing-2022/olympic-games/en/results/all-sports/medal-standings.htm"
)
soup = BeautifulSoup(resp.text, "html.parser")
table = soup.find("table", id="medal-standing-table")
for row in table.find_all("tr", limit=limit + 1)[1:]:
cells = row.find_all("td")
yield Team(
country=cells[1].div["country"],
gold=int(cells[2].text.strip()),
silver=int(cells[3].text.strip()),
bronze=int(cells[4].text.strip()),
total=int(cells[5].text.strip()),
)
def render(standings) -> List[List[int]]:
chars = [
vesta.encode_row(" {65} {69} {64} T "),
]
for i, team in enumerate(standings, start=1):
chars.append(
vesta.encode_row(
f" {i} {team.country:5} "
f"{team.gold:2} {team.silver:2} {team.bronze:2} {team.total:3}"
)
)
return chars
def main(args):
logging.basicConfig(
format="%(asctime)s %(levelname)s %(message)s",
level=logging.INFO,
)
client = vesta.Client(args.key, args.secret)
last = None
while True:
logging.info("Fetching latest standings")
try:
standings = tuple(get_standings())
except IOError as e:
logging.error(e)
time.sleep(60)
continue
if standings != last:
logging.info(
"Publishing updated standings: %s",
" ".join(team.country for team in standings),
)
chars = render(standings)
if args.pprint:
vesta.pprint(chars)
try:
client.post_message(args.sub, chars)
except IOError as e:
logging.error(e)
time.sleep(60)
continue
last = standings
time.sleep(args.interval)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--key", required=True, help="API key")
parser.add_argument("--secret", required=True, help="API secret")
parser.add_argument("--sub", required=True, help="subscription ID")
parser.add_argument("--pprint", action="store_true", help="print the board")
parser.add_argument(
"--interval", type=int, default=10 * 60, help="update interval (seconds)"
)
args = parser.parse_args()
main(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment