Files
NetworkDiffBot/src/commands.py
T
2020-11-27 09:17:44 -05:00

225 lines
5.7 KiB
Python

import datetime
import difflib
import json
import re
from io import BytesIO
from telegram import Bot, Update
from telegram.ext import Updater, CallbackContext, Job
from src.database import Database
from src.scheduler import Scheduler
from src.utils import toJson, create, dictToString, render, wrap
helpMsg = """
Welcome! This bot monitors http changes!
/start - Start the bot
*Management Commands*
/ls - List the http requests you've created
/touch - Create a http request
/rm - Delete a http request
*Configuration Commands*
/nano - Edit a http request
/test - Test a http request
/interval - Change the interval between the updates of a http request
*Start/Stop Commands*
/enable - Start listening to a http request
/disable - Stop listening to a http request
"""
# https://stackoverflow.com/a/7160778/7346633
urlValidator = re.compile(
r'^(?:http|ftp)s?://' # http:// or https://
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain...
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
r'(?::\d+)?' # optional port
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
database = Database()
scheduler: Scheduler
updater: Updater
def sendRequest(req: str):
r = create(req)
text = r.text
if r.headers['Content-Type'] == 'application/json':
text = dictToString(json.loads(text))
r.close()
return text
# Initialize bot
def init(bot: Bot, u: Updater):
global updater
updater = u
global scheduler
scheduler = Scheduler(database, updater)
for user in database.users:
for request in database.userRequests[user]:
if request['enabled']:
scheduler.startTask(user, request)
def start(update: Update, context: CallbackContext):
chat = update.effective_chat
database.checkUser(chat.id)
return helpMsg
def ls(update: Update, context: CallbackContext):
chat = update.effective_chat
user = database.checkUser(chat.id)
requests = database.userRequests[user]
return "Your requests: %s" % toJson(requests)
def touch(update: Update, context: CallbackContext):
chat = update.effective_chat
user = database.checkUser(chat.id)
# Too many requests
if len(database.userRequests[user]) > 10:
return "*Error:* One user can only have 10 requests for now ;-;"
# No args
if len(context.args) != 2:
return "Usage: /touch <request name> <proper url>"
# Validate name
name = context.args[0]
if not name.isalnum():
return "*Error:* You can only use alphanumeric names!"
if name in database.userRequests[user]:
return "*Error:* %s already exists" % name
# Validate url
url = context.args[1]
if re.match(urlValidator, url) is None:
return "*Error:* %s cannot pass the format check" % url
# Create
database.userRequests[user][name] = {'method': 'GET', 'url': url, 'headers': {}, 'data': None}
database.save()
return "%s is successfully created!" % name
def rm(update: Update, context: CallbackContext):
chat = update.effective_chat
user = database.checkUser(chat.id)
# No args
if len(context.args) != 1:
return "Usage: /rm <request name>"
# Check if name exists
name = context.args[0]
if name not in database.userRequests[user]:
return "%s doesn't exist, nothing changed." % name
# Remove
database.userRequests[user].pop(name, None)
database.save()
return "%s is successfully removed!" % name
def nano(update: Update, context: CallbackContext):
chat = update.effective_chat
user = database.checkUser(chat.id)
def test(update: Update, context: CallbackContext):
chat = update.effective_chat
user = database.checkUser(chat.id)
# No args
if len(context.args) != 1:
return "Usage: /test <request name>"
# Check if name exists
name = context.args[0]
if name not in database.userRequests[user]:
return "*Error:* %s doesn't exist." % name
# Run
text = sendRequest(database.userRequests[user][name])
if len(text) > 60000:
return "File too large (>60kb)."
context.bot.send_document(chat_id=chat.id, document=BytesIO(bytes(text, 'utf-8')), filename=name + '.txt')
return 'Done!'
def interval(update: Update, context: CallbackContext):
chat = update.effective_chat
user = database.checkUser(chat.id)
# No args
if len(context.args) != 2:
return "Usage: /interval <request name> <interval in seconds>"
# Check if name exists
name = context.args[0]
if name not in database.userRequests[user]:
return "*Error:* %s doesn't exist." % name
# Validate the interval of the interval
i = int(context.args[1])
if i < 40 or i > 60*60*24:
return "*Error:* %s is too long or too short. (Min: 40s, Max: 60 * 60 * 24s)" % i
database.userRequests[user][name]['interval'] = i
database.save()
return "Success!"
def enable(update: Update, context: CallbackContext):
chat = update.effective_chat
user = database.checkUser(chat.id)
# No args
if len(context.args) != 1:
return "Usage: /enable <request name>"
# Check if name exists
name = context.args[0]
if name not in database.userRequests[user]:
return "*Error:* %s doesn't exist." % name
# Start task
startTask(user, name)
return "Started!"
def disable(update: Update, context: CallbackContext):
chat = update.effective_chat
user = database.checkUser(chat.id)
# No args
if len(context.args) != 1:
return "Usage: /disable <request name>"
# Check if name is running
name = context.args[0]
if not scheduler.isStarted(user, name):
return "*Error:* %s isn't enabled." % name
scheduler.stop(user, name)
return "Removed!"