gitall 1.1.5

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 023bf7ff2db1c44f15f8f8f66d02356ee0d5d88c53a4e4b1b78a374873041e7a
4
+ data.tar.gz: c0f0f44647496761ff884cb2380ea5891d27ad41ee9f8c5c3bcfab55e6912ff4
5
+ SHA512:
6
+ metadata.gz: f385058ddb774533779b5efb63a53ca3ca46094575fabf15ca43444d7a8fa93806c481059bd394a5eeb61eadbde2947396a3e54e2aa6906d5156e612a4ce9c87
7
+ data.tar.gz: d3a6e33ff86b316dc41042f809731624a5777c537a2dd22d28b6252d2cb39f6ccd6095aaf2f965e02bfd465142debc4ed88bf255fd9f1291a6140d9b0e47d8e6
@@ -0,0 +1,58 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require './bot_version.rb'
4
+ require 'sinatra/base'
5
+ require 'json'
6
+ require 'cinch'
7
+ require 'cinch/plugins/basic_ctcp'
8
+ require 'cinch/plugins/identify'
9
+ require 'ostruct'
10
+ require 'recursive-open-struct'
11
+ require 'yaml'
12
+ require 'unirest'
13
+ require 'base64'
14
+ require 'active_support/all'
15
+ Thread.abort_on_exception = true
16
+
17
+ # @note Load the plugins
18
+ require 'gitallchancontrol.rb'
19
+ require './lib/admin.rb'
20
+ require './lib/logger.rb'
21
+ require './lib/eval.rb'
22
+
23
+ # @note Load the parsers
24
+ require 'gitall/parsers/gitlab'
25
+ require 'gitall/parsers/github.rb'
26
+
27
+ # Cinch
28
+
29
+ $cfg = YAML.load_file(`echo ~/.gitall-rc.yml`.chomp!)
30
+ $bots = Hash.new
31
+ $threads = Array.new
32
+
33
+ # For the sake of this example, we'll create an ORM-like model and give it an
34
+ # authenticate method, that checks if a given password matches.
35
+ class User < Struct.new :nickname, :password, :type
36
+ def authenticate(pass)
37
+ password == pass
38
+ end
39
+ end
40
+
41
+ # Simulate a database.
42
+ $users = []
43
+ @users = YAML.load_file(`echo ~/.gitall-rc.yml`.chomp!)['users']
44
+ @users.each do |user, hash|
45
+ password = hash['password']
46
+ role = hash['role']
47
+ $users << User.new(user, password, role)
48
+ end
49
+
50
+
51
+ $bots.each do |key, bot|
52
+ puts "Starting IRC connection for #{key}..."
53
+ $threads << Thread.new { bot.start }
54
+ end
55
+ $threads << Thread.new {
56
+ WebHook.run! if __FILE__ == $PROGRAM_NAME
57
+ }
58
+ $threads.each(&:join)
File without changes
@@ -0,0 +1,200 @@
1
+ require 'recursive_open_struct'
2
+ require 'json'
3
+
4
+ require 'parsers/github'
5
+ require 'parsers/gitlab'
6
+
7
+ require 'plugins/admin'
8
+ require 'plugins/chancontrol'
9
+ require 'plugins/git'
10
+ require 'plugins/eval'
11
+
12
+ module GitAll
13
+ CFG = File.open(Pathname(Dir.home).join('gitall-rc.yml'), 'r').read
14
+ USERS = CFG['users']
15
+ PROJECTS = CFG['projects']
16
+ # Houses all the gitall bots and their data
17
+
18
+ class Users
19
+ attr :users
20
+ @users = []
21
+
22
+ class User < Struct.new :nickname, :password, :type
23
+ def authenticate(pass)
24
+ password == pass
25
+ end
26
+ end
27
+
28
+ USERS.each do |user, hash|
29
+ password = hash['password']
30
+ role = hash['role']
31
+ @users << User.new(user, password, role)
32
+ end
33
+ end
34
+ class Bots
35
+ attr :bots, :config
36
+
37
+ @bots = {}
38
+ @config = GitAll::CFG
39
+
40
+
41
+
42
+ def add_bots
43
+ @config['networks'].each do |name, ncfg|
44
+ bot = Cinch::Bot.new do
45
+ configure do |c|
46
+ c.server = ncfg.fetch('server')
47
+ c.port = ncfg.fetch('port')
48
+ c.nick = ncfg.fetch('nickname')
49
+ c.user = ncfg.fetch('username')
50
+ c.realname = ncfg.fetch('realname')
51
+ c.plugins.prefix = Regexp.new(ncfg.fetch('prefix'))
52
+ c.plugins.plugins << Cinch::Plugins::Identify
53
+ identify_with = ncfg.fetch('identify-with')
54
+ case identify_with
55
+ when 'nickserv'
56
+ begin
57
+ c.plugins.options[Cinch::Plugins::Identify] = {
58
+ :username => ncfg.fetch('sasl-username'),
59
+ :password => ncfg.fetch('sasl-password'),
60
+ :type => :nickserv,
61
+ }
62
+ rescue KeyError
63
+ # ignored
64
+ end
65
+ when 'sasl'
66
+ begin
67
+ c.sasl.username = ncfg.fetch('sasl-username')
68
+ c.sasl.password = ncfg.fetch('sasl-password')
69
+ rescue KeyError
70
+ # ignored
71
+ end
72
+ when 'cert'
73
+ begin
74
+ c.ssl.client_cert = ncfg.fetch('certfp')
75
+ rescue KeyError
76
+ # ignored
77
+ end
78
+ when 'none'
79
+ # Don't identify
80
+ else
81
+ # noop
82
+ end
83
+ c.channels = ncfg.fetch('channels')
84
+ c.ssl.use = ncfg.fetch('ssl')
85
+ c.ssl.verify = ncfg.fetch('sslverify')
86
+ c.messages_per_second = ncfg.fetch('mps')
87
+ # Global configuration. This means that all plugins / matchers that
88
+ # implement authentication make use of the :login strategy, with a user
89
+ # level of :users.
90
+ c.authentication = Cinch::Configuration::Authentication.new
91
+ c.authentication.strategy = :login
92
+ c.authentication.level = :users
93
+ # The UserLogin plugin will call this lambda when a user runs !register.
94
+ #c.authentication.registration = lambda { |nickname, password|
95
+ # If you were using an ORM, you'd do something like
96
+ # `User.create(:nickname => nickname, :password => password)` here.
97
+ # return false if Users.users.one? { |user| user.nickname == nickname }
98
+ # Users.users << User.new(nickname, password, 'user')
99
+ #}
100
+ # The UserLogin plugin will call this lambda when a user runs !login. Note:
101
+ # the class it returns must respond to #authenticate with 1 argument (the
102
+ # password the user tries to login with).
103
+ c.authentication.fetch_user = lambda { |nickname|
104
+ # If you were using an ORM, you'd probably do something like
105
+ # `User.first(:nickname => nickname)` here.
106
+ Users.users.find { |user| user.nickname == nickname } }
107
+ # The Authentication mixin will call these lambdas to check if a user is
108
+ # allowed to run a command.
109
+ c.authentication.users = lambda { |user| user.type == 'user' }
110
+ c.authentication.admins = lambda { |user| user.type == 'admin' }
111
+ c.plugins.plugins << Cinch::Plugins::UserLogin
112
+ c.plugins.plugins << Cinch::Plugins::BasicCTCP
113
+ c.plugins.options[Cinch::Plugins::BasicCTCP][:replies] = {
114
+ version: Version::Bot.version,
115
+ source: 'https://gitlab.com/gitall/gitall'
116
+ }
117
+ c.plugins.plugins << ChanControl
118
+ c.plugins.options[ChanControl][:authentication_level] = :admins
119
+ c.plugins.plugins << Admin
120
+ c.plugins.options[Admin][:authentication_level] = :admins
121
+ c.plugins.plugins << Eval
122
+ c.plugins.options[Eval][:authentication_level] = :admins
123
+ c.plugins.plugins << Cinch::Plugins::UserList
124
+ c.plugins.options[Cinch::Plugins::UserList][:authentication_level] = :admins
125
+ end
126
+ end
127
+ bot.loggers.clear
128
+ bot.loggers << GitLogger.new(name, File.open("log/gitall-#{name}.log", 'a'))
129
+ bot.loggers << GitLogger.new(name, STDOUT)
130
+ bot.loggers.level = :debug
131
+ self.bots[name] = bot
132
+ end
133
+ end
134
+ end
135
+ class WebHook < Sinatra::Base
136
+ set :port, 8008
137
+ set :bind, '127.0.0.1'
138
+ set :environment, 'production'
139
+ set :threaded, true
140
+ post '/hook/?' do
141
+ request.body.rewind
142
+ payload = request.body.read
143
+ json = JSON.load(payload)
144
+ j = RecursiveOpenStruct.new(json)
145
+ repo = ''
146
+ if request.env.key? 'HTTP_X_GITLAB_TOKEN'
147
+ repo = j.project.path_with_namespace
148
+ resp = GitLabParser.parse json
149
+ phash = PROJECTS[repo]
150
+ if phash['token'] == request.env['HTTP_X_GITLAB_TOKEN']
151
+ channels = phash['channels']
152
+ channels.each do |channet|
153
+ channel = channet.split(',')[0]
154
+ net = channet.split(',')[1]
155
+ resp.each do |n|
156
+ Bots.bots[net].Channel(channel).send("#{n}")
157
+ end
158
+ end
159
+ end
160
+ elsif request.env.key? 'HTTP_X_HUB_SIGNATURE'
161
+ if !j.repository.full_name.nil?
162
+ repo = j.repository.full_name
163
+ elsif !j.organization.login.nil?
164
+ repo = j.organization.login
165
+ else
166
+ end
167
+ # phash includes orgs and repos
168
+ phash = PROJECTS[repo.to_sym]
169
+ token = phash['token']
170
+ sent_token = request.env['HTTP_X_HUB_SIGNATURE']
171
+ signature = "sha1=#{OpenSSL::HMAC.hexdigest('sha1', token, payload.strip).chomp}"
172
+ resp = GitHubParser.parse json, request.env['HTTP_X_GITHUB_EVENT']
173
+ if signature.to_s == sent_token.to_s
174
+ channels = phash['channels'.to_sym]
175
+ channels.each {
176
+ |channet|
177
+ channel = channet.split(',')[0]
178
+ network = channet.split(',')[1]
179
+ resp.each {
180
+ |n|
181
+ GitAll::Bots.bots[network].Channel(channel).send("#{n}")
182
+ }
183
+ }
184
+ end
185
+
186
+ elsif request.env.key?('HTTP_X_GOGS_EVENT')
187
+
188
+ elsif request.env.key?('HTTP_X_EVENT_KEY')
189
+ # BitBucket's Webhooks
190
+ # Requires HTTPS and does not
191
+ # implement a secret unless set into
192
+ # the url.
193
+ status 404
194
+ body 'bitbucket not implemented'
195
+ else
196
+ [404, "I can't help with that"]
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,21 @@
1
+ # lib/logger.rb
2
+ # Ken Spencer <ken@electrocode.net>
3
+ #
4
+ # This module is part of GitAll and is released under the
5
+ # MIT license: http://opensource.org/licenses/MIT
6
+
7
+ require 'cinch'
8
+
9
+ class GitLogger < Cinch::Logger::FormattedLogger
10
+ def initialize(network, *args)
11
+ @network = network
12
+ super(*args)
13
+ end
14
+
15
+ def format_general(message)
16
+ message.gsub!(/[^[:print:][:space:]]/) do |m|
17
+ colorize(m.inspect[1..-2], :bg_white, :black)
18
+ end
19
+ "[#{@network}] #{message}"
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ # lib/bitbucket.rb
2
+ # Ken Spencer <ken@electrocode.net>
3
+ #
4
+ # This module is part of GitAll and is released under the
5
+ # MIT license: http://opensource.org/licenses/MIT
6
+
7
+ class BitBucketParser
8
+ # @param [Object] json json object
9
+ # @param [Object] event the github event
10
+ def self.parse(json, event)
11
+ ec, e = event.split(':')
12
+ end
13
+ end
@@ -0,0 +1,191 @@
1
+ # lib/github.rb
2
+ # Ken Spencer <ken@electrocode.net>
3
+ #
4
+ # This module is part of GitAll and is released under the
5
+ # MIT license: http://opensource.org/licenses/MIT
6
+
7
+ # GitHub Event Parsing
8
+ # noinspection RubyUnusedLocalVariable
9
+ require 'cinch'
10
+ class GitHubParser
11
+ # @param [Object] json json object
12
+ # @param [Object] event the github event
13
+ def self.parse(json, event)
14
+ j = RecursiveOpenStruct.new(json)
15
+ response = []
16
+ case event
17
+ when 'ping'
18
+ zen = j.zen
19
+ id = j.hook_id
20
+ response << "Hook #{id} [PING] '#{zen}'"
21
+ when 'issue_comment'
22
+ when 'member'
23
+ when 'membership'
24
+ when 'milestone'
25
+ when 'label'
26
+ # "action":"created",
27
+ # "label":{
28
+ # "url":"https://api.github.com/repos/baxterandthehackers/public-repo/labels/blocked",
29
+ # "name":"blocked",
30
+ # "color":"ff0000"
31
+ # },
32
+ action = j.action
33
+ l = j.label
34
+ repo = j.repository.full_name
35
+ user = j.sender.login
36
+ lurl = l.url
37
+ lname = l.name
38
+ case action
39
+ when 'created', 'deleted'
40
+ response << "[#{repo}] #{user} #{action} label #{lname} <#{lurl}>"
41
+ when 'edited'
42
+ old = l.changes.name.from
43
+ new = lname
44
+ if old != new
45
+ response << "[#{repo}] #{user} #{action} Old: #{old} New: #{new}"
46
+ end
47
+ end
48
+ when 'team'
49
+ when 'team_add'
50
+ when 'fork'
51
+ f = RecursiveOpenStruct.new(j.forkee)
52
+ user = j.sender.login
53
+ fork = f.full_name
54
+ repo = j.repository.full_name
55
+ response << "[#{repo}] #{user} forked the repository to #{fork}"
56
+ when 'pull_request'
57
+ p = RecursiveOpenStruct.new(j.pull_request)
58
+ action = j.action
59
+ case action
60
+ when 'opened'
61
+ when 'closed'
62
+ end
63
+ when 'pull_request_review'
64
+ action = j.action
65
+ case action
66
+ when 'created'
67
+ when 'deleted'
68
+ end
69
+ when 'pull_request_review_comment'
70
+ c = RecursiveOpenStruct.new(j.comment)
71
+ action = j.action
72
+ case action
73
+ when 'created'
74
+ when 'deleted'
75
+ when 'edited'
76
+ end
77
+ when 'commit_comment'
78
+ when 'gollum'
79
+ p = j.pages
80
+ action = j.action
81
+ when 'create'
82
+ when 'delete'
83
+ when 'organization'
84
+ action = j.action
85
+ case action
86
+ when 'member_add'
87
+ when 'member_del'
88
+ end
89
+ when 'repository'
90
+ r = RecursiveOpenStruct.new(j.repository)
91
+ action = j.action
92
+ repo = r.full_name
93
+ user = j.sender.login
94
+ case action
95
+ when 'created'
96
+ response << "#{user} created repository #{repo}"
97
+ when 'deleted'
98
+ # XXX: Only triggers on Organization webhooks
99
+ response << "#{user} deleted #{r.full_name}"
100
+ end
101
+ when 'release'
102
+ r = RecursiveOpenStruct.new(j.release)
103
+ tag = r.tag_name
104
+ action = j.action
105
+ repo = j.repository.full_name
106
+ case action
107
+ when 'published'
108
+ response << "[#{repo}] released #{tag}!"
109
+ else
110
+ response << "[#{repo}] #{action} something!"
111
+ response << "**\u000304This is a fallback for when new actions are added to the 'ReleaseEvent'**"
112
+ response << 'Please submit an issue at https://github.com/IotaSpencer/gitall'
113
+ response << ' or join #gitall on the freenode or ElectroCode IRC networks.'
114
+ end
115
+ when 'watch'
116
+ # XXX: possibly add user's profile url if option set
117
+ response << "[#{repo}] #{user} starred the repository!"
118
+ when 'issue'
119
+ repo = j.repository.full_name
120
+ url = shorten(j.issue.url)
121
+ action = j.action
122
+ id = j.issue.number
123
+ title = j.issue.title
124
+ user = j.issue.user.name
125
+ # assigned", "unassigned", "labeled", "unlabeled", "opened", "edited",
126
+ # "milestoned", "demilestoned", "closed", or "reopened".
127
+ case action
128
+ when 'assigned'
129
+ # do stuff ...
130
+ when 'unassigned'
131
+ # do stuff ...
132
+ when 'labeled'
133
+ label = j.label.name
134
+ response << "[#{repo}] #{user} added #{label}"
135
+ when 'unlabeled'
136
+ # do stuff ...
137
+ when 'milestoned'
138
+ response << "[#{repo}] #{user} milestoned issue ##{id} "
139
+ when 'demilestoned'
140
+ # do stuff ...
141
+ when 'reopened'
142
+ response << "[#{repo}] #{user} reopened ##{id}"
143
+
144
+ when 'opened'
145
+ response << "[#{repo}] #{user} opened an issue ##{id} - #{title} <#{url}>"
146
+ when 'closed'
147
+ response << "[#{repo}] #{user} closed issue ##{id} - #{title} <#{url}>"
148
+ when 'edited'
149
+ response << "[#{repo}] #{user} edited issue ##{id} - #{title} <#{url}>"
150
+ end
151
+ when 'push'
152
+ repo = j.repository.full_name
153
+ branch = j.ref.split('/')[-1]
154
+ commits = j.commits
155
+ added = 0
156
+ removed = 0
157
+ modified = 0
158
+ commits.each do |h|
159
+ added += h['added'].length
160
+ removed += h['removed'].length
161
+ modified += h['modified'].length
162
+ end
163
+ pusher = j.pusher.name
164
+ commit_count = commits.length
165
+ compare_url = shorten(j.compare)
166
+ response << "[#{repo}] #{pusher} pushed #{commit_count} commit(s) [+#{added}/-#{removed}/±#{modified}] to [#{branch}] <#{compare_url}>"
167
+ if commits.length > 3
168
+ coms = commits[0..2]
169
+ coms.each do |n|
170
+ id = n.dig('id')
171
+ id = id[0...7]
172
+ msg = n.dig('message').lines[0].chomp
173
+ author = n.dig 'committer', 'name'
174
+ response << "#{author} — #{msg} [#{id}]"
175
+ end
176
+ response << "and #{commits.length - 3} commits..."
177
+ else
178
+ commits.each do |n|
179
+ id = n.dig('id')
180
+ id = id[0...7]
181
+ msg = n.dig('message').lines[0].chomp
182
+ author = n.dig 'committer', 'name'
183
+ response << "#{author} — #{msg} [#{id}]"
184
+ end
185
+ end
186
+ else
187
+ 'format not implemented'
188
+ end
189
+ response
190
+ end
191
+ end
@@ -0,0 +1,103 @@
1
+ # lib/gitlab.rb
2
+ # Ken Spencer <ken@electrocode.net>
3
+ #
4
+ # This module is part of GitAll and is released under the
5
+ # MIT license: http://opensource.org/licenses/MIT
6
+
7
+ # GitLab Event Parsing
8
+ class GitLabParser
9
+ def GitLabParser.parse(json)
10
+ j = RecursiveOpenStruct.new(json)
11
+ response = []
12
+ kind = j.object_kind
13
+ case kind
14
+ when 'note'
15
+ repo = j.project.path_with_namespace
16
+ ntype = j.object_attributes.noteable_type
17
+ case ntype
18
+ when 'MergeRequest'
19
+ mr_note = j.object_attributes.note
20
+ mr_url = shorten(j.object_attributes.url)
21
+ mr_title = j.merge_request.title
22
+ mr_id = j.merge_request.iid
23
+ mr_user = j.user.name
24
+ response << "[#{repo}] #{mr_user} commented on Merge Request ##{mr_id} \u2014 #{mr_note}"
25
+ response << "'#{mr_title}' => #{mr_url}"
26
+ when 'Commit'
27
+ c_note = j.object_attributes.note
28
+ c_sha = j.commit.id[0...7]
29
+ c_url = shorten(j.object_attributes.url)
30
+ c_user = j.user.name
31
+ response << "[#{repo}] #{c_user} commented on commit (#{c_sha}) \u2014 #{c_note} <#{c_url}>"
32
+ when 'Issue'
33
+ i_id = j.issue.iid
34
+ i_url = shorten(j.object_attributes.url)
35
+ i_msg = j.object_attributes.note
36
+ i_title = j.issue.title
37
+ i_user = j.user.name
38
+ response << "[#{repo}] #{i_user} commented on Issue ##{i_id} (#{i_title}) \u2014 #{i_msg} <#{i_url}>"
39
+ else
40
+ # type code here
41
+ end
42
+ when 'issue'
43
+ i_repo = j.project.path_with_namespace
44
+ i_user = j.user.name
45
+ i_un = j.user.username
46
+ i_id = j.object_attributes.iid
47
+ i_title = j.object_attributes.title
48
+ i_action = j.object_attributes.action
49
+ i_url = shorten(j.object_attributes.url)
50
+ response << "[#{i_repo}] #{i_user}(#{i_un}) #{i_action} issue ##{i_id} - #{i_title} <#{i_url}>"
51
+ when 'merge_request'
52
+ mr_name = j.user.name
53
+ mr_user = j.user.username
54
+ mr_url = shorten(j.url)
55
+ mr_spath = j.object_attributes.source.path_with_namespace
56
+ mr_sbranch = j.object_attributes.source_branch
57
+ mr_tpath = j.object_attributes.target.path_with_namespace
58
+ mr_tbranch = j.object_attributes.target_branch
59
+ mr_lcmessage = j.object_attributes.last_commit.message
60
+ mr_lcsha = j.object_attributes.last_commit.id[0...7]
61
+ response << "#{mr_name}(#{mr_user}) opened a merge request. #{mr_spath}[#{mr_sbranch}] ~> #{mr_tpath}[#{mr_tbranch}]"
62
+ response << "[#{mr_lcsha}] \u2014 #{mr_lcmessage} <#{mr_url}>"
63
+ when 'push' # comes to
64
+ # shove
65
+ branch = j.ref.split('/')[-1]
66
+ commits = j.commits
67
+ added = 0
68
+ removed = 0
69
+ modified = 0
70
+ commits.each do |h|
71
+ added += h['added'].length
72
+ removed += h['removed'].length
73
+ modified += h['modified'].length
74
+ end
75
+ owner = j.project.namespace
76
+ project = j.project.name
77
+ pusher = j.user_name
78
+ commit_count = j.total_commits_count
79
+ repo_url = shorten(j.project.web_url)
80
+ response << "[#{owner}/#{project}] #{pusher} pushed #{commit_count} commit(s) [+#{added}/-#{removed}/±#{modified}] to [#{branch}] at <#{repo_url}>"
81
+ if commits.length > 3
82
+ coms = commits[0..2]
83
+ coms.each do |n|
84
+ id = n['id']
85
+ msg = n['message'].lines[0]
86
+ author = n['author']['name']
87
+ response << "#{author} — #{msg.chomp!} [#{id[0...7]}]"
88
+ end
89
+ response << "and #{commits.from(3).length} commits..."
90
+ else
91
+ commits.each do |n|
92
+ id = n['id'][0...7]
93
+ msg = n['message'].lines[0]
94
+ author = n['author']['name']
95
+ response << "#{author} — #{msg.chomp!} [#{id}]"
96
+ end
97
+ end
98
+ else
99
+ # type code here
100
+ end
101
+ return response
102
+ end
103
+ end
@@ -0,0 +1,78 @@
1
+ # lib/admin.rb
2
+ # Ken Spencer <ken@electrocode.net>
3
+ #
4
+ # This module is part of GitAll and is released under the
5
+ # MIT license: http://opensource.org/licenses/MIT
6
+
7
+ require 'cinch'
8
+ require 'cinch/extensions/authentication'
9
+ require 'yaml'
10
+ require 'recursive-open-struct'
11
+
12
+ # @class Admin Plugin
13
+ class Admin
14
+ include Cinch::Plugin
15
+ include Cinch::Extensions::Authentication
16
+ match /quit$/, method: :do_Quit, group: :quit
17
+ match /quit (.+)$/, method: :do_Quit, group: :quit
18
+
19
+ match /join$/, method: :do_Join, group: :join
20
+ match /join (.+)/, method: :do_Join, group: :join
21
+
22
+ match /announce$/, method: :do_Announce, group: :announce
23
+ match /announce (.+)$/, method: :do_Announce, group: :announce
24
+ match /global$/, method: :do_Announce, group: :announce
25
+ match /global (.+)$/, method: :do_Announce, group: :announce
26
+
27
+ def do_Announce(m, msg = nil)
28
+ return unless authenticated? m
29
+ if msg.nil?
30
+ command = m.command
31
+ m.reply "Syntax: !#{command} Message to announce..."
32
+ else
33
+ $bots.each do |net, bot|
34
+ info("Announcing to #{net}")
35
+ debug("Announcing '#{msg}'")
36
+ bot.channels.each do |c|
37
+ Channel(c).send("[GLOBAL - #{m.user}@#{m.bot.irc.isupport.fetch('NETWORK')}] #{msg}",
38
+ notice=false)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def do_Quit(m, msg = nil)
45
+ return unless authenticated? m
46
+ if msg.nil?
47
+ $bots.each do |net, bot|
48
+ info("Exiting from #{net}")
49
+ bot.quit('QUIT received!')
50
+ end
51
+ else
52
+ $bots.each do |net, bot|
53
+ info("Exiting from #{net}")
54
+ bot.quit(msg)
55
+ end
56
+ end
57
+ $threads.each(&:exit)
58
+ end
59
+ def do_Join(m, channels = nil)
60
+ return unless authenticated? m
61
+ if channels.nil?
62
+ m.reply 'Syntax: join #channel[,#channel2,#channel3]'
63
+ else
64
+ chans = channels.split(',')
65
+ chans.each do |chan|
66
+ Channel(chan).join
67
+ end
68
+ end
69
+ end
70
+ def do_Part(m, channels = nil, reasons = nil)
71
+ return unless authenticated? m
72
+ if channels.nil? && reasons.nil?
73
+ m.reply 'Syntax: part #channel1[,#channel2,#channel3] [reason1[,reason2,reason3]]'
74
+ else
75
+ m.reply 'Not implemented yet'
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,127 @@
1
+ # lib/chancontrol.rb
2
+ # Ken Spencer <ken@electrocode.net>
3
+ #
4
+ # This module is part of GitAll and is released under the
5
+ # MIT license: http://opensource.org/licenses/MIT
6
+
7
+ require 'cinch'
8
+ require 'cinch/extensions/authentication'
9
+ require 'yaml'
10
+ require 'recursive-open-struct'
11
+ require 'strgen'
12
+ # @note ChanControl Plugin
13
+
14
+ class ChanControl
15
+ include Cinch::Plugin
16
+ include Cinch::Extensions::Authentication
17
+
18
+ # Write to the config
19
+ # @param [Hash] msg the data to write
20
+ def toFile(msg)
21
+ data = msg
22
+ File.open(`echo ~/.gitall-rc.yml`.chomp, 'w') {|f| f.write(data.to_yaml) }
23
+ end
24
+
25
+ # Load the config
26
+ # @return [Hash] load the current config
27
+ def deFile
28
+ begin
29
+ parsed = YAML.load(File.open(`echo ~/.gitall-rc.yml`.chomp, 'r'))
30
+ rescue ArgumentError => e
31
+ puts "Could not parse YAML: #{e.message}"
32
+ end
33
+ parsed
34
+ end
35
+
36
+ match /padd$/, method: :padd, group: :padd
37
+ match /padd (\S+) (\S+) (\S+) (\S+)/, method: :padd, group: :padd
38
+
39
+ match /list$/, method: :listchans, group: :listchans
40
+ match /list (\S+)/, method: :listchans, group: :listchans
41
+
42
+ match /token$/, method: :getToken, group: :token
43
+ match /token ([0-9]+)/, method: :getToken, group: :token
44
+
45
+ # @param [Message]
46
+ # @param [String] namespace the Repository to watch
47
+ # @param [String] host the Git Service Website
48
+ # @param [String] token Secret Token @seealso {ChanControl#getToken}
49
+ # @param [ChannelList] channels | separated list of channels in the format
50
+ # of #channel,net
51
+ def padd(m, namespace = nil, host = nil, token = nil, channels = nil)
52
+ if namespace.nil?
53
+ m.reply 'Syntax: padd {OWNER/PROJECT} {github, gitlab, bitbucket}
54
+ XXXXXXTOKEN #channel,network[|#channel2,network|#channel3,network2]'
55
+ m.reply 'GitALL works best when using owner/repo webhooks, organization hooks have not been tested.'
56
+ else
57
+ return unless authenticated? m
58
+ config = deFile
59
+ if config[:projects].has_key? namespace
60
+ m.user.send("#{m.user.nick}: #{namespace} already exists in the
61
+ config.")
62
+ else
63
+ config[:projects][namespace] = {
64
+ host: host,
65
+ token: token,
66
+ channels: channels.split('|')
67
+ }
68
+ toFile(config)
69
+ project = deFile().dig(:projects, namespace)
70
+ m.user.send("Inputted: #{project}")
71
+ end
72
+ # @param [String] host
73
+ def cap_host(host)
74
+ case host.downcase
75
+ when 'github'
76
+ 'GitHub.com'
77
+ when 'gitlab'
78
+ 'GitLab.com'
79
+ when 'bitbucket'
80
+ 'BitBucket.org'
81
+ end
82
+ end
83
+ m.user.send("Remember to add the webhook to #{cap_host(host)} if you
84
+ haven't already.")
85
+ info("Project added: #{project}")
86
+ end
87
+ end
88
+
89
+ # @param [Message] m message object
90
+ # @param [Integer] length token length
91
+ # @return [String] Token
92
+ def getToken(m, length = nil)
93
+ token = Strgen.generate do |c|
94
+ if length.nil?
95
+ c.length = 30
96
+ else
97
+ if length.to_i > 100
98
+ c.length = 100
99
+ m.reply 'Truncating to 100 characters due to spam concerns'
100
+ else
101
+ c.length = length
102
+ end
103
+ end
104
+ c.alpha = true
105
+ c.numbers = true
106
+ c.repeat = false
107
+ c.symbols = false
108
+ c.exclude = %w[1 i I l L 0 o O]
109
+ end
110
+ m.user.send "Token: #{token}"
111
+ end
112
+
113
+ # @param [Channel] channel name of channel
114
+ # @note Ensures that the channel is joined or known of
115
+ # @returns Boolean true/false
116
+
117
+ def self.joined(channel)
118
+ Channel(channel) ? true : false
119
+ end
120
+ # @param [Object] m Object
121
+
122
+ def listchans(m, project = nil)
123
+ return unless authenticated? m
124
+ project_hash = deFile['projects'][project]
125
+ m.reply "Name: #{project} Host: #{project_hash['host'.to_sym]} Channels: #{project_hash['channels'.to_sym].join(" \xB7 ")}"
126
+ end
127
+ end
@@ -0,0 +1,17 @@
1
+ require 'cinch'
2
+ class Eval
3
+ include Cinch::Plugin
4
+ include Cinch::Extensions::Authentication
5
+
6
+ match /eval$/, method: :do_eval, group: :doeval
7
+ match /eval (.*)/, method: :do_eval, group: :doeval
8
+
9
+ def do_eval(m, string = nil)
10
+ if string.nil?
11
+ m.reply "Syntax: !eval [CODE...]"
12
+ else
13
+ return unless authenticated? m
14
+ m.reply(eval(string))
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ # lib/git.rb
2
+ # Ken Spencer <ken@electrocode.net>
3
+ #
4
+ # This module is part of GitAll and is released under the
5
+ # MIT license: http://opensource.org/licenses/MIT
6
+
7
+ require 'cinch'
8
+ require 'cinch/extensions/authentication'
9
+ require 'unirest'
10
+ class ChanControl
11
+ include Cinch::Plugin
12
+ include Cinch::Extensions::Authentication
13
+
14
+ match /(\s+)\:(\S)\/(\S+)\#(\S)/, :method => :getIssue
15
+
16
+ def getIssue(m, host, user, repo, issue)
17
+ case host
18
+ when 'gl'
19
+ m.reply("https://gitlab.com/#{user}/#{repo}/issues/#{issue}")
20
+ when 'gh'
21
+ m.reply("https://github.com/#{user}/#{repo}/issue/#{issue}")
22
+ when 'bb'
23
+ m.reply("https://bitbucket.org/#{user}/#{repo}/issue/#{issue}")
24
+ else
25
+ m.user.notice("I don't know that git-service host")
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module GitAll
2
+ VERSION = '1.1.5'
3
+ end
@@ -0,0 +1 @@
1
+ Invalid / Missing 'Secret' or 'Token'
metadata ADDED
@@ -0,0 +1,224 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gitall
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Ken Spencer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-06-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cinch
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.3.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.3.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.0.2
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '2.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.0.2
47
+ - !ruby/object:Gem::Dependency
48
+ name: sinatra-contrib
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 2.0.2
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 2.0.2
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: 2.0.2
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 2.0.2
67
+ - !ruby/object:Gem::Dependency
68
+ name: thor
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '0.20'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '0.20'
81
+ - !ruby/object:Gem::Dependency
82
+ name: paint
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '2.0'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '2.0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: git
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: '1.3'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '1.3'
109
+ - !ruby/object:Gem::Dependency
110
+ name: logging
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '2.2'
116
+ type: :runtime
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '2.2'
123
+ - !ruby/object:Gem::Dependency
124
+ name: pry
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '0.11'
130
+ type: :runtime
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '0.11'
137
+ - !ruby/object:Gem::Dependency
138
+ name: bundler
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '1.16'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '1.16'
151
+ - !ruby/object:Gem::Dependency
152
+ name: rake
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '10.0'
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '10.0'
165
+ - !ruby/object:Gem::Dependency
166
+ name: rspec
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - "~>"
170
+ - !ruby/object:Gem::Version
171
+ version: '3.0'
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: '3.0'
179
+ description: A git based webhook receiver for GitHub, GitLab, and Gogs
180
+ email:
181
+ - me@iotaspencer.me
182
+ executables:
183
+ - gitall
184
+ extensions: []
185
+ extra_rdoc_files: []
186
+ files:
187
+ - bin/gitall
188
+ - lib/cli/app.rb
189
+ - lib/gitall/gitall.rb
190
+ - lib/gitall/logger.rb
191
+ - lib/gitall/parsers/bitbucket.rb
192
+ - lib/gitall/parsers/github.rb
193
+ - lib/gitall/parsers/gitlab.rb
194
+ - lib/gitall/plugins/admin.rb
195
+ - lib/gitall/plugins/chancontrol.rb
196
+ - lib/gitall/plugins/eval.rb
197
+ - lib/gitall/plugins/git.rb
198
+ - lib/gitall/version.rb
199
+ - lib/views/_403.erb
200
+ homepage: https://gitlab.com/gitall/gitall
201
+ licenses:
202
+ - MIT
203
+ metadata: {}
204
+ post_install_message:
205
+ rdoc_options: []
206
+ require_paths:
207
+ - lib
208
+ required_ruby_version: !ruby/object:Gem::Requirement
209
+ requirements:
210
+ - - "~>"
211
+ - !ruby/object:Gem::Version
212
+ version: '2'
213
+ required_rubygems_version: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
218
+ requirements: []
219
+ rubyforge_project:
220
+ rubygems_version: 2.7.6
221
+ signing_key:
222
+ specification_version: 4
223
+ summary: Git Based Webservices Webhook Receiver
224
+ test_files: []