This commit is contained in:
IGlek 2025-05-19 21:54:47 +03:00
parent c651369b17
commit a678f005bd
11 changed files with 230 additions and 22 deletions

View file

@ -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())

17
src/code/database.py Normal file
View file

@ -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()

View file

@ -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("Здравствуйте! Этот бот поможет вам добраться до кабинета в структуре корпусов Московского "
"Политехнического Университета. Для начала работы просто пропишите команду <b>/route</b>")
@router.message(Command("help"))
async def help_handler(msg: Message) -> None:
text = "<b>Текст</b>\n\n"
text = "<b>Напомню, что за команды у нас тут есть)</b>\n\n"
text += "<b>/dates</b> - Текст\n\n"
text += "<b>/picture</b> - Текст\n\n"
text += "<b>/gallery</b> - Текст"
text += "<b>/help</b> - Команда помощи, выведет все доступные команды\n\n"
text += "<b>/route</b> - Команда выводит маршрут до введённого кабинета"
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("Данного маршрута в нашей базе пока нет, извините за неудобство, можете написать "
"желаемые маршруты на почту <a href='mailto:support@new-devs.ru' >support@new-devs.ru</a>")
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("Данного маршрута в нашей базе пока нет, извините за неудобство, можете написать "
"желаемые маршруты на почту <a href='mailto:support@new-devs.ru' >support@new-devs.ru</a>")
return 0
msg_finally = await msg.edit_text("2. Видео готово!")
await msg.answer_video_note(video_note=FSInputFile(path))
await msg_finally.delete()

View file

@ -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())

View file

@ -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

BIN
src/data/cache/av-4b-04f-04401c-all.mp4 vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
src/data/cache/av-4b-04f-04412c-all.mp4 vendored Normal file

Binary file not shown.

Binary file not shown.

View file

@ -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"]}

View file

@ -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"]}