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 0000000..6068469
Binary files /dev/null and b/bot_data.db differ
diff --git a/old/bot_klining.db b/old/bot_klining.db
new file mode 100644
index 0000000..b518136
Binary files /dev/null and b/old/bot_klining.db differ