0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Advent Calendarのリマインドをする

Posted at

※この記事はUdon Advent Calendar 2024 - Adventarの10日目の記事です。

はじめに

こんにちは。Udonです。このAdvent Calendarも10日目となりました。

さて、Adventarなんですが、マイページからGoogle Calendarなどに投稿の予定を読み込むことができるiCalのURLを取得することができます。

このURLを使って、Advent Calendarのリマインドをする方法を紹介します。

iCalのURLの取得

まず、Adventarにログインして、マイページに移動します。

マイページの下の方を見ると、iCalのURLが表示されています。形式は以下のようになっています。

https://adventar.org/calendars/[UserID].ics

これを使っていきます。

作ったもの

自分のサークルのサーバで動かすことにしたので、以下のようにサークルのGitLabにリポジトリを作りました。

pgm_udon / Adventar-Notice · GitLab

Dockerを用いて動作するもので、Pythonベースで記述しました。

使い方

  1. リポジトリをクローンする
  2. .env-sample をコピーして .env を作成
  3. .env に必要な情報を記入
  4. docker-compose up -d でコンテナを起動

動作の様子

  1. 午前0時まで待つ
  2. スケジュールをiCalから取得
  3. 本日の日付を取得
  4. 本日が12/26なら終了
  5. 本日の日付とスケジュールの日付が一致するものを取得
  6. メールを送信

iCalendar

本当はBeautifulSoupを使って、Adventarのページから情報を取得する方法を考えていたのですが、seleniumを使う必要があり、環境構築が少し大変そうだと思ったので今回はiCalとiCalendarを使ってみました。

def add_schedule():
    url=f'{MYPAGE_URL}.ics'
    with urllib.request.urlopen(url) as f:
        calendar = Calendar.from_ical(f.read())
        schedule={}
        for component in calendar.walk():
            if component.name == "VEVENT":
                dtstart = component.get('DTSTART').dt
                summary = component.get('SUMMARY')
                key=f'{dtstart}'
                element=f'{summary}'
                if key in schedule:
                    schedule[key].append(element)
                else:
                    schedule[key]=[element]
    return schedule

この部分でiCalからスケジュールを取得しています。urlは.envに記述したMYPAHE_URLを用いることで生成しています。

urllib.request.urlopen(url)でiCalを取得し、Calendar.from_ical(f.read())でiCalを読み込んでいます。読み込んだデータから、VEVENTの部分を取得しています。ここには日付やイベント名などの情報が格納されているので、日付のDTSTARTとイベント名のSUMMARYを取得しています。そして、日付をキー、イベント名を要素として辞書に格納しています。イベントは複数存在する場合があるので、リストとして格納することで複数持てるようにしています。

メール送信の仕組み

メール送信にはsmtplibを使っています。

def send_mail(subject, body):
    msg = MIMEText(body, "plain", "utf-8")
    msg['Subject'] = subject
    msg['From'] = MAIL_SENDUSER
    msg['To'] = MAIL_RECIEVEUSER
    try:
        server = smtplib.SMTP_SSL(MAILSERVER_HOST, MAILSERVER_PORT)
        server.sendmail(MAIL_SENDUSER, MAIL_RECIEVEUSER, msg.as_string())
        server.quit()
    except Exception as e:
        print(e)
    return

server部分は各々の環境に合わせる感じですが、自分はサークルのサーバが使えるのでその中で自分自身に送るという流れで実装しています。おそらく、Gmailなどを使う場合は、認証が必要になると思います。

subjectbodyはそれぞれ別の関数で、日付とイベント名をもとに精製したものを渡すことになっています。

def make_subject(today_str):
    return f'{today_str}の更新予定'

def make_body(summary):
    res="今日は以下のAdvent Calendarの更新日です。\n\n"
    for s in summary:
        res+=f'{s}\n'
    res+="\n早めに更新してください。"
    return res

おわりに

これで毎日午前0時にAdvent Calendarのリマインドが届くようになりました。更新を忘れることも避けることができそうです。

ではまた、次の記事でお会いしましょう。

参考文献

iCalendarデータの仕様とPythonにおける利用方法 #icalendar - Qiita

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?