To use this script, simply replace the USERNAME
, REPOSITORY
, GITHUB_STARS_REPO
and GITHUB_DOWNLOADS_REPO
placeholders with the appropriate values for the GitHub repository you want to fetch the star and release download count for. Then, copy the complete script into a new Scriptable App script and run it. The star and release download count for the specified repository will be displayed in a Scriptable widget.
// Constants for widget configuration
const WIDGET_TITLE = "GitHub";
const USERNAME = "hoppscotch"
const REPOSITORY = "hoppscotch"
const GITHUB_STARS_REPO = "hoppscotch/hoppscotch";
const GITHUB_DOWNLOADS_REPO = "hoppscotch/releases";
const CACHED_DATA_HOURS = 0.5;
const API_BASE_URL = "https://api.github.com/repos/";
// Function to create and configure the widget
async function createWidget() {
// Initialize the widget
const listWidget = new ListWidget();
// Set background gradient
const gradient = new LinearGradient();
gradient.colors = [new Color("#111"), new Color("#010101")];
gradient.locations = [0, 1];
listWidget.backgroundGradient = gradient;
// Widget heading and tagline
const widgetHeading = listWidget.addText(WIDGET_TITLE);
widgetHeading.font = Font.semiboldRoundedSystemFont(14);
widgetHeading.textColor = new Color("#999");
listWidget.addSpacer(18);
// User and repository text elements
const user = listWidget.addText(USERNAME);
user.font = Font.boldRoundedSystemFont(14);
user.textColor = new Color("#555");
const repository = listWidget.addText(REPOSITORY);
repository.font = Font.boldRoundedSystemFont(20);
repository.textColor = new Color("#fff");
listWidget.addSpacer(10);
// Cache handling
const files = FileManager.local();
const path = files.joinPath(files.cacheDirectory(), "widget-apple-open-source");
const cacheExists = files.fileExists(path);
const cacheDate = cacheExists ? files.modificationDate(path) : 0;
const currentTime = Date.now();
let [stars, downloads] = ["?", "?"];
// Check if cached data is still valid
if (cacheExists && currentTime - cacheDate < CACHED_DATA_HOURS * 60 * 60 * 1000) {
const dataCached = JSON.parse(files.readString(path));
stars = dataCached.stars || stars;
downloads = dataCached.downloads || downloads;
} else {
// Fetch new data and update the cache
const dataToBeCached = {};
if (GITHUB_STARS_REPO) {
stars = await getGitHubStats(GITHUB_STARS_REPO);
dataToBeCached.stars = stars;
}
if (GITHUB_DOWNLOADS_REPO) {
downloads = await getGitHubDownloads(GITHUB_DOWNLOADS_REPO);
dataToBeCached.downloads = downloads;
}
files.writeString(path, JSON.stringify(dataToBeCached));
}
// Display GitHub stars and downloads
if (GITHUB_STARS_REPO) {
const githubStars = listWidget.addText(`★ ${stars}`);
githubStars.font = Font.semiboldRoundedSystemFont(16);
githubStars.textColor = new Color("#e0ff1b");
listWidget.addSpacer(5);
}
if (GITHUB_DOWNLOADS_REPO) {
const githubDownloads = listWidget.addText(` ⤓ ${downloads}`);
githubDownloads.font = Font.semiboldRoundedSystemFont(16);
githubDownloads.textColor = new Color("#4cff69");
}
// Return the configured widget
return listWidget;
}
// Function to fetch GitHub stars for a repository
async function getGitHubStats(repoName) {
const url = API_BASE_URL + repoName;
const request = new Request(url);
const data = await request.loadJSON();
return data.stargazers_count || "?";
}
// Function to fetch GitHub downloads for a repository
async function getGitHubDownloads(repoName) {
const url = `${API_BASE_URL + repoName}/releases`;
const request = new Request(url);
const data = await request.loadJSON();
// Calculate total downloads from releases and assets
const totalDownloads = data.reduce((acc, { assets }) => {
if (assets) {
return acc + assets.reduce((assetAcc, { download_count }) => assetAcc + download_count, 0);
}
return acc;
}, 0);
return totalDownloads || "?";
}
// Main execution
const widget = await createWidget();
if (config.runsInWidget) {
// Set the widget for display in the widget area
Script.setWidget(widget);
} else {
// Present the widget in a larger view for testing
widget.presentLarge();
}
// Signal that the script execution is complete
Script.complete();