hubba 0.7.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/hubba/github.rb CHANGED
@@ -1,210 +1,210 @@
1
- module Hubba
2
-
3
-
4
- class Github
5
- BASE_URL = 'https://api.github.com'
6
-
7
- ###############
8
- ## (nested) classes for "wrapped" response (parsed json body)
9
- class Resource
10
- attr_reader :data
11
- def initialize( data )
12
- @data = data
13
- end
14
- end
15
-
16
- class Repos < Resource
17
- def names
18
- ## sort by name
19
- data.map { |item| item['name'] }.sort
20
- end
21
- end
22
-
23
- class Orgs < Resource
24
- def logins
25
- ## sort by name
26
- data.map { |item| item['login'] }.sort
27
- end
28
- alias_method :names, :logins ## add name alias - why? why not?
29
- end
30
-
31
-
32
-
33
- def initialize( token: nil,
34
- user: nil,
35
- password: nil )
36
- @token = nil
37
- @user = nil
38
- @password = nil
39
-
40
- if token ## 1a) give preference to passed in token
41
- @token = token
42
- elsif user && password ## 1b) or passed in user/password credentials
43
- @user = user
44
- @password = password
45
- elsif Hubba.config.token ## 2a) followed by configured (or env) token
46
- @token = Hubba.config.token
47
- elsif Hubba.config.user && Hubba.config.password ## 2b)
48
- @user = Hubba.config.user
49
- @password = Hubba.config.password
50
- else ## 3)
51
- ## no token or credentials passed in or configured
52
- end
53
- end
54
-
55
-
56
-
57
- def user( name )
58
- Resource.new( get "/users/#{name}" )
59
- end
60
-
61
-
62
- def user_repos( name )
63
- Repos.new( get "/users/#{name}/repos" ) ## add ?per_page=100 - why? why not?
64
- end
65
-
66
-
67
- ##
68
- # note: pagination
69
- # requests that return multiple items will be paginated to 30 items by default.
70
- # You can specify further pages with the ?page parameter.
71
- # For some resources, you can also set a custom page size up to 100
72
- # with the ?per_page=100 parameter
73
-
74
- def user_orgs( name )
75
- Orgs.new( get "/users/#{name}/orgs?per_page=100" )
76
- end
77
-
78
-
79
-
80
- def org( name )
81
- Resource.new( get "/orgs/#{name}" )
82
- end
83
-
84
- def org_repos( name )
85
- Repos.new( get "/orgs/#{name}/repos?per_page=100" )
86
- end
87
-
88
-
89
-
90
- def repo( full_name ) ## full_name (handle) e.g. henrythemes/jekyll-starter-theme
91
- Resource.new( get "/repos/#{full_name}" )
92
- end
93
-
94
- def repo_languages( full_name )
95
- Resource.new( get "/repos/#{full_name}/languages" )
96
- end
97
-
98
- def repo_topics( full_name )
99
- ## note: requires "api preview" accept headers (overwrites default v3+json)
100
- ## e.g. application/vnd.github.mercy-preview+json
101
- Resource.new( get( "/repos/#{full_name}/topics", preview: 'mercy' ) )
102
- end
103
-
104
-
105
- def repo_commits( full_name )
106
- Resource.new( get "/repos/#{full_name}/commits" )
107
- end
108
-
109
-
110
- def repo_traffic_clones( full_name )
111
- # Get repository clones
112
- # Get the total number of clones and breakdown per day or week
113
- # for the last 14 days.
114
- # Timestamps are aligned to UTC midnight of the beginning of the day or week.
115
- # Week begins on Monday.
116
- Resource.new( get "/repos/#{full_name}/traffic/clones" )
117
- end
118
-
119
- def repo_traffic_views( full_name )
120
- # Get page views
121
- # Get the total number of views and breakdown per day or week
122
- # for the last 14 days.
123
- # Timestamps are aligned to UTC midnight of the beginning of the day or week.
124
- # Week begins on Monday.
125
- Resource.new( get "/repos/#{full_name}/traffic/views" )
126
- end
127
-
128
-
129
- def repo_traffic_popular_paths( full_name )
130
- # Get top referral paths
131
- # Get the top 10 popular contents over the last 14 days.
132
- Resource.new( get "/repos/#{full_name}/traffic/popular/paths" )
133
- end
134
-
135
- def repo_traffic_popular_referrers( full_name )
136
- # Get top referral sources
137
- # Get the top 10 referrers over the last 14 days.
138
- Resource.new( get "/repos/#{full_name}/traffic/popular/referrers" )
139
- end
140
-
141
-
142
-
143
-
144
- private
145
- def get( request_uri, preview: nil )
146
-
147
- puts "GET #{request_uri}"
148
-
149
- ## note: request_uri ALWAYS starts with leading /, thus use + for now!!!
150
- # e.g. /users/geraldb
151
- # /users/geraldb/repos
152
- url = BASE_URL + request_uri
153
-
154
-
155
- headers = {}
156
- ## add default headers if nothing (custom) set / passed-in
157
- headers['User-Agent'] = "ruby/hubba v#{VERSION}" ## required by GitHub API
158
- headers['Accept'] = if preview # e.g. mercy or ???
159
- "application/vnd.github.#{preview}-preview+json"
160
- else
161
- 'application/vnd.github.v3+json' ## default - recommend by GitHub API
162
- end
163
-
164
- auth = []
165
- ## check if credentials (user/password) present - if yes, use basic auth
166
- if @token
167
- puts " using (personal access) token - starting with: #{@token[0..6]}**********"
168
- headers['Authorization'] = "token #{@token}"
169
- ## token works like:
170
- ## curl -H 'Authorization: token my_access_token' https://api.github.com/user/repos
171
- elsif @user && @password
172
- puts " using basic auth - user: #{@user}, password: ***"
173
- ## use credential auth "tuple" (that is, array with two string items) for now
174
- ## or use Webclient::HttpBasicAuth or something - why? why not?
175
- auth = [@user, @password]
176
- # req.basic_auth( @user, @password )
177
- else
178
- puts " using no credentials (no token, no user/password)"
179
- end
180
-
181
- res = Webclient.get( url,
182
- headers: headers,
183
- auth: auth )
184
-
185
- # Get specific header
186
- # response["content-type"]
187
- # => "text/html; charset=UTF-8"
188
-
189
- # Iterate all response headers.
190
- # puts "HTTP HEADERS:"
191
- # res.headers.each do |key, value|
192
- # puts " #{key}: >#{value}<"
193
- # end
194
- # puts
195
-
196
- # => "location => http://www.google.com/"
197
- # => "content-type => text/html; charset=UTF-8"
198
- # ...
199
-
200
- if res.status.ok?
201
- res.json
202
- else
203
- puts "!! HTTP ERROR: #{res.status.code} #{res.status.message}:"
204
- pp res.raw
205
- exit 1
206
- end
207
- end # method get
208
-
209
- end # class Github
210
- end # module Hubba
1
+ module Hubba
2
+
3
+
4
+ class Github
5
+ BASE_URL = 'https://api.github.com'
6
+
7
+ ###############
8
+ ## (nested) classes for "wrapped" response (parsed json body)
9
+ class Resource
10
+ attr_reader :data
11
+ def initialize( data )
12
+ @data = data
13
+ end
14
+ end
15
+
16
+ class Repos < Resource
17
+ def names
18
+ ## sort by name
19
+ data.map { |item| item['name'] }.sort
20
+ end
21
+ end
22
+
23
+ class Orgs < Resource
24
+ def logins
25
+ ## sort by name
26
+ data.map { |item| item['login'] }.sort
27
+ end
28
+ alias_method :names, :logins ## add name alias - why? why not?
29
+ end
30
+
31
+
32
+
33
+ def initialize( token: nil,
34
+ user: nil,
35
+ password: nil )
36
+ @token = nil
37
+ @user = nil
38
+ @password = nil
39
+
40
+ if token ## 1a) give preference to passed in token
41
+ @token = token
42
+ elsif user && password ## 1b) or passed in user/password credentials
43
+ @user = user
44
+ @password = password
45
+ elsif Hubba.config.token ## 2a) followed by configured (or env) token
46
+ @token = Hubba.config.token
47
+ elsif Hubba.config.user && Hubba.config.password ## 2b)
48
+ @user = Hubba.config.user
49
+ @password = Hubba.config.password
50
+ else ## 3)
51
+ ## no token or credentials passed in or configured
52
+ end
53
+ end
54
+
55
+
56
+
57
+ def user( name )
58
+ Resource.new( get "/users/#{name}" )
59
+ end
60
+
61
+
62
+ def user_repos( name )
63
+ Repos.new( get "/users/#{name}/repos" ) ## add ?per_page=100 - why? why not?
64
+ end
65
+
66
+
67
+ ##
68
+ # note: pagination
69
+ # requests that return multiple items will be paginated to 30 items by default.
70
+ # You can specify further pages with the ?page parameter.
71
+ # For some resources, you can also set a custom page size up to 100
72
+ # with the ?per_page=100 parameter
73
+
74
+ def user_orgs( name )
75
+ Orgs.new( get "/users/#{name}/orgs?per_page=100" )
76
+ end
77
+
78
+
79
+
80
+ def org( name )
81
+ Resource.new( get "/orgs/#{name}" )
82
+ end
83
+
84
+ def org_repos( name )
85
+ Repos.new( get "/orgs/#{name}/repos?per_page=100" )
86
+ end
87
+
88
+
89
+
90
+ def repo( full_name ) ## full_name (handle) e.g. henrythemes/jekyll-starter-theme
91
+ Resource.new( get "/repos/#{full_name}" )
92
+ end
93
+
94
+ def repo_languages( full_name )
95
+ Resource.new( get "/repos/#{full_name}/languages" )
96
+ end
97
+
98
+ def repo_topics( full_name )
99
+ ## note: requires "api preview" accept headers (overwrites default v3+json)
100
+ ## e.g. application/vnd.github.mercy-preview+json
101
+ Resource.new( get( "/repos/#{full_name}/topics", preview: 'mercy' ) )
102
+ end
103
+
104
+
105
+ def repo_commits( full_name )
106
+ Resource.new( get "/repos/#{full_name}/commits" )
107
+ end
108
+
109
+
110
+ def repo_traffic_clones( full_name )
111
+ # Get repository clones
112
+ # Get the total number of clones and breakdown per day or week
113
+ # for the last 14 days.
114
+ # Timestamps are aligned to UTC midnight of the beginning of the day or week.
115
+ # Week begins on Monday.
116
+ Resource.new( get "/repos/#{full_name}/traffic/clones" )
117
+ end
118
+
119
+ def repo_traffic_views( full_name )
120
+ # Get page views
121
+ # Get the total number of views and breakdown per day or week
122
+ # for the last 14 days.
123
+ # Timestamps are aligned to UTC midnight of the beginning of the day or week.
124
+ # Week begins on Monday.
125
+ Resource.new( get "/repos/#{full_name}/traffic/views" )
126
+ end
127
+
128
+
129
+ def repo_traffic_popular_paths( full_name )
130
+ # Get top referral paths
131
+ # Get the top 10 popular contents over the last 14 days.
132
+ Resource.new( get "/repos/#{full_name}/traffic/popular/paths" )
133
+ end
134
+
135
+ def repo_traffic_popular_referrers( full_name )
136
+ # Get top referral sources
137
+ # Get the top 10 referrers over the last 14 days.
138
+ Resource.new( get "/repos/#{full_name}/traffic/popular/referrers" )
139
+ end
140
+
141
+
142
+
143
+
144
+ private
145
+ def get( request_uri, preview: nil )
146
+
147
+ puts "GET #{request_uri}"
148
+
149
+ ## note: request_uri ALWAYS starts with leading /, thus use + for now!!!
150
+ # e.g. /users/geraldb
151
+ # /users/geraldb/repos
152
+ url = BASE_URL + request_uri
153
+
154
+
155
+ headers = {}
156
+ ## add default headers if nothing (custom) set / passed-in
157
+ headers['User-Agent'] = "ruby/hubba v#{VERSION}" ## required by GitHub API
158
+ headers['Accept'] = if preview # e.g. mercy or ???
159
+ "application/vnd.github.#{preview}-preview+json"
160
+ else
161
+ 'application/vnd.github.v3+json' ## default - recommend by GitHub API
162
+ end
163
+
164
+ auth = []
165
+ ## check if credentials (user/password) present - if yes, use basic auth
166
+ if @token
167
+ puts " using (personal access) token - starting with: #{@token[0..6]}**********"
168
+ headers['Authorization'] = "token #{@token}"
169
+ ## token works like:
170
+ ## curl -H 'Authorization: token my_access_token' https://api.github.com/user/repos
171
+ elsif @user && @password
172
+ puts " using basic auth - user: #{@user}, password: ***"
173
+ ## use credential auth "tuple" (that is, array with two string items) for now
174
+ ## or use Webclient::HttpBasicAuth or something - why? why not?
175
+ auth = [@user, @password]
176
+ # req.basic_auth( @user, @password )
177
+ else
178
+ puts " using no credentials (no token, no user/password)"
179
+ end
180
+
181
+ res = Webclient.get( url,
182
+ headers: headers,
183
+ auth: auth )
184
+
185
+ # Get specific header
186
+ # response["content-type"]
187
+ # => "text/html; charset=UTF-8"
188
+
189
+ # Iterate all response headers.
190
+ # puts "HTTP HEADERS:"
191
+ # res.headers.each do |key, value|
192
+ # puts " #{key}: >#{value}<"
193
+ # end
194
+ # puts
195
+
196
+ # => "location => http://www.google.com/"
197
+ # => "content-type => text/html; charset=UTF-8"
198
+ # ...
199
+
200
+ if res.status.ok?
201
+ res.json
202
+ else
203
+ puts "!! HTTP ERROR: #{res.status.code} #{res.status.message}:"
204
+ pp res.raw
205
+ exit 1
206
+ end
207
+ end # method get
208
+
209
+ end # class Github
210
+ end # module Hubba
data/lib/hubba/reposet.rb CHANGED
@@ -1,83 +1,83 @@
1
- module Hubba
2
-
3
-
4
- ## orgs - include repos form org(anizations) too
5
- ## cache - save json response to cache_dir - change to/use debug/tmp_dir? - why? why not?
6
- def self.reposet( *users, orgs: true,
7
- cache: false )
8
- # users = [users] if users.is_a?( String ) ### wrap in array if single user
9
-
10
- gh = Github.new
11
-
12
- forks = []
13
-
14
- h = {}
15
- users.each do |user|
16
- res = gh.user_repos( user )
17
- save_json( "#{config.cache_dir}/users~#{user}~repos.json", res.data ) if cache
18
-
19
- repos = []
20
- ####
21
- # check for forked repos (auto-exclude personal by default)
22
- # note: forked repos in orgs get NOT auto-excluded!!!
23
- res.data.each do |repo|
24
- fork = repo['fork']
25
- if fork
26
- print "FORK "
27
- forks << "#{repo['full_name']} (AUTO-EXCLUDED)"
28
- else
29
- print " "
30
- repos << repo['name']
31
- end
32
- print repo['full_name']
33
- print "\n"
34
- end
35
-
36
-
37
- h[ "#{user} (#{repos.size})" ] = repos.sort
38
- end
39
-
40
-
41
- ## all repos from orgs
42
- ## note: for now only use first (primary user) - why? why not?
43
- if orgs
44
- user = users[0]
45
- res = gh.user_orgs( user )
46
- save_json( "#{config.cache_dir}/users~#{user}~orgs.json", res.data ) if cache
47
-
48
-
49
- logins = res.logins.each do |login|
50
- ## next if ['xxx'].include?( login ) ## add orgs here to skip
51
-
52
- res = gh.org_repos( login )
53
- save_json( "#{config.cache_dir}/orgs~#{login}~repos.json", res.data ) if cache
54
-
55
- repos = []
56
- res.data.each do |repo|
57
- fork = repo['fork']
58
- if fork
59
- print "FORK "
60
- forks << repo['full_name']
61
- repos << repo['name']
62
- else
63
- print " "
64
- repos << repo['name']
65
- end
66
- print repo['full_name']
67
- print "\n"
68
- end
69
-
70
- h[ "#{login} (#{repos.size})" ] = repos.sort
71
- end
72
- end
73
-
74
- if forks.size > 0
75
- puts
76
- puts "#{forks.size} fork(s):"
77
- puts forks
78
- end
79
-
80
- h
81
- end ## method reposet
82
-
83
- end # module Hubba
1
+ module Hubba
2
+
3
+
4
+ ## orgs - include repos form org(anizations) too
5
+ ## cache - save json response to cache_dir - change to/use debug/tmp_dir? - why? why not?
6
+ def self.reposet( *users, orgs: true,
7
+ cache: false )
8
+ # users = [users] if users.is_a?( String ) ### wrap in array if single user
9
+
10
+ gh = Github.new
11
+
12
+ forks = []
13
+
14
+ h = {}
15
+ users.each do |user|
16
+ res = gh.user_repos( user )
17
+ save_json( "#{config.cache_dir}/users~#{user}~repos.json", res.data ) if cache
18
+
19
+ repos = []
20
+ ####
21
+ # check for forked repos (auto-exclude personal by default)
22
+ # note: forked repos in orgs get NOT auto-excluded!!!
23
+ res.data.each do |repo|
24
+ fork = repo['fork']
25
+ if fork
26
+ print "FORK "
27
+ forks << "#{repo['full_name']} (AUTO-EXCLUDED)"
28
+ else
29
+ print " "
30
+ repos << repo['name']
31
+ end
32
+ print repo['full_name']
33
+ print "\n"
34
+ end
35
+
36
+
37
+ h[ "#{user} (#{repos.size})" ] = repos.sort
38
+ end
39
+
40
+
41
+ ## all repos from orgs
42
+ ## note: for now only use first (primary user) - why? why not?
43
+ if orgs
44
+ user = users[0]
45
+ res = gh.user_orgs( user )
46
+ save_json( "#{config.cache_dir}/users~#{user}~orgs.json", res.data ) if cache
47
+
48
+
49
+ logins = res.logins.each do |login|
50
+ ## next if ['xxx'].include?( login ) ## add orgs here to skip
51
+
52
+ res = gh.org_repos( login )
53
+ save_json( "#{config.cache_dir}/orgs~#{login}~repos.json", res.data ) if cache
54
+
55
+ repos = []
56
+ res.data.each do |repo|
57
+ fork = repo['fork']
58
+ if fork
59
+ print "FORK "
60
+ forks << repo['full_name']
61
+ repos << repo['name']
62
+ else
63
+ print " "
64
+ repos << repo['name']
65
+ end
66
+ print repo['full_name']
67
+ print "\n"
68
+ end
69
+
70
+ h[ "#{login} (#{repos.size})" ] = repos.sort
71
+ end
72
+ end
73
+
74
+ if forks.size > 0
75
+ puts
76
+ puts "#{forks.size} fork(s):"
77
+ puts forks
78
+ end
79
+
80
+ h
81
+ end ## method reposet
82
+
83
+ end # module Hubba