opsb-octopussy 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/octopussy.rb ADDED
@@ -0,0 +1,62 @@
1
+ require 'forwardable'
2
+
3
+ require 'httparty'
4
+ require 'hashie'
5
+ Hash.send :include, Hashie::HashExtensions
6
+
7
+ libdir = File.dirname(__FILE__)
8
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
9
+
10
+ require 'octopussy/repo'
11
+ require 'octopussy/event'
12
+ require 'octopussy/client'
13
+
14
+ module Octopussy
15
+ extend SingleForwardable
16
+
17
+ VERSION = "0.3.0".freeze
18
+
19
+ class OctopussyError < StandardError
20
+ attr_reader :data
21
+
22
+ def initialize(data)
23
+ @data = data
24
+ super
25
+ end
26
+ end
27
+
28
+ class ClientError < StandardError; end
29
+ class ServerError < OctopussyError; end
30
+ class General < OctopussyError; end
31
+
32
+ class RateLimitExceeded < ClientError; end
33
+ class Unauthorized < ClientError; end
34
+ class NotFound < ClientError; end
35
+
36
+ class Unavailable < StandardError; end
37
+ class InformOctopussy < StandardError; end
38
+
39
+ def self.client; Client.new end
40
+
41
+ # Users
42
+ def_delegators :client, :search_users, :user, :followers, :following, :follows?, :watched
43
+
44
+ # Issues
45
+ def_delegators :client, :search_issues, :issues, :issue
46
+
47
+ # Repos
48
+ def_delegators :client, :branches, :collaborators, :contributors, :languages, :list_repos,
49
+ :network, :repo, :search_repos, :tags
50
+
51
+ # Network Meta
52
+ def_delegators :client, :network_meta, :network_data
53
+
54
+ # Trees
55
+ def_delegators :client, :tree, :blob, :raw
56
+
57
+ # Commits
58
+ def_delegators :client, :list_commits, :commit
59
+
60
+ # Timeline
61
+ def_delegators :client, :public_timeline
62
+ end
@@ -0,0 +1,402 @@
1
+ require 'cgi'
2
+ module Octopussy
3
+ class Client
4
+ include HTTParty
5
+ format :json
6
+ base_uri "http://github.com/api/v2/json"
7
+
8
+ attr_reader :login, :token
9
+
10
+ # :login => 'pengwynn', :token => 'your_github_api_key'
11
+ def initialize(auth={})
12
+ if auth[:password].nil?
13
+ @login = auth[:login]
14
+ @token = auth[:token]
15
+ self.class.basic_auth(nil, nil)
16
+ else
17
+ @login = auth[:login]
18
+ self.class.basic_auth(@login, auth[:password])
19
+ end
20
+
21
+ end
22
+
23
+ def search_users(q)
24
+ q = CGI.escape(q)
25
+ response = self.class.get("/user/search/#{q}")
26
+ Hashie::Mash.new(response).users
27
+ end
28
+
29
+ def user(login=self.login)
30
+ response = self.class.get("/user/show/#{login}", :query => auth_params)
31
+ Hashie::Mash.new(response).user
32
+ end
33
+
34
+
35
+ def update_user(values={})
36
+ response = self.class.post("/user/show/#{self.login}", :query => auth_params, :body => {:values => values})
37
+ Hashie::Mash.new(response).user
38
+ end
39
+
40
+ def followers(login=self.login)
41
+ response = self.class.get("/user/show/#{login}/followers")
42
+ Hashie::Mash.new(response).users
43
+ end
44
+
45
+ def following(login=self.login)
46
+ response = self.class.get("/user/show/#{login}/following")
47
+ Hashie::Mash.new(response).users
48
+ end
49
+
50
+ def follow!(username)
51
+ response = self.class.post("/user/follow/#{username}", :query => auth_params)
52
+ Hashie::Mash.new(response).users
53
+ end
54
+
55
+ def unfollow!(username)
56
+ response = self.class.post("/user/unfollow/#{username}", :query => auth_params)
57
+ Hashie::Mash.new(response).users
58
+ end
59
+
60
+ def follows?(*args)
61
+ target = args.pop
62
+ username = args.first
63
+ username ||= self.login
64
+ return if username.nil?
65
+ self.following(username).include?(target)
66
+ end
67
+
68
+ def watched(login=self.login)
69
+ response = self.class.get("/repos/watched/#{login}")
70
+ Hashie::Mash.new(response).repositories
71
+ end
72
+
73
+ def emails
74
+ response = self.class.get("/user/emails", :query => auth_params)
75
+ Hashie::Mash.new(response).emails
76
+ end
77
+
78
+ def add_email(email)
79
+ response = self.class.post("/user/email/add", :query => auth_params, :body => {:email => email})
80
+ Hashie::Mash.new(response).emails
81
+ end
82
+
83
+ def remove_email(email)
84
+ response = self.class.post("/user/email/remove", :query => auth_params, :body => {:email => email})
85
+ Hashie::Mash.new(response).emails
86
+ end
87
+
88
+ def keys
89
+ response = self.class.get("/user/keys", :query => auth_params)
90
+ Hashie::Mash.new(response).public_keys
91
+ end
92
+
93
+ def add_key(title, key)
94
+ response = self.class.post("/user/key/add", :query => auth_params, :body => {:title => title, :key => key})
95
+ Hashie::Mash.new(response).public_keys
96
+ end
97
+
98
+ def remove_key(id)
99
+ response = self.class.post("/user/key/remove", :query => auth_params, :body => {:id => id})
100
+ Hashie::Mash.new(response).public_keys
101
+ end
102
+
103
+ # Issues
104
+
105
+ def search_issues(repo, state, q)
106
+ repo = Repo.new(repo)
107
+ response = self.class.get("/issues/search/#{repo.username}/#{repo.name}/#{state}/#{q}")
108
+ Hashie::Mash.new(response).issues
109
+ end
110
+
111
+ def issues(repo, state)
112
+ repo = Repo.new(repo)
113
+ response = self.class.get("/issues/list/#{repo.username}/#{repo.name}/#{state}")
114
+ Hashie::Mash.new(response).issues
115
+ end
116
+
117
+ def issue(repo, id)
118
+ repo = Repo.new(repo)
119
+ response = self.class.get("/issues/show/#{repo.username}/#{repo.name}/#{id}")
120
+ Hashie::Mash.new(response).issue
121
+ end
122
+
123
+ def open_issue(repo, title, body)
124
+ repo = Repo.new(repo)
125
+ response = self.class.post("/issues/open/#{repo.username}/#{repo.name}", :body => {:title => title, :body => body})
126
+ Hashie::Mash.new(response).issue
127
+ end
128
+
129
+ def close_issue(repo, number)
130
+ repo = Repo.new(repo)
131
+ response = self.class.post("/issues/close/#{repo.username}/#{repo.name}/#{number}")
132
+ Hashie::Mash.new(response).issue
133
+ end
134
+
135
+ def reopen_issue(repo, number)
136
+ repo = Repo.new(repo)
137
+ response = self.class.post("/issues/reopen/#{repo.username}/#{repo.name}/#{number}")
138
+ Hashie::Mash.new(response).issue
139
+ end
140
+
141
+ def update_issue(repo, number, title, body)
142
+ repo = Repo.new(repo)
143
+ response = self.class.post("/issues/edit/#{repo.username}/#{repo.name}/#{number}", :body => {:title => title, :body => body})
144
+ Hashie::Mash.new(response).issue
145
+ end
146
+
147
+ def labels(repo)
148
+ repo = Repo.new(repo)
149
+ response = self.class.get("/issues/labels/#{repo.username}/#{repo.name}")
150
+ Hashie::Mash.new(response).labels
151
+ end
152
+
153
+ def add_label(repo, number, label)
154
+ repo = Repo.new(repo)
155
+ response = self.class.post("/issues/label/add/#{repo.username}/#{repo.name}/#{label}/#{number}")
156
+ Hashie::Mash.new(response).labels
157
+ end
158
+
159
+ def remove_label(repo, number, label)
160
+ repo = Repo.new(repo)
161
+ response = self.class.post("/issues/label/remove/#{repo.username}/#{repo.name}/#{label}/#{number}")
162
+ Hashie::Mash.new(response).labels
163
+ end
164
+
165
+ def add_comment(repo, number, comment)
166
+ repo = Repo.new(repo)
167
+ response = self.class.post("/issues/comment/#{repo.username}/#{repo.name}/#{number}", :body => {:comment => comment})
168
+ Hashie::Mash.new(response).comment
169
+ end
170
+
171
+ # Repos
172
+
173
+ def search_repos(q)
174
+ q = CGI.escape(q)
175
+ response = self.class.get("/repos/search/#{q}")
176
+ Hashie::Mash.new(response).repositories
177
+ end
178
+
179
+ def watch(repo)
180
+ repo = Repo.new(repo)
181
+ response = self.class.post("/repos/watch/#{repo.username}/#{repo.name}", :query => auth_params)
182
+ Hashie::Mash.new(response).repository
183
+ end
184
+
185
+ def unwatch(repo)
186
+ repo = Repo.new(repo)
187
+ response = self.class.post("/repos/unwatch/#{repo.username}/#{repo.name}", :query => auth_params)
188
+ Hashie::Mash.new(response).repository
189
+ end
190
+
191
+ def fork(repo)
192
+ repo = Repo.new(repo)
193
+ response = self.class.post("/repos/fork/#{repo.username}/#{repo.name}", :query => auth_params)
194
+ Hashie::Mash.new(response).repository
195
+ end
196
+
197
+ # :name, :description, :homepage, :public
198
+ def create(options)
199
+ response = self.class.post("/repos/create", :query => auth_params, :body => options)
200
+ Hashie::Mash.new(response).repository
201
+ end
202
+
203
+ def delete(repo, delete_token={})
204
+ repo = Repo.new(repo)
205
+ response = self.class.post("/repos/delete/#{repo.name}", :query => auth_params, :body => {:delete_token => delete_token})
206
+ Hashie::Mash.new(response).repository
207
+ end
208
+
209
+ def confirm_delete(repo, delete_token)
210
+ delete(repo, delete_token)
211
+ end
212
+
213
+ def set_private(repo)
214
+ repo = Repo.new(repo)
215
+ response = self.class.post("/repos/set/private/#{repo.name}", :query => auth_params)
216
+ Hashie::Mash.new(response).repository
217
+ end
218
+
219
+ def set_public(repo)
220
+ repo = Repo.new(repo)
221
+ response = self.class.post("/repos/set/public/#{repo.name}", :query => auth_params)
222
+ Hashie::Mash.new(response).repository
223
+ end
224
+
225
+ def deploy_keys(repo)
226
+ repo = Repo.new(repo)
227
+ response = self.class.get("/repos/keys/#{repo.name}", :query => auth_params)
228
+ Hashie::Mash.new(response).public_keys
229
+ end
230
+
231
+ def add_deploy_key(repo, key, title='')
232
+ repo = Repo.new(repo)
233
+ response = self.class.post("/repos/key/#{repo.name}/add", :query => auth_params, :body => {:title => title, :key => key})
234
+ Hashie::Mash.new(response).public_keys
235
+ end
236
+
237
+ def remove_deploy_key(repo, id)
238
+ repo = Repo.new(repo)
239
+ response = self.class.post("/repos/key/#{repo.name}/remove", :query => auth_params, :body => {:id => id})
240
+ Hashie::Mash.new(response).public_keys
241
+ end
242
+
243
+ def collaborators(repo)
244
+ repo = Repo.new(repo)
245
+ response = self.class.post("/repos/show/#{repo.username}/#{repo.name}/collaborators", :query => auth_params)
246
+ Hashie::Mash.new(response).collaborators
247
+ end
248
+
249
+ def contributors(repo)
250
+ repo = Repo.new(repo)
251
+ response = self.class.get("/repos/show/#{repo.username}/#{repo.name}/contributors")
252
+ Hashie::Mash.new(response).contributors
253
+ end
254
+
255
+ def repo(repo)
256
+ repo = Repo.new(repo)
257
+ response = self.class.get("/repos/show/#{repo.username}/#{repo.name}", :query => auth_params)
258
+ Hashie::Mash.new(response).repository
259
+ end
260
+
261
+ # pass options without the "values[x]" descriped in the API docs:
262
+ # set_repo_info('user/repo', :description => "hey!", :has_wiki => false)
263
+ def set_repo_info(repo, options)
264
+ repo = Repo.new(repo)
265
+ # post body needs to be "values[has_wiki]=false"
266
+ response = self.class.post("/repos/show/#{repo.username}/#{repo.name}",
267
+ :body => options.keys.reduce({}) { |a,v| a["values[#{v}]"] = options[v]; a }.merge(auth_params))
268
+ Hashie::Mash.new(response).repository
269
+ end
270
+
271
+ def list_repos(username = nil)
272
+ if username.nil? && !@login.nil?
273
+ username = login
274
+ elsif username.nil?
275
+ raise ArgumentError, 'you must provide a username'
276
+ end
277
+ response = self.class.get("/repos/show/#{username}", :query => auth_params)
278
+ Hashie::Mash.new(response).repositories
279
+ end
280
+
281
+ def add_collaborator(repo, collaborator)
282
+ repo = Repo.new(repo)
283
+ response = self.class.post("/repos/collaborators/#{repo.name}/add/#{collaborator}", :query => auth_params)
284
+ Hashie::Mash.new(response).collaborators
285
+ end
286
+
287
+ def remove_collaborator(repo, collaborator)
288
+ repo = Repo.new(repo)
289
+ response = self.class.post("/repos/collaborators/#{repo.name}/remove/#{collaborator}", :query => auth_params)
290
+ Hashie::Mash.new(response).collaborators
291
+ end
292
+
293
+ def network(repo)
294
+ repo = Repo.new(repo)
295
+ response = self.class.get("/repos/show/#{repo.username}/#{repo.name}/network")
296
+ Hashie::Mash.new(response).network
297
+ end
298
+
299
+ def languages(repo)
300
+ repo = Repo.new(repo)
301
+ response = self.class.get("/repos/show/#{repo.username}/#{repo.name}/languages")
302
+ Hashie::Mash.new(response).languages
303
+ end
304
+
305
+ def tags(repo)
306
+ repo = Repo.new(repo)
307
+ response = self.class.get("/repos/show/#{repo.username}/#{repo.name}/tags")
308
+ Hashie::Mash.new(response).tags
309
+ end
310
+
311
+ def branches(repo)
312
+ repo = Repo.new(repo)
313
+ response = self.class.get("/repos/show/#{repo.username}/#{repo.name}/branches", :query => auth_params)
314
+ Hashie::Mash.new(response).branches
315
+ end
316
+
317
+ # Network
318
+
319
+ def network_meta(repo)
320
+ repo = Repo.new(repo)
321
+ response = self.class.get("http://github.com/#{repo.username}/#{repo.name}/network_meta")
322
+ Hashie::Mash.new(response)
323
+ end
324
+
325
+ def network_data(repo, nethash)
326
+ repo = Repo.new(repo)
327
+ response = self.class.get("http://github.com/#{repo.username}/#{repo.name}/network_data_chunk", :query => {:nethash => nethash})
328
+ Hashie::Mash.new(response).commits
329
+ end
330
+
331
+ # Trees
332
+
333
+ def tree(repo, sha)
334
+ repo = Repo.new(repo)
335
+ response = self.class.get("http://github.com/api/v2/json/tree/show/#{repo.username}/#{repo.name}/#{sha}", :query => auth_params)
336
+ Hashie::Mash.new(response).tree
337
+ end
338
+
339
+ def blob(repo, sha, path)
340
+ repo = Repo.new(repo)
341
+ response = self.class.get("http://github.com/api/v2/json/blob/show/#{repo.username}/#{repo.name}/#{sha}/#{path}", :query => auth_params)
342
+ Hashie::Mash.new(response).blob
343
+ end
344
+
345
+ def raw(repo, sha)
346
+ repo = Repo.new(repo)
347
+ response = self.class.get("http://github.com/api/v2/yaml/blob/show/#{repo.username}/#{repo.name}/#{sha}", :query => auth_params)
348
+ response.body
349
+ end
350
+
351
+ # Commits
352
+
353
+ def list_commits(repo, branch="master")
354
+ repo = Repo.new(repo)
355
+ response = self.class.get("http://github.com/api/v2/json/commits/list/#{repo.username}/#{repo.name}/#{branch}")
356
+ Hashie::Mash.new(response).commits
357
+ end
358
+
359
+ def commit(repo, sha)
360
+ repo = Repo.new(repo)
361
+ response = self.class.get("http://github.com/api/v2/json/commits/show/#{repo.username}/#{repo.name}/#{sha}")
362
+ Hashie::Mash.new(response).commit
363
+ end
364
+
365
+ def public_timeline(username = nil)
366
+ username ||= @login
367
+ if username.nil?
368
+ path = "http://github.com/timeline.json"
369
+ else
370
+ path = "http://github.com/#{username}.json"
371
+ end
372
+ response = self.class.get(path)
373
+ response.map{|item| Hashie::Mash.new(item)}
374
+ end
375
+
376
+ def timeline
377
+ response = self.class.get("http://github.com/#{@login}.private.json", :query => auth_params)
378
+ response.map{|item| Hashie::Mash.new(item)}
379
+ end
380
+
381
+ private
382
+
383
+ def auth_params
384
+ @token.nil? ? {} : {:login => @login, :token => @token}
385
+ end
386
+
387
+ def self.get(*args); handle_response super end
388
+ def self.post(*args); handle_response super end
389
+
390
+ def self.handle_response(response)
391
+ case response.code
392
+ when 401; raise Unauthorized.new
393
+ when 403; raise RateLimitExceeded.new
394
+ when 404; raise NotFound.new
395
+ when 400...500; raise ClientError.new
396
+ when 500...600; raise ServerError.new(response.code)
397
+ else; response
398
+ end
399
+ end
400
+
401
+ end
402
+ end