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?

PythonでSlackに通知する

Last updated at Posted at 2024-12-01

目的

Pythonでslackに通知する
※slackの自身のユーザーで、slackチャンネルにメッセージを送る

背景

前回PythonでLINEに通知しました。
しかし無料だと月に200通までの制限があり、微妙な気持ちになりました。
slackならたくさん送れると思ったので作ってみました。

環境

  • Windows11 バージョン24H2(OSビルド26100.2454)
  • Python3.12.4

作り方

  1. slackページでログインして、Create New Appを押下する
  2. Create an appで「from scratch」を選択する
  3. App Name と workspace を選択し,Create Appを押下する
  4. Featuresの「OAuth & Permissions」を押下する
  5. Scopesの「User Token Scopes」で「Add an OAuth Scope」を押下する
  6. 「chat:write」を選択する
  7. Settingsの Install Appを選択し、Install to <ワークスペース名>を押下する(以下の画像には私のワークスペース名であるRingが表示されている)
  8. 許可するを押下する
  9. アクセストークンを取得する
  10. PythonのSlack通知クラスを作成する
  11. slack-sdkをインストールする

slackページにアクセスして、Create New Appを押下する

image.png

Create an appで「from scratch」を選択

image.png

App Name と workspace を選択し,Create Appを押下

image.png

Featuresの「OAuth & Permissions」を押下

※以下の画面イメージは、App Nameをslack notificationで作った場合の例です。
image.png

Scopesの「User Token Scopes」で「Add an OAuth Scope」を押下

image.png

「chat:write」を選択

image.png

Settingsの Install Appを選択し、Install to <ワークスペース名>を押下

アプリをインストールするワークスペースのボタンが表示されるのでそれを押下する
※以下の画面イメージはworkspaceがRingの場合の例です
image.png

許可するを押下

※以下の画面イメージはworkspaceがRingの場合の例です
image.png

アクセストークンを取得する

Settingsの Install Appで、User OAuth Tokenのアクセストークンを控える
image.png

PythonのSlack通知クラスを作成する

例えば、AIさんに以下を質問する(前回記事で作った、LINEの通知を送るクラスは、こちらline_message_api.py)

python言語で、以下はLINEに通知を送るクラスですが、これと同様な機能でslackに通知を送るクラスを作ってください。
import json
from dataclasses import dataclass, asdict
import os
from typing import Optional
from argparse import ArgumentParser
from linebot import LineBotApi, WebhookHandler  # pip install line-bot-sdk
from linebot.exceptions import InvalidSignatureError, LineBotApiError
from linebot.models import TextSendMessage
# 警告抑制
import warnings
from linebot import LineBotSdkDeprecatedIn30


