Skip to content

Instantly share code, notes, and snippets.

@liyasthomas
Last active January 18, 2024 06:36
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liyasthomas/72312152516798f8d46f8cc5db2ea4cd to your computer and use it in GitHub Desktop.
Save liyasthomas/72312152516798f8d46f8cc5db2ea4cd to your computer and use it in GitHub Desktop.
GitHub stats count Scriptable widget script

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();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment