A lot of rework. Added inline keyboard
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
import logging
|
||||
import prettytable
|
||||
@@ -8,8 +7,22 @@ import walladb
|
||||
import constants
|
||||
|
||||
from worker import Worker
|
||||
from telegram import Update
|
||||
from telegram.ext import Application, CommandHandler, ContextTypes
|
||||
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ForceReply
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CallbackQueryHandler,
|
||||
CallbackContext,
|
||||
CommandHandler,
|
||||
ContextTypes,
|
||||
ConversationHandler,
|
||||
MessageHandler,
|
||||
filters
|
||||
)
|
||||
|
||||
ACTION, ADD_PRODUCT_NAME, ADD_PRODUCT_MIN_PRICE, ADD_PRODUCT_MAX_PRICE, \
|
||||
ADD_PRODUCT_CATEGORY, ADD_PRODUCT_TITLE_EXCLUDE, ADD_PRODUCT_DESCRIPTION_EXCLUDE, \
|
||||
ADD_PRODUCT_COORDS, ADD_PRODUCT_DISTANCE, REMOVE_PRODUCT, LIST, FINISH, CONTINUE_OR_FINISH = range(13)
|
||||
|
||||
# Enable logging
|
||||
logging.basicConfig(
|
||||
@@ -42,82 +55,229 @@ Borra un producto con `/remove nombre del producto`\n
|
||||
message = """Activa tu periodo de prueba de 7 días con `/test` o contacta con @jocarduck para más información."""
|
||||
await update.message.reply_markdown_v2(helpers.telegram_escape_characters(message))
|
||||
|
||||
async def categories_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
if walladb.is_user_valid(helpers.get_telegram_user_id(update)):
|
||||
message = ''
|
||||
for category in constants.CATEGORIES:
|
||||
message = f"{message}, {category}"
|
||||
await update.message.reply_markdown_v2(f"```{helpers.telegram_escape_characters(message)}```")
|
||||
async def main_menu(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
context.user_data.clear()
|
||||
keyboard = [
|
||||
[
|
||||
InlineKeyboardButton("Añadir", callback_data='add'),
|
||||
InlineKeyboardButton("Listar", callback_data='list'),
|
||||
InlineKeyboardButton("Borrar", callback_data='remove')]
|
||||
]
|
||||
markup = InlineKeyboardMarkup(keyboard)
|
||||
await update.message.reply_text('Selecciona una acción a realizar', reply_markup=markup)
|
||||
return ACTION
|
||||
|
||||
async def add_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
async def menu_click_handler(update: Update, context: CallbackContext):
|
||||
telegram_user_id = helpers.get_telegram_user_id(update)
|
||||
if walladb.is_user_valid(telegram_user_id):
|
||||
number_of_products = walladb.count_user_products(telegram_user_id)
|
||||
message = """Tienes que pasar el número correcto de parámetros: `/add producto;precio_mínimo;precio_máximo,categoría,excluir_título(opcional, separado por comas);excluir_descripción_y_título(opciona, separado por comas);latitud(opcional);longitud(opcional),distancia(opcional)`\n
|
||||
Ejemplo: `/add placa base itx;0;150`\n
|
||||
Ejemplo 2: `/add cpu;10;30;;intel,core 2 duo,celeron;;;100`\n
|
||||
Los campos opcionales que se dejen vacíos tomarán el valor configurado en el archivo `.env`"""
|
||||
valid = False
|
||||
if walladb.is_user_testing(telegram_user_id):
|
||||
valid = True
|
||||
if number_of_products >= 5:
|
||||
message = "Ya tienes 5 productos en seguimiento. Con premium puedes tener hasta 20."
|
||||
valid = False
|
||||
elif walladb.is_user_premium(telegram_user_id):
|
||||
valid = True
|
||||
if number_of_products >= 20:
|
||||
message = "Ya tienes 20 productos en seguimiento. Borra algunos para añadir más."
|
||||
valid = False
|
||||
if valid:
|
||||
args = update.message.text.split("/add ")
|
||||
if len(args) == 1:
|
||||
pass
|
||||
elif len(args[1].split(";")) > 2:
|
||||
product = dict()
|
||||
product['telegram_user_id'] = telegram_user_id
|
||||
args = args[1].split(";")
|
||||
product['product_name'], product['min_price'], product['max_price'] = args[0:3]
|
||||
if len(args) > 3 and args[3]:
|
||||
product['category'] = helpers.get_category_id(args[3])
|
||||
if len(args) > 4 and args[4]:
|
||||
product['title_exclude'] = args[4]
|
||||
if len(args) > 5 and args[5]:
|
||||
product['title_description_exclude'] = args[5]
|
||||
if len(args) > 6 and args[6]:
|
||||
product['latitude'] = args[6]
|
||||
if len(args) > 7 and args[7]:
|
||||
product['longitude'] = args[7]
|
||||
if len(args) > 8 and args[8]:
|
||||
product['distance'] = args[8]
|
||||
|
||||
logging.info(f'Adding: {product}')
|
||||
if not walladb.get_product(product):
|
||||
walladb.add_product(product)
|
||||
p = threading.Thread(target=Worker.run, args=(walladb.get_product(product), ))
|
||||
p.start()
|
||||
message = f"Añadido {walladb.get_product(product)['product_name']} a seguimiento."
|
||||
else:
|
||||
message = f"¡{walladb.get_product(product)['product_name']} ya está en seguimiento!"
|
||||
await update.message.reply_markdown_v2(helpers.telegram_escape_characters(message))
|
||||
context.user_data['telegram_user_id'] = telegram_user_id
|
||||
query = update.callback_query
|
||||
if query.data == 'add':
|
||||
valid = False
|
||||
if walladb.is_user_testing(telegram_user_id):
|
||||
number_of_products = walladb.count_user_products(telegram_user_id)
|
||||
valid = True
|
||||
if number_of_products >= 5:
|
||||
message = "Ya tienes 5 productos en seguimiento. Con premium puedes tener hasta 20."
|
||||
valid = False
|
||||
elif walladb.is_user_premium(telegram_user_id):
|
||||
valid = True
|
||||
if number_of_products >= 20:
|
||||
message = "Ya tienes 20 productos en seguimiento. Borra algunos para añadir más."
|
||||
valid = False
|
||||
if valid:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Escribe el nombre del producto a buscar', reply_markup=ForceReply())
|
||||
return ADD_PRODUCT_NAME
|
||||
else:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=f'{message}')
|
||||
return ConversationHandler.END
|
||||
if query.data == 'remove':
|
||||
await send_list(update, context)
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Escribe el nombre del producto a borrar, tal y como aparece en la lista', reply_markup=ForceReply())
|
||||
return REMOVE_PRODUCT
|
||||
if query.data == 'list':
|
||||
await send_list(update, context)
|
||||
#await context.bot.send_message(chat_id=update.effective_chat.id, text='Send your name', reply_markup=ForceReply())
|
||||
return ConversationHandler.END
|
||||
else:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Activa tu periodo de prueba de 7 días con `/test` o contacta con @jocarduck para más información.', parse_mode=ParseMode.MARKDOWN_V2)
|
||||
return ConversationHandler.END
|
||||
|
||||
async def add_product_name(update: Update, context: CallbackContext):
|
||||
if context.user_data.get('product_name', '') == '':
|
||||
answer = update.message.text
|
||||
context.user_data['product_name'] = answer
|
||||
if not walladb.get_product(context.user_data):
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Escribe el precio mínimo', reply_markup=ForceReply())
|
||||
return ADD_PRODUCT_MIN_PRICE
|
||||
else:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text=f"¡{walladb.get_product(context.user_data)['product_name']} ya está en seguimiento!")
|
||||
return ConversationHandler.END
|
||||
|
||||
async def remove_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
async def add_product_min_price(update: Update, context: CallbackContext):
|
||||
if context.user_data.get('min_price', '') == '':
|
||||
answer = update.message.text
|
||||
try:
|
||||
min_price = int(answer)
|
||||
except:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Pon un precio mínimo en números', reply_markup=ForceReply())
|
||||
return ADD_PRODUCT_MIN_PRICE
|
||||
if min_price < 0:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Pon un precio mínimo en números que no sean negativos', reply_markup=ForceReply())
|
||||
return ADD_PRODUCT_MIN_PRICE
|
||||
context.user_data['min_price'] = min_price
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Escribe el precio máximo', reply_markup=ForceReply())
|
||||
return ADD_PRODUCT_MAX_PRICE
|
||||
|
||||
async def add_product_max_price(update: Update, context: CallbackContext):
|
||||
if context.user_data.get('max_price', '') == '':
|
||||
answer = update.message.text
|
||||
try:
|
||||
max_price = int(answer)
|
||||
except:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Pon un precio máximo en números', reply_markup=ForceReply())
|
||||
return ADD_PRODUCT_MAX_PRICE
|
||||
if max_price < 0:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Pon un precio máximo en números que no sean negativos', reply_markup=ForceReply())
|
||||
return ADD_PRODUCT_MAX_PRICE
|
||||
context.user_data['max_price'] = max_price
|
||||
keyboard = [
|
||||
[
|
||||
InlineKeyboardButton("Añadir", callback_data='add'),
|
||||
InlineKeyboardButton("Descartar", callback_data='remove')
|
||||
], [InlineKeyboardButton("Escoge una categoría", callback_data='category'),],
|
||||
]
|
||||
markup = InlineKeyboardMarkup(keyboard)
|
||||
await update.message.reply_text(f'{context.user_data["product_name"]} de {context.user_data["min_price"]}€ a {context.user_data["max_price"]}€', reply_markup=markup)
|
||||
return ADD_PRODUCT_CATEGORY
|
||||
|
||||
async def add_product_category(update: Update, context: CallbackContext):
|
||||
query = update.callback_query
|
||||
if query.data == 'category':
|
||||
markup = InlineKeyboardMarkup(helpers.create_category_keyboard())
|
||||
context.user_data['last_step'] = 'category'
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text='Escoge la categoría', reply_markup=markup)
|
||||
return CONTINUE_OR_FINISH
|
||||
elif query.data == 'add':
|
||||
await add_to_db_and_send(update, context)
|
||||
return ConversationHandler.END
|
||||
elif query.data == 'remove':
|
||||
context.user_data.clear()
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=f'Borrado')
|
||||
return ConversationHandler.END
|
||||
|
||||
async def continue_or_finish(update: Update, context: CallbackContext):
|
||||
markup = InlineKeyboardMarkup(helpers.create_continue_keyboard())
|
||||
last_step = context.user_data.get('last_step', '')
|
||||
query = update.callback_query
|
||||
try:
|
||||
qd = query.data
|
||||
except:
|
||||
qd = ''
|
||||
|
||||
if qd == 'add':
|
||||
await add_to_db_and_send(update, context)
|
||||
return ConversationHandler.END
|
||||
if qd == 'remove':
|
||||
context.user_data.clear()
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=f'Borrado')
|
||||
return ConversationHandler.END
|
||||
|
||||
if last_step == 'category':
|
||||
category = int(query.data)
|
||||
context.user_data['category'] = category
|
||||
context.user_data['last_step'] = ''
|
||||
|
||||
if qd == 'title_exclude':
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Exclusión de título', reply_markup=ForceReply())
|
||||
context.user_data['last_step'] = 'title_exclude'
|
||||
return CONTINUE_OR_FINISH
|
||||
if last_step == 'title_exclude':
|
||||
context.user_data['title_exclude'] = update.message.text
|
||||
context.user_data['last_step'] = ''
|
||||
|
||||
if qd == 'description_exclude':
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Exclusión de descripción', reply_markup=ForceReply())
|
||||
context.user_data['last_step'] = 'description_exclude'
|
||||
return CONTINUE_OR_FINISH
|
||||
if last_step == 'description_exclude':
|
||||
context.user_data['description_exclude'] = update.message.text
|
||||
context.user_data['last_step'] = ''
|
||||
|
||||
if qd == 'coords':
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Coordenadas', reply_markup=ForceReply())
|
||||
context.user_data['last_step'] = 'coords'
|
||||
return CONTINUE_OR_FINISH
|
||||
if last_step == 'coords':
|
||||
answer = update.message.text
|
||||
try:
|
||||
latitude = float(answer.split(',')[0])
|
||||
longitude = float(answer.split(',')[1])
|
||||
except:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Pon las coordenadas siguiendo el ejemplo: 41.34, 0.65', reply_markup=ForceReply())
|
||||
return CONTINUE_OR_FINISH
|
||||
context.user_data['latitude'] = latitude
|
||||
context.user_data['longitude'] = longitude
|
||||
context.user_data['last_step'] = ''
|
||||
|
||||
if qd == 'distance':
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Distancia', reply_markup=ForceReply())
|
||||
context.user_data['last_step'] = 'distance'
|
||||
return CONTINUE_OR_FINISH
|
||||
if last_step == 'distance':
|
||||
answer = update.message.text
|
||||
try:
|
||||
latitude = int(answer)
|
||||
except:
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id,
|
||||
text='Pon la distancia en km, por ejemplo: 100', reply_markup=ForceReply())
|
||||
return CONTINUE_OR_FINISH
|
||||
context.user_data['distance'] = answer
|
||||
context.user_data['last_step'] = ''
|
||||
|
||||
if context.user_data['last_step'] == '':
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=f'Añadir?', reply_markup=markup)
|
||||
return CONTINUE_OR_FINISH
|
||||
|
||||
async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
context.user_data.clear()
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text="Cancelado.")
|
||||
return ConversationHandler.END
|
||||
|
||||
async def remove_product(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
telegram_user_id = helpers.get_telegram_user_id(update)
|
||||
if walladb.is_user_valid(telegram_user_id):
|
||||
if walladb.is_user_testing(telegram_user_id) or walladb.is_user_premium(telegram_user_id):
|
||||
product_to_remove = update.message.text[len('/remove '):]
|
||||
product_to_remove = update.message.text
|
||||
message = f"¡{product_to_remove} no está en seguimiento!"
|
||||
if walladb.remove_product({'product_name' : product_to_remove, \
|
||||
'telegram_user_id' : telegram_user_id}):
|
||||
message = f"¡{product_to_remove} borrado de la lista de seguimiento!"
|
||||
await update.message.reply_text(message)
|
||||
return ConversationHandler.END
|
||||
|
||||
async def list_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
async def send_list(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
telegram_user_id = helpers.get_telegram_user_id(update)
|
||||
if walladb.is_user_valid(telegram_user_id):
|
||||
if walladb.is_user_testing(telegram_user_id) or walladb.is_user_premium(telegram_user_id):
|
||||
products = walladb.get_products_from_user(telegram_user_id)
|
||||
|
||||
args = update.message.text.split("/list ")
|
||||
args = ''
|
||||
found = False
|
||||
if len(args) > 1:
|
||||
product = walladb.get_product({'product_name':args[1],'telegram_user_id':telegram_user_id})
|
||||
@@ -135,7 +295,7 @@ async def list_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
table.align['Máx'] = 'r'
|
||||
for product in products:
|
||||
table.add_row([helpers.telegram_escape_characters(product['product_name']), f"{helpers.telegram_escape_characters(product['min_price'])}€", f"{helpers.telegram_escape_characters(product['max_price'])}€"])
|
||||
await update.message.reply_markdown_v2(f'```{(table)}```')
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=f'```{(table)}```', parse_mode=ParseMode.MARKDOWN_V2)
|
||||
|
||||
async def admin_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
if helpers.is_user_admin(update.message.chat_id):
|
||||
@@ -185,6 +345,16 @@ async def test_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
message = "Ya eres premium. No puedes volver al periodo de prueba."
|
||||
await update.message.reply_markdown_v2(helpers.telegram_escape_characters(message))
|
||||
|
||||
async def add_to_db_and_send(update, context):
|
||||
logging.info(f"Adding product with context: {context.user_data}")
|
||||
walladb.add_product(context.user_data)
|
||||
p = threading.Thread(target=Worker.run, args=(walladb.get_product(context.user_data), ))
|
||||
p.start()
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=f"¡*{context.user_data['product_name']}* añadido correctamente\!", parse_mode=ParseMode.MARKDOWN_V2)
|
||||
|
||||
def error(update, context):
|
||||
logging.error(f'Update ---{update}--- caused error ---{context.error}---')
|
||||
|
||||
def main()->None:
|
||||
walladb.setup_db()
|
||||
products = walladb.get_all_products()
|
||||
@@ -200,16 +370,34 @@ def main()->None:
|
||||
|
||||
# on different commands - answer in Telegram
|
||||
application.add_handler(CommandHandler("help", help_command))
|
||||
application.add_handler(CommandHandler("categories", categories_command))
|
||||
application.add_handler(CommandHandler("add", add_command))
|
||||
application.add_handler(CommandHandler("remove", remove_command))
|
||||
application.add_handler(CommandHandler("list", list_command))
|
||||
application.add_handler(CommandHandler("admin", admin_command))
|
||||
application.add_handler(CommandHandler("add_premium_user", add_premium_user_command))
|
||||
application.add_handler(CommandHandler("remove_user", remove_user_command))
|
||||
application.add_handler(CommandHandler("status", status_command))
|
||||
application.add_handler(CommandHandler("test", test_command))
|
||||
|
||||
conv_handler = ConversationHandler(
|
||||
entry_points=[CommandHandler("menu", main_menu)],
|
||||
states={
|
||||
ACTION: [CallbackQueryHandler(menu_click_handler)],
|
||||
ADD_PRODUCT_NAME: [MessageHandler(filters.TEXT, add_product_name),
|
||||
CallbackQueryHandler(add_product_name)],
|
||||
ADD_PRODUCT_MIN_PRICE: [MessageHandler(filters.TEXT, add_product_min_price)],
|
||||
ADD_PRODUCT_MAX_PRICE: [MessageHandler(filters.TEXT, add_product_max_price)],
|
||||
ADD_PRODUCT_CATEGORY: [CallbackQueryHandler(add_product_category)],
|
||||
CONTINUE_OR_FINISH: [CallbackQueryHandler(continue_or_finish),
|
||||
MessageHandler(filters.TEXT, continue_or_finish)],
|
||||
REMOVE_PRODUCT: [MessageHandler(filters.TEXT, remove_product)],
|
||||
},
|
||||
fallbacks=[CommandHandler("cancel", cancel)],
|
||||
)
|
||||
|
||||
# Add ConversationHandler to application that will be used for handling updates
|
||||
application.add_handler(conv_handler)
|
||||
|
||||
#application.bot.set_chat_menu_button('Menú')
|
||||
|
||||
application.add_error_handler(error)
|
||||
# on non command i.e message - echo the message on Telegram
|
||||
#application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user