現在参画中の案件でやたらと同じ定型文を複数チャンネルに送る業務があるので、APIを使って投稿することにして手作業を減らすことにしました。
この手のちょっとしたツールをPythonを使って作るという情報はネットを探せばその辺に落ちている印象ですが、Pythonはインストールしないと使えないという点がセキュリティ()の厳しい現場とはミスマッチです。なので今回はPowershellでMattermostAPIを使ってメッセージを複数チャンネルに送信する方法についてまとめました。
結論から言うと、
-
/users/login
エンドポイントでアクセストークンを取得する -
/users/me/teams/チームID/channels
エンドポイントを検索して投稿したいチャンネルのIDを特定する -
/posts
エンドポイントにPOSTリクエストを送ってメッセージを投稿する
という段階を踏むことでPowershellを使ってMattermostAPIを叩いてメッセージを投稿するということが実現できます。
処理の流れ
今回はmessages
というフォルダの中に送信したい定型文(post.txt
)を配置することにします。
やりたいこととしては、autopost.ps1
を実行すると、post.txt
の内容でMattermostに投稿されるというものです。
getAccessToken.ps1
や`
> tree /f > .\tree.txt
C:.
│ accesstoken.txt
│ autopost.ps1
│ getAccessToken.ps1
│ getAccountInfo.ps1
│ getChannelInfo.ps1
│
└─messages
post.txt
環境構築に使ったスクリプトです。
mkdir messages
new-item ./messages/post.txt
new-item getAccessToken.ps1
new-item getChannelInfo.ps1
new-item getAccountInfo.ps1
new-item autopost.ps1
new-item accesstoken.txt
送信したい定型文は以下の内容とします。
# 5/19(月) サーバー利用禁止時間のお知らせ
@channel
本日5/19(月)は、13:00-16:00の間でサーバーの利用を禁止します。
ご利用予定の方は11:00までに申請をお願いします。
API経由でログインするには
API経由でログインするにはMattermostの統合機能からパーソナルアクセストークンを予め発行して利用する場合(①)と、/users/login
エンドポイントにリクエストを送り、受け取ったセッション用のトークンを利用する方法(②)があります。
アクセストークンを発行した後は、パーソナルアクセストークンを利用する場合と/users/login
エンドポイントで認証した場合とで使い方に変わりはなく、発行されたトークンをヘッダーに付与してリクエストを作成するという点は同じです。
①パーソナルアクセストークンによる認証
アクセストークンを発行する方法については、こちらの記事で詳しく解説している方がいらっしゃいました。基本的にはこちらで記載されている手順で自分のIDに対してパーソナルアクセストークンを発行して、accesstoken.txt
に保存しておけば良いです。
(accesstoken.txt
というファイルに保存しなければならないというわけではなく、単に使い勝手の問題なので、Powershellの内部にべた書きで書いてしまっても良いと思います。べた書きするとGitHubなどでソース管理する時に良くないよねとかは除いて・・・・・・)
①の方法は、管理者アカウントでMattermostにログインし、自身のアカウントにアクセストークンの発行許可を出すということを意図的にやらなければなりません。場合によっては、あなたは管理者アカウントのログイン情報を知らなかったり、現場の上長が管理者アカウントの情報を管理している場合もあるかと思いますが、冒頭でも説明した通り、セキュリティ()が厳格な現場では①の手順で進めようと思っても許可が出ないかもしれません。そんな時は次に紹介する②の方法で認証します。
②/users/loginエンドポイントでの認証
https://developers.mattermost.com/api-documentation/#/operations/Login
/user/login
エンドポイントで認証をするためには、http://your-mattermost-server/api/v4/users/login
宛てのリクエストのBodyにログインIDとパスワードを指定して、Postメソッドでリクエストを送信します。
この時のログインIDとパスワードとは、Webブラウザやデスクトップアプリの画面からログインする時のIDやパスワードと同じです。
$userID = "xxxxxxx@example.com"
$password = "password"
$body = @{
"login_id" = $userID
"password" = $password
}
$response = Invoke-RestMethod -Uri "http://your-mattermost-server/api/v4/users/login" -Method Post -Body $body
$response | Out-File -FilePath ".\response.log" -Encoding utf8 -Append # レスポンスをresponse.logに保存
$response.token | Out-File -FilePath ".\accesstoken.txt" -Encoding utf8 # アクセストークンをaccesstoken.txtに保存
実際に利用する場合は$userID
, $password
にはご自身のアカウント情報を指定してください。
認証が成功するとInvoke-RestMethod
のレスポンスにはtoken
が含まれていて、以降はこのトークンを使いまわすことになるので、accesstoken.txt
にその値を保存しています。
①または②の方法でトークンを取得できればAPI経由でのログインに成功したことになるので、これ以降はアクセストークンがaccesstoken.txt
に保存されている前提での説明に移ります。
XXXXXXXXXXXXXXXXXXXXX
投稿したいチャンネルのIDを特定する
アクセストークンを取得したら、いよいよAPI経由でメッセージを投稿するための材料を揃えていく作業になります。
投稿したいチャンネルが管理されているチームのチームIDを特定したら、
users/me/teams/チームID/channels
というエンドポイントにリクエストしてください。
# チームID
$teamId = "your_team_id"
# エンドポイントURL
$endpoint = "http://your-mattermost-server/api/v4/users/me/teams/$teamId/channels"
# アクセストークンを取得
$accessToken = Get-Content -Path ".\accesstoken.txt"
# リクエストヘッダーの定義
$headers = @{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
}
# APIリクエスト
$response = Invoke-RestMethod -Uri $endpoint -Method Get -Headers $headers
# 結果を表示
$response | ConvertTo-Json | Out-File -FilePath ".\channels.json" -Encoding utf8 -Append
channels.json
で受け取った中身を見ると、
自分が招待されているチャンネルのIDの他にダイレクトメッセージのIDも取得できていると思いますが、その中から自分が投稿したいチャンネルのid
を探してください。
display_name
というプロパティにMattermostのUI上で表示されている名前が記録されているので、それを手がかりに特定できると思います。
※チームIDの確認の仕方
チームIDは、WebブラウザでMattermostのシステムコンソールを開いたときのURLに含まれています。
http://your-mattermost-server/admin_console/user_management/teams/
に移動すると、
サーバーで管理されているMattermostチームの一覧が確認できると思いますが、その中の一つを選択して画面遷移すると、以下のようなURLに移動したとします。
http://your-mattermost-server/admin_console/user_management/teams/ABCABCABCABCABCABC
上記の例の場合、ABCABCABCABCABCABC
がチームIDです。
APIでメッセージを送信する
いよいよAPIで宛先のチャンネルにメッセージを投稿します。メッセージを投稿するには/posts
エンドポイント宛てにPostメソッドでリクエストを送信します。
# MattermostサーバーのURL
$serverUrl = "http://your-mattermost-server/api/v4"
# アクセストークン
$accessToken = Get-Content -Path ".\accesstoken.txt"
# 投稿先のチャンネルID
$channelId = "投稿したいチャンネルのID"
$headers = @{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
}
$message = Get-Content -Path ".\messages\post.txt" -Raw
$body = @{
channel_id = $channelId
message = $message
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri "$serverUrl/posts" -Method Post -Headers $headers -Body $body
$response | Out-File -FilePath ".\response.log" -Encoding utf8 -Append
これで、MattermostAPIを叩いてメッセージを投稿するという当初の目的は達成できるのですが、せっかくなのでもう一工夫したいですよね。毎日投稿するようなメッセージであれば、日付が自動的に更新されてほしいものです。
そこで、post.txt
を次のように修正します。
- # 5/19(月) サーバー利用禁止時間のお知らせ
+ # {{day}}({{date}}) サーバー利用禁止時間のお知らせ
@channel
- 本日5/19(月)は、13:00-16:00の間でサーバーの利用を禁止します。
+ {{day}}({{date}})は、13:00-16:00の間でサーバーの利用を禁止します。
ご利用予定の方は11:00までに申請をお願いします。
txtファイルの中で日付のように動的に内容が変わってほしい箇所を意図的に{{}}
で囲ってしまいます。
次に投稿用のPowershellを次のように修正します。
# MattermostサーバーのURL
$serverUrl = "http://your-mattermost-server/api/v4"
# アクセストークン
$accessToken = Get-Content -Path ".\accesstoken.txt"
# 投稿先のチャンネルID
$channelId = "投稿したいチャンネルのID"
$headers = @{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
}
+ $weekdayMap = @{
+ Sunday = "日"
+ Monday = "月"
+ Tuesday = "火"
+ Wednesday = "水"
+ Thursday = "木"
+ Friday = "金"
+ Saturday = "土"
+ }
+ $date = $((Get-Date).ToString('M/dd'))
+ $day = $weekdayMap[(Get-Date).DayOfWeek.ToString()]
- $message = Get-Content -Path ".\messages\post.txt" -Raw
+ $message = Get-Content -Path ".\messages\post.txt" -Raw
+ $message = $message -replace "{{date}}", $date
+ $message = $message -replace "{{day}}", $day
$body = @{
channel_id = $channelId
message = $message
} | ConvertTo-Json
$response = Invoke-RestMethod -Uri "$serverUrl/posts" -Method Post -Headers $headers -Body $body
$response | Out-File -FilePath ".\response.log" -Encoding utf8 -Append
修正後のpost.txtで{{date}}
や{{day}}
のように動的に変わってほしい箇所を書き換えていたので、Powershell側では動的に変わって欲しい箇所を置換する処理を加えています。これで毎日内容が変わる日付や時間なども、いちいち手修正せず自動的に変わってくれるようになります。
自分のダイレクトメッセージ向けにメッセージを投稿するには
自分宛てのDMを送るには、まずMattermost上での自分のIDを特定する必要があります。
自分のIDを特定するためには、/users/me
エンドポイントにリクエストを送って、自分のアカウントの情報を取得します。
$serverUrl = "http://your-mattermost-server/api/v4"
# アクセストークン
$accessToken = Get-Content -Path ".\accesstoken.txt"
$headers = @{
"Authorization" = "Bearer $accessToken"
"Content-Type" = "application/json"
}
$response = Invoke-RestMethod -Uri "$serverUrl/users/me" -Method Get -Headers $headers
$response | ConvertTo-Json | Out-File -FilePath ".\myInfo.json" -Encoding UTF8 -Append
myInfo.json
の中身を見てみると、様々な自分のアカウントの情報が取れていることがわかると思いますが、id
プロパティの値があなたのアカウントのidになるので、これを控えておいてください。
以降は、myId.txt
というファイルから取得することにします。
abcabcabcabcabcabcabcabcabcabcabcab
次に、既に取得したchannels.json
を見てください。
channels.json
には特定のチャンネルの情報の他に、あらゆるダイレクトメッセージのIDも含まれていて、自分宛てのダイレクトメッセージのIDも含まれています。
ダイレクトメッセージのname
属性は、[自分のID]__[相手のID]
または[相手のID]__[自分のID]
で表現されています。したがって、name
属性が[自分のID]__[自分のID]
となっているデータがあれば、それが自分宛てのダイレクトメッセージの情報なので、そのデータのid属性をテキストエディタ上でgrepするなどして探してください。
実行例として挙げたmyId.txt
のようなidが自分のアカウントのIDだとすると、name
属性がabcabcabcabcabcabcabcabcabcabcabcab__abcabcabcabcabcabcabcabcabcabcabcab
となっているデータのidが自分宛てのダイレクトメッセージのidです。
そのidを、既に紹介した投稿用のスクリプトのBodyのchannel_id
に指定すれば、自分宛てのDMにメッセージを送信することができるので、一斉送信する前のテストなどに活用することができます。
さいごに
PowershellでMattermostに投稿する方法について解説しました。
今回紹介したコードが最適解ではないかもしれませんが、現場の環境やポリシーに合わせて調整しやすいのがスクリプトの良いところだと思います。
投稿作業をPowershellに落とし込むことができたので、あとはタスクスケジューラに登録すれば、定期的に決まったメッセージを送る業務を完全に自動化することもできます。
同じ業務を繰り返す作業に疲弊している方の参考になれば幸いです。