Added cmd command.
This commit is contained in:
parent
0dfcb4963a
commit
72a9595122
31
README.md
31
README.md
|
@ -187,6 +187,37 @@ Example:
|
||||||
|
|
||||||
* !url status
|
* !url status
|
||||||
|
|
||||||
|
#### Cmd
|
||||||
|
|
||||||
|
Can be used to pre-configure shell commands run by bot. This is easy way to add
|
||||||
|
security issues to your bot so be careful.
|
||||||
|
|
||||||
|
Pre-defined commands can be set only by bot owner, but anyone can run them.
|
||||||
|
It's your responsibility as owner to make sure you don't allow running anything dangerous.
|
||||||
|
|
||||||
|
Commands have 5 second timeout so don't try to run long processes.
|
||||||
|
|
||||||
|
Environ variables seen by commands:
|
||||||
|
|
||||||
|
* MATRIX_USER: User who ran the command
|
||||||
|
* MATRIX_ROOM: Room the command was run (avoid using, may cause vulnerabilities)
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
|
||||||
|
* !cmd run "command" - Run command "command" (Must be done as bot owner)
|
||||||
|
* !cmd add cmdname "command" - Add new named command "command" (Must be done as bot owner)
|
||||||
|
* !cmd remove cmdname - Remove named command (Must be done as bot owner)
|
||||||
|
* !cmd list - List named commands
|
||||||
|
* !cmd cmdname - Run a named command
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
* !cmd run "hostname"
|
||||||
|
* !cmd add systemstats "uname -a && uptime"
|
||||||
|
* !cmd systemstats
|
||||||
|
* !cmd add df "df -h"
|
||||||
|
* !cmd add whoami "echo You are $MATRIX_USER in room $MATRIX_ROOM."
|
||||||
|
|
||||||
## Bot setup
|
## Bot setup
|
||||||
|
|
||||||
* Create a Matrix user
|
* Create a Matrix user
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
from modules.common.module import BotModule
|
||||||
|
import subprocess
|
||||||
|
import shlex
|
||||||
|
|
||||||
|
|
||||||
|
class MatrixModule(BotModule):
|
||||||
|
commands = dict() # cmd name -> shell command
|
||||||
|
|
||||||
|
async def matrix_message(self, bot, room, event):
|
||||||
|
args = shlex.split(event.body)
|
||||||
|
args.pop(0)
|
||||||
|
|
||||||
|
if len(args) == 2:
|
||||||
|
if args[0] == 'run':
|
||||||
|
bot.must_be_owner(event)
|
||||||
|
out = self.run_command(args[1], event.sender, room.display_name)
|
||||||
|
await self.send_output(bot, room, out)
|
||||||
|
if args[0] == 'remove':
|
||||||
|
bot.must_be_owner(event)
|
||||||
|
cmdname = args[1]
|
||||||
|
self.commands.pop(cmdname, None)
|
||||||
|
bot.save_settings()
|
||||||
|
await bot.send_text(room, 'Command removed.')
|
||||||
|
elif len(args) == 3:
|
||||||
|
if args[0] == 'add':
|
||||||
|
bot.must_be_owner(event)
|
||||||
|
cmdname = args[1]
|
||||||
|
self.commands[cmdname] = args[2]
|
||||||
|
bot.save_settings()
|
||||||
|
await bot.send_text(room, 'Command added.')
|
||||||
|
elif len(args) == 1:
|
||||||
|
if args[0] == 'list':
|
||||||
|
await bot.send_text(room, 'Known commands: ' + str(self.commands))
|
||||||
|
elif args[0] in self.commands:
|
||||||
|
self.logger.debug(f"room: {room.display_name} sender: {event.sender} wants to run cmd {args[0]}")
|
||||||
|
out = self.run_command(self.commands[args[0]], event.sender, room.display_name)
|
||||||
|
await self.send_output(bot, room, out)
|
||||||
|
else:
|
||||||
|
await bot.send_text(room, 'Unknown command.')
|
||||||
|
|
||||||
|
def help(self):
|
||||||
|
return 'Runs shell commands'
|
||||||
|
|
||||||
|
def get_settings(self):
|
||||||
|
data = super().get_settings()
|
||||||
|
data['commands'] = self.commands
|
||||||
|
return data
|
||||||
|
|
||||||
|
def set_settings(self, data):
|
||||||
|
super().set_settings(data)
|
||||||
|
if data.get('commands'):
|
||||||
|
self.commands = data['commands']
|
||||||
|
|
||||||
|
def run_command(self, command, user, roomname):
|
||||||
|
self.logger.info(f"Running command {command}..")
|
||||||
|
environment = {'MATRIX_USER': user, 'MATRIX_ROOM': roomname}
|
||||||
|
processout = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=5, text=True, env=environment)
|
||||||
|
return processout.stdout
|
||||||
|
|
||||||
|
async def send_output(self, bot, room, output):
|
||||||
|
html = output
|
||||||
|
if output.count('\n') > 1:
|
||||||
|
html = "<pre>" + output + "</pre>"
|
||||||
|
if len(output) == 0:
|
||||||
|
output = html = '(No output returned)'
|
||||||
|
await bot.send_html(room, html, output)
|
Loading…
Reference in New Issue