Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Matrix Ruby SDK
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Alexander Olofsson
Matrix Ruby SDK
Commits
f3cb20e4
Verified
Commit
f3cb20e4
authored
2 years ago
by
Alexander Olofsson
Browse files
Options
Downloads
Patches
Plain Diff
bot: Add support for handling arbitrary events
parent
b165170c
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
lib/matrix_sdk/bot/base.rb
+151
-18
151 additions, 18 deletions
lib/matrix_sdk/bot/base.rb
test/bot_test.rb
+29
-0
29 additions, 0 deletions
test/bot_test.rb
with
180 additions
and
18 deletions
lib/matrix_sdk/bot/base.rb
+
151
−
18
View file @
f3cb20e4
# frozen_string_literal: true
# frozen_string_literal: true
require
'matrix_sdk/bot/request'
require
'shellwords'
require
'shellwords'
module
MatrixSdk::Bot
module
MatrixSdk::Bot
class
Base
class
Base
extend
MatrixSdk
::
Extensions
extend
MatrixSdk
::
Extensions
RequestHandler
=
Struct
.
new
(
'RequestHandler'
,
:command
,
:proc
,
:data
)
do
RequestHandler
=
Struct
.
new
(
'RequestHandler'
,
:command
,
:type
,
:proc
,
:data
)
do
def
command?
type
==
:command
end
def
event?
type
==
:event
end
def
arity
def
arity
arity
=
self
.
proc
.
parameters
.
count
{
|
t
,
_
|
%i[opt req]
.
include?
t
}
arity
=
self
.
proc
.
parameters
.
count
{
|
t
,
_
|
%i[opt req]
.
include?
t
}
arity
=
-
arity
if
self
.
proc
.
parameters
.
any?
{
|
t
,
_
|
t
.
to_s
.
include?
'rest'
}
arity
=
-
arity
if
self
.
proc
.
parameters
.
any?
{
|
t
,
_
|
t
.
to_s
.
include?
'rest'
}
...
@@ -32,7 +39,7 @@ module MatrixSdk::Bot
...
@@ -32,7 +39,7 @@ module MatrixSdk::Bot
MatrixSdk
::
Client
.
new_for_domain
hs_url
,
**
params
MatrixSdk
::
Client
.
new_for_domain
hs_url
,
**
params
end
end
@client
.
on_event
.
add_handler
(
'm.room.message'
)
{
|
ev
|
_handle_event
(
ev
)
}
@client
.
on_event
.
add_handler
{
|
ev
|
_handle_event
(
ev
)
}
@client
.
on_invite_event
.
add_handler
{
|
ev
|
client
.
join_room
(
ev
[
:room_id
])
if
settings
.
accept_invites?
}
@client
.
on_invite_event
.
add_handler
{
|
ev
|
client
.
join_room
(
ev
[
:room_id
])
if
settings
.
accept_invites?
}
end
end
...
@@ -59,6 +66,14 @@ module MatrixSdk::Bot
...
@@ -59,6 +66,14 @@ module MatrixSdk::Bot
self
.
class
.
command
(
command
,
**
params
,
&
block
)
self
.
class
.
command
(
command
,
**
params
,
&
block
)
end
end
# Register an event during runtime
#
# @param event [String] The event to register
# @see Base.event for full parameter information
def
register_event
(
event
,
**
params
,
&
block
)
self
.
class
.
event
(
event
,
**
params
,
&
block
)
end
# Removes a registered command during runtime
# Removes a registered command during runtime
#
#
# @param command [String] The command to remove
# @param command [String] The command to remove
...
@@ -67,6 +82,14 @@ module MatrixSdk::Bot
...
@@ -67,6 +82,14 @@ module MatrixSdk::Bot
self
.
class
.
remove_command
(
command
)
self
.
class
.
remove_command
(
command
)
end
end
# Removes a registered event during runtime
#
# @param event [String] The event to remove
# @see Base.remove_event
def
unregister_event
(
command
)
self
.
class
.
remove_event
(
command
)
end
# Gets the handler for a command
# Gets the handler for a command
#
#
# @param command [String] The command to retrieve
# @param command [String] The command to retrieve
...
@@ -76,6 +99,15 @@ module MatrixSdk::Bot
...
@@ -76,6 +99,15 @@ module MatrixSdk::Bot
self
.
class
.
get_command
(
command
,
**
params
)
self
.
class
.
get_command
(
command
,
**
params
)
end
end
# Gets the handler for an event
#
# @param event [String] The event to retrieve
# @return [RequestHandler] The registered event handler
# @see Base.get_event
def
get_event
(
event
,
**
params
)
self
.
class
.
get_event
(
event
,
**
params
)
end
# Checks for the existence of a command
# Checks for the existence of a command
#
#
# @param command [String] The command to check
# @param command [String] The command to check
...
@@ -84,6 +116,14 @@ module MatrixSdk::Bot
...
@@ -84,6 +116,14 @@ module MatrixSdk::Bot
self
.
class
.
command?
(
command
,
**
params
)
self
.
class
.
command?
(
command
,
**
params
)
end
end
# Checks for the existence of a handled event
#
# @param event [String] The event to check
# @see Base.event?
def
event?
(
event
,
**
params
)
self
.
class
.
event?
(
event
,
**
params
)
end
# Access settings defined with Base.set
# Access settings defined with Base.set
def
settings
def
settings
self
.
class
.
settings
self
.
class
.
settings
...
@@ -128,9 +168,9 @@ module MatrixSdk::Bot
...
@@ -128,9 +168,9 @@ module MatrixSdk::Bot
@client_handler
=
nil
@client_handler
=
nil
end
end
def
all_handlers
def
all_handlers
(
type: :command
)
parent
=
superclass
&
.
all_handlers
if
superclass
.
respond_to?
:all_handlers
parent
=
superclass
&
.
all_handlers
(
type:
type
)
if
superclass
.
respond_to?
:all_handlers
(
parent
||
{}).
merge
(
@handlers
).
compact
(
parent
||
{}).
merge
(
@handlers
.
select
{
|
_
,
h
|
h
.
type
==
type
}
).
compact
end
end
def
set
(
option
,
value
=
(
not_set
=
true
),
ignore_setter
=
false
,
&
block
)
# rubocop:disable Style/OptionalBooleanParameter
def
set
(
option
,
value
=
(
not_set
=
true
),
ignore_setter
=
false
,
&
block
)
# rubocop:disable Style/OptionalBooleanParameter
...
@@ -181,10 +221,6 @@ module MatrixSdk::Bot
...
@@ -181,10 +221,6 @@ module MatrixSdk::Bot
opts
.
each
{
|
key
|
set
(
key
,
false
)
}
opts
.
each
{
|
key
|
set
(
key
,
false
)
}
end
end
def
add_handler
(
command
,
**
data
,
&
block
)
@handlers
[
command
]
=
RequestHandler
.
new
command
.
to_s
.
downcase
,
block
,
data
.
compact
end
# Register a bot command
# Register a bot command
#
#
# @note Due to the way blocks are handled, required parameters won't block execution.
# @note Due to the way blocks are handled, required parameters won't block execution.
...
@@ -214,6 +250,7 @@ module MatrixSdk::Bot
...
@@ -214,6 +250,7 @@ module MatrixSdk::Bot
add_handler
(
add_handler
(
command
.
to_s
.
downcase
,
command
.
to_s
.
downcase
,
type: :command
,
args:
args
,
args:
args
,
desc:
desc
,
desc:
desc
,
notes:
notes
,
notes:
notes
,
...
@@ -222,33 +259,70 @@ module MatrixSdk::Bot
...
@@ -222,33 +259,70 @@ module MatrixSdk::Bot
)
)
end
end
def
event
(
event
,
only:
nil
,
**
_params
,
&
block
)
logger
.
debug
"Registering event
#{
event
}
"
add_handler
(
event
.
to_s
,
type: :event
,
only:
[
only
].
flatten
.
compact
,
&
block
)
end
# Registers a block to be run when configuring the client, before starting the sync
def
client
(
&
block
)
@client_handler
=
block
end
def
command?
(
command
,
ignore_inherited:
false
)
def
command?
(
command
,
ignore_inherited:
false
)
return
@handlers
.
key?
command
if
ignore_inherited
return
@handlers
[
command
]
&
.
command
?
if
ignore_inherited
all_handlers
.
key?
command
all_handlers
[
command
]
&
.
command?
||
false
end
def
event?
(
event
,
ignore_inherited:
false
)
return
@handlers
[
event
]
&
.
event?
if
ignore_inherited
all_handlers
(
type: :event
)[
event
]
&
.
event?
||
false
end
end
def
get_command
(
command
,
ignore_inherited:
false
)
def
get_command
(
command
,
ignore_inherited:
false
)
if
ignore_inherited
if
ignore_inherited
&&
@handlers
[
command
]
&
.
command?
@handlers
[
command
]
@handlers
[
command
]
els
e
els
if
!
ignore_inherited
&&
all_handlers
[
command
]
&
.
command?
all_handlers
[
command
]
all_handlers
[
command
]
end
end
end
end
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
# Removes a registered command from the bot
# Removes a registered command from the bot
#
#
# @note This will only affect local commands, not ones inherited
# @note This will only affect local commands, not ones inherited
# @param command [String] The command to remove
# @param command [String] The command to remove
def
remove_command
(
command
)
def
remove_command
(
command
)
return
false
unless
@handlers
.
key?
command
return
false
unless
@handlers
[
command
]
&
.
command
?
@handers
.
delete
command
@handers
.
delete
command
true
true
end
end
def
client
(
&
block
)
# Removes a registered event from the bot
@client_handler
=
block
#
# @note This will only affect local event, not ones inherited
# @param event [String] The event to remove
def
remove_event
(
event
)
return
false
unless
@handlers
[
event
]
&
.
event?
@handers
.
delete
event
true
end
end
# Stops any running instance of the bot
# Stops any running instance of the bot
...
@@ -311,6 +385,10 @@ module MatrixSdk::Bot
...
@@ -311,6 +385,10 @@ module MatrixSdk::Bot
private
private
def
add_handler
(
command
,
type
:,
**
data
,
&
block
)
@handlers
[
command
]
=
RequestHandler
.
new
command
.
to_s
.
downcase
,
type
,
block
,
data
.
compact
end
def
start_bot
(
bot_settings
,
&
block
)
def
start_bot
(
bot_settings
,
&
block
)
cl
=
if
homeserver
=~
%r{^https?://}
cl
=
if
homeserver
=~
%r{^https?://}
MatrixSdk
::
Client
.
new
homeserver
MatrixSdk
::
Client
.
new
homeserver
...
@@ -331,8 +409,8 @@ module MatrixSdk::Bot
...
@@ -331,8 +409,8 @@ module MatrixSdk::Bot
set
:active_bot
,
bot
set
:active_bot
,
bot
block
&
.
call
bot
@client_handler
&
.
call
bot
.
client
@client_handler
&
.
call
bot
.
client
block
&
.
call
bot
if
settings
.
sync_token?
if
settings
.
sync_token?
bot
.
client
.
instance_variable_set
(
:@next_batch
,
settings
.
sync_token
)
bot
.
client
.
instance_variable_set
(
:@next_batch
,
settings
.
sync_token
)
...
@@ -424,6 +502,36 @@ module MatrixSdk::Bot
...
@@ -424,6 +502,36 @@ module MatrixSdk::Bot
@event
=
pre_event
@event
=
pre_event
end
end
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
=
MatrixSdk
::
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
#
#
# Helpers for handling events
# Helpers for handling events
#
#
...
@@ -475,6 +583,31 @@ module MatrixSdk::Bot
...
@@ -475,6 +583,31 @@ module MatrixSdk::Bot
return
if
settings
.
ignore_own?
&&
client
.
mxid
==
event
[
:sender
]
return
if
settings
.
ignore_own?
&&
client
.
mxid
==
event
[
:sender
]
logger
.
debug
"Received event
#{
event
}
"
logger
.
debug
"Received event
#{
event
}
"
return
_handle_message
(
event
)
if
event
[
:type
]
==
'm.room.message'
return
unless
event?
(
event
[
:type
])
handler
=
get_event
(
event
[
:type
])
return
unless
event_allowed?
event
@event
=
MatrixSdk
::
Response
.
new
(
client
.
api
,
event
)
logger
.
debug
"Handling command
#{
handler
.
command
}
"
instance_exec
(
&
handler
.
proc
)
# Argument errors are likely to be a "friendly" error, so don't direct the user to the log
rescue
ArgumentError
=>
e
logger
.
error
"
#{
e
.
class
}
when handling
#{
event
[
:type
]
}
:
#{
e
}
\n
#{
e
.
backtrace
[
0
,
10
].
join
(
"
\n
"
)
}
"
room
.
send_notice
(
"Failed to handle event of type
#{
event
[
:type
]
}
-
#{
e
}
."
)
rescue
StandardError
=>
e
puts
e
,
e
.
backtrace
if
settings
.
respond_to?
(
:testing?
)
&&
settings
.
testing?
logger
.
error
"
#{
e
.
class
}
when handling
#{
event
[
:type
]
}
:
#{
e
}
\n
#{
e
.
backtrace
[
0
,
10
].
join
(
"
\n
"
)
}
"
room
.
send_notice
(
"Failed to handle event of type
#{
event
[
:type
]
}
-
#{
e
}
.
\n
More information is available in the bot logs"
)
ensure
@event
=
nil
end
def
_handle_message
(
event
)
return
if
in_event?
return
if
settings
.
ignore_own?
&&
client
.
mxid
==
event
[
:sender
]
type
=
event
[
:content
][
:msgtype
]
type
=
event
[
:content
][
:msgtype
]
return
unless
settings
.
allowed_types
.
include?
type
return
unless
settings
.
allowed_types
.
include?
type
...
...
This diff is collapsed.
Click to expand it.
test/bot_test.rb
+
29
−
0
View file @
f3cb20e4
...
@@ -21,6 +21,10 @@ class BotTest < Test::Unit::TestCase
...
@@ -21,6 +21,10 @@ class BotTest < Test::Unit::TestCase
command
:test_event
do
command
:test_event
do
bot
.
send
:test_event
,
event
.
event_id
bot
.
send
:test_event
,
event
.
event_id
end
end
event
'dev.ananace.ruby-sdk.TestEvent'
do
bot
.
send
:test_state_event
end
end
end
def
setup
def
setup
...
@@ -76,6 +80,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -76,6 +80,7 @@ class BotTest < Test::Unit::TestCase
@room
.
stubs
(
:dm?
).
returns
(
false
)
@room
.
stubs
(
:dm?
).
returns
(
false
)
ev
=
{
ev
=
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -88,6 +93,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -88,6 +93,7 @@ class BotTest < Test::Unit::TestCase
@bot
.
send
:_handle_event
,
ev
@bot
.
send
:_handle_event
,
ev
ev
=
{
ev
=
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -103,6 +109,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -103,6 +109,7 @@ class BotTest < Test::Unit::TestCase
@bot
.
expects
(
:test_arr_executed
).
never
@bot
.
expects
(
:test_arr_executed
).
never
ev
=
{
ev
=
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -118,6 +125,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -118,6 +125,7 @@ class BotTest < Test::Unit::TestCase
@bot
.
expects
(
:test_arr_executed
).
once
@bot
.
expects
(
:test_arr_executed
).
once
ev
=
{
ev
=
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -130,6 +138,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -130,6 +138,7 @@ class BotTest < Test::Unit::TestCase
@bot
.
send
:_handle_event
,
ev
@bot
.
send
:_handle_event
,
ev
ev
=
{
ev
=
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -155,6 +164,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -155,6 +164,7 @@ class BotTest < Test::Unit::TestCase
@bot
.
expects
(
:test_executed
).
never
@bot
.
expects
(
:test_executed
).
never
ev
=
{
ev
=
{
type:
'm.room.message'
,
sender:
'@alice:example.com'
,
sender:
'@alice:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -176,6 +186,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -176,6 +186,7 @@ class BotTest < Test::Unit::TestCase
@bot
.
expects
(
:test_event
).
with
(
'$someevent'
).
once
@bot
.
expects
(
:test_event
).
with
(
'$someevent'
).
once
ev
=
{
ev
=
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
event_id:
'$someevent'
,
event_id:
'$someevent'
,
...
@@ -187,6 +198,20 @@ class BotTest < Test::Unit::TestCase
...
@@ -187,6 +198,20 @@ class BotTest < Test::Unit::TestCase
assert
@bot
.
command_allowed?
'test_event'
,
ev
assert
@bot
.
command_allowed?
'test_event'
,
ev
@bot
.
send
:_handle_event
,
ev
@bot
.
send
:_handle_event
,
ev
@bot
.
expects
(
:test_state_event
).
once
ev
=
{
type:
'dev.ananace.ruby-sdk.TestEvent'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
content:
{
hello:
'world'
}
}
assert
@bot
.
event_allowed?
ev
@bot
.
send
:_handle_event
,
ev
end
end
def
test_builtin_help
def
test_builtin_help
...
@@ -202,6 +227,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -202,6 +227,7 @@ class BotTest < Test::Unit::TestCase
MSG
MSG
@bot
.
send
:_handle_event
,
{
@bot
.
send
:_handle_event
,
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -218,6 +244,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -218,6 +244,7 @@ class BotTest < Test::Unit::TestCase
MSG
MSG
@bot
.
send
:_handle_event
,
{
@bot
.
send
:_handle_event
,
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -239,6 +266,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -239,6 +266,7 @@ class BotTest < Test::Unit::TestCase
MSG
MSG
@bot
.
send
:_handle_event
,
{
@bot
.
send
:_handle_event
,
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
@@ -255,6 +283,7 @@ class BotTest < Test::Unit::TestCase
...
@@ -255,6 +283,7 @@ class BotTest < Test::Unit::TestCase
MSG
MSG
@bot
.
send
:_handle_event
,
{
@bot
.
send
:_handle_event
,
{
type:
'm.room.message'
,
sender:
'@bob:example.com'
,
sender:
'@bob:example.com'
,
room_id:
@id
,
room_id:
@id
,
content:
{
content:
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment