Added button to product found. Added product_name to know from which search provides the article found.

This commit is contained in:
Joan
2023-03-13 16:42:26 +01:00
parent 23fa1205b3
commit 8057bfdba3
4 changed files with 82 additions and 29 deletions

View File

@@ -6,7 +6,9 @@ import constants
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime, timedelta
from telegram import InlineKeyboardButton
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application
from telegram.constants import ParseMode
# Enable logging
logging.basicConfig(
@@ -111,12 +113,18 @@ def create_image(article):
# guardamos la imagen con otro nombre
image.save(f"/app/data/images/products/{article['id']}_composed.png", quality=95)
def send_article(article, product):
async def send_article(article, product):
application = Application.builder().get_updates_http_version('1.1').http_version('1.1').token(constants.TELEGRAM_TOKEN).build()
create_image(article)
text = f"*{telegram_escape_characters(article['title'])}*\n\n*Descripción*: {telegram_escape_characters(article['description'])}\n\n*Precio*: {telegram_escape_characters(str(article['price']))} {telegram_escape_characters(article['currency'])}\n\n[IR AL ANUNCIO](https://es\.wallapop\.com/item/{telegram_escape_characters(article['web_slug'])})"
url = f"https://api.telegram.org/bot{constants.TELEGRAM_TOKEN}/sendPhoto?chat_id={product['telegram_user_id']}&caption={text}&parse_mode=MarkdownV2"
files = {'photo':open(f"/app/data/images/products/{article['id']}_composed.png", 'rb')}
logging.info(requests.post(url, files=files).content)
text = f"*{telegram_escape_characters(article['title'])}*\n\n*Descripción*: {telegram_escape_characters(article['description'])}\n\n*Encontrado por la búsqueda de:*{telegram_escape_characters(product['product_name'])}\n\n*Precio*: {telegram_escape_characters(str(article['price']))} {telegram_escape_characters(article['currency'])}"
#url = f"https://api.telegram.org/bot{constants.TELEGRAM_TOKEN}/sendPhoto?chat_id={product['telegram_user_id']}&caption={text}&parse_mode=MarkdownV2"
#files = {'photo':open(f"/app/data/images/products/{article['id']}_composed.png", 'rb')}
keyboard = [[InlineKeyboardButton("Ir al anuncio", url=f"https://es.wallapop.com/item/{article['web_slug']}")]]
#InlineKeyboardButton("Listar productos", callback_data="list")]
markup = InlineKeyboardMarkup(keyboard)
response = await application.bot.send_photo(chat_id=product['telegram_user_id'], photo=open(f"/app/data/images/products/{article['id']}_composed.png", 'rb'), caption=text, parse_mode=ParseMode.MARKDOWN_V2, reply_markup=markup)
#logging.info(requests.post(url, files=files).content)
logging.info(response)
def get_category_id(category):
ret = constants.CATEGORIES.get(category, '')

View File

@@ -88,7 +88,7 @@ def add_test_user(telegram_user_id, telegram_name, until):
found = False
con = sqlite3.connect(constants.DB)
cur = con.cursor()
params = (telegram_name,)
params = (telegram_user_id,)
res = cur.execute(f"SELECT * FROM users WHERE telegram_user_id=?", params)
if res.fetchone() is None:
params = (telegram_user_id, True, 'testing', until, telegram_name.first_name)
@@ -119,6 +119,19 @@ def get_user_list():
con.close()
return ret
def get_user(telegram_user_id):
con = sqlite3.connect(constants.DB)
con.row_factory = dict_factory
cur = con.cursor()
params = (telegram_user_id,)
res = cur.execute(f"SELECT telegram_name FROM users WHERE telegram_user_id=?", params)
if res != None:
ret = res.fetchone()['telegram_name']
else:
ret = 'NoName'
con.close()
return ret
def get_user_type(telegram_user_id):
con = sqlite3.connect(constants.DB)
cur = con.cursor()

View File

@@ -91,16 +91,21 @@ async def menu_click_handler(update: Update, context: CallbackContext):
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):
product_name = update.message.text
if len(product_name) > 200:
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
text='El nombre del producto a buscar es muy largo, pon otro nombre', reply_markup=ForceReply())
return ADD_PRODUCT_NAME
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
context.user_data['product_name'] = product_name
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 add_product_min_price(update: Update, context: CallbackContext):
if context.user_data.get('min_price', '') == '':
@@ -111,9 +116,9 @@ async def add_product_min_price(update: Update, context: CallbackContext):
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:
if min_price < 0 or min_price > 999999:
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())
text='Pon un precio mínimo entre 0 y 999999', 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,
@@ -129,9 +134,13 @@ async def add_product_max_price(update: Update, context: CallbackContext):
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:
if max_price < 0 or max_price > 999999:
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())
text='Pon un precio máximo entre 0 y 999999', reply_markup=ForceReply())
return ADD_PRODUCT_MAX_PRICE
if max_price < context.user_data['min_price']:
await context.bot.send_message(chat_id=update.effective_chat.id,
text='Pon un precio máximo menor al precio mínimo', reply_markup=ForceReply())
return ADD_PRODUCT_MAX_PRICE
context.user_data['max_price'] = max_price
keyboard = [
@@ -340,7 +349,7 @@ async def add_to_db_and_send(update: Update, context: ContextTypes.DEFAULT_TYPE)
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)
await context.bot.send_message(chat_id=update.effective_chat.id, text=f"¡*{helpers.telegram_escape_characters(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}---')
@@ -371,6 +380,8 @@ def main()->None:
application.add_handler(CommandHandler("remove_user", remove_user_command))
application.add_handler(CommandHandler("status", status_command))
application.add_handler(CommandHandler("test", test_command))
#application.add_handler(CallbackQueryHandler("list", send_list()))
#application.add_handler(CallbackQueryHandler(pattern="list", callback=send_list()))
conv_handler = ConversationHandler(
conversation_timeout=60,

View File

@@ -4,6 +4,7 @@ import logging
import helpers
import walladb
import constants
import asyncio
# Enable logging
logging.basicConfig(
@@ -56,6 +57,7 @@ class Worker:
return json_data['search_objects']
def first_run(self, product):
logging.info(f"First run for {product['product_name']} for {walladb.get_user(product['telegram_user_id'])}")
for i in range(5):
helpers.random_wait()
list = []
@@ -66,7 +68,7 @@ class Worker:
list.insert(0, article['id'])
return list
def work(self, product, list):
async def work(self, product, list):
helpers.random_wait() # Random wait to make requests separated in time in order to prevent API rate limit
exec_times = []
while True:
@@ -81,18 +83,20 @@ class Worker:
try:
if not self.has_excluded_words(article['title'].lower(), article['description'].lower(), product['title_description_exclude']) and not self.is_title_key_word_excluded(article['title'].lower(), product['title_exclude']):
try:
helpers.send_article(article, product)
await helpers.send_article(article, product)
except:
helpers.send_article(article, product)
time.sleep(1) # Avoid Telegram flood restriction
await helpers.send_article(article, product)
await asyncio.sleep(1)
#time.sleep(1) # Avoid Telegram flood restriction
list.insert(0, article['id'])
except Exception as e:
logging.info("---------- EXCEPTION -----------")
logging.info(f"{product['product_name']} worker crashed. {e}")
logging.info(f"{product['product_name']}: Trying to parse {article['id']}: {article['title']} .\n")
time.sleep(constants.SLEEP_TIME)
#time.sleep(constants.SLEEP_TIME)
await asyncio.sleep(constants.SLEEP_TIME)
exec_times.append(time.time() - start_time)
logging.info(f"\'{product['product_name']}\' node-> last: {exec_times[-1]} max: {self.get_max_time(exec_times)} avg: {self.get_average_time(exec_times)}")
logging.info(f"\'{product['product_name']}\' for {walladb.get_user(product['telegram_user_id'])} ({product['telegram_user_id']}) node-> last: {exec_times[-1]:.2f} max: {self.get_max_time(exec_times):.2f} avg: {self.get_average_time(exec_times):.2f}")
def has_excluded_words(self, title, description, excluded_words):
if len(excluded_words) > 0:
@@ -125,16 +129,33 @@ class Worker:
largest = i
return largest
async def old_run(product):
worker = Worker()
list = worker.first_run(product)
while True:
try:
logging.info(f"Wallapop monitor worker started. Checking for new items containing: \'{product['product_name']}\' for {walladb.get_user(product['telegram_user_id'])} ({product['telegram_user_id']}) with given parameters periodically")
await worker.work(product, list)
break
except Exception as e:
logging.info(f"Exception: {e}")
logging.info(f"{product['product_name']} worker crashed. Restarting worker...")
await asyncio.sleep(10)
#time.sleep(10)
logging.info(f"Wallapop monitor worker stopped for: \'{product['product_name']}\'")
def run(product):
worker = Worker()
list = worker.first_run(product)
while True:
try:
logging.info(f"Wallapop monitor worker started. Checking for new items containing: \'{product['product_name']}\' with given parameters periodically")
worker.work(product, list)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(worker.work(product, list))
loop.close()
break
except Exception as e:
logging.info(f"Exception: {e}")
logging.info(f"{product['product_name']} worker crashed. Restarting worker...")
time.sleep(10)
logging.info(f"Wallapop monitor worker stopped for: \'{product['product_name']}\'")
logging.info(f"Wallapop monitor worker stopped for: \'{product['product_name']}\'")