qbot 0.1.1 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 85d73bad55f14325b0a78aeaff2341de02ef5614aa2fffe440bf67a2a3b70b74
4
- data.tar.gz: 4482b338249e3c9fa3f480768f41dde54e160220929b0d6bd58e9e2a7679ad20
2
+ SHA1:
3
+ metadata.gz: 96175e44e35b00efdc98a08f7dc482c75358a2fa
4
+ data.tar.gz: f56a2d9a7e9d7634d8c8f1dcbe8a443cad455b05
5
5
  SHA512:
6
- metadata.gz: a4cc7f82c33ba57018a77b0cfadfe8c168647d0d00c53722bc894ea741dc250c1cfa042814c53673a4f12ac512a55304335be7ecf9a8917ccdd2673f084ffde4
7
- data.tar.gz: d8a08ddb77ede43079f68587967d5e70902df0ab2a9fbcb05d8ad3ade91cd0f95482e4ae7c97d3456d20577c477ad60d985c1366904ba62337bb0ee21087d3fb
6
+ metadata.gz: b03726403afaad4534f48644c27184b7a7df7fa562bbcdae9bd87a67004b816594f5c15d6726e204438793bff9cf0d3b6a27dfa715465168a4194a6bab6f6600
7
+ data.tar.gz: 0a33dbf259131511157139fefbe1faf4d790a40fc9962a77f8f4ddd962ae5b0a71de90f97748d29cc31219c2168c6f8c7b4d9d77e3b725c72d008f4070c668c6
data/README.md CHANGED
@@ -43,7 +43,7 @@ end
43
43
  Then put your Slack API Token in `.env`.
44
44
 
45
45
  ```
46
- QBOT_SLACK_API_TOKEN=xoxb-############-#######################C
46
+ QBOT_SLACK_API_TOKEN=xoxb-############-########################
47
47
  ```
48
48
 
49
49
  And now start your bot with the following command.
@@ -19,12 +19,12 @@ module Qbot
19
19
  end
20
20
 
21
21
  def run(bots)
22
- on_message do |message|
22
+ listen do |message|
23
23
  bots.each { |bot| bot.call(message.dup) }
24
24
  end
25
25
  end
26
26
 
27
- def on_message(&block)
27
+ def listen(&block)
28
28
  raise 'Not implemented'
29
29
  end
30
30
 
@@ -12,7 +12,6 @@ module Qbot
12
12
  def initialize(url: nil, username: nil, password: nil)
13
13
  @mm_url = url || ENV['QBOT_MATTERMOST_URL']
14
14
  @server = URI.join(@mm_url, '/').to_s
15
- @error = false
16
15
 
17
16
  resp = api_call(:post, '/users/login', :body => {
18
17
  login_id: username || ENV['QBOT_MATTERMOST_USERNAME'],
@@ -20,47 +19,24 @@ module Qbot
20
19
  })
21
20
 
22
21
  access_token(resp.headers['token'])
22
+ raise 'Login failed' unless @token
23
23
  end
24
24
 
25
25
  def access_token(token)
26
26
  @token = token
27
27
  end
28
28
 
29
- def on_message(&block)
30
- ws_url = URI.join(@server.gsub(/^http(s?):/, 'ws\1:'), endpoint('/websocket')).to_s
31
- headers = { "Authorization" => "Bearer #{@token}" }
32
-
33
- EM.run do
34
- @ws = Faye::WebSocket::Client.new(ws_url, {}, { headers: headers, ping: 60})
35
-
36
- @ws.on :open do |e|
37
- Qbot.app.logger.info("#{self.class} - Websocket connection opened")
38
- end
39
-
40
- @ws.on :close do |e|
41
- Qbot.app.logger.info("#{self.class} - Websocket connection closed")
42
- stop if @error
43
- on_message(&block) # restart
44
- end
45
-
46
- @ws.on :error do |e|
47
- Qbot.app.logger.error("#{self.class} - #{e.message}")
48
- @error = true
49
- end
50
-
51
- @ws.on :message do |e|
52
- data = JSON.parse(e.data)
53
- emit_event(data, block)
54
- end
55
- end
29
+ def listen(&block)
30
+ EM.run { start_connection(&block) }
56
31
  end
