Added original spotify track to pomice.Track as an attribute
This commit is contained in:
parent
267fd32898
commit
11e4a34a96
|
|
@ -0,0 +1,212 @@
|
|||
"""
|
||||
This example aims to show the full capabilities of the library.
|
||||
This is in the form of a drop-in cog you can use and modify to your liking.
|
||||
This example aims to include everything you would need to make a fully functioning music bot,
|
||||
from a queue system, advanced queue control and more.
|
||||
"""
|
||||
|
||||
import discord
|
||||
import pomice
|
||||
import asyncio
|
||||
|
||||
from discord.ext import commands
|
||||
from contextlib import suppress
|
||||
|
||||
|
||||
class Player(pomice.Player):
|
||||
"""Custom pomice Player class."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.queue = asyncio.Queue()
|
||||
self.controller: discord.Message = None
|
||||
self.context: commands.Context = None
|
||||
self.dj: discord.Member = None
|
||||
|
||||
self.pause_votes = set()
|
||||
self.resume_votes = set()
|
||||
self.skip_votes = set()
|
||||
self.shuffle_votes = set()
|
||||
self.stop_votes = set()
|
||||
|
||||
async def do_next(self) -> None:
|
||||
# Clear the votes for a new song
|
||||
self.pause_votes.clear()
|
||||
self.resume_votes.clear()
|
||||
self.skip_votes.clear()
|
||||
self.shuffle_votes.clear()
|
||||
self.stop_votes.clear()
|
||||
|
||||
# Check if theres a controller still active and deletes it
|
||||
if self.controller:
|
||||
with suppress(discord.HTTPException):
|
||||
await self.controller.delete()
|
||||
|
||||
|
||||
# Queue up the next track, else teardown the player
|
||||
try:
|
||||
track: pomice.Track = self.queue.get_nowait()
|
||||
except asyncio.queues.QueueEmpty:
|
||||
return await self.teardown()
|
||||
|
||||
await self.play(track)
|
||||
|
||||
# Call the controller (a.k.a: The "Now Playing" embed) and check if one exists
|
||||
|
||||
if track.is_stream:
|
||||
embed = discord.Embed(title="Now playing", description=f":red_circle: **LIVE** [{track.title}]({track.uri}) [{track.requester.mention}]")
|
||||
embed.set_footer(text=f"Use {track.ctx.prefix}help for more commands!", icon_url=f"{self.client.user.avatar.url}")
|
||||
self.controller = await self.context.send(embed=embed)
|
||||
else:
|
||||
embed = discord.Embed(title=f"Now playing", description=f"[{track.title}]({track.uri}) [{track.requester.mention}]")
|
||||
embed.set_footer(text=f"Use {track.ctx.prefix}help for more commands!", icon_url=f"{self.client.user.avatar.url}")
|
||||
self.controller = await self.context.send(embed=embed)
|
||||
|
||||
|
||||
async def teardown(self):
|
||||
"""Clear internal states, remove player controller and disconnect."""
|
||||
with suppress((discord.HTTPException), (KeyError)):
|
||||
await self.destroy()
|
||||
if self.controller:
|
||||
await self.controller.delete()
|
||||
|
||||
async def set_context(self, ctx: commands.Context):
|
||||
"""Set context for the player"""
|
||||
self.context = ctx
|
||||
self.dj = ctx.author
|
||||
|
||||
|
||||
|
||||
|
||||
class Music(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot) -> None:
|
||||
self.bot = bot
|
||||
|
||||
# In order to initialize a node, or really do anything in this library,
|
||||
# you need to make a node pool
|
||||
self.pomice = pomice.NodePool()
|
||||
|
||||
async def start_nodes(self):
|
||||
# You can pass in Spotify credentials to enable Spotify querying.
|
||||
# If you do not pass in valid Spotify credentials, Spotify querying will not work
|
||||
await self.pomice.create_node(
|
||||
bot=self.bot,
|
||||
host="127.0.0.1",
|
||||
port="3030",
|
||||
password="youshallnotpass",
|
||||
identifier="MAIN"
|
||||
)
|
||||
print(f"Node is ready!")
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_pomice_track_end(self, player: Player, track, _):
|
||||
await player.do_next()
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_pomice_track_stuck(self, player: Player, track, _):
|
||||
await player.do_next()
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_pomice_track_exception(self, player: Player, track, _):
|
||||
await player.do_next()
|
||||
|
||||
@commands.command(aliases=["connect"])
|
||||
async def join(self, ctx: commands.Context, *, channel: discord.VoiceChannel = None) -> None:
|
||||
if not channel:
|
||||
channel = getattr(ctx.author.voice, "channel", None)
|
||||
if not channel:
|
||||
return await ctx.send("You must be in a voice channel in order to use this command!")
|
||||
|
||||
# With the release of discord.py 1.7, you can now add a compatible
|
||||
# VoiceProtocol class as an argument in VoiceChannel.connect().
|
||||
# This library takes advantage of that and is how you initialize a player.
|
||||
await ctx.author.voice.channel.connect(cls=Player)
|
||||
player: Player = ctx.voice_client
|
||||
# Set the player context so we can use it so send messages
|
||||
player.set_context(ctx=ctx)
|
||||
await ctx.send(f"Joined the voice channel `{channel.name}`")
|
||||
|
||||
@commands.command(aliases=["dc", "disconnect"])
|
||||
async def leave(self, ctx: commands.Context):
|
||||
if not ctx.voice_client:
|
||||
return await ctx.send("You must be in a voice channel in order to use this command!")
|
||||
|
||||
player: pomice.Player = ctx.voice_client
|
||||
|
||||
await player.destroy()
|
||||
await ctx.send("Player has left the channel.")
|
||||
|
||||
@commands.command(aliases=["p"])
|
||||
async def play(self, ctx: commands.Context, *, search: str) -> None:
|
||||
# Checks if the player is in the channel before we play anything
|
||||
if not ctx.voice_client:
|
||||
await ctx.invoke(self.join)
|
||||
|
||||
player: Player = ctx.voice_client
|
||||
|
||||
# If you search a keyword, Pomice will automagically search the result using YouTube
|
||||
# You can pass in "search_type=" as an argument to change the search type
|
||||
# i.e: player.get_tracks("query", search_type=SearchType.ytmsearch)
|
||||
# will search up any keyword results on YouTube Music
|
||||
results = await player.get_tracks(search)
|
||||
|
||||
if not results:
|
||||
raise commands.CommandError("No results were found for that search term.")
|
||||
|
||||
if isinstance(results, pomice.Playlist):
|
||||
for track in results.tracks:
|
||||
await player.queue.put(track)
|
||||
else:
|
||||
track = results[0]
|
||||
await player.queue.put(track)
|
||||
|
||||
if not player.is_playing:
|
||||
await player.play
|
||||
|
||||
|
||||
|
||||
@commands.command()
|
||||
async def pause(self, ctx: commands.Context):
|
||||
if not ctx.voice_client:
|
||||
raise commands.CommandError("No player detected")
|
||||
|
||||
player: pomice.Player = ctx.voice_client
|
||||
|
||||
if player.is_paused:
|
||||
return await ctx.send("Player is already paused!")
|
||||
|
||||
await player.set_pause(pause=True)
|
||||
await ctx.send("Player has been paused")
|
||||
|
||||
@commands.command()
|
||||
async def resume(self, ctx: commands.Context):
|
||||
if not ctx.voice_client:
|
||||
raise commands.CommandError("No player detected")
|
||||
|
||||
player: pomice.Player = ctx.voice_client
|
||||
|
||||
if not player.is_paused:
|
||||
return await ctx.send("Player is already playing!")
|
||||
|
||||
await player.set_pause(pause=False)
|
||||
await ctx.send("Player has been resumed")
|
||||
|
||||
@commands.command()
|
||||
async def stop(self, ctx: commands.Context):
|
||||
if not ctx.voice_client:
|
||||
raise commands.CommandError("No player detected")
|
||||
|
||||
player: pomice.Player = ctx.voice_client
|
||||
|
||||
if not player.is_playing:
|
||||
return await ctx.send("Player is already stopped!")
|
||||
|
||||
await player.stop()
|
||||
await ctx.send("Player has been stopped")
|
||||
|
||||
|
||||
def setup(bot: commands.Bot):
|
||||
bot.add_cog(Music(bot))
|
||||
|
||||
|
||||
|
|
@ -17,17 +17,22 @@ class Track:
|
|||
info: dict,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
spotify: bool = False,
|
||||
search_type: SearchType = SearchType.ytsearch
|
||||
search_type: SearchType = SearchType.ytsearch,
|
||||
spotify_track = None,
|
||||
):
|
||||
self.track_id = track_id
|
||||
self.info = info
|
||||
self.spotify = spotify
|
||||
|
||||
self.original: Optional[Track] = None if self.spotify else self
|
||||
self._search_type = search_type
|
||||
if self.spotify:
|
||||
self.original: Optional[Track] = None
|
||||
self._search_type = search_type
|
||||
self.spotify_track = spotify_track
|
||||
|
||||
|
||||
self.title = info.get("title")
|
||||
self.author = info.get("author")
|
||||
self.thumbnail = info.get("thumbnail")
|
||||
self.length = info.get("length")
|
||||
self.ctx = ctx
|
||||
self.requester = self.ctx.author if ctx else None
|
||||
|
|
@ -66,20 +71,18 @@ class Playlist:
|
|||
tracks: list,
|
||||
ctx: Optional[commands.Context] = None,
|
||||
spotify: bool = False,
|
||||
thumbnail: Optional[str] = None,
|
||||
uri: Optional[str] = None,
|
||||
spotify_playlist = None
|
||||
):
|
||||
self.playlist_info = playlist_info
|
||||
self.tracks_raw = tracks
|
||||
self.spotify = spotify
|
||||
|
||||
self.name = playlist_info.get("name")
|
||||
|
||||
self._thumbnail = thumbnail
|
||||
self._uri = uri
|
||||
|
||||
if self.spotify:
|
||||
self.tracks = tracks
|
||||
self.spotify_playlist = spotify_playlist
|
||||
self._thumbnail = self.spotify_playlist.image
|
||||
self._uri = self.spotify_playlist.uri
|
||||
else:
|
||||
self.tracks = [
|
||||
Track(track_id=track["track"], info=track["info"], ctx=ctx)
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ class Node:
|
|||
ctx=ctx,
|
||||
search_type=search_type,
|
||||
spotify=True,
|
||||
spotify_track=spotify_results,
|
||||
info={
|
||||
"title": spotify_results.name,
|
||||
"author": spotify_results.artists,
|
||||
|
|
@ -320,6 +321,7 @@ class Node:
|
|||
ctx=ctx,
|
||||
search_type=search_type,
|
||||
spotify=True,
|
||||
spotify_track=track,
|
||||
info={
|
||||
"title": track.name,
|
||||
"author": track.artists,
|
||||
|
|
@ -339,8 +341,7 @@ class Node:
|
|||
tracks=tracks,
|
||||
ctx=ctx,
|
||||
spotify=True,
|
||||
thumbnail=spotify_results.image,
|
||||
uri=spotify_results.uri
|
||||
spotify_playlist=spotify_results
|
||||
)
|
||||
|
||||
elif discord_url := DISCORD_MP3_URL_REGEX.match(query):
|
||||
|
|
|
|||
|
|
@ -11,7 +11,10 @@ class Playlist:
|
|||
self.owner = data["owner"]["display_name"]
|
||||
self.total_tracks = data["tracks"]["total"]
|
||||
self.id = data["id"]
|
||||
self.image = data["images"][0]["url"]
|
||||
if data.get("images"):
|
||||
self.image = data["images"][0]["url"]
|
||||
else:
|
||||
self.image = None
|
||||
self.uri = data["external_urls"]["spotify"]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
|
|
|||
Loading…
Reference in New Issue