rita 0.1.0 → 5.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +19 -0
  3. data/.rubocop.yml +51 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +16 -0
  6. data/CONTRIBUTING.md +18 -0
  7. data/Gemfile +5 -0
  8. data/{LICENSE.txt → LICENSE} +1 -3
  9. data/README.md +17 -24
  10. data/Rakefile +5 -5
  11. data/bin/lita +7 -0
  12. data/lib/lita/adapter.rb +147 -0
  13. data/lib/lita/adapters/shell.rb +126 -0
  14. data/lib/lita/adapters/test.rb +62 -0
  15. data/lib/lita/authorization.rb +112 -0
  16. data/lib/lita/callback.rb +39 -0
  17. data/lib/lita/cli.rb +218 -0
  18. data/lib/lita/configurable.rb +47 -0
  19. data/lib/lita/configuration_builder.rb +247 -0
  20. data/lib/lita/configuration_validator.rb +95 -0
  21. data/lib/lita/default_configuration.rb +122 -0
  22. data/lib/lita/errors.rb +25 -0
  23. data/lib/lita/handler/chat_router.rb +141 -0
  24. data/lib/lita/handler/common.rb +208 -0
  25. data/lib/lita/handler/event_router.rb +84 -0
  26. data/lib/lita/handler/http_router.rb +31 -0
  27. data/lib/lita/handler.rb +15 -0
  28. data/lib/lita/handlers/authorization.rb +129 -0
  29. data/lib/lita/handlers/help.rb +171 -0
  30. data/lib/lita/handlers/info.rb +66 -0
  31. data/lib/lita/handlers/room.rb +36 -0
  32. data/lib/lita/handlers/users.rb +37 -0
  33. data/lib/lita/http_callback.rb +46 -0
  34. data/lib/lita/http_route.rb +83 -0
  35. data/lib/lita/logger.rb +43 -0
  36. data/lib/lita/message.rb +124 -0
  37. data/lib/lita/middleware_registry.rb +39 -0
  38. data/lib/lita/namespace.rb +29 -0
  39. data/lib/lita/plugin_builder.rb +43 -0
  40. data/lib/lita/rack_app.rb +100 -0
  41. data/lib/lita/registry.rb +164 -0
  42. data/lib/lita/response.rb +65 -0
  43. data/lib/lita/robot.rb +273 -0
  44. data/lib/lita/room.rb +119 -0
  45. data/lib/lita/route_validator.rb +82 -0
  46. data/lib/lita/rspec/handler.rb +127 -0
  47. data/lib/lita/rspec/matchers/chat_route_matcher.rb +53 -0
  48. data/lib/lita/rspec/matchers/event_route_matcher.rb +29 -0
  49. data/lib/lita/rspec/matchers/http_route_matcher.rb +34 -0
  50. data/lib/lita/rspec.rb +48 -0
  51. data/lib/lita/source.rb +81 -0
  52. data/lib/lita/store.rb +23 -0
  53. data/lib/lita/target.rb +3 -0
  54. data/lib/lita/template.rb +71 -0
  55. data/lib/lita/template_resolver.rb +52 -0
  56. data/lib/lita/timer.rb +49 -0
  57. data/lib/lita/user.rb +157 -0
  58. data/lib/lita/util.rb +31 -0
  59. data/lib/lita/version.rb +6 -0
  60. data/lib/lita.rb +166 -0
  61. data/rita.gemspec +50 -0
  62. data/spec/lita/adapter_spec.rb +54 -0
  63. data/spec/lita/adapters/shell_spec.rb +99 -0
  64. data/spec/lita/authorization_spec.rb +122 -0
  65. data/spec/lita/configuration_builder_spec.rb +247 -0
  66. data/spec/lita/configuration_validator_spec.rb +114 -0
  67. data/spec/lita/default_configuration_spec.rb +242 -0
  68. data/spec/lita/handler/chat_router_spec.rb +236 -0
  69. data/spec/lita/handler/common_spec.rb +289 -0
  70. data/spec/lita/handler/event_router_spec.rb +121 -0
  71. data/spec/lita/handler/http_router_spec.rb +155 -0
  72. data/spec/lita/handler_spec.rb +62 -0
  73. data/spec/lita/handlers/authorization_spec.rb +111 -0
  74. data/spec/lita/handlers/help_spec.rb +124 -0
  75. data/spec/lita/handlers/info_spec.rb +67 -0
  76. data/spec/lita/handlers/room_spec.rb +24 -0
  77. data/spec/lita/handlers/users_spec.rb +35 -0
  78. data/spec/lita/logger_spec.rb +28 -0
  79. data/spec/lita/message_spec.rb +178 -0
  80. data/spec/lita/plugin_builder_spec.rb +41 -0
  81. data/spec/lita/response_spec.rb +62 -0
  82. data/spec/lita/robot_spec.rb +285 -0
  83. data/spec/lita/room_spec.rb +136 -0
  84. data/spec/lita/rspec/handler_spec.rb +33 -0
  85. data/spec/lita/rspec_spec.rb +162 -0
  86. data/spec/lita/source_spec.rb +68 -0
  87. data/spec/lita/store_spec.rb +23 -0
  88. data/spec/lita/template_resolver_spec.rb +42 -0
  89. data/spec/lita/template_spec.rb +52 -0
  90. data/spec/lita/timer_spec.rb +32 -0
  91. data/spec/lita/user_spec.rb +167 -0
  92. data/spec/lita/util_spec.rb +18 -0
  93. data/spec/lita_spec.rb +227 -0
  94. data/spec/spec_helper.rb +35 -0
  95. data/spec/templates/basic.erb +1 -0
  96. data/spec/templates/basic.irc.erb +1 -0
  97. data/spec/templates/helpers.erb +1 -0
  98. data/spec/templates/interpolated.erb +1 -0
  99. data/templates/locales/en.yml +137 -0
  100. data/templates/plugin/Gemfile +5 -0
  101. data/templates/plugin/README.tt +29 -0
  102. data/templates/plugin/Rakefile +8 -0
  103. data/templates/plugin/gemspec.tt +27 -0
  104. data/templates/plugin/gitignore +18 -0
  105. data/templates/plugin/lib/lita/plugin_type/plugin.tt +19 -0
  106. data/templates/plugin/lib/plugin.tt +16 -0
  107. data/templates/plugin/locales/en.yml.tt +4 -0
  108. data/templates/plugin/spec/lita/plugin_type/plugin_spec.tt +6 -0
  109. data/templates/plugin/spec/spec_helper.tt +8 -0
  110. data/templates/plugin/templates/gitkeep +0 -0
  111. data/templates/robot/Gemfile +5 -0
  112. data/templates/robot/lita_config.rb +28 -0
  113. metadata +386 -21
  114. data/.standard.yml +0 -3
  115. data/CHANGELOG.md +0 -5
  116. data/CODE_OF_CONDUCT.md +0 -132
  117. data/lib/rita/version.rb +0 -5
  118. data/lib/rita.rb +0 -8
  119. data/sig/rita.rbs +0 -4
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require "shellwords"
5
+
6
+ module Lita
7
+ # Represents an incoming chat message.
8
+ class Message
9
+ extend Forwardable
10
+
11
+ # The body of the message.
12
+ # @return [String] The message body.
13
+ attr_reader :body
14
+
15
+ # The source of the message, which is a user and optional room.
16
+ # @return [Source] The message source.
17
+ attr_reader :source
18
+
19
+ # A hash of arbitrary data that can be populated by Lita adapters and extensions.
20
+ # @return [Hash] The extension data.
21
+ # @since 4.7.0
22
+ attr_reader :extensions
23
+
24
+ # @!method user
25
+ # The user who sent the message.
26
+ # @return [User] The user.
27
+ # @see Source#user
28
+ # @!method room_object
29
+ # The room where the message came from.
30
+ # @return [Room] The room.
31
+ # @see Source#room_object
32
+ # @since 4.5.0
33
+ # @!method private_message?
34
+ # Flag indicating that the message was sent to the robot privately.
35
+ # @return [Boolean] The boolean flag.
36
+ # @see Source#private_message?
37
+ # @since 4.5.0
38
+ def_delegators :source, :user, :room_object, :private_message?
39
+
40
+ # @param robot [Robot] The currently running robot.
41
+ # @param body [String] The body of the message.
42
+ # @param source [Source] The source of the message.
43
+ def initialize(robot, body, source)
44
+ @robot = robot
45
+ @body = body
46
+ @source = source
47
+ @extensions = {}
48
+
49
+ name_pattern = "@?#{Regexp.escape(@robot.mention_name)}[:,]?\\s+"
50
+ alias_pattern = "#{Regexp.escape(@robot.alias)}\\s*" if @robot.alias
51
+ command_regex = if alias_pattern
52
+ /\A\s*(?:#{name_pattern}|#{alias_pattern})/i
53
+ else
54
+ /\A\s*#{name_pattern}/i
55
+ end
56
+
57
+ @body = @body.sub(command_regex) do
58
+ @command = true
59
+
60
+ ""
61
+ end
62
+ end
63
+
64
+ # An array of arguments created by shellsplitting the message body, as if
65
+ # it were a shell command.
66
+ # @return [Array<String>] The array of arguments.
67
+ def args
68
+ begin
69
+ _command, *args = body.shellsplit
70
+ rescue ArgumentError
71
+ _command, *args =
72
+ body.split(/\s+/).map(&:shellescape).join(" ").shellsplit
73
+ end
74
+
75
+ args
76
+ end
77
+
78
+ # Marks the message as a command, meaning it was directed at the robot
79
+ # specifically.
80
+ # @return [void]
81
+ def command!
82
+ @command = true
83
+ end
84
+
85
+ # A boolean representing whether or not the message was a command.
86
+ # @return [Boolean] +true+ if the message was a command, +false+ if not.
87
+ def command?
88
+ @command
89
+ end
90
+
91
+ # An array of matches against the message body for the given {::Regexp}.
92
+ # @param pattern [Regexp] A pattern to match.
93
+ # @return [Array<String>, Array<Array<String>>] An array of matches.
94
+ def match(pattern)
95
+ body.scan(pattern)
96
+ end
97
+
98
+ # Replies by sending the given strings back to the source of the message.
99
+ # @param strings [String, Array<String>] The strings to send back.
100
+ # @return [void]
101
+ def reply(*strings)
102
+ @robot.send_messages(source, *strings)
103
+ end
104
+
105
+ # Replies by sending the given strings back to the user who sent the
106
+ # message directly, even if the message was sent in a room.
107
+ # @param strings [String, Array<String>] The strings to send back.
108
+ # @return [void]
109
+ def reply_privately(*strings)
110
+ private_source = source.clone
111
+ private_source.private_message!
112
+ @robot.send_messages(private_source, *strings)
113
+ end
114
+
115
+ # Replies by sending the given strings back to the source of the message.
116
+ # Each message is prefixed with the user's mention name.
117
+ # @param strings [String, Array<String>] The strings to send back.
118
+ # @return [void]
119
+ # @since 3.1.0
120
+ def reply_with_mention(*strings)
121
+ @robot.send_messages_with_mention(source, *strings)
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module Lita
6
+ # Stores Rack middleware for later use in a +Rack::Builder+.
7
+ # @since 4.0.2
8
+ # @api private
9
+ class MiddlewareRegistry
10
+ # A Rack middleware and its initialization arguments.
11
+ MiddlewareWrapper = Struct.new(:middleware, :args, :block)
12
+
13
+ extend Forwardable
14
+
15
+ def_delegators :@registry, :each, :empty?
16
+
17
+ def initialize
18
+ @registry = []
19
+ end
20
+
21
+ # Adds a Rack middleware with no initialization arguments.
22
+ # @param middleware [#call] A Rack middleware.
23
+ # @return [void]
24
+ def push(middleware)
25
+ @registry << MiddlewareWrapper.new(middleware, [], nil)
26
+ end
27
+ alias << push
28
+
29
+ # Adds a Rack middleware with initialization argumens. Uses the same interface as
30
+ # +Rack::Builder#use+.
31
+ # @param middleware [#call] A Rack middleware.
32
+ # @param args [Array] Arbitrary initialization arguments for the middleware.
33
+ # @yield An optional block to be passed to the constructor of the middleware.
34
+ # @return [void]
35
+ def use(middleware, *args, &block)
36
+ @registry << MiddlewareWrapper.new(middleware, args, block)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "i18n"
4
+
5
+ require_relative "util"
6
+
7
+ module Lita
8
+ # A mixin for setting and getting a plugin's namespace.
9
+ # @since 4.0.0
10
+ module Namespace
11
+ # Gets (and optionally sets) the namespace for a plugin. The namespace is generated from the
12
+ # class's name by default.
13
+ # @param value [String] If provided, sets the namespace of the plugin to the value.
14
+ # @return [String] The namespace.
15
+ # @raise [RuntimeError] If the plugin is an anonymous class, does not define +self.name+, and
16
+ # has not set a namespace manually.
17
+ def namespace(value = nil)
18
+ @namespace = value.to_s if value
19
+
20
+ string_name = defined?(@namespace) ? @namespace : name
21
+
22
+ if string_name
23
+ Util.underscore(string_name.split("::").last)
24
+ else
25
+ raise I18n.t("lita.plugin.name_required")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "adapter"
4
+ require_relative "handler"
5
+
6
+ module Lita
7
+ # Constructs a Lita plugin from a block.
8
+ # @since 4.0.0
9
+ # @api private
10
+ class PluginBuilder
11
+ # @param namespace [String, Symbol] The Redis namespace to use for the plugin.
12
+ # @yield The class body of the plugin.
13
+ def initialize(namespace, &block)
14
+ @namespace = namespace.to_s
15
+ @block = block
16
+ end
17
+
18
+ # Constructs an {Adapter} from the provided block.
19
+ # @return [Adapter]
20
+ def build_adapter
21
+ adapter = create_plugin(Adapter)
22
+ adapter.class_exec(&@block)
23
+ adapter
24
+ end
25
+
26
+ # Constructs a {Handler} from the provided block.
27
+ # @return [Handler]
28
+ def build_handler
29
+ handler = create_plugin(Handler)
30
+ handler.class_exec(&@block)
31
+ handler
32
+ end
33
+
34
+ private
35
+
36
+ # Creates a class of the relevant plugin type and sets its namespace.
37
+ def create_plugin(plugin_type)
38
+ plugin = Class.new(plugin_type)
39
+ plugin.namespace(@namespace)
40
+ plugin
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+ require "uri"
5
+
6
+ require "http_router"
7
+ require "rack"
8
+
9
+ # The http_router gem still uses URI.escape which has been removed from Ruby 3.0.
10
+ unless URI.respond_to?(:escape)
11
+ def URI.escape(*args)
12
+ CGI.escape(*args)
13
+ end
14
+ end
15
+
16
+ # The http_router gem still uses URI.unescape which has been removed from Ruby 3.0.
17
+ unless URI.respond_to?(:unescape)
18
+ def URI.unescape(*args)
19
+ CGI.unescape(*args)
20
+ end
21
+ end
22
+
23
+ module Lita
24
+ # A +Rack+ application to serve HTTP routes registered by handlers.
25
+ # @api private
26
+ class RackApp
27
+ # The currently running robot.
28
+ # @return [Robot] The robot.
29
+ attr_reader :robot
30
+
31
+ # An +HttpRouter+ used for dispatch.
32
+ # @return [HttpRouter] The router.
33
+ attr_reader :router
34
+
35
+ # Constructs a {RackApp} inside a +Rack::Builder+, including any configured middleware.
36
+ # @param robot [Robot] The currently running robot.
37
+ # @return [RackApp, Class] The Rack application.
38
+ def self.build(robot)
39
+ builder = Rack::Builder.new
40
+ builder.run(new(robot))
41
+
42
+ robot.config.http.middleware.each do |wrapper|
43
+ if wrapper.block
44
+ builder.use(wrapper.middleware, *wrapper.args, &wrapper.block)
45
+ else
46
+ builder.use(wrapper.middleware, *wrapper.args)
47
+ end
48
+ end
49
+
50
+ builder.to_app
51
+ end
52
+
53
+ # @param robot [Robot] The currently running robot.
54
+ def initialize(robot)
55
+ @robot = robot
56
+ @router = HttpRouter.new
57
+ compile
58
+ end
59
+
60
+ # Entry point for Lita's HTTP routes. Invokes the Rack application.
61
+ # @param env [Hash] A Rack environment.
62
+ # @return [void]
63
+ def call(env)
64
+ env["lita.robot"] = robot
65
+ router.call(env)
66
+ end
67
+
68
+ # Overrides the default inspect implementation to make output less verbose and more readable.
69
+ def inspect
70
+ hex_address = (object_id << 1).to_s(16).rjust(14, "0")
71
+ "#<Lita::RackApp:0x#{hex_address}>"
72
+ end
73
+
74
+ # Finds the first route that matches the request environment, if any. Does not trigger the
75
+ # route.
76
+ # @param env [Hash] A Rack environment.
77
+ # @return [Array] An array of the name of the first matching route.
78
+ # @since 4.0.0
79
+ def recognize(env)
80
+ env["lita.robot"] = robot
81
+ recognized_routes_for(env).map { |match| match.route.name }
82
+ end
83
+
84
+ private
85
+
86
+ # Registers routes in the router for each handler's defined routes.
87
+ def compile
88
+ robot.handlers.each do |handler|
89
+ next unless handler.respond_to?(:http_routes)
90
+
91
+ handler.http_routes.each { |route| router.add_route(route) }
92
+ end
93
+ end
94
+
95
+ # Returns an array containing the first recongnized route, if any.
96
+ def recognized_routes_for(env)
97
+ Array(router.recognize(env).first)
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+
5
+ require "i18n"
6
+ require "redis-namespace"
7
+
8
+ require_relative "../lita"
9
+ require_relative "default_configuration"
10
+ require_relative "plugin_builder"
11
+
12
+ module Lita
13
+ # An object to hold various types of data including configuration and plugins.
14
+ # @since 4.0.0
15
+ class Registry
16
+ # Allows a registry to be added to another object.
17
+ module Mixins
18
+ # The primary configuration object. Provides user settings for the robot.
19
+ # @return [Configuration] The configuration object.
20
+ def config
21
+ @config ||= DefaultConfiguration.new(self).build
22
+ end
23
+
24
+ # Yields the configuration object. Called by the user in a +lita_config.rb+ file.
25
+ # @yieldparam [Configuration] config The configuration object.
26
+ # @return [void]
27
+ def configure
28
+ yield config
29
+ end
30
+
31
+ # A registry of adapters.
32
+ # @return [Hash] A map of adapter keys to adapter classes.
33
+ def adapters
34
+ @adapters ||= {}
35
+ end
36
+
37
+ # A registry of handlers.
38
+ # @return [Set] The set of handlers.
39
+ def handlers
40
+ @handlers ||= Set.new
41
+ end
42
+
43
+ # A registry of hook handler objects.
44
+ # @return [Hash] A hash mapping hook names to sets of objects that handle them.
45
+ # @since 3.2.0
46
+ def hooks
47
+ @hooks ||= Hash.new { |h, k| h[k] = Set.new }
48
+ end
49
+
50
+ # The root Redis object.
51
+ # @return [Redis::Namespace] The root Redis object.
52
+ def redis
53
+ @redis ||= begin
54
+ redis = Redis.new(config.redis)
55
+ Redis::Namespace.new(config.robot.redis_namespace, redis: redis).tap(&:ping)
56
+ end
57
+ rescue Redis::BaseError => e
58
+ if Lita.test_mode?
59
+ raise RedisError, I18n.t("lita.redis.test_mode_exception", message: e.message)
60
+ else
61
+ Lita.logger.fatal I18n.t(
62
+ "lita.redis.exception",
63
+ message: e.message,
64
+ backtrace: e.backtrace.join("\n")
65
+ )
66
+ exit(false)
67
+ end
68
+ end
69
+
70
+ # @overload register_adapter(key, adapter)
71
+ # Adds an adapter to the registry under the provided key.
72
+ # @param key [String, Symbol] The key that identifies the adapter.
73
+ # @param adapter [Class] The adapter class.
74
+ # @return [void]
75
+ # @overload register_adapter(key)
76
+ # Adds an adapter to the registry under the provided key.
77
+ # @param key [String, Symbol] The key that identifies the adapter.
78
+ # @yield The body of the adapter class.
79
+ # @return [void]
80
+ # @since 4.0.0
81
+ def register_adapter(key, adapter = nil, &block)
82
+ adapter = PluginBuilder.new(key, &block).build_adapter if block
83
+
84
+ unless adapter.is_a?(Class)
85
+ raise ArgumentError, I18n.t("lita.core.register_adapter.block_or_class_required")
86
+ end
87
+
88
+ adapters[key.to_sym] = adapter
89
+ end
90
+
91
+ # @overload register_handler(handler)
92
+ # Adds a handler to the registry.
93
+ # @param handler [Handler] The handler class.
94
+ # @return [void]
95
+ # @overload register_handler(key)
96
+ # Adds a handler to the registry.
97
+ # @param key [String] The namespace of the handler.
98
+ # @yield The body of the handler class.
99
+ # @return [void]
100
+ # @since 4.0.0
101
+ def register_handler(handler_or_key, &block)
102
+ if block
103
+ handler = PluginBuilder.new(handler_or_key, &block).build_handler
104
+ else
105
+ handler = handler_or_key
106
+
107
+ unless handler.is_a?(Class)
108
+ raise ArgumentError, I18n.t("lita.core.register_handler.block_or_class_required")
109
+ end
110
+ end
111
+
112
+ handlers << handler
113
+ end
114
+
115
+ # Adds a hook handler object to the registry for the given hook.
116
+ # @return [void]
117
+ # @since 3.2.0
118
+ def register_hook(name, hook)
119
+ hooks[name.to_s.downcase.strip.to_sym] << hook
120
+ end
121
+
122
+ # Clears the configuration object and the adapter, handler, and hook registries.
123
+ # @return [void]
124
+ # @since 3.2.0
125
+ def reset
126
+ reset_adapters
127
+ reset_config
128
+ reset_handlers
129
+ reset_hooks
130
+ end
131
+
132
+ # Resets the adapter registry, removing all registered adapters.
133
+ # @return [void]
134
+ # @since 3.2.0
135
+ def reset_adapters
136
+ @adapters = nil
137
+ end
138
+
139
+ # Resets the configuration object. The next call to {#config}
140
+ # will create a fresh config object.
141
+ # @return [void]
142
+ def reset_config
143
+ @config = nil
144
+ end
145
+ alias clear_config reset_config
146
+
147
+ # Resets the handler registry, removing all registered handlers.
148
+ # @return [void]
149
+ # @since 3.2.0
150
+ def reset_handlers
151
+ @handlers = nil
152
+ end
153
+
154
+ # Resets the hooks registry, removing all registered hook handlers.
155
+ # @return [void]
156
+ # @since 3.2.0
157
+ def reset_hooks
158
+ @hooks = nil
159
+ end
160
+ end
161
+
162
+ include Mixins
163
+ end
164
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ module Lita
6
+ # A wrapper object that provides the primary interface for handlers to
7
+ # respond to incoming chat messages.
8
+ class Response
9
+ extend Forwardable
10
+
11
+ # The incoming message.
12
+ # @return [Message] The message.
13
+ attr_accessor :message
14
+
15
+ # A hash of arbitrary data that can be populated by Lita extensions.
16
+ # @return [Hash] The extensions data.
17
+ # @since 3.2.0
18
+ attr_accessor :extensions
19
+
20
+ # The pattern the incoming message matched.
21
+ # @return [Regexp] The pattern.
22
+ attr_accessor :pattern
23
+
24
+ # @!method args
25
+ # @see Message#args
26
+ # @!method reply(*strings)
27
+ # @see Message#reply
28
+ # @!method reply_privately(*strings)
29
+ # @see Message#reply_privately
30
+ # @!method reply_with_mention(*strings)
31
+ # @see Message#reply_with_mention
32
+ # @!method user
33
+ # @see Message#user
34
+ # @!method private_message?
35
+ # @see Message#private_message?
36
+ # @since 4.5.0
37
+ def_delegators :message, :args, :reply, :reply_privately,
38
+ :reply_with_mention, :user, :private_message?, :command?
39
+
40
+ # @!method room
41
+ # @see Message#room_object
42
+ # @since 4.5.0
43
+ def_delegator :message, :room_object, :room
44
+
45
+ # @param message [Message] The incoming message.
46
+ # @param pattern [Regexp] The pattern the incoming message matched.
47
+ def initialize(message, pattern)
48
+ self.message = message
49
+ self.extensions = {}
50
+ self.pattern = pattern
51
+ end
52
+
53
+ # An array of matches from scanning the message against the route pattern.
54
+ # @return [Array<String>, Array<Array<String>>] The array of matches.
55
+ def matches
56
+ @matches ||= message.match(pattern)
57
+ end
58
+
59
+ # A +MatchData+ object from running the pattern against the message body.
60
+ # @return [MatchData] The +MatchData+.
61
+ def match_data
62
+ @match_data ||= pattern.match(message.body)
63
+ end
64
+ end
65
+ end