57
32
 
58
- def stop
33
+ def close
59
34
  EM.stop
60
35
  end
61
36
 
62
37
  def post(text, **options)
63
- api_call(:post, "/posts", body: options.merge(message: text))
38
+ resp = api_call(:post, "/posts", body: options.merge(message: text))
39
+ Qbot.app.logger.info("#{self.class} - Post message: #{resp.status} - '#{text}'")
64
40
  end
65
41
 
66
42
  def reply_to(message, text, **options)
@@ -82,27 +58,54 @@ module Qbot
82
58
  URI(@mm_url).path + "/api/v4#{path}"
83
59
  end
84
60
 
61
+ def start_connection(&block)
62
+ running = true
63
+ ws_url = URI.join(@server.gsub(/^http(s?):/, 'ws\1:'), endpoint('/websocket')).to_s
64
+
65
+ ws = Faye::WebSocket::Client.new(ws_url)
66
+ ws.send({seq: 1, action: 'authentication_challenge', data: {token: @token}}.to_json)
67
+
68
+ ws.on :message do |e|
69
+ data = JSON.parse(e.data)
70
+ emit_event(data, block)
71
+ end
72
+
73
+ ws.on :open do |e|
74
+ Qbot.app.logger.info("#{self.class} - Websocket connection opened")
75
+ end
76
+
77
+ ws.on :close do |e|
78
+ Qbot.app.logger.info("#{self.class} - Websocket connection closed: #{e.code} #{e.reason}")
79
+ if running then start_connection(&block) else Qbot.app.stop end
80
+ end
81
+
82
+ ws.on :error do |e|
83
+ Qbot.app.logger.error("#{self.class} - Websocket encountered error: #{e.message}")
84
+ running = false
85
+ end
86
+ end
87
+
85
88
  def emit_event(data, callback)
86
- event = data['event'].to_sym
87
- Qbot.app.logger.debug("#{self.class} - Event '#{event}' recieved")
89
+ return unless type = data['event']
90
+ Qbot.app.logger.debug("#{self.class} - Event '#{type}' recieved")
88
91
 
89
- case event
90
- when :posted
92
+ case type
93
+ when 'posted'
91
94
  post = JSON.parse(data['data']['post'])
92
95
 
93
96
  message = Qbot::Message.new
94
97
  message.data = post
95
98
  message.text = post['message']
96
99
 
97
- Qbot.app.logger.info("#{self.class} - Message was '#{message.text}'")
98
100
  callback.call(message)
99
101
  end
102
+ rescue => err
103
+ Qbot.app.logger.error("#{self.class} - ERROR! #{err}")
100
104
  end
101
105
 
102
106
  def api_call(method, path, **options, &block)
103
107
  headers = { "Authorization" => "Bearer #{@token}", "Accept" => "application/json" }
104
-
105
- connection = Faraday::Connection.new(url: @server, headers: headers ) do |con|
108
+ connection = Faraday::Connection.new(url: @server, headers: headers) do |con|
106
109
  con.response :json
107
110
  con.adapter :httpclient
108
111
  end
@@ -27,10 +27,14 @@ module Qbot
27
27
  end
28
28
  end
29
29
 
30
- def on_message(&block)
30
+ def listen(&block)
31
31
  EM.run { EM.open_keyboard(Keyboard, block) }
32
32
  end
33
33
 
34
+ def close
35
+ EM.stop
36
+ end
37
+
34
38
  def post(text, **options)
35
39
  $stdout.puts text
36
40
  end
@@ -13,7 +13,6 @@ module Qbot
13
13
 
14
14
  def initialize(api_token: nil)
15
15
  @server = URI.join(SLACK_API_URL, '/').to_s
16
- @error = false
17
16
 
18
17
  access_token(api_token || ENV['QBOT_SLACK_API_TOKEN'])
19
18
  end
@@ -22,42 +21,17 @@ module Qbot
22
21
  @token = token
23
22
  end
24
23
 
