bundle.discord.cogs.music

Music playback cog – queue-based YouTube streaming with interactive controls.

Submodules

Attributes

Classes

YoutubeResolveOptions

Base data model class, providing utilities for serialization and deserialization

PlayerControls

Six-button control strip attached to the now-playing embed: prev, pause, skip, stop, shuffle, queue.

QueuePaginator

Paginated queue browser with prev/next buttons.

PlayerEmbed

Manages the persistent now-playing message and seek-bar loop for one guild.

GuildPlayer

Owns voice playback and timing for a single guild.

TrackQueue

Ordered track list with a cursor.

GuildSession

Bundles the per-guild components.

MusicCog

Queue-based YouTube audio streaming.

Functions

vc_status(→ str)

Return 'Paused' or 'Playing' based on voice client state.

Package Contents

class bundle.discord.cogs.music.YoutubeResolveOptions(/, **data: Any)

Bases: bundle.core.data.Data

Base data model class, providing utilities for serialization and deserialization from/to JSON, along with JSON Schema generation.

model_config

Default model configuration settings.

select_video_itag: int | None = None
select_audio_itag: int | None = None
best: bool = True
class bundle.discord.cogs.music.PlayerControls(cog: bundle.discord.cogs.music.MusicCog, guild_id: int)

Bases: discord.ui.View

Six-button control strip attached to the now-playing embed: prev, pause, skip, stop, shuffle, queue.

cog
guild_id
async btn_prev(interaction: discord.Interaction, button: discord.ui.Button) None
async btn_pause(interaction: discord.Interaction, button: discord.ui.Button) None
async btn_skip(interaction: discord.Interaction, button: discord.ui.Button) None
async btn_stop(interaction: discord.Interaction, button: discord.ui.Button) None
async btn_shuffle(interaction: discord.Interaction, button: discord.ui.Button) None
async btn_queue(interaction: discord.Interaction, button: discord.ui.Button) None
class bundle.discord.cogs.music.QueuePaginator(embed_mgr: bundle.discord.cogs.music.embed.PlayerEmbed, *, timeout: float = 120)

Bases: discord.ui.View

Paginated queue browser with prev/next buttons.

async btn_prev_page(interaction: discord.Interaction, button: discord.ui.Button) None
async btn_next_page(interaction: discord.Interaction, button: discord.ui.Button) None
class bundle.discord.cogs.music.PlayerEmbed(embeds: bundle.discord.embeds.EmbedFactory, queue: bundle.discord.cogs.music.queue.TrackQueue, player: bundle.discord.cogs.music.player.GuildPlayer, text_channel: discord.TextChannel)

Manages the persistent now-playing message and seek-bar loop for one guild.

text_channel
msg: discord.Message | None = None
view: discord.ui.View | None = None
now_playing(track: bundle.youtube.track.YoutubeTrackData, status: str) discord.Embed
queue_page_count(per_page: int = 15) int
queue_embed(*, page: int = 0, per_page: int = 15) discord.Embed
async refresh(*, status: str) None

Update the persistent message with current track state.

async send_or_update(embed: discord.Embed, view: discord.ui.View | None = None) None

Send a new message or edit the existing one.

disable_view() None

Disable all buttons and stop the view.

async delete() None

Delete the persistent message and clean up the view.

async show_error(description: str) None

Update the persistent message with an error embed.

start_seek_loop(guild: discord.Guild) None
cancel_seek_loop() None
bundle.discord.cogs.music.vc_status(vc: discord.VoiceProtocol | None) str

Return ‘Paused’ or ‘Playing’ based on voice client state.

class bundle.discord.cogs.music.GuildPlayer(on_track_end: collections.abc.Callable[[int, Exception | None], collections.abc.Coroutine[Any, Any, None]])

Owns voice playback and timing for a single guild.

play_started_at: float = 0.0
pause_offset: float = 0.0
paused_at: float | None = None
elapsed_secs() int
play(vc: discord.VoiceClient, track: bundle.youtube.track.YoutubeTrackData, guild_id: int) bool

Start FFmpeg playback. Returns False if no stream URL available.

pause(vc: discord.VoiceClient) bool

Pause playback. Returns True if state changed.

resume(vc: discord.VoiceClient) bool

Resume playback. Returns True if state changed.

stop(vc: discord.VoiceClient) None

Stop current source, suppress the after callback.

class bundle.discord.cogs.music.TrackQueue

Ordered track list with a cursor.

resolving: bool = False
waiting: bool = False
property tracks: list[bundle.youtube.track.YoutubeTrackData]
property index: int
property current: bundle.youtube.track.YoutubeTrackData | None
property has_next: bool
property has_prev: bool
enqueue(track: bundle.youtube.track.YoutubeTrackData) int

Append a track; return its index.

advance(delta: int = 1) bool

Move cursor by delta. Return True if the new position is valid.

shuffle() None

Shuffle remaining tracks after the current cursor position.

pos_str() str
bundle.discord.cogs.music.log
bundle.discord.cogs.music.ALONE_TIMEOUT = 30
bundle.discord.cogs.music.PAUSE_TIMEOUT = 300
class bundle.discord.cogs.music.GuildSession

Bundles the per-guild components.

queue: queue.TrackQueue
player: player.GuildPlayer
embed: embed.PlayerEmbed
resolve_tasks: list[asyncio.Task] = []
alone_task: asyncio.Task | None = None
pause_task: asyncio.Task | None = None
class bundle.discord.cogs.music.MusicCog(bot: bundle.discord.bot.Bot)

Bases: discord.ext.commands.Cog

Queue-based YouTube audio streaming.

bot
async on_voice_state_update(member: discord.Member, before: discord.VoiceState, after: discord.VoiceState) None
async play(ctx: discord.ext.commands.Context, url: str) None

Add a YouTube URL to the queue and start playing.

async skip(ctx: discord.ext.commands.Context) None

Skip to the next track in the queue.

async prev(ctx: discord.ext.commands.Context) None

Go back to the previous track.

async show_queue(ctx: discord.ext.commands.Context) None

Display the current queue.

async stop(ctx: discord.ext.commands.Context) None

Stop playback, clear the queue, and disconnect.

async pause(ctx: discord.ext.commands.Context) None

Pause playback.

async shuffle(ctx: discord.ext.commands.Context) None

Shuffle the remaining tracks in the queue.

async resume(ctx: discord.ext.commands.Context) None

Resume paused playback.