Add YouTube recoding

This commit is contained in:
BarsTiger
2023-11-07 14:13:14 +02:00
parent 54006008d3
commit 06c327933f
13 changed files with 245 additions and 15 deletions

View File

@@ -4,12 +4,13 @@ from . import (
on_home, on_home,
settings, settings,
) )
from bot.middlewares import PrivateButtonMiddleware from bot.middlewares import PrivateButtonMiddleware, SettingsInjectorMiddleware
router = Router() router = Router()
router.callback_query.middleware(PrivateButtonMiddleware()) router.callback_query.middleware(PrivateButtonMiddleware())
router.callback_query.middleware(SettingsInjectorMiddleware())
router.include_routers( router.include_routers(
full_menu.router, full_menu.router,

View File

@@ -2,6 +2,7 @@ from aiogram import Router, Bot
from aiogram.types import ( from aiogram.types import (
CallbackQuery CallbackQuery
) )
from aiogram.exceptions import TelegramBadRequest
from bot.factories.open_setting import OpenSettingCallback, SettingChoiceCallback from bot.factories.open_setting import OpenSettingCallback, SettingChoiceCallback
@@ -34,11 +35,14 @@ async def on_change_setting(
bot: Bot bot: Bot
): ):
UserSettings(callback_query.from_user.id)[callback_data.s_id] = callback_data.choice UserSettings(callback_query.from_user.id)[callback_data.s_id] = callback_data.choice
await bot.edit_message_text( try:
inline_message_id=callback_query.inline_message_id, await bot.edit_message_text(
text=settings_strings[callback_data.s_id].description, inline_message_id=callback_query.inline_message_id,
reply_markup=get_setting_kb( text=settings_strings[callback_data.s_id].description,
callback_data.s_id, reply_markup=get_setting_kb(
str(callback_query.from_user.id) callback_data.s_id,
str(callback_query.from_user.id)
)
) )
) except TelegramBadRequest:
pass

View File

@@ -9,11 +9,12 @@ from . import (
on_chosen, on_chosen,
) )
from bot.middlewares import SaveChosenMiddleware from bot.middlewares import SaveChosenMiddleware, SettingsInjectorMiddleware
router = Router() router = Router()
router.chosen_inline_result.outer_middleware(SaveChosenMiddleware()) router.chosen_inline_result.outer_middleware(SaveChosenMiddleware())
router.chosen_inline_result.middleware(SettingsInjectorMiddleware())
router.include_routers( router.include_routers(
initialize.router, initialize.router,

View File

@@ -1,5 +1,5 @@
from aiogram import Router from aiogram import Router
from . import spotify, deezer, youtube from . import spotify, deezer, youtube, recode_cached, suppress_verify
router = Router() router = Router()
@@ -7,6 +7,8 @@ router.include_routers(
spotify.router, spotify.router,
deezer.router, deezer.router,
youtube.router, youtube.router,
recode_cached.router,
suppress_verify.router,
) )
__all__ = ['router'] __all__ = ['router']

View File

@@ -0,0 +1,101 @@
from aiogram import Router, Bot, F
from aiogram.types import (
BufferedInputFile, InputMediaAudio,
ChosenInlineResult,
)
from bot.modules.youtube.downloader import YouTubeBytestream
from bot.utils.config import config
from bot.modules.database import db
from bot.modules.settings import UserSettings
from io import BytesIO
router = Router()
@router.chosen_inline_result(
F.result_id.startswith('spotc::') | F.result_id.startswith('ytc::')
)
async def on_cached_chosen(chosen_result: ChosenInlineResult, bot: Bot,
settings: UserSettings):
if settings['recode_youtube'].value != 'yes':
await bot.edit_message_reply_markup(
inline_message_id=chosen_result.inline_message_id,
reply_markup=None
)
return
if (
type(
db.recoded.get(
song_id := chosen_result.result_id
.removeprefix('spotc::')
.removeprefix('ytc::')
)
) in [bool, type(None)]
):
await bot.edit_message_reply_markup(
inline_message_id=chosen_result.inline_message_id,
reply_markup=None
)
return
await bot.edit_message_caption(
inline_message_id=chosen_result.inline_message_id,
caption='🔄 Recoding...',
reply_markup=None
)
message = await bot.forward_message(
config.telegram.files_chat,
config.telegram.files_chat,
db.recoded[song_id]
)
song_io: BytesIO = await bot.download( # type: ignore
destination=BytesIO(),
file=message.audio.file_id,
)
await message.delete()
bytestream = YouTubeBytestream.from_bytestream(
bytestream=song_io,
filename=message.audio.file_name,
duration=message.audio.duration,
)
await bytestream.rerender()
audio = await bot.send_audio(
chat_id=config.telegram.files_chat,
audio=BufferedInputFile(
file=bytestream.file,
filename=bytestream.filename,
),
thumbnail=BufferedInputFile(
file=(await bot.download(message.audio.thumbnail.file_id)).read(),
filename='thumbnail.jpg'
),
performer=message.audio.performer,
title=message.audio.title,
duration=bytestream.duration,
)
await bot.edit_message_caption(
inline_message_id=chosen_result.inline_message_id,
caption='',
reply_markup=None,
)
await bot.edit_message_media(
inline_message_id=chosen_result.inline_message_id,
media=InputMediaAudio(media=audio.audio.file_id)
)
if chosen_result.result_id.startswith('spotc::'):
db.spotify[song_id] = audio.audio.file_id
else:
db.youtube[song_id] = audio.audio.file_id
db.recoded[song_id] = True
await db.occasionally_write()

View File

@@ -10,6 +10,7 @@ from bot.modules.youtube.song import SongItem
from bot.modules.deezer import deezer from bot.modules.deezer import deezer
from bot.utils.config import config from bot.utils.config import config
from bot.modules.database import db from bot.modules.database import db
from bot.modules.settings import UserSettings
router = Router() router = Router()
@@ -22,13 +23,14 @@ def not_strict_name(song, yt_song):
@router.chosen_inline_result(F.result_id.startswith('spot::')) @router.chosen_inline_result(F.result_id.startswith('spot::'))
async def on_new_chosen(chosen_result: ChosenInlineResult, bot: Bot): async def on_new_chosen(chosen_result: ChosenInlineResult, bot: Bot,
settings: UserSettings):
song = spotify.songs.from_id(chosen_result.result_id.removeprefix('spot::')) song = spotify.songs.from_id(chosen_result.result_id.removeprefix('spot::'))
bytestream = None bytestream = None
audio = None audio = None
yt_song: SongItem = youtube.songs.search_one( yt_song: SongItem | None = youtube.songs.search_one(
song.full_name, song.full_name,
exact_match=True, exact_match=True,
) )
@@ -40,6 +42,7 @@ async def on_new_chosen(chosen_result: ChosenInlineResult, bot: Bot):
reply_markup=None, reply_markup=None,
parse_mode='HTML', parse_mode='HTML',
) )
yt_song = None
bytestream = False bytestream = False
try: try:
@@ -66,6 +69,7 @@ async def on_new_chosen(chosen_result: ChosenInlineResult, bot: Bot):
reply_markup=None, reply_markup=None,
parse_mode='HTML', parse_mode='HTML',
) )
yt_song = None
if not bytestream: if not bytestream:
try: try:
@@ -110,4 +114,42 @@ async def on_new_chosen(chosen_result: ChosenInlineResult, bot: Bot):
parse_mode='HTML', parse_mode='HTML',
) )
if yt_song and settings['recode_youtube'].value == 'yes':
await bot.edit_message_caption(
inline_message_id=chosen_result.inline_message_id,
caption='🔄 Recoding...',
reply_markup=None,
parse_mode='HTML',
)
await bytestream.rerender()
audio = await bot.send_audio(
chat_id=config.telegram.files_chat,
audio=BufferedInputFile(
file=bytestream.file,
filename=bytestream.filename,
),
thumbnail=URLInputFile(song.thumbnail),
performer=song.all_artists,
title=song.name,
duration=bytestream.duration,
)
db.youtube[yt_song.id] = audio.audio.file_id
db.spotify[song.id] = audio.audio.file_id
db.recoded[yt_song.id] = True
db.recoded[song.id] = True
await bot.edit_message_caption(
inline_message_id=chosen_result.inline_message_id,
caption='',
reply_markup=None,
)
await bot.edit_message_media(
inline_message_id=chosen_result.inline_message_id,
media=InputMediaAudio(media=audio.audio.file_id)
)
elif yt_song and settings['recode_youtube'].value == 'no':
db.recoded[yt_song.id] = audio.message_id
db.recoded[song.id] = audio.message_id
await db.occasionally_write() await db.occasionally_write()

View File

@@ -0,0 +1,16 @@
from aiogram import Router, Bot, F
from aiogram.types import (
ChosenInlineResult,
)
router = Router()
@router.chosen_inline_result(
F.result_id.startswith('deezc::')
)
async def on_unneeded_cached_chosen(chosen_result: ChosenInlineResult, bot: Bot):
await bot.edit_message_reply_markup(
inline_message_id=chosen_result.inline_message_id,
reply_markup=None
)

View File

@@ -7,12 +7,14 @@ from aiogram.types import (
from bot.modules.youtube import youtube, AgeRestrictedError from bot.modules.youtube import youtube, AgeRestrictedError
from bot.utils.config import config from bot.utils.config import config
from bot.modules.database import db from bot.modules.database import db
from bot.modules.settings import UserSettings
router = Router() router = Router()
@router.chosen_inline_result(F.result_id.startswith('yt::')) @router.chosen_inline_result(F.result_id.startswith('yt::'))
async def on_new_chosen(chosen_result: ChosenInlineResult, bot: Bot): async def on_new_chosen(chosen_result: ChosenInlineResult, bot: Bot,
settings: UserSettings):
song = youtube.songs.from_id(chosen_result.result_id.removeprefix('yt::')) song = youtube.songs.from_id(chosen_result.result_id.removeprefix('yt::'))
try: try:
@@ -46,4 +48,36 @@ async def on_new_chosen(chosen_result: ChosenInlineResult, bot: Bot):
reply_markup=None reply_markup=None
) )
if settings['recode_youtube'].value == 'yes':
await bot.edit_message_caption(
inline_message_id=chosen_result.inline_message_id,
caption='🔄 Recoding...',
reply_markup=None
)
await bytestream.rerender()
audio = await bot.send_audio(
chat_id=config.telegram.files_chat,
audio=BufferedInputFile(
file=bytestream.file,
filename=bytestream.filename,
),
thumbnail=URLInputFile(song.thumbnail),
performer=song.all_artists,
title=song.name,
duration=bytestream.duration,
)
db.youtube[song.id] = audio.audio.file_id
db.recoded[song.id] = True
await bot.edit_message_media(
inline_message_id=chosen_result.inline_message_id,
media=InputMediaAudio(media=audio.audio.file_id),
reply_markup=None
)
else:
db.recoded[song.id] = audio.message_id
await db.occasionally_write() await db.occasionally_write()

