3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

みなさんこんにちは! @ometora_sateyan と申します。
本記事は 富士通クラウドテクノロジーズ Advent Calendar 2023 20 日目の記事です。
昨日は @sameshima_alt さんの、UbuntuでDAW環境を構築するためにN100ミニPCを買った話でした!
実際に機器を購入して、趣味の音楽のための環境構築、、、
憧れますし、1つのロマンですね。
今回構築された環境で作られる音楽作品もこれから楽しみですね!

さて本日はPythonを使ってSlack botとしてToDoリマインダーを作ってみたお話です。

経緯

個人的なお話で恐縮です。
現在社会人(エンジニア)歴5年目であり、情報工学を専攻していた大学時代を含めると初めてプログラミングに触れてから10年以上経っているのですが、今となってはかなりメジャーであるPythonについては実はほとんど触ったことがありませんでした。(学生時代に機械学習を扱う講義で少し触れたくらい)
そんな中、今年度からPythonを扱う業務にアサインされることになり、急遽習得が必要となりました。
そこで社内ツール等でPythonが多く使われていることを見つけ、せっかくなら勉強しながら何かモノを作ってみようと思うようになったのが、本記事のキッカケです。

今回やりたいこと

さて今回は ToDoリストのリマインダー を作ってみます。
以下の要件を設定します。

  • ToDoタスクはGitLabのissueで管理
  • 日常のあらゆるタスク(電球交換や家賃振込など)をissueとして作成
    • 可能ならば期限も設定
  • SlackのIncoming Webhook設定を使ったbotで毎日決まった時間に積み残しのToDoタスクを通知する
    • 今回は毎朝10:00とする
  • 使用言語はPython

用意するもの

  • Slack
  • GitLab
  • 動作確認用の環境
    • ちなみに今回私は VirtualBoxのVM(CentOS) + Dockerコンテナ(Pythonイメージ) を用いました

作成

プロジェクト作成

さて、まずはGitLabのプロジェクトを作成します。
今回は以下の2つのプロジェクトを作成します。

  • ToDoタスク管理用
    • 今回は todo プロジェクトとします
    • こちらのプロジェクトの Project ID をメモしておきます
      • 2023年12月現在のGitLab仕様では、左メニューの Settings -> General で確認できます
  • リマインダー実装用
    • 今回は reminder プロジェクトとします

GitLabのプロジェクト作成画面より作成します。
公開設定については Private にすることをおすすめします。
image.png

Slackのbot設定

次にSlackのbot設定を行います。
後にPythonコードでSlackを呼び出す際に必要なパラメータをこちらで設定します。
また実際に通知するときに、どういうアカウント(どういう名前でどういうアイコン)が送っているのかの見え方の設定もこちらで行います。

