From c4f8c7d1c22bb65cb5c489d6e2fdfa865e618e60 Mon Sep 17 00:00:00 2001 From: Justin Yoo Date: Sat, 16 Jan 2021 11:39:27 +0900 Subject: [PATCH 1/3] Facebook Page Handler (#7) --- .github/workflows/dev.yaml | 80 ++++- .github/workflows/feature.yaml | 80 ++++- .github/workflows/release.yaml | 164 ++++++++++- ...gappdeploy.eventgridhandler-facebook.bicep | 257 ++++++++++++++++ ...ogappdeploy.eventgridhandler-facebook.json | 276 ++++++++++++++++++ ....eventgridhandler-facebook.parameters.json | 21 ++ .../logappdeploy.eventgridhandler-relay.bicep | 239 +++++++++++++++ .../logappdeploy.eventgridhandler-relay.json | 259 ++++++++++++++++ ...loy.eventgridhandler-relay.parameters.json | 12 + ...ogappdeploy.eventgridhandler-twitter.bicep | 81 +++-- ...logappdeploy.eventgridhandler-twitter.json | 85 +++--- 11 files changed, 1436 insertions(+), 118 deletions(-) create mode 100644 resources/logappdeploy.eventgridhandler-facebook.bicep create mode 100644 resources/logappdeploy.eventgridhandler-facebook.json create mode 100644 resources/logappdeploy.eventgridhandler-facebook.parameters.json create mode 100644 resources/logappdeploy.eventgridhandler-relay.bicep create mode 100644 resources/logappdeploy.eventgridhandler-relay.json create mode 100644 resources/logappdeploy.eventgridhandler-relay.parameters.json diff --git a/.github/workflows/dev.yaml b/.github/workflows/dev.yaml index 80b033b..3a5c424 100644 --- a/.github/workflows/dev.yaml +++ b/.github/workflows/dev.yaml @@ -172,6 +172,26 @@ jobs: template: 'resources/logappdeploy.subscription.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} + - name: Deploy LogicApp as EventGrid subscription handler for relay + id: relay + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-relay.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubePublishedEventType=${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} youTubeConvertedEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} + + - name: Deploy LogicApp as EventGrid subscription handler for Facebook + id: facebook + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-facebook.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} facebookPageId=${{ secrets.FACEBOOK_PAGE_ID }} iftttEventName=${{ secrets.IFTTT_EVENT_NAME }} iftttWebhookKey=${{ secrets.IFTTT_WEBHOOK_KEY }} + - name: Deploy LogicApp as EventGrid subscription handler for Twitter id: twitter uses: Azure/arm-deploy@v1 @@ -180,7 +200,7 @@ jobs: resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} deploymentName: 'ytwebsub' template: 'resources/logappdeploy.eventgridhandler-twitter.json' - parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeEventType=${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeTitleSegment=${{ secrets.YOUTUBE_ACCEPTED_TITLE_SEGMENT }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} twitterEventType=${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} twitterEventType=${{ secrets.TWITTER_POSTED_EVENT_TYPE }} - name: Deploy LogicApp as EventGrid subscription handler for ReTweet id: retweeter @@ -190,7 +210,7 @@ jobs: resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} deploymentName: 'ytwebsub' template: 'resources/logappdeploy.eventgridhandler-retweeter.json' - parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} twitterEventType=${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} retweeterProfileId=${{ secrets.RETWEETER_PROFILE_ID }} + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} twitterEventType=${{ secrets.TWITTER_POSTED_EVENT_TYPE }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} retweeterProfileId=${{ secrets.RETWEETER_PROFILE_ID }} - name: Download EventGrid name uses: actions/download-artifact@v2 @@ -204,6 +224,54 @@ jobs: name=$(cat eventgrid_name_dev.txt) echo "::set-output name=name::$name" + - name: Provision EventGrid subscription for relay + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-relay \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.relay.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }}) + + - name: Provision EventGrid subscription for Facebook + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-facebook-${{ secrets.FACEBOOK_PAGE_ID }} \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.facebook.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for Twitter uses: azure/CLI@v1 with: @@ -225,8 +293,8 @@ jobs: -n ${{ steps.twitter.outputs.logicAppName }} \ --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ --query "value" -o tsv) \ - --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }} \ - --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }}) + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) - name: Provision EventGrid subscription for ReTweet uses: azure/CLI@v1 @@ -249,5 +317,5 @@ jobs: -n ${{ steps.retweeter.outputs.logicAppName }} \ --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ --query "value" -o tsv) \ - --advanced-filter type StringBeginsWith ${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} \ - --advanced-filter type StringEndsWith ${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }}) + --advanced-filter type StringBeginsWith ${{ secrets.TWITTER_POSTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.TWITTER_POSTED_EVENT_TYPE }}) diff --git a/.github/workflows/feature.yaml b/.github/workflows/feature.yaml index b640537..6439233 100644 --- a/.github/workflows/feature.yaml +++ b/.github/workflows/feature.yaml @@ -173,6 +173,26 @@ jobs: template: 'resources/logappdeploy.subscription.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} + - name: Deploy LogicApp as EventGrid subscription handler for relay + id: relay + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-relay.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubePublishedEventType=${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} youTubeConvertedEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} + + - name: Deploy LogicApp as EventGrid subscription handler for Facebook + id: facebook + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-facebook.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} facebookPageId=${{ secrets.FACEBOOK_PAGE_ID }} iftttEventName=${{ secrets.IFTTT_EVENT_NAME }} iftttWebhookKey=${{ secrets.IFTTT_WEBHOOK_KEY }} + - name: Deploy LogicApp as EventGrid subscription handler for Twitter id: twitter uses: Azure/arm-deploy@v1 @@ -181,7 +201,7 @@ jobs: resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} deploymentName: 'ytwebsub' template: 'resources/logappdeploy.eventgridhandler-twitter.json' - parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeEventType=${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeTitleSegment=${{ secrets.YOUTUBE_ACCEPTED_TITLE_SEGMENT }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} twitterEventType=${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} twitterEventType=${{ secrets.TWITTER_POSTED_EVENT_TYPE }} - name: Deploy LogicApp as EventGrid subscription handler for ReTweet id: retweeter @@ -191,7 +211,7 @@ jobs: resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} deploymentName: 'ytwebsub' template: 'resources/logappdeploy.eventgridhandler-retweeter.json' - parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} twitterEventType=${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} retweeterProfileId=${{ secrets.RETWEETER_PROFILE_ID }} + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} twitterEventType=${{ secrets.TWITTER_POSTED_EVENT_TYPE }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} retweeterProfileId=${{ secrets.RETWEETER_PROFILE_ID }} - name: Download EventGrid name uses: actions/download-artifact@v2 @@ -205,6 +225,54 @@ jobs: name=$(cat eventgrid_name_dev.txt) echo "::set-output name=name::$name" + - name: Provision EventGrid subscription for relay + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-relay \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.relay.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }}) + + - name: Provision EventGrid subscription for Facebook + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-facebook-${{ secrets.FACEBOOK_PAGE_ID }} \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.facebook.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for Twitter uses: azure/CLI@v1 with: @@ -226,8 +294,8 @@ jobs: -n ${{ steps.twitter.outputs.logicAppName }} \ --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ --query "value" -o tsv) \ - --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }} \ - --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }}) + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) - name: Provision EventGrid subscription for ReTweet uses: azure/CLI@v1 @@ -250,5 +318,5 @@ jobs: -n ${{ steps.retweeter.outputs.logicAppName }} \ --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ --query "value" -o tsv) \ - --advanced-filter type StringBeginsWith ${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} \ - --advanced-filter type StringEndsWith ${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }}) + --advanced-filter type StringBeginsWith ${{ secrets.TWITTER_POSTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.TWITTER_POSTED_EVENT_TYPE }}) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c3ef726..896b3e6 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -46,7 +46,7 @@ jobs: with: subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} - deploymentName: 'dvrl.kr' + deploymentName: 'ytwebsub' template: 'resources/azuredeploy.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} functionAppEnvironment=${{ secrets.RESOURCE_FUNCTIONAPP_ENVIRONMENT_DEV }} youtubeApiKey=${{ secrets.YOUTUBE_API_KEY_DEV }} youtubeFetchParts=${{ secrets.YOUTUBE_API_FETCH_PARTS }} @@ -100,7 +100,7 @@ jobs: with: subscriptionId: ${{ secrets.SUBSCRIPTION_ID_PROD }} resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_PROD }} - deploymentName: 'dvrl.kr' + deploymentName: 'ytwebsub' template: 'resources/azuredeploy.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} functionAppEnvironment=${{ secrets.RESOURCE_FUNCTIONAPP_ENVIRONMENT_PROD }} youtubeApiKey=${{ secrets.YOUTUBE_API_KEY_PROD }} youtubeFetchParts=${{ secrets.YOUTUBE_API_FETCH_PARTS }} @@ -226,6 +226,26 @@ jobs: template: 'resources/logappdeploy.subscription.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} + - name: Deploy LogicApp as EventGrid subscription handler for relay + id: relay + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-relay.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubePublishedEventType=${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} youTubeConvertedEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} + + - name: Deploy LogicApp as EventGrid subscription handler for Facebook + id: facebook + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-facebook.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} facebookPageId=${{ secrets.FACEBOOK_PAGE_ID }} iftttEventName=${{ secrets.IFTTT_EVENT_NAME }} iftttWebhookKey=${{ secrets.IFTTT_WEBHOOK_KEY }} + - name: Deploy LogicApp as EventGrid subscription handler for Twitter id: twitter uses: Azure/arm-deploy@v1 @@ -234,7 +254,7 @@ jobs: resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} deploymentName: 'ytwebsub' template: 'resources/logappdeploy.eventgridhandler-twitter.json' - parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeEventType=${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeTitleSegment=${{ secrets.YOUTUBE_ACCEPTED_TITLE_SEGMENT }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} twitterEventType=${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} twitterEventType=${{ secrets.TWITTER_POSTED_EVENT_TYPE }} - name: Deploy LogicApp as EventGrid subscription handler for ReTweet id: retweeter @@ -244,7 +264,7 @@ jobs: resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} deploymentName: 'ytwebsub' template: 'resources/logappdeploy.eventgridhandler-retweeter.json' - parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} twitterEventType=${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} retweeterProfileId=${{ secrets.RETWEETER_PROFILE_ID }} + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} twitterEventType=${{ secrets.TWITTER_POSTED_EVENT_TYPE }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} retweeterProfileId=${{ secrets.RETWEETER_PROFILE_ID }} - name: Download EventGrid name uses: actions/download-artifact@v2 @@ -258,6 +278,54 @@ jobs: name=$(cat eventgrid_name_dev.txt) echo "::set-output name=name::$name" + - name: Provision EventGrid subscription for relay + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-relay \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.relay.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }}) + + - name: Provision EventGrid subscription for Facebook + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-facebook-${{ secrets.FACEBOOK_PAGE_ID }} \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.facebook.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for Twitter uses: azure/CLI@v1 with: @@ -279,8 +347,8 @@ jobs: -n ${{ steps.twitter.outputs.logicAppName }} \ --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ --query "value" -o tsv) \ - --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }} \ - --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }}) + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) - name: Provision EventGrid subscription for ReTweet uses: azure/CLI@v1 @@ -303,8 +371,8 @@ jobs: -n ${{ steps.retweeter.outputs.logicAppName }} \ --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ --query "value" -o tsv) \ - --advanced-filter type StringBeginsWith ${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} \ - --advanced-filter type StringEndsWith ${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }}) + --advanced-filter type StringBeginsWith ${{ secrets.TWITTER_POSTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.TWITTER_POSTED_EVENT_TYPE }}) functionapp_build_test_deploy_prod: name: 'PROD: FunctionApp Build, Test & Deploy' @@ -419,6 +487,26 @@ jobs: template: 'resources/logappdeploy.subscription.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_PROD }} + - name: Deploy LogicApp as EventGrid subscription handler for relay + id: relay + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_PROD }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_PROD }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-relay.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_PROD }} youTubePublishedEventType=${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} youTubeConvertedEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} + + - name: Deploy LogicApp as EventGrid subscription handler for Facebook + id: facebook + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_PROD }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_PROD }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-facebook.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_PROD }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} facebookPageId=${{ secrets.FACEBOOK_PAGE_ID }} iftttEventName=${{ secrets.IFTTT_EVENT_NAME }} iftttWebhookKey=${{ secrets.IFTTT_WEBHOOK_KEY }} + - name: Deploy LogicApp as EventGrid subscription handler for Twitter id: twitter uses: Azure/arm-deploy@v1 @@ -427,7 +515,7 @@ jobs: resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_PROD }} deploymentName: 'ytwebsub' template: 'resources/logappdeploy.eventgridhandler-twitter.json' - parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeEventType=${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_PROD }} youTubeTitleSegment=${{ secrets.YOUTUBE_ACCEPTED_TITLE_SEGMENT }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} twitterEventType=${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_PROD }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} twitterEventType=${{ secrets.TWITTER_POSTED_EVENT_TYPE }} - name: Deploy LogicApp as EventGrid subscription handler for ReTweet id: retweeter @@ -437,7 +525,7 @@ jobs: resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_PROD }} deploymentName: 'ytwebsub' template: 'resources/logappdeploy.eventgridhandler-retweeter.json' - parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} twitterEventType=${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} retweeterProfileId=${{ secrets.RETWEETER_PROFILE_ID }} + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} twitterEventType=${{ secrets.TWITTER_POSTED_EVENT_TYPE }} twitterProfileId=${{ secrets.TWITTER_PROFILE_ID }} retweeterProfileId=${{ secrets.RETWEETER_PROFILE_ID }} - name: Download EventGrid name uses: actions/download-artifact@v2 @@ -451,6 +539,54 @@ jobs: name=$(cat eventgrid_name_prod.txt) echo "::set-output name=name::$name" + - name: Provision EventGrid subscription for relay + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-relay \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_PROD }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_PROD }} \ + -n ${{ steps.relay.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }}) + + - name: Provision EventGrid subscription for Facebook + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-facebook-${{ secrets.FACEBOOK_PAGE_ID }} \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_PROD }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_PROD }} \ + -n ${{ steps.facebook.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for Twitter uses: azure/CLI@v1 with: @@ -472,8 +608,8 @@ jobs: -n ${{ steps.twitter.outputs.logicAppName }} \ --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ --query "value" -o tsv) \ - --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }} \ - --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_ACCEPTED_EVENT_TYPE }}) + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) - name: Provision EventGrid subscription for ReTweet uses: azure/CLI@v1 @@ -496,5 +632,5 @@ jobs: -n ${{ steps.retweeter.outputs.logicAppName }} \ --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ --query "value" -o tsv) \ - --advanced-filter type StringBeginsWith ${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }} \ - --advanced-filter type StringEndsWith ${{ secrets.TWITTER_ACCEPTED_EVENT_TYPE }}) + --advanced-filter type StringBeginsWith ${{ secrets.TWITTER_POSTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.TWITTER_POSTED_EVENT_TYPE }}) diff --git a/resources/logappdeploy.eventgridhandler-facebook.bicep b/resources/logappdeploy.eventgridhandler-facebook.bicep new file mode 100644 index 0000000..8a03cda --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-facebook.bicep @@ -0,0 +1,257 @@ +// Resource name +param name string + +// Provisioning environment +param env string { + allowed: [ + 'dev' + 'test' + 'prod' + ] + default: 'dev' +} + +// Resource location +param location string = resourceGroup().location + +// Resource location code +param locationCode string = 'krc' + +// YouTube +param youTubeChannelId string +param youTubeEventType string = 'com.youtube.video.converted' +param youTubeTitleSegment string + +// Facebook +param facebookPageId string + +// IFTTT +param iftttEventName string = 'facebook' +param iftttWebhookKey string { + secure: true +} + +var metadata = { + longName: '{0}-${name}-${env}-${locationCode}{1}' + shortName: '{0}${name}${env}${locationCode}' +} + +var logicApp = { + name: format(format(metadata.longName, 'logapp', '-eventgrid-sub-handler-facebook-{0}'), facebookPageId) + location: location +} + +var youtube = { + source: 'https://www.youtube.com/xml/feeds/videos.xml?channel_id=${youTubeChannelId}' + type: youTubeEventType + titleSegment: youTubeTitleSegment +} + +var facebook = { + source: 'https://facebook.com/${facebookPageId}' +} + +var ifttt = { + endpoint: 'https://maker.ifttt.com/trigger/${iftttEventName}/with/key/${iftttWebhookKey}' +} + +resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { + name: logicApp.name + location: logicApp.location + properties: { + state: 'Enabled' + parameters: { + iftttEndpoint: { + value: ifttt.endpoint + } + } + definition: { + '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#' + contentVersion: '1.0.0.0' + parameters: { + '$connections': { + type: 'object' + defaultValue: {} + } + acceptedYouTubeSource: { + type: 'string' + defaultValue: youtube.source + } + acceptedYouTubeType: { + type: 'string' + defaultValue: youtube.type + } + acceptedYouTubeTitleSegment: { + type: 'string' + defaultValue: youtube.titleSegment + } + iftttEndpoint: { + type: 'string' + defaultValue: '' + } + } + triggers: { + manual: { + type: 'Request' + kind: 'Http' + inputs: { + schema: { + type: 'object' + properties: { + id: { + type: 'string' + } + specversion: { + type: 'string' + } + source: { + type: 'string' + } + type: { + type: 'string' + } + time: { + type: 'string' + } + datacontenttype: { + type: 'string' + } + data: { + type: 'object' + properties: { + channelId: { + type: 'string' + } + videoId: { + type: 'string' + } + title: { + type: 'string' + } + description: { + type: 'string' + } + link: { + type: 'string' + } + thumbnailLink: { + type: 'string' + } + datePublished: { + type: 'string' + } + dateUpdated: { + type: 'string' + } + } + } + } + } + } + } + } + actions: { + Proceed_Only_If_Accepted_Source: { + type: 'If' + runAfter: {} + expression: { + and: [ + { + equals: [ + '@triggerBody()?[\'source\']' + '@parameters(\'acceptedYouTubeSource\')' + ] + } + { + equals: [ + '@triggerBody()?[\'type\']' + '@parameters(\'acceptedYouTubeType\')' + ] + } + ] + } + actions: {} + else: { + actions: { + Cancel_Processing_Post: { + type: 'Terminate' + runAfter: {} + inputs: { + runStatus: 'Cancelled' + } + } + } + } + } + Split_Title: { + type: 'Compose' + runAfter: { + Proceed_Only_If_Accepted_Source: [ + 'Succeeded' + ] + } + inputs: '@split(triggerBody()?[\'data\']?[\'title\'], \'|\')' + } + Process_Only_If_Title_Met: { + type: 'If' + runAfter: { + Split_Title: [ + 'Succeeded' + ] + } + expression: { + and: [ + { + equals: [ + '@trim(last(outputs(\'Split_Title\')))' + '@parameters(\'acceptedYouTubeTitleSegment\')' + ] + } + ] + } + actions: { + Build_IFTTT_Post: { + type: 'Compose' + runAfter: {} + inputs: { + value1: '@{trim(first(outputs(\'Split_Title\')))} | @{trim(first(skip(outputs(\'Split_Title\'), 1)))}' + value2: '@replace(triggerBody()?[\'data\']?[\'description\'], \'\n\', \'
 
\')' + value3: '@triggerBody()?[\'data\']?[\'link\']' + } + } + } + else: { + actions: { + Cancel_Posting_Facebook: { + type: 'Terminate' + runAfter: {} + inputs: { + runStatus: 'Cancelled' + } + } + } + } + } + Send_IFTTT_Post: { + type: 'Http' + runAfter: { + Process_Only_If_Title_Met: [ + 'Succeeded' + ] + } + inputs: { + method: 'POST' + uri: '@parameters(\'iftttEndpoint\')' + headers: { + 'Content-Type': 'application/json' + } + body: '@outputs(\'Build_IFTTT_Post\')' + } + } + } + outputs: {} + } + } +} + +output logicAppName string = logapp.name diff --git a/resources/logappdeploy.eventgridhandler-facebook.json b/resources/logappdeploy.eventgridhandler-facebook.json new file mode 100644 index 0000000..5a97a28 --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-facebook.json @@ -0,0 +1,276 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "type": "string" + }, + "env": { + "type": "string", + "defaultValue": "dev", + "allowedValues": [ + "dev", + "test", + "prod" + ] + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]" + }, + "locationCode": { + "type": "string", + "defaultValue": "krc" + }, + "youTubeChannelId": { + "type": "string" + }, + "youTubeEventType": { + "type": "string", + "defaultValue": "com.youtube.video.converted" + }, + "youTubeTitleSegment": { + "type": "string" + }, + "facebookPageId": { + "type": "string" + }, + "iftttEventName": { + "type": "string", + "defaultValue": "facebook" + }, + "iftttWebhookKey": { + "type": "secureString" + } + }, + "functions": [], + "variables": { + "metadata": { + "longName": "[format('{{0}}-{0}-{1}-{2}{{1}}', parameters('name'), parameters('env'), parameters('locationCode'))]", + "shortName": "[format('{{0}}{0}{1}{2}', parameters('name'), parameters('env'), parameters('locationCode'))]" + }, + "logicApp": { + "name": "[format(format(variables('metadata').longName, 'logapp', '-eventgrid-sub-handler-facebook-{0}'), parameters('facebookPageId'))]", + "location": "[parameters('location')]" + }, + "youtube": { + "source": "[format('https://www.youtube.com/xml/feeds/videos.xml?channel_id={0}', parameters('youTubeChannelId'))]", + "type": "[parameters('youTubeEventType')]", + "titleSegment": "[parameters('youTubeTitleSegment')]" + }, + "facebook": { + "source": "[format('https://facebook.com/{0}', parameters('facebookPageId'))]" + }, + "ifttt": { + "endpoint": "[format('https://maker.ifttt.com/trigger/{0}/with/key/{1}', parameters('iftttEventName'), parameters('iftttWebhookKey'))]" + } + }, + "resources": [ + { + "type": "Microsoft.Logic/workflows", + "apiVersion": "2019-05-01", + "name": "[variables('logicApp').name]", + "location": "[variables('logicApp').location]", + "properties": { + "state": "Enabled", + "parameters": { + "iftttEndpoint": { + "value": "[variables('ifttt').endpoint]" + } + }, + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "$connections": { + "type": "object", + "defaultValue": {} + }, + "acceptedYouTubeSource": { + "type": "string", + "defaultValue": "[variables('youtube').source]" + }, + "acceptedYouTubeType": { + "type": "string", + "defaultValue": "[variables('youtube').type]" + }, + "acceptedYouTubeTitleSegment": { + "type": "string", + "defaultValue": "[variables('youtube').titleSegment]" + }, + "iftttEndpoint": { + "type": "string", + "defaultValue": "" + } + }, + "triggers": { + "manual": { + "type": "Request", + "kind": "Http", + "inputs": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "specversion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "type": { + "type": "string" + }, + "time": { + "type": "string" + }, + "datacontenttype": { + "type": "string" + }, + "data": { + "type": "object", + "properties": { + "channelId": { + "type": "string" + }, + "videoId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "link": { + "type": "string" + }, + "thumbnailLink": { + "type": "string" + }, + "datePublished": { + "type": "string" + }, + "dateUpdated": { + "type": "string" + } + } + } + } + } + } + } + }, + "actions": { + "Proceed_Only_If_Accepted_Source": { + "type": "If", + "runAfter": {}, + "expression": { + "and": [ + { + "equals": [ + "@triggerBody()?['source']", + "@parameters('acceptedYouTubeSource')" + ] + }, + { + "equals": [ + "@triggerBody()?['type']", + "@parameters('acceptedYouTubeType')" + ] + } + ] + }, + "actions": {}, + "else": { + "actions": { + "Cancel_Processing_Post": { + "type": "Terminate", + "runAfter": {}, + "inputs": { + "runStatus": "Cancelled" + } + } + } + } + }, + "Split_Title": { + "type": "Compose", + "runAfter": { + "Proceed_Only_If_Accepted_Source": [ + "Succeeded" + ] + }, + "inputs": "@split(triggerBody()?['data']?['title'], '|')" + }, + "Process_Only_If_Title_Met": { + "type": "If", + "runAfter": { + "Split_Title": [ + "Succeeded" + ] + }, + "expression": { + "and": [ + { + "equals": [ + "@trim(last(outputs('Split_Title')))", + "@parameters('acceptedYouTubeTitleSegment')" + ] + } + ] + }, + "actions": { + "Build_IFTTT_Post": { + "type": "Compose", + "runAfter": {}, + "inputs": { + "value1": "@{trim(first(outputs('Split_Title')))} | @{trim(first(skip(outputs('Split_Title'), 1)))}", + "value2": "@replace(triggerBody()?['data']?['description'], '\n', '
 
')", + "value3": "@triggerBody()?['data']?['link']" + } + } + }, + "else": { + "actions": { + "Cancel_Posting_Facebook": { + "type": "Terminate", + "runAfter": {}, + "inputs": { + "runStatus": "Cancelled" + } + } + } + } + }, + "Send_IFTTT_Post": { + "type": "Http", + "runAfter": { + "Process_Only_If_Title_Met": [ + "Succeeded" + ] + }, + "inputs": { + "method": "POST", + "uri": "@parameters('iftttEndpoint')", + "headers": { + "Content-Type": "application/json" + }, + "body": "@outputs('Build_IFTTT_Post')" + } + } + }, + "outputs": {} + } + } + } + ], + "outputs": { + "logicAppName": { + "type": "string", + "value": "[variables('logicApp').name]" + } + } +} \ No newline at end of file diff --git a/resources/logappdeploy.eventgridhandler-facebook.parameters.json b/resources/logappdeploy.eventgridhandler-facebook.parameters.json new file mode 100644 index 0000000..540f932 --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-facebook.parameters.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "" + }, + "youTubeChannelId": { + "value": "" + }, + "youTubeTitleSegment": { + "value": "" + }, + "facebookPageId": { + "value": "" + }, + "iftttEventName": { + "value": "" + } + } +} diff --git a/resources/logappdeploy.eventgridhandler-relay.bicep b/resources/logappdeploy.eventgridhandler-relay.bicep new file mode 100644 index 0000000..f55527e --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-relay.bicep @@ -0,0 +1,239 @@ +// Resource name +param name string + +// Provisioning environment +param env string { + allowed: [ + 'dev' + 'test' + 'prod' + ] + default: 'dev' +} + +// Resource location +param location string = resourceGroup().location + +// Resource location code +param locationCode string = 'krc' + +// Function App +param functionName string = 'FetchAsync' + +// YouTube +param youTubeChannelId string +param youTubePublishedEventType string = 'com.youtube.video.published' +param youTubeConvertedEventType string = 'com.youtube.video.converted' + +var metadata = { + longName: '{0}-${name}-${env}-${locationCode}{1}' + shortName: '{0}${name}${env}${locationCode}' +} + +var logicApp = { + name: format(metadata.longName, 'logapp', '-eventgrid-sub-handler-relay') + location: location +} + +var functionApp = { + name: format(metadata.longName, 'fncapp', '') + functionResourceId: resourceId('Microsoft.Web/sites/functions', format(metadata.longName, 'fncapp', ''), functionName) +} + +var eventGridTopic = { + name: format(metadata.longName, 'evtgrd', '-topic') + resourceId: resourceId('Microsoft.EventGrid/topics', format(metadata.longName, 'evtgrd', '-topic')) +} + +var youtube = { + source: 'https://www.youtube.com/xml/feeds/videos.xml?channel_id=${youTubeChannelId}' + publishedType: youTubePublishedEventType + convertedType: youTubeConvertedEventType +} + +resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { + name: logicApp.name + location: logicApp.location + properties: { + state: 'Enabled' + parameters: { + functionAppKey: { + value: listKeys(functionApp.functionResourceId, '2020-06-01').default + } + eventGridTopicEndpoint: { + value: reference(eventGridTopic.resourceId, '2020-06-01', 'Full').properties.endpoint + } + eventGridTopicKey: { + value: listKeys(eventGridTopic.resourceId, '2020-06-01').key1 + } + } + definition: { + '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#' + contentVersion: '1.0.0.0' + parameters: { + '$connections': { + type: 'object' + defaultValue: {} + } + functionAppName: { + type: 'string' + defaultValue: functionApp.name + } + functionAppKey: { + type: 'string' + defaultValue: '' + } + publishedYouTubeSource: { + type: 'string' + defaultValue: youtube.source + } + publishedYouTubeType: { + type: 'string' + defaultValue: youtube.publishedType + } + convertedYouTubeSource: { + type: 'string' + defaultValue: youtube.source + } + convertedYouTubeType: { + type: 'string' + defaultValue: youtube.convertedType + } + eventGridTopicEndpoint: { + type: 'string' + defaultValue: '' + } + eventGridTopicKey: { + type: 'string' + defaultValue: '' + } + } + triggers: { + manual: { + type: 'Request' + kind: 'Http' + inputs: { + schema: { + type: 'object' + properties: { + id: { + type: 'string' + } + specversion: { + type: 'string' + } + source: { + type: 'string' + } + type: { + type: 'string' + } + time: { + type: 'string' + } + datacontenttype: { + type: 'string' + } + data: { + type: 'string' + } + traceparent: { + type: 'string' + } + } + } + } + } + } + actions: { + Proceed_Only_If_Published: { + type: 'If' + runAfter: {} + expression: { + and: [ + { + equals: [ + '@triggerBody()?[\'source\']' + '@parameters(\'publishedYouTubeSource\')' + ] + } + { + equals: [ + '@triggerBody()?[\'type\']' + '@parameters(\'publishedYouTubeType\')' + ] + } + ] + } + actions: { + Fetch_YouTube_Video_Details: { + type: 'Http' + runAfter: {} + inputs: { + method: 'POST' + uri: 'https://@{parameters(\'functionAppName\')}.azurewebsites.net/api/fetch' + headers: { + 'x-functions-key': '@parameters(\'functionAppKey\')' + } + body: '@triggerBody()' + } + } + } + else: { + actions: { + Cancel_Processing_Event: { + type: 'Terminate' + runAfter: {} + inputs: { + runStatus: 'Cancelled' + } + } + } + } + } + Build_CloudEvents_Payload: { + type: 'Compose' + runAfter: { + Proceed_Only_If_Published: [ + 'Succeeded' + ] + } + inputs: { + id: '@guid()' + specversion: '1.0' + source: '@parameters(\'convertedYouTubeSource\')' + type: '@parameters(\'convertedYouTubeType\')' + time: '@utcNow()' + datacontenttype: 'application/cloudevents+json' + data: '@body(\'Fetch_YouTube_Video_Details\')' + } + } + Send_EventGrid_Tweet: { + type: 'Http' + runAfter: { + Build_CloudEvents_Payload: [ + 'Succeeded' + ] + } + inputs: { + method: 'POST' + uri: '@parameters(\'eventGridTopicEndpoint\')' + headers: { + 'aeg-sas-key': '@parameters(\'eventGridTopicKey\')' + 'Content-Type': '@outputs(\'Build_CloudEvents_Payload\')?[\'datacontenttype\']' + 'ce-id': '@outputs(\'Build_CloudEvents_Payload\')?[\'id\']' + 'ce-specversion': '@outputs(\'Build_CloudEvents_Payload\')?[\'specversion\']' + 'ce-source': '@outputs(\'Build_CloudEvents_Payload\')?[\'source\']' + 'ce-type': '@outputs(\'Build_CloudEvents_Payload\')?[\'type\']' + 'ce-time': '@outputs(\'Build_CloudEvents_Payload\')?[\'time\']' + } + body: '@outputs(\'Build_CloudEvents_Payload\')' + } + } + } + outputs: {} + } + } +} + +output logicAppName string = logapp.name diff --git a/resources/logappdeploy.eventgridhandler-relay.json b/resources/logappdeploy.eventgridhandler-relay.json new file mode 100644 index 0000000..167a7b9 --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-relay.json @@ -0,0 +1,259 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "type": "string" + }, + "env": { + "type": "string", + "defaultValue": "dev", + "allowedValues": [ + "dev", + "test", + "prod" + ] + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]" + }, + "locationCode": { + "type": "string", + "defaultValue": "krc" + }, + "functionName": { + "type": "string", + "defaultValue": "FetchAsync" + }, + "youTubeChannelId": { + "type": "string" + }, + "youTubePublishedEventType": { + "type": "string", + "defaultValue": "com.youtube.video.published" + }, + "youTubeConvertedEventType": { + "type": "string", + "defaultValue": "com.youtube.video.converted" + } + }, + "functions": [], + "variables": { + "metadata": { + "longName": "[format('{{0}}-{0}-{1}-{2}{{1}}', parameters('name'), parameters('env'), parameters('locationCode'))]", + "shortName": "[format('{{0}}{0}{1}{2}', parameters('name'), parameters('env'), parameters('locationCode'))]" + }, + "logicApp": { + "name": "[format(variables('metadata').longName, 'logapp', '-eventgrid-sub-handler-relay')]", + "location": "[parameters('location')]" + }, + "functionApp": { + "name": "[format(variables('metadata').longName, 'fncapp', '')]", + "functionResourceId": "[resourceId('Microsoft.Web/sites/functions', format(variables('metadata').longName, 'fncapp', ''), parameters('functionName'))]" + }, + "eventGridTopic": { + "name": "[format(variables('metadata').longName, 'evtgrd', '-topic')]", + "resourceId": "[resourceId('Microsoft.EventGrid/topics', format(variables('metadata').longName, 'evtgrd', '-topic'))]" + }, + "youtube": { + "source": "[format('https://www.youtube.com/xml/feeds/videos.xml?channel_id={0}', parameters('youTubeChannelId'))]", + "publishedType": "[parameters('youTubePublishedEventType')]", + "convertedType": "[parameters('youTubeConvertedEventType')]" + } + }, + "resources": [ + { + "type": "Microsoft.Logic/workflows", + "apiVersion": "2019-05-01", + "name": "[variables('logicApp').name]", + "location": "[variables('logicApp').location]", + "properties": { + "state": "Enabled", + "parameters": { + "functionAppKey": { + "value": "[listKeys(variables('functionApp').functionResourceId, '2020-06-01').default]" + }, + "eventGridTopicEndpoint": { + "value": "[reference(variables('eventGridTopic').resourceId, '2020-06-01', 'Full').properties.endpoint]" + }, + "eventGridTopicKey": { + "value": "[listKeys(variables('eventGridTopic').resourceId, '2020-06-01').key1]" + } + }, + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "$connections": { + "type": "object", + "defaultValue": {} + }, + "functionAppName": { + "type": "string", + "defaultValue": "[variables('functionApp').name]" + }, + "functionAppKey": { + "type": "string", + "defaultValue": "" + }, + "publishedYouTubeSource": { + "type": "string", + "defaultValue": "[variables('youtube').source]" + }, + "publishedYouTubeType": { + "type": "string", + "defaultValue": "[variables('youtube').publishedType]" + }, + "convertedYouTubeSource": { + "type": "string", + "defaultValue": "[variables('youtube').source]" + }, + "convertedYouTubeType": { + "type": "string", + "defaultValue": "[variables('youtube').convertedType]" + }, + "eventGridTopicEndpoint": { + "type": "string", + "defaultValue": "" + }, + "eventGridTopicKey": { + "type": "string", + "defaultValue": "" + } + }, + "triggers": { + "manual": { + "type": "Request", + "kind": "Http", + "inputs": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "specversion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "type": { + "type": "string" + }, + "time": { + "type": "string" + }, + "datacontenttype": { + "type": "string" + }, + "data": { + "type": "string" + }, + "traceparent": { + "type": "string" + } + } + } + } + } + }, + "actions": { + "Proceed_Only_If_Published": { + "type": "If", + "runAfter": {}, + "expression": { + "and": [ + { + "equals": [ + "@triggerBody()?['source']", + "@parameters('publishedYouTubeSource')" + ] + }, + { + "equals": [ + "@triggerBody()?['type']", + "@parameters('publishedYouTubeType')" + ] + } + ] + }, + "actions": { + "Fetch_YouTube_Video_Details": { + "type": "Http", + "runAfter": {}, + "inputs": { + "method": "POST", + "uri": "https://@{parameters('functionAppName')}.azurewebsites.net/api/fetch", + "headers": { + "x-functions-key": "@parameters('functionAppKey')" + }, + "body": "@triggerBody()" + } + } + }, + "else": { + "actions": { + "Cancel_Processing_Event": { + "type": "Terminate", + "runAfter": {}, + "inputs": { + "runStatus": "Cancelled" + } + } + } + } + }, + "Build_CloudEvents_Payload": { + "type": "Compose", + "runAfter": { + "Proceed_Only_If_Published": [ + "Succeeded" + ] + }, + "inputs": { + "id": "@guid()", + "specversion": "1.0", + "source": "@parameters('convertedYouTubeSource')", + "type": "@parameters('convertedYouTubeType')", + "time": "@utcNow()", + "datacontenttype": "application/cloudevents+json", + "data": "@body('Fetch_YouTube_Video_Details')" + } + }, + "Send_EventGrid_Tweet": { + "type": "Http", + "runAfter": { + "Build_CloudEvents_Payload": [ + "Succeeded" + ] + }, + "inputs": { + "method": "POST", + "uri": "@parameters('eventGridTopicEndpoint')", + "headers": { + "aeg-sas-key": "@parameters('eventGridTopicKey')", + "Content-Type": "@outputs('Build_CloudEvents_Payload')?['datacontenttype']", + "ce-id": "@outputs('Build_CloudEvents_Payload')?['id']", + "ce-specversion": "@outputs('Build_CloudEvents_Payload')?['specversion']", + "ce-source": "@outputs('Build_CloudEvents_Payload')?['source']", + "ce-type": "@outputs('Build_CloudEvents_Payload')?['type']", + "ce-time": "@outputs('Build_CloudEvents_Payload')?['time']" + }, + "body": "@outputs('Build_CloudEvents_Payload')" + } + } + }, + "outputs": {} + } + } + } + ], + "outputs": { + "logicAppName": { + "type": "string", + "value": "[variables('logicApp').name]" + } + } +} \ No newline at end of file diff --git a/resources/logappdeploy.eventgridhandler-relay.parameters.json b/resources/logappdeploy.eventgridhandler-relay.parameters.json new file mode 100644 index 0000000..1509d74 --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-relay.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "" + }, + "youTubeChannelId": { + "value": "" + } + } +} diff --git a/resources/logappdeploy.eventgridhandler-twitter.bicep b/resources/logappdeploy.eventgridhandler-twitter.bicep index eec4432..8e55fe4 100644 --- a/resources/logappdeploy.eventgridhandler-twitter.bicep +++ b/resources/logappdeploy.eventgridhandler-twitter.bicep @@ -17,12 +17,9 @@ param location string = resourceGroup().location // Resource location code param locationCode string = 'krc' -// Function App -param functionName string = 'FetchAsync' - // YouTube -param youTubeEventType string = 'com.youtube.video.published' param youTubeChannelId string +param youTubeEventType string = 'com.youtube.video.converted' param youTubeTitleSegment string // Twitter @@ -58,11 +55,6 @@ var logicApp = { location: location } -var functionApp = { - name: format(metadata.longName, 'fncapp', '') - functionResourceId: resourceId('Microsoft.Web/sites/functions', format(metadata.longName, 'fncapp', ''), functionName) -} - var eventGridTopic = { name: format(metadata.longName, 'evtgrd', '-topic') resourceId: resourceId('Microsoft.EventGrid/topics', format(metadata.longName, 'evtgrd', '-topic')) @@ -94,9 +86,6 @@ resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { } } } - functionAppKey: { - value: listKeys(functionApp.functionResourceId, '2020-06-01').default - } eventGridTopicEndpoint: { value: reference(eventGridTopic.resourceId, '2020-06-01', 'Full').properties.endpoint } @@ -112,14 +101,6 @@ resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { type: 'object' defaultValue: {} } - functionAppName: { - type: 'string' - defaultValue: functionApp.name - } - functionAppKey: { - type: 'string' - defaultValue: '' - } acceptedYouTubeSource: { type: 'string' defaultValue: youtube.source @@ -176,10 +157,33 @@ resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { type: 'string' } data: { - type: 'string' - } - traceparent: { - type: 'string' + type: 'object' + properties: { + channelId: { + type: 'string' + } + videoId: { + type: 'string' + } + title: { + type: 'string' + } + description: { + type: 'string' + } + link: { + type: 'string' + } + thumbnailLink: { + type: 'string' + } + datePublished: { + type: 'string' + } + dateUpdated: { + type: 'string' + } + } } } } @@ -187,7 +191,7 @@ resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { } } actions: { - Proceed_Only_If_Published: { + Proceed_Only_If_Accepted_Source: { type: 'If' runAfter: {} expression: { @@ -206,23 +210,10 @@ resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { } ] } - actions: { - Fetch_YouTube_Video_Details: { - type: 'Http' - runAfter: {} - inputs: { - method: 'POST' - uri: 'https://@{parameters(\'functionAppName\')}.azurewebsites.net/api/fetch' - headers: { - 'x-functions-key': '@parameters(\'functionAppKey\')' - } - body: '@triggerBody()' - } - } - } + actions: {} else: { actions: { - Cancel_Processing_Event: { + Cancel_Processing_Tweet: { type: 'Terminate' runAfter: {} inputs: { @@ -235,20 +226,20 @@ resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { Split_Title: { type: 'Compose' runAfter: { - 'Proceed_Only_If_Published': [ + Proceed_Only_If_Accepted_Source: [ 'Succeeded' ] } - inputs: '@split(body(\'Fetch_YouTube_Video_Details\')?[\'title\'], \'|\')' + inputs: '@split(triggerBody()?[\'data\']?[\'title\'], \'|\')' } Split_Description: { type: 'Compose' runAfter: { - 'Proceed_Only_If_Published': [ + Proceed_Only_If_Accepted_Source: [ 'Succeeded' ] } - inputs: '@split(body(\'Fetch_YouTube_Video_Details\')?[\'description\'], \'---\')' + inputs: '@split(triggerBody()?[\'data\']?[\'description\'], \'---\')' } Process_Only_If_Title_Met: { type: 'If' @@ -274,7 +265,7 @@ resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { Build_Tweet_Post: { type: 'Compose' runAfter: {} - inputs: '@{trim(first(outputs(\'Split_Title\')))}\n\n@{trim(first(outputs(\'Split_Description\')))}\n\n@{body(\'Fetch_YouTube_Video_Details\')?[\'link\']}' + inputs: '@{trim(first(outputs(\'Split_Title\')))}\n\n@{trim(first(outputs(\'Split_Description\')))}\n\n@{triggerBody()?[\'data\']?[\'link\']}' } } else: { diff --git a/resources/logappdeploy.eventgridhandler-twitter.json b/resources/logappdeploy.eventgridhandler-twitter.json index 12accb1..73569cd 100644 --- a/resources/logappdeploy.eventgridhandler-twitter.json +++ b/resources/logappdeploy.eventgridhandler-twitter.json @@ -22,16 +22,12 @@ "type": "string", "defaultValue": "krc" }, - "functionName": { - "type": "string", - "defaultValue": "FetchAsync" + "youTubeChannelId": { + "type": "string" }, "youTubeEventType": { "type": "string", - "defaultValue": "com.youtube.video.published" - }, - "youTubeChannelId": { - "type": "string" + "defaultValue": "com.youtube.video.converted" }, "youTubeTitleSegment": { "type": "string" @@ -60,10 +56,6 @@ "name": "[format(format(variables('metadata').longName, 'logapp', '-eventgrid-sub-handler-twitter-{0}'), parameters('twitterProfileId'))]", "location": "[parameters('location')]" }, - "functionApp": { - "name": "[format(variables('metadata').longName, 'fncapp', '')]", - "functionResourceId": "[resourceId('Microsoft.Web/sites/functions', format(variables('metadata').longName, 'fncapp', ''), parameters('functionName'))]" - }, "eventGridTopic": { "name": "[format(variables('metadata').longName, 'evtgrd', '-topic')]", "resourceId": "[resourceId('Microsoft.EventGrid/topics', format(variables('metadata').longName, 'evtgrd', '-topic'))]" @@ -109,9 +101,6 @@ } } }, - "functionAppKey": { - "value": "[listKeys(variables('functionApp').functionResourceId, '2020-06-01').default]" - }, "eventGridTopicEndpoint": { "value": "[reference(variables('eventGridTopic').resourceId, '2020-06-01', 'Full').properties.endpoint]" }, @@ -127,14 +116,6 @@ "type": "object", "defaultValue": {} }, - "functionAppName": { - "type": "string", - "defaultValue": "[variables('functionApp').name]" - }, - "functionAppKey": { - "type": "string", - "defaultValue": "" - }, "acceptedYouTubeSource": { "type": "string", "defaultValue": "[variables('youtube').source]" @@ -191,10 +172,33 @@ "type": "string" }, "data": { - "type": "string" - }, - "traceparent": { - "type": "string" + "type": "object", + "properties": { + "channelId": { + "type": "string" + }, + "videoId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "link": { + "type": "string" + }, + "thumbnailLink": { + "type": "string" + }, + "datePublished": { + "type": "string" + }, + "dateUpdated": { + "type": "string" + } + } } } } @@ -202,7 +206,7 @@ } }, "actions": { - "Proceed_Only_If_Published": { + "Proceed_Only_If_Accepted_Source": { "type": "If", "runAfter": {}, "expression": { @@ -221,23 +225,10 @@ } ] }, - "actions": { - "Fetch_YouTube_Video_Details": { - "type": "Http", - "runAfter": {}, - "inputs": { - "method": "POST", - "uri": "https://@{parameters('functionAppName')}.azurewebsites.net/api/fetch", - "headers": { - "x-functions-key": "@parameters('functionAppKey')" - }, - "body": "@triggerBody()" - } - } - }, + "actions": {}, "else": { "actions": { - "Cancel_Processing_Event": { + "Cancel_Processing_Tweet": { "type": "Terminate", "runAfter": {}, "inputs": { @@ -250,20 +241,20 @@ "Split_Title": { "type": "Compose", "runAfter": { - "Proceed_Only_If_Published": [ + "Proceed_Only_If_Accepted_Source": [ "Succeeded" ] }, - "inputs": "@split(body('Fetch_YouTube_Video_Details')?['title'], '|')" + "inputs": "@split(triggerBody()?['data']?['title'], '|')" }, "Split_Description": { "type": "Compose", "runAfter": { - "Proceed_Only_If_Published": [ + "Proceed_Only_If_Accepted_Source": [ "Succeeded" ] }, - "inputs": "@split(body('Fetch_YouTube_Video_Details')?['description'], '---')" + "inputs": "@split(triggerBody()?['data']?['description'], '---')" }, "Process_Only_If_Title_Met": { "type": "If", @@ -289,7 +280,7 @@ "Build_Tweet_Post": { "type": "Compose", "runAfter": {}, - "inputs": "@{trim(first(outputs('Split_Title')))}\n\n@{trim(first(outputs('Split_Description')))}\n\n@{body('Fetch_YouTube_Video_Details')?['link']}" + "inputs": "@{trim(first(outputs('Split_Title')))}\n\n@{trim(first(outputs('Split_Description')))}\n\n@{triggerBody()?['data']?['link']}" } }, "else": { From fd7b5ee6364f7a7dbf27774930545f80456b76e9 Mon Sep 17 00:00:00 2001 From: Justin Yoo Date: Sat, 16 Jan 2021 14:55:21 +0900 Subject: [PATCH 2/3] Add LogicApp for LinkedIn (#8) --- .github/workflows/dev.yaml | 34 ++ .github/workflows/feature.yaml | 34 ++ .github/workflows/release.yaml | 68 ++++ ...gappdeploy.eventgridhandler-linkedin.bicep | 278 ++++++++++++++++ ...ogappdeploy.eventgridhandler-linkedin.json | 301 ++++++++++++++++++ ....eventgridhandler-linkedin.parameters.json | 18 ++ 6 files changed, 733 insertions(+) create mode 100644 resources/logappdeploy.eventgridhandler-linkedin.bicep create mode 100644 resources/logappdeploy.eventgridhandler-linkedin.json create mode 100644 resources/logappdeploy.eventgridhandler-linkedin.parameters.json diff --git a/.github/workflows/dev.yaml b/.github/workflows/dev.yaml index 3a5c424..effc16e 100644 --- a/.github/workflows/dev.yaml +++ b/.github/workflows/dev.yaml @@ -182,6 +182,16 @@ jobs: template: 'resources/logappdeploy.eventgridhandler-relay.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubePublishedEventType=${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} youTubeConvertedEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} + - name: Deploy LogicApp as EventGrid subscription handler for LinkedIn + id: linkedin + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-linkedin.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} linkedInUsername=${{ secrets.LINKEDIN_USERNAME }} + - name: Deploy LogicApp as EventGrid subscription handler for Facebook id: facebook uses: Azure/arm-deploy@v1 @@ -248,6 +258,30 @@ jobs: --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} \ --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for LinkedIn + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-linkedin-${{ secrets.LINKEDIN_USERNAME }} \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.linkedin.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for Facebook uses: azure/CLI@v1 with: diff --git a/.github/workflows/feature.yaml b/.github/workflows/feature.yaml index 6439233..38c6613 100644 --- a/.github/workflows/feature.yaml +++ b/.github/workflows/feature.yaml @@ -183,6 +183,16 @@ jobs: template: 'resources/logappdeploy.eventgridhandler-relay.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubePublishedEventType=${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} youTubeConvertedEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} + - name: Deploy LogicApp as EventGrid subscription handler for LinkedIn + id: linkedin + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-linkedin.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} linkedInUsername=${{ secrets.LINKEDIN_USERNAME }} + - name: Deploy LogicApp as EventGrid subscription handler for Facebook id: facebook uses: Azure/arm-deploy@v1 @@ -249,6 +259,30 @@ jobs: --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} \ --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for LinkedIn + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-linkedin-${{ secrets.LINKEDIN_USERNAME }} \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.linkedin.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for Facebook uses: azure/CLI@v1 with: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 896b3e6..87ba900 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -236,6 +236,16 @@ jobs: template: 'resources/logappdeploy.eventgridhandler-relay.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubePublishedEventType=${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} youTubeConvertedEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} + - name: Deploy LogicApp as EventGrid subscription handler for LinkedIn + id: linkedin + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_DEV }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_DEV }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-linkedin.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_DEV }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_DEV }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} linkedInUsername=${{ secrets.LINKEDIN_USERNAME }} + - name: Deploy LogicApp as EventGrid subscription handler for Facebook id: facebook uses: Azure/arm-deploy@v1 @@ -302,6 +312,30 @@ jobs: --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} \ --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for LinkedIn + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-linkedin-${{ secrets.LINKEDIN_USERNAME }} \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_DEV }} \ + -n ${{ steps.linkedin.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for Facebook uses: azure/CLI@v1 with: @@ -497,6 +531,16 @@ jobs: template: 'resources/logappdeploy.eventgridhandler-relay.json' parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_PROD }} youTubePublishedEventType=${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} youTubeConvertedEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} + - name: Deploy LogicApp as EventGrid subscription handler for LinkedIn + id: linkedin + uses: Azure/arm-deploy@v1 + with: + subscriptionId: ${{ secrets.SUBSCRIPTION_ID_PROD }} + resourceGroupName: ${{ secrets.RESOURCE_GROUP_NAME_PROD }} + deploymentName: 'ytwebsub' + template: 'resources/logappdeploy.eventgridhandler-linkedin.json' + parameters: name=${{ secrets.RESOURCE_NAME }} env=${{ secrets.RESOURCE_ENVIRONMENT_PROD }} locationCode=${{ secrets.RESOURCE_LOCATION_CODE }} youTubeChannelId=${{ secrets.YOUTUBE_CHANNEL_ID_PROD }} youTubeEventType=${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} youTubeTitleSegment=${{ secrets.YOUTUBE_CONVERTED_TITLE_SEGMENT }} linkedInUsername=${{ secrets.LINKEDIN_USERNAME }} + - name: Deploy LogicApp as EventGrid subscription handler for Facebook id: facebook uses: Azure/arm-deploy@v1 @@ -563,6 +607,30 @@ jobs: --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }} \ --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_PUBLISHED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for LinkedIn + uses: azure/CLI@v1 + with: + inlineScript: | + az extension add -n eventgrid + az extension add -n logic + sub=$(az eventgrid event-subscription create \ + -n ${{ steps.eventgrid.outputs.name }}-sub-linkedin-${{ secrets.LINKEDIN_USERNAME }} \ + --source-resource-id $(az eventgrid topic show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_PROD }} \ + -n ${{ steps.eventgrid.outputs.name }}-topic \ + --query "id" -o tsv) \ + --event-delivery-schema cloudeventschemav1_0 \ + --endpoint-type webhook \ + --endpoint $(az rest \ + -m POST \ + -u "https://management.azure.com$(az logic workflow show \ + -g ${{ secrets.RESOURCE_GROUP_NAME_PROD }} \ + -n ${{ steps.linkedin.outputs.logicAppName }} \ + --query "id" -o tsv)/triggers/manual/listCallbackUrl?api-version=2016-06-01" \ + --query "value" -o tsv) \ + --advanced-filter type StringBeginsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }} \ + --advanced-filter type StringEndsWith ${{ secrets.YOUTUBE_CONVERTED_EVENT_TYPE }}) + - name: Provision EventGrid subscription for Facebook uses: azure/CLI@v1 with: diff --git a/resources/logappdeploy.eventgridhandler-linkedin.bicep b/resources/logappdeploy.eventgridhandler-linkedin.bicep new file mode 100644 index 0000000..f9fba4f --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-linkedin.bicep @@ -0,0 +1,278 @@ +// Resource name +param name string + +// Provisioning environment +param env string { + allowed: [ + 'dev' + 'test' + 'prod' + ] + default: 'dev' +} + +// Resource location +param location string = resourceGroup().location + +// Resource location code +param locationCode string = 'krc' + +// YouTube +param youTubeChannelId string +param youTubeEventType string = 'com.youtube.video.converted' +param youTubeTitleSegment string + +// LinkedIn +param linkedInUsername string + +var metadata = { + longName: '{0}-${name}-${env}-${locationCode}{1}' + shortName: '{0}${name}${env}${locationCode}' +} + +var linkedInConnector = { + id: '${subscription().id}/providers/Microsoft.Web/locations/${location}/managedApis/linkedinv2' + connectionId: '${resourceGroup().id}/providers/Microsoft.Web/connections/${format(format(metadata.longName, 'apicon', '-linkedin-{0}'), linkedInUsername)}' + connectionName: format(format(metadata.longName, 'apicon', '-linkedin-{0}'), linkedInUsername) + location: location +} + +resource apiconLinkedIn 'Microsoft.Web/connections@2016-06-01' = { + name: linkedInConnector.connectionName + location: linkedInConnector.location + kind: 'V1' + properties: { + displayName: linkedInConnector.connectionName + api: { + id: linkedInConnector.id + } + } +} + +var logicApp = { + name: format(format(metadata.longName, 'logapp', '-eventgrid-sub-handler-linkedin-{0}'), linkedInUsername) + location: location +} + +var youtube = { + source: 'https://www.youtube.com/xml/feeds/videos.xml?channel_id=${youTubeChannelId}' + type: youTubeEventType + titleSegment: youTubeTitleSegment +} + +resource logapp 'Microsoft.Logic/workflows@2019-05-01' = { + name: logicApp.name + location: logicApp.location + properties: { + state: 'Enabled' + parameters: { + '$connections': { + value: { + linkedin: { + id: linkedInConnector.id + connectionId: linkedInConnector.connectionId + connectionName: apiconLinkedIn.name + } + } + } + } + definition: { + '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#' + contentVersion: '1.0.0.0' + parameters: { + '$connections': { + type: 'object' + defaultValue: {} + } + acceptedYouTubeSource: { + type: 'string' + defaultValue: youtube.source + } + acceptedYouTubeType: { + type: 'string' + defaultValue: youtube.type + } + acceptedYouTubeTitleSegment: { + type: 'string' + defaultValue: youtube.titleSegment + } + } + triggers: { + manual: { + type: 'Request' + kind: 'Http' + inputs: { + schema: { + type: 'object' + properties: { + id: { + type: 'string' + } + specversion: { + type: 'string' + } + source: { + type: 'string' + } + type: { + type: 'string' + } + time: { + type: 'string' + } + datacontenttype: { + type: 'string' + } + data: { + type: 'object' + properties: { + channelId: { + type: 'string' + } + videoId: { + type: 'string' + } + title: { + type: 'string' + } + description: { + type: 'string' + } + link: { + type: 'string' + } + thumbnailLink: { + type: 'string' + } + datePublished: { + type: 'string' + } + dateUpdated: { + type: 'string' + } + } + } + } + } + } + } + } + actions: { + Proceed_Only_If_Accepted_Source: { + type: 'If' + runAfter: {} + expression: { + and: [ + { + equals: [ + '@triggerBody()?[\'source\']' + '@parameters(\'acceptedYouTubeSource\')' + ] + } + { + equals: [ + '@triggerBody()?[\'type\']' + '@parameters(\'acceptedYouTubeType\')' + ] + } + ] + } + actions: {} + else: { + actions: { + Cancel_Processing_Post: { + type: 'Terminate' + runAfter: {} + inputs: { + runStatus: 'Cancelled' + } + } + } + } + } + Split_Title: { + type: 'Compose' + runAfter: { + Proceed_Only_If_Accepted_Source: [ + 'Succeeded' + ] + } + inputs: '@split(triggerBody()?[\'data\']?[\'title\'], \'|\')' + } + Process_Only_If_Title_Met: { + type: 'If' + runAfter: { + Split_Title: [ + 'Succeeded' + ] + } + expression: { + and: [ + { + equals: [ + '@trim(last(outputs(\'Split_Title\')))' + '@parameters(\'acceptedYouTubeTitleSegment\')' + ] + } + ] + } + actions: { + Build_LinkedIn_Post: { + type: 'Compose' + runAfter: {} + inputs: { + title: '@{trim(first(outputs(\'Split_Title\')))} | @{trim(first(skip(outputs(\'Split_Title\'), 1)))}' + body: '@triggerBody()?[\'data\']?[\'description\']' + link: '@triggerBody()?[\'data\']?[\'link\']' + } + } + } + else: { + actions: { + Cancel_Posting_LinkedIn: { + type: 'Terminate' + runAfter: {} + inputs: { + runStatus: 'Cancelled' + } + } + } + } + } + Post_LinkedIn: { + type: 'ApiConnection' + runAfter: { + Process_Only_If_Title_Met: [ + 'Succeeded' + ] + } + inputs: { + method: 'POST' + host: { + connection: { + name: '@parameters(\'$connections\')[\'linkedin\'][\'connectionId\']' + } + } + path: '/v2/people/shares' + body: { + distribution: { + linkedInDistributionTarget: { + visibleToGuest: true + } + } + text: { + text: '@{outputs(\'Build_LinkedIn_Post\')?[\'title\']}\n\n@{outputs(\'Build_LinkedIn_Post\')?[\'body\']}' + } + content: { + 'content-url': '@outputs(\'Build_LinkedIn_Post\')?[\'link\']' + } + } + } + } + } + outputs: {} + } + } +} + +output logicAppName string = logapp.name diff --git a/resources/logappdeploy.eventgridhandler-linkedin.json b/resources/logappdeploy.eventgridhandler-linkedin.json new file mode 100644 index 0000000..67bd871 --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-linkedin.json @@ -0,0 +1,301 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "type": "string" + }, + "env": { + "type": "string", + "defaultValue": "dev", + "allowedValues": [ + "dev", + "test", + "prod" + ] + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]" + }, + "locationCode": { + "type": "string", + "defaultValue": "krc" + }, + "youTubeChannelId": { + "type": "string" + }, + "youTubeEventType": { + "type": "string", + "defaultValue": "com.youtube.video.converted" + }, + "youTubeTitleSegment": { + "type": "string" + }, + "linkedInUsername": { + "type": "string" + } + }, + "functions": [], + "variables": { + "metadata": { + "longName": "[format('{{0}}-{0}-{1}-{2}{{1}}', parameters('name'), parameters('env'), parameters('locationCode'))]", + "shortName": "[format('{{0}}{0}{1}{2}', parameters('name'), parameters('env'), parameters('locationCode'))]" + }, + "linkedInConnector": { + "id": "[format('{0}/providers/Microsoft.Web/locations/{1}/managedApis/linkedinv2', subscription().id, parameters('location'))]", + "connectionId": "[format('{0}/providers/Microsoft.Web/connections/{1}', resourceGroup().id, format(format(variables('metadata').longName, 'apicon', '-linkedin-{0}'), parameters('linkedInUsername')))]", + "connectionName": "[format(format(variables('metadata').longName, 'apicon', '-linkedin-{0}'), parameters('linkedInUsername'))]", + "location": "[parameters('location')]" + }, + "logicApp": { + "name": "[format(format(variables('metadata').longName, 'logapp', '-eventgrid-sub-handler-linkedin-{0}'), parameters('linkedInUsername'))]", + "location": "[parameters('location')]" + }, + "youtube": { + "source": "[format('https://www.youtube.com/xml/feeds/videos.xml?channel_id={0}', parameters('youTubeChannelId'))]", + "type": "[parameters('youTubeEventType')]", + "titleSegment": "[parameters('youTubeTitleSegment')]" + } + }, + "resources": [ + { + "type": "Microsoft.Web/connections", + "apiVersion": "2016-06-01", + "name": "[variables('linkedInConnector').connectionName]", + "location": "[variables('linkedInConnector').location]", + "kind": "V1", + "properties": { + "displayName": "[variables('linkedInConnector').connectionName]", + "api": { + "id": "[variables('linkedInConnector').id]" + } + } + }, + { + "type": "Microsoft.Logic/workflows", + "apiVersion": "2019-05-01", + "name": "[variables('logicApp').name]", + "location": "[variables('logicApp').location]", + "properties": { + "state": "Enabled", + "parameters": { + "$connections": { + "value": { + "linkedin": { + "id": "[variables('linkedInConnector').id]", + "connectionId": "[variables('linkedInConnector').connectionId]", + "connectionName": "[variables('linkedInConnector').connectionName]" + } + } + } + }, + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "$connections": { + "type": "object", + "defaultValue": {} + }, + "acceptedYouTubeSource": { + "type": "string", + "defaultValue": "[variables('youtube').source]" + }, + "acceptedYouTubeType": { + "type": "string", + "defaultValue": "[variables('youtube').type]" + }, + "acceptedYouTubeTitleSegment": { + "type": "string", + "defaultValue": "[variables('youtube').titleSegment]" + } + }, + "triggers": { + "manual": { + "type": "Request", + "kind": "Http", + "inputs": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "specversion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "type": { + "type": "string" + }, + "time": { + "type": "string" + }, + "datacontenttype": { + "type": "string" + }, + "data": { + "type": "object", + "properties": { + "channelId": { + "type": "string" + }, + "videoId": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "link": { + "type": "string" + }, + "thumbnailLink": { + "type": "string" + }, + "datePublished": { + "type": "string" + }, + "dateUpdated": { + "type": "string" + } + } + } + } + } + } + } + }, + "actions": { + "Proceed_Only_If_Accepted_Source": { + "type": "If", + "runAfter": {}, + "expression": { + "and": [ + { + "equals": [ + "@triggerBody()?['source']", + "@parameters('acceptedYouTubeSource')" + ] + }, + { + "equals": [ + "@triggerBody()?['type']", + "@parameters('acceptedYouTubeType')" + ] + } + ] + }, + "actions": {}, + "else": { + "actions": { + "Cancel_Processing_Post": { + "type": "Terminate", + "runAfter": {}, + "inputs": { + "runStatus": "Cancelled" + } + } + } + } + }, + "Split_Title": { + "type": "Compose", + "runAfter": { + "Proceed_Only_If_Accepted_Source": [ + "Succeeded" + ] + }, + "inputs": "@split(triggerBody()?['data']?['title'], '|')" + }, + "Process_Only_If_Title_Met": { + "type": "If", + "runAfter": { + "Split_Title": [ + "Succeeded" + ] + }, + "expression": { + "and": [ + { + "equals": [ + "@trim(last(outputs('Split_Title')))", + "@parameters('acceptedYouTubeTitleSegment')" + ] + } + ] + }, + "actions": { + "Build_LinkedIn_Post": { + "type": "Compose", + "runAfter": {}, + "inputs": { + "title": "@{trim(first(outputs('Split_Title')))} | @{trim(first(skip(outputs('Split_Title'), 1)))}", + "body": "@triggerBody()?['data']?['description']", + "link": "@triggerBody()?['data']?['link']" + } + } + }, + "else": { + "actions": { + "Cancel_Posting_LinkedIn": { + "type": "Terminate", + "runAfter": {}, + "inputs": { + "runStatus": "Cancelled" + } + } + } + } + }, + "Post_LinkedIn": { + "type": "ApiConnection", + "runAfter": { + "Process_Only_If_Title_Met": [ + "Succeeded" + ] + }, + "inputs": { + "method": "POST", + "host": { + "connection": { + "name": "@parameters('$connections')['linkedin']['connectionId']" + } + }, + "path": "/v2/people/shares", + "body": { + "distribution": { + "linkedInDistributionTarget": { + "visibleToGuest": true + } + }, + "text": { + "text": "@{outputs('Build_LinkedIn_Post')?['title']}\n\n@{outputs('Build_LinkedIn_Post')?['body']}" + }, + "content": { + "content-url": "@outputs('Build_LinkedIn_Post')?['link']" + } + } + } + } + }, + "outputs": {} + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Web/connections', variables('linkedInConnector').connectionName)]" + ] + } + ], + "outputs": { + "logicAppName": { + "type": "string", + "value": "[variables('logicApp').name]" + } + } +} \ No newline at end of file diff --git a/resources/logappdeploy.eventgridhandler-linkedin.parameters.json b/resources/logappdeploy.eventgridhandler-linkedin.parameters.json new file mode 100644 index 0000000..4a004a0 --- /dev/null +++ b/resources/logappdeploy.eventgridhandler-linkedin.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "" + }, + "youTubeChannelId": { + "value": "" + }, + "youTubeTitleSegment": { + "value": "" + }, + "linkedInUsername": { + "value": "" + } + } +} From b840fe4cc7f5ab37c0267d888e6216b7560bfc2a Mon Sep 17 00:00:00 2001 From: Justin Yoo Date: Sat, 16 Jan 2021 15:09:30 +0900 Subject: [PATCH 3/3] Add release notes for v1.0.0 --- release-notes/v0.1.0.md | 17 +++++++++++++++++ release-notes/v0.2.0.md | 12 ++++++++++++ release-notes/v1.0.0.md | 14 ++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 release-notes/v0.1.0.md create mode 100644 release-notes/v0.2.0.md create mode 100644 release-notes/v1.0.0.md diff --git a/release-notes/v0.1.0.md b/release-notes/v0.1.0.md new file mode 100644 index 0000000..50165fb --- /dev/null +++ b/release-notes/v0.1.0.md @@ -0,0 +1,17 @@ +# v0.1.0 – Release Notes # + +Initial Release + + +## Main Features ## + +* Azure Functions + * To handle YouTube WebSub subscriptions + * To handle YouTube feed update +* Azure Event Grid + * To convert YouTube WebSub event data into CloudEvents as a canonical format + * To publish CloudEvents data as a canonical form for other event handlers to process them +* Azure Logic Apps + * To schedule daily subscription to YouTube WebSub + * To handle CloudEvents data to amplify YouTUbe feed to other social media including Twitter + diff --git a/release-notes/v0.2.0.md b/release-notes/v0.2.0.md new file mode 100644 index 0000000..8169b82 --- /dev/null +++ b/release-notes/v0.2.0.md @@ -0,0 +1,12 @@ +# v0.2.0 – Release Notes # + +Refactored Logic Apps as event handlers + + +## Changes ## + +* Refactored Logic App as an event handler to become more flexible to handle social media other than Twitter + + +## Fixes ## + diff --git a/release-notes/v1.0.0.md b/release-notes/v1.0.0.md new file mode 100644 index 0000000..9920278 --- /dev/null +++ b/release-notes/v1.0.0.md @@ -0,0 +1,14 @@ +# v0.1.0 – Release Notes # + +Refactored Logic Apps event handlers to be independent from each other + + +## Changes ## + +* Extracted the Twitter amplifier from the CloudEvents data handler +* Added Facebook amplifier +* Added LinkedIn amplifier + + +## Fixes ## +