View File

@@ -1,2 +1,3 @@
from .private_button import PrivateButtonMiddleware from .private_button import PrivateButtonMiddleware
from .save_chosen import SaveChosenMiddleware from .save_chosen import SaveChosenMiddleware
from .inject_settings import SettingsInjectorMiddleware

View File

@@ -0,0 +1,22 @@
from aiogram.dispatcher.middlewares.base import BaseMiddleware
from aiogram.types import TelegramObject
from typing import Any, Awaitable, Callable, Dict
from bot.modules.settings import UserSettings
class SettingsInjectorMiddleware(BaseMiddleware):
async def __call__(
self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: Dict[str, Any],
):
if not hasattr(event, 'from_user'):
return await handler(event, data)
settings = UserSettings(event.from_user.id)
data['settings'] = settings
return await handler(event, data)

View File

@@ -20,6 +20,7 @@ class Db(object):
self.spotify = DBDict('spotify') self.spotify = DBDict('spotify')
self.deezer = DBDict('deezer') self.deezer = DBDict('deezer')
self.youtube = DBDict('youtube') self.youtube = DBDict('youtube')
self.recoded = DBDict('recoded')
async def write(self): async def write(self):
await self.config.write() await self.config.write()

View File

@@ -29,10 +29,10 @@ class YouTubeBytestream:
async def rerender(self): async def rerender(self):
segment = AudioSegment.from_file( segment = AudioSegment.from_file(
file=self.file file=BytesIO(self.file)
) )
self.file = segment.export(BytesIO(), format='mp3', codec='libmp3lame') self.file = segment.export(BytesIO(), format='mp3', codec='libmp3lame').read()
return self return self

View File

@@ -35,5 +35,10 @@ async def get_common_search_result(
InlineQueryResultCachedAudio( InlineQueryResultCachedAudio(
id=f'{service_id}c::' + audio.id, id=f'{service_id}c::' + audio.id,
audio_file_id=db_table[audio.id], audio_file_id=db_table[audio.id],
reply_markup=InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text='Verifying...', callback_data='.')]
]
),
) )
) )