Skip to content
Permalink
Browse files
Music file
  • Loading branch information
emrulovd committed Nov 29, 2018
1 parent 8e4ae61 commit 95c8644dc4dd2c6bd1ac9c3d2769cf207f7f7ee7
Showing 1 changed file with 227 additions and 0 deletions.
227 musci.py
@@ -0,0 +1,227 @@
import asyncio
import discord
from discord.voice_client import VoiceClient
from discord.ext import commands
if not discord.opus.is_loaded():
# the 'opus' library here is opus.dll on windows
# or libopus.so on linux in the current directory
# you should replace this with the location the
# opus library is located in and with the proper filename.
# note that on windows this DLL is automatically provided for you
discord.opus.load_opus('opus')
"""I took this code from https://mega.nz/#!eopkmZrD!6vNS6xitffXDp41JcO4-kjV5gxqrTuHcirgZiN4Vj2M
but I had to rewrite the commands from discord.py 0.16 version to discord.py 1.0.0a version . """
def __init__(self, bot):
self.bot = bot

class VoiceEntry:
def __init__(self, message, player):
self.requester = message.author
self.channel = message.channel
self.player = player

def __str__(self):
fmt = ' {0.title} uploaded by {0.uploader} and requested by {1.display_name}'
duration = self.player.duration
if duration:
fmt = fmt + ' [length: {0[0]}m {0[1]}s]'.format(divmod(duration, 60))
return fmt.format(self.player, self.requester)

class VoiceState:
def __init__(self, bot):
self.current = None
self.voice = None
self.bot = bot
self.play_next_song = asyncio.Event()
self.songs = asyncio.Queue()
self.skip_votes = set() # a set of user_ids that voted
self.audio_player = self.bot.loop.create_task(self.audio_player_task())

def is_playing(self):
if self.voice is None or self.current is None:
return False

player = self.current.player
return not player.is_done()

@property
def player(self):
return self.current.player

def skip(self):
self.skip_votes.clear()
if self.is_playing():
self.player.stop()

def toggle_next(self):
self.bot.loop.call_soon_threadsafe(self.play_next_song.set)

async def audio_player_task(self):
while True:
self.play_next_song.clear()
self.current = await self.songs.get()
await self.bot.send_message(self.current.channel, 'Now playing' + str(self.current))
self.current.player.start()
await self.play_next_song.wait()
class Music:
"""Voice related commands.
Works in multiple servers at once.
"""
def __init__(self, bot):
self.bot = bot
self.voice_states = {}

def get_voice_state(self, server):
state = self.voice_states.get(server.id)
if state is None:
state = VoiceState(self.bot)
self.voice_states[server.id] = state

return state

async def create_voice_client(self, channel):
voice = await self.bot.VoiceChannel.connect(channel)
state = self.get_voice_state(channel.server)
state.voice = voice

def __unload(self):
for state in self.voice_states.values():
try:
state.audio_player.cancel()
if state.voice:
self.bot.loop.create_task(state.voice.disconnect())
except:
pass

@commands.command(pass_context=True, no_pm=True)
async def join(self, ctx, *, channel : discord.channel):
"""Joins a voice channel."""
try:
await self.create_voice_client(channel)
except discord.ClientException:
await self.ctx.send('Already in a voice channel...')
except discord.InvalidArgument:
await self.ctx.send('This is not a voice channel...')
else:
await self.ctx.send('Ready to play audio in **' + channel.name)

@commands.command(pass_context=True, no_pm=True)
async def summon(self, ctx):
"""Summons the bot to join your voice channel."""
summoned_channel = ctx.message.author.voice.channel
if summoned_channel is None:
await self.ctx.send('Are you sure your in a channel?')
return False

state = self.get_voice_state(ctx.message.guild)
if state.voice is None:
state.voice = await self.bot.VoiceChannel.connect(summoned_channel)
else:
await state.voice.move_to(summoned_channel)

return True

@commands.command(pass_context=True, no_pm=True)
async def play(self, ctx, song : str):
"""Plays a song.
"""
state = self.get_voice_state(ctx.channel.guild)
opts = {
'default_search': 'auto',
'quiet': True,
}

if state.voice is None:
success = await ctx.invoke(self.summon)
await self.bot.say("Loading the song please be patient..")
if not success:
return

try:
player = await state.voice.create_ytdl_player(song, ytdl_options=opts, after=state.toggle_next)
except Exception as e:
fmt = 'An error occurred while processing this request: ```py\n{}: {}\n```'
await self.bot.send_message(ctx.message.channel, fmt.format(type(e).__name__, e))
else:
player.volume = 0.6
entry = VoiceEntry(ctx.message, player)
await self.ctx.send('Enqueued ' + str(entry))
await state.songs.put(entry)

@commands.command(pass_context=True, no_pm=True)
async def volume(self, ctx, value : int):
"""Sets the volume of the currently playing song."""

state = self.get_voice_state(ctx.message.server)
if state.is_playing():
player = state.player
player.volume = value / 100
await self.bot.say('Set the volume to {:.0%}'.format(player.volume))
@commands.command(pass_context=True, no_pm=True)
async def resume(self, ctx):
"""Resumes the currently played song."""
state = self.get_voice_state(ctx.message.guild)
if state.is_playing():
player = state.player
player.resume()

@commands.command(pass_context=True, no_pm=True)
async def stop(self, ctx):
"""Stops playing audio and leaves the voice channel.
This also clears the queue.
"""
server = ctx.message.guild
state = self.get_voice_state(server)

if state.is_playing():
player = state.player
player.stop()

try:
state.audio_player.cancel()
del self.voice_states[server.id]
await state.voice.disconnect()
await self.ctx.send("Cleared the queue and disconnected from voice channel ")
except:
pass

@commands.command(pass_context=True, no_pm=True)
async def skip(self, ctx):
"""Vote to skip a song. The song requester can automatically skip.
3 skip votes are needed for the song to be skipped.
"""

state = self.get_voice_state(ctx.message.guild)
if not state.is_playing():
await self.ctx.send('Not playing any music right now...')
return

voter = ctx.message.author
if voter == state.current.requester:
await self.ctx.send('Requester requested skipping song...')
state.skip()
elif voter.id not in state.skip_votes:
state.skip_votes.add(voter.id)
total_votes = len(state.skip_votes)
if total_votes >= 3:
await self.ctx.send('Skip vote passed, skipping song...')
state.skip()
else:
await self.ctx.send('Skip vote added, currently at [{}/3]'.format(total_votes))
else:
await self.ctx.send('You have already voted to skip this song.')

@commands.command(pass_context=True, no_pm=True)
async def playing(self, ctx):
"""Shows info about the currently played song."""

state = self.get_voice_state(ctx.message.guild)
if state.current is None:
await self.ctx.send('Not playing anything.')
else:
skip_count = len(state.skip_votes)
await self.ctx.send('Now playing {} [skips: {}/3]'.format(state.current, skip_count))

def setup(bot):
bot.add_cog(Music(bot))
print('Music is loaded')

0 comments on commit 95c8644

Please sign in to comment.