Generate tweets and images with Node

Generate tweets and images with Node header image

Last December the CLI for Microsoft 365 brainstormed some new ideas to drive adoption and to highlight some of the things we could do. One of the things that made sense of 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 tweet 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 the things 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.

NodeJs 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 on https://aka.ms/cli-m365. For each command we do 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 commands 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", "");

That 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 into 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 where a bit off. Samples Like Trying to removing a specified users instead 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 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 it the NodeJs scenario was not slower for me. I ended up spending a little bit more time to generate the image as I might have had to do 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 to 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 checkout CLI for Microsoft 365 on twitter

Loading comments…