Microsoft 系のあれこれ

港区の SIer で よくわからんことをしている人です。Xamarin 中心でした。(過去形)

SharePointにニュースが投稿されたらTeamsにPower Automateで通知する(投稿者アイコン画像付き)

ポイント

  • ニュース(ページ)が"変更されたら"じゃなくて"発行されたら"通知する
  • 投稿者のアイコン画像はData URI schemeを利用してAdaptive Cardに設定する

内容としてはタイトルの通りです。
上述の通り、いくつかポイントがあるので紹介します。

完成形

f:id:ShunsukeKawai:20200727141633p:plain

手順

準備(ListIDを控える)

SharePointのサイトすべてのサイトコンテンツからサイトのページの設定を開きます。
f:id:ShunsukeKawai:20200727132759p:plain
遷移先のURLから `List=` 以降の部分のIDを控えておきます。
f:id:ShunsukeKawai:20200727132650p:plain

Power Automateの定義

トリガー

Power Automateの作成画面から、トリガーとして「ファイルが作成または変更されたとき (プロパティのみ)」を選択し、サイトのアドレスには対象のサイトをドロップダウンから選択し、ライブラリ名には先ほど控えたListIDをカスタム値を入力から設定します。
フォルダーは `/SitePages` を指定します。
f:id:ShunsukeKawai:20200727134352p:plain

条件の設定その1(ポイント①)

SharePointのニュースは書き始めた段階で下書き状態のファイルを保存してくれます。
非常に便利な機能ですが、今回の場合はこのままなにもせずにTeamsに通知すると書き始めや下書き保存のタイミングで何度も通知が来てしまいます。
そこで、条件により通知を絞り込みます。
Power Automateのアクションから「条件」を選択し、「昇格した状態」が「2」だったらという条件を追加します。
f:id:ShunsukeKawai:20200727135940p:plain
f:id:ShunsukeKawai:20200727135717p:plain
昇格した状態は英語だとPromotedStateっていうみたいです。
最初はバージョンの値に「.0」という文字列が含まれていたらって条件でやってましたが、こっちの方がきれいにできそうです。
参考:
PromotedState 列挙型 (OfficeDevPnP.Core.Pages) | Microsoft Docs
sharepoint online - PromotedState of modern news pages is 0 after publishing - why? - SharePoint Stack Exchange

「2」以外の場合はまだ発行された状態ではないので通知はしないようにしています。

条件の設定その2

その他テンプレートやHome.aspx(ホーム画面)など、通知したくないファイルを条件に指定します。
f:id:ShunsukeKawai:20200727184043p:plain

ユーザーのアイコン画像取得(ポイント②-1)

SharePointから送られてきたデータにも更新者の画像URLは付いていますが、そのURLをTeamsの通知に設定してもアクセスすることができません。(実はWebブラウザでTeamを開いている場合は見れる)
f:id:ShunsukeKawai:20200727151437p:plain
そのため、更新者のメールアドレスから画像を取得する処理を追加します。
アクションの検索に「365」と入力し、「Microsoft 365 Users」を指定して「ユーザーの写真の取得 (V2)」を選択し、更新者のメールアドレスを設定します。
f:id:ShunsukeKawai:20200727152451p:plain
f:id:ShunsukeKawai:20200727150312p:plain

Teamsに投稿する

最後に今までの情報でTeamsに投稿します。

アクションをTeamsで検索して、「独自のアダプティブ カードをフローボットとしてチャンネルに投稿する(プレビュー)」(ここではなぜかチャネルじゃなくてチャンネルって表記だけど気にしない)を選択します。
f:id:ShunsukeKawai:20200727173137p:plain
チーム、チャネルをそれぞれ通知したい対象を選択して設定します。
f:id:ShunsukeKawai:20200727173454p:plain
メッセージに以下のようなJSONを設定します。 設定内容のポイントはその下に記載します。