25
- def on_message(&block)
26
- resp = api_call(:get, '/rtm.start')
27
- data = JSON.parse(resp.body)
28
- ws_url = data['url']
29
-
30
- EM.run do
31
- @ws = Faye::WebSocket::Client.new(ws_url, {}, { ping: 60})
32
-
33
- @ws.on :open do |e|
34
- Qbot.app.logger.info("#{self.class} - Websocket connection opened")
35
- end
36
-
37
- @ws.on :close do |e|
38
- Qbot.app.logger.info("#{self.class} - Websocket connection closed")
39
- stop if @error
40
- on_message(&block) # restart
41
- end
42
-
43
- @ws.on :error do |e|
44
- Qbot.app.logger.error("#{self.class} - #{e.message}")
45
- @error = true
46
- end
47
-
48
- @ws.on :message do |e|
49
- data = JSON.parse(e.data)
50
- emit_event(data, block)
51
- end
52
- end
24
+ def listen(&block)
25
+ EM.run { start_connection(&block) }
53
26
  end
54
27
 
55
- def stop
28
+ def close
56
29
  EM.stop
57
30
  end
58
31
 
59
32
  def post(text, **options)
60
- api_call(:post, "/chat.postMessage", options.merge(text: text))
33
+ resp = api_call(:post, "/chat.postMessage", options.merge(text: text))
34
+ Qbot.app.logger.info("#{self.class} - Post message: #{resp.status} - '#{text}'")
61
35
  end
62
36
 
63
37
  def reply_to(message, text, **options)
@@ -79,19 +53,46 @@ module Qbot
79
53
  URI(SLACK_API_URL).path + path
80
54
  end
81
55
 
56
+ def start_connection(&block)
57
+ resp = api_call(:get, '/rtm.start')
58
+ data = JSON.parse(resp.body)
59
+
60
+ running = true
61
+ ws_url = data['url']
62
+ ws = Faye::WebSocket::Client.new(ws_url, nil, {ping: 60})
63
+
64
+ ws.on :message do |e|
65
+ data = JSON.parse(e.data)
66
+ emit_event(data, block)
67
+ end
68
+
69
+ ws.on :open do |e|
70
+ Qbot.app.logger.info("#{self.class} - Websocket connection opened")
71
+ end
72
+
73
+ ws.on :close do |e|
74
+ Qbot.app.logger.info("#{self.class} - Websocket connection closed: #{e.code} #{e.reason}")
75
+ if running then start_connection(&block) else Qbot.app.stop end
76
+ end
77
+
78
+ ws.on :error do |e|
79
+ Qbot.app.logger.error("#{self.class} - Websocket encountered error: #{e.message}")
80
+ running = false
81
+ end
82
+ end
83
+
82
84
  def emit_event(data, callback)
83
- event = data['type'].to_sym
84
- Qbot.app.logger.debug("#{self.class} - Event '#{event}' recieved")
85
+ return unless type = data['event']
86
+ Qbot.app.logger.debug("#{self.class} - Event '#{type}' recieved")
85
87
 
86
- case event
87
- when :message
88
+ case type
89
+ when 'message'
88
90
  return if data['subtype']
89
91
 
90
92
  message = Qbot::Message.new
91
93
  message.data = data
92
94
  message.text = data['text']
93
95
 
94
- Qbot.app.logger.info("#{self.class} - Message was '#{message.text}'")
95
96
  callback.call(message)
96
97
  end
97
98
  end
@@ -41,16 +41,18 @@ module Qbot
41
41
 
42
42
  def start
43
43
  @logger.info("Booting #{self.class}.")
44
- @logger.info("#{storage.class} - Storage driver loaded")
45
- @logger.info("#{adapter.class} - Adapter driver loaded")
44
+ @logger.info("#{storage.class} - Storage driver loaded.")
45
+ @logger.info("#{adapter.class} - Adapter driver loaded.")
46
+ bots.each { |bot| @logger.info("Loading #{bot}.") }
46
47
 
48
+ Thread.abort_on_exception = true
47
49
  @threads << Thread.start { loop { @timers.wait } }
48
50
  @threads << Thread.start { adapter.run(@bots) }
49
51
  @threads.each { |th| th.join }
50
52
  end
51
53
 
52
54
  def stop
53
- adapter.stop if adapter.respond_to?(:stop)
55
+ adapter.close if adapter.respond_to?(:close)
54
56
  @threads.each { |th| th.kill if th }
55
57
  end
56
58
 
@@ -1,5 +1,3 @@
1
- require 'qbot/embed/help'
2
-
3
1
  module Qbot
4
2
 
5
3
  def self.autorun
@@ -1,5 +1,5 @@
1
- require 'parse-cron'
2
1
  require 'dotenv/load'
2
+ require 'parse-cron'
3
3
 
4
4
  require 'qbot/app'
5
5
  require 'qbot/adapter'
@@ -22,15 +22,7 @@ module Qbot
22
22
  schedule(pattern, &block)
23
23
  end
24
24
 
25
- def usage(text)
26
- on(/^#{prefix}help\s+#{name.downcase}\b/) { post(text) }
27
- end
28
-
29
25
  private
30
- def prefix
31
- "#{ENV['QBOT_PREFIX']}\s+" if ENV['QBOT_PREFIX']
32
- end
33
-
34
26
  def schedule(pattern, &block)
35
27
  parser = CronParser.new(pattern)
36
28
  current = Time.now
@@ -53,7 +45,12 @@ module Qbot
53
45
  @message = message
54
46
  return unless @pattern =~ @message.text.to_s.strip
55
47
 
56
- instance_exec($~, &@callback)
48
+ begin
49
+ Qbot.app.logger.debug("#{self.class} - Recieve message: '#{message.text}'")
50
+ instance_exec($~, &@callback)
51
+ rescue => e
52
+ Qbot.app.logger.error("#{self.class} - Error: #{e}")
53
+ end
57
54
  end
58
55
 
59
56
  def post(text, **options)
@@ -1,3 +1,3 @@
1
1
  module Qbot
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -30,6 +30,6 @@ Gem::Specification.new do |spec|
30
30
  spec.add_dependency "leveldb", "~> 0.1"
31
31
  spec.add_dependency "faraday", "~> 0.14"
32
32
  spec.add_dependency "faraday_middleware", "~> 0.12"
33
- spec.add_dependency "httpclient", ">= 2.2"
33
+ spec.add_dependency "httpclient", ">= 2.6"
34
34
  spec.add_dependency "faye-websocket", "~> 0.10"
35
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qbot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - haccht
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-31 00:00:00.000000000 Z
11
+ date: 2018-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - ">="
130
130
  - !ruby/object:Gem::Version
131
- version: '2.2'
131
+ version: '2.6'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
- version: '2.2'
138
+ version: '2.6'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: faye-websocket
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -175,7 +175,6 @@ files:
175
175
  - lib/qbot/base.rb
176
176
  - lib/qbot/embed/cron.rb
177
177
  - lib/qbot/embed/echo.rb
178
- - lib/qbot/embed/help.rb
179
178
  - lib/qbot/embed/ping.rb
180
179
  - lib/qbot/storage.rb
181
180
  - lib/qbot/storage/leveldb.rb
@@ -202,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
201
  version: '0'
203
202
  requirements: []
204
203
  rubyforge_project:
205
- rubygems_version: 2.7.6
204
+ rubygems_version: 2.6.14.1
206
205
  signing_key:
207
206
  specification_version: 4
208
207
  summary: Tiny chatbot flamework.
@@ -1,22 +0,0 @@
1
- require 'stringio'
2
-
3
- module Qbot
4
-
5
- class Help < Qbot::Base
6
-
7
- on /^#{prefix}help$/ do |msg|
8
- names = Qbot.app.bots
9
- .reject { |n| %w(Qbot::Base Qbot::Help).include?(n) }
10
- .map { |n| n.split('::').last.downcase }
11
-
12
- next if names.empty?
13
- resp = StringIO.new
14
- resp.puts 'Features:'
15
- resp.puts names.map { |name| " #{name}" }
16
-
17
- post resp.string
18
- end
19
-
20
- end
21
-
22
- end