Merge remote-tracking branch 'upstream/develop' into develop

This commit is contained in:
scummboy 2016-02-17 10:46:31 +00:00
commit 375e447a97
4 changed files with 341 additions and 13 deletions

View File

@ -60,9 +60,10 @@ class Audio:
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.queue = []
self.current = -1
self.playlist = [link]
self.playlist = []
self.queue.append(link)
self.music_player.stop()
else:
self.playlist = []
@ -140,7 +141,7 @@ class Audio:
votes_needed = int((len(current_users)-1) / 2)
if len(self.skip_votes)-1 >= votes_needed:
if len(self.skip_votes)-1 >= votes_needed:
self.music_player.stop()
self.skip_votes = []
return
@ -245,7 +246,16 @@ class Audio:
if await self.check_voice(ctx.message.author, ctx.message):
if not self.playlist:
self.queue.append(link)
await self.bot.say("Link added to queue.")
msg = ctx.message
result = await self.get_song_metadata(link)
try: # In case of invalid SOUNDCLOUD ID
if result["title"] != []:
await self.bot.say("{} has been put into the queue by {}.".format(result["title"], msg.author))
else:
await self.bot.say("The song has been put into the queue by {}, however it may error.".format(msg.author))
except:
await self.bot.say("A song has been put into the queue by {}.".format(msg.author))
else:
await self.bot.say("I'm already playing a playlist.")
@ -318,6 +328,29 @@ class Audio:
else:
await self.bot.say("There are no local playlists.")
@_list.command(name="queue", pass_context=True)
async def list_queue(self, ctx):
message = ctx.message
cmdmsg = message
song_names = []
song_names.append(self.downloader["TITLE"])
if len(self.queue) > 0:
for song_url in self.queue:
try:
result = await self.get_song_metadata(song_url)
if result["title"] != []:
song_names.append(result["title"])
else:
song_names.append("Could not get song title")
except:
song_names.append("Could not get song title")
song_list = '\n'.join('{}: {}'.format(*k) for k in enumerate(song_names))
elif self.music_player.is_playing():
song_list = "0: {}".format(song_names)
else:
song_list = "None"
await self.bot.say("Videos in queue: \n" + song_list)
@commands.group(pass_context=True)
@checks.mod_or_permissions()
async def audioset(self, ctx):
@ -336,7 +369,7 @@ class Audio:
if status == "on" or status == "true":
self.settings["QUEUE_MODE"] = True
await self.bot.say("Queue mode is now on.")
elif status == "off" or status == "false":
elif status == "off" or status == "false":
self.settings["QUEUE_MODE"] = False
await self.bot.say("Queue mode is now off.")
else:
@ -374,6 +407,17 @@ class Audio:
else:
await self.bot.say("Maximum audio cache size has been set to " + str(size) + "MB.")
@audioset.command()
@checks.is_owner()
async def soundcloud(self, ID : str=None):
"""Sets the SoundCloud Client ID
"""
self.settings["SOUNDCLOUD_CLIENT_ID"] = ID
fileIO("data/audio/settings.json", "save", self.settings)
if not ID:
await self.bot.say("SoundCloud API intergration has been disabled")
else:
await self.bot.say("SoundCloud Client ID has been set")
@commands.group(pass_context=True)
@checks.is_owner()
@ -402,7 +446,7 @@ class Audio:
for f in total:
size += f
return int(size / (1024*1024.0))
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:
@ -505,7 +549,7 @@ class Audio:
print("Cache emptied.")
if msg.channel.is_private and msg.attachments != []:
await self.transfer_playlist(msg)
if not msg.channel.is_private:
@ -608,6 +652,39 @@ class Audio:
except:
return False
async def get_json(self, url):
"""
Returns the JSON from an URL.
Expects the url to be valid and return a JSON object.
"""
async with aiohttp.get(url) as r:
result = await r.json()
return result
async def get_song_metadata(self, song_url):
"""
Returns JSON object containing metadata about the song.
Expects song_url to be valid url and in acepted_list
"""
youtube_regex = (
r'(https?://)?(www\.)?'
'(youtube|youtu|youtube-nocookie)\.(com|be)/'
'(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')
soundcloud_regex = "^(https:\\/\\/soundcloud\\.com\\/.*)"
is_youtube_link = re.match(youtube_regex, song_url)
is_soundcloud_link = re.match(soundcloud_regex, song_url)
if is_youtube_link:
url = "http://www.youtube.com/oembed?url={0}&format=json".format(song_url)
result = await self.get_json(url)
elif is_soundcloud_link and (self.settings["SOUNDCLOUD_CLIENT_ID"] is not None):
url = "http://api.soundcloud.com/resolve.json?url={0}&client_id={1}".format(song_url, self.settings["SOUNDCLOUD_CLIENT_ID"])
result = await self.get_json(url)
else:
result = {"title": "A song "}
return result
class EmptyPlayer(): #dummy player
def __init__(self):
pass
@ -632,8 +709,8 @@ def check_folders():
os.makedirs(folder)
def check_files():
default = {"VOLUME" : 0.5, "MAX_LENGTH" : 3700, "QUEUE_MODE" : True, "MAX_CACHE" : 0}
default = {"VOLUME" : 0.5, "MAX_LENGTH" : 3700, "QUEUE_MODE" : True, "MAX_CACHE" : 0, "SOUNDCLOUD_CLIENT_ID": None}
settings_path = "data/audio/settings.json"
if not os.path.isfile(settings_path):
@ -651,7 +728,7 @@ def check_files():
allowed = ["^(https:\/\/www\\.youtube\\.com\/watch\\?v=...........*)", "^(https:\/\/youtu.be\/...........*)",
"^(https:\/\/youtube\\.com\/watch\\?v=...........*)", "^(https:\/\/soundcloud\\.com\/.*)"]
if not os.path.isfile("data/audio/accepted_links.json"):
print("Creating accepted_links.json...")
fileIO("data/audio/accepted_links.json", "save", allowed)
@ -663,4 +740,4 @@ def setup(bot):
n = Audio(bot)
loop.create_task(n.queue_manager())
bot.add_listener(n.incoming_messages, "on_message")
bot.add_cog(n)
bot.add_cog(n)

