Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions DiscordUtils/InviteTracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ async def cache_invites(self):
try:
invs = await guild.invites()
for invite in invs:
if invite.inviter not in self._cache[guild.id].keys():
if invite.inviter not in self._cache[guild.id]:
self._cache[guild.id][invite.inviter] = []
self._cache[guild.id][invite.inviter].append(invite)
except discord.errors.Forbidden:
pass

async def update_invite_cache(self, invite):
try:
if not invite.guild.id in self._cache.keys():
if not invite.guild.id in self._cache:
self._cache[invite.guild.id] = {}
if not invite.inviter in self._cache[invite.guild.id].keys():
if not invite.inviter in self._cache[invite.guild.id]:
self._cache[invite.guild.id][invite.inviter] = []
self._cache[invite.guild.id][invite.inviter].append(invite)
except discord.errors.Forbidden:
Expand All @@ -37,15 +37,15 @@ async def remove_invite_cache(self, invite):
break

async def remove_guild_cache(self, guild):
if guild.id in self._cache.keys():
if guild.id in self._cache:
del self._cache[guild.id]

async def update_guild_cache(self, guild):
try:
invs = await guild.invites()
self._cache[guild.id] = {}
for invite in invs:
if not invite.inviter in self._cache[guild.id].keys():
if not invite.inviter in self._cache[guild.id]:
self._cache[guild.id][invite.inviter] = []
self._cache[guild.id][invite.inviter].append(invite)
except discord.errors.Forbidden:
Expand All @@ -59,7 +59,7 @@ async def fetch_inviter(self, member):
except discord.errors.Forbidden:
return
for invite in new_invites:
if not invite.inviter in invs.keys():
if not invite.inviter in invs:
invs[invite.inviter] = []
invs[invite.inviter].append(invite)
for new_invite_key in invs:
Expand All @@ -73,6 +73,4 @@ async def fetch_inviter(self, member):
cached_invite_list.remove(old_invite)
cached_invite_list.append(new_invite)
return new_invite_key
break
else:
return None
break
152 changes: 71 additions & 81 deletions DiscordUtils/Music.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,56 +33,32 @@ async def ytbettersearch(query):
return url

async def get_video_data(url, search, bettersearch, loop):
if not search and not bettersearch:
if bettersearch:
url = await ytbettersearch(url)
data = await loop.run_in_executor(None, lambda: ydl.extract_info(url, download=False))
source = data["url"]
url = "https://www.youtube.com/watch?v="+data["id"]
title = data["title"]
description = data["description"]
likes = data["like_count"]
dislikes = data["dislike_count"]
views = data["view_count"]
duration = data["duration"]
thumbnail = data["thumbnail"]
channel = data["uploader"]
channel_url = data["uploader_url"]
return Song(source, url, title, description, views, duration, thumbnail, channel, channel_url, False)
elif search:
ytdl = youtube_dl.YoutubeDL({"format": "bestaudio/best", "restrictfilenames": True, "noplaylist": True, "nocheckcertificate": True, "ignoreerrors": True, "logtostderr": False, "quiet": True, "no_warnings": True, "default_search": "auto", "source_address": "0.0.0.0"})
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=False))
try:
data = data["entries"][0]
except (KeyError, TypeError):
pass
del ytdl
else:
if bettersearch:
url = await ytbettersearch(url)
data = await loop.run_in_executor(None, lambda: ydl.extract_info(url, download=False))
source = data["url"]
url = "https://www.youtube.com/watch?v="+data["id"]
title = data["title"]
description = data["description"]
likes = data["like_count"]
dislikes = data["dislike_count"]
views = data["view_count"]
duration = data["duration"]
thumbnail = data["thumbnail"]
channel = data["uploader"]
channel_url = data["uploader_url"]
return Song(source, url, title, description, views, duration, thumbnail, channel, channel_url, False)
elif search:
ytdl = youtube_dl.YoutubeDL({"format": "bestaudio/best", "restrictfilenames": True, "noplaylist": True, "nocheckcertificate": True, "ignoreerrors": True, "logtostderr": False, "quiet": True, "no_warnings": True, "default_search": "auto", "source_address": "0.0.0.0"})
data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=False))
try:
data = data["entries"][0]
except KeyError or TypeError:
pass
del ytdl
source = data["url"]
url = "https://www.youtube.com/watch?v="+data["id"]
title = data["title"]
description = data["description"]
likes = data["like_count"]
dislikes = data["dislike_count"]
views = data["view_count"]
duration = data["duration"]
thumbnail = data["thumbnail"]
channel = data["uploader"]
channel_url = data["uploader_url"]
return Song(source, url, title, description, views, duration, thumbnail, channel, channel_url, False)
data = await loop.run_in_executor(None, lambda: ydl.extract_info(url, download=False))

