Trigger an Azure Function ? with Power Automate ??

Trigger an Azure Function ? with Power Automate ??

This is a simple use case created when was learning about Azure Functions

??Note: I am not a code-first developer. I know some basic Power Fx expressions and can write simple prompts to OpenAI and copy and paste.

Case description

Send a notification to Microsoft Teams chat only if a followed YT channel uploads a new video which contains a specific term. e.g: "Demo".

Prerequisites

  1. Azure Subscription (to deploy your Azure Functions)
  2. Power Apps Developer Plan (or per-user/per-flow plan)
  3. Google API key (call YouTube Data API v3)
  4. GitHub account (for CI/CD optional) and VS Code to build, test and deploy.
  5. YouTube user profile and followed channels

I have found a youtube-transcript-api · PyPI that does exactly what I was looking for. I also realized that this code uses an undocumented part of the YouTube API, which is called by the YouTube web-client. For dev/test purpose it was good enough for me.

I knew that I want to write a simple script that will use this code and return me some values to Power Automate in JSON. Learn that Azure Function HTTP trigger returns HTML so I had to ask for a JSON output.

I wanted to go fast and fail quickly so I followed the steps here: Create a Python function using Visual Studio Code - Azure Functions | Microsoft Learn

It was my first hands on experience with Phyton script in Azure Functions so I asked ChatGPT for help. Took pretty fast to get a working code.

That was the first working one, not judging if f-strings should be used it is a good start for a few minutes of prompt writing exercise:

import logging
import json
import azure.functions as func
from youtube_transcript_api import YouTubeTranscriptApi as yta
from youtube_transcript_api._errors import TranscriptsDisabled
import re

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    video_id = req.params.get('id')
    query = req.params.get('q')
    
    if not video_id:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            video_id = req_body.get('id')

    if video_id:
        try:
            transcript = yta.get_transcript(video_id)
        except TranscriptsDisabled:
            return func.HttpResponse(
                 "Transcripts are disabled for the specified video ID.",
                 status_code=404
            )
        except:
            return func.HttpResponse(
                 "No transcript available for the specified video ID.",
                 status_code=404
            )

        transcript_text =''
        for value in transcript:
            for key, val in value.items():
                if key == 'text':
                    transcript_text += val + ' '

        prefix = "https://www.youtube.com/watch?v=" + video_id + "&t="
        filtered_list = []

        for obj in transcript:
            if query in obj['text']:
                filtered_list.append(obj)

        start_values = []
        for obj in filtered_list:
            start_values.append(round(float(obj['start'])))
        start_values_with_prefix = [prefix + str(start_val) + 's' for start_val in start_values]

        transcript_lines = transcript_text.splitlines()
        final_transcript = ' '.join(transcript_lines)
        lowercased_transcript = final_transcript.lower()

        jsdata = {"VideoID": video_id, "Words": len(re.findall(r'\w+', lowercased_transcript)), "QueryCount": lowercased_transcript.count(query), "VideoUrls": start_values_with_prefix ,  "Transcript": final_transcript}

        return func.HttpResponse(json.dumps(jsdata), mimetype="application/json", status_code=200)
    else:
        return func.HttpResponse(
             "Please provide a valid video ID in the query string or in the request body.",
             status_code=400
        )        

I wrote few more prompts just for different versions, copied that code, tested locally and deployed to Azure.

A function-specific API key is required. This is the default value when a level isn't specifically set, however when you initialize a Function in VS Code you can select Anonymous authorization level as well.

No alt text provided for this image


Additionally I set App Service authentication to Enabled and created an App registration so my Power Automate HTTP action can be called only from Power Automate, otherwise the function will reply with 401. Configure Azure AD authentication - Azure App Service | Microsoft Learn

For testing I always use the Manually trigger a flow trigger, after testing I just change the trigger and replace the parameters from the trigger: When a video is uploaded by a channel YouTube - Connectors | Microsoft Learn

I request the VideoID as id and a keyword query as q. The VideoID will come directly from channel trigger. The query keyword will depend of the specificity of that channel. For that I used a Compose action which is static variable.

