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.
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.