source = data["url"]
url = f"https://www.youtube.com/watch?v={data['id']}"
title = data["title"]
description = data["description"]
likes = data["like_count"]
dislikes = data["dislike_count"]
views = data["view_count"]
duration = data["duration"]
thumbnail = data["thumbnail"]
channel = data["uploader"]
channel_url = data["uploader_url"]
return Song(source, url, title, description, views, duration, thumbnail, channel, channel_url, False)

def check_queue(ctx, opts, music, after, on_play, loop):
try:
Expand All @@ -91,10 +67,10 @@ def check_queue(ctx, opts, music, after, on_play, loop):
return
if not song.is_looping:
try:
music.queue[ctx.guild.id].pop(0)
music.queue[ctx.guild.id].pop()
except IndexError:
return
if len(music.queue[ctx.guild.id]) > 0:
if len(music.queue[ctx.guild.id]):
source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(music.queue[ctx.guild.id][0].source, **opts))
ctx.voice_client.play(source, after=lambda error: after(ctx, opts, music, after, on_play, loop))
song = music.queue[ctx.guild.id][0]
Expand All @@ -111,93 +87,101 @@ class Music(object):
def __init__(self):
self.queue = {}
self.players = []

def create_player(self, ctx, **kwargs):
if not ctx.voice_client:
raise NotConnectedToVoice("Cannot create the player because bot is not connected to voice")
player = MusicPlayer(ctx, self, **kwargs)
self.players.append(player)
return player
def get_player(self, **kwargs):
guild = kwargs.get("guild_id")
channel = kwargs.get("channel_id")

def get_player(self, guild_id=None, channel_id=None):
for player in self.players:
if guild and channel and player.ctx.guild.id == guild and player.voice.channel.id == channel:
return player
elif not guild and channel and player.voice.channel.id == channel:
return player
elif not channel and guild and player.ctx.guild.id == guild:
if (guild_id and channel_id and player.ctx.guild.id == guild_id and player.voice.channel.id == channel_id) or (not guild_id and channel_id and player.voice.channel.id == channel_id) or (not channel_id and guild_id and player.ctx.guild.id == guild_id):
return player
else:
return None

class MusicPlayer(object):
def __init__(self, ctx, music, **kwargs):
self.ctx = ctx
self.voice = ctx.voice_client
self.loop = ctx.bot.loop
self.music = music
if self.ctx.guild.id not in self.music.queue.keys():
if self.ctx.guild.id not in self.music.queue:
self.music.queue[self.ctx.guild.id] = []
self.after_func = check_queue
self.on_play_func = self.on_queue_func = self.on_skip_func = self.on_stop_func = self.on_pause_func = self.on_resume_func = self.on_loop_toggle_func = self.on_volume_change_func = self.on_remove_from_queue_func = None
ffmpeg_error = kwargs.get("ffmpeg_error_betterfix", kwargs.get("ffmpeg_error_fix"))
if ffmpeg_error and "ffmpeg_error_betterfix" in kwargs.keys():
if ffmpeg_error and "ffmpeg_error_betterfix" in kwargs:
self.ffmpeg_opts = {"options": "-vn -loglevel quiet -hide_banner -nostats", "before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 0 -nostdin"}
elif ffmpeg_error:
self.ffmpeg_opts = {"options": "-vn", "before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 0 -nostdin"}
else:
self.ffmpeg_opts = {"options": "-vn", "before_options": "-nostdin"}

def disable(self):
self.music.players.remove(self)

def on_queue(self, func):
self.on_queue_func = func

def on_play(self, func):
self.on_play_func = func

def on_skip(self, func):
self.on_skip_func = func

def on_stop(self, func):
self.on_stop_func = func

