octospy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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"}}