From 37b152a4317a35b6e30b1df9eb3c7fa37a2d9bb8 Mon Sep 17 00:00:00 2001 From: krasi Date: Mon, 17 Jun 2024 10:44:18 +0300 Subject: [PATCH] 170600 --- bot-market/.idea/.gitignore | 3 + bot-market/.idea/bot-market.iml | 10 ++ .../inspectionProfiles/profiles_settings.xml | 6 ++ bot-market/.idea/misc.xml | 7 ++ bot-market/.idea/modules.xml | 8 ++ bot-market/app/admin.py | 94 ++++++++++++++++++ bot-market/app/database/models.py | 62 ++++++++++++ bot-market/app/database/requests.py | 64 ++++++++++++ bot-market/app/handlers.py | 72 ++++++++++++++ bot-market/app/keyboards.py | 49 +++++++++ bot-market/config.py | 3 + bot-market/run.py | 25 +++++ bot_data.db | Bin 0 -> 16384 bytes old/bot_klining.db | Bin 0 -> 28672 bytes 14 files changed, 403 insertions(+) create mode 100644 bot-market/.idea/.gitignore create mode 100644 bot-market/.idea/bot-market.iml create mode 100644 bot-market/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 bot-market/.idea/misc.xml create mode 100644 bot-market/.idea/modules.xml create mode 100644 bot-market/app/admin.py create mode 100644 bot-market/app/database/models.py create mode 100644 bot-market/app/database/requests.py create mode 100644 bot-market/app/handlers.py create mode 100644 bot-market/app/keyboards.py create mode 100644 bot-market/config.py create mode 100644 bot-market/run.py create mode 100644 bot_data.db create mode 100644 old/bot_klining.db diff --git a/bot-market/.idea/.gitignore b/bot-market/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/bot-market/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/bot-market/.idea/bot-market.iml b/bot-market/.idea/bot-market.iml new file mode 100644 index 0000000..2c80e12 --- /dev/null +++ b/bot-market/.idea/bot-market.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/bot-market/.idea/inspectionProfiles/profiles_settings.xml b/bot-market/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/bot-market/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/bot-market/.idea/misc.xml b/bot-market/.idea/misc.xml new file mode 100644 index 0000000..23bd63c --- /dev/null +++ b/bot-market/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/bot-market/.idea/modules.xml b/bot-market/.idea/modules.xml new file mode 100644 index 0000000..6c24722 --- /dev/null +++ b/bot-market/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/bot-market/app/admin.py b/bot-market/app/admin.py new file mode 100644 index 0000000..6566ee3 --- /dev/null +++ b/bot-market/app/admin.py @@ -0,0 +1,94 @@ +from aiogram import Router, F +from aiogram.types import Message, CallbackQuery +from aiogram.filters import CommandStart, Command, Filter +from aiogram.fsm.context import FSMContext +from aiogram.fsm.state import State, StatesGroup + +import app.keyboards as kb +from app.database.requests import get_users, set_item + +admin = Router() + + +class Newsletter(StatesGroup): + message = State() + + +class AddItem(StatesGroup): + name = State() + category = State() + description = State() + photo = State() + price = State() + + +class AdminProtect(Filter): + async def __call__(self, message: Message): + return message.from_user.id in [1477217831] + + +@admin.message(AdminProtect(), Command('apanel')) +async def apanel(message: Message): + await message.answer('Возможные команды: /newsletter\n/add_item') + + +@admin.message(AdminProtect(), Command('newsletter')) +async def newsletter(message: Message, state: FSMContext): + await state.set_state(Newsletter.message) + await message.answer('Отправьте сообщение, которое вы хотите разослать всем пользователям') + + +@admin.message(AdminProtect(), Newsletter.message) +async def newsletter_message(message: Message, state: FSMContext): + await message.answer('Подождите... идёт рассылка.') + for user in await get_users(): + try: + await message.send_copy(chat_id=user.tg_id) + except: + pass + await message.answer('Рассылка успешно завершена.') + await state.clear() + + +@admin.message(AdminProtect(), Command('add_item')) +async def add_item(message: Message, state: FSMContext): + await state.set_state(AddItem.name) + await message.answer('Введите название товара') + + +@admin.message(AdminProtect(), AddItem.name) +async def add_item_name(message: Message, state: FSMContext): + await state.update_data(name=message.text) + await state.set_state(AddItem.category) + await message.answer('Выберите категорию товара', reply_markup=await kb.categories()) + + +@admin.callback_query(AdminProtect(), AddItem.category) +async def add_item_category(callback: CallbackQuery, state: FSMContext): + await state.update_data(category=callback.data.split('_')[1]) + await state.set_state(AddItem.description) + await callback.answer('') + await callback.message.answer('Введите описание товара') + + +@admin.message(AdminProtect(), AddItem.description) +async def add_item_description(message: Message, state: FSMContext): + await state.update_data(description=message.text) + await state.set_state(AddItem.photo) + await message.answer('Отправьте фото товара') + + +@admin.message(AdminProtect(), AddItem.photo, F.photo) +async def add_item_photo(message: Message, state: FSMContext): + await state.update_data(photo=message.photo[-1].file_id) + await state.set_state(AddItem.price) + await message.answer('Введите цену товара') + + +@admin.message(AdminProtect(), AddItem.price) +async def add_item_price(message: Message, state: FSMContext): + await state.update_data(price=message.text) + data = await state.get_data() + await set_item(data) + await message.answer('Товар успешно добавлен') + await state.clear() \ No newline at end of file diff --git a/bot-market/app/database/models.py b/bot-market/app/database/models.py new file mode 100644 index 0000000..d527058 --- /dev/null +++ b/bot-market/app/database/models.py @@ -0,0 +1,62 @@ +from sqlalchemy import BigInteger, ForeignKey, String +from sqlalchemy.orm import Mapped, mapped_column, relationship, DeclarativeBase +from sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engine + +from typing import List +from config import ENGINE, ECHO + +engine = create_async_engine(url=ENGINE)#, echo=ECHO) + +async_session = async_sessionmaker(engine) + + +class Base(AsyncAttrs, DeclarativeBase): + pass + + +class User(Base): + __tablename__ = 'users' + + id: Mapped[int] = mapped_column(primary_key=True) + tg_id = mapped_column(BigInteger) + + basket_rel: Mapped[List['Basket']] = relationship(back_populates='user_rel') + + +class Category(Base): + __tablename__ = 'categories' + + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(String(50)) + + item_rel: Mapped[List['Item']] = relationship(back_populates='category_rel') + + +class Item(Base): + __tablename__ = 'items' + + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(String(50)) + description: Mapped[str] = mapped_column(String(200)) + photo: Mapped[str] = mapped_column(String(200)) + price: Mapped[int] = mapped_column() + category: Mapped[int] = mapped_column(ForeignKey('categories.id')) + + category_rel: Mapped['Category'] = relationship(back_populates='item_rel') + basket_rel: Mapped[List['Basket']] = relationship(back_populates='item_rel') + + +class Basket(Base): + __tablename__ = 'basket' + + id: Mapped[int] = mapped_column(primary_key=True) + user: Mapped[int] = mapped_column(ForeignKey('users.id')) + item: Mapped[int] = mapped_column(ForeignKey('items.id')) + + user_rel: Mapped['User'] = relationship(back_populates='basket_rel') + item_rel: Mapped['Item'] = relationship(back_populates='basket_rel') + + +async def async_main(): + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) \ No newline at end of file diff --git a/bot-market/app/database/requests.py b/bot-market/app/database/requests.py new file mode 100644 index 0000000..2897bd2 --- /dev/null +++ b/bot-market/app/database/requests.py @@ -0,0 +1,64 @@ +from app.database.models import User, Category, Item, Basket +from app.database.models import async_session + +from sqlalchemy import select, update, delete + + +async def set_user(tg_id): + async with async_session() as session: + user = await session.scalar(select(User).where(User.tg_id == tg_id)) + + if not user: + session.add(User(tg_id=tg_id)) + await session.commit() + + +async def set_item(data): + async with async_session() as session: + session.add(Item(**data)) + await session.commit() + + +async def set_basket(tg_id, item_id): + async with async_session() as session: + user = await session.scalar(select(User).where(User.tg_id == tg_id)) + session.add(Basket(user=user.id, item=item_id)) + await session.commit() + + +async def get_basket(tg_id): + async with async_session() as session: + user = await session.scalar(select(User).where(User.tg_id == tg_id)) + basket = await session.scalars(select(Basket).where(Basket.user == user.id)) + return basket + + +async def get_users(): + async with async_session() as session: + users = await session.scalars(select(User)) + return users + + +async def get_categories(): + async with async_session() as session: + categories = await session.scalars(select(Category)) + return categories + + +async def get_items_by_category(category_id: int): + async with async_session() as session: + items = await session.scalars(select(Item).where(Item.category == category_id)) + return items + + +async def get_item_by_id(item_id: int): + async with async_session() as session: + item = await session.scalar(select(Item).where(Item.id == item_id)) + return item + + +async def delete_basket(tg_id, item_id): + async with async_session() as session: + user = await session.scalar(select(User).where(User.tg_id == tg_id)) + await session.execute(delete(Basket).where(Basket.user == user.id, Basket.item == item_id)) + await session.commit() \ No newline at end of file diff --git a/bot-market/app/handlers.py b/bot-market/app/handlers.py new file mode 100644 index 0000000..64297ce --- /dev/null +++ b/bot-market/app/handlers.py @@ -0,0 +1,72 @@ +from aiogram import Router, F +from aiogram.types import Message, CallbackQuery +from aiogram.filters import CommandStart, Command + +import app.keyboards as kb +from app.database.requests import (get_item_by_id, set_user, + set_basket, get_basket, get_item_by_id, delete_basket) + +router = Router() + + +@router.message(CommandStart()) +@router.callback_query(F.data == 'to_main') +async def cmd_start(message: Message | CallbackQuery): + if isinstance(message, Message): + await set_user(message.from_user.id) + await message.answer("Добро пожаловать в интернет магазин!", + reply_markup=kb.main) + else: + await message.answer('Вы вернулись на главную') + await message.message.answer("Добро пожаловать в интернет магазин!", + reply_markup=kb.main) + + +@router.callback_query(F.data == 'catalog') +async def catalog(callback: CallbackQuery): + await callback.answer('') + await callback.message.edit_text(text='Выберите категорию.', + reply_markup=await kb.categories()) + + +@router.callback_query(F.data.startswith('category_')) +async def category(callback: CallbackQuery): + await callback.answer('') + await callback.message.edit_text('Выберите товар', + reply_markup=await kb.items(callback.data.split('_')[1])) + + +@router.callback_query(F.data.startswith('item_')) +async def category(callback: CallbackQuery): + item = await get_item_by_id(callback.data.split('_')[1]) + await callback.answer('') + await callback.message.answer_photo(photo=item.photo, + caption=f'{item.name}\n\n{item.description}\n\nЦена: {item.price} рублей', + reply_markup=await kb.basket(item.id)) + + +@router.callback_query(F.data.startswith('order_')) +async def basket(callback: CallbackQuery): + await set_basket(callback.from_user.id, callback.data.split('_')[1]) + await callback.answer('Товар добавлен в корзину') + + +@router.callback_query(F.data == 'mybasket') +async def mybasket(callback: CallbackQuery): + await callback.answer('') + basket = await get_basket(callback.from_user.id) + counter = 0 + for item_info in basket: + item = await get_item_by_id(item_info.item) + await callback.message.answer_photo(photo=item.photo, + caption=f'{item.name}\n\n{item.description}\n\nЦена: {item.price} рублей', + reply_markup=await kb.delete_from_basket(item.id)) + counter += 1 + await callback.message.answer('Ваша корзина пуста') if counter == 0 else await callback.answer('') + + +@router.callback_query(F.data.startswith('delete_')) +async def delete_from_basket(callback: CallbackQuery): + await delete_basket(callback.from_user.id, callback.data.split('_')[1]) + await callback.message.delete() + await callback.answer('Вы удалили товар из корзины') \ No newline at end of file diff --git a/bot-market/app/keyboards.py b/bot-market/app/keyboards.py new file mode 100644 index 0000000..4bd544e --- /dev/null +++ b/bot-market/app/keyboards.py @@ -0,0 +1,49 @@ + +from aiogram.types import (ReplyKeyboardMarkup, KeyboardButton, + InlineKeyboardMarkup, InlineKeyboardButton) +from aiogram.utils.keyboard import InlineKeyboardBuilder + +from app.database.requests import get_categories, get_items_by_category + +main = InlineKeyboardMarkup(inline_keyboard=[ + [InlineKeyboardButton(text='Каталог', callback_data='catalog')], + [InlineKeyboardButton(text='Корзина', callback_data='mybasket'), + InlineKeyboardButton(text='Контакты', callback_data='contacts')] +]) + +to_main = InlineKeyboardMarkup(inline_keyboard=[ + [InlineKeyboardButton(text='На главную', callback_data='to_main')] +]) + + +async def delete_from_basket(order_id): + keyboard = InlineKeyboardBuilder() + keyboard.add(InlineKeyboardButton(text='Удалить из корзины', callback_data=f'delete_{order_id}')) + return keyboard.adjust(2).as_markup() + + +async def basket(order_id): + keyboard = InlineKeyboardBuilder() + keyboard.add(InlineKeyboardButton(text='Оформить заказ', callback_data=f'order_{order_id}')) + keyboard.add(InlineKeyboardButton(text='Назад', callback_data='to_main')) + return keyboard.adjust(2).as_markup() + + +async def categories(): + all_categories = await get_categories() + keyboard = InlineKeyboardBuilder() + for category in all_categories: + keyboard.add(InlineKeyboardButton(text=category.name, + callback_data=f'category_{category.id}')) + keyboard.add(InlineKeyboardButton(text='Назад', callback_data='to_main')) + return keyboard.adjust(2).as_markup() + + +async def items(category_id: int): + items = await get_items_by_category(category_id) + keyboard = InlineKeyboardBuilder() + for item in items: + keyboard.add(InlineKeyboardButton(text=item.name, + callback_data=f"item_{item.id}")) + keyboard.add(InlineKeyboardButton(text='Назад', callback_data='to_main')) + return keyboard.adjust(2).as_markup() \ No newline at end of file diff --git a/bot-market/config.py b/bot-market/config.py new file mode 100644 index 0000000..613fb0f --- /dev/null +++ b/bot-market/config.py @@ -0,0 +1,3 @@ +TOKEN='7103505936:AAEpiQxlKNd9Uji9IziTdNzSTH38PavqXZM' +ENGINE='sqlite+aiosqlite:///db.sqlite3' +ECHO='' \ No newline at end of file diff --git a/bot-market/run.py b/bot-market/run.py new file mode 100644 index 0000000..04c0cb5 --- /dev/null +++ b/bot-market/run.py @@ -0,0 +1,25 @@ +import asyncio +import logging + +from aiogram import Bot, Dispatcher + +from config import TOKEN +from app.database.models import async_main +from app.handlers import router +from app.admin import admin + + +async def main(): + await async_main() + bot = Bot(token=TOKEN) + dp = Dispatcher() + dp.include_routers(admin, router) + await dp.start_polling(bot) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + try: + asyncio.run(main()) + except KeyboardInterrupt: + print('Exit') \ No newline at end of file diff --git a/bot_data.db b/bot_data.db new file mode 100644 index 0000000000000000000000000000000000000000..6068469b657fe1e967d6b42484664227d0cac2c2 GIT binary patch literal 16384 zcmeI#&q~8E90%~E9S(#I!9&?CC)w!m;tN4VQSfnCJ z^PzU`aLeV)wa)sS<&~*bzF`A(4dr5cK>#yzIr`I+YNV>VPYH>!Mxt>iqDN9!* zS(Y9UB1zJOSh8Y?Qd$&J(Td3BzVd0s3F(gWVM6&KWiB3kvOAXZ)oI^wp`m< z)ydLUv#G7=Mo_t_*Ba~bUdvCKT76|LIPvV!`SPTxEo)+jC2f-gb^fen=EGLyyXkaR zotcr}Ho|VU_9!>@ET6mHL4P?j(Cz*$ecg{3qCD>DuQ{T)C_j}a3W##y;?rGr%q!X& z)n?SOoLwW3J#*~Aep2i{J+PU>4V&>j*GxEYh-8SHhj$X&>oLliX^0uq`Hp}$ zS4OkywQF+M4M)I{HuHOh)WA6CRsXv~;g4^M*9US|RaLpW5t4+DuJC7MfFi8=iwvB# z*{(=KmM?3ZrWffB*y_009U<00Izz00bZa0sQ?RV*mmWfB*y_009U<00Izz z00bZ~3ottE?+Gm6WJJf&c^{009U<00Izz00bZa0SNp@0yoCQ zXX~z)ZTg%U;TIlCg;Hg%aCfdaPl}7x%3^iCkjsjgneq;8JvX>(*wk`PL{;wPGGP>L zwcL*Qri4j3JrPwXOs7SZS{9#?@c6OK3)T6BTq@}xrRsb!H=5L-Qnj*>8%aJ^d2w1k KwLzt7`QA@fyXgV| literal 0 HcmV?d00001