-
Notifications
You must be signed in to change notification settings - Fork 0
/
render.coffee
165 lines (143 loc) · 5.57 KB
/
render.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
Async = require("async")
Request = require("request")
Sugar = require("sugar")
Less = require("less")
File = require("fs")
exec = require("child_process").exec
require("eco")
index = require("./src/index")
# TODO: These should be set from the command line
options =
organization: "demandforce"
topRepos: 6
# Retrieve organization members in alphabetical order.
retrieveMembers = ({ organization }, callback)->
Request.get "https://api.github.com/orgs/#{organization}/members", (error, response, body)->
if error
throw error
# At this point we get member login, we also want their name, URL and repos
members = JSON.parse(body)
Async.map members, (member, done)->
Request.get "https://api.github.com/users/#{member.login}", (error, response, body)->
if error
done error
else if response.statusCode == 200
done null, JSON.parse(body)
else
done null, member
, (error, members)->
if error
throw error
# Lets also retrieve all their repos, these will be included in the finale
# list
Async.map members, (member, done)->
Request.get "https://api.github.com/users/#{member.login}/repos", (error, response, body)->
if error
done error
else
if response.statusCode == 200
repos = JSON.parse(body)
# We're only interested in member's own repos, no forks; sorted by
# watchers.
member.repos = repos
.filter((repo)-> !repo.fork)
.sort((a, b)-> rank(b) - rank(a))
done null, member
, (error, members)->
if error
throw error
# Pass members list, sorted alphabetically.
callback members.sort((a, b)-> a.name >= b.name)
rank = (repo)->
days_old = (Date.now() - new Date(repo.pushed_at)) / 86400000
return (repo.watchers + repo.forks * 2) * (1- days_old * 0.005)
# Retrieve organization repositories, merge with member repositories, pass to
# callback sorted by most watched.
retrieveOrgRepos = ({ organization }, members, callback)->
Request.get "https://api.github.com/orgs/#{organization}/repos", (error, response, body)->
if error
throw error
# Filter organization's own repositories.
repos = JSON.parse(body).filter((repo)-> !repo.fork)
# Merge with member repositories
for member in members
repos = repos.concat(member.repos)
# Sort from most to least watched
repos = repos.sort((a,b)-> b.watchers - a.watchers)
callback repos
retrieveContributors = (repos, members, callback)->
# Let's find all the contributors
Async.reduce repos, [], (contributors, repo, done)->
Request.get "#{repo.url}/contributors", (error, response, body)->
if error
done error
else
for contributor in JSON.parse(body)
if members.find((member)-> member.login == contributor.login)
contributors.push contributor
done null, contributors
, (error, contributors)->
if error
throw error
# First, remove all duplicates. Calling .unique() doesn't work because we
# have distinct objects here.
contributors = contributors
.reduce((map, member)->
map[member.login] = member
return map
, {})
# Next get the list of unique contributors and sort alphabetically.
contributors = Object.values(contributors)
.sort((a, b)-> a.name >= b.name)
# We want their full name and URL
Async.map contributors, (contributor, done)->
Request.get "https://api.github.com/users/#{contributor.login}", (error, response, body)->
done error, body && JSON.parse(body)
, (error, contributors)->
if error
throw error
callback contributors
# Retrieve organization and member repositories and pass the following object to
# callback:
# members - Array of members with repositories, sorted alphabetically
# repos - Array of organization and member repositories, sorted by watchers
# contributors - Organization members that either have a repository or
# are contributors to one, sorted alphabetically
#
# For each member you get:
# login - Github login
# name - Member name
# html_url - URL for their Github page
# avatar_url - Gravatar URL
# repos - Interesting repositories, sorted by most watched first
#
# Each member repository includes:
# name - Repository name
# homepage - Homepage URL (nor necessarily same as repository)
# html_url - URL for Github page
# watchers - Number of watchers
# forkers - Number of forkers
retrieve = (options, callback)->
retrieveMembers options, (members)->
retrieveOrgRepos options, members, (repos)->
retrieveContributors repos, members, (contributors)->
top_repos = repos.slice(0, options.topRepos)
takeScreenshots top_repos, ->
callback
repos: top_repos
members: members
contributors: contributors
# Takes a screenshot of the `url` and passes the
screenshot = (url, save_to, callback)->
exec "phantomjs #{__dirname}/scripts/screenshot.coffee #{url} #{save_to}", callback
# Given an array of `repos`, it takes a screenshot of each of them and
# saves it to the appropriate path.
takeScreenshots = (repos, callback)->
Async.forEach repos, (repo, done)->
return done() unless repo.homepage
screenshot repo.homepage, "#{__dirname}/html/images/#{repo.id}.png", done
, callback
# Retrieve what we need and render it to stdout.
retrieve options, (data)->
html = index(data)
process.stdout.write html