summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--configstore.py4
-rw-r--r--main.py32
3 files changed, 37 insertions, 0 deletions
diff --git a/README.md b/README.md
index 752e17e..4444d34 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ token=YOUR_TOKEN
admins=
123456 ; admin id
000123 ; another admin id
+shell_admin=123456 ; admin that's allowed to spawn shell commands
isv_bin=/path/to/isv
use_sudo=0
```
diff --git a/configstore.py b/configstore.py
index fcaa5c8..36765d6 100644
--- a/configstore.py
+++ b/configstore.py
@@ -37,6 +37,10 @@ def get_token() -> str:
return get_config()['token']
+def get_shell_admin_id() -> int:
+ return int(get_config()['shell_admin'])
+
+
def get_admins() -> tuple:
config = get_config()
return tuple([int(s) for s in re.findall(r'\b\d+\b', config['admins'], flags=re.MULTILINE)])
diff --git a/main.py b/main.py
index 51f8d35..15cad1d 100644
--- a/main.py
+++ b/main.py
@@ -3,6 +3,8 @@ import re
import datetime
import isv
import configstore
+import subprocess
+import os
from html import escape
from time import sleep
@@ -90,6 +92,30 @@ def msg_status(update: Update, context: CallbackContext) -> None:
reply(update, 'exception: ' + str(e))
+def msg_shell(update: Update, context: CallbackContext) -> None:
+ try:
+ argv = re.findall('^shell (.*)$', update.message.text)[0].split()
+ result = subprocess.run(argv, capture_output=True)
+ if result.returncode != 0:
+ raise ChildProcessError('spawned process returned ' + str(result.returncode))
+
+ buf = '[stdout] ' + result.stdout.decode('utf-8')
+ buf += '\n[stderr] ' + result.stderr.decode('utf-8')
+ reply(update, buf)
+ except Exception as e:
+ logging.exception(str(e))
+ reply(update, 'exception: ' + str(e))
+
+
+def msg_spawn(update: Update, context: CallbackContext) -> None:
+ try:
+ argv = re.findall('^spawn (.*)$', update.message.text)[0].split()
+ os.spawnlp(os.P_NOWAIT, argv[0], *argv)
+ except Exception as e:
+ logging.exception(str(e))
+ reply(update, 'exception: ' + str(e))
+
+
def msg_generation(update: Update, context: CallbackContext) -> None:
try:
today = datetime.date.today()
@@ -171,15 +197,21 @@ if __name__ == '__main__':
dispatcher = updater.dispatcher
user_filter = Filters.user(configstore.get_admins())
+ shell_admin_filter = Filters.user((configstore.get_shell_admin_id(), ))
dispatcher.add_handler(CommandHandler('start', start))
+ dispatcher.add_handler(MessageHandler(Filters.regex(r'^shell ') & shell_admin_filter, msg_shell))
+ dispatcher.add_handler(MessageHandler(Filters.regex(r'^spawn ') & shell_admin_filter, msg_spawn))
+
dispatcher.add_handler(MessageHandler(Filters.text(_('status')) & user_filter, msg_status))
dispatcher.add_handler(MessageHandler(Filters.text(_('generation')) & user_filter, msg_generation))
dispatcher.add_handler(MessageHandler(Filters.text(_('gs')) & user_filter, msg_gs))
dispatcher.add_handler(MessageHandler(Filters.text(_('ri')) & user_filter, msg_ri))
dispatcher.add_handler(MessageHandler(Filters.text(_('errors')) & user_filter, msg_errors))
+
dispatcher.add_handler(MessageHandler(Filters.all & user_filter, msg_all))
+
# start the bot
updater.start_polling()