Scripts by lannonbr

View GitHub Trending Repos

This was a fun one to build. So GitHub does not have an API endpoint for their trending page. So to work around this I used playwright to scrape the pages for various languages. Then I'd create a tab for a variety of language. What I ran into though was given the data likely doesn't change too often, going and scraping on every tab change was slow. To resolve this, I wrote a second script that runs on an hourly cron and then saves the data to a lowdb database with the preloaded db function. This now makes the main script run instantly as the entries are cached on my system.

Screen Shot 2021-05-02 at 10 25 49 AM

Scripts

Main Script:

// Menu: GitHub Trending
// Description: Show today's Trending GitHub Repos for various languages
const trendingDB = db("github-trending");
const langs = ["rust", "javascript", "typescript", "go", "python", "ruby"];
for (const lang of langs) {
onTab(lang, async () => {
const repo = await arg("Select a repo to open it", trendingDB.get(lang));
exec(`open ${repo}`);
});
}

Background puller script:

// Description: Pulls down trending repos from github and save to database
// Schedule: 0 * * * *
// Exclude: true
/** @type typeof import('playwright') */
const playwright = await npm("playwright");
let dbDefaults = {};
const langs = ["rust", "javascript", "typescript", "go", "python", "ruby"];
for (const lang of langs) {
dbDefaults[lang] = [];
}
const trendingDB = db("github-trending", dbDefaults);
const browser = await playwright.chromium.launch();
for (const lang of langs) {
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(`https://github.com/trending/${lang}`);
const repos = await page.evaluate(() => {
const repos = document.querySelectorAll(".Box-row");
const results = [];
for (let repo of repos) {
const repoName = repo.querySelector("h1 a").getAttribute("href").slice(1);
let description = repo.querySelector("p")?.textContent.trim();
const starCount = repo
.querySelector("div span.d-inline-block.float-sm-right")
?.textContent.trim();
if (!description) {
description = starCount;
} else {
description = `${starCount} | ${description}`;
}
results.push({
name: repoName,
value: `https://github.com/${repoName}`,
description,
});
}
return results;
});
trendingDB.set(lang, repos).write();
}
await browser.close();
Discuss Post

View supported versions of node

The NodeJS core team provides a JSON file in nodejs/release: https://github.com/nodejs/Release/blob/main/schedule.json which details all of the major versions of Node, their initial release date, EOL, maintenance mode date, as well as LTS date.

I wanted to do a test run with this document of parsing it and getting some initial results. As Node 10 went EOL at the end of today, I thought it could be neat to use this to track node versions in projects you work on and if you're using a node version that is no longer supported, it could inform you of such and tell you to upgrade to the latest LTS. As a test run, I pull down the JSON file and parse it out to list the versions of Node which are still being supported.

Screen Shot 2021-04-30 at 10 33 07 PM

(Also as a fun aside, I am tending more and more of using arg() to display a list of content even if I don't then select one & go further with it. I enjoy the way it presents the data & it is filterable by default. I know of the img and html fields are around but I have yet to find neat ways of using them.)

Code:

// Menu: Available Node versions
// Description: View all supported versions of NodeJS
// Author: Benjamin Lannon
// Twitter: @lannonbr
let resp = await get(
"https://raw.githubusercontent.com/nodejs/Release/main/schedule.json"
);
const data = Object.entries(resp.data);
/** @type typeof import('dayjs') */
let dayjs = await npm("dayjs");
let opts = [];
for (let [version, info] of data) {
let isSupported =
dayjs(info.start).diff(dayjs(), "days") < 0 &&
dayjs(info.end).diff(dayjs(), "days") > 0;
if (isSupported) {
opts.push({
name: `Node ${version}`,
description: `Maintainence ends on ${dayjs(info.end).format(
"MMMM DD, YYYY"
)}`,
endDate: info.end,
});
}
}
opts = opts.sort((a, b) => {
return dayjs(a.endDate).unix() - dayjs(b.endDate).unix();
});
await arg("These versions of NodeJS are currently maintained", opts);
Discuss Post

View current week's tasks from Todoist

I use Todoist as my main todo app. This is a script I can use to view all of the tasks I want to get done in the next 7 days.

Screen Shot 2021-04-25 at 12 51 41 AM

Code

// Menu: Todoist Tasks
// Description: View this week's tasks from Todoist
// Author: Benjamin Lannon
// Twitter: @lannonbr
/** @type typeof import('todoist') */
const todoistPackage = await npm("todoist");
/** @type typeof import('dayjs') */
const dayjs = await npm("dayjs");
// API Token can be found here: https://todoist.com/prefs/integrations
const token = await env("TODOIST_TOKEN");
const client = todoistPackage.v8(token);
await client.sync();
let items = client.items.get();
items = items.filter((item) => {
let dueDate = dayjs(item.due.date);
return dueDate.diff(dayjs(), "day") <= 7;
});
await arg(
"View this week's tasks",
items.map((item) => {
return {
name: item.content,
description: `Due: ${item.due.date}`,
};
})
);
Discuss Post

Searching my Digital Garden

Based on An Alfred Workflow I've previously written, I wrote a script with the same functionality of search through the posts on my site, open a post in a chrome tab, and copy the link to the clipboard:

// Menu: Lannonbr.com Garden
// Description: Search posts on lannonbr.com
// Author: Benjamin Lannon
// Twitter: @lannonbr
let resp = await get("https://lannonbr.com/posts.json");
let post = await arg("What post do you want to read", resp.data.items);
let { focusTab } = await kit("chrome");
focusTab(post);
copy(post);
Discuss Post

Open GitHub Discussion listing of repo

Did a quick remix on the chrome-tab script @johnlindquist made so I could quickly navigate to the discussions tab of any repo.

// Description: Open the Discussions pane of a GitHub repo
// Author: Benjamin Lannon
// Twitter: @lannonbr
let { focusTab } = await kit('chrome')
let repo = await arg('Enter repo (ex: johnlindquist/kit):')
focusTab(`https://github.com/${repo}/discussions`)
Discuss Post

View AWS Cost for the month

I wrote a script this morning that uses the aws-cli to check the cost of my AWS account for a particular time-range:

let start = await arg('Enter start date (YYYY-MM-DD)')
let end = await arg('Enter end date (YYYY-MM-DD)')
let {stdout} = exec(`aws ce get-cost-and-usage --time-period Start=${start},End=${end} --granularity MONTHLY --metrics "BlendedCost"`)
let data = JSON.parse(stdout)
let monthCost = data.ResultsByTime[0].Total.BlendedCost
let { say } = await kit('speech')
await say(`Your AWS bill is $${Number(monthCost.Amount).toFixed(2)}`)

I'm thinking in the future of expanding this so if I can get other time granularities (weekly, daily), or drill down based on costs of items based on a tag.

Discuss Post