diff --git a/app.py b/app.py index bc6d978..36521b4 100644 --- a/app.py +++ b/app.py @@ -12,175 +12,175 @@ app.config['CACHE_DEFAULT_TIMEOUT'] = 44444 cache = Cache(app) def isValidDay(day): - t=dt.date.today() - return t<=day<=t+dt.timedelta(days=31) + t=dt.date.today() + return t<=day<=t+dt.timedelta(days=31) @app.route("/") def index(): - t=dt.date.today() - return render_template("index.html", today=str(t), dayafter=str(t+dt.timedelta(days=2)), later=str(t+dt.timedelta(days=31))) + t=dt.date.today() + return render_template("index.html", today=str(t), dayafter=str(t+dt.timedelta(days=2)), later=str(t+dt.timedelta(days=31))) @app.route("/today") def index_today(): - t=dt.date.today() - return index_day(t.year,t.month,t.day) + t=dt.date.today() + return index_day(t.year,t.month,t.day) @app.route("/tomorrow") def index_tomorrow(): - t=dt.date.today()+dt.timedelta(days=1) - return index_day(t.year,t.month,t.day) + t=dt.date.today()+dt.timedelta(days=1) + return index_day(t.year,t.month,t.day) @app.route('/--') def index_day(y,m,d): - day=dt.date(y,m,d) - if not (isValidDay(day)): - q=request.query_string.decode('utf-8') - if (q): q="?"+q - return redirect("today"+q) - return render_template("list.html", day=str(day)) + day=dt.date(y,m,d) + if not (isValidDay(day)): + q=request.query_string.decode('utf-8') + if (q): q="?"+q + return redirect("today"+q) + return render_template("list.html", day=str(day)) @app.route('/') @cache.cached(timeout=86400) def index_space(space): - return render_template("space.html", data=s(space)) + return render_template("space.html", data=s(space)) @app.route('/event/') @cache.cached(timeout=600) def index_event(event): - return render_template("event.html", data=e(event)) + return render_template("event.html", data=e(event)) @app.route("/calendar.svg") def static_calendar(): - return send_from_directory(app.static_folder, "calendar.svg") + return send_from_directory(app.static_folder, "calendar.svg") @app.route("/clock.svg") def static_clock(): - return send_from_directory(app.static_folder, "clock.svg") + return send_from_directory(app.static_folder, "clock.svg") @app.route("/location.svg") def static_location(): - return send_from_directory(app.static_folder, "location.svg") + return send_from_directory(app.static_folder, "location.svg") @app.route('/.json') @cache.cached(timeout=86400) def s(space): - return requests.post("https://25live.collegenet.com/25live/data/louisville/run/spaces.json?request_method=get",headers={"Content-Type":"application/json","Accept-Encoding":"gzip"},json={"mapxml":{"scope":"extended","space_id":space}}).json().get("spaces",[]).get("space",[]) + return requests.post("https://25live.collegenet.com/25live/data/louisville/run/spaces.json?request_method=get",headers={"Content-Type":"application/json","Accept-Encoding":"gzip"},json={"mapxml":{"scope":"extended","space_id":space}}).json().get("spaces",[]).get("space",[]) @app.route('/event/.json') @cache.cached(timeout=600) def e(event): - return requests.post("https://25live.collegenet.com/25live/data/louisville/run/events.json?request_method=get",headers={"Content-Type":"application/json","Accept-Encoding":"gzip"},json={"mapxml":{"scope":"extended","event_id":event}}).json().get("events",[]).get("event",[]) + return requests.post("https://25live.collegenet.com/25live/data/louisville/run/events.json?request_method=get",headers={"Content-Type":"application/json","Accept-Encoding":"gzip"},json={"mapxml":{"scope":"extended","event_id":event}}).json().get("events",[]).get("event",[]) @app.route('/--.json') @cache.cached(timeout=300) def all(y,m,d): - day=dt.date(y,m,d) - if (not isValidDay(day)): - return "invalid" - weekday=str(day.weekday()) - sday=str(day) - spaces=dict() - for restaurant, schedules in dining_data().items(): - schedule = [] - current_range = None - for period in schedules: - if period != "Standard": - if "-" in period: - s,e = [dt.date(day.year,*map(int, p.split("/"))) for p in period.split("-")] - if s <= day <= e: - current_range = period - break - else: - d = dt.date(day.year,*map(int, period.split("/"))) - if d == day: - current_range = period - break - else: current_range = "Standard" - for weekdays, meals in schedules[current_range].items(): - if weekday in weekdays.split(","): - for meal, times in meals.items(): - schedule.append({ - "s":int(times.split("-")[0]), - "e":int(times.split("-")[1]), - "n":meal - }) - spaces[restaurant] = { - "l":sorted(schedule, key=lambda x:x["s"]) - } - data=requests.get(f"https://25live.collegenet.com/25live/data/louisville/run/home/calendar/calendardata.json?obj_cache_accl=0&page=1&compsubject=event&events_query_id=939025&start_dt={sday}&end_dt={sday}").json() - food=set() - for event in data["root"]["events"][0].get("rsrv", []): - food.add(event["event_id"]) - data=requests.get(f"https://25live.collegenet.com/25live/data/louisville/run/availability/availabilitydata.json?obj_cache_accl=0&comptype=availability&compsubject=location&page_size=400&spaces_query_id=667440&include=closed+blackouts+pending+related+empty+requests+draft&start_dt={sday}").json() - for space in data.get('subjects', []): - spaces[space['itemName']] = { - "i":space['itemId'], - "l":sorted([{ - "s":round(float(item['start'])*60)-480, - "e":round(float(item['end'])*60)-480, - "n":item['itemName'], - **({"i":item['itemId']} if item['itemId'] != 0 else {}), - **({"t":"food"} if item['itemId'] in food - else {"t":"exam"} if item.get('event_type_id') == 139 - else {"t":"booked"} if item.get('event_type_id') == 143 - else {"t":"class"} if item.get('event_type_id') == 172 - else {}) - } for item in space.get('items', [])], key=lambda x:x["s"]) - } - return spaces + day=dt.date(y,m,d) + if (not isValidDay(day)): + return "invalid" + weekday=str(day.weekday()) + sday=str(day) + spaces=dict() + for restaurant, schedules in dining_data().items(): + schedule = [] + current_range = None + for period in schedules: + if period != "Standard": + if "-" in period: + s,e = [dt.date(day.year,*map(int, p.split("/"))) for p in period.split("-")] + if s <= day <= e: + current_range = period + break + else: + d = dt.date(day.year,*map(int, period.split("/"))) + if d == day: + current_range = period + break + else: current_range = "Standard" + for weekdays, meals in schedules[current_range].items(): + if weekday in weekdays.split(","): + for meal, times in meals.items(): + schedule.append({ + "s":int(times.split("-")[0]), + "e":int(times.split("-")[1]), + "n":meal + }) + spaces[restaurant] = { + "l":sorted(schedule, key=lambda x:x["s"]) + } + data=requests.get(f"https://25live.collegenet.com/25live/data/louisville/run/home/calendar/calendardata.json?obj_cache_accl=0&page=1&compsubject=event&events_query_id=939025&start_dt={sday}&end_dt={sday}").json() + food=set() + for event in data["root"]["events"][0].get("rsrv", []): + food.add(event["event_id"]) + data=requests.get(f"https://25live.collegenet.com/25live/data/louisville/run/availability/availabilitydata.json?obj_cache_accl=0&comptype=availability&compsubject=location&page_size=400&spaces_query_id=667440&include=closed+blackouts+pending+related+empty+requests+draft&start_dt={sday}").json() + for space in data.get('subjects', []): + spaces[space['itemName']] = { + "i":space['itemId'], + "l":sorted([{ + "s":round(float(item['start'])*60)-480, + "e":round(float(item['end'])*60)-480, + "n":item['itemName'], + **({"i":item['itemId']} if item['itemId'] != 0 else {}), + **({"t":"food"} if item['itemId'] in food + else {"t":"exam"} if item.get('event_type_id') == 139 + else {"t":"booked"} if item.get('event_type_id') == 143 + else {"t":"class"} if item.get('event_type_id') == 172 + else {}) + } for item in space.get('items', [])], key=lambda x:x["s"]) + } + return spaces # [{ periodId : '2230', name : 'Breakfast' }, { periodId : '3180', name : 'Light Lunch' }, { periodId : '2232', name : 'Lunch' }, { periodId : '2233', name : 'Dinner' }] @app.route('/dining.json') @cache.cached(timeout=44444) def dining_data(): - data = cache.get("dining") - if data: return data + data = cache.get("dining") + if data: return data - base = "https://louisville.campusdish.com/LocationsAndMenus/Belknap/" - locations = dict() - for location in re.findall(r':"/LocationsAndMenus/Belknap/([^",]+)', requests.get(base).text): - locations[location] = dict() - soup = BeautifulSoup(requests.get(base+location).text, 'html.parser') + base = "https://louisville.campusdish.com/LocationsAndMenus/Belknap/" + locations = dict() + for location in re.findall(r':"/LocationsAndMenus/Belknap/([^",]+)', requests.get(base).text): + locations[location] = dict() + soup = BeautifulSoup(requests.get(base+location).text, 'html.parser') - schedule_dates = [] - dates = soup.select_one(".location__scheduledates") - if dates: schedule_dates.append(dates.text.strip().replace(" ","")) - else: schedule_dates.append("Standard") - for timePeriod in soup.select("a.additionalschedule"): - match = re.search(r"(\d+/\d+-\d+/\d+)", timePeriod.text) - if not match: match = re.search(r"(\d+/\d+)", timePeriod.text) - if match: schedule_dates.append(match.group(1)) - else: schedule_dates.append("Standard") + schedule_dates = [] + dates = soup.select_one(".location__scheduledates") + if dates: schedule_dates.append(dates.text.strip().replace(" ","")) + else: schedule_dates.append("Standard") + for timePeriod in soup.select("a.additionalschedule"): + match = re.search(r"(\d+/\d+-\d+/\d+)", timePeriod.text) + if not match: match = re.search(r"(\d+/\d+)", timePeriod.text) + if match: schedule_dates.append(match.group(1)) + else: schedule_dates.append("Standard") - timeframes = [ul for ul in soup.find_all("div",class_="location__hours") if not ul.find("a.additionalschedule")] - for timeframe, date_range in zip(timeframes, schedule_dates): - meal_by_day = dict() - for meal_period in timeframe.find_all("li"): - period = meal_period.find("div", class_="mealPeriod") - if period: - period_range = period.text.strip() - for time_entry in meal_period.find_all("li"): - day = time_entry.find("span", class_="location__day") - times = time_entry.find("span", class_="location__times") - if day and times: - day_range = day.text.strip().replace("Mon","0").replace("Tue","1").replace("Wed","2").replace("Thu","3").replace("Fri","4").replace("Sat","5").replace("Sun","6") - d = [] - for wd in day_range.split(", "): - if "-" in wd: - s,e = map(int, wd.split("-")) - d.extend(map(str, (range(s,e+1)))) - else: - d.append(wd) - day_range = ",".join(d) - time_range = times.text.strip() - if "-" in time_range: - s,e = [int((dt.datetime.strptime(t, "%I:%M%p")-dt.datetime.strptime("8:00AM", "%I:%M%p")).total_seconds()/60) for t in time_range.split(" - ")] - if s < 0: s = 0 - if e < 0 or e > 900: e = 900 - time_range = str(s)+"-"+str(e) - else: continue - if day_range not in meal_by_day: meal_by_day[day_range]=dict() - meal_by_day[day_range][period_range] = time_range - locations[location][date_range] = meal_by_day - cache.set("dining", locations) - return locations + timeframes = [ul for ul in soup.find_all("div",class_="location__hours") if not ul.find("a.additionalschedule")] + for timeframe, date_range in zip(timeframes, schedule_dates): + meal_by_day = dict() + for meal_period in timeframe.find_all("li"): + period = meal_period.find("div", class_="mealPeriod") + if period: + period_range = period.text.strip() + for time_entry in meal_period.find_all("li"): + day = time_entry.find("span", class_="location__day") + times = time_entry.find("span", class_="location__times") + if day and times: + day_range = day.text.strip().replace("Mon","0").replace("Tue","1").replace("Wed","2").replace("Thu","3").replace("Fri","4").replace("Sat","5").replace("Sun","6") + d = [] + for wd in day_range.split(", "): + if "-" in wd: + s,e = map(int, wd.split("-")) + d.extend(map(str, (range(s,e+1)))) + else: + d.append(wd) + day_range = ",".join(d) + time_range = times.text.strip() + if "-" in time_range: + s,e = [int((dt.datetime.strptime(t, "%I:%M%p")-dt.datetime.strptime("8:00AM", "%I:%M%p")).total_seconds()/60) for t in time_range.split(" - ")] + if s < 0: s = 0 + if e < 0 or e > 900: e = 900 + time_range = str(s)+"-"+str(e) + else: continue + if day_range not in meal_by_day: meal_by_day[day_range]=dict() + meal_by_day[day_range][period_range] = time_range + locations[location][date_range] = meal_by_day + cache.set("dining", locations) + return locations