Skip to content

Instantly share code, notes, and snippets.

@drnic
Created July 13, 2010 10:30
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save drnic/473707 to your computer and use it in GitHub Desktop.
Save drnic/473707 to your computer and use it in GitHub Desktop.
Discover the contribution status of a user for all their watched repos: owner, collaborator, or watcher
#!/usr/bin/env ruby
#
# Discover the contribution status of a user for all their watched repos: owner, collaborator, or watcher
# Returns either JSON (default) or HTML (example http://github-user-profiles-example.heroku.com/)
#
# JSON: Returns either Array of JSON; or streams each JSON result as discovered (--stream flag)
# { "repo" => { ... }, "owner" => is project owner?, "collaborator" => has collaborator access? }
#
# HTML: Sort-of pretty HTML output. Nice to use --stream | bcat.
#
# Usage:
#
# Save to file github_user_collaborations.rb
#
# JSON usage:
# ./github_user_collaborations.rb drnic --stream # lots of results streamed
# ./github_user_collaborations.rb kef # 20+ results in an Array
#
# HTML usage:
# gem install bcat
# ./github_user_collaborations.rb drnic --stream --html | bcat
#
# Or:
#
# ruby -rubygems -ropen-uri -e 'eval open("http://gist.github.com/raw/473707/github_user_collaborations.rb").read' drnic --stream
require "json"
require "open-uri"
def collaborators(user, project)
begin
url = "http://github.com/api/v2/json/repos/show/#{user}/#{project}/collaborators"
$stderr.puts "open #{url}" if ENV['DEBUG']
JSON.parse(open(url).read)["collaborators"]
rescue OpenURI::HTTPError => e
$stderr.puts "404 on #{url}" if ENV['DEBUG']
[]
end
end
def watched_repos(user)
begin
url = "http://github.com/api/v2/json/repos/watched/#{user}"
$stderr.puts "open #{url}" if ENV['DEBUG']
JSON.parse(open(url).read)["repositories"]
rescue OpenURI::HTTPError => e
$stderr.puts "404 on #{url}" if ENV['DEBUG']
[]
end
end
def contributions(user, &block)
if block
watched_repos(user).each do |repo|
is_owner = repo["owner"] == user
yield({ "repo" => repo, "owner" => is_owner, "collaborator" => (is_owner || collaborators(repo["owner"], repo["name"]).include?(user)) })
end
else
watched_repos(user).map do |repo|
is_owner = repo["owner"] == user
{ "repo" => repo, "owner" => is_owner, "collaborator" => (is_owner || collaborators(repo["owner"], repo["name"]).include?(user)) }
end
end
end
def render_html_header(user)
puts <<-HTML
<html>
<head>
<title>Profile for Github User #{user}</title>
<link href="http://assets2.github.com/stylesheets/bundle_common.css" media="screen" rel="stylesheet" type="text/css" />
<link href="http://assets1.github.com/stylesheets/bundle_github.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="first">
<h2>#{user} repositories</h2>
<ul class="repositories">
HTML
end
def render_contribution_html(contribution)
repo = contribution["repo"]
puts <<-HTML
<li class="public">
<ul class="repo-stats">
#{render_status(contribution["owner"], contribution["collaborator"], repo['url'])}
</ul>
<h3><a href="#{repo['url']}">#{repo["owner"]}/#{repo["name"]}</a></h3>
<div class="body">
</div>
</li>
HTML
$stdout.flush
end
def render_status(owner, collaborator, url)
if owner
%Q{<li class="forks"><a href="#{url}" title="Owner">Owner</a></li>}
elsif collaborator
%Q{<li class="forks"><a href="#{url}" title="Contributor">Contributor</a></li>}
end
end
def render_contributions_html(user, contributions)
render_html_header user
contributions.each {|contribution| render_contribution_html contribution }
end
options = {:format => "json"}
parser = OptionParser.new do |opts|
opts.banner = <<-BANNER.gsub(/^ /, '')
Discover the contribution status of a user for all their watched repositories: owner, collaborator, or watcher
Returns JSON { "repo" => { ... }, "owner" => is project owner?, "collaborator" => has collaborator access? }
Returns either Array of JSON above; or streams each JSON result as discovered (--stream flag)
Usage: #{File.basename($0)} user [options]
Options are:
BANNER
opts.separator ""
opts.on("-s", "--stream",
"Stream each watched repository result on a line of its own."
) { |arg| options[:stream] = true }
opts.on("--html",
"Outputs HTML (streaming and non-stream)",
"Default: false"
) { |arg| options[:format] = "html" }
opts.on("--json",
"Outputs JSON (streaming and non-stream)",
"Default: true"
) { |arg| options[:format] = "json" }
opts.on("-h", "--help",
"Show this help message.") { $stdout.puts opts; exit }
opts.parse!(ARGV)
end
if user = ARGV.shift
if options[:format] == "json"
if options[:stream]
contributions(user) do |contribution|
puts contribution.to_json
$stdout.flush
end
else
print contributions(user).to_json
end
elsif options[:format] == "html"
if options[:stream]
render_html_header user
contributions(user) do |contribution|
render_contribution_html contribution
end
else
render_contributions_html user, contributions(user)
end
end
else
puts parser
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment