waylon-core 0.1.0

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.roxanne.yml +4 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +38 -0
  6. data/.ruby-version +1 -0
  7. data/CHANGELOG.md +5 -0
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +137 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +57 -0
  12. data/Rakefile +23 -0
  13. data/bin/console +17 -0
  14. data/bin/setup +8 -0
  15. data/lib/waylon/base_component.rb +124 -0
  16. data/lib/waylon/condition.rb +64 -0
  17. data/lib/waylon/conditions/default.rb +34 -0
  18. data/lib/waylon/conditions/permission_denied.rb +34 -0
  19. data/lib/waylon/conditions/regex.rb +22 -0
  20. data/lib/waylon/config.rb +134 -0
  21. data/lib/waylon/core.rb +46 -0
  22. data/lib/waylon/exceptions/not_implemented_error.rb +9 -0
  23. data/lib/waylon/exceptions/validation_error.rb +9 -0
  24. data/lib/waylon/generic_exception.rb +7 -0
  25. data/lib/waylon/group.rb +70 -0
  26. data/lib/waylon/logger.rb +41 -0
  27. data/lib/waylon/message.rb +17 -0
  28. data/lib/waylon/route.rb +71 -0
  29. data/lib/waylon/routes/default.rb +17 -0
  30. data/lib/waylon/routes/permission_denied.rb +17 -0
  31. data/lib/waylon/rspec/matchers/route_matcher.rb +43 -0
  32. data/lib/waylon/rspec/skill.rb +71 -0
  33. data/lib/waylon/rspec/test_channel.rb +83 -0
  34. data/lib/waylon/rspec/test_message.rb +63 -0
  35. data/lib/waylon/rspec/test_sense.rb +110 -0
  36. data/lib/waylon/rspec/test_server.rb +120 -0
  37. data/lib/waylon/rspec/test_user.rb +165 -0
  38. data/lib/waylon/rspec/test_worker.rb +15 -0
  39. data/lib/waylon/rspec.rb +50 -0
  40. data/lib/waylon/sense.rb +74 -0
  41. data/lib/waylon/sense_registry.rb +30 -0
  42. data/lib/waylon/skill.rb +132 -0
  43. data/lib/waylon/skill_registry.rb +74 -0
  44. data/lib/waylon/skills/default.rb +48 -0
  45. data/lib/waylon/skills/fun.rb +26 -0
  46. data/lib/waylon/user.rb +61 -0
  47. data/lib/waylon/version.rb +12 -0
  48. data/lib/waylon/webhook.rb +73 -0
  49. data/lib/waylon.rb +5 -0
  50. data/scripts/test.sh +5 -0
  51. data/waylon-core.gemspec +50 -0
  52. metadata +312 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 01c6d89ed4d79dba9305c9c83fd597fed10ace104592f7d8ae6ed2f630bb9351
4
+ data.tar.gz: 83ac891dc983e61f76b5cd366062381b748dcc49c86d6177b4e245c8c29573e0
5
+ SHA512:
6
+ metadata.gz: bd0fabfda6646c84cb17af27dd55bd8c70ad1c803a257e1e4ed992ce4298563a579705dff33b898519b82ed2123e59ab2259021bbdec320914914a7ee19291f0
7
+ data.tar.gz: 5b2c06fc2c55256014f35e953465f21c11c6de9390e55c0a504f7fcb08c2fcff1898e583dac97b546b1d1a7c00650014562c2e678aff6832353a3c24f08527b8
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.roxanne.yml ADDED
@@ -0,0 +1,4 @@
1
+ version: 1.0
2
+ stages:
3
+ test:
4
+ image: ruby:3.0
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,38 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.0
3
+ NewCops: enable
4
+
5
+ Style/MixinUsage:
6
+ Exclude:
7
+ - "bin/console"
8
+
9
+ Style/StringLiterals:
10
+ Enabled: true
11
+ EnforcedStyle: double_quotes
12
+
13
+ Style/StringLiteralsInInterpolation:
14
+ Enabled: true
15
+ EnforcedStyle: double_quotes
16
+
17
+ Layout/LineLength:
18
+ Max: 120
19
+
20
+ Gemspec/RequireMFA:
21
+ Enabled: false
22
+
23
+ Metrics/AbcSize:
24
+ Max: 19
25
+
26
+ Metrics/CyclomaticComplexity:
27
+ Max: 9
28
+
29
+ Metrics/PerceivedComplexity:
30
+ Max: 9
31
+
32
+ Metrics/MethodLength:
33
+ Max: 20
34
+
35
+ Metrics/BlockLength:
36
+ Exclude:
37
+ - "**/*_spec.rb"
38
+ - "*.gemspec"
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.3
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2021-11-17
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in waylon-core.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,137 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ waylon-core (0.1.0)
5
+ addressable (~> 2.8)
6
+ faraday (~> 1.8)
7
+ i18n (~> 1.8)
8
+ json (~> 2.6)
9
+ moneta (~> 1.4)
10
+ puma (~> 5.5)
11
+ resque (~> 2.2)
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ specs:
16
+ addressable (2.8.0)
17
+ public_suffix (>= 2.0.2, < 5.0)
18
+ ast (2.4.2)
19
+ concurrent-ruby (1.1.9)
20
+ diff-lcs (1.4.4)
21
+ docile (1.4.0)
22
+ faraday (1.8.0)
23
+ faraday-em_http (~> 1.0)
24
+ faraday-em_synchrony (~> 1.0)
25
+ faraday-excon (~> 1.1)
26
+ faraday-httpclient (~> 1.0.1)
27
+ faraday-net_http (~> 1.0)
28
+ faraday-net_http_persistent (~> 1.1)
29
+ faraday-patron (~> 1.0)
30
+ faraday-rack (~> 1.0)
31
+ multipart-post (>= 1.2, < 3)
32
+ ruby2_keywords (>= 0.0.4)
33
+ faraday-em_http (1.0.0)
34
+ faraday-em_synchrony (1.0.0)
35
+ faraday-excon (1.1.0)
36
+ faraday-httpclient (1.0.1)
37
+ faraday-net_http (1.0.1)
38
+ faraday-net_http_persistent (1.2.0)
39
+ faraday-patron (1.0.0)
40
+ faraday-rack (1.0.0)
41
+ i18n (1.8.11)
42
+ concurrent-ruby (~> 1.0)
43
+ json (2.6.1)
44
+ moneta (1.4.2)
45
+ mono_logger (1.1.1)
46
+ multi_json (1.15.0)
47
+ multipart-post (2.1.1)
48
+ mustermann (1.1.1)
49
+ ruby2_keywords (~> 0.0.1)
50
+ nio4r (2.5.8)
51
+ parallel (1.21.0)
52
+ parser (3.0.3.2)
53
+ ast (~> 2.4.1)
54
+ public_suffix (4.0.6)
55
+ puma (5.5.2)
56
+ nio4r (~> 2.0)
57
+ rack (2.2.3)
58
+ rack-protection (2.1.0)
59
+ rack
60
+ rainbow (3.0.0)
61
+ rake (13.0.6)
62
+ redis (4.5.1)
63
+ redis-namespace (1.8.1)
64
+ redis (>= 3.0.4)
65
+ regexp_parser (2.2.0)
66
+ resque (2.2.0)
67
+ mono_logger (~> 1.0)
68
+ multi_json (~> 1.0)
69
+ redis-namespace (~> 1.6)
70
+ sinatra (>= 0.9.2)
71
+ vegas (~> 0.1.2)
72
+ rexml (3.2.5)
73
+ rspec (3.10.0)
74
+ rspec-core (~> 3.10.0)
75
+ rspec-expectations (~> 3.10.0)
76
+ rspec-mocks (~> 3.10.0)
77
+ rspec-core (3.10.1)
78
+ rspec-support (~> 3.10.0)
79
+ rspec-expectations (3.10.1)
80
+ diff-lcs (>= 1.2.0, < 2.0)
81
+ rspec-support (~> 3.10.0)
82
+ rspec-mocks (3.10.2)
83
+ diff-lcs (>= 1.2.0, < 2.0)
84
+ rspec-support (~> 3.10.0)
85
+ rspec-support (3.10.3)
86
+ rubocop (1.23.0)
87
+ parallel (~> 1.10)
88
+ parser (>= 3.0.0.0)
89
+ rainbow (>= 2.2.2, < 4.0)
90
+ regexp_parser (>= 1.8, < 3.0)
91
+ rexml
92
+ rubocop-ast (>= 1.12.0, < 2.0)
93
+ ruby-progressbar (~> 1.7)
94
+ unicode-display_width (>= 1.4.0, < 3.0)
95
+ rubocop-ast (1.15.0)
96
+ parser (>= 3.0.1.1)
97
+ rubocop-rake (0.6.0)
98
+ rubocop (~> 1.0)
99
+ rubocop-rspec (2.6.0)
100
+ rubocop (~> 1.19)
101
+ ruby-progressbar (1.11.0)
102
+ ruby2_keywords (0.0.5)
103
+ simplecov (0.21.2)
104
+ docile (~> 1.1)
105
+ simplecov-html (~> 0.11)
106
+ simplecov_json_formatter (~> 0.1)
107
+ simplecov-html (0.12.3)
108
+ simplecov_json_formatter (0.1.3)
109
+ sinatra (2.1.0)
110
+ mustermann (~> 1.0)
111
+ rack (~> 2.2)
112
+ rack-protection (= 2.1.0)
113
+ tilt (~> 2.0)
114
+ tilt (2.0.10)
115
+ unicode-display_width (2.1.0)
116
+ vegas (0.1.11)
117
+ rack (>= 1.0.0)
118
+ webrick (1.7.0)
119
+ yard (0.9.27)
120
+ webrick (~> 1.7.0)
121
+
122
+ PLATFORMS
123
+ arm64-darwin-21
124
+
125
+ DEPENDENCIES
126
+ bundler (~> 2.2)
127
+ rake (~> 13.0)
128
+ rspec (~> 3.10)
129
+ rubocop (~> 1.23)
130
+ rubocop-rake (~> 0.6)
131
+ rubocop-rspec (~> 2.6)
132
+ simplecov (~> 0.21)
133
+ waylon-core!
134
+ yard (~> 0.9, >= 0.9.27)
135
+
136
+ BUNDLED WITH
137
+ 2.2.32
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Jonathan Gnagy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # Waylon::Core
2
+
3
+ Waylon is a bot framework in the same vein as [Lita](https://www.lita.io/) built to make creating bots easy and fun. It supports swappable sensory inputs (chat platforms, web endpoints, and more), easy to build Skills, built-in and extensible permissions, and modern JSON logging.
4
+
5
+ This repo/library is the core of Waylon; it provides the essential pieces of the framework and some working examples.
6
+
7
+ ## Why Waylon
8
+
9
+ Waylon is built to be scalable and to deliver features missing in other chat frameworks. For instance, it supports self-reporting and discovering plugin features (such as supporting HTML cards, reactions, etc.) to making Skills more powerful and dynamic. Waylon also supports a full, shared caching layer to make scaling simple. It also makes heavy use of Redis for queuing work, meaning zero-downtime upgrades and faster user responses.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'waylon-core'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install waylon-core
26
+
27
+ If you're building a plugin for Waylon, you'll only need to require the core:
28
+
29
+ ```ruby
30
+ require "waylon/core"
31
+ ```
32
+
33
+ If you're launching your own bot, require the entire library and plus any additional plugins:
34
+
35
+ ```ruby
36
+ require "waylon"
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ### Demo Mode
42
+
43
+ Alone, this library isn't super useful for running a bot, but it does include a "demo", local REPL mode for experimenting. To use it, run `rake demo`.
44
+
45
+ ## Development
46
+
47
+ Waylon's development pipeline makes heavy use of [RSpec](https://rspec.info/) for testing (and [SimpleCov](https://github.com/simplecov-ruby/simplecov) for reporting on coverage), [Rubocop](https://rubocop.org/) for linting/format checking, [YARD](https://yardoc.org/) for documentation, and [Travis CI](https://www.travis-ci.com/) for CI. Most of this is built-in and will work out-of-the-box for GitHub PRs.
48
+
49
+ To get started locally, after checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake` to run the tests and linting. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
50
+
51
+ ## Contributing
52
+
53
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jgnagy/waylon-core.
54
+
55
+ ## License
56
+
57
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
6
+ require "redis/errors"
7
+ require "resque/tasks"
8
+ require "yard"
9
+ require "waylon/core"
10
+
11
+ RSpec::Core::RakeTask.new(:spec)
12
+ RuboCop::RakeTask.new
13
+ YARD::Rake::YardocTask.new do |y|
14
+ y.options = [
15
+ "--markup", "markdown"
16
+ ]
17
+ end
18
+
19
+ task default: %i[spec rubocop yard]
20
+
21
+ task :demo do
22
+ require "waylon/rspec/test_server"
23
+ end
data/bin/console ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "waylon"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ include Waylon
16
+
17
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Waylon
4
+ # The base mixin for all core Waylon components
5
+ # @abstract
6
+ module BaseComponent
7
+ def self.included(base)
8
+ base.send :include, InstanceLoggingMethods
9
+ base.send :include, InstanceUtilityMethods
10
+ base.extend ClassLoggingMethods
11
+ base.extend ClassUtilityMethods
12
+ end
13
+
14
+ # Base class logging methods
15
+ module ClassLoggingMethods
16
+ # Simple pass-through for logging through the Waylon Logger
17
+ # @param message [String] The message to log
18
+ # @param level [String,Symbol] The log level for this message
19
+ def log(message, level = :info)
20
+ ::Waylon::Logger.log(message, level)
21
+ end
22
+ end
23
+
24
+ # Base Component utility methods
25
+ module ClassUtilityMethods
26
+ # The namespace used for this component's storage
27
+ # @param value [String,nil] Sets this namespace unless set (without setting, returns a sane default)
28
+ # @return [String] The namespace for this component
29
+ def component_namespace(value = nil)
30
+ @namespace ||= value
31
+ # Either returns the namespace or the stripped down class name
32
+ @namespace || name.to_s.split("::").last.downcase
33
+ end
34
+
35
+ # Creates namespaced configuration keys for Webhook subclasses
36
+ # @param (see Config#add_schema)
37
+ def config(key, default: nil, required: false, type: String)
38
+ conf = Config.instance
39
+ config_key = config_key_for(key)
40
+ conf.add_schema(config_key, default: default, required: required, type: type)
41
+ end
42
+
43
+ # Provides the full Config key given a relative key
44
+ # @param key [String] The relative key to fully-qualify
45
+ # @return [String] The fully-qualified Config key
46
+ def config_key_for(key)
47
+ "#{config_namespace}.#{key}"
48
+ end
49
+
50
+ # Determines if the current component is fully configured
51
+ # @return [Boolean]
52
+ def configured?
53
+ conf = Config.instance
54
+ req_confs = conf.schema.select do |k, v|
55
+ k.match?(/^#{config_namespace}\./) && v[:required]
56
+ end
57
+ missing_configs = req_confs.reject { |k, _v| conf.set?(k) }
58
+ if missing_configs.empty? && conf.valid?
59
+ true
60
+ elsif missing_configs.empty?
61
+ log("Configuration for #{component_namespace} failed validation!", :error)
62
+ false
63
+ else
64
+ missing_configs.each { |k, _v| log("Missing required configuration: #{k}", :error) }
65
+ false
66
+ end
67
+ end
68
+
69
+ # Describes features supported by a Sense
70
+ # @param list [String,Array<String,Symbol>] List of features supported by this BaseComponent
71
+ def features(list)
72
+ @features = [*list].map(&:to_sym)
73
+ end
74
+
75
+ # Determine if a BaseComponent subclass supports a feature
76
+ # @param key [String,Symbol] The feature in question
77
+ def supports?(key)
78
+ @features ||= []
79
+ @features.include?(key.to_sym)
80
+ end
81
+ end
82
+
83
+ # Base instance logging methods
84
+ module InstanceLoggingMethods
85
+ # Instance-level access to logging via the Class log method
86
+ # @param (see ClassLoggingMethods#log)
87
+ def log(message, level = :info)
88
+ self.class.log(message, level)
89
+ end
90
+ end
91
+
92
+ # Base instance utility methods
93
+ module InstanceUtilityMethods
94
+ # Allows caching operations (or retrieving cached versions)
95
+ # @param [String] key How to store/retrieved the cached value
96
+ # @param [Integer] expires How long to cache the value
97
+ def cache(key, expires: 600)
98
+ cache_key = self.class.config_key_for(key)
99
+ if !Waylon::Cache.key?(cache_key) && block_given?
100
+ result = yield
101
+ Waylon::Cache.store(cache_key, result, expires: expires)
102
+ elsif !Waylon::Cache.key?(cache_key)
103
+ return nil
104
+ end
105
+ Waylon::Cache.load(cache_key, expires: expires)
106
+ end
107
+
108
+ # A wrapper for access to a namespaced Config key
109
+ # @param [String] key The key name to lookup
110
+ def config(key)
111
+ conf = Config.instance
112
+ conf[self.class.config_key_for(key)]
113
+ end
114
+
115
+ # A wrapper for accessing the persistent storage
116
+ # @return [Waylon::Storage] The Storage wrapper class
117
+ def storage
118
+ Waylon::Storage
119
+ end
120
+
121
+ alias db storage
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Waylon
4
+ # Abstract route condition superclass
5
+ # @abstract
6
+ class Condition
7
+ attr_reader :action, :help, :mechanism
8
+
9
+ # @param mechanism The meat of the condition used to decide if this condition applies
10
+ # @param action [Symbol] The method to call if the condition matches
11
+ # @param allowed_groups [Array<Symbol>] The group names allowed to use this action
12
+ # @param help [String] Optional help text to describe usage for this action
13
+ def initialize(mechanism, action, allowed_groups, help = nil)
14
+ @mechanism = mechanism
15
+ @action = action
16
+ @allowed_groups = allowed_groups
17
+ @help = help
18
+ end
19
+
20
+ # Placeholder for determining if this condition applies to the given input
21
+ # @param _input [Waylon::Message] The input message
22
+ def matches?(_input)
23
+ false
24
+ end
25
+
26
+ # Checks if a user is allowed based on this condition
27
+ # @param user [Waylon::User] abstract user
28
+ def permits?(user)
29
+ return true if allows?(:everyone)
30
+
31
+ Logger.log("Checking permissions for #{user.email}", :debug)
32
+ group_class = user.class.sense.group_class
33
+ # Check for global admins
34
+ return true if Config.instance.admins.include?(user.email)
35
+ # Check for managed admins
36
+ return true if group_class.new("admins").include?(user)
37
+
38
+ permitted = false
39
+
40
+ [*@allowed_groups].each do |group|
41
+ permitted = true if group_class.new(group).include?(user)
42
+ break if permitted
43
+ end
44
+ permitted
45
+ end
46
+
47
+ # Tokens is used to provide details about the message input to the action
48
+ # @param _input [String] The message content as text
49
+ # @return [Array<String>] The tokens extracted from the input message
50
+ def tokens(_input)
51
+ []
52
+ end
53
+
54
+ private
55
+
56
+ # Determines if a group name is among the list of allowed groups for this condition
57
+ # @note Does not involve determining user group membership, just allows access to the list of allowed groups
58
+ # @param group [Symbol] A group name to lookup
59
+ def allows?(group)
60
+ @allowed_groups ||= []
61
+ [*@allowed_groups].include?(group.to_sym)
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Waylon
4
+ module Conditions
5
+ # A pre-made catch-all condition for denying access
6
+ class Default < Condition
7
+ # Overrides normal Condition initialization to force a specific action
8
+ def initialize(*_args) # rubocop:disable Lint/MissingSuper
9
+ @mechanism = nil
10
+ @action = :unknown
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
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Waylon
4
+ module Conditions
5
+ # A pre-made catch-all condition for denying access
6
+ class PermissionDenied < Condition
7
+ # Overrides normal Condition initialization to force a specific action
8
+ def initialize(*_args) # rubocop:disable Lint/MissingSuper
9
+ @mechanism = nil
10
+ @action = :denied
11
+ @allowed_groups = [:everyone]
12
+ @help = "This action is not allowed"
13
+ end
14
+
15
+ # Matches any input (since the PermissionDenied route, when used, should always function)
16
+ # @return [Boolean]
17
+ def matches?(_input)
18
+ true
19
+ end
20
+
21
+ # Permits any user (since the PermissionDenied 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
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Waylon
4
+ module Conditions
5
+ # Routing via Regular Expression
6
+ class Regex < Condition
7
+ # Checks if this condition matches the message
8
+ # @param message [String] The message text
9
+ # @return [Boolean]
10
+ def matches?(message)
11
+ @mechanism =~ message
12
+ end
13
+
14
+ # Provides the regular expression match groups as tokens
15
+ # @param input [String] The message text
16
+ # @return [Array<String>] The regular expression match groups
17
+ def tokens(input)
18
+ @mechanism.match(input).to_a[1..]
19
+ end
20
+ end
21
+ end
22
+ end