def test_price_unsigned(self): price_pos = 1.752221 price_neg = -1.82111 self.assertEqual(formatter.price(price_pos, False), "1.75 €", msg="Positive price not displayed correctly") self.assertEqual(formatter.price(price_neg, False), "-1.82 €", msg="Negative price not displayed correctly")
def add_entity(update, context): msg = update.message text = update.message.text t_user = update.effective_user logger.info("Adding new entity for user '{}'".format(t_user.id)) reply_markup = InlineKeyboardMarkup([[cancel_button]]) user = User(user_id=t_user.id, first_name=t_user.first_name, last_name=t_user.last_name, username=t_user.username, lang_code=t_user.language_code) core.add_user_if_new(user) try: entity_type = core.get_type_by_url(text) url = core.get_e_url(text, entity_type) logger.info("Valid URL for new entity is '{}'".format(url)) except InvalidURLException: logger.warning("Invalid url '{}' sent by user {}!".format(text, t_user)) msg.reply_text(text="Die URL ist ungültig!", reply_markup=reply_markup) return try: if entity_type == EntityType.WISHLIST: entity = Wishlist.from_url(url) elif entity_type == EntityType.PRODUCT: entity = Product.from_url(url) else: raise ValueError("EntityType '{}' not found!".format(entity_type)) except HTTPError as e: logger.error(e) if e.response.status_code == 403: msg.reply_text(text="Die URL ist nicht öffentlich einsehbar, daher wurde kein neuer Preisagent erstellt!") elif e.response.status_code == 429: msg.reply_text(text="Entschuldige, ich bin temporär bei Geizhals blockiert und kann keine Preise auslesen. Bitte probiere es später noch einmal.") except (ValueError, Exception) as e: # Raised when price could not be parsed logger.error(e) msg.reply_text(text="Name oder Preis konnte nicht ausgelesen werden! Preisagent wurde nicht erstellt!") else: core.add_entity_if_new(entity) try: logger.debug("Subscribing to entity.") core.subscribe_entity(user, entity) entity_data = EntityType.get_type_article_name(entity_type) msg.reply_html("Preisagent für {article} {type} {link_name} erstellt! Aktueller Preis: {price}".format( article=entity_data.get("article"), type=entity_data.get("name"), link_name=link(entity.url, entity.name), price=bold(price(entity.price, signed=False))), disable_web_page_preview=True) context.user_data["state"] = State.IDLE except AlreadySubscribedException: logger.debug("User already subscribed!") msg.reply_text("Du hast bereits einen Preisagenten für diese URL! Bitte sende mir eine andere URL.", reply_markup=InlineKeyboardMarkup([[cancel_button]]))
def add_product(bot, update): text = update.message.text user = update.message.from_user logger.info("Adding new product for user '{}'".format(user.id)) reply_markup = InlineKeyboardMarkup([[cancel_button]]) add_user_if_new(user) try: url = get_p_url(text) logger.info("Valid URL for new product is '{}'".format(url)) except InvalidURLException: logger.warning("Invalid url '{}' sent by user {}!".format(text, user)) bot.sendMessage(chat_id=user.id, text="Die URL ist ungültig!", reply_markup=reply_markup) return try: product = Product.from_url(url) except HTTPError as e: logger.error(e) if e.code == 403: bot.sendMessage(chat_id=user.id, text="Das Produkt ist nicht zugänglich! Preisagent wurde nicht erstellt!") elif e.code == 429: bot.sendMessage(chat_id=user.id, text="Entschuldige, ich bin temporär bei Geizhals blockiert und kann keine Preise auslesen. Bitte probiere es später noch einmal.") except ValueError as valueError: # Raised when price could not be parsed logger.error(valueError) bot.sendMessage(chat_id=user.id, text="Name oder Preis konnte nicht ausgelesen werden! Preisagent wurde nicht erstellt!") except Exception as e: logger.error(e) bot.sendMessage(chat_id=user.id, text="Name oder Preis konnte nicht ausgelesen werden! Wunschliste nicht erstellt!") else: add_product_if_new(product) try: logger.debug("Subscribing to product.") subscribe_entity(user, product) bot.sendMessage(user.id, "Preisagent für das Produkt {link_name} erstellt! Aktueller Preis: {price}".format( link_name=link(product.url, product.name), price=bold(price(product.price, signed=False))), parse_mode="HTML", disable_web_page_preview=True) rm_state(user.id) except AlreadySubscribedException: logger.debug("User already subscribed!") bot.sendMessage(user.id, "Du hast bereits einen Preisagenten für dieses Produkt! Bitte sende mir eine andere URL.", reply_markup=InlineKeyboardMarkup([[cancel_button]]))
def notify_user(bot, user_id, entity, old_price): """Notify a user of price changes""" diff = entity.price - old_price if diff > 0: emoji = "📈" change = "teurer" else: emoji = "📉" change = "billiger" logger.info("Notifying user {}!".format(user_id)) message = "Der Preis von {link_name} hat sich geändert: {price}\n\n" \ "{emoji} {diff} {change}".format(link_name=link(entity.url, entity.name), price=bold(price(entity.price, signed=False)), emoji=emoji, diff=bold(price(diff)), change=change) bot.sendMessage(user_id, message, parse_mode=ParseMode.HTML, disable_web_page_preview=True)
def add_wishlist(bot, update): text = update.message.text user = update.message.from_user reply_markup = InlineKeyboardMarkup([[cancel_button]]) add_user_if_new(user) try: url = get_wl_url(text) except InvalidURLException: logger.debug("Invalid url '{}'!".format(text)) bot.sendMessage(chat_id=user.id, text="Die URL ist ungültig!", reply_markup=reply_markup) return # Check if website is parsable! try: wishlist = Wishlist.from_url(url) except HTTPError as e: logger.error(e) if e.code == 403: bot.sendMessage(chat_id=user.id, text="Wunschliste ist nicht öffentlich! Wunschliste nicht hinzugefügt!") elif e.code == 429: bot.sendMessage(chat_id=user.id, text="Entschuldige, ich bin temporär bei Geizhals blockiert und kann keine Preise auslesen. Bitte probiere es später noch einmal.") except ValueError as valueError: # Raised when price could not be parsed logger.error(valueError) bot.sendMessage(chat_id=user.id, text="Name oder Preis konnte nicht ausgelesen werden! Preisagent wurde nicht erstellt!") except Exception as e: logger.error(e) bot.sendMessage(chat_id=user.id, text="Name oder Preis konnte nicht ausgelesen werden! Preisagent wurde nicht erstellt!") else: add_wishlist_if_new(wishlist) try: logger.debug("Subscribing to wishlist.") subscribe_entity(user, wishlist) bot.sendMessage(user.id, "Preisagent für die Wunschliste {link_name} erstellt! Aktueller Preis: {price}".format( link_name=link(wishlist.url, wishlist.name), price=bold(price(wishlist.price, signed=False))), parse_mode="HTML", disable_web_page_preview=True) rm_state(user.id) except AlreadySubscribedException as ase: logger.debug("User already subscribed!") bot.sendMessage(user.id, "Du hast bereits einen Preisagenten für diese Wunschliste! Bitte sende mir eine andere URL.", reply_markup=InlineKeyboardMarkup([[cancel_button]]))
def pa_detail_handler(update, context): """Handler for the price agent detail menu""" cbq = update.callback_query user_id = cbq.from_user.id menu, action, entity_id, entity_type_str = cbq.data.split("_") entity_type = EntityType(int(entity_type_str)) entity = core.get_entity(entity_id, entity_type) user = core.get_user_by_id(user_id) if action == "show": cbq.edit_message_text(text="{link_name} kostet aktuell {price}".format( link_name=link(entity.url, entity.name), price=bold(price(entity.price, signed=False))), reply_markup=get_entity_keyboard(entity.TYPE, entity.entity_id), parse_mode=ParseMode.HTML, disable_web_page_preview=True) cbq.answer() elif action == "delete": core.unsubscribe_entity(user, entity) callback_data = 'm04_subscribe_{id}_{type}'.format(id=entity.entity_id, type=entity.TYPE.value) keyboard = [[InlineKeyboardButton("Rückgängig", callback_data=callback_data)]] reply_markup = InlineKeyboardMarkup(keyboard) text = "Preisagent für '{0}' wurde gelöscht!".format(link(entity.url, entity.name)) cbq.edit_message_text(text=text, reply_markup=reply_markup, parse_mode=ParseMode.HTML, disable_web_page_preview=True) cbq.answer(text="Preisagent für wurde gelöscht!") elif action == "subscribe": entity_info = EntityType.get_type_article_name(entity.TYPE) try: core.subscribe_entity(user, entity) text = "Du hast {article} {entity_name} {link_name} erneut abboniert!".format( article=entity_info.get("article"), entity_name=entity_info.get("name"), link_name=link(entity.url, entity.name)) cbq.edit_message_text(text=text, parse_mode=ParseMode.HTML, disable_web_page_preview=True) cbq.answer(text="{} erneut abboniert".format(entity_info.get("name"))) except AlreadySubscribedException: text = "{} bereits abboniert!".format(entity_info.get("name")) cbq.edit_message_text(text=text, parse_mode=ParseMode.HTML, disable_web_page_preview=True) cbq.answer(text=text) elif action == "history": entity_price_history(update, context) else: logger.warning("A user tried to use an unimplemented method: '{}'".format(action)) cbq.answer(text="Die gewählte Funktion ist noch nicht implementiert!")
def callback_handler_f(bot, update): user_id = update.callback_query.from_user.id message_id = update.callback_query.message.message_id callback_query_id = update.callback_query.id user = get_user_by_id(user_id) if user is None: return data = update.callback_query.data if "_" in data: # TODO Input validation! action, entity_id, entity_type_value = data.split("_") entity_type = EntityType(int(entity_type_value)) else: action = data entity_id = None entity_type = None if entity_id: """Check if it's just a command or if an ID/type is passed""" if entity_type == EntityType.WISHLIST: wishlist_id = entity_id try: wishlist = get_wishlist(wishlist_id) except WishlistNotFoundException: invalid_wl_text = "Die Wunschliste existiert nicht!" bot.answerCallbackQuery(callback_query_id=callback_query_id, text=invalid_wl_text) bot.editMessageText(chat_id=user_id, message_id=message_id, text=invalid_wl_text) return if action == "delete": unsubscribe_entity(user, wishlist) callback_data = 'subscribe_{id}_{type}'.format(id=wishlist_id, type=EntityType.WISHLIST.value) keyboard = [ [InlineKeyboardButton("Rückgängig", callback_data=callback_data)]] reply_markup = InlineKeyboardMarkup(keyboard) bot.editMessageText(chat_id=user_id, message_id=message_id, text="Preisagent für die Wunschliste {link_name} wurde gelöscht!".format( link_name=link(wishlist.url, wishlist.name)), reply_markup=reply_markup, parse_mode="HTML", disable_web_page_preview=True) bot.answerCallbackQuery(callback_query_id=callback_query_id, text="Preisagent für die Wunschliste wurde gelöscht!") elif action == "show": bot.editMessageText(chat_id=user_id, message_id=message_id, text="Die Wunschliste {link_name} kostet aktuell {price}".format( link_name=link(wishlist.url, wishlist.name), price=bold(price(wishlist.price, signed=False))), reply_markup=get_entity_keyboard(EntityType.WISHLIST, wishlist.id, "showWishlists"), parse_mode="HTML", disable_web_page_preview=True) bot.answerCallbackQuery(callback_query_id=callback_query_id) elif action == "subscribe": try: subscribe_entity(user, wishlist) text = "Du hast die Wunschliste {link_name} erneut abboniert!".format( link_name=link(wishlist.url, wishlist.name)) bot.editMessageText(chat_id=user_id, message_id=message_id, text=text, parse_mode="HTML", disable_web_page_preview=True) bot.answerCallbackQuery(callback_query_id=callback_query_id, text="Wunschliste erneut abboniert") except AlreadySubscribedException: text = "Wunschliste bereits abboniert!" bot.editMessageText(chat_id=user_id, message_id=message_id, text=text, parse_mode="HTML", disable_web_page_preview=True) bot.answerCallbackQuery(callback_query_id=callback_query_id, text=text) elif entity_type == EntityType.PRODUCT: product_id = entity_id try: product = get_product(product_id) except ProductNotFoundException: invalid_p_text = "Das Produkt existiert nicht!" bot.answerCallbackQuery(callback_query_id=callback_query_id, text=invalid_p_text) bot.editMessageText(chat_id=user_id, message_id=message_id, text=invalid_p_text) return if action == "delete": unsubscribe_entity(user, product) callback_data = 'subscribe_{id}_{type}'.format(id=product_id, type=EntityType.PRODUCT.value) keyboard = [[InlineKeyboardButton("Rückgängig", callback_data=callback_data)]] reply_markup = InlineKeyboardMarkup(keyboard) bot.editMessageText(chat_id=user_id, message_id=message_id, text="Preisagent für das Produkt {link_name} wurde gelöscht!".format( link_name=link(product.url, product.name)), reply_markup=reply_markup, parse_mode="HTML", disable_web_page_preview=True) bot.answerCallbackQuery(callback_query_id=callback_query_id, text="Preisagent für das Produkt wurde gelöscht!") elif action == "show": bot.editMessageText(chat_id=user_id, message_id=message_id, text="Das Produkt {link_name} kostet aktuell {price}".format( link_name=link(product.url, product.name), price=bold(price(product.price, signed=False))), reply_markup=get_entity_keyboard(EntityType.PRODUCT, product.id, "showProducts"), parse_mode="HTML", disable_web_page_preview=True) bot.answerCallbackQuery(callback_query_id=callback_query_id) elif action == "subscribe": try: subscribe_entity(user, product) text = "Du hast das Produkt {link_name} erneut abboniert!".format( link_name=link(product.url, product.name)) bot.editMessageText(chat_id=user_id, message_id=message_id, text=text, parse_mode="HTML", disable_web_page_preview=True) bot.answerCallbackQuery(callback_query_id=callback_query_id, text="Produkt erneut abboniert") except AlreadySubscribedException: text = "Produkt bereits abboniert!" bot.editMessageText(chat_id=user_id, message_id=message_id, text=text, parse_mode="HTML", disable_web_page_preview=True) bot.answerCallbackQuery(callback_query_id=callback_query_id, text=text) elif action == "newPriceAgent": keyboard = [[InlineKeyboardButton("Wunschliste", callback_data='addWishlist'), InlineKeyboardButton("Produkt", callback_data='addProduct')]] bot.editMessageText(chat_id=user_id, message_id=message_id, text="Wofür möchtest du einen Preisagenten einrichten?", reply_markup=InlineKeyboardMarkup(keyboard)) elif action == "myPriceAgents": keyboard = [[InlineKeyboardButton("Wunschlisten", callback_data='showWishlists'), InlineKeyboardButton("Produkte", callback_data='showProducts')]] bot.editMessageText(chat_id=user_id, message_id=message_id, text="Welche Preisagenten möchtest du einsehen?", reply_markup=InlineKeyboardMarkup(keyboard)) elif action == "cancel": """Reset the user's state""" rm_state(user_id) text = "Okay, Ich habe die Aktion abgebrochen!" bot.editMessageText(chat_id=user_id, message_id=message_id, text=text) bot.answerCallbackQuery(callback_query_id=callback_query_id, text=text) elif action == "addWishlist": if get_wishlist_count(user_id) >= MAX_WISHLISTS: bot.editMessageText(chat_id=user_id, message_id=message_id, text="Du kannst zu maximal 5 Wunschlisten Benachrichtigungen bekommen. " "Entferne doch eine Wunschliste, die du nicht mehr benötigst.", reply_markup=get_entities_keyboard("delete", get_wishlists_for_user(user_id), prefix_text="❌ ", cancel=True)) return set_state(user_id, STATE_SEND_WL_LINK) bot.editMessageText(chat_id=user_id, message_id=message_id, text="Bitte sende mir eine URL einer Wunschliste!", reply_markup=InlineKeyboardMarkup([[cancel_button]])) bot.answerCallbackQuery(callback_query_id=callback_query_id) elif action == "addProduct": if get_product_count(user_id) >= MAX_PRODUCTS: bot.editMessageText(chat_id=user_id, message_id=message_id, text="Du kannst zu maximal 5 Wunschlisten Benachrichtigungen bekommen. " "Entferne doch eine Wunschliste, die du nicht mehr benötigst.", reply_markup=get_entities_keyboard("delete", get_products_for_user(user_id), prefix_text="❌ ", cancel=True)) return set_state(user_id, STATE_SEND_P_LINK) bot.editMessageText(chat_id=user_id, message_id=message_id, text="Bitte sende mir eine URL eines Produkts!", reply_markup=InlineKeyboardMarkup([[cancel_button]])) bot.answerCallbackQuery(callback_query_id=callback_query_id) elif action == "showWishlists": wishlists = get_wishlists_for_user(user_id) if len(wishlists) == 0: bot.editMessageText(chat_id=user_id, message_id=message_id, text="Du hast noch keinen Preisagenten für eine Wunschliste angelegt!") return keyboard = get_entities_keyboard("show", wishlists) bot.answerCallbackQuery(callback_query_id=callback_query_id) bot.editMessageText(chat_id=user_id, message_id=message_id, text="Das sind deine Preisagenten für deine Wunschlisten:", reply_markup=keyboard) elif action == "showProducts": products = get_products_for_user(user_id) if len(products) == 0: bot.editMessageText(chat_id=user_id, message_id=message_id, text="Du hast noch keinen Preisagenten für ein Produkt angelegt!") return keyboard = get_entities_keyboard("show", products) bot.editMessageText(chat_id=user_id, message_id=message_id, text="Das sind deine Preisagenten für deine Produkte:", reply_markup=keyboard)