forked from bitcoin-dot-org/Bitcoin.org
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontributors.rb
152 lines (138 loc) · 5.63 KB
/
contributors.rb
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
# This file is licensed under the MIT License (MIT) available on
# http://opensource.org/licenses/MIT.
#contributors.rb fetches Bitcoin Core contributors list and set
#site.contributors array. This is later used to display the
#list of contributors on the "Development" page.
require 'open-uri'
require 'json'
module Jekyll
class CategoryGenerator < Generator
def contributors(repo, aliases)
contributors = []
# Call GitHub API with 100 results per page
page = 1
data = []
while page < 10 do
begin
ar = JSON.parse(open("https://api.github.com/repos/"+repo+"/contributors?page=#{page}&per_page=100","User-Agent"=>"Ruby/#{RUBY_VERSION}").read)
# Prevent any error to stop the build process, return an empty array instead
rescue
print 'GitHub API Call Failed!'
break
end
if !ar.is_a?(Array)
print 'GitHub API Call Failed!'
return contributors
end
if ar.length > 100
print 'GitHub API exceeding the 100 results limit!'
return contributors
end
# Stop calling GitHub API when no new results are returned
break if (ar.length == 0)
# Merge contributors into a single array
data.push(*ar)
page += 1
end
# Loop in returned results array
result = {}
for c in data
# Skip incomplete / invalid data and set contributor's name
next if !c.is_a?(Hash)
next if !c.has_key?('contributions') or !c['contributions'].is_a?(Integer) or c['contributions'] > 1000000
if c.has_key?('name') and c['name'].is_a?(String) and /^[A-Za-z0-9\-]{1,150}$/.match(c['name'])
name = c['name']
elsif c.has_key?('login') and c['login'].is_a?(String) and /^[A-Za-z0-9\-]{1,150}$/.match(c['login'])
name = c['login']
else
next
end
# Replace name by its corresponding alias if defined in _config.yml
name = aliases[name] if aliases.has_key?(name)
# Assign variables
x = {}
x['name'] = name
x['contributions'] = c['contributions']
# Set avatar_url when available
if c.has_key?('avatar_url') and c['avatar_url'].is_a?(String) and /^https:\/\/avatars\.githubusercontent\.com\/u\/[0-9]{1,10}\?v=[0-9]{1,2}$/.match(c['avatar_url'])
x['avatar_url'] = c['avatar_url'] + '&size=16'
end
# Set login when available
if c.has_key?('login') and c['login'].is_a?(String) and /^[A-Za-z0-9\-]{1,150}$/.match(c['login'])
x['login'] = c['login']
end
# Add new contributor to the array, or increase contributions if it already exists
if result.has_key?(name)
result[name]['contributions'] += x['contributions']
else
result[name] = x
end
end
# Generate final ordered contributors array
result.each do |key, value|
contributors.push(value)
end
contributors.sort_by{|c| - c['contributions']}
end
def generate(site)
# Set site.contributors global variables for liquid/jekyll
class << site
attr_accessor :corecontributors
attr_accessor :sitecontributors
alias contrib_site_payload site_payload
def site_payload
h = contrib_site_payload
payload = h["site"]
payload["corecontributors"] = self.corecontributors
payload["sitecontributors"] = self.sitecontributors
h["site"] = payload
h
end
end
# Set site.corecontributors and site.sitecontributors arrays
site.corecontributors = {}
site.sitecontributors = {}
#Do nothing if plugin is disabled
if !ENV['ENABLED_PLUGINS'].nil? and ENV['ENABLED_PLUGINS'].index('contributors').nil?
print 'Contributors disabled' + "\n"
return
end
## Create cache directory if it doesn't exist
if !File.exists?('_cache')
Dir.mkdir('_cache')
end
# Populate site.corecontributors and site.sitecontributors with
# data from GitHub.com. Store data in the cache and only
# re-retrieve the data if 86,400 seconds (24 hours) passes from
# the retrieval date or if the cache file is deleted. For
# simplicity, updates on the two cache files are linked, so if one
# file has to be updated, they both get updated.
corecontributors_cache = '_cache/corecontributors.marshall'
sitecontributors_cache = '_cache/sitecontributors.marshall'
if File.exists?(corecontributors_cache) && File.exists?(sitecontributors_cache)
corecontributors_cache_age = (Time.now - File.stat(corecontributors_cache).mtime).to_i
sitecontributors_cache_age = (Time.now - File.stat(sitecontributors_cache).mtime).to_i
else
corecontributors_cache_age = Time.now.to_i
sitecontributors_cache_age = Time.now.to_i
end
if corecontributors_cache_age > 86400 || sitecontributors_cache_age > 86400
site.corecontributors = contributors('bitcoin/bitcoin',site.config['aliases'])
File.open(corecontributors_cache,'w') do |file|
Marshal.dump(site.corecontributors, file)
end
site.sitecontributors = contributors('bitcoin-dot-org/bitcoin.org',site.config['aliases'])
File.open(sitecontributors_cache,'w') do |file|
Marshal.dump(site.sitecontributors, file)
end
else
File.open(corecontributors_cache,'r') do |file|
site.corecontributors = Marshal.load(file)
end
File.open(sitecontributors_cache,'r') do |file|
site.sitecontributors = Marshal.load(file)
end
end
end
end
end