diff --git a/docs/source/v6d3music.rst b/docs/source/v6d3music.rst index 2346530..ef6b1a5 100644 --- a/docs/source/v6d3music.rst +++ b/docs/source/v6d3music.rst @@ -17,6 +17,16 @@ Root modules Core modules ------------ +.. automodule:: v6d3music.core.aservicing + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: v6d3music.core.audio + :members: + :undoc-members: + :show-inheritance: + .. automodule:: v6d3music.core.caching :members: :undoc-members: @@ -57,16 +67,6 @@ Core modules :undoc-members: :show-inheritance: -.. automodule:: v6d3music.core.ytaservicing - :members: - :undoc-members: - :show-inheritance: - -.. automodule:: v6d3music.core.ytaudio - :members: - :undoc-members: - :show-inheritance: - v6d2ctx module ============== diff --git a/v6d3music/commands.py b/v6d3music/commands.py index d53fedf..5a7910b 100644 --- a/v6d3music/commands.py +++ b/v6d3music/commands.py @@ -62,7 +62,7 @@ presets: {shlex.join(allowed_presets)} if attachments: args = ["[[", *(attachment.url for attachment in attachments), "]]"] + args added = 0 - async for audio in mainservice.yt_audios(ctx, args): + async for audio in mainservice.audios(ctx, args): queue.append(audio) added += 1 await ctx.reply(f"added track(s): {added}") diff --git a/v6d3music/core/ytaservicing.py b/v6d3music/core/aservicing.py similarity index 75% rename from v6d3music/core/ytaservicing.py rename to v6d3music/core/aservicing.py index 11a00bd..d05702f 100644 --- a/v6d3music/core/ytaservicing.py +++ b/v6d3music/core/aservicing.py @@ -1,8 +1,8 @@ from v6d3music.processing.abstractrunner import AbstractRunner -__all__ = ("YTAServicing",) +__all__ = ("AServicing",) -class YTAServicing: +class AServicing: def __init__(self, runner: AbstractRunner) -> None: self.runner = runner diff --git a/v6d3music/core/ytaudio.py b/v6d3music/core/audio.py similarity index 95% rename from v6d3music/core/ytaudio.py rename to v6d3music/core/audio.py index 6b843ba..f2ce88c 100644 --- a/v6d3music/core/ytaudio.py +++ b/v6d3music/core/audio.py @@ -9,23 +9,23 @@ from typing import Optional import discord from v6d2ctx.context import Explicit +from v6d3music.core.aservicing import AServicing from v6d3music.core.ffmpegnormalaudio import FFmpegNormalAudio from v6d3music.core.real_url import real_url -from v6d3music.core.ytaservicing import YTAServicing from v6d3music.processing.abstractrunner import CoroContext, CoroStatusChanged from v6d3music.utils.fill import FILL from v6d3music.utils.options_for_effects import options_for_effects from v6d3music.utils.sparq import sparq -__all__ = ("YTAudio",) +__all__ = ("Audio",) -class YTAudio(discord.AudioSource): +class Audio(discord.AudioSource): source: FFmpegNormalAudio def __init__( self, - servicing: YTAServicing, + servicing: AServicing, url: str, origin: str, description: str, @@ -133,7 +133,7 @@ class YTAudio(discord.AudioSource): await self._do_update_duration() async def _update_duration_context(self, context: CoroContext): - context.events.send(CoroStatusChanged({"ytaudio": "duration"})) + context.events.send(CoroStatusChanged({"audio": "duration"})) await self._update_duration() async def update_duration(self): @@ -224,7 +224,7 @@ class YTAudio(discord.AudioSource): } @classmethod - async def respawn(cls, servicing: YTAServicing, guild: discord.Guild, respawn: dict) -> YTAudio: + async def respawn(cls, servicing: AServicing, guild: discord.Guild, respawn: dict) -> Audio: member_id: int | None = respawn["rby"] if member_id is None: member = None @@ -236,7 +236,7 @@ class YTAudio(discord.AudioSource): guild._add_member(member) except discord.NotFound: member = None - audio = YTAudio( + audio = Audio( servicing, respawn["url"], respawn["origin"], @@ -269,8 +269,8 @@ class YTAudio(discord.AudioSource): "canbeskipped": self.can_be_skipped_by(member), } - def copy(self) -> YTAudio: - return YTAudio( + def copy(self) -> Audio: + return Audio( self.servicing, self.url, self.origin, @@ -280,11 +280,11 @@ class YTAudio(discord.AudioSource): 0, ) - def branch(self) -> YTAudio: + def branch(self) -> Audio: if self.stop_at is not None: raise Explicit("already branched") self.stop_at = stop_at = self.already_read + 50 - audio = YTAudio( + audio = Audio( self.servicing, self.url, self.origin, diff --git a/v6d3music/core/create_audio.py b/v6d3music/core/create_audio.py new file mode 100644 index 0000000..ea1c0c1 --- /dev/null +++ b/v6d3music/core/create_audio.py @@ -0,0 +1,24 @@ +from v6d2ctx.context import Context +from v6d3music.core.real_url import real_url +from v6d3music.core.aservicing import AServicing +from v6d3music.core.audio import Audio +from v6d3music.utils.argctx import BoundCtx, InfoCtx + +__all__ = ("create_audio",) + + +async def _create_audio(servicing: AServicing, bound: BoundCtx) -> Audio: + return Audio( + servicing, + await real_url(bound.url, False), + bound.url, + bound.description, + bound.options, + bound.member, + bound.already_read, + ) + + +async def create_audio(servicing: AServicing, ctx: Context, it: InfoCtx) -> Audio: + bound = it.bind(ctx) + return await _create_audio(servicing, bound) diff --git a/v6d3music/core/create_ytaudio.py b/v6d3music/core/create_ytaudio.py deleted file mode 100644 index 674a8a8..0000000 --- a/v6d3music/core/create_ytaudio.py +++ /dev/null @@ -1,24 +0,0 @@ -from v6d2ctx.context import Context -from v6d3music.core.real_url import real_url -from v6d3music.core.ytaservicing import YTAServicing -from v6d3music.core.ytaudio import YTAudio -from v6d3music.utils.argctx import BoundCtx, InfoCtx - -__all__ = ("create_ytaudio",) - - -async def _create_ytaudio(servicing: YTAServicing, bound: BoundCtx) -> YTAudio: - return YTAudio( - servicing, - await real_url(bound.url, False), - bound.url, - bound.description, - bound.options, - bound.member, - bound.already_read, - ) - - -async def create_ytaudio(servicing: YTAServicing, ctx: Context, it: InfoCtx) -> YTAudio: - bound = it.bind(ctx) - return await _create_ytaudio(servicing, bound) diff --git a/v6d3music/core/mainaudio.py b/v6d3music/core/mainaudio.py index cc33b43..ca65c74 100644 --- a/v6d3music/core/mainaudio.py +++ b/v6d3music/core/mainaudio.py @@ -3,7 +3,7 @@ import discord from ptvp35 import DbConnection from v6d2ctx.context import Explicit from v6d3music.core.queueaudio import QueueAudio -from v6d3music.core.ytaservicing import YTAServicing +from v6d3music.core.aservicing import AServicing from v6d3music.utils.assert_admin import assert_admin __all__ = ("MainAudio",) @@ -29,6 +29,6 @@ class MainAudio(discord.PCMVolumeTransformer): @classmethod async def create( - cls, servicing: YTAServicing, db: DbConnection, queues: DbConnection, guild: discord.Guild + cls, servicing: AServicing, db: DbConnection, queues: DbConnection, guild: discord.Guild ) -> "MainAudio": return cls(db, await QueueAudio.create(servicing, queues, guild)) diff --git a/v6d3music/core/mainservice.py b/v6d3music/core/mainservice.py index a6bd8a8..754020a 100644 --- a/v6d3music/core/mainservice.py +++ b/v6d3music/core/mainservice.py @@ -20,8 +20,8 @@ from v6d3music.core.mainaudio import MainAudio from v6d3music.core.monitoring import Monitoring, PersistentMonitoring from v6d3music.core.queueaudio import QueueAudio from v6d3music.core.ystate import YState -from v6d3music.core.ytaservicing import YTAServicing -from v6d3music.core.ytaudio import YTAudio +from v6d3music.core.aservicing import AServicing +from v6d3music.core.audio import Audio from v6d3music.processing.pool import Pool, PoolEvent from v6d3music.utils.argctx import ArgCtx from v6d3music.utils.assert_admin import assert_admin @@ -114,7 +114,7 @@ class MainService: self.__volumes = await es.enter_async_context(DbFactory(myroot / "volume.db", kvfactory=KVJson())) self.__queues = await es.enter_async_context(DbFactory(myroot / "queue.db", kvfactory=KVJson())) self.__pool = await es.enter_async_context(Pool(5, self.__pool_events)) - self.__servicing = YTAServicing(self.__pool) + self.__servicing = AServicing(self.__pool) self.__vcs_restored: asyncio.Future[None] = asyncio.Future() self.__save_task = asyncio.create_task(self.save_daemon()) self.monitoring = await es.enter_async_context(Monitoring()) @@ -224,7 +224,7 @@ class MainService: if not self.__vcs_restored.done(): await self.restore_vcs() - async def yt_audios(self, ctx: Context, args: list[str]) -> AsyncIterable[YTAudio]: + async def audios(self, ctx: Context, args: list[str]) -> AsyncIterable[Audio]: assert ctx.guild is not None argctx = ArgCtx(self.defaulteffects.get(ctx.guild.id), args) ystate = YState(self.__servicing, self.__pool, ctx, argctx.sources) diff --git a/v6d3music/core/queueaudio.py b/v6d3music/core/queueaudio.py index 28e2220..c2848fe 100644 --- a/v6d3music/core/queueaudio.py +++ b/v6d3music/core/queueaudio.py @@ -11,8 +11,8 @@ import discord from ptvp35 import DbConnection from v6d2ctx.context import Explicit -from v6d3music.core.ytaservicing import YTAServicing -from v6d3music.core.ytaudio import YTAudio +from v6d3music.core.aservicing import AServicing +from v6d3music.core.audio import Audio from v6d3music.utils.assert_admin import assert_admin from v6d3music.utils.fill import FILL @@ -23,9 +23,9 @@ PRE_SET_LENGTH = 6 class QueueAudio(discord.AudioSource): - def __init__(self, db: DbConnection, guild: discord.Guild, respawned: list[YTAudio]): + def __init__(self, db: DbConnection, guild: discord.Guild, respawned: list[Audio]): self.db = db - self.queue: deque[YTAudio] = deque() + self.queue: deque[Audio] = deque() for audio in respawned: self.append(audio) self.guild = guild @@ -40,12 +40,12 @@ class QueueAudio(discord.AudioSource): return @staticmethod - async def respawned(servicing: YTAServicing, db: DbConnection, guild: discord.Guild) -> list[YTAudio]: + async def respawned(servicing: AServicing, db: DbConnection, guild: discord.Guild) -> list[Audio]: respawned = [] try: for audio_respawn in db.get(guild.id, []): try: - respawned.append(await YTAudio.respawn(servicing, guild, audio_respawn)) + respawned.append(await Audio.respawn(servicing, guild, audio_respawn)) except Exception as e: print("audio respawn failed", e) raise @@ -55,7 +55,7 @@ class QueueAudio(discord.AudioSource): return respawned @classmethod - async def create(cls, servicing: YTAServicing, db: DbConnection, guild: discord.Guild) -> QueueAudio: + async def create(cls, servicing: AServicing, db: DbConnection, guild: discord.Guild) -> QueueAudio: return cls(db, guild, await cls.respawned(servicing, db, guild)) async def save(self, delay: bool) -> None: @@ -66,12 +66,12 @@ class QueueAudio(discord.AudioSource): hybernated.append(audio.hybernate()) self.db.set_nowait(self.guild.id, hybernated) - def append(self, audio: YTAudio): + def append(self, audio: Audio): if len(self.queue) < PRE_SET_LENGTH: audio.set_source_given_index(len(self.queue)) self.queue.append(audio) - def _popleft(self, audio: YTAudio): + def _popleft(self, audio: Audio): if self.queue and self.queue[0] is audio: self.queue.popleft().cleanup() self.update_sources() @@ -104,7 +104,7 @@ class QueueAudio(discord.AudioSource): if not self.skip_at(pos0, member): pos0 += 1 - def skip_audio(self, audio: YTAudio, member: discord.Member) -> bool: + def skip_audio(self, audio: Audio, member: discord.Member) -> bool: if audio in self.queue: if audio.can_be_skipped_by(member): self.queue.remove(audio) @@ -208,21 +208,21 @@ class QueueAudio(discord.AudioSource): self.queue.insert(1, audio) -class ForwardView(MutableSequence[YTAudio]): - def __init__(self, sequence: MutableSequence[YTAudio]) -> None: +class ForwardView(MutableSequence[Audio]): + def __init__(self, sequence: MutableSequence[Audio]) -> None: self.sequence = sequence def __len__(self) -> int: return max(0, self.sequence.__len__() - 1) - def __setitem__(self, index: int, value: YTAudio) -> None: + def __setitem__(self, index: int, value: Audio) -> None: self.sequence.__setitem__(index + 1, value) - def __getitem__(self, index: int) -> YTAudio: + def __getitem__(self, index: int) -> Audio: return self.sequence.__getitem__(index + 1) def __delitem__(self, index: int | slice) -> None: self.sequence.__delitem__(index) - def insert(self, index: int, value: YTAudio) -> None: + def insert(self, index: int, value: Audio) -> None: self.sequence.insert(index, value) diff --git a/v6d3music/core/ystate.py b/v6d3music/core/ystate.py index 6a3b2bb..f31d427 100644 --- a/v6d3music/core/ystate.py +++ b/v6d3music/core/ystate.py @@ -5,9 +5,9 @@ from typing import Any, AsyncIterable, Callable, Coroutine, Iterable from v6d2ctx.context import Context, Explicit from v6d2ctx.integration.responsetype import ResponseType, cast_to_response -from v6d3music.core.create_ytaudio import create_ytaudio -from v6d3music.core.ytaservicing import YTAServicing -from v6d3music.core.ytaudio import YTAudio +from v6d3music.core.create_audio import create_audio +from v6d3music.core.aservicing import AServicing +from v6d3music.core.audio import Audio from v6d3music.processing.pool import JobContext, JobStatusChanged, JobUnit, Pool from v6d3music.utils.argctx import InfoCtx, UrlCtx @@ -19,14 +19,14 @@ class _Stop: class YState: - def __init__(self, servicing: YTAServicing, pool: Pool, ctx: Context, sources: Iterable[UrlCtx]) -> None: + def __init__(self, servicing: AServicing, pool: Pool, ctx: Context, sources: Iterable[UrlCtx]) -> None: self.servicing = servicing self.pool = pool self.ctx = ctx self.sources: deque[UrlCtx] = deque(sources) self.playlists: deque[asyncio.Future[list[InfoCtx]]] = deque() self.entries: deque[InfoCtx | BaseException] = deque() - self.results: asyncio.Queue[asyncio.Future[YTAudio | None] | _Stop] = asyncio.Queue() + self.results: asyncio.Queue[asyncio.Future[Audio | None] | _Stop] = asyncio.Queue() self.es = AsyncExitStack() self.descheduled: int = 0 @@ -40,7 +40,7 @@ class YState: for _ in range(self.pool.workers()): await self.es.enter_async_context(YStream(self).at(self.pool)) - async def _next_audio(self) -> YTAudio | None | _Stop: + async def _next_audio(self) -> Audio | None | _Stop: future = await self.results.get() if isinstance(future, _Stop): return _Stop() @@ -48,12 +48,12 @@ class YState: return await future except OSError as e: raise Explicit( - "extraction error\nunknown ytdl error (probably due to video being unavailable, e.g. because of regional restrictions)\nnote: sea\u200Drch is still not supported" + "extraction error\nunknown extraction error (probably due to video being unavailable, e.g. because of regional restrictions)\nnote: sea\u200Drch is still not supported" ) from e finally: self.results.task_done() - async def _iterate_with_workers(self) -> AsyncIterable[YTAudio]: + async def _iterate_with_workers(self) -> AsyncIterable[Audio]: while not self.empty(): audio = await self._next_audio() if isinstance(audio, _Stop): @@ -61,12 +61,12 @@ class YState: if audio is not None: yield audio - async def _iterate(self) -> AsyncIterable[YTAudio]: + async def _iterate(self) -> AsyncIterable[Audio]: await self._start_workers() async for audio in self._iterate_with_workers(): yield audio - async def iterate(self) -> AsyncIterable[YTAudio]: + async def iterate(self) -> AsyncIterable[Audio]: async with self.es: async for audio in self._iterate(): yield audio @@ -74,9 +74,9 @@ class YState: async def playlist(self, source: UrlCtx) -> list[InfoCtx]: return [info async for info in source.entries()] - async def result(self, entry: InfoCtx) -> YTAudio | None: + async def result(self, entry: InfoCtx) -> Audio | None: try: - return await create_ytaudio(self.servicing, self.ctx, entry) + return await create_audio(self.servicing, self.ctx, entry) except Exception: if not entry.ignore: raise @@ -117,7 +117,7 @@ class YStream(JobUnit): def _case_has_entries(self, context: JobContext, /) -> Callable[[], Coroutine[Any, Any, None]]: entry = self.state.entries.popleft() - audiotask: asyncio.Future[YTAudio | None] + audiotask: asyncio.Future[Audio | None] if isinstance(entry, BaseException): self._set_details(context, {"status": "breaking downstream audio creation"}) audiotask = asyncio.Future()