octospy 0.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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +23 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +58 -0
  8. data/Rakefile +4 -0
  9. data/bin/octospy +6 -0
  10. data/lib/cinch/plugins/management.rb +91 -0
  11. data/lib/cinch/plugins/octospy/job.rb +97 -0
  12. data/lib/cinch/plugins/octospy/recording.rb +101 -0
  13. data/lib/cinch/plugins/octospy.rb +68 -0
  14. data/lib/octospy/configurable.rb +49 -0
  15. data/lib/octospy/extensions/string.rb +39 -0
  16. data/lib/octospy/octokit/client.rb +9 -0
  17. data/lib/octospy/parser/download.rb +13 -0
  18. data/lib/octospy/parser/gist.rb +20 -0
  19. data/lib/octospy/parser/issue.rb +43 -0
  20. data/lib/octospy/parser/organization.rb +22 -0
  21. data/lib/octospy/parser/pull_request.rb +32 -0
  22. data/lib/octospy/parser/repository.rb +80 -0
  23. data/lib/octospy/parser/user.rb +37 -0
  24. data/lib/octospy/parser/wiki.rb +19 -0
  25. data/lib/octospy/parser.rb +117 -0
  26. data/lib/octospy/recordable/channel.rb +23 -0
  27. data/lib/octospy/recordable/repo.rb +16 -0
  28. data/lib/octospy/recordable.rb +26 -0
  29. data/lib/octospy/shortener.rb +48 -0
  30. data/lib/octospy/version.rb +3 -0
  31. data/lib/octospy/worker.rb +48 -0
  32. data/lib/octospy.rb +55 -0
  33. data/octospy.gemspec +37 -0
  34. data/spec/fixtures/commit_comment_event.json +59 -0
  35. data/spec/fixtures/create_event.json +21 -0
  36. data/spec/fixtures/delete_event.json +23 -0
  37. data/spec/fixtures/follow_event.json +48 -0
  38. data/spec/fixtures/fork_event.json +139 -0
  39. data/spec/fixtures/gist_event.json +27 -0
  40. data/spec/fixtures/gollum_event.json +30 -0
  41. data/spec/fixtures/issue_comment_event.json +97 -0
  42. data/spec/fixtures/issues_event.json +70 -0
  43. data/spec/fixtures/member_event.json +39 -0
  44. data/spec/fixtures/public_event.json +16 -0
  45. data/spec/fixtures/pull_request_event.json +400 -0
  46. data/spec/fixtures/pull_request_review_comment_event.json +73 -0
  47. data/spec/fixtures/push_event.json +35 -0
  48. data/spec/fixtures/team_add_event.json +51 -0
  49. data/spec/fixtures/watch_event.json +23 -0
  50. data/spec/helper.rb +79 -0
  51. data/spec/octospy/extensions/string_spec.rb +84 -0
  52. data/spec/octospy/parser/download_spec.rb +9 -0
  53. data/spec/octospy/parser/gist_spec.rb +17 -0
  54. data/spec/octospy/parser/issue_spec.rb +33 -0
  55. data/spec/octospy/parser/organization_spec.rb +33 -0
  56. data/spec/octospy/parser/pull_request_spec.rb +33 -0
  57. data/spec/octospy/parser/repository_spec.rb +101 -0
  58. data/spec/octospy/parser/user_spec.rb +44 -0
  59. data/spec/octospy/parser/wiki_spec.rb +17 -0
  60. data/spec/octospy/parser_spec.rb +63 -0
  61. data/spec/octospy/shortener_spec.rb +46 -0
  62. data/spec/support/shared_context.rb +60 -0
  63. metadata +345 -0
