import re from aiogram import types from aiogram.dispatcher import filters, FSMContext from app.models import Product, ShoppingList, ShoppingListToProduct from app.misc import dp from app.states.state_ingredients import IngredientsForRecipe @dp.callback_query_handler(filters.Regexp(r'select_all_product_for_recipe'), state=IngredientsForRecipe.ingredients) async def select_all_product_for_recipe(query: types.CallbackQuery, state: FSMContext): async with state.proxy() as st: name = re.match(r'select_all_product_for_recipe', query.data).groups() products = await Product.query.where( Product.user_id == query.from_user.id).gino.all() shopping_list_product_connections = await ShoppingList \ .join(ShoppingListToProduct, ShoppingListToProduct.shopping_list_id == ShoppingList.id) \ .select(ShoppingList.user_id == query.from_user.id) \ .gino.all() shopping_list_product_ids = [ data[3] for data in shopping_list_product_connections ] products = list( filter(lambda item: item.id not in shopping_list_product_ids, products)) if len(st.get("ingredients", [])) == 0: st["ingredients"] = [] for prod in products:
import re from aiogram import types from aiogram.dispatcher import filters, FSMContext from app.misc import dp, bot from app.states import IngredientsForRecipe @dp.callback_query_handler(filters.Regexp(r'(\d*)_kcal'), state=IngredientsForRecipe.kcal) async def calories_filter_handler(query: types.CallbackQuery, state: FSMContext): groups = re.match(r'(\d*)_kcal', query.data).groups() async with state.proxy() as kcal: kcal['kcal'] = groups[0] await IngredientsForRecipe.previous() await query.answer() await bot.delete_message(query.from_user.id, query.message.message_id)
import re from typing import List from aiogram import types from aiogram.dispatcher import filters, FSMContext from app.keyboards.inline.recipes_keyboard import RecipesListKeyboard from app.misc import dp, bot from app.recipe_parser.parser import ParserHelper, Parser from app.recipe_parser.recipe_models import Recipe from app.states.state_ingredients import IngredientsForRecipe @dp.callback_query_handler(filters.Regexp(r'find_recipe'), state=IngredientsForRecipe.ingredients) async def find_recipe(query: types.CallbackQuery, state: FSMContext): await IngredientsForRecipe.next() await IngredientsForRecipe.next() f = True async with state.proxy() as ingredients: await query.answer("Ищем рецепты...") ingredients_list = ingredients['ingredients'] helper = ParserHelper(ingredients_list) search_url = await helper.get_search_string() parser = Parser(search_url) recipes_list: List = parser.get_recipes() if not ingredients.get("kcal", None): ingredients['recipes'] = recipes_list else: ingredients['recipes'] = [ i for i in recipes_list
import re from aiogram import types from aiogram.dispatcher import filters, FSMContext from loguru import logger from app.keyboards.inline.product_list_keyboard import ProductListKeyboard from app.keyboards.inline.recipe_product_list_keyboard import RecipeProductListKeyboard from app.misc import dp, bot from app.models import Product, ShoppingList, ShoppingListToProduct, User from app.states import IngredientsForRecipe @dp.callback_query_handler( filters.Regexp(r'(previous_page|next_page)_recipe_(\d*)'), state=IngredientsForRecipe.ingredients) async def page_callback_handler(query: types.CallbackQuery, state: FSMContext): groups = re.match(r'(previous_page|next_page)_recipe_(\d*)', query.data).groups() new_page = 0 if groups[0] == 'previous_page': new_page = int(groups[1]) - 1 elif groups[0] == 'next_page': new_page = int(groups[1]) + 1 logger.info(f"Next page: {new_page}") products = await Product.query.where(Product.user_id == query.from_user.id ).gino.all() shopping_list_product_connections = await ShoppingList \ .join(ShoppingListToProduct, ShoppingListToProduct.shopping_list_id == ShoppingList.id) \
from datetime import datetime, timedelta from aiogram import types from aiogram.dispatcher import filters from app.misc import dp, bot from app.keyboards.inline.automatic_setting_of_the_purchase_date_keyboard import \ AutomaticSettingOfThePurchaseDateListKeyboard from app.keyboards.inline.default_list_of_products_keyboard import DefaultListOfProductsListKeyboard from app.models import Product, UserSettings @dp.callback_query_handler( filters.Regexp(r'other_(default_list_of_products|auto_set_purchase_date)')) async def other_settings_callback_handler(query: types.CallbackQuery): groups = re.match( r'other_(default_list_of_products|auto_set_purchase_date)', query.data).groups() source = groups[0] if source == 'auto_set_purchase_date': await bot.edit_message_text( 'Настройка автоматической выставления даты:', query.from_user.id, query.message.message_id, reply_markup=AutomaticSettingOfThePurchaseDateListKeyboard.create( )) elif source == 'default_list_of_products': await bot.edit_message_text( 'Настройка дефолтного списка покупок:',
if not match: await message.answer(_("Wrong invoice link.")) return product_index, product_filters, product_size = match.groups() await answer_product_invoice( message, state, locale, int(product_index), ProductFilters(product_filters), int(product_size), ) @dp.callback_query_handler(filters.Regexp(rf"list_sizes:{PRODUCT_REGEX}"), state=any_state) @handle_product_params async def list_product_sizes( callback_query: types.CallbackQuery, *, state: FSMContext, handled_params: tuple, locale: str, **kwargs, ) -> None: product_index, product_filters = handled_params product = await get_product(state, product_index, product_filters) await callback_query.message.reply( emojize(_(":shoe: Choose shoe size")), reply_markup=get_product_sizes_keyboard(product, product_index,
def edit_info_product_message(name: str, exp_date: datetime, bought_date: datetime, info: str): bubble = f'Продукт:\n{name}\n' if exp_date is not None: e = parse(str(exp_date)).strftime('%d.%m.%Y') bubble += f'Срок годности: до {e}\n' if bought_date is not None: b = parse(str(bought_date)).strftime('%d.%m.%Y') bubble += f'Дата покупки: {b}\n' bubble += info if info else '' bubble += 'Что изменить?' return bubble @dp.callback_query_handler(filters.Regexp(r'change_(\d+)')) async def edit_callback_handler(query: types.CallbackQuery): groups = re.match(r'change_(\d*)', query.data).groups() product = await Product.query.where(Product.id == int(groups[0]) ).gino.first() await bot.send_message( query.from_user.id, "Что изменить?", reply_markup=ChangeInfoAboutProductKeyboard.create(product)) await query.answer() @dp.callback_query_handler(filters.Regexp(r'change_name_(\d+)')) async def change_name_callback_handler(query: types.CallbackQuery): groups = re.match(r'change_name_(\d+)', query.data).groups() ChangeProductState.id = groups[0]
import re from aiogram import types from aiogram.dispatcher import filters from app.misc import dp, bot from app.models import Product, ShoppingList, ShoppingListToProduct @dp.callback_query_handler(filters.Regexp(r'add_to_shop_list_(\d*)')) async def add_to_shop_list_from_fridge(query: types.CallbackQuery): groups = re.match(r'add_to_shop_list_(\d*)', query.data).groups() product = await Product.query.where(Product.id == int(groups[0]) ).gino.first() shop_list = await ShoppingList.query.where( ShoppingList.user_id == query.from_user.id).gino.first() new_product = await Product.create(user_id=query.from_user.id, name=product.name, info=None) await ShoppingListToProduct.create(product_id=new_product.id, shopping_list_id=shop_list.id) await bot.send_message(query.from_user.id, "Продукт добавлен в список покупок") await query.answer()
from typing import Match from aiogram import types from aiogram.dispatcher import FSMContext, filters from aiogram.dispatcher.filters.state import any_state from aiogram.utils.exceptions import Throttled from ..bot import _, dp # type: ignore from ..product_answers import get_bookmark_answer, get_product, get_product_slide_answer from .common import PRODUCT_REGEX, answer_product_slide, handle_product_params logger = logging.getLogger(__name__) @dp.callback_query_handler( filters.Regexp(rf"controls:(?:previous|next):{PRODUCT_REGEX}"), state=any_state ) @handle_product_params async def process_browse_controls( callback_query: types.CallbackQuery, *, state: FSMContext, handled_params: tuple, locale: str, **kwargs, ) -> None: next_product_index, product_filters = handled_params product_slide = await get_product_slide_answer( state, locale, next_product_index, product_filters ) await answer_product_slide(
import re from aiogram import types from aiogram.dispatcher import filters from app.keyboards.inline.delete_product_keyboard import ConfirmDeleteProductKeyboard from app.misc import dp, bot from app.models import Product def delete_product_confirm_message(name: str): return f'Вы действительно хотите удалить продукт "{name}"?' @dp.callback_query_handler(filters.Regexp(r'delete_(\d+)')) async def delete_confirm_callback_handler(query: types.CallbackQuery): groups = re.match(r'delete_(\d*)', query.data).groups() product = await Product.query.where(Product.id == int(groups[0]) ).gino.first() await bot.send_message(query.from_user.id, delete_product_confirm_message(product.name), reply_markup=ConfirmDeleteProductKeyboard.create( product, query.message.message_id)) await query.answer() @dp.callback_query_handler(filters.Regexp(r'delete_yes_(\d+)_(\d+)')) async def delete_yes_callback_handler(query: types.CallbackQuery): groups = re.match(r'delete_yes_(\d+)_(\d+)', query.data).groups()
from app.keyboards.inline.product_keyboard import ProductKeyboard from app.misc import dp, bot from app.models import Product from dateutil.parser import parse def create_info_product_message(name: str, exp_date: datetime, bought_date: datetime, info: str): bubble = f'{name}\n' if exp_date is not None: e = parse(str(exp_date)).strftime('%d.%m.%Y') bubble += f'Срок годности: до {e}\n' if bought_date is not None: b = parse(str(bought_date)).strftime('%d.%m.%Y') bubble += f'Дата покупки: {b}\n' bubble += info if info else '' return bubble @dp.callback_query_handler(filters.Regexp(r'show_(fridge|shopping_list)_(\d*)')) async def handler_product_button(query: types.CallbackQuery): groups = re.match(r'show_(fridge|shopping_list)_(\d*)', query.data).groups() product = await Product.query.where(Product.id == int(groups[1])).gino.first() if groups[0] == 'fridge': await bot.send_message(query.from_user.id, create_info_product_message(product.name, product.expiration_date, product.bought_date, product.info), reply_markup=ProductKeyboard.create(product)) elif groups[0] == 'shopping_list': await bot.send_message(query.from_user.id, create_info_product_message(product.name, product.expiration_date, product.bought_date, product.info), reply_markup=ShoppingListProductInfoKeyboard.create(product)) await query.answer()
import re from aiogram import types from aiogram.dispatcher import filters from loguru import logger from app.keyboards.inline.product_list_keyboard import ProductListKeyboard from app.keyboards.inline.recipe_product_list_keyboard import RecipeProductListKeyboard from app.misc import dp, bot from app.models import Product, ShoppingList, ShoppingListToProduct, User @dp.callback_query_handler( filters.Regexp(r'(previous_page|next_page)_(fridge|shopping_list)_(\d*)')) async def page_callback_handler(query: types.CallbackQuery): groups = re.match( r'(previous_page|next_page)_(fridge|shopping_list)_(\d*)', query.data).groups() new_page = 0 if groups[0] == 'previous_page': new_page = int(groups[2]) - 1 elif groups[0] == 'next_page': new_page = int(groups[2]) + 1 source = groups[1] logger.info(f"Source: {source}") logger.info(f"Next page: {new_page}") keyboard = None products = None if source == 'fridge':
import re from aiogram import types from aiogram.dispatcher import filters from app.keyboards.inline.add_product_method import AddProductMethod from app.misc import dp, bot @dp.callback_query_handler(filters.Regexp(r'add_to_(fridge|shopping_list)')) async def add_to_callback_handler(query: types.CallbackQuery): info = re.findall(r'(fridge|shopping_list)', query.data) await bot.send_message(query.from_user.id, "Выберите тип добавления продукта", reply_markup=AddProductMethod.create( info, query.message.message_id)) await query.answer()
await answer_next_filter_or_results(callback_query.message, state, locale, next_filter) await callback_query.answer() @dp.callback_query_handler(filters.Text(r"filter:skip_all"), state=ProductFiltersForm.all_states) async def process_filter_skip_all(callback_query: types.CallbackQuery, state: FSMContext, locale: str) -> None: # None state finishes the filtering await answer_next_filter_or_results(callback_query.message, state, locale, None) await callback_query.answer() @dp.callback_query_handler(filters.Regexp(r"filter:choice:(\w+):(\w+)"), state=ProductFiltersForm.all_states) @handle_regex_params(None, None) async def process_filter_choice( callback_query: types.CallbackQuery, *, state: FSMContext, locale: str, handled_params: tuple, **kwargs, ) -> None: filter_name, query_value = handled_params logger.debug("Filter name: %s. Filter query value: %s", filter_name, query_value) store_name = settings.PRODUCT_FILTERS[filter_name].query_name or filter_name
import re from aiogram import types from aiogram.dispatcher import filters, FSMContext from app.misc import dp from app.states.state_ingredients import IngredientsForRecipe @dp.callback_query_handler(filters.Regexp(r'add_to_recipe_(\w*)'), state=IngredientsForRecipe.ingredients) async def add_to_recipe(query: types.CallbackQuery, state: FSMContext): name = re.match(r'add_to_recipe_(\w*)', query.data).groups() await query.answer() async with state.proxy() as ingredients: if len(ingredients.get("ingredients", [])) == 0: ingredients["ingredients"] = [] ingredients["ingredients"].append(name[0])
from aiogram import types from aiogram.dispatcher import filters, FSMContext from app.keyboards.inline.calories_keyboard import CaloriesKeyboard from app.misc import dp, bot from app.states import IngredientsForRecipe @dp.callback_query_handler(filters.Regexp(r'calories_keyboard'),state=IngredientsForRecipe.ingredients) async def calories_keyboard_handler(query: types.CallbackQuery,state: FSMContext): await IngredientsForRecipe.next() await bot.send_message(query.from_user.id,'Выберите максимальноее число ккал в 100 гр блюда',reply_markup=CaloriesKeyboard.create()) await query.answer()
async def noticker_on_yahoo(message: types.Message): return await message.reply("Ticker not found", reply_markup=kb.cancel_kb) """ Setting amount """ @dp.message_handler(state=PaperFSM.ticker) async def paper_setticker_getamount(message: types.Message, state: FSMContext): new_paper.ticker = message.text.upper() new_paper.get_yahoo() # Load data from yahoo to fetch currency await PaperFSM.next() await bot.send_message(message.chat.id, "Enter amount of papers", reply_markup=kb.cancel_kb) """ Setting price """ @dp.message_handler(filters.Regexp(regexp='^-?\d+(?:\.\d+)?$'), state=PaperFSM.amount) async def paper_setamount_getprice(message: types.Message, state: FSMContext): new_paper.amount = int(message.text) await PaperFSM.next() await bot.send_message(message.chat.id, "Enter price of papers", reply_markup=kb.cancel_kb) """ Finish FSM, save object to DB """ @dp.message_handler(state=PaperFSM.price) async def portfolio_setprice_finishmachine(message: types.Message, state: FSMContext): new_paper.price = float(message.text) new_paper.margin = query.fetch('portfolios', ['margin'], id=new_paper.portfolio_id)[0]['margin'] new_paper.set_commission() new_paper.add_transaction(new_paper.amount, new_paper.price, new_paper.commission) new_paper.save()
from aiogram import types from aiogram.dispatcher import filters from utils.database.api import get_rhash from loader import dp REGULAR_LINK_REGEX = "^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?(?!t\.me)([a-z0-9])+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$" @dp.message_handler(filters.Regexp(regexp=REGULAR_LINK_REGEX)) async def bot_link_format(message: types.Message): domain_name = message.text.split("//")[1].split("/")[0].replace('www.', '') rhash = get_rhash(user_id=message.from_user.id, domain_name=domain_name) if rhash: await message.answer(f"[](https://t.me/iv?url={message.text}&rhash={rhash}){message.text}", parse_mode="Markdown") await message.answer(f"[](https://t.me/iv?url={message.text}&rhash={rhash})", parse_mode="Markdown", disable_web_page_preview=True) else: await message.answer(f"You don't have Template for your domain {domain_name}")
import datetime import re from aiogram import types from aiogram.dispatcher import filters from app.misc import dp, bot from app.models import Product, ShoppingListToProduct @dp.callback_query_handler(filters.Regexp(r'buy_(\d*)')) async def buy_product(query: types.CallbackQuery): groups = re.match(r'buy_(\d*)', query.data).groups() product = await Product.query.where(Product.id == int(groups[0]) ).gino.first() await ShoppingListToProduct.delete.where( product.id == ShoppingListToProduct.product_id).gino.status() await product.update(bought_date=datetime.datetime.now()).apply() await bot.delete_message(query.from_user.id, query.message.message_id) await bot.send_message( query.from_user.id, f"Продукт \"{product.name}\" добавлен в ваш холодильник") await query.answer()
import re from aiogram import types from aiogram.dispatcher import filters from app.keyboards.inline.delete_product_keyboard import ConfirmDeleteProductKeyboard from app.misc import dp, bot from app.models import Product def delete_product_confirm_message(name: str): return f'Вы действительно хотите удалить продукт "{name}" из списка покупок?' @dp.callback_query_handler(filters.Regexp(r'delete_from_shopping_list_(\d*)')) async def delete_confirm_callback_handler(query: types.CallbackQuery): groups = re.match(r'delete_from_shopping_list_(\d*)', query.data).groups() product = await Product.query.where(Product.id == int(groups[0])).gino.first() await bot.send_message(query.from_user.id, delete_product_confirm_message(product.name), reply_markup=ConfirmDeleteProductKeyboard.create(product, query.message.message_id)) await query.answer() @dp.callback_query_handler(filters.Regexp(r'delete_yes_(\d+)_(\d+)')) async def delete_yes_callback_handler(query: types.CallbackQuery): groups = re.match(r'delete_yes_(\d+)_(\d+)', query.data).groups() await Product.delete.where(Product.id == int(groups[0])).gino.status()
from aiogram.dispatcher import filters, FSMContext from app.misc import dp, bot from app.recipe_parser.parser import Parser from app.recipe_parser.recipe_models import RecipeDetails from app.states import IngredientsForRecipe def recipe_details_helper(rd: RecipeDetails): # steps = rd.instructions ingredients = ", ".join(map(lambda x: str(x), rd.ingredients)) if rd.instructions is None: steps = '\n'.join(rd.steps) return f'{rd.name}\n\nКБЖУ: {rd.weight} гр - {rd.PFC}\nВремя приготовления {rd.cooking_time}\n\nДля {rd.portions_count} порций: {ingredients}\n\n{steps}' return f'{rd.name}\n\nКБЖУ: {rd.weight} гр - {rd.PFC}\nВремя приготовления {rd.cooking_time}\n\nДля {rd.portions_count} порций: {ingredients}\n\n{rd.instructions}' @dp.callback_query_handler(filters.Regexp(r'select_recipe_([0-9a-f]{32}\Z)'), state=IngredientsForRecipe.recipes) async def select_recipe(query: types.CallbackQuery, state: FSMContext): recipe_id = re.match(r'select_recipe_([0-9a-f]{32}\Z)', query.data).groups() async with state.proxy() as list_recipes: recipes = list_recipes['recipes'] recipe = next((x for x in recipes if x.id == recipe_id[0]), None) recipe_details = await Parser.get_recipe_details(recipe) await bot.send_message(query.from_user.id, recipe_details_helper(recipe_details)) await state.finish() await query.answer()
import re from aiogram import types from aiogram.dispatcher import filters, FSMContext from app.keyboards.inline.recipes_keyboard import RecipesListKeyboard from app.misc import dp, bot from app.states import IngredientsForRecipe @dp.callback_query_handler( filters.Regexp(r'(previous|next)_page_recipes_(\d+)'), state=IngredientsForRecipe.recipes) async def change_page_recipe(query: types.CallbackQuery, state: FSMContext): groups = re.match(r'(previous|next)_page_recipes_(\d+)', query.data).groups() new_page = 0 if groups[0] == 'previous': new_page = int(groups[1]) - 1 elif groups[0] == 'next': new_page = int(groups[1]) + 1 async with state.proxy() as recipes: await bot.edit_message_reply_markup( query.from_user.id, query.message.message_id, reply_markup=RecipesListKeyboard.create(recipes['recipes'], new_page)) await query.answer()
from aiogram import types from aiogram.dispatcher import filters from urllib.parse import urlsplit, parse_qs, unquote from utils.database.api import add_domain from loader import dp IV_LINK_REGEX = "^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?t\.me(\/.*rhash=.*)$" BROKEN_IV_LINK_REGEX = "^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?t\.me(\/*.*)$" @dp.message_handler(filters.Regexp(regexp=IV_LINK_REGEX)) async def bot_link_telegram(message: types.Message): iv_link = unquote(message.text) iv_link_query = urlsplit(iv_link).query iv_link_params = parse_qs(iv_link_query) iv_link_params_dict = { param: value[0] for param, value in iv_link_params.items() } try: domain_name = iv_link_params_dict['url'].split("//")[-1].split( "/")[0].replace('www.', '') rhash = iv_link_params_dict['rhash'] add_domain(user_id=message.from_user.id, domain_name=domain_name, rhash=rhash)
async def add_product_photo_check_shoplist_handler(query: types.CallbackQuery): await ShoppingAddPhotoCheckState.name.set() await bot.send_message(query.message.chat.id, "Отправьте фото чека в хорошем качестве (без лишних предметов и надписей):") await query.answer('Распознаю продукты...') @dp.callback_query_handler(filters.Text('add_product_photo_[\'fridge\']')) async def add_product_photo_fridge_handler(query: types.CallbackQuery): await FridgeAddPhotoState.name.set() await bot.send_message(query.message.chat.id, "Отправьте фото продукта/этикетки в хорошем качестве (без лишних предметов и надписей):") await query.answer('Распознаю продукт...') @dp.callback_query_handler(filters.Regexp(r'add_product_photo_name_ok_\[\'fridge\']\+.*')) async def add_product_photo_fridge_nameok_handler(query: types.CallbackQuery, state: FSMContext): name = re.findall(r'[^+]*$', query.data)[0] async with state.proxy() as data: data['name'] = name await FridgeProductState.expiration_date.set() await bot.send_message(query.message.chat.id, 'Введите срок годности продукта (пропустить - /skip, пропустить остальные шаги /skipall)') await query.answer() @dp.callback_query_handler(filters.Text('add_product_photo_[\'shopping_list\']')) async def add_product_photo_shoplist_handler(query: types.CallbackQuery): await ShoppingAddPhotoState.name.set() await bot.send_message(query.message.chat.id, "Отправьте фото продукта/этикетки в хорошем качестве (без лишних предметов и надписей):") await query.answer('Распознаю продукт...')