mirror of
https://github.com/EDeev/mospoly-helper.git
synced 2026-06-18 22:10:59 +03:00
v. 1.0
This commit is contained in:
parent
c651369b17
commit
a678f005bd
11 changed files with 230 additions and 22 deletions
|
|
@ -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
17
src/code/database.py
Normal 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()
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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
BIN
src/data/cache/av-4b-04f-04401c-all.mp4
vendored
Normal file
Binary file not shown.
BIN
src/data/cache/av-4b-04f-04401c-small.mp4
vendored
Normal file
BIN
src/data/cache/av-4b-04f-04401c-small.mp4
vendored
Normal file
Binary file not shown.
BIN
src/data/cache/av-4b-04f-04412c-all.mp4
vendored
Normal file
BIN
src/data/cache/av-4b-04f-04412c-all.mp4
vendored
Normal file
Binary file not shown.
BIN
src/data/cache/av-4b-04f-04412c-small.mp4
vendored
Normal file
BIN
src/data/cache/av-4b-04f-04412c-small.mp4
vendored
Normal file
Binary file not shown.
1
src/data/users/732366984.json
Normal file
1
src/data/users/732366984.json
Normal 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"]}
|
||||
1
src/data/users/934493329.json
Normal file
1
src/data/users/934493329.json
Normal 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"]}
|
||||
Loading…
Add table
Reference in a new issue