stalkerr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e221a6891528b82fcb96f86fd755fc67849b574
4
+ data.tar.gz: c3b563649487135c4c77e4ce77f3f3f3dee32205
5
+ SHA512:
6
+ metadata.gz: 80b0e80f8c158bb4081e9426a25d4381343f40b2bfd604318b73bccc7d10b23cefba63535744500632f21044b3a72e1270b971d8b53daaa03086ca8355dae1fa
7
+ data.tar.gz: 13ae4d63529d31a4e98195f52b5813a6c8b798983ebd2f6561a9fa94fdbf88be2b765df34b88fe10b43701d464796e5c79aa5549bb7b8f95d93fa93bfc6a50ac
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ vendor
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ log
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'net-irc'
4
+ gem 'json'
5
+ gem 'octokit'
6
+ gem 'string-irc'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 by linyows <linyows@gmail.com>
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.
@@ -0,0 +1,38 @@
1
+ Stalkerr
2
+ ========
3
+
4
+ Stalkerr is IRC Gateway, inspired by [agig](https://github.com/hsbt/agig) and [atig](https://github.com/mzp/atig).
5
+
6
+ ![The Shining](http://goo.gl/7JPKQ)
7
+
8
+ Usage
9
+ -----
10
+
11
+ ### Start Stalkerr
12
+
13
+ $ gem install stalkerr
14
+ $ stalkerr --help
15
+ $ stalkerr -D
16
+
17
+ ### Connecting to Stalkerr
18
+
19
+ /join #github <username>:<password>
20
+
21
+ Contributing
22
+ ------------
23
+
24
+ 1. Fork it
25
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
26
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
27
+ 4. Push to the branch (`git push origin my-new-feature`)
28
+ 5. Create new Pull Request
29
+
30
+ Author
31
+ ------
32
+
33
+ - [@linyows](https://github.com/linyows)
34
+
35
+ License
36
+ -------
37
+
38
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'stalkerr'
4
+
5
+ ::Stalkerr::Server.run
@@ -0,0 +1,7 @@
1
+ require 'stalkerr/version'
2
+ require 'stalkerr/optparse'
3
+ require 'stalkerr/const'
4
+ require 'stalkerr/server'
5
+ require 'stalkerr/session'
6
+ require 'stalkerr/target'
7
+ require 'stalkerr/extensions/string'
@@ -0,0 +1,10 @@
1
+ module Stalkerr::Const
2
+
3
+ DEFAULT_HOST = '127.0.0.1'
4
+
5
+ DEFAULT_PORT = 16705
6
+
7
+ ROLLBACK_SEC = 60 * 60
8
+
9
+ FETCH_INTERVAL = 30
10
+ end
@@ -0,0 +1,16 @@
1
+ module Stalkerr::Extensions
2
+ module String
3
+ def constantize
4
+ names = self.split('::')
5
+ names.shift if names.empty? || names.first.empty?
6
+ constant = Object
7
+ names.each do |name|
8
+ constant = constant.const_defined?(name, false) ?
9
+ constant.const_get(name) : constant.const_missing(name)
10
+ end
11
+ constant
12
+ end
13
+ end
14
+ end
15
+
16
+ ::String.__send__(:include, Stalkerr::Extensions::String)
@@ -0,0 +1,47 @@
1
+ require 'optparse'
2
+ require 'stalkerr'
3
+
4
+ module Stalkerr::OptParser
5
+ def self.parse!(argv)
6
+ opts = {
7
+ host: Stalkerr::Const::DEFAULT_HOST,
8
+ port: Stalkerr::Const::DEFAULT_PORT,
9
+ log: nil,
10
+ debug: false,
11
+ daemonize: false,
12
+ }
13
+
14
+ OptionParser.new do |parser|
15
+ parser.instance_eval do
16
+ self.banner = "Usage: #{$0} [opts]"
17
+ separator "Options:"
18
+
19
+ on("-p", "--port [PORT=#{opts[:port]}]",
20
+ "use PORT (default: #{Stalkerr::Const::DEFAULT_PORT})") do |port|
21
+ opts[:port] = port
22
+ end
23
+
24
+ on("-h", "--host [HOST=#{opts[:host]}]",
25
+ "listen HOST (default: #{Stalkerr::Const::DEFAULT_HOST})") do |host|
26
+ opts[:host] = host
27
+ end
28
+
29
+ on("-l", "--log LOG", "log file") do |log|
30
+ opts[:log] = log
31
+ end
32
+
33
+ on("-d", "--debug", "enable debug mode") do
34
+ opts[:log] = $stdout
35
+ opts[:debug] = true
36
+ end
37
+
38
+ on("-D", "--daemonize", "run daemonized in the background") do
39
+ opts[:daemonize] = true
40
+ end
41
+
42
+ parse!(argv)
43
+ end
44
+ end
45
+ opts
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ require 'net/irc'
2
+ require 'logger'
3
+
4
+ module Stalkerr::Server
5
+ def self.run
6
+ opts = Stalkerr::OptParser.parse!(ARGV)
7
+ Process.daemon if opts[:daemonize]
8
+ opts[:logger] = Logger.new(opts[:log], 'daily')
9
+ opts[:logger].level = opts[:debug] ? Logger::DEBUG : Logger::INFO
10
+ Net::IRC::Server.new(opts[:host], opts[:port], Stalkerr::Session, opts).start
11
+ end
12
+ end
@@ -0,0 +1,73 @@
1
+ require 'ostruct'
2
+ require 'time'
3
+ require 'net/irc'
4
+ require 'stalkerr'
5
+ Dir["#{File.dirname(__FILE__)}/target/*.rb"].each { |p| require p }
6
+
7
+ class Stalkerr::Session < Net::IRC::Server::Session
8
+
9
+ def initialize(*args)
10
+ super
11
+ @debug = args.last.debug
12
+ @channels = {}
13
+ Dir["#{File.dirname(__FILE__)}/target/*.rb"].each do |path|
14
+ name = File.basename(path, '.rb')
15
+ @channels.merge!(name.to_sym => "##{name}")
16
+ end
17
+ end
18
+
19
+ def on_disconnected
20
+ @retrieve_thread.kill rescue nil
21
+ end
22
+
23
+ def on_user(m)
24
+ super
25
+ @real, *@opts = @real.split(/\s+/)
26
+ @opts = OpenStruct.new @opts.inject({}) { |r, i|
27
+ key, value = i.split("=", 2)
28
+ r.update key => case value
29
+ when nil then true
30
+ when /\A\d+\z/ then value.to_i
31
+ when /\A(?:\d+\.\d*|\.\d+)\z/ then value.to_f
32
+ else value
33
+ end
34
+ }
35
+ end
36
+
37
+ def on_join(m)
38
+ super
39
+
40
+ matched = m.params[1].match(/(.*?):(.*)/)
41
+ channel = m.params[0]
42
+
43
+ if !@channels.value?(channel) || !matched
44
+ @log.error "#{channel} not found."
45
+ end
46
+
47
+ @class_name = "Stalkerr::Target::#{@channels.invert[channel].capitalize}"
48
+ @username = matched[1]
49
+ @password = matched[2]
50
+ post @username, JOIN, channel
51
+
52
+ @retrieve_thread = Thread.start do
53
+ loop do
54
+ begin
55
+ target.stalking do |prefix, command, *params|
56
+ post(prefix, command, *params)
57
+ end
58
+ sleep Stalkerr::Const::FETCH_INTERVAL
59
+ rescue Exception => e
60
+ @log.error e.inspect
61
+ e.backtrace.each { |l| @log.error "\t#{l}" }
62
+ sleep 10
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def target
71
+ @target ||= @class_name.constantize.new(@username, @password)
72
+ end
73
+ end
@@ -0,0 +1 @@
1
+ Dir["#{File.dirname(__FILE__)}/stalkerr/target/*.rb"].each { |p| require p }
@@ -0,0 +1,197 @@
1
+ require 'time'
2
+ require 'net/irc'
3
+ require 'octokit'
4
+ require 'net/http'
5
+ require 'string-irc'
6
+ require 'stalkerr'
7
+
8
+ module Stalkerr::Target
9
+ class Github
10
+ include Net::IRC::Constants
11
+
12
+ HOST = 'https://github.com'
13
+ CHANNEL = '#github'
14
+
15
+ def initialize(username, password)
16
+ @username = username
17
+ @password = password
18
+ @last_event_id = nil
19
+ end
20
+
21
+ def client
22
+ @client ||= Octokit::Client.new(login: @username, password: @password)
23
+ end
24
+
25
+ def stalking(&post)
26
+ @post = post
27
+ client.received_events(@username).reverse_each { |event|
28
+ if @last_event_id.nil?
29
+ next if Time.now.utc - Stalkerr::Const::ROLLBACK_SEC >= Time.parse(event.created_at).utc
30
+ else
31
+ next if @last_event_id >= event.id
32
+ end
33
+ result = parse(event)
34
+ @last_event_id = result if result != false
35
+ }
36
+ end
37
+
38
+ def parse(event)
39
+ obj = event.payload
40
+ header = status = title = link = ''
41
+ body = []
42
+ none_repository = false
43
+ notice_body = false
44
+
45
+ case event.type
46
+ when 'CommitCommentEvent'
47
+ status = "commented on commit"
48
+ title = "#{obj.comment.path}"
49
+ body = body + split_for_comment(obj.comment.body)
50
+ link = obj.comment.html_url
51
+ when 'PullRequestReviewCommentEvent'
52
+ status = "commented on pull request"
53
+ if obj.comment.pull_request_url
54
+ pull_id = obj.comment.pull_request_url.match(/\/pulls\/([0-9]+)/)[1]
55
+ pull = client.pull(event.repo.name, pull_id)
56
+ title = "#{pull.title}: #{obj.comment.path}"
57
+ else
58
+ title = obj.comment.path
59
+ end
60
+ body = body + split_for_comment(obj.comment.body)
61
+ link = obj.comment.html_url
62
+ when 'IssueCommentEvent'
63
+ if obj.action == 'created'
64
+ status = "commented on issue ##{obj.issue.number}"
65
+ title = obj.issue.title
66
+ else
67
+ status = "#{obj.action} issue comment"
68
+ end
69
+ body = body + split_for_comment(obj.comment.body)
70
+ link = obj.comment.html_url
71
+ when 'IssuesEvent'
72
+ status = "#{obj.action} issue ##{obj.issue.number}"
73
+ title = obj.issue.title
74
+ body = body + split_for_comment(obj.issue.body)
75
+ body << "assignee: #{obj.issue.assignee.login}" if obj.issue.assignee
76
+ body << "milestone: #{obj.issue.milestone.title}[#{obj.issue.milestone.state}]" if obj.issue.milestone
77
+ link = obj.issue.html_url
78
+ when 'PullRequestEvent'
79
+ status = "#{obj.action} pull request ##{obj.number}"
80
+ title = obj.pull_request.title
81
+ body = body + split_for_comment(obj.pull_request.body)
82
+ link = obj.pull_request.html_url
83
+ when 'PushEvent'
84
+ notice_body = true
85
+ status = "pushed to #{obj.ref.gsub('refs/heads/', '')}"
86
+ obj.commits.each do |commit|
87
+ verbose_commit = client.commit(event.repo.name, commit.sha)
88
+ name = verbose_commit.author ? verbose_commit.author.login : commit.author.name
89
+ url = "#{HOST}/#{event.repo.name}/commit/#{commit.sha}"
90
+ line = "#{StringIrc.new(name).silver}: #{commit.message}"
91
+ line << " - #{StringIrc.new(shorten url).blue}"
92
+ body = body + split_for_comment(line)
93
+ end
94
+ link = "#{HOST}/#{event.repo.name}"
95
+ when 'CreateEvent'
96
+ if obj.ref_type.eql? 'repository'
97
+ none_repository = true
98
+ status = "created repository"
99
+ title = event.repo.name
100
+ else
101
+ status = "created #{obj.ref_type}:#{obj.ref}"
102
+ end
103
+ title = obj.description
104
+ link = "#{HOST}/#{event.repo.name}"
105
+ when 'DeleteEvent'
106
+ status = "deleted #{obj.ref_type}:#{obj.ref}"
107
+ link = "#{HOST}/#{event.repo.name}"
108
+ when 'DownloadEvent'
109
+ status = "download #{obj.name}"
110
+ title = obj.description
111
+ link = obj.html_url
112
+ when 'ForkEvent'
113
+ status = "forked #{obj.forkee.full_name} [#{obj.forkee.language}]"
114
+ title = obj.forkee.description
115
+ link = obj.forkee.html_url
116
+ when 'TeamAddEvent'
117
+ status = "add team"
118
+ title = obj.team.name
119
+ when 'WatchEvent'
120
+ none_repository = true
121
+ status = "#{obj.action} repository"
122
+ title = event.repo.name
123
+ link = "#{HOST}/#{event.repo.name}"
124
+ when 'FollowEvent'
125
+ none_repository = true
126
+ notice_body = true
127
+ user = obj.target
128
+ status = "followed"
129
+ title = user.login
130
+ title = "#{title} (#{user.name})" if user.name && user.name != ''
131
+ profile = ["#{StringIrc.new('repos').silver}: #{user.public_repos}"]
132
+ profile << "#{StringIrc.new('followers').silver}: #{user.followers}"
133
+ profile << "#{StringIrc.new('following').silver}: #{user.following}"
134
+ profile << "#{StringIrc.new('location').silver}: #{user.location && user.location != '' ? user.location : '-'}"
135
+ profile << "#{StringIrc.new('company').silver}: #{user.company && user.company != '' ? user.company : '-'}"
136
+ profile << "#{StringIrc.new('bio').silver}: #{user.bio && user.bio != '' ? user.bio : '-'}"
137
+ profile << "#{StringIrc.new('blog').silver}: #{user.blog && user.blog != '' ? user.blog : '-'}"
138
+ body << profile.join(', ')
139
+ link = "#{HOST}/#{user.login}"
140
+ when 'MemberEvent'
141
+ user = obj.member
142
+ status = "#{obj.action} member"
143
+ title = user.login
144
+ link = "#{HOST}/#{user.login}"
145
+ when 'GistEvent'
146
+ none_repository = true
147
+ status = "#{obj.action}d gist"
148
+ title = obj.gist.description unless obj.gist.description.eql? ''
149
+ link = obj.gist.html_url
150
+ when 'DownloadEvent',
151
+ 'ForkApplyEvent',
152
+ 'GollumEvent',
153
+ 'PublicEvent'
154
+ return false
155
+ end
156
+
157
+ nick = event.actor.login
158
+ unless status.eql? ''
159
+ color = case
160
+ when status.include?('created') then :pink
161
+ when status.include?('commented') then :yellow
162
+ when status.include?('pushed') then :lime
163
+ when status.include?('forked') then :orange
164
+ when status.include?('closed') then :brown
165
+ when status.include?('deleted') then :red
166
+ when status.include?('started') then :rainbow
167
+ when status.include?('followed') then :seven_eleven
168
+ else :aqua
169
+ end
170
+ header = StringIrc.new(status).send(color)
171
+ header = "(#{event.repo.name}) #{header}" unless none_repository
172
+ end
173
+ header = "#{header} #{title}" unless title.eql? ''
174
+ header = "#{header} - #{StringIrc.new(shorten link).blue}" unless link.eql? ''
175
+
176
+ @post.call nick, NOTICE, CHANNEL, header unless header.eql? ''
177
+ mode = notice_body ? NOTICE : PRIVMSG
178
+ body.each { |b| @post.call nick, mode, CHANNEL, b } unless body.eql? ''
179
+ event.id
180
+ end
181
+
182
+ def split_for_comment(string)
183
+ string.split(/\r\n|\n/).map { |v| v unless v.eql? '' }.compact
184
+ end
185
+
186
+ def shorten(url)
187
+ Net::HTTP.start('git.io', 80) do |http|
188
+ request = Net::HTTP::Post.new '/'
189
+ request.content_type = 'application/x-www-form-urlencoded'
190
+ query = Hash.new.tap { |h| h[:url] = url }
191
+ request.body = URI.encode_www_form(query)
192
+ response = http.request(request)
193
+ response.key?('Location') ? response["Location"] : url
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,3 @@
1
+ module Stalkerr
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../lib/stalkerr/version', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = ['linyows']
5
+ gem.email = ['linyows@gmail.com']
6
+ gem.description = %q{Stalkerr is IRC Server for stalking :)}
7
+ gem.summary = %q{Stalkerr is IRC Gateway, inspired by agig and atig.}
8
+ gem.homepage = 'https://github.com/linyows/stalkerr'
9
+
10
+ gem.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
11
+
12
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
13
+ gem.files = `git ls-files`.split("\n")
14
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ gem.name = 'stalkerr'
16
+ gem.require_paths = ['lib']
17
+ gem.version = Stalkerr::VERSION
18
+
19
+ gem.add_dependency 'net-irc'
20
+ gem.add_dependency 'json'
21
+ gem.add_dependency 'octokit'
22
+ gem.add_dependency 'string-irc'
23
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stalkerr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - linyows
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net-irc
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: octokit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: string-irc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Stalkerr is IRC Server for stalking :)
70
+ email:
71
+ - linyows@gmail.com
72
+ executables:
73
+ - stalkerr
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - bin/stalkerr
83
+ - lib/stalkerr.rb
84
+ - lib/stalkerr/const.rb
85
+ - lib/stalkerr/extensions/string.rb
86
+ - lib/stalkerr/optparse.rb
87
+ - lib/stalkerr/server.rb
88
+ - lib/stalkerr/session.rb
89
+ - lib/stalkerr/target.rb
90
+ - lib/stalkerr/target/github.rb
91
+ - lib/stalkerr/version.rb
92
+ - stalkerr.gemspec
93
+ homepage: https://github.com/linyows/stalkerr
94
+ licenses: []
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - '>='
103
+ - !ruby/object:Gem::Version
104
+ version: 1.9.3
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.0.0
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Stalkerr is IRC Gateway, inspired by agig and atig.
116
+ test_files: []