Permalink
Cannot retrieve contributors at this time
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?
chatBotProject/Music.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
143 lines (128 sloc)
6.92 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) |