Class: ActiveMatrix::Bot::Base
Direct Known Subclasses
Defined Under Namespace
Classes: RequestHandler
Constant Summary collapse
- CALLERS_TO_IGNORE =
[ /\/matrix_sdk\/.+\.rb$/, # all ActiveMatrix code /^\(.*\)$/, # generated code /rubygems\/(custom|core_ext\/kernel)_require\.rb$/, # rubygems require hacks /bundler(\/(?:runtime|inline))?\.rb/, # bundler require hacks /<internal:/ # internal in ruby >= 1.9.2 ].freeze
- EMPTY_BOT_FILTER =
A filter that should only result in a valid sync token and no other data
{ account_data: { types: [] }, event_fields: [], presence: { types: [] }, room: { account_data: { types: [] }, ephemeral: { types: [] }, state: { types: [], lazy_load_members: true }, timeline: { types: [] } } }.freeze
Class Attribute Summary collapse
-
.handlers ⇒ Object
readonly
Returns the value of attribute handlers.
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
-
#event ⇒ Object
readonly
Returns the value of attribute event.
- #logger ⇒ Object
Class Method Summary collapse
-
.all_handlers(type: :command) ⇒ Array[RequestHandler]
Retrieves all registered - including inherited - handlers for the bot.
-
.client(&block) ⇒ Object
Registers a block to be run when configuring the client, before starting the sync.
-
.command(command, desc: nil, notes: nil, only: nil, **params) ⇒ Object
Register a bot command.
-
.command?(command, ignore_inherited: false) ⇒ Boolean
Check if a command is registered.
-
.disable(*opts) ⇒ Object
Same as calling ‘set :option, false` for each of the given options.
-
.enable(*opts) ⇒ Object
Same as calling ‘set :option, true` for each of the given options.
-
.event(event, only: nil, **_params) ⇒ Object
Register a Matrix event.
-
.event?(event, ignore_inherited: false) ⇒ Boolean
Check if an event is registered.
-
.get_command(command, ignore_inherited: false) ⇒ RequestHandler?
Retrieves the RequestHandler for a given command.
-
.get_event(event, ignore_inherited: false) ⇒ RequestHandler?
Retrieves the RequestHandler for a given event.
- .logger ⇒ Object
-
.quit! ⇒ Object
Stops any running instance of the bot.
-
.remove_command(command) ⇒ Object
Removes a registered command from the bot.
-
.remove_event(event) ⇒ Object
Removes a registered event from the bot.
-
.reset! ⇒ Object
Reset the bot class, removing any local handlers that have been registered.
-
.run!(options = {}) ⇒ Object
Starts the bot up.
-
.running? ⇒ Boolean
Check whether the self-hosted server is running or not.
-
.set(option, value = (not_set = true), ignore_setter = false, &block) ⇒ Object
Set a class-wide option for the bot.
-
.settings ⇒ Object
Access settings defined with Base.set.
Instance Method Summary collapse
- #bot ⇒ Object
-
#command?(command, **params) ⇒ Boolean
Checks for the existence of a command.
- #command_allowed?(command, event) ⇒ Boolean
-
#event?(event, **params) ⇒ Boolean
Checks for the existence of a handled event.
- #event_allowed?(event) ⇒ Boolean
-
#expanded_prefix ⇒ Object
Helpers.
-
#get_command(command, **params) ⇒ RequestHandler
Gets the handler for a command.
-
#get_event(event, **params) ⇒ RequestHandler
Gets the handler for an event.
-
#in_event? ⇒ Boolean
Helpers for handling events.
-
#initialize(hs_url, **params) ⇒ Base
constructor
A new instance of Base.
-
#register_command(command, **params) ⇒ Object
Register a command during runtime.
-
#register_event(event, **params) ⇒ Object
Register an event during runtime.
- #room ⇒ Object
- #sender ⇒ Object
-
#sender_admin? ⇒ Boolean
Helpers for checking power levels.
- #sender_moderator? ⇒ Boolean
-
#settings ⇒ Object
Access settings defined with Base.set.
-
#unregister_command(command) ⇒ Object
Removes a registered command during runtime.
-
#unregister_event(command) ⇒ Object
Removes a registered event during runtime.
Methods included from Extensions
Methods included from Logging
Constructor Details
#initialize(hs_url, **params) ⇒ Base
Returns a new instance of Base.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/active_matrix/bot/base.rb', line 31 def initialize(hs_url, **params) @client = case hs_url when ActiveMatrix::Api ActiveMatrix::Client.new hs_url when ActiveMatrix::Client hs_url when %r{^https?://.*} ActiveMatrix::Client.new hs_url, **params else ActiveMatrix::Client.new_for_domain hs_url, **params end @client.on_event.add_handler { |ev| _handle_event(ev) } @client.on_invite_event.add_handler do |ev| break unless settings.accept_invites? logger.info "Received invite to #{ev[:room_id]}, joining." client.join_room(ev[:room_id]) end @event = nil logger.warn 'The bot abstraction is not fully finalized and can be expected to change.' end |
Class Attribute Details
.handlers ⇒ Object (readonly)
Returns the value of attribute handlers.
143 144 145 |
# File 'lib/active_matrix/bot/base.rb', line 143 def handlers @handlers end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
26 27 28 |
# File 'lib/active_matrix/bot/base.rb', line 26 def client @client end |
#event ⇒ Object (readonly)
Returns the value of attribute event.
26 27 28 |
# File 'lib/active_matrix/bot/base.rb', line 26 def event @event end |
#logger ⇒ Object
56 57 58 59 60 |
# File 'lib/active_matrix/bot/base.rb', line 56 def logger return @logger if instance_variable_defined?(:@logger) && @logger self.class.logger end |
Class Method Details
.all_handlers(type: :command) ⇒ Array[RequestHandler]
Retrieves all registered - including inherited - handlers for the bot
181 182 183 184 |
# File 'lib/active_matrix/bot/base.rb', line 181 def all_handlers(type: :command) parent = superclass&.all_handlers(type: type) if superclass.respond_to? :all_handlers (parent || {}).merge(@handlers.select { |_, h| type == :all || h.type == type }).compact end |
.client(&block) ⇒ Object
Registers a block to be run when configuring the client, before starting the sync
301 302 303 |
# File 'lib/active_matrix/bot/base.rb', line 301 def client(&block) @client_handler = block end |
.command(command, desc: nil, notes: nil, only: nil, **params) ⇒ Object
Due to the way blocks are handled, required parameters won’t block execution. If your command requires all parameters to be valid, you will need to check for nil yourself.
Execution will be performed with a ActiveMatrix::Bot::Request object as self. To access the bot instance, use ActiveMatrix::Bot::Request#bot
Register a bot command
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/active_matrix/bot/base.rb', line 257 def command(command, desc: nil, notes: nil, only: nil, **params, &) args = params[:args] || convert_to_lambda(&).parameters.map do |type, name| case type when :req name.to_s.upcase when :opt "[#{name.to_s.upcase}]" when :rest "[#{name.to_s.upcase}...]" end end.compact.join(' ') logger.debug "Registering command #{command} with args #{args}" add_handler( command.to_s.downcase, type: :command, args: args, desc: desc, notes: notes, only: [only].flatten.compact, & ) end |
.command?(command, ignore_inherited: false) ⇒ Boolean
Check if a command is registered
309 310 311 312 313 |
# File 'lib/active_matrix/bot/base.rb', line 309 def command?(command, ignore_inherited: false) return @handlers[command.to_s.downcase]&.command? if ignore_inherited all_handlers[command.to_s.downcase]&.command? || false end |
.disable(*opts) ⇒ Object
Same as calling ‘set :option, false` for each of the given options.
240 241 242 |
# File 'lib/active_matrix/bot/base.rb', line 240 def disable(*opts) opts.each { |key| set(key, false) } end |
.enable(*opts) ⇒ Object
Same as calling ‘set :option, true` for each of the given options.
233 234 235 |
# File 'lib/active_matrix/bot/base.rb', line 233 def enable(*opts) opts.each { |key| set(key, true) } end |
.event(event, only: nil, **_params) ⇒ Object
Currently it’s only possible to register one handler per event type
Register a Matrix event
289 290 291 292 293 294 295 296 297 298 |
# File 'lib/active_matrix/bot/base.rb', line 289 def event(event, only: nil, **_params, &) logger.debug "Registering event #{event}" add_handler( event.to_s, type: :event, only: [only].flatten.compact, & ) end |
.event?(event, ignore_inherited: false) ⇒ Boolean
Check if an event is registered
319 320 321 322 323 |
# File 'lib/active_matrix/bot/base.rb', line 319 def event?(event, ignore_inherited: false) return @handlers[event]&.event? if ignore_inherited all_handlers(type: :event)[event]&.event? || false end |
.get_command(command, ignore_inherited: false) ⇒ RequestHandler?
Retrieves the RequestHandler for a given command
330 331 332 333 334 335 336 |
# File 'lib/active_matrix/bot/base.rb', line 330 def get_command(command, ignore_inherited: false) if ignore_inherited && @handlers[command]&.command? @handlers[command] elsif !ignore_inherited && all_handlers[command]&.command? all_handlers[command] end end |
.get_event(event, ignore_inherited: false) ⇒ RequestHandler?
Retrieves the RequestHandler for a given event
343 344 345 346 347 348 349 |
# File 'lib/active_matrix/bot/base.rb', line 343 def get_event(event, ignore_inherited: false) if ignore_inherited && @handlers[event]&.event? @handlers[event] elsif !ignore_inherited && all_handlers(type: :event)[event]&.event? all_handlers(type: :event)[event] end end |
.logger ⇒ Object
62 63 64 |
# File 'lib/active_matrix/bot/base.rb', line 62 def self.logger @logger ||= ActiveMatrix.logger end |
.quit! ⇒ Object
Stops any running instance of the bot
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
# File 'lib/active_matrix/bot/base.rb', line 374 def quit! return unless running? active_bot.logger.info "Stopping #{settings.bot_name}..." if settings.store_sync_token begin active_bot.client.api.set_account_data( active_bot.client.mxid, "dev.ananace.ruby-sdk.#{settings.bot_name}", { sync_token: active_bot.client.sync_token } ) rescue StandardError => e active_bot.logger.error "Failed to save sync token, #{e.class}: #{e}" end end active_bot.client.logout if login? active_bot.client.api.stop_inflight active_bot.client.stop_listener_thread set :active_bot, nil end |
.remove_command(command) ⇒ Object
This will only affect local commands, not ones inherited
Removes a registered command from the bot
355 356 357 358 359 360 |
# File 'lib/active_matrix/bot/base.rb', line 355 def remove_command(command) return false unless @handlers[command]&.command? @handers.delete command true end |
.remove_event(event) ⇒ Object
This will only affect local event, not ones inherited
Removes a registered event from the bot
366 367 368 369 370 371 |
# File 'lib/active_matrix/bot/base.rb', line 366 def remove_event(event) return false unless @handlers[event]&.event? @handers.delete event true end |
.reset! ⇒ Object
Reset the bot class, removing any local handlers that have been registered
172 173 174 175 |
# File 'lib/active_matrix/bot/base.rb', line 172 def reset! @handlers = {} @client_handler = nil end |
.run!(options = {}) ⇒ Object
Starts the bot up
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'lib/active_matrix/bot/base.rb', line 401 def run!( = {}, &) return if running? set bot_settings = settings.respond_to?(:bot_settings) ? settings.bot_settings : {} bot_settings.merge!( threadsafe: settings.threadsafe, client_cache: settings.client_cache, sync_filter: settings.sync_filter ) bot_settings[:auth] = if settings.access_token? { access_token: settings.access_token } else { username: settings.username, password: settings.password } end begin start_bot(bot_settings, &) ensure quit! end end |
.running? ⇒ Boolean
Check whether the self-hosted server is running or not.
427 428 429 |
# File 'lib/active_matrix/bot/base.rb', line 427 def running? active_bot? end |
.set(option, value = (not_set = true), ignore_setter = false, &block) ⇒ Object
Set a class-wide option for the bot
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/active_matrix/bot/base.rb', line 192 def set(option, value = (not_set = true), ignore_setter = false, &block) # rubocop:disable Style/OptionalBooleanParameter raise ArgumentError if block && !not_set if block value = block not_set = false end if not_set raise ArgumentError unless option.respond_to?(:each) option.each { |k, v| set(k, v) } return self end return send("#{option}=", value) if respond_to?("#{option}=") && !ignore_setter setter = proc { |val| set option, val, true } getter = proc { value } case value when Proc getter = value when Symbol, Integer, FalseClass, TrueClass, NilClass getter = value.inspect when Hash setter = proc do |val| val = value.merge val if val.is_a? Hash set option, val, true end end define_singleton("#{option}=", setter) define_singleton(option, getter) define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?" self end |
.settings ⇒ Object
Access settings defined with Base.set
138 139 140 |
# File 'lib/active_matrix/bot/base.rb', line 138 def self.settings self end |
Instance Method Details
#bot ⇒ Object
595 596 597 |
# File 'lib/active_matrix/bot/base.rb', line 595 def bot self end |
#command?(command, **params) ⇒ Boolean
Checks for the existence of a command
120 121 122 |
# File 'lib/active_matrix/bot/base.rb', line 120 def command?(command, **params) self.class.command?(command, **params) end |
#command_allowed?(command, event) ⇒ Boolean
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
# File 'lib/active_matrix/bot/base.rb', line 527 def command_allowed?(command, event) pre_event = @event return false unless command? command handler = get_command(command) return true if (handler.data[:only] || []).empty? # Avoid modifying input data for a checking method @event = ActiveMatrix::Response.new(client.api, event.dup) return false if [handler.data[:only]].flatten.compact.any? do |only| if only.is_a? Proc !instance_exec(&only) else case only.to_s.downcase.to_sym when :dm !room.dm?(members_only: true) when :admin !sender_admin? when :mod !sender_moderator? end end end true ensure @event = pre_event end |
#event?(event, **params) ⇒ Boolean
Checks for the existence of a handled event
128 129 130 |
# File 'lib/active_matrix/bot/base.rb', line 128 def event?(event, **params) self.class.event?(event, **params) end |
#event_allowed?(event) ⇒ Boolean
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 |
# File 'lib/active_matrix/bot/base.rb', line 557 def event_allowed?(event) pre_event = @event return false unless event? event[:type] handler = get_event(event[:type]) return true if (handler.data[:only] || []).empty? # Avoid modifying input data for a checking method @event = ActiveMatrix::Response.new(client.api, event.dup) return false if [handler.data[:only]].flatten.compact.any? do |only| if only.is_a? Proc instance_exec(&only) else case only.to_s.downcase.to_sym when :dm !room.dm?(members_only: true) when :admin !sender_admin? when :mod !sender_moderator? end end end true ensure @event = pre_event end |
#expanded_prefix ⇒ Object
Helpers
620 621 622 623 624 |
# File 'lib/active_matrix/bot/base.rb', line 620 def return "#{settings.command_prefix}#{settings.bot_name} " if settings.bot_name? settings.command_prefix end |
#get_command(command, **params) ⇒ RequestHandler
Gets the handler for a command
103 104 105 |
# File 'lib/active_matrix/bot/base.rb', line 103 def get_command(command, **params) self.class.get_command(command, **params) end |
#get_event(event, **params) ⇒ RequestHandler
Gets the handler for an event
112 113 114 |
# File 'lib/active_matrix/bot/base.rb', line 112 def get_event(event, **params) self.class.get_event(event, **params) end |
#in_event? ⇒ Boolean
Helpers for handling events
591 592 593 |
# File 'lib/active_matrix/bot/base.rb', line 591 def in_event? !@event.nil? end |
#register_command(command, **params) ⇒ Object
Register a command during runtime
70 71 72 |
# File 'lib/active_matrix/bot/base.rb', line 70 def register_command(command, **params, &) self.class.command(command, **params, &) end |
#register_event(event, **params) ⇒ Object
Register an event during runtime
78 79 80 |
# File 'lib/active_matrix/bot/base.rb', line 78 def register_event(event, **params, &) self.class.event(event, **params, &) end |
#room ⇒ Object
599 600 601 |
# File 'lib/active_matrix/bot/base.rb', line 599 def room client.ensure_room(event[:room_id]) if in_event? end |
#sender ⇒ Object
603 604 605 |
# File 'lib/active_matrix/bot/base.rb', line 603 def sender client.get_user(event[:sender]) if in_event? end |
#sender_admin? ⇒ Boolean
Helpers for checking power levels
608 609 610 |
# File 'lib/active_matrix/bot/base.rb', line 608 def sender_admin? sender&.admin? room end |
#sender_moderator? ⇒ Boolean
612 613 614 |
# File 'lib/active_matrix/bot/base.rb', line 612 def sender_moderator? sender&.moderator? room end |
#settings ⇒ Object
Access settings defined with Base.set
133 134 135 |
# File 'lib/active_matrix/bot/base.rb', line 133 def settings self.class.settings end |
#unregister_command(command) ⇒ Object
Removes a registered command during runtime
86 87 88 |
# File 'lib/active_matrix/bot/base.rb', line 86 def unregister_command(command) self.class.remove_command(command) end |
#unregister_event(command) ⇒ Object
Removes a registered event during runtime
94 95 96 |
# File 'lib/active_matrix/bot/base.rb', line 94 def unregister_event(command) self.class.remove_event(command) end |