Skip to content

Instantly share code, notes, and snippets.

@hyrious
Last active November 29, 2019 10:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyrious/e34d49fc9fb164356482c9da82509543 to your computer and use it in GitHub Desktop.
Save hyrious/e34d49fc9fb164356482c9da82509543 to your computer and use it in GitHub Desktop.
Pull GitHub Stars
#!/usr/bin/env ruby -wKU
require 'io/console'
require 'ostruct'
require 'http'
def h2o h
JSON.parse(JSON.generate(h), object_class: OpenStruct)
end
def o2h o, h={}
o.each_pair { |k, v| h[k] = (OpenStruct === v ? (o2h v) : v) }; h
end
url = 'https://api.github.com'
print 'Input your GitHub API token (hidden): '
token = STDIN.noecho(&:gets).chomp
puts
puts 'Working on it ...'
@client = HTTP[Accept: 'application/json'].auth("bearer #{token}").persistent(url)
def q text
key_limit = 'x-ratelimit-limit'
key_remain = 'x-ratelimit-remaining'
# puts format '> %s', text
res = @client.post('/graphql', json: { query: text })
# puts format '(rate-limit %s / %s)', res[key_remain], res[key_limit]
h2o res.parse
end
begin
login = (q 'query { viewer { login } }').data.viewer.login
puts format 'login = %p', login
query = 'query { user(login: %p) { starredRepositories(first: 1) { totalCount } } }'
count = (q format query, login).data.user.starredRepositories.totalCount
puts format 'stars = %p', count
cursor, continue = nil, true
stars = []
query = 'query { user(login: %p) { starredRepositories(first: 100%s) { nodes { name, url } pageInfo { endCursor, hasNextPage } } } }'
while continue
fix = cursor ? format(', after: %p', cursor) : ''
ret = q format query, login, fix
stars.concat ret.data.user.starredRepositories.nodes
cursor = ret.data.user.starredRepositories.pageInfo.endCursor
continue = ret.data.user.starredRepositories.pageInfo.hasNextPage
puts format 'downloading ... %p / %p', stars.size, count
end
File.write 'stars.json', JSON.generate(stars.map { |e| o2h e })
ensure
@client.close if @client
end
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stars</title>
<style>
* {
box-sizing: border-box;
}
input {
display: block;
width: 100%;
}
</style>
</head>
<body>
<input type="search" oninput="update(this.value)">
<div><small id="count"></small></div>
<ul id="output"></ul>
<script src="stars.js"></script>
<script src="https://unpkg.com/lunr/lunr.js"></script>
<script>
var Idx = lunr(function() {
this.field("name");
this.field("url");
this.field("description");
stars.forEach((e, id) => this.add({ ...e, id }));
});
function elt(tag, ...children) {
var el = document.createElement(tag);
el.append(...children);
return el;
}
function tap(obj, func) {
func(obj);
return obj;
}
function update(text) {
text = text.trim();
var results = Idx.search(text);
if (results.length === 0) {
output.style.opacity = 0.5;
return;
}
count.textContent = `Found ${results.length} repos.`;
output.style.opacity = 1;
output.innerHTML = "";
if (text === '') results.reverse();
for (var { ref } of results) {
var { name, url, description } = stars[ref];
output.append(
elt(
"li",
tap(elt("a", name), a => (a.href = url)),
": ",
description
)
);
}
}
update('');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment