Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
maubot-exec-cmd
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
isgphys
maubot-exec-cmd
Commits
c734fbc5
Commit
c734fbc5
authored
5 years ago
by
Tulir Asokan
Browse files
Options
Downloads
Patches
Plain Diff
Make stuff work
parent
9260e829
No related branches found
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
base-config.yaml
+47
-3
47 additions, 3 deletions
base-config.yaml
exec/bot.py
+59
-8
59 additions, 8 deletions
exec/bot.py
exec/runner/python.py
+1
-0
1 addition, 0 deletions
exec/runner/python.py
with
107 additions
and
11 deletions
base-config.yaml
+
47
−
3
View file @
c734fbc5
# The message prefix to treat as exec commands
prefix
:
!exec
prefix
:
'
!exec
'
# Whether or not to enable "userbot" mode, where commands that the bot's user
# sends are handled and responded to with edits instead of replies.
# This is intended to be used when you run the plugin on your own account.
...
...
@@ -8,5 +8,49 @@ userbot: false
# sandboxing in maubot or this plugin, keep this list small.
whitelist
:
-
'
@user:example.com'
# Number of seconds to wait between output update edits.
output_interval
:
5
output
:
# Number of seconds to wait between output update edits.
interval
:
5
# Arguments for the Jinja2 template initialization.
template_args
:
lstrip_blocks
:
true
trim_blocks
:
yes
# Plaintext output template.
plaintext
:
|
Input ({{ input }}):
{{ code }}
{% if output %}
Output:
{{ output }}
{% endif %}
{% if return_value %}
Return:
{{ return_value }}
{% endif %}
{% if duration %}
Took {{ duration | round(3) }} seconds
{% else %}
Running...
{% endif %}
# HTML output template.
html
:
|
<h4>Input</h4>
<pre><code class="language-{{ language }}">{{ code }}</code></pre>
{% if output %}
<h4>Output</h4>
<pre>{{ output }}</pre>
{% endif %}
{% if return_value %}
<h4>Return</h4>
<pre>{{ return_value }}</pre>
{% endif %}
{% if duration %}
<h4>Took {{ duration | round(3) }} seconds</h4>
{% else %}
<h4>Running...</h4>
{% endif %}
This diff is collapsed.
Click to expand it.
exec/bot.py
+
59
−
8
View file @
c734fbc5
...
...
@@ -16,8 +16,11 @@
from
typing
import
Type
,
Set
,
Optional
,
Any
from
io
import
StringIO
from
time
import
time
from
html
import
escape
from
mautrix.types
import
EventType
,
UserID
from
jinja2
import
Template
from
mautrix.types
import
EventType
,
UserID
,
TextMessageEventContent
,
MessageType
,
Format
from
mautrix.util.config
import
BaseProxyConfig
,
ConfigUpdateHelper
from
mautrix.util.formatter
import
MatrixParser
,
EntityString
,
SimpleEntity
,
EntityType
from
maubot
import
Plugin
,
MessageEvent
...
...
@@ -35,7 +38,10 @@ class Config(BaseProxyConfig):
helper
.
copy
(
"
prefix
"
)
helper
.
copy
(
"
userbot
"
)
helper
.
copy
(
"
whitelist
"
)
helper
.
copy
(
"
output_interval
"
)
helper
.
copy
(
"
output.interval
"
)
helper
.
copy
(
"
output.template_args
"
)
helper
.
copy
(
"
output.plaintext
"
)
helper
.
copy
(
"
output.html
"
)
class
ExecBot
(
Plugin
):
...
...
@@ -43,6 +49,8 @@ class ExecBot(Plugin):
userbot
:
bool
prefix
:
str
output_interval
:
int
plaintext_template
:
Template
html_template
:
Template
@classmethod
def
get_config_class
(
cls
)
->
Type
[
BaseProxyConfig
]:
...
...
@@ -56,7 +64,24 @@ class ExecBot(Plugin):
self
.
whitelist
=
set
(
self
.
config
[
"
whitelist
"
])
self
.
userbot
=
self
.
config
[
"
userbot
"
]
self
.
prefix
=
self
.
config
[
"
prefix
"
]
self
.
output_interval
=
self
.
config
[
"
output_interval
"
]
self
.
output_interval
=
self
.
config
[
"
output.interval
"
]
template_args
=
self
.
config
[
"
output.template_args
"
]
self
.
plaintext_template
=
Template
(
self
.
config
[
"
output.plaintext
"
],
**
template_args
)
self
.
html_template
=
Template
(
self
.
config
[
"
output.html
"
],
**
template_args
)
def
format_status
(
self
,
code
:
str
,
language
:
str
,
output
:
str
=
""
,
output_html
:
str
=
""
,
return_value
:
Any
=
None
,
duration
:
Optional
[
float
]
=
None
,
msgtype
:
MessageType
=
MessageType
.
NOTICE
)
->
TextMessageEventContent
:
return_value
=
repr
(
return_value
)
if
return_value
else
''
content
=
TextMessageEventContent
(
msgtype
=
msgtype
,
format
=
Format
.
HTML
,
body
=
self
.
plaintext_template
.
render
(
code
=
code
,
language
=
language
,
output
=
output
,
return_value
=
return_value
,
duration
=
duration
),
formatted_body
=
self
.
html_template
.
render
(
code
=
escape
(
code
),
language
=
language
,
output
=
output_html
,
return_value
=
escape
(
return_value
),
duration
=
duration
))
return
content
@event.on
(
EventType
.
ROOM_MESSAGE
)
async
def
exec
(
self
,
evt
:
MessageEvent
)
->
None
:
...
...
@@ -76,7 +101,7 @@ class ExecBot(Plugin):
if
entity
.
type
!=
EntityType
.
PREFORMATTED
:
continue
current_lang
=
entity
.
extra_info
[
"
language
"
].
lower
()
value
=
command
.
text
[
entity
.
offset
:
entity
.
offset
+
entity
.
length
]
value
=
command
.
text
[
entity
.
offset
:
entity
.
offset
+
entity
.
length
]
if
not
code
:
code
=
value
lang
=
current_lang
...
...
@@ -89,16 +114,42 @@ class ExecBot(Plugin):
await
evt
.
respond
(
"
Only python is currently supported
"
)
return
if
self
.
userbot
:
msgtype
=
MessageType
.
TEXT
content
=
self
.
format_status
(
code
,
lang
,
msgtype
=
msgtype
)
await
evt
.
edit
(
content
)
output_event_id
=
evt
.
event_id
else
:
msgtype
=
MessageType
.
NOTICE
content
=
self
.
format_status
(
code
,
lang
,
msgtype
=
msgtype
)
output_event_id
=
await
evt
.
respond
(
content
)
runner
=
PythonRunner
()
stdo
ut
=
StringIO
()
stderr
=
StringIO
()
outp
ut
=
StringIO
()
output_html
=
StringIO
()
return_value
:
Any
=
None
start_time
=
time
()
prev_output
=
start_time
async
for
out_type
,
data
in
runner
.
run
(
code
,
stdin
):
if
out_type
==
OutputType
.
STDOUT
:
stdout
.
write
(
data
)
output
.
write
(
data
)
output_html
.
write
(
escape
(
data
))
elif
out_type
==
OutputType
.
STDERR
:
stderr
.
write
(
data
)
output
.
write
(
data
)
output_html
.
write
(
f
'
<font color=
"
red
"
data-mx-color=
"
red
"
>
{
escape
(
data
)
}
</font>
'
)
elif
out_type
==
OutputType
.
RETURN
:
return_value
=
data
continue
cur_time
=
time
()
if
prev_output
+
self
.
output_interval
<
cur_time
:
content
=
self
.
format_status
(
code
,
lang
,
output
.
getvalue
(),
output_html
.
getvalue
(),
msgtype
=
msgtype
)
content
.
set_edit
(
output_event_id
)
await
self
.
client
.
send_message
(
evt
.
room_id
,
content
)
prev_output
=
cur_time
duration
=
time
()
-
start_time
content
=
self
.
format_status
(
code
,
lang
,
output
.
getvalue
(),
output_html
.
getvalue
(),
return_value
,
duration
,
msgtype
=
msgtype
)
content
.
set_edit
(
output_event_id
)
await
self
.
client
.
send_message
(
evt
.
room_id
,
content
)
This diff is collapsed.
Click to expand it.
exec/runner/python.py
+
1
−
0
View file @
c734fbc5
...
...
@@ -37,6 +37,7 @@ class AsyncTextOutput:
self
.
read_task
=
None
self
.
queue
=
asyncio
.
Queue
(
loop
=
self
.
loop
)
self
.
closed
=
False
self
.
writers
=
{}
def
__aiter__
(
self
)
->
'
AsyncTextOutput
'
:
return
self
...
...
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