diff --git a/src/code/bot.py b/src/code/bot.py
index 353bd0f..f18653c 100644
--- a/src/code/bot.py
+++ b/src/code/bot.py
@@ -7,6 +7,8 @@ from handlers import router
async def main() -> None:
dp.include_router(router)
await bot.delete_webhook(drop_pending_updates=True)
+
+ await setup_bot_commands()
await dp.start_polling(bot, allowed_updates=dp.resolve_used_update_types())
diff --git a/src/code/database.py b/src/code/database.py
new file mode 100644
index 0000000..f110316
--- /dev/null
+++ b/src/code/database.py
@@ -0,0 +1,17 @@
+import json
+
+
+class JsonTools:
+ def __init__(self, user_id):
+ self.f_name = f"../data/users/{user_id}.json"
+
+ def save_json(self, data):
+ with open(self.f_name, "w", encoding="utf8") as f:
+ return json.dump(data, f)
+
+ def read_json(self):
+ with open(self.f_name, "r", encoding="utf8") as f:
+ return json.load(f)
+
+ def get_buildings(self):
+ return self.read_json().keys()
\ No newline at end of file
diff --git a/src/code/handlers.py b/src/code/handlers.py
index 282a303..9a6a849 100644
--- a/src/code/handlers.py
+++ b/src/code/handlers.py
@@ -1,27 +1,115 @@
-from aiogram import types, F, Router
-from aiogram.types import (Message, InlineQuery, InlineQueryResultArticle, InputTextMessageContent, ChosenInlineResult,
- ContentType, InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery, FSInputFile,
- InputMediaPhoto, InlineQueryResultPhoto)
+from aiogram import F, Router
+from aiogram.types import (Message, ContentType, InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery, FSInputFile)
from aiogram.filters import Command, CommandStart
-from aiogram.utils.keyboard import InlineKeyboardBuilder
-from init import *
from scripts import *
+from database import *
router = Router()
@router.message(CommandStart())
async def start_handler(msg: Message) -> None:
- await msg.answer("Привет мир!")
+ await msg.answer("Здравствуйте! Этот бот поможет вам добраться до кабинета в структуре корпусов Московского "
+ "Политехнического Университета. Для начала работы просто пропишите команду /route")
@router.message(Command("help"))
async def help_handler(msg: Message) -> None:
- text = "Текст\n\n"
+ text = "Напомню, что за команды у нас тут есть)\n\n"
- text += "/dates - Текст\n\n"
- text += "/picture - Текст\n\n"
- text += "/gallery - Текст"
+ text += "/help - Команда помощи, выведет все доступные команды\n\n"
+ text += "/route - Команда выводит маршрут до введённого кабинета"
await msg.answer(text)
+
+
+@router.message(Command("route"))
+async def route_handler(msg: Message) -> None:
+ buttons = [[InlineKeyboardButton(text=f"На Большой Семёновской", callback_data="edu:bs")],
+ [InlineKeyboardButton(text=f"На Павла Корчагина", callback_data="edu:pk")],
+ [InlineKeyboardButton(text=f"На Прянишкова", callback_data="edu:pr"),
+ InlineKeyboardButton(text=f"На Михалковской", callback_data="edu:mi")],
+ [InlineKeyboardButton(text=f"На Автозаводской", callback_data="edu:av")]]
+ keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
+
+ await msg.answer(text="Выберите корпус на котором вы хотите проложить маршрут:", reply_markup=keyboard)
+
+
+@router.callback_query(F.data.startswith("edu:"))
+async def route_button(call: CallbackQuery) -> None:
+ action = call.data.split(":")[1]
+
+ user_dict = dict()
+ user_dict[action] = []
+
+ JsonTools(call.from_user.id).save_json(user_dict)
+
+ await call.message.edit_text("Укажите до какого кабинет вам необходимо добраться "
+ "(обязательно напишите кабинет в точности как указано в личном кабинет):")
+
+@router.message(F.content_type == ContentType.TEXT)
+async def add_cabinet(msg: Message) -> None:
+ cab = msg.text.lower()
+
+ jsn = JsonTools(msg.from_user.id)
+ user_dict = jsn.read_json()
+ edu_keys = list(user_dict.keys())
+
+ if ((cab[0] == "м" and len(cab) == 5 and "mi" == edu_keys[0]) or
+ (cab[:2] == "ав" and len(cab) == 6 and "av" == edu_keys[0]) or
+ (cab[:2] == "пк" and len(cab) == 6 and "pk" == edu_keys[0]) or
+ (cab[:2] == "пр" and len(cab) == 6 and "pr" == edu_keys[0]) or
+ (cab[0] in ["а", "б", "в", "н", "нд"] and "bs" == edu_keys[0])):
+ lst_routes = get_routes(edu_keys[0], cab)
+
+ if lst_routes:
+ user_dict[edu_keys[0]] = lst_routes
+ jsn.save_json(user_dict)
+
+ buttons = [[InlineKeyboardButton(text=f"От входа на территорию", callback_data="route:build")],
+ [InlineKeyboardButton(text=f"От входа в корпус", callback_data="route:floor")]]
+ keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
+
+ await msg.answer("Кабинет успешно получен, обрабатываем путь! Откуда вам проложить маршрут:", reply_markup=keyboard)
+ else:
+ await msg.answer("Обрыв программы по неизвестной причине!")
+ else:
+ await msg.answer("Вы скинули не кабинет! Я же вижу)")
+
+
+@router.callback_query(F.data.startswith("route:"))
+async def var_button(call: CallbackQuery) -> None:
+ action = call.data.split(":")[1]
+
+ jsn = JsonTools(call.from_user.id)
+ user_dict = jsn.read_json()
+ edu_keys = list(user_dict.keys())
+ lst_routes = user_dict[edu_keys[0]]
+
+ msg = await call.message.answer("1. Получение видео...")
+ path = ""
+
+ if action == "build":
+ if os.path.exists(f"../data/cache/{lst_routes[-1][21:].replace('.mp4', '-all.mp4')}"):
+ path = f"../data/cache/{lst_routes[-1][21:].replace('.mp4', '-all.mp4')}"
+ else:
+ path = make_full_clip(lst_routes)
+ if not path:
+ await msg.edit_text("Данного маршрута в нашей базе пока нет, извините за неудобство, можете написать "
+ "желаемые маршруты на почту support@new-devs.ru")
+ return 0
+ elif action == "floor":
+ if os.path.exists(f"../data/cache/{lst_routes[-1][21:].replace('.mp4', '-small.mp4')}"):
+ path = f"../data/cache/{lst_routes[-1][21:].replace('.mp4', '-small.mp4')}"
+ else:
+ path = make_full_clip(lst_routes[1:])
+ if not path:
+ await msg.edit_text("Данного маршрута в нашей базе пока нет, извините за неудобство, можете написать "
+ "желаемые маршруты на почту support@new-devs.ru")
+ return 0
+
+ msg_finally = await msg.edit_text("2. Видео готово!")
+
+ await msg.answer_video_note(video_note=FSInputFile(path))
+ await msg_finally.delete()
diff --git a/src/code/init.py b/src/code/init.py
index 4004301..f3eda99 100644
--- a/src/code/init.py
+++ b/src/code/init.py
@@ -2,9 +2,22 @@ from aiogram import Bot, Dispatcher
from aiogram.enums.parse_mode import ParseMode
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.client.bot import DefaultBotProperties
+from aiogram.types import BotCommand, BotCommandScopeDefault
+from aiogram.methods import SetMyCommands
import config
+# Структурированное определение команд для меню
+async def setup_bot_commands():
+ commands = [
+ BotCommand(command="help", description="Получить помощь"),
+ BotCommand(command="route", description="Построить маршрут")
+ ]
+
+ await bot(SetMyCommands(
+ commands=commands,
+ scope=BotCommandScopeDefault()
+ ))
bot = Bot(token=config.BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp = Dispatcher(storage=MemoryStorage())
diff --git a/src/code/scripts.py b/src/code/scripts.py
index 24ad5c6..3413dee 100644
--- a/src/code/scripts.py
+++ b/src/code/scripts.py
@@ -1,15 +1,101 @@
-from csv import reader, writer
+from moviepy import VideoFileClip, concatenate_videoclips
+import os
-def write_log(text):
- with open("../data/database/log.txt", "a") as f:
- f.writelines(text)
+def get_routes(id_building: str, id_cab: str, other=False):
+
+ if other:
+ id_cab = id_cab.replace('-', "")
+ building=id_cab[0]
+ cab_num=id_cab[1:]
+ corp_route=f"../videos/{id_building}/{id_building}-{building}b.mp4"
+ cab_route=f"../videos/{id_building}/{id_building}-{building}b-{cab_num}.mp4"
+ return [corp_route,cab_route]
-def view_csv(filename):
- data = []
- with open(f'../data/database/{filename}', 'r', encoding='utf-8') as csvfile:
- csvreader = reader(csvfile)
- for row in csvreader:
- data.append(row)
+ match id_building:
+ #авbfnn
+ case "av":
+ building = id_cab[2]
+ floor = id_cab[3]
+ cab_num = id_cab[4:]
+ corp_route = f"../videos/{id_building}/buildings/{id_building}-{building}b.mp4"
+ floor_route = f"../videos/{id_building}/floors/{id_building}-{building}b-0{floor}f.mp4"
+ cab_route = f"../videos/{id_building}/offices/{id_building}-{building}b-0{floor}f-0{building}{floor}{cab_num}c.mp4"
+
+ return [corp_route, floor_route, cab_route]
+
+ case "mi":
+ building = id_cab[1]
+ floor = id_cab[2]
+ cab_num = id_cab[3:]
+ corp_route = f"../videos/{id_building}/buildings/{id_building}-{building}b.mp4"
+ floor_route = f"../videos/{id_building}/floors/{id_building}-{building}b-0{floor}f.mp4"
+ cab_route = f"../videos/{id_building}/offices/{id_building}-{building}b-0{floor}f-0{building}{floor}{cab_num}c.mp4"
+
+ return [corp_route, floor_route, cab_route]
+
+ case "pk":
+ building = id_cab[2]
+ floor = id_cab[3]
+ cab_num = id_cab[4:]
+ corp_route = f"../videos/{id_building}/buildings/{id_building}-{building}b.mp4"
+ floor_route = f"../videos/{id_building}/floors/{id_building}-{building}b-0{floor}f.mp4"
+ cab_route = f"../videos/{id_building}/offices/{id_building}-{building}b-0{floor}f-0{building}{floor}{cab_num}c.mp4"
+
+ return [corp_route, floor_route, cab_route]
+
+ case "pr":
+ building = id_cab[2]
+ floor = id_cab[3]
+ cab_num = id_cab[4:]
+ corp_route = f"../videos/{id_building}/buildings/{id_building}-{building}b.mp4"
+ floor_route = f"../videos/{id_building}/floors/{id_building}-{building}b-0{floor}f.mp4"
+ cab_route = f"../videos/{id_building}/offices/{id_building}-{building}b-0{floor}f-0{building}{floor}{cab_num}c.mp4"
+
+ return [corp_route, floor_route, cab_route]
+
+
+ #id_building: bs
+ #id_cab: bfnn
+ case "bs":
+ id_cab= id_cab.replace('-',"")
+ building = id_cab[0]
+ floor = id_cab[1]
+ cab_num = id_cab[3:]
+ corp_route = f"../videos/{id_building}/buildings/{id_building}-{building}b.mp4"
+ floor_route = f"../videos/{id_building}/floors/{id_building}-{building}b-0{floor}f.mp4"
+ cab_route = f"../videos/{id_building}/offices/{id_building}-{building}b-0{floor}f-0{building}{floor}{cab_num}c.mp4"
+
+ return [corp_route, floor_route, cab_route]
+
+ return None
+
+
+def make_full_clip(paths):
+
+ if not all(os.path.exists(path) for path in paths):
+ print("Некоторые файлы не найдены")
+ return None
+
+ clips = [VideoFileClip(path) for path in paths] # cоздаем список клипов
+
+ full_clip = concatenate_videoclips(clips) # cклеиваем все клипы
+
+ full_clip = full_clip.without_audio() # удаляем звук
+ full_clip = full_clip.time_transform(lambda t: t * 1.5).with_duration(full_clip.duration / 1.5) # ускоряем в 1.5 раз
+ full_clip = full_clip.resized(height=512)
+
+ full_clip_name = f"{paths[-1][21:].replace('.mp4', '')}-{'all' if len(paths) == 3 else 'small'}.mp4" # генерируем рандомный 5-ти значный ключ
+
+ # рендерим видео с параметрами
+ full_clip.write_videofile(f"../data/cache/{full_clip_name}",
+ fps=30,
+ codec="libx264",
+ bitrate="1500k",
+ preset="fast",
+ ffmpeg_params=["-crf", "23"])
+
+
+ return f"../data/cache/{full_clip_name}"
+
- return data
diff --git a/src/data/cache/av-4b-04f-04401c-all.mp4 b/src/data/cache/av-4b-04f-04401c-all.mp4
new file mode 100644
index 0000000..354b34d
Binary files /dev/null and b/src/data/cache/av-4b-04f-04401c-all.mp4 differ
diff --git a/src/data/cache/av-4b-04f-04401c-small.mp4 b/src/data/cache/av-4b-04f-04401c-small.mp4
new file mode 100644
index 0000000..981141a
Binary files /dev/null and b/src/data/cache/av-4b-04f-04401c-small.mp4 differ
diff --git a/src/data/cache/av-4b-04f-04412c-all.mp4 b/src/data/cache/av-4b-04f-04412c-all.mp4
new file mode 100644
index 0000000..4fc88e7
Binary files /dev/null and b/src/data/cache/av-4b-04f-04412c-all.mp4 differ
diff --git a/src/data/cache/av-4b-04f-04412c-small.mp4 b/src/data/cache/av-4b-04f-04412c-small.mp4
new file mode 100644
index 0000000..c318756
Binary files /dev/null and b/src/data/cache/av-4b-04f-04412c-small.mp4 differ
diff --git a/src/data/users/732366984.json b/src/data/users/732366984.json
new file mode 100644
index 0000000..ff64eb6
--- /dev/null
+++ b/src/data/users/732366984.json
@@ -0,0 +1 @@
+{"av": ["../videos/av/buildings/av-4b.mp4", "../videos/av/floors/av-4b-04f.mp4", "../videos/av/offices/av-4b-04f-04412c.mp4"]}
\ No newline at end of file
diff --git a/src/data/users/934493329.json b/src/data/users/934493329.json
new file mode 100644
index 0000000..69826be
--- /dev/null
+++ b/src/data/users/934493329.json
@@ -0,0 +1 @@
+{"bs": ["../videos/bs/buildings/bs-\u0430b.mp4", "../videos/bs/floors/bs-\u0430b-02f.mp4", "../videos/bs/offices/bs-\u0430b-02f-0\u043021\u0430c.mp4"]}
\ No newline at end of file