E.g. If John Savill will upload a new video and mention "Azure" flow will send a notification how many times John used that phrase in his video. Another flow will trigger if Reza Dorrani, Shane Young, Scott Durow, Damien Bird, April Dunnam or Lisa Crosbie will mention "PowerApps", "Flow", "SharePoint" or "Demo".

GetVideoDetails is an HTTP action with a Get method to:

No alt text provided for this image


https://youtube.googleapis.com/youtube/v3/videos?part=snippet%2CcontentDetails%2Cstatistics&id=<VideoID goes here>&q=<Keyword query goes here>&key=<API Key Goes here>        

It returns a lot of details about the video, e.g. "channelId", "title", "thumbnails", "channelTitle", "duration", "caption".

Regarding "caption" parameter I thought it will be enough if it "caption": "false", then I can skip calling my HTTP action to Azure Function. But it is false when there is no manually uploaded caption. It is still false if it auto-generated.

So I had to go and return an 404 error from my HTTP function if there not even a single auto-generated transcript.

This exception is handled by Power Automate: Configure run after option

No alt text provided for this image
Body message from HTTP action when no transcript is available to parse


No alt text provided for this image
Run after configuration for failed transcript queries

Here is my test flow when transcript is generated. Azure KeyVault is optional, I could hardcode the Keys.

No alt text provided for this image
No alt text provided for this image
Sample example of a post in Teams

It was a fun automation to build while was learning a lot about Azure Functions. Finally I can save the results of mentioned keywords on a SharePoint or DataVerse table, pass the links with time stamps of mentioned keywords. I have hundreds of connectors to choose from. I could also create as many Azure Functions as Channel Id I want to follow and add additional outputs.

Here I can get a notification if Damien Bird mentions "Demo" in his video. Follow him here: DamoBird365 - YouTube

No alt text provided for this image
Final script flow triggered by Youtube upload to channel

Thanks for scrolling this far. If you liked that use case, click:????

要查看或添加评论,请登录

Krzysztof Borkowski的更多文章

  • Uploading Files to Canvas Power Apps from Different Folders with Non-Unique Names

    Uploading Files to Canvas Power Apps from Different Folders with Non-Unique Names

    TLDR: In this article, I will try to explain how do I upload files as media to Canvas Power Apps when these files are…

  • Centering (flex) containers in Power Apps

    Centering (flex) containers in Power Apps

    Hi everyone, Happy April's 1st. I also fooled myself with trying to vertically center align a container.

    4 条评论
  • SetFocus() to the rescue ??♂?

    SetFocus() to the rescue ??♂?

    How I used SetFocus() to improve the user experience of my Power Apps project Hi ?? everyone, I hope you are having or…

    13 条评论
  • FEM Job listing with filtering got PowerApp'ed

    FEM Job listing with filtering got PowerApp'ed

    This Sunday low-code project was challenging for different reasons. Here it is Frontend Mentor | Job listings with…

  • This weekend was about WeatherAPI

    This weekend was about WeatherAPI

    Kristine just dropped a Free Power Apps design masterclass on Youtube last Friday evening. So I decided to let's build…

    2 条评论
  • Where in the world FEM challenge got Power App'ed

    Where in the world FEM challenge got Power App'ed

    This weekend challenge was pretty massive and indeed a bit more time consuming than I previously estimated for it…

    5 条评论
  • Time tracking dashboard Power App'ed

    Time tracking dashboard Power App'ed

    Saturday afternoon challenged myself to build this Frontend Mentor | Time tracking dashboard coding challenge with…

  • Friday evening fun with Power Apps basic animation capabilities

    Friday evening fun with Power Apps basic animation capabilities

    This Friday evening I took this Frontend Mentor | Fylo data storage component coding challenge, low-coded and added…

  • FEM Four Cards Challenge Power App'ed

    FEM Four Cards Challenge Power App'ed

    Frontend Mentor | Four card feature section coding challenge As a Saturday relaxation I was trying to wrap my head…

  • FAQ accordion card in PowerApps

    FAQ accordion card in PowerApps

    Quick tutorial how to create a simple accordion card with flexible height gallery in Power Apps. Layout, text, colors…

社区洞察

其他会员也浏览了