mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-12-08 10:22:31 -05:00
First commit
This commit is contained in:
614
cogs/audio.py
Normal file
614
cogs/audio.py
Normal file
@@ -0,0 +1,614 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
import asyncio
|
||||
import threading
|
||||
import youtube_dl
|
||||
import os
|
||||
from random import choice as rndchoice
|
||||
from random import shuffle
|
||||
from .utils.dataIO import fileIO
|
||||
from .utils import checks
|
||||
import glob
|
||||
import re
|
||||
import aiohttp
|
||||
from bs4 import BeautifulSoup
|
||||
import __main__
|
||||
import json
|
||||
|
||||
if not discord.opus.is_loaded():
|
||||
discord.opus.load_opus('libopus-0.dll')
|
||||
|
||||
main_path = os.path.dirname(os.path.realpath(__main__.__file__))
|
||||
|
||||
settings = {"VOLUME" : 0.5, "MAX_LENGTH" : 3700, "QUEUE_MODE" : True}
|
||||
|
||||
youtube_dl_options = {
|
||||
'format': 'bestaudio/best',
|
||||
'extractaudio': True,
|
||||
'audioformat': "mp3",
|
||||
'outtmpl': '%(id)s',
|
||||
'noplaylist': True,
|
||||
'nocheckcertificate': True,
|
||||
'ignoreerrors': True,
|
||||
'quiet': True,
|
||||
'no_warnings': True,
|
||||
'outtmpl': "data/audio/cache/%(id)s"}
|
||||
|
||||
class Audio:
|
||||
"""Music streaming."""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.music_player = EmptyPlayer()
|
||||
self.queue_mode = False
|
||||
self.queue = []
|
||||
self.playlist = []
|
||||
self.current = -1 #current track index in self.playlist
|
||||
self.downloader = {"DONE" : False, "TITLE" : False, "ID" : False, "URL" : False, "DURATION" : False, "DOWNLOADING" : False}
|
||||
self.quit_manager = False
|
||||
self.skip_votes = []
|
||||
|
||||
self.sing = ["https://www.youtube.com/watch?v=zGTkAVsrfg8", "https://www.youtube.com/watch?v=cGMWL8cOeAU",
|
||||
"https://www.youtube.com/watch?v=vFrjMq4aL-g", "https://www.youtube.com/watch?v=WROI5WYBU_A",
|
||||
"https://www.youtube.com/watch?v=41tIUr_ex3g", "https://www.youtube.com/watch?v=f9O2Rjn1azc"]
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def play(self, ctx, link : str):
|
||||
"""Plays link
|
||||
"""
|
||||
if self.downloader["DOWNLOADING"]:
|
||||
await self.bot.say("I'm already downloading a track.")
|
||||
return
|
||||
msg = ctx.message
|
||||
if await self.check_voice(msg.author, msg):
|
||||
if self.is_playlist_valid([link]): # reusing a function
|
||||
if await self.is_alone_or_admin(msg.author):
|
||||
self.queue = []
|
||||
self.playlist = []
|
||||
self.current = -1
|
||||
await self.play_video(link)
|
||||
else:
|
||||
self.playlist = []
|
||||
self.current = -1
|
||||
if not queue: await self.bot.say("The link has been put into queue.")
|
||||
self.queue.append(link)
|
||||
else:
|
||||
await self.bot.say("That link is not allowed.")
|
||||
|
||||
@commands.command(aliases=["title"])
|
||||
async def song(self):
|
||||
"""Shows song title
|
||||
"""
|
||||
if self.downloader["TITLE"]:
|
||||
await self.bot.say(self.downloader["TITLE"])
|
||||
else:
|
||||
await self.bot.say("No title available.")
|
||||
|
||||
@commands.command(name="playlist", pass_context=True, no_pm=True)
|
||||
async def _playlist(self, ctx, name : str): #some checks here
|
||||
"""Plays saved playlist
|
||||
"""
|
||||
await self.start_playlist(ctx, name, random=False)
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def mix(self, ctx, name : str): #some checks here
|
||||
"""Plays saved playlist (shuffled)
|
||||
"""
|
||||
await self.start_playlist(ctx, name, random=True)
|
||||
|
||||
async def start_playlist(self, ctx, name, random=None):
|
||||
if self.downloader["DOWNLOADING"]:
|
||||
await self.bot.say("I'm already downloading a track.")
|
||||
return
|
||||
msg = ctx.message
|
||||
name += ".txt"
|
||||
if await self.check_voice(msg.author, msg):
|
||||
if os.path.isfile("data/audio/playlists/" + name):
|
||||
self.queue = []
|
||||
self.current = -1
|
||||
self.playlist = fileIO("data/audio/playlists/" + name, "load")["playlist"]
|
||||
if random: shuffle(self.playlist)
|
||||
self.music_player.stop()
|
||||
|
||||
@commands.command(pass_context=True, aliases=["next"], no_pm=True)
|
||||
async def skip(self, ctx):
|
||||
"""Skips song
|
||||
"""
|
||||
msg = ctx.message
|
||||
if self.music_player.is_playing():
|
||||
if await self.is_alone_or_admin(msg.author):
|
||||
self.music_player.stop()
|
||||
else:
|
||||
await self.vote_skip(msg)
|
||||
|
||||
async def vote_skip(self, msg):
|
||||
v_channel = msg.server.me.voice_channel
|
||||
if msg.author.voice_channel.id == v_channel.id:
|
||||
if msg.author.id in self.skip_votes:
|
||||
await self.bot.say("You already voted.")
|
||||
return
|
||||
self.skip_votes.append(msg.author.id)
|
||||
if msg.server.me.id not in self.skip_votes: self.skip_votes.append(msg.server.me.id)
|
||||
current_users = []
|
||||
for m in v_channel.voice_members:
|
||||
current_users.append(m.id)
|
||||
|
||||
clean_skip_votes = [] #Removes votes of people no longer in the channel
|
||||
for m_id in self.skip_votes:
|
||||
if m_id in current_users:
|
||||
clean_skip_votes.append(m_id)
|
||||
self.skip_votes = clean_skip_votes
|
||||
|
||||
votes_needed = int((len(current_users)-1) / 2)
|
||||
|
||||
if len(self.skip_votes)-1 >= votes_needed:
|
||||
self.music_player.stop()
|
||||
self.skip_votes = []
|
||||
return
|
||||
await self.bot.say("You voted to skip. Votes: [{0}/{1}]".format(str(len(self.skip_votes)-1), str(votes_needed)))
|
||||
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def local(self, ctx, name : str):
|
||||
"""Plays a local playlist"""
|
||||
if self.downloader["DOWNLOADING"]:
|
||||
await self.bot.say("I'm already downloading a track.")
|
||||
return
|
||||
msg = ctx.message
|
||||
localplaylists = self.get_local_playlists()
|
||||
if localplaylists and ("data/audio/localtracks/" not in name and "\\" not in name):
|
||||
if name in localplaylists:
|
||||
files = []
|
||||
if glob.glob("data/audio/localtracks/" + name + "/*.mp3"):
|
||||
files.extend(glob.glob("data/audio/localtracks/" + name + "/*.mp3"))
|
||||
if glob.glob("data/audio/localtracks/" + name + "/*.flac"):
|
||||
files.extend(glob.glob("data/audio/localtracks/" + name + "/*.flac"))
|
||||
if await self.is_alone_or_admin(msg.author):
|
||||
if await self.check_voice(msg.author, ctx.message):
|
||||
self.queue = []
|
||||
self.current = -1
|
||||
self.playlist = files
|
||||
self.music_player.stop()
|
||||
else:
|
||||
await self.bot.say("I'm in queue mode. Controls are disabled if you're in a room with multiple people.")
|
||||
else:
|
||||
await self.bot.say("There is no local playlist with that name.")
|
||||
else:
|
||||
await self.bot.say(message.channel, "There are no valid playlists in the localtracks folder.")
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def loop(self, ctx):
|
||||
"""Loops single song
|
||||
"""
|
||||
msg = ctx.message
|
||||
if self.music_player.is_playing():
|
||||
if await self.is_alone_or_admin(msg.author):
|
||||
if self.playlist:
|
||||
self.playlist = self.playlist[[self.current]]
|
||||
elif self.queue:
|
||||
self.playlist = self.playlist[[self.queue[0]]]
|
||||
await self.bot.say("I will play this song on repeat.")
|
||||
else:
|
||||
await self.bot.say("I'm in queue mode. Controls are disabled if you're in a room with multiple people.")
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def shuffle(self, ctx):
|
||||
"""Shuffle playlist
|
||||
"""
|
||||
msg = ctx.message
|
||||
if self.music_player.is_playing():
|
||||
if await self.is_alone_or_admin(msg.author):
|
||||
if self.playlist:
|
||||
shuffle(self.playlist)
|
||||
await self.bot.say("The order of this playlist has been mixed")
|
||||
else:
|
||||
await self.bot.say("I'm in queue mode. Controls are disabled if you're in a room with multiple people.")
|
||||
|
||||
@commands.command(pass_context=True, aliases=["previous"], no_pm=True) #TODO, PLAYLISTS
|
||||
async def prev(self, ctx):
|
||||
"""Previous song
|
||||
"""
|
||||
msg = ctx.message
|
||||
if self.music_player.is_playing() and self.playlist:
|
||||
if await self.is_alone_or_admin(msg.author):
|
||||
self.current -= 2
|
||||
if self.current == -1:
|
||||
self.current = len(self.playlist) -3
|
||||
elif self.current == -2:
|
||||
self.current = len(self.playlist) -2
|
||||
self.music_player.stop()
|
||||
|
||||
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def stop(self, ctx):
|
||||
"""Stops audio activity
|
||||
"""
|
||||
msg = ctx.message
|
||||
if self.music_player.is_playing():
|
||||
if await self.is_alone_or_admin(msg.author):
|
||||
await self.close_audio()
|
||||
else:
|
||||
await self.bot.say("You can't stop music when there are other people in the channel! Vote to skip instead.")
|
||||
else:
|
||||
await self.close_audio()
|
||||
|
||||
async def close_audio(self):
|
||||
self.queue = []
|
||||
self.playlist = []
|
||||
self.current = -1
|
||||
self.music_player.stop()
|
||||
await asyncio.sleep(1)
|
||||
await self.bot.voice.disconnect()
|
||||
|
||||
@commands.command(name="queue", pass_context=True, no_pm=True) #check that author is in the same channel as the bot
|
||||
async def _queue(self, ctx, link : str):
|
||||
"""Add link to queue
|
||||
"""
|
||||
if await self.check_voice(ctx.message.author, ctx.message):
|
||||
if not self.playlist:
|
||||
self.queue.append(link)
|
||||
await self.bot.say(self.queue)
|
||||
else:
|
||||
await self.bot.say("I'm already playing a playlist.")
|
||||
|
||||
async def is_alone_or_admin(self, author): #Direct control. fix everything
|
||||
if not settings["QUEUE_MODE"]:
|
||||
return True
|
||||
elif discord.utils.get(author.roles, name=checks.settings["ADMIN_ROLE"]) is not None:
|
||||
return True
|
||||
elif discord.utils.get(author.roles, name=checks.settings["MOD_ROLE"]) is not None:
|
||||
return True
|
||||
elif len(author.voice_channel.voice_members) == 2:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@commands.command(name="sing", pass_context=True, no_pm=True)
|
||||
async def _sing(self, ctx):
|
||||
"""Makes Red sing"""
|
||||
if self.downloader["DOWNLOADING"]:
|
||||
await self.bot.say("I'm already downloading a track.")
|
||||
return
|
||||
msg = ctx.message
|
||||
if await self.check_voice(msg.author, msg):
|
||||
if not self.music_player.is_playing():
|
||||
self.queue = []
|
||||
await self.play_video(rndchoice(self.sing))
|
||||
else:
|
||||
if await self.is_alone_or_admin(msg.author):
|
||||
self.queue = []
|
||||
await self.play_video(rndchoice(self.sing))
|
||||
else:
|
||||
await self.bot.say("I'm already playing music for someone else at the moment.")
|
||||
|
||||
@commands.group(name="list", pass_context=True)
|
||||
async def _list(self, ctx):
|
||||
"""Lists playlists"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await self.bot.say("Type help list for info.")
|
||||
|
||||
@_list.command(name="playlist", pass_context=True)
|
||||
async def list_playlist(self, ctx):
|
||||
msg = "Available playlists: \n\n```"
|
||||
files = os.listdir("data/audio/playlists/")
|
||||
if files:
|
||||
for i, f in enumerate(files):
|
||||
if f.endswith(".txt"):
|
||||
if i % 4 == 0 and i != 0:
|
||||
msg = msg + f.replace(".txt", "") + "\n"
|
||||
else:
|
||||
msg = msg + f.replace(".txt", "") + "\t"
|
||||
msg += "```"
|
||||
await self.bot.send_message(ctx.message.author, msg)
|
||||
else:
|
||||
await self.bot.say("There are no playlists.")
|
||||
|
||||
@_list.command(name="local", pass_context=True)
|
||||
async def list_local(self, ctx):
|
||||
msg = "Available local playlists: \n\n```"
|
||||
dirs = self.get_local_playlists()
|
||||
if dirs:
|
||||
for i, d in enumerate(dirs):
|
||||
if i % 4 == 0 and i != 0:
|
||||
msg = msg + d + "\n"
|
||||
else:
|
||||
msg = msg + d + "\t"
|
||||
msg += "```"
|
||||
await self.bot.send_message(ctx.message.author, msg)
|
||||
else:
|
||||
await self.bot.say("There are no local playlists.")
|
||||
|
||||
@commands.group(pass_context=True)
|
||||
@checks.mod_or_permissions()
|
||||
async def audioset(self, ctx):
|
||||
"""Changes audio module settings"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
msg = "```"
|
||||
for k, v in settings.items():
|
||||
msg += str(k) + ": " + str(v) + "\n"
|
||||
msg += "\nType help audioset to see the list of commands.```"
|
||||
await self.bot.say(msg)
|
||||
|
||||
@audioset.command(name="queue")
|
||||
async def queueset(self, status : str):
|
||||
"""Enables/disables queue"""
|
||||
global settings
|
||||
status = status.lower()
|
||||
if status == "on" or status == "true":
|
||||
settings["QUEUE_MODE"] = True
|
||||
await self.bot.say("Queue mode is now on.")
|
||||
elif status == "off" or status == "false":
|
||||
settings["QUEUE_MODE"] = False
|
||||
await self.bot.say("Queue mode is now off.")
|
||||
else:
|
||||
await self.bot.say("Queue status can be either on or off.")
|
||||
return
|
||||
self.save_settings()
|
||||
|
||||
@audioset.command()
|
||||
async def maxlength(self, length : int):
|
||||
"""Maximum track length for requested links"""
|
||||
global settings
|
||||
settings["MAX_LENGTH"] = length
|
||||
await self.bot.say("Maximum length is now " + str(length) + " seconds.")
|
||||
self.save_settings()
|
||||
|
||||
@audioset.command()
|
||||
async def volume(self, level : float):
|
||||
"""Sets the volume (0-1)"""
|
||||
global settings
|
||||
if level >= 0 and level <= 1:
|
||||
settings["VOLUME"] = level
|
||||
await self.bot.say("Volume is now set at " + str(level) + ". It will take effect after the current track.")
|
||||
self.save_settings()
|
||||
else:
|
||||
await self.bot.say("Volume must be between 0 and 1. Example: 0.40")
|
||||
|
||||
async def play_video(self, link):
|
||||
self.downloader = {"DONE" : False, "TITLE" : False, "ID" : False, "URL": False, "DURATION" : False, "DOWNLOADING" : False}
|
||||
if "https://" in link or "http://" in link:
|
||||
path = "data/audio/cache/"
|
||||
t = threading.Thread(target=self.get_video, args=(link,self,))
|
||||
t.start()
|
||||
else: #local
|
||||
path = ""
|
||||
self.downloader = {"DONE" : True, "TITLE" : link, "ID" : link, "URL": False, "DURATION" : False, "DOWNLOADING" : False}
|
||||
while not self.downloader["DONE"]:
|
||||
await asyncio.sleep(1)
|
||||
if self.downloader["ID"]:
|
||||
try:
|
||||
self.music_player.stop()
|
||||
self.music_player = self.bot.voice.create_ffmpeg_player(path + self.downloader["ID"], options='''-filter:a "volume={}"'''.format(settings["VOLUME"]))
|
||||
self.music_player.start()
|
||||
if path != "": await self.bot.change_status(discord.Game(name=self.downloader["TITLE"]))
|
||||
except discord.errors.ClientException:
|
||||
print("Error: I can't play music without ffmpeg. Install it.")
|
||||
self.downloader = {"DONE" : False, "TITLE" : False, "ID" : False, "URL": False, "DURATION" : False, "DOWNLOADING" : False}
|
||||
self.queue = []
|
||||
self.playlist = []
|
||||
except Exception as e:
|
||||
print(e)
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
async def check_voice(self, author, message):
|
||||
if self.bot.is_voice_connected():
|
||||
v_channel = message.server.me.voice_channel
|
||||
if author.voice_channel == v_channel:
|
||||
return True
|
||||
elif len(v_channel.voice_members) == 1:
|
||||
if author.is_voice_connected():
|
||||
if author.voice_channel.permissions_for(message.server.me).connect:
|
||||
await self.bot.join_voice_channel(author.voice_channel)
|
||||
return True
|
||||
else:
|
||||
await self.bot.say("I need permissions to join that voice channel.")
|
||||
return False
|
||||
else:
|
||||
await self.bot.say("You need to be in a voice channel.")
|
||||
return False
|
||||
else:
|
||||
if not self.playlist and not self.queue:
|
||||
return True
|
||||
else:
|
||||
await self.bot.say("I'm already playing music for other people.")
|
||||
return False
|
||||
elif author.voice_channel:
|
||||
if author.voice_channel.permissions_for(message.server.me).connect:
|
||||
await self.bot.join_voice_channel(author.voice_channel)
|
||||
return True
|
||||
else:
|
||||
await self.bot.say("I need permissions to join that voice channel.")
|
||||
return False
|
||||
else:
|
||||
await self.bot.say("You need to be in a voice channel.")
|
||||
return False
|
||||
|
||||
async def queue_manager(self):
|
||||
while not self.quit_manager:
|
||||
if self.queue and not self.music_player.is_playing():
|
||||
new_link = self.queue[0]
|
||||
self.queue.pop(0)
|
||||
self.skip_votes = []
|
||||
await self.play_video(new_link)
|
||||
elif self.playlist and not self.music_player.is_playing():
|
||||
if not self.current == len(self.playlist)-1:
|
||||
self.current += 1
|
||||
else:
|
||||
self.current = 0
|
||||
new_link = self.playlist[self.current]
|
||||
self.skip_votes = []
|
||||
await self.play_video(new_link)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
def get_video(self, url, audio):
|
||||
try:
|
||||
self.downloader["DOWNLOADING"] = True
|
||||
yt = youtube_dl.YoutubeDL(youtube_dl_options)
|
||||
v = yt.extract_info(url, download=False)
|
||||
if v["duration"] > settings["MAX_LENGTH"]: raise MaximumLength("Track exceeded maximum length. See help audioset maxlength")
|
||||
if not os.path.isfile("data/audio/cache/" + v["id"]):
|
||||
v = yt.extract_info(url, download=True)
|
||||
audio.downloader = {"DONE" : True, "TITLE" : v["title"], "ID" : v["id"], "URL" : url, "DURATION" : v["duration"], "DOWNLOADING" : False} #Errors out here if invalid link
|
||||
except Exception as e:
|
||||
print(e) # TODO
|
||||
audio.downloader = {"DONE" : True, "TITLE" : False, "ID" : False, "URL" : False, "DOWNLOADING" : False}
|
||||
|
||||
async def incoming_messages(self, msg): # Workaround, need to fix
|
||||
if msg.author.id != self.bot.user.id:
|
||||
cmds = ("unload cogs.audio", "reload cogs.audio")
|
||||
|
||||
if msg.content in cmds:
|
||||
self.quit_manager = True
|
||||
if msg.channel.is_private and msg.attachments != []:
|
||||
await self.transfer_playlist(msg)
|
||||
if not msg.channel.is_private:
|
||||
if not self.playlist and not self.queue and not self.music_player.is_playing() and msg.server.me.game != None:
|
||||
await self.bot.change_status(None)
|
||||
|
||||
def get_local_playlists(self):
|
||||
dirs = []
|
||||
files = os.listdir("data/audio/localtracks/")
|
||||
for f in files:
|
||||
if os.path.isdir("data/audio/localtracks/" + f) and " " not in f:
|
||||
if glob.glob("data/audio/localtracks/" + f + "/*.mp3") != []:
|
||||
dirs.append(f)
|
||||
elif glob.glob("data/audio/localtracks/" + f + "/*.flac") != []:
|
||||
dirs.append(f)
|
||||
if dirs != []:
|
||||
return dirs
|
||||
else:
|
||||
return False
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def addplaylist(self, ctx, name : str, link : str): #CHANGE COMMAND NAME
|
||||
"""Adds tracks from youtube playlist link"""
|
||||
if self.is_playlist_name_valid(name) and len(name) < 25 and self.is_playlist_link_valid(link):
|
||||
if fileIO("playlists/" + name + ".txt", "check"):
|
||||
await self.bot.say("`A playlist with that name already exists.`")
|
||||
return False
|
||||
links = await self.parse_yt_playlist(link)
|
||||
if links:
|
||||
data = { "author" : ctx.message.author.id,
|
||||
"playlist": links,
|
||||
"link" : link}
|
||||
fileIO("data/audio/playlists/" + name + ".txt", "save", data)
|
||||
await self.bot.say("Playlist added. Name: {}".format(name))
|
||||
else:
|
||||
await self.bot.say("Something went wrong. Either the link was incorrect or I was unable to retrieve the page.")
|
||||
else:
|
||||
await self.bot.say("Something is wrong with the playlist's link or its filename. Remember, the name must be with only numbers, letters and underscores. Link must be this format: https://www.youtube.com/playlist?list=PLe8jmEHFkvsaDOOWcREvkgFoj6MD0pXXX")
|
||||
|
||||
async def transfer_playlist(self, message):
|
||||
msg = message.attachments[0]
|
||||
if msg["filename"].endswith(".txt"):
|
||||
if not fileIO("data/audio/playlists/" + msg["filename"], "check"): #returns false if file already exists
|
||||
r = await aiohttp.get(msg["url"])
|
||||
r = await r.text()
|
||||
data = r.replace("\r", "")
|
||||
data = data.split()
|
||||
if self.is_playlist_valid(data) and self.is_playlist_name_valid(msg["filename"].replace(".txt", "")):
|
||||
data = { "author" : message.author.id,
|
||||
"playlist": data,
|
||||
"link" : False}
|
||||
fileIO("data/audio/playlists/" + msg["filename"], "save", data)
|
||||
await self.bot.send_message(message.channel, "Playlist added. Name: {}".format(msg["filename"].replace(".txt", "")))
|
||||
else:
|
||||
await self.bot.send_message(message.channel, "Something is wrong with the playlist or its filename.") # Add formatting info
|
||||
else:
|
||||
await self.bot.send_message(message.channel, "A playlist with that name already exists. Change the filename and resubmit it.")
|
||||
|
||||
def is_playlist_valid(self, data):
|
||||
data = [y for y in data if y != ""] # removes all empty elements
|
||||
data = [y for y in data if y != "\n"]
|
||||
pattern = "|".join(fileIO("data/audio/accepted_links.json", "load"))
|
||||
for link in data:
|
||||
rr = re.search(pattern, link, re.I | re.U)
|
||||
if rr == None:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_playlist_link_valid(self, link):
|
||||
pattern = "^https:\/\/www.youtube.com\/playlist\?list=(.[^:/]*)"
|
||||
rr = re.search(pattern, link, re.I | re.U)
|
||||
if not rr == None:
|
||||
return rr.group(1)
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_playlist_name_valid(self, name):
|
||||
for l in name:
|
||||
if l.isdigit() or l.isalpha() or l == "_":
|
||||
pass
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
async def parse_yt_playlist(self, url):
|
||||
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
|
||||
try:
|
||||
page = await aiohttp.post(url, headers=headers)
|
||||
page = await page.text()
|
||||
soup = BeautifulSoup(page, 'html.parser')
|
||||
tags = soup.find_all("tr", class_="pl-video yt-uix-tile ")
|
||||
links = []
|
||||
|
||||
for tag in tags:
|
||||
links.append("https://www.youtube.com/watch?v=" + tag['data-video-id'])
|
||||
if links != []:
|
||||
return links
|
||||
else:
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
def save_settings(self):
|
||||
with open(main_path + "/data/audio/settings.json", "w") as f:
|
||||
f.write(json.dumps(settings))
|
||||
|
||||
class EmptyPlayer(): #dummy player
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
def is_playing(self):
|
||||
return False
|
||||
|
||||
class MaximumLength(Exception):
|
||||
def __init__(self, m):
|
||||
self.message = m
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
||||
def check_folders():
|
||||
folders = ("data/audio", "data/audio/cache", "data/audio/playlists")
|
||||
for folder in folders:
|
||||
if not os.path.exists(folder):
|
||||
print("Creating " + folder + " folder...")
|
||||
os.makedirs(folder)
|
||||
|
||||
def check_files(n):
|
||||
if not os.path.isfile(main_path + "/data/audio/settings.json"):
|
||||
print("Creating default audio settings.json...")
|
||||
n.save_settings()
|
||||
|
||||
allowed = ["^(https:\/\/www\\.youtube\\.com\/watch\\?v=...........*)", "^(https:\/\/youtu.be\/...........*)",
|
||||
"^(https:\/\/youtube\\.com\/watch\\?v=...........*)", "^(https:\/\/soundcloud\\.com\/.*)"]
|
||||
|
||||
if not os.path.isfile(main_path + "/data/audio/accepted_links.json"):
|
||||
print("Creating accepted_links.json...")
|
||||
with open(main_path + "/data/audio/accepted_links.json", "w") as f:
|
||||
f.write(json.dumps(allowed))
|
||||
|
||||
def setup(bot):
|
||||
loop = asyncio.get_event_loop()
|
||||
n = Audio(bot)
|
||||
check_folders()
|
||||
check_files(n)
|
||||
loop.create_task(n.queue_manager())
|
||||
bot.add_listener(n.incoming_messages, "on_message")
|
||||
bot.add_cog(n)
|
||||
Reference in New Issue
Block a user