qbert_bot 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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDNiYWFhNTFhMDEwYzVkNGI4OTc0ODI0Zjc4N2MwNDhkNTQzODQ3Nw==
5
+ data.tar.gz: !binary |-
6
+ YTk5OWI0YTcyODFjNmYzZDVkMmI5OWI0N2E4NjM0YjFlNjdjNTY5NA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MmE0NjY5YjMzMzYwYjkwZWJmMDUxNjRlNmEzZDdkZTgxYzUxYTllYjBjN2Y2
10
+ OTU2ZjU2MTFjNWI1NzZmOTE5MmUxYzU1OWViYzJlNWEyMzZiOWNkOGI3YmZl
11
+ MDAyYjk2OWVhOTk2MmM1ODkyZTg3NDg5M2VmZjA5MGFkM2QxN2Y=
12
+ data.tar.gz: !binary |-
13
+ NjdmY2E5ODgwYzliZjAxYmMyM2FmMmIzNmZmOGM5MDY2YzZjZmIzNWY0Yzgx
14
+ MjMzM2YxMzRiYmYzMGE5NjQwNmM5NWYzYTA4N2MzZGI5ODg2YTYwYzQwY2Zi
15
+ Nzc0ZDg4M2Q4MGYzODZhNTJhZmM0ZjI5MGY4Y2VmMDRhMmRkMzc=
data/bin/qbert_bot ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'qbert_bot'
3
+ QbertBot.run!
@@ -0,0 +1,28 @@
1
+ module QbertBot
2
+ class Message
3
+ attr_accessor :token, :team_id, :channel_id, :channel_name, :timestamp,
4
+ :user_id, :user_name, :raw_text, :trigger_word
5
+ attr_accessor :matches
6
+
7
+ def initialize(bot, post_data)
8
+ @bot = bot
9
+ [:token, :team_id, :channel_id, :channel_name, :timestamp,
10
+ :user_id, :user_name, :trigger_word].each do |k|
11
+ send("#{k.to_s}=", post_data[k])
12
+ end
13
+ self.raw_text = post_data[:text]
14
+ end
15
+
16
+ def say(*args)
17
+ @bot.say(*args)
18
+ end
19
+
20
+ def reply(text, opts = {})
21
+ say(channel_name, text, opts)
22
+ end
23
+
24
+ def text
25
+ raw_text.sub(trigger_word, '').strip
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module QbertBot
2
+ module Plugin
3
+ def self.included(klass)
4
+ @plugins ||= []
5
+ @plugins << klass
6
+ puts "Loading plugin #{klass}"
7
+ end
8
+
9
+ def self.plugins
10
+ @plugins
11
+ end
12
+
13
+ attr_accessor :bot, :slack, :router, :scheduler
14
+ def register
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,116 @@
1
+ require 'singleton'
2
+ require 'sinatra/base'
3
+ require 'yaml'
4
+ require 'rufus-scheduler'
5
+
6
+ module QbertBot
7
+ Listener = Struct.new(:pattern, :proc)
8
+ BlankListener = Listener.new(//, proc {})
9
+
10
+ class Match
11
+ attr_reader :listener, :matches
12
+ def initialize(listener, matches)
13
+ @listener = listener
14
+ @matches = matches
15
+ end
16
+
17
+ def proc
18
+ @listener.proc
19
+ end
20
+ end
21
+
22
+ class Robot
23
+ include Singleton
24
+ attr_reader :config, :slack, :router, :scheduler
25
+
26
+ def initialize
27
+ @plugins = []
28
+ @listeners = []
29
+ end
30
+
31
+ def load_config
32
+ @config = YAML.load_file('qbert.yml')
33
+ end
34
+
35
+ def run!
36
+ prepare_workers
37
+ load_plugins
38
+ start_workers
39
+ end
40
+
41
+ def hear(pattern, &block)
42
+ puts("Adding #{pattern.source}")
43
+ @listeners << Listener.new(pattern, block)
44
+ end
45
+
46
+ def handle_web(method, request, params)
47
+ if method == :post && request.path_info == @router.endpoint
48
+ return handle_slack(params)
49
+ end
50
+
51
+ @router.exec_route(method, request, params)
52
+ end
53
+
54
+ def handle_slack(params)
55
+ msg = Message.new(self, params)
56
+ match = find_listener(msg)
57
+ msg.matches = match.matches
58
+ match.proc.call(msg)
59
+ ''
60
+ end
61
+
62
+ def say(*args)
63
+ @slack.say(*args)
64
+ end
65
+
66
+ private
67
+ def prepare_workers
68
+ @scheduler = Rufus::Scheduler.new
69
+ @router = Router.new(config['http'])
70
+ @slack = Slack.new(config['slack'])
71
+ end
72
+
73
+ def load_plugins
74
+ Plugin.plugins.each do |klass|
75
+ p = klass.new
76
+ p.bot = self
77
+ p.router = router
78
+ p.slack = slack
79
+ p.scheduler = scheduler
80
+ p.register
81
+ @plugins << p
82
+ end
83
+ end
84
+
85
+ def start_workers
86
+ Thread.new {
87
+ @scheduler.join
88
+ }
89
+ Web.run!
90
+ end
91
+
92
+ def find_listener(msg)
93
+ puts("Checking '#{msg.text}'")
94
+ @listeners.each do |l|
95
+ if match = msg.text.match(l.pattern)
96
+ puts("Found '#{l.pattern.source}'")
97
+ return Match.new(l, match)
98
+ end
99
+ end
100
+ return Match.new(BlankListener, [])
101
+ end
102
+ end
103
+
104
+ class Web < Sinatra::Base
105
+ set :port, proc { Robot.instance.router.port }
106
+ set :bind, proc { Robot.instance.router.bind }
107
+
108
+ get(//) do
109
+ Robot.instance.handle_web(:get, request, params)
110
+ end
111
+
112
+ post(//) do
113
+ Robot.instance.handle_web(:post, request, params)
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,47 @@
1
+ module QbertBot
2
+ Route = Struct.new(:method, :path, :proc)
3
+
4
+ class Router
5
+ attr_reader :routes, :port, :bind, :endpoint
6
+
7
+ def initialize(conf)
8
+ @routes = []
9
+ @bind = conf['bind']
10
+ @port = conf['port']
11
+ @endpoint = conf['endpoint']
12
+ end
13
+
14
+ def get(path, &block)
15
+ add_route(:get, path, &block)
16
+ end
17
+
18
+ def post(path, &block)
19
+ add_route(:post, path, &block)
20
+ end
21
+
22
+ def exec_route(method, request, params)
23
+ @routes.each do |route|
24
+ next unless route.method == method
25
+ next unless match = request.path_info.match(route.path)
26
+ return route.proc.call(request, params, match)
27
+ end
28
+ return 'no route'
29
+ end
30
+
31
+ private
32
+ def add_route(method, path, &block)
33
+ clean_path = nil
34
+
35
+ if path.is_a?(Regexp)
36
+ clean_path = path.source
37
+ elsif path.is_a?(String)
38
+ clean_path = Regexp.escape(path)
39
+ clean_path = "/#{clean_path}" unless clean_path[0] == '/'
40
+ clean_path = "#{clean_path}$" unless clean_path[-1, 1] == '$'
41
+ end
42
+
43
+ puts("Adding route for #{method} #{clean_path}")
44
+ @routes << Route.new(method, Regexp.new(clean_path), block)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,37 @@
1
+ require 'faraday'
2
+ require 'json'
3
+
4
+ module QbertBot
5
+ class Slack
6
+ attr_reader :hook, :default_name, :default_icon
7
+ def initialize(conf)
8
+ @hook = conf['hook']
9
+ @default_name = conf['name']
10
+ @default_icon = conf['icon']
11
+ end
12
+
13
+ def channel_or_dm(name)
14
+ return name if name[0] == '#'
15
+ return name if name[0] == '@'
16
+ "##{name}"
17
+ end
18
+
19
+
20
+ def say(to, text, opts = {})
21
+ payload = {
22
+ text: text,
23
+ channel: channel_or_dm(to),
24
+ username: default_name,
25
+ icon_emoji: default_icon,
26
+ }
27
+ payload[:icon_emoji] = opts[:icon] if opts.key?(:icon)
28
+ payload[:icon_url] = opts[:icon_url] if opts.key?(:icon_url)
29
+ payload[:username] = opts[:name] if opts.key?(:name)
30
+ payload[:attachments] = opts[:attachments] if opts.key?(:attachments)
31
+
32
+ puts("Saying: #{payload[:channel]} -> #{text}")
33
+ Faraday.post(@hook, payload: payload.to_json)
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module QbertBot
2
+ VERSION = "0.0.1"
3
+ end
data/lib/qbert_bot.rb ADDED
@@ -0,0 +1,21 @@
1
+ require "qbert_bot/version"
2
+ require "qbert_bot/plugin"
3
+ require "qbert_bot/message"
4
+ require "qbert_bot/router"
5
+ require "qbert_bot/slack"
6
+ require "qbert_bot/robot"
7
+
8
+
9
+
10
+ module QbertBot
11
+ def self.run!
12
+ bot = Robot.instance
13
+ bot.load_config
14
+
15
+ Dir['plugins/*.rb'].each do |f|
16
+ load f
17
+ end
18
+
19
+ bot.run!
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qbert_bot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - lxfontes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rufus-scheduler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '0.9'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ description: ''
84
+ email:
85
+ - lxfontes@gmail.com
86
+ executables:
87
+ - qbert_bot
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - bin/qbert_bot
92
+ - lib/qbert_bot.rb
93
+ - lib/qbert_bot/message.rb
94
+ - lib/qbert_bot/plugin.rb
95
+ - lib/qbert_bot/robot.rb
96
+ - lib/qbert_bot/router.rb
97
+ - lib/qbert_bot/slack.rb
98
+ - lib/qbert_bot/version.rb
99
+ homepage: http://github.com/lxfontes/qbert_bot
100
+ licenses:
101
+ - MIT
102
+ metadata: {}
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 2.4.4
120
+ signing_key:
121
+ specification_version: 4
122
+ summary: The no frills ruby bot for Slack
123
+ test_files: []