rodbot 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +5 -0
- data/checksums/rodbot-0.3.0.gem.sha512 +1 -0
- data/lib/rodbot/memoize.rb +21 -12
- data/lib/rodbot/plugins/otp/README.otp.md +6 -2
- data/lib/rodbot/plugins/otp/app.rb +2 -4
- data/lib/rodbot/plugins/slack/README.slack.md +48 -0
- data/lib/rodbot/plugins/slack/relay.rb +79 -0
- data/lib/rodbot/version.rb +1 -1
- data/lib/templates/new/gems.rb +5 -0
- data/rodbot.gemspec +3 -1
- data.tar.gz.sig +0 -0
- metadata +37 -6
- metadata.gz.sig +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4e3022218a7df9e0e16b2430fa3144a9abfadc49242fd439f48945709fb20e2
|
4
|
+
data.tar.gz: b1dbe4adfd865bdcb0ee107bbff5806705470961ba721da97d04ac92e1bba3ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96a4262cbeaa00e9548d962014fd63353aac9c1a48843f5d5c082c66c306aeb5ccaee1660f0a501e9af104293eb68d80108deb9d1fae1a017aaa9ec327fcaf66
|
7
|
+
data.tar.gz: b2977391b972eeafad320e4dd54cf8f51a2b79a6efcea9f05f314caf912dbc6f9c1d961998afd11d78a61e3c8e12c61226993e3c564aee9220305f2f80c4da04
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
789b796fc2127afbb1850f083f9b3255a31a4dfe570e0a0c75b7ed2be9bbf736c89d418233b0c855656b75e87da2d8e3c9f31ffe0932f8a5c37461f9e4ddabc5
|
data/lib/rodbot/memoize.rb
CHANGED
@@ -39,7 +39,10 @@ module Rodbot
|
|
39
39
|
# e.either(keyword: 2) # => 2 (memoized)
|
40
40
|
# e.either { 3 } # => :not_nil (cannot be memoized)
|
41
41
|
# Rodbot::Memoize.suspend do
|
42
|
-
# e.either(1) # => 1 (
|
42
|
+
# e.either(1) # => 1 (recalculated, not memoized)
|
43
|
+
# end
|
44
|
+
# Rodbot::Memoize.revisit do
|
45
|
+
# e.either(5) # => 5 (recalculated, memoized anew)
|
43
46
|
# end
|
44
47
|
module Memoize
|
45
48
|
module ClassMethods
|
@@ -47,12 +50,12 @@ module Rodbot
|
|
47
50
|
unmemoized_method = :"_unmemoized_#{method}"
|
48
51
|
alias_method unmemoized_method, method
|
49
52
|
define_method method do |*args, **kargs, &block|
|
50
|
-
if Rodbot::Memoize.
|
53
|
+
if Rodbot::Memoize.suspend? || block
|
51
54
|
send(unmemoized_method, *args, **kargs, &block)
|
52
55
|
else
|
53
56
|
id = method.hash ^ args.hash ^ kargs.hash
|
54
57
|
@_memoize_cache ||= {}
|
55
|
-
if @_memoize_cache.has_key?
|
58
|
+
if !Rodbot::Memoize.revisit? && @_memoize_cache.has_key?(id)
|
56
59
|
@_memoize_cache[id]
|
57
60
|
else
|
58
61
|
@_memoize_cache[id] = send(unmemoized_method, *args, **kargs)
|
@@ -64,16 +67,22 @@ module Rodbot
|
|
64
67
|
end
|
65
68
|
|
66
69
|
class << self
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
%i(suspend revisit).each do |switch|
|
71
|
+
ivar = "@#{switch}"
|
72
|
+
define_method switch do |&block|
|
73
|
+
instance_variable_set(ivar, true)
|
74
|
+
block.call
|
75
|
+
ensure
|
76
|
+
instance_variable_set(ivar, false)
|
77
|
+
end
|
73
78
|
|
74
|
-
|
75
|
-
|
76
|
-
|
79
|
+
define_method "#{switch}?" do
|
80
|
+
if instance_variable_defined? ivar
|
81
|
+
instance_variable_get ivar
|
82
|
+
else
|
83
|
+
instance_variable_set(ivar, false)
|
84
|
+
end
|
85
|
+
end
|
77
86
|
end
|
78
87
|
|
79
88
|
def included(base)
|
@@ -47,7 +47,7 @@ module Routes
|
|
47
47
|
end
|
48
48
|
```
|
49
49
|
|
50
|
-
|
50
|
+
As a reminder: In the above example, `r.arguments` is a mere shortcut for `r.params['arguments']`.
|
51
51
|
|
52
52
|
In order to protect this rather dangerous command with a one-time password, you have to guard the route:
|
53
53
|
|
@@ -66,7 +66,9 @@ To execute the command now, you have to add the six digit one-time password to t
|
|
66
66
|
!reboot example.com 123456
|
67
67
|
```
|
68
68
|
|
69
|
-
The `r.valid_otp?` guard extracts the one-time password from the message and validates it. In this example, a validation result `true` causes the server to be rebooted.
|
69
|
+
The `r.valid_otp?` guard extracts the one-time password from the message and validates it. In this example, a validation result `true` causes the server to be rebooted.
|
70
|
+
|
71
|
+
Please note that `r.valid_otp?` redefines `r.arguments` to no longer include the password.
|
70
72
|
|
71
73
|
If halting with a 401 error is all you want, there's even a shorter alternative `r.require_valid_otp!`:
|
72
74
|
|
@@ -80,3 +82,5 @@ end
|
|
80
82
|
```
|
81
83
|
|
82
84
|
This route does exactly the same as the more verbose one above.
|
85
|
+
|
86
|
+
Please note that `r.require_valid_otp!` redefines `r.arguments` to no longer include the password.
|
@@ -11,6 +11,7 @@ module Rodbot
|
|
11
11
|
include Rodbot::Memoize
|
12
12
|
|
13
13
|
def valid_otp?
|
14
|
+
def self.arguments = params['arguments'].sub(/\s*\d{6}\s*\z/, '')
|
14
15
|
return false unless password
|
15
16
|
return false if Rodbot.db.get(:otp, password) # already used
|
16
17
|
!!if totp.verify(password, drift_behind: Rodbot.config(:otp, :drift).to_i)
|
@@ -34,10 +35,7 @@ module Rodbot
|
|
34
35
|
#
|
35
36
|
# @return [String, nil] extracted password if any
|
36
37
|
memoize def password
|
37
|
-
|
38
|
-
params['arguments'] = params['arguments'].sub(/\s*(\d{6})\s*\z/, '')
|
39
|
-
$1
|
40
|
-
end
|
38
|
+
params['arguments']&.match(/\s*(\d{6})\s*\z/)&.captures&.first
|
41
39
|
end
|
42
40
|
end
|
43
41
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Rodbot Plugin – Slack
|
2
|
+
|
3
|
+
Relay with the Slack communication network
|
4
|
+
|
5
|
+
## Preparation
|
6
|
+
|
7
|
+
To get an `access_token`, you have to follow the [basic app setup guide](https://api.slack.com/authentication/basics):
|
8
|
+
|
9
|
+
1. [Create a new Slack classic app](https://api.slack.com/apps?new_classic_app=1)
|
10
|
+
2. In the overlay: Give the app a name and pick the workspace for the app and the bot.
|
11
|
+
3. In the sidebar: Click on "Basic Information", unfold "Add features and functionality" and hit "Bots". Then click the "Add Legacy Bot User" button and in the overlay enter the display name (used e.g in the user list) and user name (used e.g. for mentions). Optionally activate "Always Show My Bot as Online".
|
12
|
+
4. In the sidebar: Click on "Basic Information" again, scroll down to "Display Information" to set an app icon, color and descriptions. Click "Save Changes" when done".
|
13
|
+
5. Scroll up and click the "Install to Workspace" button, then click "Allow".
|
14
|
+
6. In the sidebar: Click on "Basic Information" again, scroll down to "App Credentials" and copy the "Signing Secret" which will be used as `signing_secret` below.
|
15
|
+
7. In the sidebar: Click on "OAuth and Permissions" and copy the "Bot User OAuth Token" (starting with "xoxb-") which will be used as `access_token` below.
|
16
|
+
|
17
|
+
With the app in place, open the Slack client with your normal user, then:
|
18
|
+
|
19
|
+
1. Select the channel you want the bot to be present in.
|
20
|
+
2. In the upper right corner click on "View all members of this channel".
|
21
|
+
3. Select the "Integrations" tab, then click on "Add apps" and add the app you've just created.
|
22
|
+
4. Select the "About" tab, scroll all the way down and note the `channel_id` to be used below.
|
23
|
+
|
24
|
+
## Activation
|
25
|
+
|
26
|
+
Install the required gems via the corresponding Bundler group:
|
27
|
+
|
28
|
+
```
|
29
|
+
bundle config set --local with slack
|
30
|
+
bundle install
|
31
|
+
```
|
32
|
+
|
33
|
+
Then activate and configure this plugin in `config/rodbot.rb`:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
plugin :slack do
|
37
|
+
access_token '<TOKEN>'
|
38
|
+
channel_id '<CHANNEL_ID>'
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
You might want to use the credentials facilities of Rodbot to encrypt the token.
|
43
|
+
|
44
|
+
## Usage
|
45
|
+
|
46
|
+
Once Rodbot is restarted, the Slack relay starts listening. To check whether the relay works fine, just say +!ping+ in the channel, you should receive a "pong" in reply.
|
47
|
+
|
48
|
+
Any room message beginning with "!" is considered a bot command.
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'slack-ruby-client'
|
4
|
+
|
5
|
+
using Rodbot::Refinements
|
6
|
+
|
7
|
+
module Rodbot
|
8
|
+
class Plugins
|
9
|
+
class Slack
|
10
|
+
class Relay < Rodbot::Relay
|
11
|
+
include Rodbot::Memoize
|
12
|
+
|
13
|
+
def loops
|
14
|
+
::Slack.configure do |config|
|
15
|
+
config.token = access_token
|
16
|
+
end
|
17
|
+
[method(:read_loop), method(:write_loop)]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def access_token
|
23
|
+
Rodbot.config(:plugin, :slack, :access_token)
|
24
|
+
rescue => error
|
25
|
+
raise Rodbot::PluginError.new("invalid access_token", error.message)
|
26
|
+
end
|
27
|
+
|
28
|
+
memoize def client
|
29
|
+
::Slack::RealTime::Client.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def channel_id
|
33
|
+
Rodbot.config(:plugin, :slack, :channel_id)
|
34
|
+
rescue => error
|
35
|
+
raise Rodbot::PluginError.new("invalid channel_id", error.message)
|
36
|
+
end
|
37
|
+
|
38
|
+
def write_loop
|
39
|
+
server = TCPServer.new(*bind)
|
40
|
+
loop do
|
41
|
+
Thread.start(server.accept) do |remote|
|
42
|
+
body = remote.gets("\x04")
|
43
|
+
remote.close
|
44
|
+
body.force_encoding('UTF-8')
|
45
|
+
client.web_client.chat_postMessage(channel: channel_id, text: body, as_user: true)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def read_loop
|
51
|
+
client.on :message do |message|
|
52
|
+
on_message(message) if message.channel == channel_id
|
53
|
+
end
|
54
|
+
client.start!
|
55
|
+
end
|
56
|
+
|
57
|
+
def on_message(message)
|
58
|
+
if message.text.start_with?('!')
|
59
|
+
md = 'pong' if message.text == '!ping'
|
60
|
+
md ||= reply_to(message)
|
61
|
+
client.web_client.chat_postMessage(channel: message.channel, text: md, as_user: true)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def reply_to(message)
|
66
|
+
command(*message.text[1..].split(/\s+/, 2)).
|
67
|
+
psub(placeholders(message.user))
|
68
|
+
end
|
69
|
+
|
70
|
+
def placeholders(sender)
|
71
|
+
{
|
72
|
+
sender: "<@#{sender}>"
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/rodbot/version.rb
CHANGED
data/lib/templates/new/gems.rb
CHANGED
data/rodbot.gemspec
CHANGED
@@ -58,8 +58,10 @@ Gem::Specification.new do |spec|
|
|
58
58
|
|
59
59
|
# Sync versions with lib/templates/new/gems.rb
|
60
60
|
spec.add_development_dependency 'redis', '~> 5'
|
61
|
-
spec.add_development_dependency 'matrix_sdk', '~> 2'
|
62
61
|
spec.add_development_dependency 'rotp', '~> 6'
|
62
|
+
spec.add_development_dependency 'matrix_sdk', '~> 2'
|
63
|
+
spec.add_development_dependency 'slack-ruby-client', '~> 2'
|
64
|
+
spec.add_development_dependency 'async-websocket', '~> 0.8.0'
|
63
65
|
|
64
66
|
spec.add_development_dependency 'rake'
|
65
67
|
spec.add_development_dependency 'minitest'
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Schwyn
|
@@ -29,7 +29,7 @@ cert_chain:
|
|
29
29
|
kAyiRqgxF4dJviwtqI7mZIomWL63+kXLgjOjMe1SHxfIPo/0ji6+r1p4KYa7o41v
|
30
30
|
fwIwU1MKlFBdsjkd
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date: 2023-
|
32
|
+
date: 2023-10-11 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: zeitwerk
|
@@ -247,6 +247,20 @@ dependencies:
|
|
247
247
|
- - "~>"
|
248
248
|
- !ruby/object:Gem::Version
|
249
249
|
version: '5'
|
250
|
+
- !ruby/object:Gem::Dependency
|
251
|
+
name: rotp
|
252
|
+
requirement: !ruby/object:Gem::Requirement
|
253
|
+
requirements:
|
254
|
+
- - "~>"
|
255
|
+
- !ruby/object:Gem::Version
|
256
|
+
version: '6'
|
257
|
+
type: :development
|
258
|
+
prerelease: false
|
259
|
+
version_requirements: !ruby/object:Gem::Requirement
|
260
|
+
requirements:
|
261
|
+
- - "~>"
|
262
|
+
- !ruby/object:Gem::Version
|
263
|
+
version: '6'
|
250
264
|
- !ruby/object:Gem::Dependency
|
251
265
|
name: matrix_sdk
|
252
266
|
requirement: !ruby/object:Gem::Requirement
|
@@ -262,19 +276,33 @@ dependencies:
|
|
262
276
|
- !ruby/object:Gem::Version
|
263
277
|
version: '2'
|
264
278
|
- !ruby/object:Gem::Dependency
|
265
|
-
name:
|
279
|
+
name: slack-ruby-client
|
266
280
|
requirement: !ruby/object:Gem::Requirement
|
267
281
|
requirements:
|
268
282
|
- - "~>"
|
269
283
|
- !ruby/object:Gem::Version
|
270
|
-
version: '
|
284
|
+
version: '2'
|
271
285
|
type: :development
|
272
286
|
prerelease: false
|
273
287
|
version_requirements: !ruby/object:Gem::Requirement
|
274
288
|
requirements:
|
275
289
|
- - "~>"
|
276
290
|
- !ruby/object:Gem::Version
|
277
|
-
version: '
|
291
|
+
version: '2'
|
292
|
+
- !ruby/object:Gem::Dependency
|
293
|
+
name: async-websocket
|
294
|
+
requirement: !ruby/object:Gem::Requirement
|
295
|
+
requirements:
|
296
|
+
- - "~>"
|
297
|
+
- !ruby/object:Gem::Version
|
298
|
+
version: 0.8.0
|
299
|
+
type: :development
|
300
|
+
prerelease: false
|
301
|
+
version_requirements: !ruby/object:Gem::Requirement
|
302
|
+
requirements:
|
303
|
+
- - "~>"
|
304
|
+
- !ruby/object:Gem::Version
|
305
|
+
version: 0.8.0
|
278
306
|
- !ruby/object:Gem::Dependency
|
279
307
|
name: rake
|
280
308
|
requirement: !ruby/object:Gem::Requirement
|
@@ -421,6 +449,7 @@ files:
|
|
421
449
|
- checksums/rodbot-0.1.0.pre9.gem.sha512
|
422
450
|
- checksums/rodbot-0.1.1.gem.sha512
|
423
451
|
- checksums/rodbot-0.2.0.gem.sha512
|
452
|
+
- checksums/rodbot-0.3.0.gem.sha512
|
424
453
|
- doc/rodbot.afphoto
|
425
454
|
- doc/rodbot.avif
|
426
455
|
- exe/rodbot
|
@@ -462,6 +491,8 @@ files:
|
|
462
491
|
- lib/rodbot/plugins/matrix/relay.rb
|
463
492
|
- lib/rodbot/plugins/otp/README.otp.md
|
464
493
|
- lib/rodbot/plugins/otp/app.rb
|
494
|
+
- lib/rodbot/plugins/slack/README.slack.md
|
495
|
+
- lib/rodbot/plugins/slack/relay.rb
|
465
496
|
- lib/rodbot/plugins/word_of_the_day/README.word_of_the_day.md
|
466
497
|
- lib/rodbot/plugins/word_of_the_day/schedule.rb
|
467
498
|
- lib/rodbot/rack.rb
|
@@ -531,7 +562,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
531
562
|
- !ruby/object:Gem::Version
|
532
563
|
version: '0'
|
533
564
|
requirements: []
|
534
|
-
rubygems_version: 3.4.
|
565
|
+
rubygems_version: 3.4.20
|
535
566
|
signing_key:
|
536
567
|
specification_version: 4
|
537
568
|
summary: Minimalistic framework to build chat bots on top of a Roda backend
|
metadata.gz.sig
CHANGED