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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 47c3a44346c54c0c69fb51561b692fb4f9216304
4
+ data.tar.gz: 80c043163646771135069da36e087dc01cab75c7
5
+ SHA512:
6
+ metadata.gz: d19a444802e932594a9513605314cd665bc85274f12d9a22a5892d9902cb327ee8279979e28f0ef79f3bd468b3b7818069438bea923c20bac07533da16a6ef0d
7
+ data.tar.gz: 25694444c3dd360c39f1fa2549ca27795da1aaff97704b556502b04c2c4784f4bcf3fe4820cd962441a1f01dc150628086fde0f7996b8986bcb1d19d5d7b9ff5
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor
19
+ spec/cassettes
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,23 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+
7
+ before_install:
8
+ - gem update bundler
9
+
10
+ script:
11
+ - bundle exec rake spec
12
+
13
+ notifications:
14
+ email:
15
+ recipients:
16
+ - linyows@gmail.com
17
+ on_success: change
18
+ on_failure: always
19
+ irc:
20
+ on_success: change
21
+ on_failure: always
22
+ channels:
23
+ - "irc.freenode.org#linyows"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in octospy.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 linyows
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ Octospy
2
+ =======
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/octospy.png)][gem]
5
+ [![Build Status](https://secure.travis-ci.org/linyows/octospy.png?branch=master)][travis]
6
+ [![Dependency Status](https://gemnasium.com/linyows/octospy.png?travis)][gemnasium]
7
+ [![Code Climate](https://codeclimate.com/github/linyows/octospy.png)][codeclimate]
8
+ [![Coverage Status](https://coveralls.io/repos/linyows/octospy/badge.png?branch=master)][coveralls]
9
+
10
+ [gem]: https://rubygems.org/gems/octospy
11
+ [travis]: http://travis-ci.org/linyows/octospy
12
+ [gemnasium]: https://gemnasium.com/linyows/octospy
13
+ [codeclimate]: https://codeclimate.com/github/linyows/octospy
14
+ [coveralls]: https://coveralls.io/r/linyows/octospy
15
+
16
+ Octospy notifies the repository activity to an IRC channel.
17
+
18
+ <img src="http://octodex.github.com/images/daftpunktocat-thomas.gif" width="300">
19
+ <img src="http://octodex.github.com/images/daftpunktocat-guy.gif" width="300">
20
+
21
+ Installation
22
+ ------------
23
+
24
+ Add this line to your application's Gemfile:
25
+
26
+ gem 'octospy'
27
+
28
+ And then execute:
29
+
30
+ $ bundle
31
+
32
+ Or install it yourself as:
33
+
34
+ $ gem install octospy
35
+
36
+ Usage
37
+ -----
38
+
39
+ TODO: Write usage instructions here
40
+
41
+ Contributing
42
+ ------------
43
+
44
+ 1. Fork it
45
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
46
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
47
+ 4. Push to the branch (`git push origin my-new-feature`)
48
+ 5. Create new Pull Request
49
+
50
+ Author
51
+ ------
52
+
53
+ - [linyows](https://github.com/linyows)
54
+
55
+ License
56
+ -------
57
+
58
+ MIT
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
data/bin/octospy ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ require "#{lib}/octospy"
5
+
6
+ Octospy.run
@@ -0,0 +1,91 @@
1
+ module Cinch
2
+ module Plugins
3
+ class Management
4
+ include Cinch::Plugin
5
+
6
+ match(/plugin load (\S+)(?: (\S+))?/, method: :load_plugin)
7
+ match(/plugin unload (\S+)/, method: :unload_plugin)
8
+ match(/plugin reload (\S+)(?: (\S+))?/, method: :reload_plugin)
9
+ match(/plugin set (\S+) (\S+) (.+)$/, method: :set_option)
10
+ def load_plugin(m, plugin, mapping)
11
+ mapping ||= plugin.gsub(/(.)([A-Z])/) { |_|
12
+ $1 + "_" + $2
13
+ }.downcase # we downcase here to also catch the first letter
14
+
15
+ file_name = "lib/cinch/plugins/#{mapping}.rb"
16
+ unless File.exist?(file_name)
17
+ m.reply "Could not load #{plugin} because #{file_name} does not exist."
18
+ return
19
+ end
20
+
21
+ begin
22
+ load(file_name)
23
+ rescue
24
+ m.reply "Could not load #{plugin}."
25
+ raise
26
+ end
27
+
28
+ begin
29
+ const = Cinch::Plugins.const_get(plugin)
30
+ rescue NameError
31
+ m.reply "Could not load #{plugin} because no matching class was found."
32
+ return
33
+ end
34
+
35
+ @bot.plugins.register_plugin(const)
36
+ m.reply "Successfully loaded #{plugin}"
37
+ end
38
+
39
+ def unload_plugin(m, plugin)
40
+ begin
41
+ plugin_class = Cinch::Plugins.const_get(plugin)
42
+ rescue NameError
43
+ m.reply "Could not unload #{plugin} because no matching class was found."
44
+ return
45
+ end
46
+
47
+ @bot.plugins.select {|p| p.class == plugin_class}.each do |p|
48
+ @bot.plugins.unregister_plugin(p)
49
+ end
50
+
51
+ ## FIXME not doing this at the moment because it'll break
52
+ ## plugin options. This means, however, that reloading a
53
+ ## plugin is relatively dirty: old methods will not be removed
54
+ ## but only overwritten by new ones. You will also not be able
55
+ ## to change a classes superclass this way.
56
+ # Cinch::Plugins.__send__(:remove_const, plugin)
57
+
58
+ # Because we're not completely removing the plugin class,
59
+ # reset everything to the starting values.
60
+ plugin_class.hooks.clear
61
+ plugin_class.matchers.clear
62
+ plugin_class.listeners.clear
63
+ plugin_class.timers.clear
64
+ plugin_class.ctcps.clear
65
+ plugin_class.react_on = :message
66
+ plugin_class.plugin_name = nil
67
+ plugin_class.help = nil
68
+ plugin_class.prefix = nil
69
+ plugin_class.suffix = nil
70
+ plugin_class.required_options.clear
71
+
72
+ m.reply "Successfully unloaded #{plugin}"
73
+ end
74
+
75
+ def reload_plugin(m, plugin, mapping)
76
+ unload_plugin(m, plugin)
77
+ load_plugin(m, plugin, mapping)
78
+ end
79
+
80
+ def set_option(m, plugin, option, value)
81
+ begin
82
+ const = Cinch::Plugins.const_get(plugin)
83
+ rescue NameError
84
+ m.reply "Could not set plugin option for #{plugin} because no matching class was found."
85
+ return
86
+ end
87
+ @bot.config.plugins.options[const][option.to_sym] = eval(value)
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,97 @@
1
+ require 'octospy'
2
+
3
+ module Cinch
4
+ module Plugins
5
+ class Octospy
6
+ module Job
7
+ def self.included(base)
8
+ base.class_eval do
9
+ match('job start', method: :start_with_message)
10
+ match('job stop', method: :stop_with_message)
11
+ match('job restart', method: :restart_with_message)
12
+ end
13
+
14
+ Channel.class_eval do
15
+ attr_accessor :job_thread, :last_github_event_id
16
+
17
+ define_method(:job_thread_alive?) do
18
+ @job_thread && @job_thread.alive?
19
+ end
20
+ end
21
+ end
22
+
23
+ def start_with_message(m)
24
+ if m.channel.job_thread_alive?
25
+ m.reply 'I have already started'
26
+ return
27
+ end
28
+
29
+ start(m)
30
+ m.reply 'I started'
31
+ end
32
+
33
+ def stop_with_message(m)
34
+ unless m.channel.job_thread_alive?
35
+ m.reply 'I have not started'
36
+ return
37
+ end
38
+
39
+ stop(m)
40
+ m.reply 'I stopped'
41
+ end
42
+
43
+ def restart_with_message(m)
44
+ if restart(m)
45
+ m.reply 'I restarted'
46
+ else
47
+ m.reply 'I have not started'
48
+ end
49
+ end
50
+
51
+ def start(m)
52
+ repos = ::Octospy.channel(m.channel.name).repos
53
+ channel = m.channel
54
+
55
+ worker = ::Octospy.worker(repos) do |message|
56
+ case message.class.name
57
+ when 'String'
58
+ message.each_char.each_slice(512) do |string|
59
+ channel.notice string.join
60
+ sleep 1
61
+ end
62
+ when 'Array'
63
+ message.each do |line|
64
+ # maximum line length 512
65
+ # http://www.mirc.com/rfc2812.html
66
+ line.each_char.each_slice(512) do |string|
67
+ channel.notice string.join
68
+ sleep 1
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ m.channel.job_thread = worker.thread
75
+ end
76
+
77
+ def stop(m)
78
+ m.channel.job_thread.kill
79
+ end
80
+
81
+ def restart(m)
82
+ if m.channel.job_thread_alive?
83
+ restart!(m)
84
+ true
85
+ else
86
+ false
87
+ end
88
+ end
89
+
90
+ def restart!(m)
91
+ stop(m) if m.channel.job_thread_alive?
92
+ start(m)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,101 @@
1
+ module Cinch
2
+ module Plugins
3
+ class Octospy
4
+ module Recording
5
+ def self.included(base)
6
+ base.class_eval do
7
+ match(/watch ([\w\-\.]+)\/([\w\-\.]+)/, method: :watch_repository)
8
+ match(/unwatch ([\w\-\.]+)\/([\w\-\.]+)/, method: :unwatch_repository)
9
+ match(/watch ([\w\-\.]+)/, method: :watch_repositories)
10
+ match(/unwatch ([\w\-\.]+)/, method: :unwatch_repositories)
11
+ match(/show watched( repos(itories)?)?/, method: :show_watched_repositories)
12
+ end
13
+ end
14
+
15
+ def watch_repository(m, owner, project)
16
+ repo = "#{owner}/#{project}"
17
+
18
+ unless ::Octokit.repository?(repo)
19
+ m.reply "Sorry, '#{repo}' not found"
20
+ return
21
+ end
22
+
23
+ ::Octospy.add_channel m.channel.name
24
+ ::Octospy.channel(m.channel.name).add_repo(repo)
25
+
26
+ restart(m)
27
+ m.reply "I started to watch the #{repo} events"
28
+ end
29
+
30
+ def watch_repositories(m, owner)
31
+ user = ::Octokit.user?(owner)
32
+
33
+ unless user
34
+ m.reply "Sorry, '#{owner}' not found"
35
+ return
36
+ end
37
+
38
+ ::Octospy.add_channel m.channel.name
39
+ method = "#{'org_' if user.type == 'Organization'}repos".to_sym
40
+ repos = ::Octokit.send(method, owner).map { |repo|
41
+ ::Octospy.channel(m.channel.name).add_repo(repo.full_name)
42
+ repo.full_name
43
+ }
44
+
45
+ if repos.count > 0
46
+ m.reply "I started to watch events of #{repos.count} repositories"
47
+ restart(m)
48
+ end
49
+ end
50
+
51
+ def unwatch_repository(m, owner, project)
52
+ repo = "#{owner}/#{project}"
53
+
54
+ unless ::Octokit.repository?(repo)
55
+ m.reply "Sorry, '#{repo}' not found"
56
+ return
57
+ end
58
+
59
+ ::Octospy.channel(m.channel.name).remove_repo(repo)
60
+
61
+ restart(m)
62
+ m.reply "I stopped to watch the #{repo} events"
63
+ end
64
+
65
+ def unwatch_repositories(m, owner)
66
+ repos = ::Octospy.channel(m.channel.name).repos.each_with_object([]) do |repo, obj|
67
+ next unless repo.split('/').first == owner
68
+ ::Octospy.channel(m.channel.name).remove_repo(repo)
69
+ opj << repo
70
+ end
71
+
72
+ if repos.count > 0
73
+ if ::Octospy.channel(m.channel.name).repos.count > 0
74
+ m.reply "stopped to watch events of #{repos.count} repositories"
75
+ restart(m)
76
+ else
77
+ m.reply "stopped job so no watched repository"
78
+ stop(m)
79
+ end
80
+ end
81
+ end
82
+
83
+ def unwatch_all(m)
84
+ end
85
+
86
+ def show_watched_repositories(m)
87
+ channel = ::Octospy.channel(m.channel.name)
88
+
89
+ if channel.nil? || channel.repos.nil? || !channel.repos
90
+ m.reply 'nothing!'
91
+ return
92
+ end
93
+
94
+ channel.repos.each.with_index(1) do |repo, i|
95
+ m.reply "#{i} #{repo}"
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,68 @@
1
+ require 'cinch/plugins/octospy/recording'
2
+ require 'cinch/plugins/octospy/job'
3
+
4
+ module Cinch
5
+ module Plugins
6
+ class Octospy
7
+ include Cinch::Plugin
8
+ include Octospy::Recording
9
+ include Octospy::Job
10
+
11
+ set :prefix, ->(m) { %r(^#{Regexp.escape "#{m.bot.nick}: "}) }
12
+
13
+ match(/hello|hi|hey/, method: :greet)
14
+ match('ping', method: :pong)
15
+ match('rename', method: :rename)
16
+ match(/join (.+)/, method: :join)
17
+ match(/part(?: (.+))?/, method: :part)
18
+ match(/show status/, method: :show_status)
19
+ match(/show commands/, method: :show_commands)
20
+
21
+ listen_to :invite, method: :join_on_invite
22
+
23
+ def greet(m)
24
+ m.reply "hi #{m.user.nick}"
25
+ end
26
+
27
+ def pong(m)
28
+ m.reply "#{m.user.nick}: pong"
29
+ end
30
+
31
+ def rename(m)
32
+ @bot.nick += '_'
33
+ end
34
+
35
+ def join(m, channel)
36
+ ch = "##{channel.gsub('#', '')}"
37
+ Channel(ch).join
38
+ m.reply "#{ch} joined!"
39
+ end
40
+
41
+ def part(m, channel)
42
+ channel ||= m.channel
43
+ if channel
44
+ ch = "##{channel.gsub('#', '')}"
45
+ Channel(ch).part
46
+ m.reply "#{ch} parted!" unless ch == m.channel
47
+ end
48
+ end
49
+
50
+ def show_status(m)
51
+ @bot.channels.each.with_index(1) do |channel, i|
52
+ number = ::Octospy.channel(channel).repos.count
53
+ m.reply "#{"%02d" % i} #{channel}: #{number} repo"
54
+ end
55
+ end
56
+
57
+ def show_commands(m)
58
+ # @matchers.each.with_index(1) do |matcher, i|
59
+ # m.reply "#{"%02d" % i} #{matcher}"
60
+ # end
61
+ end
62
+
63
+ def join_on_invite(m)
64
+ Channel(m.channel).join
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,49 @@
1
+ module Octospy
2
+ module Configurable
3
+ OPTIONS_KEYS = %i(
4
+ channels
5
+ server
6
+ nick
7
+ github_api_endpoint
8
+ github_web_endpoint
9
+ github_login
10
+ github_token
11
+ ).freeze
12
+
13
+ attr_accessor(*OPTIONS_KEYS)
14
+
15
+ class << self
16
+ def keys
17
+ @keys ||= OPTIONS_KEYS
18
+ end
19
+ end
20
+
21
+ DEFAULT_GITHUB_API_ENDPOINT = ENV['GITHUB_API_ENDPOINT'] || 'https://api.github.com'
22
+ DEFAULT_GITHUB_WEB_ENDPOINT = ENV['GITHUB_WEB_ENDPOINT'] || 'https://github.com'
23
+ DEFAULT_NICK = ENV['NICK'] || 'octospy'
24
+
25
+ def configure
26
+ yield self
27
+ end
28
+
29
+ def options
30
+ Hash[Octospy::Configurable.keys.map{ |key|
31
+ [key, instance_variable_get(:"@#{key}")]
32
+ }]
33
+ end
34
+
35
+ def setup
36
+ @github_api_endpoint = DEFAULT_GITHUB_API_ENDPOINT
37
+ @github_web_endpoint = DEFAULT_GITHUB_WEB_ENDPOINT
38
+ @nick = DEFAULT_NICK
39
+ @channels = if ENV['CHANNELS']
40
+ ENV['CHANNELS'].gsub(/\s|#/, '').split(',').map { |ch| "##{ch}" }
41
+ else
42
+ ''
43
+ end
44
+ @server = ENV['SERVER']
45
+ @github_login = ENV['GITHUB_LOGIN']
46
+ @github_token = ENV['GITHUB_TOKEN']
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ require 'string-irc'
2
+ require 'octospy/shortener'
3
+
4
+ module Octospy
5
+ module Extensions
6
+ module String
7
+ def underscore
8
+ self.gsub('::', '/').
9
+ gsub(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2').
10
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
11
+ tr("-", "_").
12
+ downcase
13
+ end
14
+
15
+ def split_by_linefeed_except_blankline
16
+ self.split(/\r\n|\n/).map { |v| v unless v.eql? '' }.compact
17
+ end
18
+ alias_method :split_lfbl, :split_by_linefeed_except_blankline
19
+
20
+ def colorize_for_irc
21
+ StringIrc.new(self)
22
+ end
23
+
24
+ def shorten_url
25
+ case
26
+ when self =~ /https?:\/\/(\w+\.)?github\.com/
27
+ Octospy::Shortener.shorten_by_github self
28
+ when self =~ /https?:\/\/.+/
29
+ Octospy::Shortener.shorten_by_google self
30
+ else
31
+ self
32
+ end
33
+ end
34
+ alias_method :shorten, :shorten_url
35
+ end
36
+ end
37
+ end
38
+
39
+ ::String.__send__ :include, Octospy::Extensions::String
@@ -0,0 +1,9 @@
1
+ module Octokit
2
+ class Client
3
+ def user?(user, options = {})
4
+ user(user)
5
+ rescue Octokit::NotFound
6
+ false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Octospy
2
+ class Parser
3
+ module Download
4
+ def parse_download_event
5
+ {
6
+ status: "download #{@event.payload.name}",
7
+ title: @event.payload.description,
8
+ link: @event.payload.html_url
9
+ }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Octospy
2
+ class Parser
3
+ module Gist
4
+ def parse_gist_event
5
+ unless @event.payload.gist.description.eql? ''
6
+ title = @event.payload.gist.description
7
+ else
8
+ title = ''
9
+ end
10
+
11
+ {
12
+ status: "#{@event.payload.action}d gist",
13
+ title: title,
14
+ link: @event.payload.gist.html_url,
15
+ none_repository: true
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,43 @@
1
+ module Octospy
2
+ class Parser
3
+ module Issue
4
+ def parse_issues_event
5
+ body = "#{@event.payload.issue.body}".split_lfbl
6
+
7
+ if @event.payload.issue.assignee
8
+ body << "assignee: #{@event.payload.issue.assignee.login}"
9
+ end
10
+
11
+ if @event.payload.issue.milestone
12
+ milestone_title = @event.payload.issue.milestone.title
13
+ milestone_state = @event.payload.issue.milestone.state
14
+ body << "milestone: #{milestone_title}[#{milestone_state}]"
15
+ end
16
+
17
+ {
18
+ status: "#{@event.payload.action} issue ##{@event.payload.issue.number}",
19
+ title: @event.payload.issue.title,
20
+ body: body,
21
+ link: @event.payload.issue.html_url
22
+ }
23
+ end
24
+
25
+ def parse_issue_comment_event
26
+ if @event.payload.action == 'created'
27
+ status = "commented on issue ##{@event.payload.issue.number}"
28
+ title = @event.payload.issue.title
29
+ else
30
+ status = "#{@event.payload.action} issue comment"
31
+ title = ''
32
+ end
33
+
34
+ {
35
+ status: status,
36
+ title: title,
37
+ body: "#{@event.payload.comment.body}".split_lfbl,
38
+ link: @event.payload.comment.html_url
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end