{
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "type": "AdaptiveCard",
    "version": "1.2",
    "body": [
        {
            "type": "Container",
            "items": [
                {
                    "type": "TextBlock",
                    "text": "記事が投稿or更新されました!",
                    "weight": "Bolder",
                    "size": "Medium"
                }
            ],
            "style": "default"
        },
        {
            "type": "Container",
            "items": [
                {
                    "type": "TextBlock",
                    "text": "@{triggerBody()?['Title']}",
                    "size": "ExtraLarge",
                    "weight": "Bolder",
                    "color": "Attention",
                    "wrap": true
                },
                {
                    "type": "TextBlock",
                    "text": "@{triggerBody()?['Description']}",
                    "wrap": true,
                    "size": "Medium",
                    "height": "stretch",
                    "fontType": "Default"
                }
            ]
        },
        {
            "type": "ColumnSet",
            "columns": [
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "Image",
                            "style": "Person",
                            "url": "data:@{body('ユーザーの写真の取得_(V2)')?['$content-type']};base64,@{body('ユーザーの写真の取得_(V2)')?['$content']}",
                            "size": "Small"
                        }
                    ],
                    "width": "auto"
                },
                {
                    "type": "Column",
                    "items": [
                        {
                            "type": "Container",
                            "items": [
                                {
                                    "type": "TextBlock",
                                    "weight": "Bolder",
                                    "text": "@{triggerBody()?['Editor']?['DisplayName']}",
                                    "wrap": true,
                                    "size": "Large",
                                    "spacing": "None"
                                }
                            ],
                            "height": "stretch",
                            "verticalContentAlignment": "Center"
                        }
                    ],
                    "width": "stretch"
                }
            ]
        },
        {
            "type": "TextBlock",
            "text": "",
            "wrap": true,
            "separator": true
         }
    ],
    "actions": [
        {
            "type": "Action.OpenUrl",
            "title": " 記事はこちら",
            "url": "@{triggerBody()?['{Link}']}",
            "style": "positive",
            "iconUrl": "https://user-images.githubusercontent.com/6369070/88062730-2db2f780-cba4-11ea-9c2f-27a823ab3088.png"
        }
    ]
}

JSONの内容は以下の公式デザイナーでいろいろいじって作成すると便利です。
Designer | Adaptive Cards

AdaptiveCard設定のポイント
  • 画像はData URI schemeを使用して設定 (ポイント②-2)

ユーザー写真取得処理の結果には以下のような値が入っています。画像のタイプと画像ファイルのバイナリデータです。
f:id:ShunsukeKawai:20200727182027p:plain
その内容をAdaptiveCardに設定するにはData URI schemeを使用してImageのURLに以下のように指定します。

data:@{body('ユーザーの写真の取得_(V2)')?['$content-type']};base64,@{body('ユーザーの写真の取得_(V2)')?['$content']}

Data URI schemeについては以下を参考にしてください。
Data URI scheme - Wikipedia

設定画面では以下のように見えると思います。
f:id:ShunsukeKawai:20200727182719p:plain
実際に設定されている内容はこんな感じです。

"url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wB~中略~A//Z",

※※※2020/09/14 追記※※※※※※※※※※※※
イコン画像によってエラーになってうまくいかない場合がありました。
>HTTP 要求に失敗しました。コンテンツが有効な JSON ではありませんでした。

あくまで予想なのですが、バイナリが大きすぎるとエラーになるっぽい挙動をみせています。
そのため、一回OneDriveとかにアップしてその画像を取得/表示するか、以下のようにエラーが発生したら諦めて画像なしで投稿するようにしましょう。
・Teams投稿のアクションをコピーして、すぐ下に貼り付け
・投稿のJSONから画像の部分を削除
・貼り付けたアクションの実行条件の構成を前のタスクに失敗した場合を追加
f:id:ShunsukeKawai:20200914185054p:plain
f:id:ShunsukeKawai:20200914185023p:plain
※※※※※※※※※※※※※※※※※※※※※※


  • 投稿内容と自動付加される境界に線を引く

現在、Power AutomateからTeamsに通知するフローボットを使用するとどうしても下記画像のようなテキストとリンクが自動で付加されてしまいます。
f:id:ShunsukeKawai:20200728005346p:plain
そのため、なんとなくわかりやすくしたいなということで空のテキストを置いてseparatorをtrueにして線を設定しています。

{
    "type": "TextBlock",
    "text": "",
    "wrap": true,
    "separator": true
}

線がないのとあるのじゃなんとなく印象が変わる気がしますよね。
変わんないじゃんと思っていても言わないでください。
f:id:ShunsukeKawai:20200914184522p:plain

  • ボタンに画像を設定する(小ネタ)

iconUrlに画像のURLを設定するだけですが、下記のURLを見てもらうとわかると思いますが、~github~となっています。
これはGitHubのどこのリポジトリでもいいのでIssue作成画面に行ってその画像をコピペやドラッグアンドドロップするとサーバーにあげて公開URLを生成してくれるので、とても便利です。(本来の使い方ではないでしょうが…)
Issueは保存する必要はなく、URLが生成されたらコピーして閉じちゃいましょう。消されたりして画像が見れなくなったことは今までありません。
(今後どうなるかはわかりません)

"actions": [
    {
        "type": "Action.OpenUrl",
        "title": " 記事はこちら",
        "url": "@{triggerBody()?['{Link}']}",
        "style": "positive",
        "iconUrl": "https://user-images.githubusercontent.com/6369070/88062730-2db2f780-cba4-11ea-9c2f-27a823ab3088.png"
    }
]


以上でおしまいです。

できてないこと

ニュースに設定されているサムネイルも通知に含めたかったんですが、うまくいかず。
やり方を知っている方いたら教えてください。