def on_pause(self, func):
self.on_pause_func = func

def on_resume(self, func):
self.on_resume_func = func

def on_loop_toggle(self, func):
self.on_loop_toggle_func = func

def on_volume_change(self, func):
self.on_volume_change_func = func

def on_remove_from_queue(self, func):
self.on_remove_from_queue_func = func

async def queue(self, url, search=False, bettersearch=False):
song = await get_video_data(url, search, bettersearch, self.loop)
self.music.queue[self.ctx.guild.id].append(song)
if self.on_queue_func:
await self.on_queue_func(self.ctx, song)
return song

async def play(self):
source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(self.music.queue[self.ctx.guild.id][0].source, **self.ffmpeg_opts))
self.voice.play(source, after=lambda error: self.after_func(self.ctx, self.ffmpeg_opts, self.music, self.after_func, self.on_play_func, self.loop))
song = self.music.queue[self.ctx.guild.id][0]
if self.on_play_func:
await self.on_play_func(self.ctx, song)
return song

async def skip(self, force=False):
if len(self.music.queue[self.ctx.guild.id]) == 0:
raise NotPlaying("Cannot loop because nothing is being played")
elif not len(self.music.queue[self.ctx.guild.id]) > 1 and not force:
raise EmptyQueue("Cannot skip because queue is empty")
else:
old = self.music.queue[self.ctx.guild.id][0]
old.is_looping = False if old.is_looping else False
self.voice.stop()
try:
new = self.music.queue[self.ctx.guild.id][0]
if self.on_skip_func:
await self.on_skip_func(self.ctx, old, new)
return (old, new)
except IndexError:
if self.on_skip_func:
await self.on_skip_func(self.ctx, old)
return old

old = self.music.queue[self.ctx.guild.id][0]
old.is_looping = False
self.voice.stop()
try:
new = self.music.queue[self.ctx.guild.id][0]
if self.on_skip_func:
await self.on_skip_func(self.ctx, old, new)
return (old, new)
except IndexError:
if self.on_skip_func:
await self.on_skip_func(self.ctx, old)
return old

async def stop(self):
try:
self.music.queue[self.ctx.guild.id] = []
Expand All @@ -207,6 +191,7 @@ async def stop(self):
raise NotPlaying("Cannot loop because nothing is being played")
if self.on_stop_func:
await self.on_stop_func(self.ctx)

async def pause(self):
try:
self.voice.pause()
Expand All @@ -216,6 +201,7 @@ async def pause(self):
if self.on_pause_func:
await self.on_pause_func(self.ctx, song)
return song

async def resume(self):
try:
self.voice.resume()
Expand All @@ -225,28 +211,30 @@ async def resume(self):
if self.on_resume_func:
await self.on_resume_func(self.ctx, song)
return song

def current_queue(self):
try:
return self.music.queue[self.ctx.guild.id]
except KeyError:
raise EmptyQueue("Queue is empty")

def now_playing(self):
try:
return self.music.queue[self.ctx.guild.id][0]
except:
return None
pass

async def toggle_song_loop(self):
try:
song = self.music.queue[self.ctx.guild.id][0]
except:
raise NotPlaying("Cannot loop because nothing is being played")
if not song.is_looping:
song.is_looping = True
else:
song.is_looping = False

song.is_looping = not song.is_looping
if self.on_loop_toggle_func:
await self.on_loop_toggle_func(self.ctx, song)
return song

async def change_volume(self, vol):
self.voice.source.volume = vol
try:
Expand All @@ -256,6 +244,7 @@ async def change_volume(self, vol):
if self.on_volume_change_func:
await self.on_volume_change_func(self.ctx, song, vol)
return (song, vol)

async def remove_from_queue(self, index):
if index == 0:
try:
Expand All @@ -269,6 +258,7 @@ async def remove_from_queue(self, index):
if self.on_remove_from_queue_func:
await self.on_remove_from_queue_func(self.ctx, song)
return song

def delete(self):
self.music.players.remove(self)

Expand All @@ -284,4 +274,4 @@ def __init__(self, source, url, title, description, views, duration, thumbnail,
self.thumbnail = thumbnail
self.channel = channel
self.channel_url = channel_url
self.is_looping = loop
self.is_looping = loop
Loading