まずSlackのWebhook設定のサイトにアクセスします。
未ログインならログインして、右上のワークスペース欄が今回botを追加したいワークスペースになっていることを確認します。
チャンネルへの投稿 の欄にて、今回追加したいチャンネル名を指定して、 Incoming Webhook インテグレーションの追加 を押下します。
(今回は #private-todo というチャンネルに投稿するようにしてみます)
image.png

ボタンを押下すると 新しい機能が追加されました! という表示とともに、Webhookインテグレーションについての各設定の画面に遷移します。
まず冒頭の Webhook URL はメモしておきましょう。(後で使います)
また 名前をカスタマイズアイコンをカスタマイズする も好みに合わせて設定します。
そして 設定を保存する を押下して設定を保存します。
image.png

Pythonで実装

さてGitLabやSlackの準備も整ったので、早速実装していきましょう。
まず根幹となる処理について、以下のようなPythonコードを作成します。

executor.py
import gitlab
import requests
import json
import datetime
import sys

gl = gitlab.Gitlab(private_token=sys.argv[1]) # トークンで認証しながらGitLabクラスのインスタンスを作成

project = gl.projects.get(iterator=True, id={todoプロジェクトのProject ID}) # GitLabのプロジェクト情報を取得

issues = project.issues.list(state='opened', iterator=True) # 取得したプロジェクトにてopenされているissue情報を取得

today = datetime.date.today() # 今日の日付を取得

title = "" # 全issueリスト
title_out = "" # 期限切れissueリスト
title_top = "" # 締切7日以内issueリスト
title_nor = "" # 締切が近くないissueリスト

# issue.titleがissueのタイトル、issue.due_dateが締切日となっている
for issue in issues:
  if issue.due_date is None:
    date_sub = 999
  else:
    due_time = datetime.datetime.strptime(issue.due_date, '%Y-%m-%d')
    date_sub = (datetime.date(due_time.year, due_time.month, due_time.day) - today).days
  if date_sub < 0:
    title_out = title_out + "【期限切れ :cry: 】 :skull_and_crossbones: :skull_and_crossbones: *" + due_time.strftime('%Y/%m/%d') + "マデ " + issue.title + "* :skull_and_crossbones: :skull_and_crossbones: \n"
  elif date_sub < 7:
    title_top = title_top + "【もうすぐ締切!!】 :fire: :fire: *" + due_time.strftime('%Y/%m/%d') + "マデ " + issue.title + "* :fire: :fire: \n"
  else:
    title_nor = title_nor + due_time.strftime('%Y/%m/%d') + "マデ " + issue.title + "\n"

title = title_out + title_top + title_nor
if title == "":
  title = ":tada: :tada: No task!! :tada: :tada:" # もしタスクがないとき(openされているissueがないとき)

requests.post("{作成したSlack Webhook設定のWebhook URL}", data = json.dumps({"text": "*==== :sleepy: " + today.strftime('%Y年%m月%d日') + " 本日のタスク :sleepy: ====* \n\n" + title})) # ここでSlackに投稿される

print("reminder posted!!") # おわり

文言などは好みに合わせてアレンジしてみましょう!

参考までに今回用いたAPIのドキュメントは以下となります。

botの実行準備

冒頭で作成した reminder プロジェクトにて、先ほどの executor.py をプッシュします。

次にPythonコード内からGitlabを呼び出す際に必要なトークンの参照設定を行います。(もしトークン未作成の場合はあらかじめ作成しておきます)
わざわざ変数の参照設定をしなくてもpythonコード内に直に書くことで一応動きますが、トークンを誰でも見られるところに書くのはセキュリティ的にあまり良くないので、、、

  • GitLabの reminder プロジェクトの左メニューにて Settings -> CI/CD と入っていき、 Variables にて Expand を押下
  • Add variable を押下し、以下のパラメータを入力
    • Type: Variable(default)
    • Environments: All(default)
    • 以下の3つ全てにチェック
      • Protect variable
      • Mask variable
      • Expand variable reference
    • Key: GITLAB_TOKEN
    • Value: トークンの値
  • 画面下方の Add variable を押下

次に実行の設定を行います。
今回は自動実行を行いたいのですが、ここでGitLabのCIジョブを活用することにします。
reminder プロジェクト配下に以下のファイルを作成します。

.gitlab-ci.yml
image: python:3.11.3

stages:
    - execute

execute_script:
    stage: execute
    only:
        - web
        - schedule
    script:
        - pip install python-gitlab
        - python executor.py $GITLAB_TOKEN

さて実行準備は整いました!
ちなみにもし別にブランチを作成している場合は、mainブランチにマージしておきましょう。

ToDoリスト作成

それでは todo プロジェクト配下にissueとしてタスクを登録してみましょう。
今回は以下のようなタスクを用意します。
image.png

自動実行設定

最後に毎日決まった時間に自動実行されるよう設定したいと思います。

  • reminder プロジェクトの左メニューにて Build -> pipeline schedules と移動
  • Create a new pipeline schedule を押下
  • 以下のパラメータを指定
    • Description: reminder
    • Interval Pattern: Custom を選択して 0 10 * * *
    • Cron timezone: [UTC+9] Tokyo
    • Select target branch or tag: main
    • Variables: (特に指定しない)
    • Actived にチェック
  • Create pipeline schedule を押下

以下のようなスケジューラー設定が作成されます。
image.png

リマインダー稼働

これで毎朝10時にリマインダーが届くようになりました!
スマホ版アプリでSlackにログインしていたら、10時になると通知が届くようになります。
image.png

そしてSlackの #private_todo チャンネルにもタスクが出るようになりました!
image.png

感想

今回は比較的シンプルなものを作りましたが、複数の既存プラットフォームや既存ライブラリを組み合わせながら、どうやって実現させるか考えるのが難しいながらも楽しかったです。
今まで業務でSlackやGitLabの便利機能に触れていき、いつか自分で設定してみてから普段の生活に役立つモノを作ってみたいと思っていたので、今回それを実現することができて良かったです。
今度はもっと応用させたもの(Slackワークフロー機能を使ってみたり、わざわざGitLab画面に行かずにタスク作成できるようにしたり)を考えてみようと思います。

最後まで読んでくださり、ありがとうございました!
明日は @ystkfujii さんによる traefikのplugin作ってみる という内容の記事が予定されております。
近年主流のクラウド環境やDocker/k8sなどのコンテナ環境で活用されており、ルーティングを行ってくれるというtraefik、これを使ってどのようなものが出来上がるのか楽しみですね!

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?