Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
import discord
from discord.ext import commands
# dictionaries using server ids to store the values of context objects so that they can be usedin other functions and not async
players = {}
queues = {}
voice_client = {}
class Music:
def __init__(self, client):
self.client = client
def check_queue(self, id):
# try is for key errors if a queue doesn't exist
try:
# if the queue is empty disconnect
if not queues[id]:
voice = voice_client[id]
# disconnects the voice is written like this since co-routines don't run in afters so you have to do
# it in a specific way
discord.compat.run_coroutine_threadsafe(voice.disconnect(),
self.client.loop)
if queues[id]:
players[id].stop()
song = queues[id][0]
# supposed to send a message with info of the next song but it doesn't work consistently yet
discord.compat.run_coroutine_threadsafe(self.client.say(
"Now playing {} by {} ,time:{}mins".format(song.title, song.uploader, round(song.duration / 60),
2)),
self.client.loop)
player = queues[id].pop(0)
players[id] = player
player.start()
except:
# disconnects the voice is written like this since co-routines don't run in afters so you have to do it in a
# specific way
voice = voice_client[id]
discord.compat.run_coroutine_threadsafe(voice.disconnect(),
self.client.loop)
@commands.command(description="takes a youtube url and joins the channel and plays it",
brief="plays youtube audio",
pass_context=True)
async def play(self, ctx, *url: str):
"""creates a new voice client session, coverts a youtube video into a playable format and plays it,
if a player exists it creates a queue """
# appends arguments into one string so it can have spaces in the search
url = "{}".format(" ".join(url))
# sets a voice client = to the one currently in the voice channel so it can be parsed ,if it doesn't exist it
# will be null
voice = self.client.voice_client_in(ctx.message.server)
# puts the voice client in a dictionary so the context object can be used outside the command specifically
# for disconnecting after the steam is over
voice_client[ctx.message.server.id] = voice
# options for the youtube dl player
opts = {
'default_search': 'auto',
'quiet': True,
'skip_download': True
}
# will go through try if a voice client exists already
try:
if voice.is_connected():
player = await voice.create_ytdl_player(url, ytdl_options=opts
,after=lambda: self.check_queue(ctx.message.server.id)
)
# adding players to a queue or creating a queue depending on if one already exists or not
if ctx.message.server.id in queues:
queues[ctx.message.server.id].append(player)
else:
queues[ctx.message.server.id] = [player]
await self.client.say("Searching for {} \nQueued {} by {}".format(url, player.title, player.uploader))
except:
voice = await self.client.join_voice_channel(ctx.message.author.voice_channel)
voice_client[ctx.message.server.id]=voice
player = await voice.create_ytdl_player(url, ytdl_options=opts,
after=lambda: self.check_queue(ctx.message.server.id))
# adds the player to the players dictionary with the server id as a key
players[ctx.message.server.id] = player
await self.client.say(
"Searching for {} \nNow playing {} by {} ,time:{}mins".format(url, player.title, player.uploader,
round(player.duration / 60), 2))
player.start()
@commands.command(description="leaves voice",
brief="leaves current voice channel",
pass_context=True)
async def leave(self, ctx):
"""disconnects from the voice if a voice session in the server exists"""
voice = self.client.voice_client_in(ctx.message.server)
await voice.disconnect()
# used guide https://www.youtube.com/watch?v=KEZuva7yeq8 to help write commands wrapped below
############################################################################################
@commands.command(description="pauses current media stream",
brief="pauses music",
pass_context=True)
async def pause(self, ctx):
"""pauses the servers player getting the playing from the players dictionary"""
players[ctx.message.server.id].pause()
@commands.command(description="stops current media stream",
brief="stops music",
pass_context=True)
async def stop(self, ctx):
"""stops the current player and leaves the current voice channel if it exists"""
players[ctx.message.server.id].stop()
voice = self.client.voice_client_in(ctx.message.server)
await voice.disconnect()
@commands.command(description="resumes media stream",
brief="un-pauses music",
pass_context=True)
async def resume(self, ctx):
"""resumes the servers player getting the playing from the players dictionary"""
players[ctx.message.server.id].resume()
############################################################################################
@commands.command(description="skips to the next song in queue",
brief="skips song",
pass_context=True)
async def skip(self, ctx):
"""performs the check_queue function that happens after a song is ended due to this it's buggy as hell as the
after for the players trigger as well"""
voice = self.client.voice_client_in(ctx.message.server)
players[ctx.message.server.id].stop()
self.check_queue(ctx.message.server.id)
@commands.command(description="returns the current players youtube url",
brief="gets the url of the video playing",
pass_context=True)
async def url(self,ctx):
"""supposed to get the current url of the current player but it just lies to me"""
player = players[ctx.message.server.id]
await self.client.say(player.url)
# adding the music cog
def setup(client):
client.add_cog(Music(client))