from flask import Flask, request import os import urllib.request from icalendar.cal import Calendar, Component app = Flask(__name__) PORT = int(os.environ.get('PORT', 5000)) BASE_URL = os.environ.get('BASE_URL', None) EXCLUDED_COURSES = os.environ.get('COURSES', '').split(',') EXCLUDED_TYPES = os.environ.get('TYPES', '').split(',') YEAR = os.environ.get('YEAR', '4') GROUP = os.environ.get('GROUP', '1') ALLOWED_YEARS = os.environ.get('ALLOWED_YEARS', '3,4,5').split(',') ALLOWED_GROUPS = os.environ.get('ALLOWED_GROUPS', '1,2,3').split(',') @app.route("/") def hello(): url = BASE_URL if url is None: return "" year = request.args.get('year', '') group = request.args.get('group', '') year = validate(year, ALLOWED_YEARS, YEAR) group = validate(group, ALLOWED_GROUPS, GROUP) url += "&promo={year}&groupe={group}".format(year=year, group=group) cal_str = urllib.request.urlopen(url).read() cal = Component.from_ical(cal_str) other = Calendar() # Copy all properties of calendar for k, v in cal.items(): other.add(k, v) # Copy VTIMEZONE components for ev in cal.walk('VTIMEZONE'): other.add_component(ev) # Filter and copy VEVENTs for ev in cal.walk('VEVENT'): if should_add(ev): other.add_component(ev) return other.to_ical().replace(b'\r\n', b'\n').strip() def should_add(event): """ Determines whether an event should be added to the returned calendar or not. :param event: The event to determine if should be added or not. :type event: Component :return: True if the event should be added, False otherwise. :rtype: bool """ course_code = event['SUMMARY'].split('-')[1].split('/')[0] course_type = event['SUMMARY'].split('/')[1].split('_')[1] # Get user specified excluded courses/types if exist excluded_courses = request.args.get('excluded_courses', '') excluded_types = request.args.get('excluded_types', '') if excluded_courses == '': excluded_courses = EXCLUDED_COURSES else: excluded_courses = excluded_courses.split(',') if excluded_types == '': excluded_types = EXCLUDED_TYPES else: excluded_types = excluded_types.split(',') # Filter against courses and types return \ course_code not in excluded_courses \ and course_type not in excluded_types def validate(item, validation_list, default): """ Validates an item from user input against a list of possible values. :param item: The item to validate. :type item: object :param validation_list: The list of possible values. :type item: list(object) :param default: The default value to fallback on if item is not in list. :type default: object :return: The item if it is valid (in the list), or default :rtype: object """ try: int(item) if item not in validation_list: raise ValueError(item.__name__ + ' not allowed') except ValueError: return default return item if __name__ == "__main__": app.run('0.0.0.0', PORT)