DEV Community

Nikolas Evers
Nikolas Evers

Posted on • Originally published at nikol.as on

WeeklyRandom #0

Welcome to WeeklyRandom, a blog series in which I challenge myself to explore a random GitHub repository starred by me every week.

Let's get started. I'll need a way to retrieve a random GitHub repository starred by me. I found this Gist that shows how one can retrieve the starred repositories of a user.

// https://gist.github.com/derhuerst/19e0844796fa3b62e1e9567a1dc0b5a3
const stars = (user) =>
    got(`https://api.github.com/users/${user}/starred`)
    .then((res) => JSON.parse(res.body))
    .then((starred) => starred.map((s) => ({
          owner:       s.owner.login
        , repo:        s.name
        , description: s.description
        , language:    s.language
        , isFork:      false
        , stargazers:  s.stargazers_count
        , watchers:    s.watchers_count
})))

I am no JavaScript wizard 🧙 and do not know if the got dependency is really necessary here. Let's keep it for now.

Problem: This only returns 30 repositories. Since the GitHub API is paginated, I'll need to figure out a way to get the total number of pages before trying to get a random page and entry. I solved this by parsing the response headers which contained the following Link:

<https://api.github.com/user/13335308/starred?page=2>; rel="next", <https://api.github.com/user/13335308/starred?page=93>; rel="last"

Perfect. I can use rel="last" to generate a random page number between 1 and - in this case - 93. If I send a request for that page, the only thing left to do is to pick a random repository out of the returned 30.

This is the current script:

Note: Updated on Oct 16, 2018 to reflect changes suggested by u/ChucklefuckBitch and u/dulac91. Thanks!

// index.js

"use strict";

const got = require("got");

let user = process.argv.slice(2)[0];
let randomEntry = Math.floor(Math.random() * 30);
let lastPage = new RegExp(/(.*)page=(.*)>; rel=\"last\"/);

if (!user) {
  console.log("Usage: `node index.js username`");
  process.exit(1);
}

const getStars = (user, page) =>
  got(`https://api.github.com/users/${user}/starred?page=${page}`)
    .then((res) => JSON.parse(res.body))
    .then((starred) =>
      starred.map((s) => ({
        owner: s.owner.login,
        repo: s.name
      }))
    );

const getRandomPage = (user) =>
  got(`https://api.github.com/users/${user}/starred`)
    .then((res) =>
      res.headers.link
        .replace(lastPage, "$2")
    )
    .then((pages) => Math.floor(Math.random() * pages) + 1);

getRandomPage(user, randomEntry)
  .then((page) => getStars(user, page))
  .then((result) =>
    console.log("https://github.com/" + result[randomEntry].owner + "/" + result[randomEntry].repo)
  );

I'm pretty sure that this is a very inefficient way to do this, but it should get the job done. The whole purpose of this series is to learn something and to improve myself. And I definitely learned something about consuming the GitHub API and about arrow functions in JavaScript.

Let's try it:

node index.js vintagesucks
https://github.com/lgkonline/mavo-snippets

node index.js vintagesucks
https://github.com/simonepri/geo-maps

node index.js vintagesucks
https://github.com/genuinetools/apk-file

It works! 🎉

You can find the complete code on GitHub at vintagesucks/random-starred-repository. Pull requests with improvements are very welcome!

Until next week, when I'll check out my first WeeklyRandom repository.

Top comments (0)