waylon-core 0.1.1 → 0.1.2
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 +4 -4
- data/.rubocop.yml +8 -1
- data/.ruby-version +1 -1
- data/Gemfile.lock +9 -9
- data/lib/waylon/condition.rb +26 -1
- data/lib/waylon/conditions/black_hole.rb +34 -0
- data/lib/waylon/conditions/regex.rb +5 -0
- data/lib/waylon/config.rb +3 -2
- data/lib/waylon/core.rb +5 -0
- data/lib/waylon/group.rb +1 -1
- data/lib/waylon/logger.rb +1 -1
- data/lib/waylon/message.rb +19 -0
- data/lib/waylon/route.rb +1 -1
- data/lib/waylon/routes/black_hole.rb +17 -0
- data/lib/waylon/rspec/matchers/route_matcher.rb +7 -0
- data/lib/waylon/rspec/skill.rb +1 -1
- data/lib/waylon/rspec/test_message.rb +2 -0
- data/lib/waylon/rspec/test_sense.rb +21 -15
- data/lib/waylon/rspec/test_worker.rb +2 -2
- data/lib/waylon/sense.rb +5 -6
- data/lib/waylon/sense_registry.rb +2 -0
- data/lib/waylon/skill.rb +54 -21
- data/lib/waylon/skill_registry.rb +47 -10
- data/lib/waylon/skills/default.rb +5 -0
- data/lib/waylon/skills/diagnostics.rb +58 -0
- data/lib/waylon/skills/fun.rb +5 -2
- data/lib/waylon/skills/groups.rb +167 -0
- data/lib/waylon/skills/help.rb +174 -0
- data/lib/waylon/user.rb +5 -0
- data/lib/waylon/version.rb +1 -1
- data/lib/waylon/webhook.rb +24 -25
- data/lib/waylon.rb +3 -0
- data/waylon-core.gemspec +1 -1
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf4a171a8420b5e982d54cf24b991a7ae667f3aa93f08b361d10ac28d9726207
|
4
|
+
data.tar.gz: 63982b47f1c05134c4fa5c69d07c4e05e8a1d748c245a4d7bd0695dabe4171c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17a2baf807fd68312c76da6d9d1ca328ed5e5fec065711a7b8ce14a7d86850843d3ce2f6cfa3d4ea26f3c3ce30f329796427deeb98dcd6df77ec181da0afaf3f
|
7
|
+
data.tar.gz: 3edb93a7e82655d44d553687493d11a0a7559b6ae318ffb92051d481872c882baa2c6191a88e96ddd3936df278844e1caee97837f15523fd2158275d0a84eb03
|
data/.rubocop.yml
CHANGED
@@ -21,7 +21,10 @@ Gemspec/RequireMFA:
|
|
21
21
|
Enabled: false
|
22
22
|
|
23
23
|
Metrics/AbcSize:
|
24
|
-
Max: 19
|
24
|
+
Max: 19.5
|
25
|
+
|
26
|
+
Metrics/ClassLength:
|
27
|
+
Max: 200
|
25
28
|
|
26
29
|
Metrics/CyclomaticComplexity:
|
27
30
|
Max: 9
|
@@ -32,7 +35,11 @@ Metrics/PerceivedComplexity:
|
|
32
35
|
Metrics/MethodLength:
|
33
36
|
Max: 20
|
34
37
|
|
38
|
+
Metrics/ParameterLists:
|
39
|
+
Max: 6
|
40
|
+
|
35
41
|
Metrics/BlockLength:
|
36
42
|
Exclude:
|
37
43
|
- "**/*_spec.rb"
|
38
44
|
- "*.gemspec"
|
45
|
+
- "lib/waylon/rspec/matchers/**/*.rb"
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.0
|
1
|
+
3.1.0
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
waylon-core (0.1.
|
4
|
+
waylon-core (0.1.2)
|
5
5
|
addressable (~> 2.8)
|
6
6
|
faraday (~> 1.8)
|
7
7
|
i18n (~> 1.8)
|
@@ -17,7 +17,7 @@ GEM
|
|
17
17
|
public_suffix (>= 2.0.2, < 5.0)
|
18
18
|
ast (2.4.2)
|
19
19
|
concurrent-ruby (1.1.9)
|
20
|
-
diff-lcs (1.
|
20
|
+
diff-lcs (1.5.0)
|
21
21
|
docile (1.4.0)
|
22
22
|
faraday (1.9.3)
|
23
23
|
faraday-em_http (~> 1.0)
|
@@ -53,7 +53,7 @@ GEM
|
|
53
53
|
ruby2_keywords (~> 0.0.1)
|
54
54
|
nio4r (2.5.8)
|
55
55
|
parallel (1.21.0)
|
56
|
-
parser (3.0.
|
56
|
+
parser (3.1.0.0)
|
57
57
|
ast (~> 2.4.1)
|
58
58
|
public_suffix (4.0.6)
|
59
59
|
puma (5.5.2)
|
@@ -87,20 +87,20 @@ GEM
|
|
87
87
|
diff-lcs (>= 1.2.0, < 2.0)
|
88
88
|
rspec-support (~> 3.10.0)
|
89
89
|
rspec-support (3.10.3)
|
90
|
-
rubocop (1.
|
90
|
+
rubocop (1.24.1)
|
91
91
|
parallel (~> 1.10)
|
92
92
|
parser (>= 3.0.0.0)
|
93
93
|
rainbow (>= 2.2.2, < 4.0)
|
94
94
|
regexp_parser (>= 1.8, < 3.0)
|
95
95
|
rexml
|
96
|
-
rubocop-ast (>= 1.
|
96
|
+
rubocop-ast (>= 1.15.1, < 2.0)
|
97
97
|
ruby-progressbar (~> 1.7)
|
98
98
|
unicode-display_width (>= 1.4.0, < 3.0)
|
99
|
-
rubocop-ast (1.15.
|
99
|
+
rubocop-ast (1.15.1)
|
100
100
|
parser (>= 3.0.1.1)
|
101
101
|
rubocop-rake (0.6.0)
|
102
102
|
rubocop (~> 1.0)
|
103
|
-
rubocop-rspec (2.
|
103
|
+
rubocop-rspec (2.7.0)
|
104
104
|
rubocop (~> 1.19)
|
105
105
|
ruby-progressbar (1.11.0)
|
106
106
|
ruby2_keywords (0.0.5)
|
@@ -127,7 +127,7 @@ PLATFORMS
|
|
127
127
|
arm64-darwin-21
|
128
128
|
|
129
129
|
DEPENDENCIES
|
130
|
-
bundler (~> 2.
|
130
|
+
bundler (~> 2.3)
|
131
131
|
rake (~> 13.0)
|
132
132
|
rspec (~> 3.10)
|
133
133
|
rubocop (~> 1.23)
|
@@ -138,4 +138,4 @@ DEPENDENCIES
|
|
138
138
|
yard (~> 0.9, >= 0.9.27)
|
139
139
|
|
140
140
|
BUNDLED WITH
|
141
|
-
2.
|
141
|
+
2.3.4
|
data/lib/waylon/condition.rb
CHANGED
@@ -10,19 +10,37 @@ module Waylon
|
|
10
10
|
# @param action [Symbol] The method to call if the condition matches
|
11
11
|
# @param allowed_groups [Array<Symbol>] The group names allowed to use this action
|
12
12
|
# @param help [String] Optional help text to describe usage for this action
|
13
|
-
|
13
|
+
# @param mention_only [Boolean] Only applies to messages that directly mention (or IM) this bot
|
14
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
15
|
+
def initialize(mechanism, action, allowed_groups, help = nil, mention_only = true)
|
14
16
|
@mechanism = mechanism
|
15
17
|
@action = action
|
16
18
|
@allowed_groups = allowed_groups
|
17
19
|
@help = help
|
20
|
+
@mention_only = mention_only
|
18
21
|
end
|
22
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
19
23
|
|
20
24
|
# Placeholder for determining if this condition applies to the given input
|
21
25
|
# @param _input [Waylon::Message] The input message
|
26
|
+
# @return [Boolean]
|
22
27
|
def matches?(_input)
|
23
28
|
false
|
24
29
|
end
|
25
30
|
|
31
|
+
# Is this condition only valid for Messages that directly mention the bot?
|
32
|
+
# @return [Boolean]
|
33
|
+
def mention_only?
|
34
|
+
@mention_only
|
35
|
+
end
|
36
|
+
|
37
|
+
# Placeholder for optionally providing _named_ tokens
|
38
|
+
# @param _input [String] The message content
|
39
|
+
# @return [Hash<String,Object>]
|
40
|
+
def named_tokens(_input)
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
|
26
44
|
# Checks if a user is allowed based on this condition
|
27
45
|
# @param user [Waylon::User] abstract user
|
28
46
|
def permits?(user)
|
@@ -44,6 +62,13 @@ module Waylon
|
|
44
62
|
permitted
|
45
63
|
end
|
46
64
|
|
65
|
+
# Determines of a message complies with the {#mention_only?} setting for this condition
|
66
|
+
# @param message [Waylon::Message] The received message
|
67
|
+
# @return [Boolean]
|
68
|
+
def properly_mentions?(message)
|
69
|
+
(mention_only? && message.to_bot?) || (!mention_only? && !message.to_bot?)
|
70
|
+
end
|
71
|
+
|
47
72
|
# Tokens is used to provide details about the message input to the action
|
48
73
|
# @param _input [String] The message content as text
|
49
74
|
# @return [Array<String>] The tokens extracted from the input message
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
module Conditions
|
5
|
+
# A pre-made catch-all condition for ignoring messages
|
6
|
+
class BlackHole < Condition
|
7
|
+
# Overrides normal Condition initialization to force a specific action
|
8
|
+
def initialize(*_args) # rubocop:disable Lint/MissingSuper
|
9
|
+
@mechanism = nil
|
10
|
+
@action = :ignore
|
11
|
+
@allowed_groups = [:everyone]
|
12
|
+
@help = ""
|
13
|
+
end
|
14
|
+
|
15
|
+
# Matches any input (since the Default route, when used, should always function)
|
16
|
+
# @return [Boolean]
|
17
|
+
def matches?(_input)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
# Permits any user (since the Default route, when used, should always function)
|
22
|
+
# @return [Boolean]
|
23
|
+
def permits?(_user)
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
# Just provides back all input as a single token
|
28
|
+
# @return [Array<String>]
|
29
|
+
def tokens(input)
|
30
|
+
[input]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/waylon/config.rb
CHANGED
@@ -23,7 +23,7 @@ module Waylon
|
|
23
23
|
true
|
24
24
|
end
|
25
25
|
|
26
|
-
# A list of emails specified via the
|
26
|
+
# A list of emails specified via the GLOBAL_ADMINS environment variable
|
27
27
|
# @return [Array<String>] a list of emails
|
28
28
|
def admins
|
29
29
|
admin_emails = self["global.admins"]
|
@@ -32,11 +32,12 @@ module Waylon
|
|
32
32
|
|
33
33
|
# Load in the config from env variables
|
34
34
|
# @return [Boolean] Was the configuration loaded?
|
35
|
-
def load_env
|
35
|
+
def load_env # rubocop:disable Metrics/AbcSize
|
36
36
|
@schema ||= {}
|
37
37
|
self["global.log.level"] = ENV.fetch("LOG_LEVEL", "info")
|
38
38
|
self["global.redis.host"] = ENV.fetch("REDIS_HOST", "redis")
|
39
39
|
self["global.redis.port"] = ENV.fetch("REDIS_PORT", "6379")
|
40
|
+
self["global.admins"] = ENV.fetch("GLOBAL_ADMINS", "")
|
40
41
|
ENV.keys.grep(/CONF_/).each do |env_key|
|
41
42
|
conf_key = env_key.downcase.split("_")[1..].join(".")
|
42
43
|
::Waylon::Logger.log("Attempting to set #{conf_key} from #{env_key}", :debug)
|
data/lib/waylon/core.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
# Standard Library dependencies
|
4
4
|
require "base64"
|
5
|
+
require "benchmark"
|
5
6
|
require "digest"
|
6
7
|
require "English"
|
7
8
|
require "fileutils"
|
@@ -21,6 +22,7 @@ require "i18n"
|
|
21
22
|
require "json"
|
22
23
|
require "moneta"
|
23
24
|
require "resque"
|
25
|
+
require "sinatra"
|
24
26
|
|
25
27
|
# Internal requirements
|
26
28
|
require "waylon/version"
|
@@ -39,8 +41,11 @@ require "waylon/sense"
|
|
39
41
|
require "waylon/skill_registry"
|
40
42
|
require "waylon/skill"
|
41
43
|
require "waylon/user"
|
44
|
+
require "waylon/conditions/black_hole"
|
42
45
|
require "waylon/conditions/default"
|
43
46
|
require "waylon/conditions/permission_denied"
|
44
47
|
require "waylon/conditions/regex"
|
48
|
+
require "waylon/routes/black_hole"
|
45
49
|
require "waylon/routes/default"
|
46
50
|
require "waylon/routes/permission_denied"
|
51
|
+
require "waylon/webhook"
|
data/lib/waylon/group.rb
CHANGED
data/lib/waylon/logger.rb
CHANGED
@@ -6,7 +6,7 @@ module Waylon
|
|
6
6
|
# The log level as defined in the global Config singleton
|
7
7
|
# @return [String] The current log level
|
8
8
|
def self.level
|
9
|
-
Config.instance["global.log.level"]
|
9
|
+
Config.instance["global.log.level"] || "info"
|
10
10
|
end
|
11
11
|
|
12
12
|
# Abstraction for sending logs to the logger at some level
|
data/lib/waylon/message.rb
CHANGED
@@ -9,9 +9,28 @@ module Waylon
|
|
9
9
|
nil
|
10
10
|
end
|
11
11
|
|
12
|
+
# Message body
|
13
|
+
def body
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
12
17
|
# Message channel (meant to be overwritten by mixing classes)
|
13
18
|
def channel
|
14
19
|
nil
|
15
20
|
end
|
21
|
+
|
22
|
+
# Does the Message mention the bot (meant to be overwritten by mixing classes)
|
23
|
+
def mentions_bot?
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# Is the Message a private/direct Message?
|
28
|
+
def private?
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_bot?
|
33
|
+
true
|
34
|
+
end
|
16
35
|
end
|
17
36
|
end
|
data/lib/waylon/route.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
module Routes
|
5
|
+
# The route for unroutable events
|
6
|
+
class BlackHole < Route
|
7
|
+
def initialize(
|
8
|
+
name: "black_hole",
|
9
|
+
destination: Skills::Default,
|
10
|
+
condition: Conditions::BlackHole.new,
|
11
|
+
priority: 0
|
12
|
+
)
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -36,6 +36,13 @@ module Waylon
|
|
36
36
|
chain :to do |method_name|
|
37
37
|
@method_name = method_name
|
38
38
|
end
|
39
|
+
|
40
|
+
description do
|
41
|
+
result = "route \"#{expected}\""
|
42
|
+
result += " to action \"#{@method_name}\"" if @method_name
|
43
|
+
result += " while a member of \"#{@group}\"" if @group
|
44
|
+
result
|
45
|
+
end
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
data/lib/waylon/rspec/skill.rb
CHANGED
@@ -22,14 +22,14 @@ module Waylon
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# Overrides the Sense.enqueue class method to avoid Resque
|
25
|
-
def self.enqueue(route,
|
25
|
+
def self.enqueue(route, request)
|
26
26
|
details = {
|
27
27
|
"sense" => self,
|
28
|
-
"
|
29
|
-
"
|
28
|
+
"request" => request,
|
29
|
+
"route" => route.name
|
30
30
|
}
|
31
31
|
|
32
|
-
fake_queue.push [route.destination,
|
32
|
+
fake_queue.push [route.destination, details]
|
33
33
|
end
|
34
34
|
|
35
35
|
# Allows access to the fake version of Resque
|
@@ -50,15 +50,10 @@ module Waylon
|
|
50
50
|
@message_list ||= []
|
51
51
|
end
|
52
52
|
|
53
|
-
#
|
54
|
-
# @
|
55
|
-
|
56
|
-
|
57
|
-
message_list << message_details
|
58
|
-
message_id = message_list.size - 1
|
59
|
-
msg = message_class.new(message_id)
|
60
|
-
route = SkillRegistry.instance.route(msg) || SkillRegistry.instance.default_route
|
61
|
-
enqueue(route, msg.id, msg.text)
|
53
|
+
# Provides a way to use an initial request to reconstitute a Sense-specific Message
|
54
|
+
# @return [Waylon::Message]
|
55
|
+
def self.message_from_request(request)
|
56
|
+
message_class.new(message_list.size - 1, request)
|
62
57
|
end
|
63
58
|
|
64
59
|
# Emulates reactions by sending a message with the reaction type
|
@@ -66,7 +61,7 @@ module Waylon
|
|
66
61
|
# @param type [Symbol,String] The type of reaction to send
|
67
62
|
# @return [void]
|
68
63
|
def self.react(request, type)
|
69
|
-
msg =
|
64
|
+
msg = message_from_request(request)
|
70
65
|
msg.channel.post_message(":#{type}:")
|
71
66
|
end
|
72
67
|
|
@@ -81,10 +76,21 @@ module Waylon
|
|
81
76
|
# @param text [String] The message content to send in response to the request
|
82
77
|
# @return [void]
|
83
78
|
def self.reply(request, text)
|
84
|
-
msg =
|
79
|
+
msg = message_from_request(request)
|
85
80
|
msg.channel.post_message(text)
|
86
81
|
end
|
87
82
|
|
83
|
+
# Receives incoming message details and places work on a queue to be performed by a Skill
|
84
|
+
# @param message_details [Hash] The details necessary for creating a TestMessage
|
85
|
+
# @return [void]
|
86
|
+
def self.run(message_details)
|
87
|
+
message_list << message_details
|
88
|
+
message_id = message_list.size - 1
|
89
|
+
msg = message_class.new(message_id)
|
90
|
+
route = SkillRegistry.route(msg) || SkillRegistry.instance.default_route(msg)
|
91
|
+
enqueue(route, message_details)
|
92
|
+
end
|
93
|
+
|
88
94
|
# Provides all message text sent _by_ Waylon
|
89
95
|
# @return [Array<String>]
|
90
96
|
def self.sent_messages
|
@@ -7,8 +7,8 @@ module Waylon
|
|
7
7
|
# Instructs the worker to grab an item off the Queue and run it
|
8
8
|
# @param queue [Queue] The queue that contains work to be done
|
9
9
|
def self.handle(queue)
|
10
|
-
skill,
|
11
|
-
skill.perform(
|
10
|
+
skill, details = queue.pop
|
11
|
+
skill.perform(details)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
data/lib/waylon/sense.rb
CHANGED
@@ -20,17 +20,16 @@ module Waylon
|
|
20
20
|
|
21
21
|
# The connection between Senses and Skills happens here, via a Route and a Hash of details
|
22
22
|
# @param route [Route] route The matching Route from the SkillRegistry
|
23
|
-
# @param
|
24
|
-
# @param body [String] Message content for the Skill
|
23
|
+
# @param request [String] The request message (or its ID) from the messaging platform
|
25
24
|
# @api private
|
26
|
-
def self.enqueue(route,
|
25
|
+
def self.enqueue(route, request)
|
27
26
|
details = {
|
28
27
|
"sense" => self,
|
29
|
-
"
|
30
|
-
"
|
28
|
+
"request" => request,
|
29
|
+
"route" => route.name
|
31
30
|
}
|
32
31
|
|
33
|
-
Resque.enqueue route.destination,
|
32
|
+
Resque.enqueue route.destination, details
|
34
33
|
end
|
35
34
|
|
36
35
|
# Provides a simple mechanism for referencing the Group subclass provided by this Sense
|
data/lib/waylon/skill.rb
CHANGED
@@ -5,7 +5,7 @@ module Waylon
|
|
5
5
|
class Skill
|
6
6
|
include BaseComponent
|
7
7
|
|
8
|
-
attr_reader :sense, :tokens, :request
|
8
|
+
attr_reader :sense, :tokens, :request, :route
|
9
9
|
|
10
10
|
# Config namespace for config keys
|
11
11
|
# @return [String] The namespace for config keys
|
@@ -14,32 +14,31 @@ module Waylon
|
|
14
14
|
end
|
15
15
|
|
16
16
|
# Resque uses this to execute the Skill. Just defers to the `action` subclass method
|
17
|
-
# @param action [Symbol,String] The method on the Skill subclass to call
|
18
17
|
# @param details [Hash] Input details about the message for running a Skill action
|
19
|
-
def self.perform(
|
20
|
-
new(details["sense"], details["
|
21
|
-
|
18
|
+
def self.perform(details)
|
19
|
+
skill = new(details["sense"], details["route"], details["request"], details["meta"])
|
20
|
+
skill.send(skill.route.action.to_sym)
|
22
21
|
end
|
23
22
|
|
24
23
|
# Redis/Resque queue name
|
25
24
|
# @api private
|
26
25
|
# @return [Symbol]
|
27
26
|
def self.queue
|
28
|
-
:
|
27
|
+
:skills
|
29
28
|
end
|
30
29
|
|
31
30
|
# Adds skills to the SkillRegistry
|
32
31
|
# @param condition [Condition,Regexp] The condition that determines if this route applies
|
33
32
|
# @param action [Symbol,String] The method on the Skill subclass to call
|
34
33
|
# @param allowed_groups [Symbol,Array<Symbol>] The group or list of groups allowed to use this
|
35
|
-
# @param help [String] A description of how to use the skill
|
36
|
-
def self.route(condition, action, allowed_groups: :everyone, help: nil, name: nil)
|
34
|
+
# @param help [String,Hash] A description of how to use the skill
|
35
|
+
def self.route(condition, action, allowed_groups: :everyone, help: nil, name: nil, mention_only: true)
|
37
36
|
name ||= "#{to_s.split("::").last.downcase}##{action}"
|
38
37
|
real_cond = case condition
|
39
38
|
when Condition
|
40
39
|
condition
|
41
40
|
when Regexp
|
42
|
-
Conditions::Regex.new(condition, action, allowed_groups, help)
|
41
|
+
Conditions::Regex.new(condition, action, allowed_groups, help, mention_only)
|
43
42
|
else
|
44
43
|
log("Unknown condition for route for #{name}##{action}", :warn)
|
45
44
|
nil
|
@@ -48,13 +47,13 @@ module Waylon
|
|
48
47
|
end
|
49
48
|
|
50
49
|
# @param sense [Class,String] Class (or Class name) of the source Sense
|
51
|
-
# @param
|
52
|
-
# @param request [String,Integer] Reference to the request from the Sense provider (usually an ID)
|
50
|
+
# @param request [String,Integer] Reference to the request from the Sense provider (usually ID or message itself)
|
53
51
|
# @param meta [Hash] Optional meta data that can be passed along from a Sense for use in Skills
|
54
|
-
def initialize(sense,
|
52
|
+
def initialize(sense, route, request, meta)
|
55
53
|
@sense = sense.is_a?(Class) ? sense : Module.const_get(sense)
|
56
|
-
@
|
54
|
+
@route = SkillRegistry.find_by_name(route)
|
57
55
|
@request = request
|
56
|
+
@tokens = @route.tokens(message.body) || []
|
58
57
|
@meta = meta
|
59
58
|
end
|
60
59
|
|
@@ -62,7 +61,6 @@ module Waylon
|
|
62
61
|
# @return [String]
|
63
62
|
def acknowledgement
|
64
63
|
responses = [
|
65
|
-
"I'll get back to you in just a sec.",
|
66
64
|
"You got it!",
|
67
65
|
"As you wish.",
|
68
66
|
"Certainly!",
|
@@ -73,11 +71,10 @@ module Waylon
|
|
73
71
|
"Of course!",
|
74
72
|
"I'd be delighted!",
|
75
73
|
"Right away!",
|
76
|
-
"Gladly",
|
74
|
+
"Gladly!",
|
77
75
|
"All right.",
|
78
76
|
"I'm all over it.",
|
79
77
|
"I'm on it!",
|
80
|
-
"Let me see what I can do.",
|
81
78
|
"Will do!"
|
82
79
|
]
|
83
80
|
responses.sample
|
@@ -97,7 +94,8 @@ module Waylon
|
|
97
94
|
sense: @sense,
|
98
95
|
message: @request,
|
99
96
|
tokens: @tokens,
|
100
|
-
meta: @meta
|
97
|
+
meta: @meta,
|
98
|
+
route: route.name
|
101
99
|
}
|
102
100
|
end
|
103
101
|
|
@@ -111,7 +109,11 @@ module Waylon
|
|
111
109
|
# Provides a wrapped message for responding to the received Sense
|
112
110
|
# @return [Waylon::Message]
|
113
111
|
def message
|
114
|
-
sense.
|
112
|
+
sense.message_from_request(request)
|
113
|
+
end
|
114
|
+
|
115
|
+
def named_tokens
|
116
|
+
@named_tokens ||= @route.named_tokens(message.body) || {}
|
115
117
|
end
|
116
118
|
|
117
119
|
# Defers to the Sense to react to a message
|
@@ -124,9 +126,40 @@ module Waylon
|
|
124
126
|
end
|
125
127
|
|
126
128
|
# Defers to the Sense to determine how to reply to a message
|
127
|
-
# @param [String]
|
128
|
-
def reply(text)
|
129
|
-
sense.
|
129
|
+
# @param text [String] The reply text
|
130
|
+
def reply(text, private: false)
|
131
|
+
if private && sense.supports?(:private_messages)
|
132
|
+
sense.private_reply(request, text)
|
133
|
+
else
|
134
|
+
log("Unable to send private message for Sense #{sense.name}, replying instead", :debug) if private
|
135
|
+
sense.reply(request, text)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Defers to the Sense to determine how to reply to a message with rich content
|
140
|
+
# @param blocks [String] The reply blocks
|
141
|
+
def reply_with_blocks(blocks, private: false)
|
142
|
+
unless sense.supports?(:blocks)
|
143
|
+
log("Unable to use blocks with Sense #{sense.name}")
|
144
|
+
return false
|
145
|
+
end
|
146
|
+
if private
|
147
|
+
sense.private_reply_with_blocks(request, blocks)
|
148
|
+
else
|
149
|
+
log("Unable to send private message for Sense #{sense.name}, replying instead", :debug) if private
|
150
|
+
sense.reply_with_blocks(request, blocks)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Defers to the Sense to do threaded replies if it can, otherwise it falls back to normal replies
|
155
|
+
# @param text [String] The reply text
|
156
|
+
def threaded_reply(text)
|
157
|
+
if sense.supports?(:threads)
|
158
|
+
sense.threaded_reply(request, text)
|
159
|
+
else
|
160
|
+
log("Unable to reply in theads for Sense #{sense.name}, replying instead", :debug)
|
161
|
+
sense.reply(request, text)
|
162
|
+
end
|
130
163
|
end
|
131
164
|
end
|
132
165
|
end
|