디지털액자 (4)

알림 기능을 구현해 보겠습니다.

실시간 알림은 websocket 등으로 구현 하면 되지만 디지털액자는 그렇게까지 실시간으로 알림을 보지 않아도 되기 때문에 2~5초 간격으로 서버에 ajax 요청을 보냅니다. 서버는 알림 배열을 반환합니다.

알림 API 응답

클라이언트는 이 배열을 읽고 알림 표시 기한(expire)이 지났는지 확인한 후 알림을 display_time 초 동안 표시합니다. 랜덤 id 값이 부여되기 때문에 클라이언크는 알림을 표시했으면 localstorage 에 이 id 값을 저장합니다.

localstorage 에 읽을 알림 id 저장

이 localstorage 는 새로고침해도 데이터가 지워지지 않습니다. 따라서 한번 표시된 알림은 다시 표시되지 않습니다.

이제 notification 을 자동으로 넣어주는 코드를 짜야 합니다. 우선 일정 시작 전 알려주는 코드를 짭니다.

매 1분마다 작업을 돌려줘야 하기 때문에 fastapi_utils 라이브러리를 사용했습니다.

@app.on_event("startup")
@repeat_every(seconds=60 * 1)  # 1 minute
def event_notification() -> None:
    now = datetime.datetime.now(tz=tzoffset(None, 32400))
    evt_list = get_event_list()
    expire = 60 * 10  # 10 분
    display_time = 30  # 30 초

    for evt in evt_list:
        for reminders in evt.reminders:
            reminder_at = get_evt_start_date(evt) - datetime.timedelta(minutes=reminders.minutes_before_start)
            if now <= reminder_at < now + datetime.timedelta(minutes=1):
                start_date = get_evt_start_date(evt).strftime("%m-%d %H:%M")
                add_notification(f"{start_date}<br>{evt.summary}<br>일정이 {reminders.minutes_before_start}분 후 시작합니다.",
                                 expire=now.timestamp() + expire, display_time=display_time, show_notiboard=False)

        if len(evt.reminders) == 0:
            reminder_at = get_evt_start_date(evt) - datetime.timedelta(minutes=30)
            if now <= reminder_at < now + datetime.timedelta(minutes=1):
                start_date = get_evt_start_date(evt).strftime("%m-%d %H:%M")
                add_notification(f"{start_date}<br>{evt.summary}<br>일정이 {30}분 후 시작합니다.",
                                 expire=now.timestamp() + expire, display_time=display_time, show_notiboard=False)

임의의 초에 1분마다 실행되는 것이기 때문에 (현재시각 <= 리마인더시각 < 현재시각 + 1분) 범위로 잡아야 알림을 빠짐없이 잡을 수 있습니다.

다음은 학사·학과공지 코드로 알림을 구현할 예정입니다.

댓글 남기기