"""Callbacks for matrix messages"""
import html
import time
import traceback
from mab import * # type: ignore
import util
from database import Database
from datatypes import *
#
# PRIVATE
#
_db: Database = None # type: ignore
_COMMANDS = {
"help": "Получить справку",
"info": "Получить сведения о комнате",
"tokens": "Получить список токенов",
"auth": "Создать новый токен",
"deauth": "Удалить существующий токен",
"name": "Задать (или удалить) имя для токена",
"ban": "Забанить IP адрес",
"unban": "Разбанить IP адрес",
"bans": "Получить список забаненных IP адресов",
"short": "(Небезопасно) Создать токен-имя",
}
def _generate_help_message() -> str:
"""Generates help message in HTML markup"""
result = "Как использовать
!auth, создайте токен!info в комнате, чтобы узнать код канала уведомений!{key} - {html.escape(_COMMANDS[key])}"
return result
#
# COMMAND HANDLERS
#
async def _on_cmd_help(ctx: EventContext) -> None:
"""!help"""
await ctx.bot.send_text(ctx.room, _generate_help_message())
async def _on_cmd_info(ctx: EventContext) -> None:
"""!info"""
# get room info (or add it)
room_info = await _db.room_get(ctx.room.room_id)
if room_info is None:
room_info = await _db.room_create(ctx.room.room_id)
# failure
if room_info is None:
await ctx.bot.send_text(
ctx.room, "Нет информации о комнате"
)
return
# respond
response = "Сведения о комнате{html.escape(room_info.code)}"
await ctx.bot.send_text(ctx.room, response)
async def _on_cmd_tokens(ctx: EventContext) -> None:
"""!info"""
# get all tokens and check if there are none
tokens = await _db.token_get_all()
if not tokens:
await ctx.bot.send_text(
ctx.room,
"Нет токенов, используйте !auth"
)
return
# create the list of tokens
response = "Список токенов"
for token in tokens:
response += f"{html.escape(token.code)}{token.name}{token.code}"
response += f"{html.escape(token.name)}"
else:
response += "указывается в запросе"
# respond
await ctx.bot.send_text(ctx.room, response)
async def _on_cmd_deauth(ctx: EventContext) -> None:
"""!deauth"""
# no token provided
if len(ctx[CTX_CMD_ARGS]) != 1:
await ctx.bot.send_text(ctx.room, "Укажите токен, который надо удалить (должен быть ровно один аргумент)")
return
token = ctx[CTX_CMD_ARGS][0]
# check if token does not exist
if await _db.token_get(token) is None:
await ctx.bot.send_text(ctx.room, "Токен не найден")
return
# remove the token
await _db.token_delete(token)
# respond
response = f"Удалён токен {token}"
await ctx.bot.send_text(ctx.room, response)
async def _on_cmd_name(ctx: EventContext) -> None:
"""!name"""
# check arguments
if len(ctx[CTX_CMD_ARGS]) < 1:
error = "Требуется указать как минимум токен. Если хотите убрать имя, то имя указывать не надо. Если имя нужно назначить или изменить, то после токена укажите новое имя."
await ctx.bot.send_text(ctx.room, error)
return
token = ctx[CTX_CMD_ARGS][0]
new_name = " ".join(ctx[CTX_CMD_ARGS][1:])
if not new_name.strip():
new_name = None
# check if token exists
if await _db.token_get(token) is None:
await ctx.bot.send_text(ctx.room, "Токен не существует")
return
# set new name
await _db.token_set_name(token, new_name)
# prepare the response
if new_name:
response = f"Новое имя для токена {token}: {new_name}"
else:
response = f"Удалено имя для токена {token}"
# respond
await ctx.bot.send_text(ctx.room, response)
async def _on_cmd_ban(ctx: EventContext) -> None:
"""!ban"""
# check arguments
if len(ctx[CTX_CMD_ARGS]) < 2:
error = "Формат: !ban <IP> <SECONDS> [REASON]"
await ctx.bot.send_text(ctx.room, error)
return
# get event.command_args
try:
ip = ctx[CTX_CMD_ARGS][0]
duration = float(ctx[CTX_CMD_ARGS][1])
reason = " ".join(ctx[CTX_CMD_ARGS][2:]) if ctx[CTX_CMD_ARGS][2:] else "Manual ban"
except:
error = "Возникла ошибка. Наверняка неправильно указаны секунды."
await ctx.bot.send_text(ctx.room, error)
return
# ban
try:
await _db.ban_create(ip, time.time() + duration, reason)
await ctx.bot.send_text(ctx.room, "IP адрес заблокирован")
except:
await ctx.bot.send_text(ctx.room, "Возникла ошибка")
async def _on_cmd_unban(ctx: EventContext) -> None:
"""!unban"""
# check arguments
if len(ctx[CTX_CMD_ARGS]) != 1:
error = "Формат: !ban <IP>"
await ctx.bot.send_text(ctx.room, error)
return
# unban
try:
await _db.ban_delete(ctx[CTX_CMD_ARGS][0])
await ctx.bot.send_text(ctx.room, "IP адрес разблокирован (если он был заблокирован)")
except:
await ctx.bot.send_text(ctx.room, "Возникла ошибка")
async def _on_cmd_bans(ctx: EventContext) -> None:
"""!bans"""
# list
bans = _db.ban_get_all()
if not bans:
await ctx.bot.send_text(ctx.room, "Нет заблокированных IP адресов")
return
# create the response
result = "Список заблокированных IP{util.date_to_text(ban["expires_at"])}{html.escape(ban["reason"])}!short <token>"
await ctx.bot.send_text(ctx.room, error)
return
# create new token
try:
token = await _db.token_create(ctx[CTX_CMD_ARGS][0])
except Exception as e:
await ctx.bot.send_text(ctx.room, f"Не удалось создать токен: {" ".join(e.args)}")
return
# create the response
response = "Создан новый токен"
response += f"{token.code}"
response += f"