waylon-core 0.1.1 → 0.1.4
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/.roxanne.yml +5 -1
- data/.rubocop.yml +8 -1
- data/.ruby-version +1 -1
- data/Gemfile.lock +42 -44
- data/README.md +1 -1
- data/lib/waylon/condition.rb +29 -1
- data/lib/waylon/conditions/black_hole.rb +34 -0
- data/lib/waylon/conditions/regex.rb +8 -0
- data/lib/waylon/config.rb +4 -3
- data/lib/waylon/core.rb +6 -0
- data/lib/waylon/group.rb +1 -1
- data/lib/waylon/logger.rb +14 -7
- data/lib/waylon/message.rb +20 -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_server.rb +4 -1
- data/lib/waylon/rspec/test_user.rb +2 -2
- 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/services/ping.rb +30 -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 +60 -0
- data/lib/waylon/skills/fun.rb +5 -2
- data/lib/waylon/skills/groups.rb +173 -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/webhook_registry.rb +32 -0
- data/lib/waylon.rb +3 -0
- data/scripts/release.sh +7 -0
- data/scripts/test.sh +1 -1
- data/waylon-core.gemspec +1 -1
- metadata +16 -8
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
module Skills
|
5
|
+
# A Skill for providing help
|
6
|
+
class Help < Skill
|
7
|
+
# Ask for some help.
|
8
|
+
# Defaults to all things a user has access to, but allows specifying either a Skill name or a Skill and Route
|
9
|
+
route(
|
10
|
+
/^help(?<skill_clause>\s+(?<skill>\w+)(?<action_clause>#(?<action>\w+)|\s+(?<action>\w+))?)?$/i,
|
11
|
+
:help,
|
12
|
+
help: {
|
13
|
+
usage: "help [skill [action]]",
|
14
|
+
description: "Allows asking for help, either for all skills or for a particular skill or action"
|
15
|
+
}
|
16
|
+
)
|
17
|
+
|
18
|
+
# Responds to "help" requests
|
19
|
+
def help
|
20
|
+
skill = named_tokens[:skill]
|
21
|
+
action = named_tokens[:action]
|
22
|
+
|
23
|
+
react :book
|
24
|
+
|
25
|
+
immediate_responses = [
|
26
|
+
"I'll send you a DM to go over that with you.",
|
27
|
+
"I'll DM you the details.",
|
28
|
+
"Look for a private message with those details.",
|
29
|
+
"You should have a private message with that information shortly."
|
30
|
+
]
|
31
|
+
|
32
|
+
# Only send this if you aren't already in a DM
|
33
|
+
threaded_reply "#{acknowledgement} #{immediate_responses.sample}" unless message.private?
|
34
|
+
|
35
|
+
if sense.supports?(:blocks)
|
36
|
+
reply_with_blocks(help_blocks(skill, action), private: true)
|
37
|
+
else
|
38
|
+
reply(help_text(skill, action), private: true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def help_text(skill = nil, action = nil) # rubocop:disable Metrics/AbcSize
|
43
|
+
allowed_routes = SkillRegistry.instance.help(message.author)
|
44
|
+
resp = []
|
45
|
+
if skill
|
46
|
+
if action
|
47
|
+
resp << "## Help for #{skill}##{action}:"
|
48
|
+
this_route = allowed_routes[skill].find do |r|
|
49
|
+
r[:name].to_s == "#{skill}##{action}"
|
50
|
+
end
|
51
|
+
return "I couldn't find #{action} on #{skill}..." unless this_route
|
52
|
+
|
53
|
+
resp << build_help_text(this_route)
|
54
|
+
else
|
55
|
+
resp << "## Help for #{skill}:\n"
|
56
|
+
routes = allowed_routes[skill]
|
57
|
+
(routes || []).each { |r| resp << build_help_text(r) }
|
58
|
+
end
|
59
|
+
else
|
60
|
+
help_text_for_all(allowed_routes)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def help_blocks(skill = nil, action = nil) # rubocop:disable Metrics/AbcSize
|
65
|
+
allowed_routes = SkillRegistry.instance.help(message.author)
|
66
|
+
if skill
|
67
|
+
if action
|
68
|
+
this_route = allowed_routes[skill].find do |r|
|
69
|
+
r[:name].to_s == "#{skill}##{action}"
|
70
|
+
end
|
71
|
+
|
72
|
+
return not_found_block(skill, action) unless this_route
|
73
|
+
|
74
|
+
[build_header_block(skill, action), build_help_block(this_route)]
|
75
|
+
else
|
76
|
+
routes = allowed_routes[skill]
|
77
|
+
return not_found_block(skill, nil) unless routes
|
78
|
+
|
79
|
+
resp = [build_header_block(skill, nil)]
|
80
|
+
routes.each { |r| resp << build_help_block(r) }
|
81
|
+
resp
|
82
|
+
end
|
83
|
+
else
|
84
|
+
allowed_routes = SkillRegistry.instance.help(message.author)
|
85
|
+
help_blocks_for_all(allowed_routes)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def help_blocks_for_all(routes)
|
90
|
+
resp = [
|
91
|
+
{ type: "header", text: { type: "plain_text", text: "All known actions:", emoji: true } }
|
92
|
+
]
|
93
|
+
|
94
|
+
routes.each do |k, v|
|
95
|
+
resp += [
|
96
|
+
{ type: "divider" },
|
97
|
+
{
|
98
|
+
type: "section",
|
99
|
+
text: {
|
100
|
+
type: "mrkdwn",
|
101
|
+
text: "*Actions for '#{k}':*"
|
102
|
+
}
|
103
|
+
}
|
104
|
+
]
|
105
|
+
v.each { |r| resp << build_help_block(r) }
|
106
|
+
end
|
107
|
+
resp
|
108
|
+
end
|
109
|
+
|
110
|
+
def help_text_for_all(routes)
|
111
|
+
resp = []
|
112
|
+
resp << "*All known actions:*\n"
|
113
|
+
routes.each do |k, v|
|
114
|
+
resp << "* *#{k}*:"
|
115
|
+
v.each do |r|
|
116
|
+
resp << build_help_text(r)
|
117
|
+
end
|
118
|
+
resp << " --- "
|
119
|
+
end
|
120
|
+
resp.join("\n")
|
121
|
+
end
|
122
|
+
|
123
|
+
def build_header_block(skill, action)
|
124
|
+
text = if action
|
125
|
+
"Help for #{skill}##{action}:"
|
126
|
+
else
|
127
|
+
"Help for #{skill}:"
|
128
|
+
end
|
129
|
+
{ type: "header", text: { type: "plain_text", text: text, emoji: true } }
|
130
|
+
end
|
131
|
+
|
132
|
+
def build_help_block(this_route)
|
133
|
+
{
|
134
|
+
type: "section",
|
135
|
+
text: {
|
136
|
+
type: "mrkdwn",
|
137
|
+
text: " *#{this_route[:name]}*\n#{build_help_text(this_route)}"
|
138
|
+
}
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
def build_help_text(this_route)
|
143
|
+
route_help_text = []
|
144
|
+
case this_route[:help]
|
145
|
+
when String
|
146
|
+
route_help_text << " *Usage:* #{this_route[:help]}"
|
147
|
+
when Hash
|
148
|
+
route_help_text << " *Usage:* #{this_route.dig(:help, :usage)}"
|
149
|
+
if this_route.dig(:help, :description)
|
150
|
+
route_help_text << "\n *Description:* #{this_route.dig(:help, :description)}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
route_help_text.join
|
154
|
+
end
|
155
|
+
|
156
|
+
def not_found_block(skill, action)
|
157
|
+
sentence = if action
|
158
|
+
"I couldn't find any '#{action}' action on the '#{skill}' skill..."
|
159
|
+
else
|
160
|
+
"I couldn't find any routes related to a '#{skill}' skill..."
|
161
|
+
end
|
162
|
+
[
|
163
|
+
{
|
164
|
+
type: "section",
|
165
|
+
text: {
|
166
|
+
type: "mrkdwn",
|
167
|
+
text: sentence
|
168
|
+
}
|
169
|
+
}
|
170
|
+
]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/lib/waylon/user.rb
CHANGED
@@ -18,6 +18,11 @@ module Waylon
|
|
18
18
|
raise NotImplementedError, "find_by_handle isn't implemented"
|
19
19
|
end
|
20
20
|
|
21
|
+
# This should be overridden by subclasses to provide a mechanism for looking up Users based on mention strings
|
22
|
+
def from_mention(_mention_string)
|
23
|
+
raise NotImplementedError, "from_mention isn't implemented"
|
24
|
+
end
|
25
|
+
|
21
26
|
# Provides a simple mechanism for referencing User subclass's Sense
|
22
27
|
# @return [Class] A Sense subclass
|
23
28
|
def sense
|
data/lib/waylon/version.rb
CHANGED
data/lib/waylon/webhook.rb
CHANGED
@@ -21,7 +21,7 @@ module Waylon
|
|
21
21
|
# @return [Class] The name of the corresponding Sense class
|
22
22
|
def sense_class
|
23
23
|
last = self.class.name.split("::").last
|
24
|
-
Module.const_get("Senses::#{last}")
|
24
|
+
Module.const_get("Waylon::Senses::#{last}")
|
25
25
|
end
|
26
26
|
|
27
27
|
# This must be implemented on every Webhook to provide a mechanism to ensure received payloads are legit
|
@@ -38,36 +38,35 @@ module Waylon
|
|
38
38
|
end
|
39
39
|
|
40
40
|
before do
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
unless request.get? || request.options?
|
45
|
-
request.body.rewind
|
46
|
-
@parsed_body = JSON.parse(request.body.read, symbolize_names: true)
|
47
|
-
end
|
48
|
-
rescue StandardError => e
|
49
|
-
halt(400, { error: "Request must be JSON: #{e.message}" }.to_json)
|
41
|
+
unless request.get? || request.options?
|
42
|
+
request.body.rewind
|
43
|
+
@parsed_body = JSON.parse(request.body.read, symbolize_names: true)
|
50
44
|
end
|
45
|
+
rescue StandardError => e
|
46
|
+
content_type "application/json"
|
47
|
+
halt(400, { error: "Request must be JSON: #{e.message}" }.to_json)
|
51
48
|
end
|
52
49
|
|
53
50
|
after do
|
54
51
|
request.options? && headers("Access-Control-Allow-Methods" => @allowed_types || %w[OPTIONS POST])
|
55
52
|
end
|
56
53
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
54
|
+
## Example incoming webhook
|
55
|
+
#
|
56
|
+
# post "/" do
|
57
|
+
# begin
|
58
|
+
# request.body.rewind
|
59
|
+
# verify request.body.read, request.env
|
60
|
+
# enqueue @parsed_body
|
61
|
+
# rescue StandardError => e
|
62
|
+
# halt(422, { error: "Unprocessable entity: #{e.message}" }.to_json)
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# { status: :ok }.to_json
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# options "/" do
|
69
|
+
# halt 200
|
70
|
+
# end
|
72
71
|
end
|
73
72
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Waylon
|
4
|
+
# Registry of Webhook subclasses known to Waylon
|
5
|
+
class WebhookRegistry
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
attr_reader :webhooks
|
9
|
+
|
10
|
+
# A convenience wrapper around the singleton instance #register method
|
11
|
+
# @param (see #register)
|
12
|
+
# @return (see #register)
|
13
|
+
def self.register(name, class_name)
|
14
|
+
instance.register(name, class_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Add the provided Webhook class to the registry under `name`
|
18
|
+
# @param name [String] The name of the Webhook in the registry
|
19
|
+
# @param class_name [Class] The Webhook subclass to add
|
20
|
+
# @return [Class] The Webhook subclass
|
21
|
+
def register(name, class_name)
|
22
|
+
@webhooks ||= {}
|
23
|
+
@webhooks[name.to_s] = class_name
|
24
|
+
end
|
25
|
+
|
26
|
+
# Provides a Hash version of this registry
|
27
|
+
# @return [Hash]
|
28
|
+
def to_hash
|
29
|
+
(@webhooks || {}).transform_keys { |k| "/hooks/#{k}" }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/waylon.rb
CHANGED
data/scripts/release.sh
ADDED
data/scripts/test.sh
CHANGED
data/waylon-core.gemspec
CHANGED
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_dependency "puma", "~> 5.5"
|
36
36
|
spec.add_dependency "resque", "~> 2.2"
|
37
37
|
|
38
|
-
spec.add_development_dependency "bundler", "~> 2.
|
38
|
+
spec.add_development_dependency "bundler", "~> 2.3"
|
39
39
|
spec.add_development_dependency "rake", "~> 13.0"
|
40
40
|
spec.add_development_dependency "rspec", "~> 3.10"
|
41
41
|
spec.add_development_dependency "rubocop", "~> 1.23"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: waylon-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Gnagy
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '2.
|
117
|
+
version: '2.3'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '2.
|
124
|
+
version: '2.3'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rake
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -249,6 +249,7 @@ files:
|
|
249
249
|
- lib/waylon.rb
|
250
250
|
- lib/waylon/base_component.rb
|
251
251
|
- lib/waylon/condition.rb
|
252
|
+
- lib/waylon/conditions/black_hole.rb
|
252
253
|
- lib/waylon/conditions/default.rb
|
253
254
|
- lib/waylon/conditions/permission_denied.rb
|
254
255
|
- lib/waylon/conditions/regex.rb
|
@@ -261,6 +262,7 @@ files:
|
|
261
262
|
- lib/waylon/logger.rb
|
262
263
|
- lib/waylon/message.rb
|
263
264
|
- lib/waylon/route.rb
|
265
|
+
- lib/waylon/routes/black_hole.rb
|
264
266
|
- lib/waylon/routes/default.rb
|
265
267
|
- lib/waylon/routes/permission_denied.rb
|
266
268
|
- lib/waylon/rspec.rb
|
@@ -274,13 +276,19 @@ files:
|
|
274
276
|
- lib/waylon/rspec/test_worker.rb
|
275
277
|
- lib/waylon/sense.rb
|
276
278
|
- lib/waylon/sense_registry.rb
|
279
|
+
- lib/waylon/services/ping.rb
|
277
280
|
- lib/waylon/skill.rb
|
278
281
|
- lib/waylon/skill_registry.rb
|
279
282
|
- lib/waylon/skills/default.rb
|
283
|
+
- lib/waylon/skills/diagnostics.rb
|
280
284
|
- lib/waylon/skills/fun.rb
|
285
|
+
- lib/waylon/skills/groups.rb
|
286
|
+
- lib/waylon/skills/help.rb
|
281
287
|
- lib/waylon/user.rb
|
282
288
|
- lib/waylon/version.rb
|
283
289
|
- lib/waylon/webhook.rb
|
290
|
+
- lib/waylon/webhook_registry.rb
|
291
|
+
- scripts/release.sh
|
284
292
|
- scripts/test.sh
|
285
293
|
- waylon-core.gemspec
|
286
294
|
homepage: https://github.com/jgnagy/waylon-core
|
@@ -290,7 +298,7 @@ metadata:
|
|
290
298
|
homepage_uri: https://github.com/jgnagy/waylon-core
|
291
299
|
source_code_uri: https://github.com/jgnagy/waylon-core
|
292
300
|
changelog_uri: https://github.com/jgnagy/waylon-core/blob/main/CHANGELOG.md
|
293
|
-
post_install_message:
|
301
|
+
post_install_message:
|
294
302
|
rdoc_options: []
|
295
303
|
require_paths:
|
296
304
|
- lib
|
@@ -305,8 +313,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
305
313
|
- !ruby/object:Gem::Version
|
306
314
|
version: '0'
|
307
315
|
requirements: []
|
308
|
-
rubygems_version: 3.
|
309
|
-
signing_key:
|
316
|
+
rubygems_version: 3.3.7
|
317
|
+
signing_key:
|
310
318
|
specification_version: 4
|
311
319
|
summary: Core library for the Waylon bot framework
|
312
320
|
test_files: []
|