Ejemplo n.º 1
0
    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")
Ejemplo n.º 2
0
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]]))
Ejemplo n.º 3
0
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]]))
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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]]))
Ejemplo n.º 6
0
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!")
Ejemplo n.º 7
0
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)