예제 #1
0
def process_arxiv_url(url: str) -> Tuple[str]:
    def get_paper_id_from_url(url) -> str:
        while "/" in url:
            slash_idx = url.find("/")
            url = url[slash_idx + 1:]
        if url.endswith(".pdf"):
            return url[:-4]
        else:
            return url

    if "arxiv.org/abs" in url:
        ## abstract page
        paper_id = get_paper_id_from_url(url)
        paper_url = url
        pdf_url = f"https://arxiv.org/pdf/{paper_id}.pdf"
        return paper_id, paper_url, pdf_url
    elif "arxiv.org/pdf" in url:
        ## pdf page
        paper_id = get_paper_id_from_url(url)
        paper_url = f"https://arxiv.org/abs/{paper_id}"
        pdf_url = url
        return paper_id, paper_url, pdf_url
    else:
        logger.error("Unexpected URL Error by arxiv URL Handler.")
        raise Exception("Unexpected URL Error by arxiv URL Handler.")
예제 #2
0
async def get_all_student_info(
        username=Depends(auth_handler.auth_wrapper), num: int = 30):
    """
    Get all student info

    Require: Admin-read
    """
    logger.debug(f"User({username}) trying fetching all students info.")
    permission_ok: bool = Access.is_admin(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    student_info_list = []
    count = 0
    try:
        for student_info in students_collection.find():
            count += 1
            clean_dict(student_info)
            student_info_list.append(student_info)
            if count >= num:
                break
    except Exception as e:
        logger.error(MSG.DB_QUERY_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

    return student_info_list
async def get_an_application_period(uid: str,
                                    username=Depends(
                                        auth_handler.auth_wrapper)):
    """
    Get an Application Period

    Require: Admin-read
    """
    logger.debug(
        f"User({username}) requested to get ApplicationPeriod({uid}).")
    permission_ok = Access.is_admin(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    try:
        ap_info = application_periods_collection.find_one(filter={"uid": uid})
        clean_dict(ap_info)
    except Exception as e:
        logger.error(MSG.DB_QUERY_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

    if ap_info:
        ap_info["applicable_periods"] = convert_to_applicable_periods(
            ap_info["applicable_periods"])
        return ap_info
    else:
        raise HTTPException(status_code=404, detail=MSG.ITEM_NOT_FOUND)
예제 #4
0
async def create_an_event(new_event: Event,
                          username=Depends(auth_handler.auth_wrapper)):
    """
    Create an Event

    Require: Student-HG or Admin-write
    """
    logger.debug(f"User({username}) trying creating new Event.")
    # Check access
    permission_ok = Access.at_least_student_hg_write(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    new_event.created_by = str(username)
    event_dict = dict(new_event.dict())
    try:
        _inserted_id = events_collection.insert_one(event_dict).inserted_id
        logger.debug(
            f"New Event inserted to DB with inserted_id: {_inserted_id}")
        _event = events_collection.find_one({"_id": _inserted_id})
        clean_dict(_event)
        logger.debug(f"New Event info: {_event}")
        return _event
    except Exception as e:
        logger.error(MSG.DB_UPDATE_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_UPDATE_ERROR)
예제 #5
0
async def get_a_student_info(student_id: str,
                             username=Depends(auth_handler.auth_wrapper)):
    """
    Set a particular Student info

    Require: Student-self or Admin-read
    """

    logger.debug(
        f"User({username}) trying fetching student({student_id}) info.")
    permission_ok = False
    if student_id == username or Access.is_admin(username):
        permission_ok = True

    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    try:
        student_info = students_collection.find_one({"student_id": student_id})
        clean_dict(student_info)
    except Exception as e:
        logger.error(MSG.DB_QUERY_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

    if student_info:
        logger.debug(f"student_info: {student_info}")
        return student_info
    else:
        raise HTTPException(status_code=404, detail=MSG.ITEM_NOT_FOUND)
예제 #6
0
async def login(auth_details: User):
    try:
        user = users_collection.find_one({"username": auth_details.username})
    except Exception as e:
        logger.error("Failed to query user from database.")
        logger.error(e)
        raise HTTPException(status_code=500, detail="Databse Error.")
    if not user or not auth_handler.verify_password(auth_details.password,
                                                    user["password"]):
        raise HTTPException(status_code=401,
                            detail="Invalid username and/or password")
    token = auth_handler.encode_token(auth_details.username)
    logger.debug(
        f"New JWT token generated for user: '******'")
    is_student = Access.is_student(auth_details.username)
    is_student_hg = Access.is_student_hg(auth_details.username)
    is_admin = Access.is_admin(auth_details.username)
    is_admin_write = Access.is_admin_write(auth_details.username)

    return {
        "token": token,
        "is_student": is_student,
        "is_student_hg": is_student_hg,
        "is_admin": is_admin,
        "is_admin_write": is_admin_write,
    }
예제 #7
0
def url_MsgHandler(update, context):
    # context.bot.send_message(chat_id=update.effective_chat.id, text=update.message.text)
    try:
        url_received = update.message.text

        if "arxiv" in url_received:
            logger.debug("URL identified: arXiv")

            paper = get_paper(url_received)
            msg = "*Paper*: {}\n\n*Author*: {}\n\n*PDF*: {}".format(
                paper.title, paper.first_author, paper.pdf_url)

            user = get_current_telegram_user(update)
            add_paper_to_user(paper, user)

        elif "openaccess.thecvf.com" in url_received:
            logger.debug("URL identified: CVPR Open Access")
            msg = "CVPR Open Access (in development)"

        else:
            msg = "Currently only arxiv paper url is supported."

    except Exception as err:
        logger.error(err)
        msg = "Internal Server Error"
        # msg = telegram.utils.helpers.escape_markdown(msg)

    # respond to user
    update.message.reply_text(msg, parse_mode=telegram.ParseMode.MARKDOWN)
    user_log(update, remarks="respond_paper_info_from_url")
예제 #8
0
def student_update_application_form_status(
    AF_uid: str, username: str, new_status: str, pre_status: List[str]
) -> dict:
    # Check access 1
    permission_ok = False
    if Access.is_student(username) or Access.is_admin_write(username):
        permission_ok = True

    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    # Check access 2: check if the application belongs to student
    if Access.is_student(username):
        try:
            student_info = students_collection.find_one({"student_id": username})
            clean_dict(student_info)
        except Exception as e:
            logger.error(MSG.DB_QUERY_ERROR)
            logger.error(e)
            raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

        student_application_uids = student_info.get("application_uids", [])

        if AF_uid not in student_application_uids:
            raise HTTPException(status_code=400, detail=MSG.NOT_YOUR_AF)

    _updated = update_application_form_both_status(AF_uid, new_status, pre_status)
    return _updated
예제 #9
0
async def get_an_application_info(
    uid: str, username=Depends(auth_handler.auth_wrapper)
):
    """
    Get an ApplicationForm info

    Require: Student-self or Admin-read
    """
    # Special case, check permission after getting item from DB
    logger.debug(f"User({username}) fetching record({uid}) info")
    try:
        application_dict: dict = applications_collection.find_one({"uid": uid})
        clean_dict(application_dict)
    except Exception as e:
        logger.error(MSG.DB_QUERY_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

    if not application_dict:
        raise HTTPException(status_code=404, detail=MSG.ITEM_NOT_FOUND)

    # Student-self can access DisciplinaryRecord issued to himself/herself.
    application_owner = application_dict.get("student_id", "")
    permission_ok = Access.is_admin(username)
    permission_ok = True if username == application_owner else permission_ok
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    return application_dict
async def create_new_application_period(ap: ApplicationPeriod,
                                        username=Depends(
                                            auth_handler.auth_wrapper)):
    """
    Create an ApplicationPeriod

    Require: Admin-write
    """
    permission_ok = Access.is_admin_write(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    ap.created_by = str(username)
    ap_dict = dict(ap.dict())
    ap_dict["applicable_periods"] = convert_from_applicable_periods(
        ap.applicable_periods)

    try:
        _inserted_id = application_periods_collection.insert_one(
            ap_dict).inserted_id
        logger.debug(
            f"New ApplicationPeriod inserted to DB with inserted_id: {_inserted_id}"
        )
        logger.debug(f"New ApplicationPeriod info: {ap_dict}")
        return ap_dict
    except Exception as e:
        logger.error(MSG.DB_UPDATE_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_UPDATE_ERROR)
async def get_active_application_periods(username=Depends(
    auth_handler.auth_wrapper)):
    """
    Get Active (currently open) Application Periods

    Require: Any authenticated user
    """

    logger.debug(f"User({username}) fetching active ApplicationPeriods")
    ap_list = []
    _now = datetime.now()
    try:
        for ap_dict in application_periods_collection.find({
                "application_window_open": {
                    "$lt": _now
                },
                "application_window_close": {
                    "$gte": _now
                },
        }).sort("application_window_open"):
            clean_dict(ap_dict)
            ap_dict["applicable_periods"] = convert_to_applicable_periods(
                ap_dict["applicable_periods"])
            ap_list.append(ap_dict)
    except Exception as e:
        logger.error(MSG.DB_QUERY_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

    return ap_list
async def get_all_application_periods(username=Depends(
    auth_handler.auth_wrapper)):
    """
    Get ALL Application Periods

    Require: Admin-read
    """

    logger.debug(f"User({username}) fetching ALL ApplicationPeriods.")
    permission_ok = Access.is_admin(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    ap_list = []
    try:
        for ap_dict in application_periods_collection.find().sort(
                "created_by", DESCENDING):
            clean_dict(ap_dict)
            ap_dict["applicable_periods"] = convert_to_applicable_periods(
                ap_dict["applicable_periods"])
            ap_list.append(ap_dict)
    except Exception as e:
        logger.error(MSG.DB_QUERY_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

    return ap_list
예제 #13
0
async def get_all_disciplinary_record(username=Depends(
    auth_handler.auth_wrapper)):
    """
    Get all Disciplinary Records

    Require: Admin-read
    """
    logger.debug(f"User({username}) fetching all records info")

    permission_ok: bool = Access.is_admin(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    records_list = []
    try:
        for record in records_collection.find():
            clean_dict(record)
            records_list.append(record)
    except Exception as e:
        logger.error(MSG.DB_QUERY_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

    return records_list
예제 #14
0
async def update_disciplinary_record(
        uid: str,
        record_edit: RecordEditable,
        username=Depends(auth_handler.auth_wrapper),
):
    """
    Update a DisciplinaryRecord

    Require: Admin-write
    """
    logger.debug(f"{username} trying to update a DisciplinaryRecord({uid})")
    permission_ok = Access.is_admin_write(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    record_dict = dict(record_edit.dict())
    remove_none_value_keys(record_dict)
    try:
        updated = records_collection.find_one_and_update(
            filter={"uid": uid},
            update={"$set": record_dict},
            return_document=ReturnDocument.AFTER,
        )
        clean_dict(updated)
    except Exception as e:
        logger.error(MSG.DB_UPDATE_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_UPDATE_ERROR)

    if updated:
        logger.debug(f"Updated: {updated}")
        return updated
    else:
        raise HTTPException(status_code=404, detail=MSG.TARGET_ITEM_NOT_FOUND)
def get_event_list(ics_path: str) -> List[List[str]]:
    ics_path = Path(ics_path)
    if not ics_path.is_file():
        logger.error("File does not exist.")

    with ics_path.open() as f:
        lines = f.readlines()

    reading_event: bool = False

    event_list: List[List[str]] = []
    current_event_lines: List[str] = []

    for line in lines:
        line: str = line.strip()

        if line.startswith("BEGIN:VEVENT"):
            reading_event = True

        if reading_event:
            current_event_lines.append(line)

        if line.startswith("END:VEVENT"):
            reading_event = False
            event_list.append(fix_broken_lines(current_event_lines))
            # reset
            current_event_lines = []

    return event_list
예제 #16
0
async def revoke_a_student_as_hg(student_id: str,
                                 username=Depends(auth_handler.auth_wrapper)):
    """
    Revoke a Student as House Guardian

    Require: Admin-write
    """
    permission_ok = False
    if Access.is_admin_write(username):
        permission_ok = True

    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    try:
        updated = students_collection.find_one_and_update(
            filter={"student_id": student_id},
            update={"$set": {
                "is_house_guardian": False
            }},
            return_document=ReturnDocument.AFTER,
        )
        logger.debug(f"{str(updated)}")
        clean_dict(updated)
    except Exception as e:
        logger.error(MSG.DB_UPDATE_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_UPDATE_ERROR)

    if updated:
        logger.debug(f"Updated: {updated}")
        return updated
    else:
        raise HTTPException(status_code=404, detail=MSG.TARGET_ITEM_NOT_FOUND)
예제 #17
0
def generate_video_list(video_folder: str):
    """
    get metadata of all videos inside a video_folder, and
    write to `video_metadata_lst.json` and save it to the video_folder
    existing `video_metadata_lst.json` inside the target folder will be overwritten
    """
    video_folder = Path(video_folder)
    if not video_folder.is_dir():
        raise ValueError(f"'{dir}' is not a valid path to a folder.")

    video_list: list = []

    for file in os.listdir(video_folder):
        logger.debug(file)
        video_filepath = os.path.join(video_folder, file)
        if os.path.isfile(video_filepath):
            try:
                video_metadata: dict = get_video_metadata(video_filepath)
                video_list.append(video_metadata)
            except Exception as err:
                logger.error(f"Error for {video_filepath}: {err}")
                continue

    # sort video list by video name alphabetically
    video_list = sorted(video_list, key=lambda x: x["filename"])

    print(f"\nTotal number of videos: {len(video_list)}\n")

    export_filepath = video_folder / "video_metadata_lst.json"
    with export_filepath.open(mode="w") as f:
        f.write(json.dumps(video_list, indent=4))
예제 #18
0
async def update_a_student_identity(
        student_id: str,
        student_identity_profile: StudentIdentityProfile,
        username=Depends(auth_handler.auth_wrapper),
):
    logger.debug(
        f"User({username}) trying to update Student({student_id})'s identity profile."
    )
    permission_ok = Access.is_admin_write(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    identity_dict = dict(student_identity_profile.dict())
    remove_none_value_keys(identity_dict)

    try:
        updated = students_collection.find_one_and_update(
            filter={"student_id": student_id},
            update={"$set": identity_dict},
            return_document=ReturnDocument.AFTER,
        )
        clean_dict(updated)
    except Exception as e:
        logger.error(MSG.DB_UPDATE_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_UPDATE_ERROR)

    if updated:
        logger.debug(f"Updated: {updated}")
        return updated
    else:
        raise HTTPException(status_code=404, detail=MSG.TARGET_ITEM_NOT_FOUND)
예제 #19
0
def get_video_metadata(video_path: str) -> dict:

    # check if the file exist
    video_path = Path(video_path)
    if not video_path.is_file():
        logger.error(f"Invalid video_path: `{video_path}` does not exist.")
        raise Exception("Invalid video_path: file does not exist.")

    # check if it is a video file
    known_video_formats = (".mp4", ".flv", ".mov", ".avi", ".wmv", ".mkv")
    video_path_obs = video_path.resolve()
    head, tail = os.path.split(video_path_obs)
    name, ext = os.path.splitext(tail)
    if ext not in known_video_formats:
        logger.warning(
            f"Invalid video_path: `{tail}` is not a known video format.")
        raise Exception(
            f"Invalid video_path: `{tail}` is not a known video format.")

    command_template = "ffprobe -v error -select_streams v:0 -show_entries stream=width,height,avg_frame_rate,duration -of json"
    args = shlex.split(command_template)
    args.append(str(video_path))
    proc = subprocess.Popen(args, stdout=subprocess.PIPE)
    out: bytes = proc.communicate()[0]
    json_string: str = out.decode("utf-8").strip()

    # logger.debug(json_string)

    json_obj: dict = json.loads(json_string)

    streams: list = json_obj.get("streams", [])
    if len(streams) == 1:
        _data = streams[0]
    elif len(streams) == 0:
        raise Exception()
    else:
        _data: dict = streams[0]
        logger.info(f"More than one stream is found at {video_path}")

    width: int = _data.get("width")
    height: int = _data.get("height")
    ratio = width / height
    avg_frame_rate: str = _data.get("avg_frame_rate")
    frame_rate: int = round(eval(avg_frame_rate)) if avg_frame_rate else None
    duration: float = round(float(_data.get("duration")), 2)

    video_metadata: dict = {
        "filepath": str(video_path_obs),
        "filename": name,
        "ext": ext,
        "width": width,
        "height": height,
        "ratio": ratio,  # width / height
        "duration": duration,  # in number of seconds
        "fps": frame_rate,  # frame per seconds
        "avg_frame_rate": avg_frame_rate,
    }

    # logger.debug(json.dumps(video_metadata, indent=4))
    return video_metadata
예제 #20
0
async def get_list_of_events(event_uids: List[str],
                             username=Depends(auth_handler.auth_wrapper)):
    """
    Get a list of Events for a given list of Event UIDs.
    If one or more provided uid(s) do not exist, it will be ignored.

    Require: Any authenticated user
    """

    logger.debug(f"User({username}) fetching a list of events info")
    event_info_list: List[dict] = []
    event_uids = list(set(event_uids))
    try:
        for uid in event_uids:
            if isinstance(uid, str):
                event_dict: dict = events_collection.find_one({"uid": uid})
                if event_dict:
                    clean_dict(event_dict)
                    event_info_list.append(event_dict)
    except Exception as e:
        logger.error(MSG.DB_QUERY_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)

    return event_info_list
예제 #21
0
async def add_room(new_room: Room, username=Depends(auth_handler.auth_wrapper)):
    """
    Add a new Room to database

    Require: Admin-write
    """
    logger.debug(f"User({username}) trying add new Room.")

    permission_ok: bool = Access.is_admin_write(username)
    if not permission_ok:
        logger.debug(MSG.permission_denied_msg(username))
        raise HTTPException(status_code=401, detail=MSG.PERMISSION_ERROR)

    room_dict = dict(new_room.dict())
    try:
        _inserted_id = rooms_collection.insert_one(room_dict).inserted_id
        logger.debug(f"New Room inserted to DB with inserted_id: {_inserted_id}")
    except Exception as e:
        logger.error(MSG.DB_UPDATE_ERROR)
        logger.error(e)
        raise HTTPException(status_code=500, detail=MSG.DB_UPDATE_ERROR)

    clean_dict(room_dict)
    logger.debug(f"New Room info: {room_dict}")
    return room_dict
def parse_single_event(event_lines: List[str]) -> Dict[str, str]:
    if event_lines[0] == "BEGIN:VEVENT" and event_lines[-1] == "END:VEVENT":
        event_lines = event_lines[1:-1]
    else:
        logger.error("Invalid Event")
        return

    event = OrderedDict({
        "SUMMARY": None,
        "DESCRIPTION": None,
        "LOCATION": None,
        "DTSTART": None,
        "DTEND": None,
        "UID": None,
        "RRULE": None,
        "EXDATE": None,
    })

    for line in event_lines:
        colon_index = line.find(":")
        key = line[:colon_index]
        if key not in event:
            continue
        line_value = line[colon_index + 1:]
        # timezone fix
        if key == "DTSTART" or key == "DTEND" or key == "EXDATE":
            event[key + ";TZID=Asia/Singapore"] = line_value
        elif key == "RRULE":
            # TODO: convert UNTIL field to GMT (add Z ad the back as well)
            # see: https://www.kanzaki.com/docs/ical/recur.html
            event[key] = line_value
        else:
            event[key] = line_value
    # correct summary
    original_summary = event.get("SUMMARY")
    logger.info(original_summary)
    if original_summary:
        room_index = original_summary.find("ROOM:")
        if room_index != -1:
            location_value = original_summary[room_index + 5:]
            event["LOCATION"] = location_value.strip()
            original_summary = original_summary[:room_index]

        chop_index = original_summary.find(":")
        if chop_index != -1:
            chopped = original_summary[:chop_index - 2]
            event["SUMMARY"] = chopped.strip()

    if event.get("SUMMARY") == event.get("DESCRIPTION"):
        event.pop("DESCRIPTION")

    unused = []
    for key in event.keys():
        if not event.get(key):
            unused.append(key)

    for key in unused:
        event.pop(key)

    return event
예제 #23
0
 def is_admin_write(username: str) -> bool:
     try:
         admin_info: dict = admins_collection.find_one(
             {"username": username})
     except Exception as e:
         logger.error(MSG.DB_QUERY_ERROR)
         logger.error(e)
         raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)
     if admin_info and admin_info.get("read_only", True) == False:
         return True
     return False
예제 #24
0
 def is_student_hg(username: str) -> bool:
     """ Check if the given username is an existing Student House Guardian """
     try:
         student_info: dict = students_collection.find_one(
             {"username": username})
     except Exception as e:
         logger.error(MSG.DB_QUERY_ERROR)
         logger.error(e)
         raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)
     if student_info and student_info.get("is_house_guardian", False):
         return True
     return False
예제 #25
0
 def is_student(username: str) -> bool:
     """ Check if the given username is an existing Student in the database """
     try:
         student_info: dict = students_collection.find_one(
             {"username": username})
     except Exception as e:
         logger.error(MSG.DB_QUERY_ERROR)
         logger.error(e)
         raise HTTPException(status_code=500, detail=MSG.DB_QUERY_ERROR)
     if student_info:
         return True
     return False
예제 #26
0
def ics(update, context):
    # get file type
    file_type = update.message.document.mime_type
    # proceed only if the file is an ics
    if file_type == "text/calendar":
        # update.message.reply_text("Received!", parse_mode=telegram.ParseMode.MARKDOWN)
        logger.debug("New file (text/calendar) received.")
        ts: str = timestamp_now()
        file_id = update.message.document.file_id
        tg_file_ref = context.bot.get_file(file_id)
        download_filepath: Path = usr_data_path / f"{ts}.ics"
        tg_file_ref.download(download_filepath)
        # format the ics file
        try:
            new_file, number_of_events = calendarFixer.fix(download_filepath)
            user_log(update, ts=ts, remarks="ics")
        except Exception as e:
            logger.error("re-formatting of calendar ics file has failed.")
            logger.error(str(e))
            update.message.reply_text(
                "Sorry, I failed to parse your file, please report the issue from here: /source",
                parse_mode=telegram.ParseMode.MARKDOWN,
            )
            return

        # reply back
        update.message.reply_text(
            f"{number_of_events} events successfully re-formatted!",
            parse_mode=telegram.ParseMode.MARKDOWN,
        )
        context.bot.send_document(chat_id=update.effective_chat.id,
                                  document=open(new_file, "rb"))
        update.message.reply_text(
            """*Fantastic, you can now import this `xxx_new.ics` into your Google/ Apple Calendar App, but you need to do this on your computer.*

Instructions for Google Calendar:

1. Open [Google Calendar](https://calendar.google.com/) on Web.
2. At the top right, click gear-like icon and then *Settings*.
3. At the left, click *Import & Export*.
4. Click *Select file from your computer* and select the `.ics` file you get from me.
5. Choose which calendar to add the imported events to. By default, events will be imported into your primary calendar.
6. Click *Import*.
""",
            parse_mode=telegram.ParseMode.MARKDOWN,
        )

    else:
        update.message.reply_text(
            "I can only digest `.ics` file for now.",
            parse_mode=telegram.ParseMode.MARKDOWN,
        )
예제 #27
0
 def tearDown(self):
     if self.ignore:
         return
     request_url = (
         self.url_local_root + f"/api/application_periods/{self.test_use_uid}"
     )
     response = requests.delete(url=request_url, headers=self.headers)
     if response.status_code == 200:
         logger.debug("Successfully removed test-generated data from database.")
     elif response.status_code == 404:
         logger.debug("No test-generated data found in database.")
     else:
         logger.error("Failed to remove test-generated data from database.")
예제 #28
0
def main():
    """Start the bot"""

    logger.info("Getting bot_token from environment")
    bot_token = os.environ.get("BOT_TOKEN", None)

    if bot_token == "REPLACE_ME" or bot_token is None:

        logger.info("Getting bot_token from src/config.conf")
        config_fp = curr_folder / "config.conf"

        if not config_fp.is_file():
            logger.error("bot_token not found: No Config File is Found.")
            return

        with config_fp.open() as f:
            config = json.load(f)
        bot_token = config.get("bot_token", None)

    if bot_token == "REPLACE_ME" or bot_token is None:
        logger.error(
            "bot_token not found: Failed getting bot token from environment and 'config.conf'"
        )
        return

    load_stats()

    # Create the Updater and pass it your bot's token.
    # Make sure to set use_context=True to use the new context based callbacks
    # Post version 12 this will no longer be necessary
    updater = Updater(bot_token, use_context=True)
    # Get the dispatcher to register handlers
    dispatcher = updater.dispatcher

    # Command Handlers
    dispatcher.add_handler(CommandHandler("start", start))
    dispatcher.add_handler(CommandHandler("help", help))
    dispatcher.add_handler(CommandHandler("stats", stats))
    dispatcher.add_handler(CommandHandler("friends", friends))
    dispatcher.add_handler(CommandHandler("source", source))

    # Message Handlers
    dispatcher.add_handler(MessageHandler(Filters.text, echo))
    dispatcher.add_handler(MessageHandler(Filters.document, ics))

    # log all errors
    dispatcher.add_error_handler(error)

    # Start the Bot
    updater.start_polling()
    updater.idle()
예제 #29
0
def process_openreview_url(url: str) -> Tuple[str]:
    """
    Open Review url can be splitted into 5 parts:
    start: 'https://openreview.net/'
    pg_type: 'forum' or 'pdf'
    mid: '?id='
    paper_id: 'nlAxjsniDzg'
    ==> url = start + pg_type + mid + paper_id
    """

    # url validation
    if "openreview.net" not in url:
        logger.error("Unexpected URL Error by openreview URL Handler.")
        raise Exception("Unexpected URL Error by openreview URL Handler.")

    def get_paper_id(url) -> str:
        while "/" in url:
            slash_idx = url.find("/")
            url = url[slash_idx + 1:]
        idx = url.find("=")
        paper_id = url[idx + 1:]
        return paper_id

    def get_pg_from_paper_id(paper_id: str, parse_mode="abs") -> str:
        start = "https://openreview.net/"
        mid = "?id="
        if parse_mode == "abs":
            pg_type = "forum"
        elif parse_mode == "pdf":
            pg_type = "pdf"
        else:
            raise Exception("parse_mode error")
        url = start + pg_type + mid + paper_id
        return url

    paper_id = get_paper_id(url)
    if "forum" in url:
        ## abstract page
        paper_url = url
        pdf_url = get_pg_from_paper_id(paper_id, parse_mode="pdf")
        return paper_id, paper_url, pdf_url
    elif "pdf" in url:
        ## pdf page
        paper_url = get_pg_from_paper_id(paper_id, parse_mode="abs")
        pdf_url = url
        return paper_id, paper_url, pdf_url
    else:
        logger.error("Unexpected URL Error by openreview URL Handler.")
        raise Exception("Unexpected URL Error by openreview URL Handler.")
예제 #30
0
def create_new_user_db(user: TelegramUser):
    db_ref = db.collection(ALL_USER_PARENT).document(user.username)
    doc = db_ref.get()
    if doc.exists:
        logger.error("User already exists")
        return False
    else:
        profile = {
            "username": user.username,
            "first_name": user.first_name,
            "last_name": user.last_name,
            "user_createdAt": timestamp_seconds(),
            "papers": {},
        }
        db_ref.set(profile)
        return True