Generate tweets and images with Node

15 februari 2021

Last December the CLI for Microsoft 365 group brainstormed about some new ideas to drive adoption and to highlight some of the capabilities. One of the things that made sense to us was to engage a bit more on the socials. We wanted to not only highlight how well we are doing, but also share some of our commands. We decided we wanted to tweet a bit more often, so we set out to construct some tweets. The thing with the tweets is that we wanted to tweet about our commands. Most of that information is already in the CLI source code itself. We also wanted to add some visuals to get a bit more exposure. Meaning that for each tweet we had to come up with 160 characters of fun and create an image. We decided to see if we could automate some of this to speed up the process rather than one of us having to create a lot of images for each command. And as I wanted to challenge myself a bit, I wanted to do things in NodeJs instead of PowerShell. 

Node.js to generate some tweets

Generating a tweet requires a few things: 
  • The command names
  • The command description
  • A URL to more information - The message to tweet 

Most of that information we already store here. For each command we have a page with detailed information. These pages are generated based on our codebase.

Step one, to read all commands, is simply reading our mkdocs.yml file that contains a link to each command. A regex can be used to filter out all documents in a the cmd folder as that is where all documentation around the command lives. 

    let navigationContents = fs.readFileSync( (rootPath + "mkdocs.yml"), 'utf8'); 
    let navData = yaml.safeLoad(navigationContents);
    const re = /\s*cmd.*?(md)/g;
    let links = JSON.stringify(navData).match(re);

    links.forEach(link => {
        console.log("Generating tweet for" + link);

Given that we have links to each command file, you can use the same logic to read the actual file. With the contents of the file being markdown with a predefined structure, we can process those as well to extract the command URL, command name and get the command description. 

let fileContents = fs.readFileSync((rootPath + "docs/" + link), 'utf8');
fileContents = fileContents.split("\n");

let commandName = fileContents[0].replace('#', ");
let commandDescription = fileContents[2];
let commandUrl = docUrl + link.replace (".md", "");

The data can be saved to a CSV file to generate an overview of all commands with the details we are looking for. In our case we decided to randomize a set of tweets based as well. We put in seven different tweets and injected the content in those. Picked a random tweet and put in the CSV. That way we only had to curate the tweets and tweak them a bit. The tweets sometimes contain capitalizations, as the command description uses a capital, or sentences were a bit off. Samples like "Trying to removing a specified users" instead off "Trying to remove a specified users" can occur as there is no logic in the script to capture those. 

Generating images.

To generate images for tweets we picked jimp. We required the image to contain the command, something we already had. Setting up Jimp is straightforward. You need to include jimp, and then you can use it in your code. We decided on a function, included a default background image and used a text overlay with the command. By storing the file with the command name it can be easily found again. 

var Jimp = require('jimp');
async function textOverlay(textForImage, FileName) {
    console.log('Generating image' + textForImage)
    const font = await Jimp.loadFont(Jimp.FONT_SANS_128_WHITE);
    const image = await Jimp.read("C:/git/sbx/tweetgenerator/images/bg.png");

    await image.print(font, 10, 10, {
        text: textForImage,
        alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
        alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
}, 1024, 512);

    await image.writeAsync(fileName);

You can find the full sample as a appieschot - Gist.

PowerShell vs NodeJs.

Usually, I resort to PowerShell to generate CSV files and capture content. Yet the NodeJs scenario was not slower for me. I ended up spending a little bit more time to generate the images than I might have to in PowerShell, but I would blame that on the learning curve. 

We ended up with a CSV with sample tweets, and a bunch of images. We still go through each tweet manually to make sure the text is correct. It does not make sense to just blast tweets without some curation. To see the results check out CLI for Microsoft 365 on Twitter

Originally posted at: https://www.cloudappie.nl/marketingautomation-climicrosoft365/

Submit a comment