Using Azure Functions and Microsoft Flow to Send Notifications for NuGet Package Downloads

One of the NuGet packages I maintain is approaching 100,000 downloads. I thought it would be nice to get a notification on my phone when the number of downloads hit 100,000.

To implement this I installed the Flow app on my iPhone, wrote an Azure Function that executes on a timer, and calls into Flow.

Creating a Flow

The first step is to create a new Microsoft Flow that is triggered by a HTTP Post being sent to it.

The flow uses a Request trigger and a URL is auto generated by which the flow can be initiated.

The second step is the Notification action that results in a notification being raised in the Flow app for iOS.

Azure Function calling Microsoft Flow

Creating an Azure Function with Timer Trigger

Now that there is a URL to POST to to create notifications, a timer-triggered Azure Function can be created.

This function screen scrapes the NuGet page (I’m sure there’s a more elegant/less brittle way of doing this) and grabbing the HTML element containing the total downloads. If the total number of downloads >= 100,000 , then the flow URL will be called with a message in the body. The timer schedule runs once per day. I’ll have to manually disable the function once > 100,000 downloads are met.

The function code:

using System.Net;
using HtmlAgilityPack;
using System.Globalization;
using System.Text;

public static async Task Run(TimerInfo myTimer, TraceWriter log)
{       
    try
    {
        string html = new WebClient().DownloadString("https://www.nuget.org/packages/FeatureToggle");

        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(html);     
                            
        HtmlNode downloadsNode = doc.DocumentNode
                                    .Descendants("p")
                                    .First(x => x.Attributes.Contains("class") &&  
                                                x.Attributes["class"].Value.Contains("stat-number"));                        

        int totalDownloads = int.Parse(downloadsNode.InnerText, NumberStyles.AllowThousands);
        
        bool thresholdMetOrExceeded = totalDownloads >= 1; // 1 for test purposes, should be 100000

        if (thresholdMetOrExceeded)
        {
            var message = $"FeatureToggle now has {totalDownloads} downloads";

            log.Info(message);

            await SendToFlow(message);            
        }        
    }
    catch (Exception ex)
    {
        log.Info(ex.ToString());
        await SendToFlow($"Error: {ex}");
    }
}

public static async Task SendToFlow(string message)
{
    const string flowUrl = "https://prod-16.australiasoutheast.logic.azure.com:443/workflows/[redacted]/triggers/manual/paths/invoke?api-version=2015-08-01-preview&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=[redacted]";

    using (var client = new HttpClient())
    {
        var content = new StringContent(message, Encoding.UTF8, "text/plain");
        
        await client.PostAsync(flowUrl, content);
    }
}

Manually running the function (with test threshold of 1 download) results in the following notification on from the Flow iOS app:

This demonstrates the nice thing about Azure Functions, namely that it’s easy to throw something together to solve a problem.

iOS Flow App Notification

To jump-start your Azure Functions knowledge check out my Azure Function Triggers Quick Start Pluralsight course.

Comments (2) -

  • Andrew Herrick

    3/3/2017 1:14:54 AM | Reply

    Awesome! Simple & clean implementation.

  • Michael Washington

    3/3/2017 8:46:25 PM | Reply

    Nice clean, learned a lot from this.

Add comment

Loading