rita 0.1.0 → 5.0.0.alpha.2

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/lib/rita.rb +2 -7
  62. data/rita.gemspec +50 -0
  63. data/spec/lita/adapter_spec.rb +54 -0
  64. data/spec/lita/adapters/shell_spec.rb +99 -0
  65. data/spec/lita/authorization_spec.rb +122 -0
  66. data/spec/lita/configuration_builder_spec.rb +247 -0
  67. data/spec/lita/configuration_validator_spec.rb +114 -0
  68. data/spec/lita/default_configuration_spec.rb +242 -0
  69. data/spec/lita/handler/chat_router_spec.rb +236 -0
  70. data/spec/lita/handler/common_spec.rb +289 -0
  71. data/spec/lita/handler/event_router_spec.rb +121 -0
  72. data/spec/lita/handler/http_router_spec.rb +155 -0
  73. data/spec/lita/handler_spec.rb +62 -0
  74. data/spec/lita/handlers/authorization_spec.rb +111 -0
  75. data/spec/lita/handlers/help_spec.rb +124 -0
  76. data/spec/lita/handlers/info_spec.rb +67 -0
  77. data/spec/lita/handlers/room_spec.rb +24 -0
  78. data/spec/lita/handlers/users_spec.rb +35 -0
  79. data/spec/lita/logger_spec.rb +28 -0
  80. data/spec/lita/message_spec.rb +178 -0
  81. data/spec/lita/plugin_builder_spec.rb +41 -0
  82. data/spec/lita/response_spec.rb +62 -0
  83. data/spec/lita/robot_spec.rb +285 -0
  84. data/spec/lita/room_spec.rb +136 -0
  85. data/spec/lita/rspec/handler_spec.rb +33 -0
  86. data/spec/lita/rspec_spec.rb +162 -0
  87. data/spec/lita/source_spec.rb +68 -0
  88. data/spec/lita/store_spec.rb +23 -0
  89. data/spec/lita/template_resolver_spec.rb +42 -0
  90. data/spec/lita/template_spec.rb +52 -0
  91. data/spec/lita/timer_spec.rb +32 -0
  92. data/spec/lita/user_spec.rb +167 -0
  93. data/spec/lita/util_spec.rb +18 -0
  94. data/spec/lita_spec.rb +227 -0
  95. data/spec/spec_helper.rb +35 -0
  96. data/spec/templates/basic.erb +1 -0
  97. data/spec/templates/basic.irc.erb +1 -0
  98. data/spec/templates/helpers.erb +1 -0
  99. data/spec/templates/interpolated.erb +1 -0
  100. data/templates/locales/en.yml +137 -0
  101. data/templates/plugin/Gemfile +5 -0
  102. data/templates/plugin/README.tt +29 -0
  103. data/templates/plugin/Rakefile +8 -0
  104. data/templates/plugin/gemspec.tt +27 -0
  105. data/templates/plugin/gitignore +18 -0
  106. data/templates/plugin/lib/lita/plugin_type/plugin.tt +19 -0
  107. data/templates/plugin/lib/plugin.tt +16 -0
  108. data/templates/plugin/locales/en.yml.tt +4 -0
  109. data/templates/plugin/spec/lita/plugin_type/plugin_spec.tt +6 -0
  110. data/templates/plugin/spec/spec_helper.tt +8 -0
  111. data/templates/plugin/templates/gitkeep +0 -0
  112. data/templates/robot/Gemfile +5 -0
  113. data/templates/robot/lita_config.rb +28 -0
  114. metadata +386 -20
  115. data/.standard.yml +0 -3
  116. data/CHANGELOG.md +0 -5
  117. data/CODE_OF_CONDUCT.md +0 -132
  118. data/lib/rita/version.rb +0 -5
  119. data/sig/rita.rbs +0 -4
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lita
4
+ # A namespace to hold all subclasses of {Handler}.
5
+ module Handlers
6
+ # Provides a chat interface for administering authorization groups.
7
+ class Authorization
8
+ extend Handler::ChatRouter
9
+
10
+ route(
11
+ /^auth\s+add/,
12
+ :add,
13
+ command: true,
14
+ restrict_to: :admins,
15
+ help: { t("help.add_key") => t("help.add_value") }
16
+ )
17
+ route(
18
+ /^auth\s+remove/,
19
+ :remove,
20
+ command: true,
21
+ restrict_to: :admins,
22
+ help: { t("help.remove_key") => t("help.remove_value") }
23
+ )
24
+ route(/^auth\s+list/, :list, command: true, restrict_to: :admins, help: {
25
+ t("help.list_key") => t("help.list_value")
26
+ })
27
+
28
+ # Adds a user to an authorization group.
29
+ # @param response [Response] The response object.
30
+ # @return [void]
31
+ def add(response)
32
+ toggle_membership(response, :add_user_to_group, "user_added", "user_already_in")
33
+ end
34
+
35
+ # Removes a user from an authorization group.
36
+ # @param response [Response] The response object.
37
+ # @return [void]
38
+ def remove(response)
39
+ toggle_membership(response, :remove_user_from_group, "user_removed", "user_not_in")
40
+ end
41
+
42
+ # Lists all authorization groups (or only the specified group) and the
43
+ # names of their members.
44
+ # @param response [Response] The response object.
45
+ # @return [void]
46
+ def list(response)
47
+ requested_group = response.args[1]
48
+ output = get_groups_list(response.args[1])
49
+ if output.empty?
50
+ response.reply(empty_state_for_list(requested_group))
51
+ else
52
+ response.reply(output.join("\n"))
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def empty_state_for_list(requested_group)
59
+ if requested_group
60
+ t("empty_state_group", group: requested_group)
61
+ else
62
+ t("empty_state")
63
+ end
64
+ end
65
+
66
+ def get_groups_list(requested_group)
67
+ groups_with_users = robot.auth.groups_with_users
68
+ if requested_group
69
+ requested_group = requested_group.downcase.strip.to_sym
70
+ groups_with_users.select! { |group, _| group == requested_group }
71
+ end
72
+ groups_with_users.map do |group, users|
73
+ user_names = users.map(&:name).join(", ")
74
+ "#{group}: #{user_names}"
75
+ end
76
+ end
77
+
78
+ def toggle_membership(response, method_name, success_key, failure_key)
79
+ return unless valid_message?(response)
80
+
81
+ if robot.auth.public_send(method_name, response.user, @user, @group)
82
+ response.reply t(success_key, user: @user.name, group: @group)
83
+ else
84
+ response.reply t(failure_key, user: @user.name, group: @group)
85
+ end
86
+ end
87
+
88
+ def valid_group?(response, identifier)
89
+ unless identifier && @group
90
+ response.reply "#{t("format")}: #{robot.name} auth add USER GROUP"
91
+ return false
92
+ end
93
+
94
+ if @group.downcase.strip == "admins"
95
+ response.reply t("admin_management")
96
+ return false
97
+ end
98
+
99
+ true
100
+ end
101
+
102
+ # Validates that incoming messages have the right format and a valid user.
103
+ # Also assigns the user and group to instance variables for the main
104
+ # methods to use later.
105
+ def valid_message?(response)
106
+ _command, identifier, @group = response.args
107
+
108
+ return unless valid_group?(response, identifier)
109
+
110
+ return unless valid_user?(response, identifier)
111
+
112
+ true
113
+ end
114
+
115
+ def valid_user?(response, identifier)
116
+ @user = User.fuzzy_find(identifier)
117
+
118
+ if @user
119
+ true
120
+ else
121
+ response.reply t("no_user_found", identifier: identifier)
122
+ false
123
+ end
124
+ end
125
+ end
126
+
127
+ Lita.register_handler(Authorization)
128
+ end
129
+ end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lita
4
+ # A namespace to hold all subclasses of {Handler}.
5
+ module Handlers
6
+ # Provides online help about Lita commands for users.
7
+ class Help
8
+ extend Handler::ChatRouter
9
+
10
+ route(/^help\s*(?<query>.+)?/i, :help, command: true, help: {
11
+ "help" => t("help.help_value"),
12
+ t("help.help_query_key") => t("help.help_query_value")
13
+ })
14
+
15
+ # Outputs help information about Lita commands.
16
+ # @param response [Response] The response object.
17
+ # @return [void]
18
+ def help(response)
19
+ query = response.match_data["query"]
20
+
21
+ if query.nil?
22
+ return response.reply_privately(
23
+ "#{t("info", address: address)}\n\n#{list_handlers.join("\n")}"
24
+ )
25
+ end
26
+
27
+ handlers = matching_handlers(query)
28
+ handlers_to_messages = map_handlers_to_messages(response, handlers)
29
+ messages = matching_messages(response, query, handlers_to_messages)
30
+ response.reply_privately(format_reply(handlers_to_messages, messages, query))
31
+ end
32
+
33
+ private
34
+
35
+ # Checks if the user is authorized to at least one of the given groups.
36
+ def authorized?(user, required_groups)
37
+ required_groups.nil? || required_groups.any? do |group|
38
+ robot.auth.user_in_group?(user, group)
39
+ end
40
+ end
41
+
42
+ # Creates an alphabetically-sorted array containing the names of all
43
+ # installed handlers.
44
+ def list_handlers
45
+ robot.handlers.flat_map do |handler|
46
+ handler.namespace if handler.respond_to?(:routes)
47
+ end.compact.uniq.sort
48
+ end
49
+
50
+ # Creates an array of handlers matching the given query.
51
+ def matching_handlers(query)
52
+ name = query.downcase.strip
53
+
54
+ return [] unless list_handlers.include?(name)
55
+
56
+ robot.handlers.select { |handler| handler.namespace == name }
57
+ end
58
+
59
+ # Creates a hash of handler namespaces and their associated help messages.
60
+ def map_handlers_to_messages(response, handlers)
61
+ handlers_to_messages = {}
62
+ handlers.each do |handler|
63
+ messages = if handler.respond_to?(:routes)
64
+ handler.routes.map do |route|
65
+ route.help.map do |command, description|
66
+ help_command(response, route, command, description)
67
+ end
68
+ end.flatten
69
+ else
70
+ []
71
+ end
72
+
73
+ (handlers_to_messages[handler.namespace] ||= []).push(*messages)
74
+ end
75
+
76
+ handlers_to_messages
77
+ end
78
+
79
+ # Creates an array of help messages for all registered routes.
80
+ def all_help_messages(response)
81
+ robot.handlers.map do |handler|
82
+ next unless handler.respond_to?(:routes)
83
+
84
+ handler.routes.map do |route|
85
+ route.help.map do |command, description|
86
+ help_command(response, route, command, description)
87
+ end
88
+ end
89
+ end.flatten.compact
90
+ end
91
+
92
+ # Creates an array consisting of all help messages that match the given
93
+ # query.
94
+ def all_matching_messages(response, query)
95
+ filter_messages(all_help_messages(response), query)
96
+ end
97
+
98
+ # Removes matching help messages that are already present in the
99
+ # comprehensive array of help messages defined by the requested
100
+ # handler(s).
101
+ def dedup_messages(handlers_to_messages, messages)
102
+ all_handler_messages = handlers_to_messages.values.flatten
103
+ messages.reject { |m| all_handler_messages.include?(m) }
104
+ end
105
+
106
+ # Creates an array of help messages matching the given query, minus
107
+ # duplicates.
108
+ def matching_messages(response, query, handlers_to_messages)
109
+ dedup_messages(handlers_to_messages, all_matching_messages(response, query))
110
+ end
111
+
112
+ # Filters help messages matching a query.
113
+ def filter_messages(messages, query)
114
+ messages.select do |line|
115
+ /(?:@?#{Regexp.escape(address)})?#{Regexp.escape(query)}/i.match?(line)
116
+ end
117
+ end
118
+
119
+ # Formats a block of text associating a handler namespace with the help
120
+ # messages it defines.
121
+ def format_handler_messages(handler, messages)
122
+ unless messages.empty?
123
+ "#{t("handler_contains", handler: handler)}:\n\n" + messages.join("\n")
124
+ end
125
+ end
126
+
127
+ # Formats a block of text for message patterns or descriptions that directly match the user's
128
+ # query.
129
+ def format_messages(messages, query)
130
+ if messages.empty?
131
+ messages
132
+ else
133
+ ["#{t("pattern_or_description_contains", query: query)}:\n"] + messages
134
+ end
135
+ end
136
+
137
+ # Formats the message to be sent in response to a help command.
138
+ def format_reply(handlers_to_messages, messages, query)
139
+ return t("no_help_found") if handlers_to_messages.empty? && messages.empty?
140
+
141
+ handler_messages = handlers_to_messages.keys.map do |handler|
142
+ format_handler_messages(handler, handlers_to_messages[handler])
143
+ end.compact
144
+ separator = handler_messages.empty? || messages.empty? ? "" : "\n\n"
145
+ [handler_messages, format_messages(messages, query)].map do |m|
146
+ m.join("\n")
147
+ end.join(separator)
148
+ end
149
+
150
+ # Formats an individual command's help message.
151
+ def help_command(response, route, command, description)
152
+ command = "#{address}#{command}" if route.command?
153
+ message = "#{command} - #{description}"
154
+ message << t("unauthorized") unless authorized?(response.user, route.required_groups)
155
+ message
156
+ end
157
+
158
+ # The way the bot should be addressed in order to trigger a command.
159
+ def address
160
+ robot.config.robot.alias || "#{name}: "
161
+ end
162
+
163
+ # Fallback in case no alias is defined.
164
+ def name
165
+ robot.config.robot.mention_name || robot.config.robot.name
166
+ end
167
+ end
168
+
169
+ Lita.register_handler(Help)
170
+ end
171
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Lita
6
+ # A namespace to hold all subclasses of {Handler}.
7
+ module Handlers
8
+ # Provides information about the currently running robot.
9
+ class Info
10
+ extend Handler::ChatRouter
11
+ extend Handler::HTTPRouter
12
+
13
+ route(/^info$/i, :chat, command: true, help: {
14
+ "info" => t("help.info_value")
15
+ })
16
+
17
+ http.get "/lita/info", :web
18
+
19
+ # Replies with the current version of Lita, the current version of Redis,
20
+ # and Redis memory usage.
21
+ # @param response [Response] The response object.
22
+ # @return [void]
23
+ # @since 3.0.0
24
+ def chat(response)
25
+ response.reply(
26
+ %(Lita #{Lita::VERSION} - https://www.lita.io/),
27
+ %(Redis #{redis_version} - Memory used: #{redis_memory_usage})
28
+ )
29
+ end
30
+
31
+ # Returns JSON with basic information about the robot.
32
+ # @param _request [Rack::Request] The HTTP request.
33
+ # @param response [Rack::Response] The HTTP response.
34
+ # @return [void]
35
+ def web(_request, response)
36
+ response.headers["Content-Type"] = "application/json"
37
+ json = JSON.dump(
38
+ adapter: robot.config.robot.adapter,
39
+ lita_version: Lita::VERSION,
40
+ redis_memory_usage: redis_memory_usage,
41
+ redis_version: redis_version,
42
+ robot_mention_name: robot.mention_name,
43
+ robot_name: robot.name
44
+ )
45
+ response.write(json)
46
+ end
47
+
48
+ # A hash of information about Redis.
49
+ def redis_info
50
+ @redis_info ||= Lita.redis.redis.info
51
+ end
52
+
53
+ # The current version of Redis.
54
+ def redis_version
55
+ redis_info["redis_version"]
56
+ end
57
+
58
+ # The amount of memory Redis is using.
59
+ def redis_memory_usage
60
+ redis_info["used_memory_human"]
61
+ end
62
+ end
63
+
64
+ Lita.register_handler(Info)
65
+ end
66
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lita
4
+ # A namespace to hold all subclasses of {Handler}.
5
+ module Handlers
6
+ # Allows administrators to make Lita join and part from rooms.
7
+ # @since 3.0.0
8
+ class Room
9
+ extend Handler::ChatRouter
10
+
11
+ route(/^join\s+(.+)$/i, :join, command: true, restrict_to: :admins, help: {
12
+ t("help.join_key") => t("help.join_value")
13
+ })
14
+
15
+ route(/^part\s+(.+)$/i, :part, command: true, restrict_to: :admins, help: {
16
+ t("help.part_key") => t("help.part_value")
17
+ })
18
+
19
+ # Joins the room with the specified ID.
20
+ # @param response [Response] The response object.
21
+ # @return [void]
22
+ def join(response)
23
+ robot.join(response.args[0])
24
+ end
25
+
26
+ # Parts from the room with the specified ID.
27
+ # @param response [Response] The response object.
28
+ # @return [void]
29
+ def part(response)
30
+ robot.part(response.args[0])
31
+ end
32
+ end
33
+
34
+ Lita.register_handler(Room)
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lita
4
+ module Handlers
5
+ # Provides information on Lita users.
6
+ # @since 4.1.0
7
+ class Users
8
+ extend Handler::ChatRouter
9
+
10
+ route(/^users\s+find\s+(.+)/i, :find, command: true, help: {
11
+ t("help.find_key") => t("help.find_value")
12
+ })
13
+
14
+ # Outputs the name, ID, and mention name of a user matching the search query.
15
+ # @param response [Response] The response object.
16
+ # @return [void]
17
+ def find(response)
18
+ user = User.fuzzy_find(response.args[1])
19
+
20
+ if user
21
+ response.reply(formatted_user(user))
22
+ else
23
+ response.reply(t("find_empty_state"))
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # Extract and label the relevant user information.
30
+ def formatted_user(user)
31
+ "#{user.name} (ID: #{user.id}, Mention name: #{user.mention_name})"
32
+ end
33
+ end
34
+
35
+ Lita.register_handler(Users)
36
+ end
37
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack"
4
+
5
+ module Lita
6
+ # A wrapper around a handler's HTTP route callbacks that sets up the request and response.
7
+ # @api private
8
+ # @since 4.0.0
9
+ class HTTPCallback
10
+ # @param handler_class [Handler] The handler defining the callback.
11
+ # @param callback [Proc] The callback.
12
+ def initialize(handler_class, callback)
13
+ @handler_class = handler_class
14
+ @callback = callback
15
+ end
16
+
17
+ # Call the Rack endpoint with a standard environment hash.
18
+ def call(env)
19
+ request = Rack::Request.new(env)
20
+ response = Rack::Response.new
21
+
22
+ if request.head?
23
+ response.status = 204
24
+ else
25
+ begin
26
+ handler = @handler_class.new(env["lita.robot"])
27
+
28
+ @callback.call(handler, request, response)
29
+ rescue StandardError => e
30
+ robot = env["lita.robot"]
31
+ error_handler = robot.config.robot.error_handler
32
+
33
+ if error_handler.arity == 2
34
+ error_handler.call(e, rack_env: env, robot: robot)
35
+ else
36
+ error_handler.call(e)
37
+ end
38
+
39
+ raise
40
+ end
41
+ end
42
+
43
+ response.finish
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "http_router"
4
+
5
+ require_relative "callback"
6
+ require_relative "http_callback"
7
+
8
+ module Lita
9
+ # Handlers use this class to define HTTP routes for the built-in web
10
+ # server.
11
+ class HTTPRoute
12
+ # An +HttpRouter::Route+ class used for dispatch.
13
+ # @since 3.0.0
14
+ ExtendedRoute = Class.new(HttpRouter::Route) do
15
+ include HttpRouter::RouteHelper
16
+ include HttpRouter::GenerationHelper
17
+ end
18
+
19
+ # The handler registering the route.
20
+ # @return [Handler] The handler.
21
+ attr_reader :handler_class
22
+
23
+ # @param handler_class [Handler] The handler registering the route.
24
+ def initialize(handler_class)
25
+ @handler_class = handler_class
26
+ end
27
+
28
+ class << self
29
+ private
30
+
31
+ # @!macro define_http_method
32
+ # @overload $1(path, method_name, options = {})
33
+ # Defines a new route with the "$1" HTTP method.
34
+ # @param path [String] The URL path component that will trigger the route.
35
+ # @param method_name [Symbol, String] The name of the instance method in
36
+ # the handler to call for the route.
37
+ # @param options [Hash] Various options for controlling the behavior of the route.
38
+ # @return [void]
39
+ # @overload $1(path, options = {})
40
+ # Defines a new route with the "$1" HTTP method.
41
+ # @param path [String] The URL path component that will trigger the route.
42
+ # @param options [Hash] Various options for controlling the behavior of the route.
43
+ # @yield The body of the route's callback.
44
+ # @return [void]
45
+ # @since 4.0.0
46
+ def define_http_method(http_method)
47
+ define_method(http_method) do |path, method_name = nil, options = {}, &block|
48
+ register_route(http_method.to_s.upcase, path, Callback.new(method_name || block), options)
49
+ end
50
+ end
51
+ end
52
+
53
+ define_http_method :head
54
+ define_http_method :get
55
+ define_http_method :post
56
+ define_http_method :put
57
+ define_http_method :patch
58
+ define_http_method :delete
59
+ define_http_method :options
60
+ define_http_method :link
61
+ define_http_method :unlink
62
+
63
+ private
64
+
65
+ # Adds a new HTTP route for the handler.
66
+ def register_route(http_method, path, callback, options)
67
+ route = new_route(http_method, path, callback, options)
68
+ route.to(HTTPCallback.new(handler_class, callback))
69
+ handler_class.http_routes << route
70
+ end
71
+
72
+ # Creates and configures a new HTTP route.
73
+ def new_route(http_method, path, callback, options)
74
+ route = ExtendedRoute.new
75
+ route.path = path
76
+ route.name = callback.method_name
77
+ route.add_match_with(options)
78
+ route.add_request_method(http_method)
79
+ route.add_request_method("HEAD") if http_method == "GET"
80
+ route
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ require_relative "default_configuration"
6
+
7
+ module Lita
8
+ # Creates a Logger with the proper configuration.
9
+ # @api private
10
+ module Logger
11
+ class << self
12
+ # Creates a new {::Logger} outputting to standard error with the given
13
+ # severity level and a custom format.
14
+ # @param level [Symbol, String] The name of the log level to use.
15
+ # @param formatter [Proc] A proc to produce a custom log message format.
16
+ # @param io [String, IO] Where to write the logs. When this value is a +String+, logs will be
17
+ # written to the named file. When this value is an +IO+, logs will be written to the +IO+.
18
+ # @return [::Logger] The {::Logger} object.
19
+ def get_logger(level, formatter: DefaultConfiguration::DEFAULT_LOG_FORMATTER, io: $stderr)
20
+ logger = ::Logger.new(io)
21
+ logger.progname = "lita"
22
+ logger.level = get_level_constant(level)
23
+ logger.formatter = formatter if formatter
24
+ logger
25
+ end
26
+
27
+ private
28
+
29
+ # Gets the Logger constant for the given severity level.
30
+ def get_level_constant(level)
31
+ if level
32
+ begin
33
+ ::Logger.const_get(level.to_s.upcase)
34
+ rescue NameError
35
+ ::Logger::INFO
36
+ end
37
+ else
38
+ ::Logger::INFO
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end