@dataclass(frozen=True)
class LineMessageAPI:
    """
    LINE Messaging API のアクセストークンとChannel Secretを保持し、
    メッセージ送信機能と、設定情報のJSONファイル保存・ロード機能を提供するクラス。
    デストラクタで設定情報をJSONファイルに保存します。
    設定情報指定せずにインスタンス作成時は、JSONファイルがあればロードし、
    JSONファイルがなければエラー表示で終了します。
    """
    access_token: str
    channel_secret: str
    json_path: str = "line_message_api_config.json"
    line_bot_api: LineBotApi = None  # 型ヒントを追加
    handler: WebhookHandler = None  # 型ヒントを追加

    def __post_init__(self):
        """
        アクセストークンとChannel Secretが指定されていない場合、JSONファイルからロードを試みる。
        JSONファイルが存在しない場合は、エラーメッセージを表示して終了する。
        """
        if not self.access_token or not self.channel_secret:
            try:
                loaded_self = self.load_from_json()
                # _replace で frozen な dataclass の属性を更新
                object.__setattr__(self, "access_token", loaded_self.access_token)
                object.__setattr__(self, "channel_secret", loaded_self.channel_secret)
            except FileNotFoundError:
                print(f"エラー: JSONファイル({self.json_path})が見つかりません。"
                      "アクセストークンとChannel Secretを指定するか、JSONファイルを作成してください。")
                exit(1)
        self.save_to_json()
        object.__setattr__(self, "line_bot_api", LineBotApi(self.access_token))
        object.__setattr__(self, "handler", WebhookHandler(self.channel_secret))

    def send_message(self, user_id: str, message: str) -> bool:
        """
        指定したユーザーにメッセージを送信する。

        Args:
            user_id: 送信先のユーザーID。
            message: 送信するメッセージ。
        Returns:
            送信に成功した場合はTrue、失敗した場合はFalseを返す。
        """
        text_message = TextSendMessage(text=message)
        try:
            self.line_bot_api.push_message(user_id, text_message)
            return True  # 送信成功
        except LineBotApiError as e:
            print(f"メッセージの送信に失敗しました: {e}")
            return False  # 送信失敗

    def save_to_json(self) -> None:
        """
        設定情報をJSONファイルに保存する。
        """
        try:
            with open(self.json_path, 'w', encoding='utf-8') as f:
                json.dump(asdict(self), f, ensure_ascii=False, indent=4)
        except Exception as e:
            print(f"メッセージの保存に失敗しました: {e}")

    @classmethod
    def load_from_json(cls, json_path: Optional[str] = None) -> "LineMessageAPI":
        """
        JSONファイルから設定情報を読み込み、インスタンスを生成する。

        Args:
            json_path: JSONファイルのパス。指定しない場合は、デフォルトのパスを使用する。

        Returns:
            LineMessageAPI インスタンス。
        """
        path = json_path or cls.json_path
        if os.path.exists(path):
            with open(path, "r") as f:
                data = json.load(f)
                return cls(**data)
        else:
            raise FileNotFoundError(f"JSONファイルが見つかりません: {path}")


def get_option():
    arg_parser = ArgumentParser()
    arg_parser.add_argument('-a', '--access_token', type=str, default="",
                            help='LINE Messege APIのアクセストークンを指定する')
    arg_parser.add_argument('-c', '--channel_secret', type=str, default="",
                            help='LINE Messege APIのチャンネルシークレットを指定する')
    arg_parser.add_argument('-i', '--user_id', type=str, default="",
                            help='メッセージを送るUserIDを指定する')
    arg_parser.add_argument('-m', '--message', type=str, default="Hello from Python!",
                            help='送るメッセージを指定する')
    return arg_parser.parse_args()


if __name__ == '__main__':  # インポート時には動かない
    # 警告抑制 v3 api
    warnings.filterwarnings("ignore", category=LineBotSdkDeprecatedIn30)
    arg = get_option()
    print(arg)
    if arg.access_token:
        line_message_api = LineMessageAPI(access_token=arg.access_token, channel_secret=arg.channel_secret)
    else:
        line_message_api = LineMessageAPI(access_token="", channel_secret="")
    if line_message_api.send_message(arg.user_id, arg.message):
        print("メッセージを送信しました。")
    else:
        print("メッセージの送信に失敗しました。")

回答のコードを、自分好みに直して使います。
slack_message_api.py

slack-sdkをインストールする

コマンドラインで以下を入力する

pip install slack-sdk

使い方

SlackMessageAPIクラスのdocstringを見てもらえばわかりますが、引数access_tokeにアクセストークンを指定して、SlackMessageAPIクラスのインスタンスを作り、引数channel_idで送るチャンネルのIDと、messageで送るメッセージを指定して、send_messageメソッドを呼び出せば通知できます。
初回は、以下のコマンドで通知を送ります。slack_message_api_config.jsonファイルにアクセストークンが保存されます。

python slack_message_api.py -a <アクセストークン> -c <通知を送るチャンネルID> -m <メッセージ>

次回からは、アクセストークンをslack_message_api_config.jsonから読み込むので、以下の通り省略できます。

python slack_message_api.py -c <通知をチャンネルID> -m <メッセージ>

チャンネルIDを指定しなかった場合のデフォルトは「#general」です。

おわりに

AIさんのおかげで、すぐ作れました。
Slack APIにも、1つのワークスペースにつき 1 時間あたり 30,000 回のイベント送信というレート制限があるらしいですが、私の使い方だとまず引っかからないので、今後も活用したいです。

関連リンク

参考サイト

ドキュメント

0
0
1

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?