この記事はオルターブース Advent Calendar 2021の11日目の記事です。
弊社ではMicrosoft Teamsをメインに日々の業務を進めています。有用な記事などRSSでフォローしておく情報については個々のRSSで収集するより、Teamsに流しておくほうが社員でシェアでき、記事についてTeams上でディスカッションすることもできるため、Teamsに流すようにしています。
TeamsでRSSを購読する簡単な方法としては、TeamsのRSSコネクタを利用します。
もしくは、少し手間をかけてLogic Appsを使ってRSSを購読しTeamsに通知することもできます。
Logic Appsでわざわざ作るのか?
では、なぜビルドインのコネクタがあるのに、Logic Appsで車輪の再発明のようなことをしたのか?それは、ビルドインのコネクタでは、Basic認証があるRSSで「パスワードあるいはIDに@
を含む」と現状Basic認証が通りません。。。
https://feedback.azure.com/d365community/idea/414f7154-7b26-ec11-b6e6-000d3a4f032c
上記条件のRSSを購読する必要があったため、Logic Appsで簡易RSSリーダーを作ってみました。
このブログでご紹介するLogic Appsの全景は次ようになります。ただ、購読するRSSによっては処理を変える必要があるので、どのようなRSSにも対応してる訳ではありません。本当はビルドインコネクタを使いたいので、よろしければ上記のfeedbackに投票をお願いします!
準備
Logic Appsのデザインを始める前に、処理に必要なAzureリソースを準備します。
- ブログ記事管理のデータベースとしてAzure Storage Tableを利用するので、リソースを作成します。Azure Storage TableはLogic Appsのエンティティアクションで利用します。
az storage account create -g <resource group> -n <name> -l <location> az storage table create -n rss --connection-string <Storage account connection string>
Logic AppsのJavaScriptコード実行アクションを利用するので、統合アカウントリソース作成します。
統合アカウントの作成
Logic Appsと統合アカウントを関連付け
Logic Appsデザイン
Logic AppsでRSSリーダーを作っていきます。
Logic AppsのHTMLトリガーでRSSを取得します。
今回は弊社ブログのRSSを利用します。
https://aadojo.alterbooth.com/feed
RSSはXMLなので、Logic Appsで処理しやすいJSONへ変換します。
XMLからJSONへの変換は式を利用します。
json(xml(triggerBody()))
変換した値は作成アクションに入れます。
JSON変換後は次のようになります。各ブログの記事が
Entry
リストに存在します。{ "feed": { "@xmlns": "http://www.w3.org/2005/Atom", "@xml:lang": "ja", "title": "Alternative Architecture DOJO", "link": { "@href": "https://aadojo.alterbooth.com/" }, "updated": "2021-12-06T03:00:47+09:00", "author": { "name": "alterbooth" }, "generator": { "@uri": "https://blog.hatena.ne.jp/", "@version": "430259ab8ce45790e2f4b723542a620b", "#text": "Hatena::Blog" }, "id": "hatenablog://blog/10257846132689992429", "entry": [ { "title": "Flask+MySQLのアプリを作ってAzureにデプロイする!", "link": [ { "@href": "https://aadojo.alterbooth.com/entry/2021/12/06/030047?utm_source=feed" }, { "@rel": "enclosure", "@href": "https://cdn-ak.f.st-hatena.com/images/fotolife/m/mitsuzono-dev/20211206/20211206023654.png", "@type": "image/png", "@length": "0" } ], "id": "hatenablog://entry/13574176438039949656", "published": "2021-12-06T03:00:47+09:00", "updated": "2021-12-06T03:00:47+09:00", "summary": { ...
Entry
リストのブログ記事を日付(published
)でソートします。Logic Appsと統合アカウントを関連付けたあと、JavaScriptコード実行アクションにソート処理を記載します。
var ret = workflowContext.actions.作成.outputs.feed.entry.sort(function(a,b) { return (a.published < b.published ? -1 : 1); }); return ret;
JavaScriptコード実行アクションの結果(ソート後の値)を作成2アクションに入れます。
データベースとしてAzure Storage Tableを利用するので、Partition KeyとRow Keyを変数アクションで用意します。
Entry
リストをソートした作成2アクションの出力で、For Eachループアクションを開始します。- Azure Storage Tableにデータが存在しない。-> 新規記事
- Azure Storage Tableにデータが存在する。-> 過去記事
ループは逐次処理となるように設定します。
- コンカレンシー制御
有効
- 並列処理の次数
1
Entry
をJSONの解析アクションで解析します。スキーマは次のようになります。
{ "properties": { "author": { "properties": { "name": { "type": "string" } }, "type": "object" }, "content": { "properties": { "#text": { "type": "string" }, "@@type": { "type": "string" } }, "type": "object" }, "id": { "type": "string" }, "link": { "items": { "properties": { "@@href": { "type": "string" }, "@@length": { "type": "string" }, "@@rel": { "type": "string" }, "@@type": { "type": "string" } }, "required": [ "@@href" ], "type": "object" }, "type": "array" }, "published": { "type": "string" }, "summary": { "properties": { "#text": { "type": "string" }, "@@type": { "type": "string" } }, "type": "object" }, "title": { "type": "string" }, "updated": { "type": "string" } }, "type": "object" }
JSONの解析アクションの結果の
id
をURLエンコードの式で変換し、変数の設定アクションでRow Keyへ入れます。encodeUriComponent(body('JSON_の解析')?['id'])
スコープアクション利用して次のアクションをカプセル化します。
- Azure Storage Tableのエンティティの取得アクションを実行します。
取得できた場合はJSONの解析2アクションを実行します。
スキーマは次のようになります。
{ "type": "object", "properties": { "odata.metadata": { "type": "string" }, "odata.etag": { "type": "string" }, "PartitionKey": { "type": "string" }, "RowKey": { "type": "string" }, "Timestamp": { "type": "string" }, "link": { "type": "string" }, "published": { "type": "string" }, "title": { "type": "string" }, "updated": { "type": "string" } } }
条件アクションでIF判定を行います。
JSONの解析2アクションの本文がNULL(Azure Storage Tableに存在しない)かどうか判定します。
Azure Storage Tableに
id
が存在しないとエンティティの取得アクションが失敗(StatusCode 404)するため、失敗でも条件アクションを実行するように設定します。条件アクションの結果がFalseの場合
過去記事のため処理終了です。
条件アクションの結果がTrueの場合
新規記事のため後続処理を行います。
記事のURLを取得したいので、JSONの解析アクションの結果
link
リストでFor Eathループを行います。ループは逐次処理となるように設定します。- コンカレンシー制御
有効
- 並列処理の次数
1
- コンカレンシー制御
link
の内容をJSONの解析3アクションで解析します。スキーマは次のようになります。
{ "properties": { "@@href": { "type": "string" }, "@@length": { "type": "string" }, "@@rel": { "type": "string" }, "@@type": { "type": "string" } }, "type": "object" }
@href
がブログのURLを含んでいるか条件2アクションで判定します。条件2アクションの結果がFalseの場合
OJB画像となるので処理は行いません。
条件2アクションの結果がTrueの場合
- TeamsアクションでTeamsチャンネルに新着記事を投稿します。
Azure Storage Tableに記事の
id
を設定します。Azure Storage Tableには次のようにデータが保存され、新着記事の判定に用います。
初回はAzure Storage Tableが空のため全記事が新規記事判定になってしまいますが、新着記事があると、こんな感じでTeamsに通知してくれます。
Logic Appsの作り方など他のやり方もあるとは思いますが、課題は解決できたので仕事環境改善に繋がりました。本当は本当はビルドインコネクタを使いたいのでfeedbackに投稿をお願いします!
https://feedback.azure.com/d365community/idea/414f7154-7b26-ec11-b6e6-000d3a4f032c