mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-07 03:38:53 -05:00
Merge remote-tracking branch 'upstream/develop' into develop
This commit is contained in:
commit
375e447a97
@ -62,7 +62,8 @@ class Audio:
|
|||||||
if await self.is_alone_or_admin(msg.author):
|
if await self.is_alone_or_admin(msg.author):
|
||||||
self.queue = []
|
self.queue = []
|
||||||
self.current = -1
|
self.current = -1
|
||||||
self.playlist = [link]
|
self.playlist = []
|
||||||
|
self.queue.append(link)
|
||||||
self.music_player.stop()
|
self.music_player.stop()
|
||||||
else:
|
else:
|
||||||
self.playlist = []
|
self.playlist = []
|
||||||
@ -245,7 +246,16 @@ class Audio:
|
|||||||
if await self.check_voice(ctx.message.author, ctx.message):
|
if await self.check_voice(ctx.message.author, ctx.message):
|
||||||
if not self.playlist:
|
if not self.playlist:
|
||||||
self.queue.append(link)
|
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:
|
else:
|
||||||
await self.bot.say("I'm already playing a playlist.")
|
await self.bot.say("I'm already playing a playlist.")
|
||||||
|
|
||||||
@ -318,6 +328,29 @@ class Audio:
|
|||||||
else:
|
else:
|
||||||
await self.bot.say("There are no local playlists.")
|
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)
|
@commands.group(pass_context=True)
|
||||||
@checks.mod_or_permissions()
|
@checks.mod_or_permissions()
|
||||||
async def audioset(self, ctx):
|
async def audioset(self, ctx):
|
||||||
@ -374,6 +407,17 @@ class Audio:
|
|||||||
else:
|
else:
|
||||||
await self.bot.say("Maximum audio cache size has been set to " + str(size) + "MB.")
|
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)
|
@commands.group(pass_context=True)
|
||||||
@checks.is_owner()
|
@checks.is_owner()
|
||||||
@ -608,6 +652,39 @@ class Audio:
|
|||||||
except:
|
except:
|
||||||
return False
|
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
|
class EmptyPlayer(): #dummy player
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
@ -633,7 +710,7 @@ def check_folders():
|
|||||||
|
|
||||||
def check_files():
|
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"
|
settings_path = "data/audio/settings.json"
|
||||||
|
|
||||||
if not os.path.isfile(settings_path):
|
if not os.path.isfile(settings_path):
|
||||||
|
|||||||
251
cogs/streams.py
Normal file
251
cogs/streams.py
Normal 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)
|
||||||
@ -104,7 +104,7 @@ class TriviaSession():
|
|||||||
triviaManager.trivia_sessions.remove(self)
|
triviaManager.trivia_sessions.remove(self)
|
||||||
|
|
||||||
def loadList(self, qlist):
|
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()
|
qlist = f.readlines()
|
||||||
parsedList = []
|
parsedList = []
|
||||||
for line in qlist:
|
for line in qlist:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user