Skip to content

Commit f93c113

Browse files
v411eddogfoodd
andauthored
Feature/hid (#8)
* feat: parse HiD program to dict * Integrate hid feature Co-authored-by: Jost Alemann <jost_alemann@me.com>
1 parent e0315c1 commit f93c113

File tree

2 files changed

+68
-9
lines changed

2 files changed

+68
-9
lines changed

ovgumensabot/mensabot.py

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88
from mautrix.errors import MForbidden
99
from mautrix.types import TextMessageEventContent, MessageType, Format, RelatesTo, RelationType, RoomID
1010

11-
from .parser import get_menus
11+
from .parser import get_menus, parse_movies
1212
from .db import MenuDatabase
1313
from .menu import Menu
1414

1515
URLS = [
1616
'https://www.studentenwerk-magdeburg.de/mensen-cafeterien/mensa-unicampus/speiseplan-unten/',
1717
'https://www.studentenwerk-magdeburg.de/mensen-cafeterien/mensa-unicampus/speiseplan-oben/'
18-
#'https://www.studentenwerk-magdeburg.de/mensen-cafeterien/mensa-stendal/speiseplan/',
19-
#'https://www.studentenwerk-magdeburg.de/mensen-cafeterien/mensa-herrenkrug/speiseplan/',
20-
#'https://www.studentenwerk-magdeburg.de/mensen-cafeterien/mensa-kellercafe/speiseplan/'
18+
# 'https://www.studentenwerk-magdeburg.de/mensen-cafeterien/mensa-stendal/speiseplan/',
19+
# 'https://www.studentenwerk-magdeburg.de/mensen-cafeterien/mensa-herrenkrug/speiseplan/',
20+
# 'https://www.studentenwerk-magdeburg.de/mensen-cafeterien/mensa-kellercafe/speiseplan/'
2121
]
2222
NOTIF_TIME = {
2323
"h": 14,
@@ -39,6 +39,14 @@ def date_keyword_to_date(date_keyword) -> date:
3939
return switcher.get(date_keyword)
4040

4141

42+
def formatted_movie_list(movies: list[tuple[datetime, str]]) -> str:
43+
ret = "Next movies: \n\n"
44+
for movie in movies:
45+
datetime_str = movie[0].strftime("%d.%m.%Y, %H:%M")
46+
ret += f"* {datetime_str}: {movie[1]}\n"
47+
return ret
48+
49+
4250
class MensaBot(Plugin):
4351
db: MenuDatabase
4452
loop_task: asyncio.Future
@@ -55,8 +63,10 @@ async def fetch_loop(self) -> None:
5563
self.log.debug("Fetching loop started")
5664
while True:
5765
now = datetime.now(TZ)
58-
days = 1 if now > now.replace(hour=NOTIF_TIME.get("h"), minute=NOTIF_TIME.get("m"), second=0, microsecond=0) else 0
59-
scheduled_time = now.replace(hour=NOTIF_TIME.get("h"), minute=NOTIF_TIME.get("m"), second=0, microsecond=0) + timedelta(days=days)
66+
days = 1 if now > now.replace(hour=NOTIF_TIME.get("h"), minute=NOTIF_TIME.get("m"), second=0,
67+
microsecond=0) else 0
68+
scheduled_time = now.replace(hour=NOTIF_TIME.get("h"), minute=NOTIF_TIME.get("m"), second=0,
69+
microsecond=0) + timedelta(days=days)
6070
self.log.info(f"Scheduled fetch for {scheduled_time} in {scheduled_time - now} seconds")
6171
await asyncio.sleep((scheduled_time - now).total_seconds())
6272
asyncio.create_task(self.autofetch_menus())
@@ -170,6 +180,25 @@ async def unsubscribe(self, evt: MessageEvent) -> None:
170180
))
171181
await evt.respond(content)
172182

183+
@command.new("hid", help="Next Hörsaal im Dunkeln event")
184+
async def hid(self, evt: MessageEvent) -> None:
185+
movies = await parse_movies(self, "https://www.unifilm.de/studentenkinos/MD_HiD")
186+
187+
# remove all old movies
188+
movies[:] = [movie for movie in movies if movie[0].date() >= datetime.now(TZ).date()]
189+
190+
self.log.debug(f"Upcoming movies: {movies}")
191+
if len(movies) == 0:
192+
await evt.respond("No planned movies.")
193+
return
194+
else:
195+
# only keep movies of the next movie day
196+
next_movie_day = movies[0][0].date()
197+
movies[:] = [movie for movie in movies if movie[0].date() == next_movie_day]
198+
199+
self.log.info(f"Movies on next movie day: {movies}")
200+
await evt.respond(formatted_movie_list(movies))
201+
173202
async def fetch_menus(self) -> None:
174203
days = []
175204
for url in URLS:
@@ -214,7 +243,7 @@ def get_next_available_day(self):
214243
days = self.db.get_menu_days()
215244
for day in days:
216245
if day >= today:
217-
if day != today: # no menu today, returning the next available
246+
if day != today: # no menu today, returning the next available
218247
return day
219248
elif datetime.now(TZ) > today2pm:
220249
return days.__next__()

ovgumensabot/parser.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import logging
21
from datetime import datetime
32
from typing import List
43

54
import pytz
6-
from bs4 import BeautifulSoup
5+
from bs4 import BeautifulSoup, ResultSet
76
from maubot import Plugin
87

98
from .meal import Meal
109
from .menu import Menu
10+
1111
TZ = pytz.timezone('Europe/Berlin')
1212

1313

@@ -42,3 +42,33 @@ def parse_table(menu_table) -> Menu:
4242
last_updated=datetime.now(TZ),
4343
meals=meals)
4444
return menu
45+
46+
47+
# parse hoersaal im dunkeln movie calendar
48+
# https://www.unifilm.de/studentenkinos/MD_HiD
49+
async def parse_movies(mensabot: Plugin, url: str) -> list[tuple[datetime, str]]:
50+
async with mensabot.http.get(url) as resp:
51+
page = await resp.text()
52+
# mensabot.log.debug(page)
53+
soup = BeautifulSoup(page, "html.parser")
54+
55+
# locate calendar for current semester
56+
div_semester = soup.find("div", class_="kino-detail-spielplan spielplan-thisSemester")
57+
58+
# locate all movies in current semester
59+
div_movie: List[BeautifulSoup] = div_semester.find_all("div", class_="semester-film-row")
60+
61+
movies_dict = {}
62+
63+
# for each movie locate date, time and title
64+
for movie in div_movie:
65+
date = movie.find("div", class_="film-row-text film-row-datum").text
66+
time = movie.find("div", class_="film-row-text film-row-uhrzeit").text
67+
date_time_str = f"{date.strip().split(' ', 1)[1]}-{time.split(' ', 1)[0]}"
68+
parsed_datetime: datetime = datetime.strptime(date_time_str, "%d.%m.%Y-%H:%M")
69+
# ignore space at the end of each title
70+
title = movie.find("div", class_="film-row-text film-row-titel").text.strip()
71+
72+
movies_dict[parsed_datetime] = title
73+
74+
return sorted(movies_dict.items())

0 commit comments

Comments
 (0)