View File

@ -123,4 +123,4 @@ def setup(bot):
check_files()
n = CustomCommands(bot)
bot.add_listener(n.checkCC, "on_message")
bot.add_cog(n)
bot.add_cog(n)

251
cogs/streams.py Normal file
View File

@ -0,0 +1,251 @@
import discord
from discord.ext import commands
from .utils.dataIO import fileIO
from .utils import checks
import os
import time
import aiohttp
import asyncio
from copy import deepcopy
import logging
class Streams:
"""Streams
Twitch and Hitbox alerts"""
def __init__(self, bot):
self.bot = bot
self.twitch_streams = fileIO("data/streams/twitch.json", "load")
self.hitbox_streams = fileIO("data/streams/hitbox.json", "load")
self.pattern = {"CHANNELS" : [], "NAME" : "", "ALREADY_ONLINE" : False}
@commands.command()
async def hitbox(self, stream : str):
"""Checks if hitbox stream is online"""
online = await self.hitbox_online(stream)
if online:
await self.bot.say("http://www.hitbox.tv/{}/ is online!".format(stream))
elif online == False:
await self.bot.say(stream + " is offline.")
elif online == None:
await self.bot.say("That stream doesn't exist.")
else:
await self.bot.say("Error.")
@commands.command()
async def twitch(self, stream : str):
"""Checks if twitch stream is online"""
online = await self.twitch_online(stream)
if online:
await self.bot.say("http://www.twitch.tv/{} is online!".format(stream))
elif online == False:
await self.bot.say(stream + " is offline.")
elif online == None:
await self.bot.say("That stream doesn't exist.")
else:
await self.bot.say("Error.")
@commands.group(pass_context=True)
@checks.mod_or_permissions(manage_server=True)
async def streamalert(self, ctx):
"""Adds/removes stream alerts from the current channel"""
if ctx.invoked_subcommand is None:
await self.bot.say("Type help streamalert for info.")
@streamalert.command(name="twitch", pass_context=True)
async def twitch_alert(self, ctx, stream : str):
"""Adds/removes twitch alerts from the current channel"""
channel = ctx.message.channel
check = await self.twitch_online(stream)
if check == None:
await self.bot.say("That stream doesn't exist.")
return
elif check == "error":
await self.bot.say("Error.")
return
done = False
for i, s in enumerate(self.twitch_streams):
if s["NAME"] == stream:
if channel.id in s["CHANNELS"]:
if len(s["CHANNELS"]) == 1:
self.twitch_streams.remove(s)
await self.bot.say("Alert has been removed from this channel.")
done = True
else:
self.twitch_streams[i]["CHANNELS"].remove(channel.id)
await self.bot.say("Alert has been removed from this channel.")
done = True
else:
self.twitch_streams[i]["CHANNELS"].append(channel.id)
await self.bot.say("Alert activated. I will notify this channel everytime {} is live.".format(stream))
done = True
if not done:
self.twitch_streams.append({"CHANNELS" : [channel.id], "NAME" : stream, "ALREADY_ONLINE" : False})
await self.bot.say("Alert activated. I will notify this channel everytime {} is live.".format(stream))
fileIO("data/streams/twitch.json", "save", self.twitch_streams)
@streamalert.command(name="hitbox", pass_context=True)
async def hitbox_alert(self, ctx, stream : str):
"""Adds/removes hitbox alerts from the current channel"""
channel = ctx.message.channel
check = await self.hitbox_online(stream)
if check == None:
await self.bot.say("That stream doesn't exist.")
return
elif check == "error":
await self.bot.say("Error.")
return
done = False
for i, s in enumerate(self.hitbox_streams):
if s["NAME"] == stream:
if channel.id in s["CHANNELS"]:
if len(s["CHANNELS"]) == 1:
self.hitbox_streams.remove(s)
await self.bot.say("Alert has been removed from this channel.")
done = True
else:
self.hitbox_streams[i]["CHANNELS"].remove(channel.id)
await self.bot.say("Alert has been removed from this channel.")
done = True
else:
self.hitbox_streams[i]["CHANNELS"].append(channel.id)
await self.bot.say("Alert activated. I will notify this channel everytime {} is live.".format(stream))
done = True
if not done:
self.hitbox_streams.append({"CHANNELS" : [channel.id], "NAME" : stream, "ALREADY_ONLINE" : False})
await self.bot.say("Alert activated. I will notify this channel everytime {} is live.".format(stream))
fileIO("data/streams/hitbox.json", "save", self.hitbox_streams)
@streamalert.command(name="stop", pass_context=True)
async def stop_alert(self, ctx):
"""Stops all streams alerts in the current channel"""
channel = ctx.message.channel
to_delete = []
for s in self.hitbox_streams:
if channel.id in s["CHANNELS"]:
if len(s["CHANNELS"]) == 1:
to_delete.append(s)
else:
s["CHANNELS"].remove(channel.id)
for s in to_delete:
self.hitbox_streams.remove(s)
to_delete = []
for s in self.twitch_streams:
if channel.id in s["CHANNELS"]:
if len(s["CHANNELS"]) == 1:
to_delete.append(s)
else:
s["CHANNELS"].remove(channel.id)
for s in to_delete:
self.twitch_streams.remove(s)
fileIO("data/streams/twitch.json", "save", self.twitch_streams)
fileIO("data/streams/hitbox.json", "save", self.hitbox_streams)
await self.bot.say("There will be no more stream alerts in this channel.")
async def hitbox_online(self, stream):
url = "https://api.hitbox.tv/user/" + stream
try:
async with aiohttp.get(url) as r:
data = await r.json()
if data["is_live"] == "0":
return False
elif data["is_live"] == "1":
return True
elif data["is_live"] == None:
return None
except:
return "error"
async def twitch_online(self, stream):
url = "https://api.twitch.tv/kraken/streams/" + stream
async with aiohttp.get(url) as r:
data = await r.json()
try:
if "stream" in data:
if data["stream"] != None:
return True
else:
return False
elif "error" in data:
return None
except:
return "error"
return False
async def stream_checker(self):
CHECK_DELAY = 10
while "Streams" in self.bot.cogs:
old = (deepcopy(self.twitch_streams), deepcopy(self.hitbox_streams))
for stream in self.twitch_streams:
online = await self.twitch_online(stream["NAME"])
if online and not stream["ALREADY_ONLINE"]:
stream["ALREADY_ONLINE"] = True
for channel in stream["CHANNELS"]:
if self.bot.get_channel(channel):
await self.bot.send_message(self.bot.get_channel(channel), "http://www.twitch.tv/{} is online!".format(stream["NAME"]))
else:
if stream["ALREADY_ONLINE"] and not online: stream["ALREADY_ONLINE"] = False
await asyncio.sleep(1)
for stream in self.hitbox_streams:
online = await self.hitbox_online(stream["NAME"])
if online and not stream["ALREADY_ONLINE"]:
stream["ALREADY_ONLINE"] = True
for channel in stream["CHANNELS"]:
if self.bot.get_channel(channel):
await self.bot.send_message(self.bot.get_channel(channel), "http://www.hitbox.tv/{} is online!".format(stream["NAME"]))
else:
if stream["ALREADY_ONLINE"] and not online: stream["ALREADY_ONLINE"] = False
await asyncio.sleep(1)
if old != (self.twitch_streams, self.hitbox_streams):
fileIO("data/streams/twitch.json", "save", self.twitch_streams)
fileIO("data/streams/hitbox.json", "save", self.hitbox_streams)
await asyncio.sleep(CHECK_DELAY)
def check_folders():
if not os.path.exists("data/streams"):
print("Creating data/streams folder...")
os.makedirs("data/streams")
def check_files():
f = "data/streams/twitch.json"
if not fileIO(f, "check"):
print("Creating empty twitch.json...")
fileIO(f, "save", [])
f = "data/streams/hitbox.json"
if not fileIO(f, "check"):
print("Creating empty hitbox.json...")
fileIO(f, "save", [])
def setup(bot):
logger = logging.getLogger('aiohttp.client')
logger.setLevel(50) #Stops warning spam
check_folders()
check_files()
n = Streams(bot)
loop = asyncio.get_event_loop()
loop.create_task(n.stream_checker())
bot.add_cog(n)

View File

@ -104,7 +104,7 @@ class TriviaSession():
triviaManager.trivia_sessions.remove(self)
def loadList(self, qlist):
with open(qlist, "r", encoding="utf-8") as f:
with open(qlist, "r", encoding="ISO-8859-1") as f:
qlist = f.readlines()
parsedList = []
for line in qlist: