Present Latest Weblog Posts In GitHub ReadMe Utilizing An Azure Perform
Introduction

GitHub secret repository
This opens countless alternatives for what you are able to do to your GitHub residence web page. For instance, I’m displaying the picture of the titles of my current 5 weblog posts on my residence web page routinely. I did it utilizing the Azure Perform which is able to return the picture, and all I needed to do on this repository was to make use of it. Total it was enjoyable.

Customized GitHub residence web page
Right here on this submit, we’ll see how we are able to develop an Azure Perform resolution that returns the above-mentioned picture.
Develop an Azure operate
The very first thing that you should do is to create a brand new Azure Perform. Go to your Azure portal, and seek for Azure Perform. The creation course of is similar as we’d create some other Azure useful resource.
When you create the Azure operate, you’re good to go and develop an Azure operate utility in Visual Studio. Right here, I’m utilizing Visual Studio 2019.

Create Azure operate utilizing Visual Studio
We’re going to create an HttpTrigger Azure operate, so be sure you choose that choice on the subsequent display. If you happen to want a primary introduction concerning the HttpTrigger Azure operate. I named my operate as GetLatestPosts, and be happy to present any identify you want. This Azure operate has the previous jobs to do.
- Get the most recent posts particulars from the feed of my weblog
- Create a picture with the feed knowledge
- Ship again the picture as a stream
Get the most recent posts particulars from the feed
You possibly can often get the feed knowledge by going to {yoursitelink}/feed. For instance, I can get my feed knowledge by going to https://sibeeshpassion.com/feed/. So in our operate, we’ll get this knowledge utilizing an XmlReader and Deserialize it utilizing SyndicationFeed. Please be famous that the Syndication namespace is a part of the System.ServiceModel and it is best to set up the Nuget bundle System.ServiceModel.Syndication. Beneath is the operate used to retrieve the most recent 5 weblog posts’ particulars.
- public static IEnumerable < SyndicationItem > GetLatestFeeds() {
- var reader = XmlReader.Create(Configuration.BlogLink);
- var feed = SyndicationFeed.Load(reader);
- reader.Shut();
- return feed.Gadgets.Take(5);
- }
Create a picture with titles
Now we want a operate to generate a picture and write the weblog posts title to that picture dynamically. To do that, we’re utilizing the Nuget bundle known as SixLabors.ImageSharp. Be happy to make use of any packages you want, the one factor that issues is that we want a picture with the weblog posts titles. The SixLabors.ImageSharp is certainly a tremendous library, I can suggest you to present it a strive. That is how your Nuget bundle put in window ought to look now:

Required Nuget packages
Now we are able to write the operate as proven beneath.
- personal static string WriteOnImage(IEnumerable < SyndicationItem > feedItems) {
- var titles = string.Be a part of(“, “, feedItems.Choose(s => s.Title.Textual content).ToList());
- utilizing
- var img = new Picture < Rgba32 > (Configuration.ImageWidth, Configuration.ImageHeight);
- var font = System Fonts.CreateFont(Configuration.Font, Configuration.FontSize);
- img.Mutate(ctx => ctx.ApplyScalingWaterMark(font, titles, Shade.Black, 5, true));
- return img.ToBase64String(PngFormat.Occasion);
- }
As you’ll be able to see that there’s a Configuration class, from the place we take all of the configurations. Let’ write that now. You may also use Surroundings variables right here, I could replace my repository within the coming days.
- namespace GitHub Funcs {
- public static class Configuration {
- public static string BlogLink {
- get;
- set;
- } = “https://sibeeshpassion.com/feed”;
- public static int ImageWidth {
- get;
- set;
- } = 850;
- public static int ImageHeight {
- get;
- set;
- } = 100;
- public static string ContentType {
- get;
- set;
- } = “picture/png”;
- public static string Font {
- get;
- set;
- } = “Arial”;
- public static int FontSize {
- get;
- set;
- } = 5;
- }
- }
The SixLabors.ImageSharp has an inbuilt extension operate known as ToBase64String, which is able to return the picture as base64 string. Did you discover that we’re utilizing one other extension technique right here, “ApplyScalingWaterMark”? Let’s create a category for our Extension strategies in order that it will likely be useful sooner or later.
- utilizing SixLabors.Fonts;
- utilizing SixLabors.ImageSharp;
- utilizing SixLabors.ImageSharp.Drawing.Processing;
- utilizing SixLabors.ImageSharp.Processing;
- utilizing System;
- namespace GitHub Funcs.ExtensionMethods {
- public static class ImageSharpExtensions {
- public static IImageProcessingContextApplyScalingWaterMark(thisIImageProcessingContextprocessingContext, Font font, string textual content, Shade colour, float padding, bool wordwrap) {
- if (wordwrap) {
- return processing Context.ApplyScalingWaterMarkWordWrap(font, textual content, colour, padding);
- } else {
- return processing Context.ApplyScalingWaterMarkSimple(font, textual content, colour, padding);
- }
- }
- personal static IImage Processing Context Apply Scaling WaterMarkSimple(thisIImageProcessingContextprocessingContext, Font font, string textual content, Shade colour, float padding) {
- Dimension imgSize = processingContext.GetCurrentSize();
- float goal Width = img Dimension.Width – (padding * 2);
- float goal Top = img Dimension.Top – (padding * 2);
- Font Rectangle dimension = Textual content Measurer.Measure(textual content, newRendererOptions(font));
- float scaling Issue = Math.Min(imgSize.Width / dimension.Width, imgSize.Top / dimension.Top);
- Fonts caled Font = new Font(font, scalingFactor * font.Dimension);
- var heart = new PointF(imgSize.Width / 2, imgSize.Top / 2);
- var textGraphicOptions = new TextGraphicsOptions() {
- Textual content Choices = {
- Horizontal Alignment = Horizontal Alignment.Middle,
- Vertical Alignment = Vertical Alignment.Middle
- }
- };
- return processing Context.DrawText(textGraphicOptions, textual content, scaledFont, colour, heart);
- }
- personal static IImageProcessing ContextApply ScalingWaterMark WordWrap(thisIImageProcessingContextprocessingContext, Font font, string textual content, Shade colour, float padding) {
- Dimension imgSize = processing Context.GetCurrentSize();
- floattar get Width = img Dimension.Width – (padding * 2);
- floattar get Top = imgSize.Top – (padding * 2);
- float goal Min Top = imgSize.Top – (padding * 3);
- var scaled Font = font;
- Font Rectangles = new FontRectangle(0, 0, float.MaxValue, float.MaxValue);
- float scale Issue = (scaledFont.Dimension / 2);
- int lure Depend = (int) scaledFont.Dimension * 2;
- if (lure Depend < 10) {
- lure Depend = 10;
- }
- bool is TooSmall = false;
- whereas ((s.Top > targetHeight || s.Top < targetMinHeight) && trapCount > 0) {
- if (s.Top > goal Top) {
- if (isTooSmall) {
- scale Issue = scale Issue / 2;
- }
- scaled Font = new Font(scaledFont, scaledFont.Dimension – scaleFactor);
- isTooSmall = false;
- }
- if (s.Top < targetMinHeight) {
- if (!isTooSmall) {
- scale Issue = scale Issue / 2;
- }
- scaled Font = new Font(scaledFont, scaledFont.Dimension + scaleFactor);
- isTooSmall = true;
- }
- trapCount–;
- s = TextMeasurer.Measure(textual content, newRendererOptions(scaledFont) {
- Wrapping Width = goal Width
- });
- }
- var heart = new PointF(padding, imgSize.Top / 2);
- var textGraphicOptions = new TextGraphicsOptions() {
- Textual content Choices = {
- Horizontal Alignment = Horizontal Alignment.Left,
- Vertical Alignment = Vertical Alignment.Middle,
- WrapText Width = goal Width
- }
- };
- return processing Context.DrawText(textGraphicOptions, textual content, scaledFont, colour, heart);
- }
- }
- }
Azure operate to return a stream
As all of the supporting strategies are prepared, let’s write our important operate. The final word job of this operate is to transform the bottom64 string to a stream and return the stream. It is so simple as that.
- [FunctionName(“GetLatestPosts”)]
- public static FileStreamResultRun([HttpTrigger(AuthorizationLevel.Function, “get”, Route = null)] HttpRequestrequest, ILoggerlog) {
- strive {
- varbase String = WriteOnImage(GetLatestFeeds());
- string convert = baseString.Exchange(“knowledge:picture/png;base64,”, String.Empty);
- var bytes = Convert.FromBase64String(convert);
- var outcome = new FileStreamResult(newMemoryStream(bytes), Configuration.ContentType);
- log.LogInformation(“Returning stream now!”);
- request.HttpContext.Response.Headers.Add(“Cache-Management”, “s-maxage=1, stale-while-revalidate”);
- return outcome;;
- } catch (System.Exceptionex) {
- log.LogError($ “One thing went improper: {ex}”);
- throwex;
- }
- }
As soon as your Azure operate is prepared, please keep in mind to publish the identical to Azure. To publish your Azure Perform app, good click on in your mission and click on Publish after which arrange your publish goal by selecting the prevailing Azure Perform App, keep in mind we’ve created one earlier?
Develop secret GitHub readme repository
Right here, I’m assuming that you just already created your secret repository. And if sure, you’ll be able to replace the “readme” content material as follows. Please keep in mind that that is only a pattern, you’ll be able to replace it as you want.
Hello there ?, be happy to take a look at my weblog and youtube channel!
Beneath are the titles of the most recent 5 posts from my weblog (That is an automatic message utilizing Azure Perform. Azure is Love!)
- ? I’m at the moment engaged on Azure IoT Hub, IoT Central, Raspberry Pi
- ? I’m at the moment studying numerous new IoT matters
- ? I’m seeking to collaborate on any MVP product in IoT
- ⚡ Enjoyable reality: Nicely, this readme file won’t be sufficient!
Increase!. We did it. Now go to your GitHub residence web page, and I’m certain that you’ll love your new stunning, detailed residence web page.
Replace
As GitHub has a really low timeout, typically the picture created was not displaying in my profile. Thus, I needed to change the mechanism. I modified my Azure operate to a time set off operate that runs each hour and the principle performance of this operate now could be to generate the picture and add to the Azure blob storage. Now I can straight get the blob picture URL within the Readme file. No extra timeout points. Following are the codes of the brand new Azure operate. You may also see this within the Dev department of the repository.
- utilizing GitHubFuncs.ExtensionMethods;
- utilizing Microsoft.AspNetCore.Mvc;
- utilizing Microsoft.Azure.WebJobs;
- utilizing Microsoft.Extensions.Logging;
- utilizing Microsoft.WindowsAzure.Storage;
- utilizing SixLabors.Fonts;
- utilizing SixLabors.ImageSharp;
- utilizing SixLabors.ImageSharp.Codecs.Png;
- utilizing SixLabors.ImageSharp.PixelFormats;
- utilizing SixLabors.ImageSharp.Processing;
- utilizing System;
- utilizing System.Collections.Generic;
- utilizing System.IO;
- utilizing System.Linq;
- utilizing System.Web.Mime;
- utilizing System.ServiceModel.Syndication;
- utilizing System.Threading.Duties;
- utilizing System.Xml;
- namespace GitHubFuncs {
- public class GetLatestPosts {
- personal static ILogger_logger;
- personal
- const string_fileName = “latestpost.png”;
- personal
- const string_blobContainerName = “github”;
- [FunctionName(“GetLatestPosts”)]
- public async TaskRun([TimerTrigger(“0 0 */1 * * *”)] TimerInfomyTimer, ILoggerlog) {
- strive {
- _logger = log;
- await UplaodImageToStorage();
- } catch (System.Exceptionex) {
- log.LogError($ “One thing went improper: {ex}”);
- throwex;
- }
- }
- personal static async Job < bool > UplaodImageToStorage() {
- strive {
- var base String = WriteOnImage(GetLatestFeeds());
- string convert = baseString.Exchange(“knowledge:picture/png;base64,”, String.Empty);
- var bytes = Convert.FromBase64String(convert);
- var stream = newMemoryStream(bytes);
- if (CloudStorageAccount.TryParse(Surroundings.GetEnvironmentVariable(“AzureWebJobsStorage”), outCloudStorageAccountcloudStorageAccount)) {
- var cloud BlobClient = cloud StorageAccount.CreateCloudBlobClient();
- var cloud BlobContainer = cloud BlobClient.GetContainerReference(_blobContainerName);
- var cloud BlockBlob = cloud BlobContainer.GetBlockBlobReference(_fileName);
- cloud BlockBlob.Properties.ContentType = “picture/png”;
- await cloud BlockBlob.UploadFromStreamAsync(stream);
- _logger.LogInformation(“Uploaded new picture”);
- } else {
- _logger.LogError(“Error in connection”);
- }
- } catch (Exceptionex) {
- _logger.LogError(ex.Message);
- }
- return false;
- }
- personal static string WriteOnImage(IEnumerable < SyndicationItem > feedItems) {
- var titles = string.Be a part of(“, “, feedItems.Choose(s => s.Title.Textual content).ToList());
- utilizing
- var img = new Picture < Rgba32 > (Configuration.ImageWidth, Configuration.ImageHeight);
- var font = SystemFonts.CreateFont(Configuration.Font, Configuration.FontSize);
- img.Mutate(ctx => ctx.ApplyScalingWaterMark(font, titles, Shade.Black, 5, true));
- return img.ToBase64String(PngFormat.Occasion);
- }
- public static IEnumerable < SyndicationItem > GetLatestFeeds() {
- var reader = XmlReader.Create(Configuration.BlogLink);
- var feed = SyndicationFeed.Load(reader);
- reader.Shut();
- return feed.Gadgets.Take(5);
- }
- }
- }
Supply Code
Please be happy to take a look at the repositories right here:
- https://github.com/SibeeshVenu/GitHubFuncs
- https://github.com/SibeeshVenu/sibeeshvenu
Your flip. What do you suppose?
Thanks so much for studying. Did I miss something that you could be suppose is required on this article? Did you discover this submit helpful? Please don’t forget to share your suggestions!