Initial commit

This commit is contained in:
2022-04-03 10:17:37 +02:00
parent 2315419319
commit 35ae416a1e
5 changed files with 165 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*json

6
Dockerfile Normal file
View File

@ -0,0 +1,6 @@
FROM python:3.8-alpine
WORKDIR /usr/src/app
COPY ./requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt
COPY . ./
CMD ["python", "bot.py"]

132
bot.py Normal file
View File

@ -0,0 +1,132 @@
import _thread
import os
import logging
import telebot
from telebot import types
from pymongo import MongoClient
telebot.logger.setLevel(logging.DEBUG)
# Bot & config
bot = telebot.TeleBot(os.environ['TOKEN'])
admin = int(os.environ['ADMIN'])
# Acceso a bd
client = MongoClient('database:27017')
db = client.bot
tests = db.tests
users = db.users
# Funciones de utilidad
def is_user(cid):
return users.find_one(str(cid)) is not None
def add_user(cid):
users.insert_one({
"_id": str(cid),
"taken_tests": [],
"current_tests": []
})
def restart_process():
_thread.interrupt_main()
def is_admin(cid):
return str(cid) == str(admin)
def split(a, n):
k, m = divmod(len(a), n)
return (a[i*k+min(i, m):(i+1)*k+min(i+1, m)] for i in range(n))
def find_question(test, question):
questions = tests.find_one({'test': int(test)}, {'preguntas':{'$elemMatch': {'pregunta': int(question)}}, '_id':0})
if questions:
return questions['preguntas'][0]
return {}
def generate_tests_keyboard():
keyboard = types.InlineKeyboardMarkup(row_width=4)
buttons = []
for test in tests.find({},{'test':1, '_id':0}):
buttons.append(types.InlineKeyboardButton('Test {}'.format(test['test']-100), callback_data='test {}'.format(test['test'])))
for chunk in split(buttons, 4):
keyboard.add(*chunk)
return keyboard
def generate_test_keyboard(question, test):
keyboard = types.InlineKeyboardMarkup()
for i,answer in enumerate(question.get('respuestas')):
keyboard.add(types.InlineKeyboardButton('{}'.format(answer['texto']), callback_data='pregunta {} {} {}'.format(test, question['pregunta'], i)))
next_prev_buttons = []
if question.get('pregunta') == 1:
next_prev_buttons.append(types.InlineKeyboardButton('', callback_data='pregunta {} {} +'.format(test, question['pregunta'])))
elif question.get('pregunta') == 20:
next_prev_buttons.append(types.InlineKeyboardButton('', callback_data='pregunta {} {} -'.format(test, question['pregunta'])))
else:
next_prev_buttons.append(types.InlineKeyboardButton('', callback_data='pregunta {} {} -'.format(test, question['pregunta'])))
next_prev_buttons.append(types.InlineKeyboardButton('', callback_data='pregunta {} {} +'.format(test, question['pregunta'])))
keyboard.add(*next_prev_buttons)
return keyboard
# Manejadores de comandos
@bot.message_handler(commands=['start'])
def start_handler(m):
cid = m.chat.id
if not is_user(cid):
add_user(cid)
bot.send_message(cid, "Bienvenid@")
@bot.message_handler(commands=['reload'])
def reload_handler(m):
cid = m.chat.id
if is_admin(cid):
restart_process()
@bot.message_handler(commands=['tests'])
def tests_handler(m):
cid = m.chat.id
keyboard = generate_tests_keyboard()
bot.send_message(cid, "Haz click en un test para empezar a resolverlo", reply_markup=keyboard)
@bot.callback_query_handler(func=lambda call: call.data.startswith('test'))
def test_callback_handler(call):
cid = call.message.chat.id
test = call.data.split()[-1]
question = find_question(test, 1)
keyboard = generate_test_keyboard(question, test)
txt = "Test: {}\nPregunta: {}\n\n{}"
bot.send_photo(cid, question.get('img'), caption=txt.format(test, 1, question['encabezado']), reply_markup=keyboard)
# TODO: Añadir el test a current_tests del usuario
bot.answer_callback_query(call.id)
@bot.callback_query_handler(func=lambda call: call.data.startswith('pregunta') and (call.data.endswith('+') or call.data.endswith('-')))
def question_answer_callback_handler(call):
cid = call.message.chat.id
mid = call.message.id
_, test, q, option = call.data.split()
question = find_question(test, int(q)+1)
keyboard = generate_test_keyboard(question, test)
txt = "Test: {}\nPregunta: {}\n\n{}"
@bot.callback_query_handler(func=lambda call: call.data.startswith('pregunta') and (call.data.endswith('+') or call.data.endswith('-')))
def question_pager_callback_handler(call):
cid = call.message.chat.id
mid = call.message.id
_, test, q, action = call.data.split()
question = find_question(test, eval(q+action+'1'))
keyboard = generate_test_keyboard(question, test)
txt = "Test: {}\nPregunta: {}\n\n{}"
try:
bot.edit_message_media(types.InputMediaPhoto(question.get('img'), caption=txt.format(test, question['pregunta'], question['encabezado'])), cid, mid, reply_markup=keyboard)
bot.answer_callback_query(call.id)
except:
bot.answer_callback_query(call.id, "No se pudo cargar la pregunta")
# Iniciar bot
bot.send_message(admin, "Reiniciado")
bot.polling(skip_pending=True)

23
docker-compose.yml Normal file
View File

@ -0,0 +1,23 @@
version: '3'
services:
bot:
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
environment:
- TOKEN=$TOKEN
- ADMIN=52033876
volumes:
- ./:/usr/src/app
depends_on:
- database
database:
image: "mvertes/alpine-mongo"
restart: unless-stopped
volumes:
- db:/data/db
volumes:
db: {}

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
pytelegrambotapi
pymongo
requests