@@ -0,0 +1,22 @@
1
+ module Octospy
2
+ class Parser
3
+ module Organization
4
+ def parse_team_add_event
5
+ {
6
+ status: "add team",
7
+ title: @event.payload.team.name
8
+ }
9
+ end
10
+
11
+ def parse_member_event
12
+ user = @event.payload.member
13
+
14
+ {
15
+ status: "#{@event.payload.action} member",
16
+ title: user.login,
17
+ link: "#{Octokit.web_endpoint}/#{user.login}"
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ module Octospy
2
+ class Parser
3
+ module PullRequest
4
+ def parse_pull_request_event
5
+ {
6
+ status: "#{@event.payload.action} pull request ##{@event.payload.number}",
7
+ title: @event.payload.pull_request.title,
8
+ body: "#{@event.payload.pull_request.body}".split_lfbl,
9
+ link: @event.payload.pull_request.html_url
10
+ }
11
+ end
12
+
13
+ def parse_pull_request_review_comment_event
14
+ if @event.payload.comment.pull_request_url
15
+ url = @event.payload.comment.pull_request_url
16
+ pull_id = url.match(/\/pulls\/([0-9]+)/)[1]
17
+ pull = Octokit.pull(@event.repo.name, pull_id)
18
+ title = "#{pull.title}: #{@event.payload.comment.path}"
19
+ else
20
+ title = @event.payload.comment.path
21
+ end
22
+
23
+ {
24
+ status: "commented on pull request",
25
+ title: title,
26
+ body: "#{@event.payload.comment.body}".split_lfbl,
27
+ link: @event.payload.comment._links.html.href
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,80 @@
1
+ module Octospy
2
+ class Parser
3
+ module Repository
4
+ def parse_commit_comment_event
5
+ {
6
+ status: "commented on commit",
7
+ title: "#{@event.payload.comment.path}",
8
+ body: "#{@event.payload.comment.body}".split_lfbl,
9
+ link: @event.payload.comment.html_url
10
+ }
11
+ end
12
+
13
+ def parse_push_event
14
+ body = []
15
+ @event.payload.commits.each do |commit|
16
+ verbose_commit = Octokit.commit(@event.repo.name, commit.sha)
17
+ name = "#{verbose_commit.author ? verbose_commit.author.login : commit.author.name}"
18
+ link = "#{Octokit.web_endpoint}/#{@event.repo.name}/commit/#{commit.sha}"
19
+ line = "#{name.colorize_for_irc.silver}: #{commit.message}"
20
+ line << " - #{link.shorten.colorize_for_irc.blue}"
21
+ body = body + "#{line}".split_lfbl
22
+ end
23
+
24
+ {
25
+ status: "pushed to #{@event.payload.ref.gsub('refs/heads/', '')}",
26
+ body: body,
27
+ link: "#{Octokit.web_endpoint}/#{@event.repo.name}",
28
+ notice_body: true
29
+ }
30
+ end
31
+
32
+ def parse_create_event
33
+ if @event.payload.ref_type.eql? 'repository'
34
+ title = @event.repo.name
35
+ title = "#{title}: #{@event.payload.description}" if @event.payload.description
36
+ {
37
+ status: "created repository",
38
+ title: title,
39
+ link: "#{Octokit.web_endpoint}/#{@event.repo.name}",
40
+ repository: nil
41
+ }
42
+ else
43
+ {
44
+ status: "created #{@event.payload.ref_type}:#{@event.payload.ref}",
45
+ title: @event.payload.description,
46
+ link: "#{Octokit.web_endpoint}/#{@event.repo.name}"
47
+ }
48
+ end
49
+ end
50
+
51
+ def parse_delete_event
52
+ {
53
+ status: "deleted #{@event.payload.ref_type}:#{@event.payload.ref}",
54
+ link: "#{Octokit.web_endpoint}/#{@event.repo.name}"
55
+ }
56
+ end
57
+
58
+ def parse_fork_event
59
+ forkee_name = @event.payload.forkee.full_name
60
+ forkee_lang = @event.payload.forkee.language
61
+ {
62
+ status: "forked #{forkee_name} [#{forkee_lang}]",
63
+ title: @event.payload.forkee.description,
64
+ link: @event.payload.forkee.html_url
65
+ }
66
+ end
67
+
68
+ def parse_public_event
69
+ {
70
+ status: "published #{@event.repo.name}",
71
+ link: "#{Octokit.web_endpoint}/#{@event.repo.name}"
72
+ }
73
+ end
74
+
75
+ def parse_fork_apply_event
76
+ {}
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,37 @@
1
+ module Octospy
2
+ class Parser
3
+ module User
4
+ def parse_watch_event
5
+ {
6
+ status: "#{@event.payload.action} repository",
7
+ title: @event.repo.name,
8
+ link: "#{Octokit.web_endpoint}/#{@event.repo.name}",
9
+ repository: nil
10
+ }
11
+ end
12
+
13
+ def parse_follow_event
14
+ user = @event.payload.target
15
+
16
+ title = user.login
17
+ title = "#{title} (#{user.name})" if user.name && user.name != ''
18
+ profile = ["#{'repos'.colorize_for_irc.silver}: #{user.public_repos}"]
19
+ profile << "#{'followers'.colorize_for_irc.silver}: #{user.followers}"
20
+ profile << "#{'following'.colorize_for_irc.silver}: #{user.following}"
21
+ profile << "#{'location'.colorize_for_irc.silver}: #{user.location && user.location != '' ? user.location : '-'}"
22
+ profile << "#{'company'.colorize_for_irc.silver}: #{user.company && user.company != '' ? user.company : '-'}"
23
+ profile << "#{'bio'.colorize_for_irc.silver}: #{user.bio && user.bio != '' ? user.bio : '-'}"
24
+ profile << "#{'blog'.colorize_for_irc.silver}: #{user.blog && user.blog != '' ? user.blog : '-'}"
25
+
26
+ {
27
+ status: "followed",
28
+ title: title,
29
+ body: profile.join(', '),
30
+ link: "#{Octokit.web_endpoint}/#{user.login}",
31
+ repository: nil,
32
+ notice: true
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ module Octospy
2
+ class Parser
3
+ module Wiki
4
+ def parse_gollum_event
5
+ action = @event.payload.pages[0].action
6
+ title = @event.payload.pages[0].title
7
+ sha = @event.payload.pages[0].sha[0,6]
8
+ url = @event.payload.pages[0].html_url
9
+ url = "#{url}/_compare/#{sha}%5E...#{sha}" if action == 'edited'
10
+
11
+ {
12
+ status: "#{action} the #{@event.repo.name} wiki",
13
+ title: title,
14
+ link: url
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,117 @@
1
+ require 'octospy/extensions/string'
2
+ require 'octospy/parser/user'
3
+ require 'octospy/parser/organization'
4
+ require 'octospy/parser/repository'
5
+ require 'octospy/parser/issue'
6
+ require 'octospy/parser/pull_request'
7
+ require 'octospy/parser/wiki'
8
+ require 'octospy/parser/download'
9
+ require 'octospy/parser/gist'
10
+
11
+ module Octospy
12
+ class Parser
13
+ include User
14
+ include Organization
15
+ include Repository
16
+ include Issue
17
+ include PullRequest
18
+ include Wiki
19
+ include Download
20
+ include Gist
21
+
22
+ def initialize(event)
23
+ @event = event
24
+ end
25
+
26
+ def default_params
27
+ {
28
+ notice_body: false,
29
+ none_repository: false,
30
+ nick: '',
31
+ repository: '',
32
+ status: '',
33
+ link: '',
34
+ title: '',
35
+ body: []
36
+ }
37
+ end
38
+
39
+ def parse
40
+ hash = default_params.merge(
41
+ nick: @event.actor.login,
42
+ repository: @event.repo.name
43
+ )
44
+ hash.merge! self.send(parsing_method)
45
+ build(hash)
46
+ end
47
+
48
+ def build(hash)
49
+ header = "#{hash[:nick].colorize_for_irc.bold} #{colorize_to hash[:status]}"
50
+
51
+ if hash[:repository] && !hash[:repository].empty?
52
+ header = "(#{hash[:repository]}) #{header}"
53
+ end
54
+
55
+ if hash[:title] && !hash[:title].empty?
56
+ header = "#{header} #{hash[:title]}"
57
+ end
58
+
59
+ if hash[:link] && !hash[:link].empty?
60
+ header = "#{header} - #{hash[:link].shorten.colorize_for_irc.blue}"
61
+ end
62
+
63
+ body = if hash[:body].length > 20
64
+ body_footer = hash[:body][-3..-1]
65
+ body = hash[:body][0...15]
66
+ body << '-----8<----- c u t -----8<-----'
67
+ body + body_footer
68
+ else
69
+ hash[:body]
70
+ end
71
+
72
+ [
73
+ {
74
+ nick: hash[:nick],
75
+ type: :notice,
76
+ message: header
77
+ },
78
+ {
79
+ nick: hash[:nick],
80
+ type: hash[:notice_body] ? :notice : :private,
81
+ message: body
82
+ }
83
+ ]
84
+ end
85
+
86
+ def parsing_method
87
+ "Parse#{@event.type}".underscore.to_sym
88
+ end
89
+
90
+ def color_table
91
+ {
92
+ default: :aqua,
93
+ created: :pink,
94
+ commented: :yellow,
95
+ pushed: :lime,
96
+ forked: :orange,
97
+ closed: :brown,
98
+ deleted: :red,
99
+ edited: :green,
100
+ published: :blue,
101
+ started: :rainbow,
102
+ followed: :seven_eleven
103
+ }
104
+ end
105
+
106
+ def behavior_color(string)
107
+ color_table.each { |word, color|
108
+ return color if string.include? "#{word}"
109
+ }
110
+ color_table[:default]
111
+ end
112
+
113
+ def colorize_to(string)
114
+ string.colorize_for_irc.send(behavior_color string).to_s
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,23 @@
1
+ require 'octospy/recordable/repo'
2
+
3
+ module Octospy
4
+ module Recordable
5
+ class Channel
6
+ def initialize(name)
7
+ @name = name.to_sym
8
+ end
9
+
10
+ def repos
11
+ @repos ||= []
12
+ end
13
+
14
+ def add_repo(name)
15
+ @repos << name if repos.empty? || !repos.include?(name)
16
+ end
17
+
18
+ def del_repo(name)
19
+ @repos.delete(name.to_sym) if !repos.empty? && repos.include?(name)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module Octospy
2
+ module Recordable
3
+ class Repo
4
+ attr_accessor :name, :last_event_id
5
+
6
+ def initialize(name)
7
+ @name = name.to_sym
8
+ @last_event_id = nil
9
+ end
10
+
11
+ def clear!
12
+ @last_event_id = nil
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ require 'octospy/recordable/channel'
2
+ require 'octospy/recordable/repo'
3
+
4
+ module Octospy
5
+ module Recordable
6
+ def channels
7
+ @channels ||= {}
8
+ end
9
+
10
+ def add_channel(name)
11
+ @channels.merge!(:"#{name}" => Channel.new(name)) unless channels.has_key?(name.to_sym)
12
+ end
13
+
14
+ def del_channel(name)
15
+ @channels.delete(name.to_sym) if channels.has_key?(name)
16
+ end
17
+
18
+ def channel(name)
19
+ if channels.has_key?(name.to_sym)
20
+ @channels[name.to_sym]
21
+ else
22
+ Channel.new(name)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ module Octospy
5
+ module Shortener
6
+ class << self
7
+ def github_shortener_endpoint
8
+ 'http://git.io'
9
+ end
10
+
11
+ def shorten_by_github(url)
12
+ conn = Faraday.new(url: self.github_shortener_endpoint) do |f|
13
+ f.request :url_encoded
14
+ f.adapter Faraday.default_adapter
15
+ end
16
+
17
+ res = conn.post '/', { url: url }
18
+ res.headers && res.headers.key?('location') ? res.headers['location'] : url
19
+ rescue
20
+ url
21
+ end
22
+
23
+ def google_shortener_endpoint
24
+ 'https://www.googleapis.com'
25
+ end
26
+
27
+ def shorten_by_google(url)
28
+ conn = Faraday.new(url: self.google_shortener_endpoint) do |f|
29
+ f.response :mashify
30
+ f.response :json
31
+ f.request :url_encoded
32
+ f.request :json
33
+ f.adapter Faraday.default_adapter
34
+ end
35
+
36
+ res = conn.post do |req|
37
+ req.url '/urlshortener/v1/url'
38
+ req.headers['Content-Type'] = 'application/json'
39
+ req.body = "{ \"longUrl\": \"#{url}\" }"
40
+ end
41
+
42
+ res.body && res.body.respond_to?(:id) ? res.body.id : url
43
+ rescue
44
+ url
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,3 @@
1
+ module Octospy
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,48 @@
1
+ module Octospy
2
+ class Worker
3
+ attr_reader :thread
4
+
5
+ def initialize(repositories, &block)
6
+ @repositories = repositories
7
+ @block = block
8
+ @last_event_id = nil
9
+ thread_loop
10
+ end
11
+
12
+ def thread_loop
13
+ @thread = Thread.start do
14
+ loop do
15
+ begin
16
+ watch_repositories
17
+ sleep 30
18
+ rescue => e
19
+ puts e.message
20
+ sleep 30
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ def events
27
+ @repositories.each_with_object([]) do |repo, arr|
28
+ arr.concat ::Octokit.repository_events(repo)
29
+ end
30
+ end
31
+
32
+ def watch_repositories
33
+ events.sort_by(&:id).reverse_each { |event|
34
+ if @last_event_id.nil?
35
+ next if Time.now.utc - (60*60) >= event.created_at
36
+ else
37
+ next if @last_event_id >= event.id
38
+ end
39
+
40
+ parsed_event = Octospy.parse(event)
41
+ next unless parsed_event
42
+
43
+ @last_event_id = event.id
44
+ parsed_event.each { |p| @block.call p[:message] }
45
+ }
46
+ end
47
+ end
48
+ end
data/lib/octospy.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'awesome_print'
2
+ require 'cinch'
3
+ require 'octokit'
4
+ require 'dotenv'
5
+
6
+ require 'cinch/plugins/management'
7
+ require 'cinch/plugins/octospy'
8
+ require 'octospy/configurable'
9
+ require 'octospy/recordable'
10
+ require 'octospy/parser'
11
+ require 'octospy/worker'
12
+ require 'octospy/octokit/client'
13
+
14
+ module Octospy
15
+ class << self
16
+ include Octospy::Configurable
17
+ include Octospy::Recordable
18
+
19
+ def parse(event)
20
+ Octospy::Parser.new(event).parse
21
+ end
22
+
23
+ def worker(repositories, &block)
24
+ Octospy::Worker.new(repositories, &block)
25
+ end
26
+
27
+ def irc_bot
28
+ Octokit.configure do |c|
29
+ c.api_endpoint = Octospy.github_api_endpoint
30
+ c.web_endpoint = Octospy.github_web_endpoint
31
+ c.login = Octospy.github_login
32
+ c.access_token = Octospy.github_token
33
+ end
34
+
35
+ Cinch::Bot.new do
36
+ configure do |c|
37
+ c.server = Octospy.server
38
+ c.nick = Octospy.nick
39
+ c.channels = Octospy.channels
40
+ c.plugins.plugins = [
41
+ Cinch::Plugins::Management,
42
+ Cinch::Plugins::Octospy
43
+ ]
44
+ end
45
+ end
46
+ end
47
+
48
+ def run
49
+ self.irc_bot.start
50
+ end
51
+ end
52
+
53
+ Dotenv.load
54
+ Octospy.setup
55
+ end
data/octospy.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'octospy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "octospy"
8
+ spec.version = Octospy::VERSION
9
+ spec.authors = ["linyows"]
10
+ spec.email = ["linyows@gmail.com"]
11
+ spec.description = %q{This is IRC bot that notifies repository activity on github.}
12
+ spec.summary = %q{Octospy notifies the repository activity to an IRC channel.}
13
+ spec.homepage = "https://github.com/linyows/octospy"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'webmock'
25
+ spec.add_development_dependency 'vcr'
26
+ spec.add_development_dependency 'simplecov'
27
+ spec.add_development_dependency 'coveralls'
28
+ spec.add_development_dependency "pry"
29
+ spec.add_development_dependency "awesome_print"
30
+
31
+ spec.add_dependency "cinch"
32
+ spec.add_dependency "octokit"
33
+ spec.add_dependency "string-irc"
34
+ spec.add_dependency "faraday"
35
+ spec.add_dependency "faraday_middleware"
36
+ spec.add_dependency "dotenv"
37
+ end
@@ -0,0 +1,59 @@
1
+ {"id":"1774494665",
2
+ "type":"CommitCommentEvent",
3
+ "actor":
4
+ {"id":550256,
5
+ "login":"fromonesrc",
6
+ "gravatar_id":"f71525fec8cbb00c959afe657aa2c8fa",
7
+ "url":"https://api.github.com/users/fromonesrc",
8
+ "avatar_url":
9
+ "https://secure.gravatar.com/avatar/f71525fec8cbb00c959afe657aa2c8fa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png"},
10
+ "repo":
11
+ {"id":6049573,
12
+ "name":"boxen/our-boxen",
13
+ "url":"https://api.github.com/repos/boxen/our-boxen"},
14
+ "payload":
15
+ {"comment":
16
+ {"url":"https://api.github.com/repos/boxen/our-boxen/comments/3583654",
17
+ "html_url":
18
+ "https://github.com/boxen/our-boxen/commit/08009e9b0718869d269d9b1c48383e6e145950db#commitcomment-3583654",
19
+ "id":3583654,
20
+ "user":
21
+ {"login":"fromonesrc",
22
+ "id":550256,
23
+ "avatar_url":
24
+ "https://secure.gravatar.com/avatar/f71525fec8cbb00c959afe657aa2c8fa?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png",
25
+ "gravatar_id":"f71525fec8cbb00c959afe657aa2c8fa",
26
+ "url":"https://api.github.com/users/fromonesrc",
27
+ "html_url":"https://github.com/fromonesrc",
28
+ "followers_url":"https://api.github.com/users/fromonesrc/followers",
29
+ "following_url":
30
+ "https://api.github.com/users/fromonesrc/following{/other_user}",
31
+ "gists_url":"https://api.github.com/users/fromonesrc/gists{/gist_id}",
32
+ "starred_url":
33
+ "https://api.github.com/users/fromonesrc/starred{/owner}{/repo}",
34
+ "subscriptions_url":
35
+ "https://api.github.com/users/fromonesrc/subscriptions",
36
+ "organizations_url":"https://api.github.com/users/fromonesrc/orgs",
37
+ "repos_url":"https://api.github.com/users/fromonesrc/repos",
38
+ "events_url":
39
+ "https://api.github.com/users/fromonesrc/events{/privacy}",
40
+ "received_events_url":
41
+ "https://api.github.com/users/fromonesrc/received_events",
42
+ "type":"User"},
43
+ "position":null,
44
+ "line":null,
45
+ "path":null,
46
+ "commit_id":"08009e9b0718869d269d9b1c48383e6e145950db",
47
+ "created_at":"2013-07-08T13:22:48Z",
48
+ "updated_at":"2013-07-08T13:22:48Z",
49
+ "body":
50
+ "AFAIK that was the only problem. Please let us know if you run into anything weird so we can resolve it. "}},
51
+ "public":true,
52
+ "created_at":"2013-07-08T13:22:48Z",
53
+ "org":
54
+ {"id":1800808,
55
+ "login":"boxen",
56
+ "gravatar_id":"964fa6e7c2e05f0ae6f76063e184fd28",
57
+ "url":"https://api.github.com/orgs/boxen",
58
+ "avatar_url":
59
+ "https://secure.gravatar.com/avatar/964fa6e7c2e05f0ae6f76063e184fd28?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png"}}
@@ -0,0 +1,21 @@
1
+ {"id":"1774947291",
2
+ "type":"CreateEvent",
3
+ "actor":
4
+ {"id":25254,
5
+ "login":"visionmedia",
6
+ "gravatar_id":"f1e3ab214a976a39cfd713bc93deb10f",
7
+ "url":"https://api.github.com/users/visionmedia",
8
+ "avatar_url":
9
+ "https://secure.gravatar.com/avatar/f1e3ab214a976a39cfd713bc93deb10f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png"},
10
+ "repo":
11
+ {"id":237159,
12
+ "name":"visionmedia/express",
13
+ "url":"https://api.github.com/repos/visionmedia/express"},
14
+ "payload":
15
+ {"ref":"3.3.3",
16
+ "ref_type":"tag",
17
+ "master_branch":"master",
18
+ "description":
19
+ "Sinatra inspired web development framework for node.js -- insanely fast, flexible, and simple"},
20
+ "public":true,
21
+ "created_at":"2013-07-08T21:42:50Z"}
@@ -0,0 +1,23 @@
1
+ {"id":"1774943065",
2
+ "type":"DeleteEvent",
3
+ "actor":
4
+ {"id":262566,
5
+ "login":"jeffkaufman",
6
+ "gravatar_id":"1c43cb01fde39470cde8a1d7fd600a4f",
7
+ "url":"https://api.github.com/users/jeffkaufman",
8
+ "avatar_url":
9
+ "https://secure.gravatar.com/avatar/1c43cb01fde39470cde8a1d7fd600a4f?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png"},
10
+ "repo":
11
+ {"id":4766638,
12
+ "name":"pagespeed/ngx_pagespeed",
13
+ "url":"https://api.github.com/repos/pagespeed/ngx_pagespeed"},
14
+ "payload":{"ref":"jefftk-fix-beacon", "ref_type":"branch"},
15
+ "public":true,
16
+ "created_at":"2013-07-08T21:38:03Z",
17
+ "org":
18
+ {"id":1880112,
19
+ "login":"pagespeed",
20
+ "gravatar_id":"0736e1c30e49c94fb04060488d6dae78",
21
+ "url":"https://api.github.com/orgs/pagespeed",
22
+ "avatar_url":
23
+ "https://secure.gravatar.com/avatar/0736e1c30e49c94fb04060488d6dae78?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-org-420.png"}}