diff --git a/cogs/streams.py b/cogs/streams.py index 77dab134a..098c6bb7c 100644 --- a/cogs/streams.py +++ b/cogs/streams.py @@ -11,6 +11,7 @@ import re import aiohttp import asyncio import logging +import json class StreamsError(Exception): @@ -43,6 +44,7 @@ class Streams: self.twitch_streams = dataIO.load_json("data/streams/twitch.json") self.hitbox_streams = dataIO.load_json("data/streams/hitbox.json") self.beam_streams = dataIO.load_json("data/streams/beam.json") + self.picarto_streams = dataIO.load_json("data/streams/picarto.json") settings = dataIO.load_json("data/streams/settings.json") self.settings = defaultdict(dict, settings) self.messages_cache = defaultdict(list) @@ -103,6 +105,23 @@ class Streams: else: await self.bot.say(embed=embed) + @commands.command() + async def picarto(self, stream: str): + """Checks if picarto stream is online""" + stream = escape_mass_mentions(stream) + regex = r'^(https?\:\/\/)?(www\.)?(picarto\.tv\/)' + stream = re.sub(regex, '', stream) + try: + embed = await self.picarto_online(stream) + except OfflineStream: + await self.bot.say(stream + " is offline.") + except StreamNotFound: + await self.bot.say("That stream doesn't exist.") + except APIError: + await self.bot.say("Error contacting the API.") + else: + await self.bot.say(embed=embed) + @commands.group(pass_context=True, no_pm=True) @checks.mod_or_permissions(manage_server=True) async def streamalert(self, ctx): @@ -204,6 +223,36 @@ class Streams: dataIO.save_json("data/streams/beam.json", self.beam_streams) + @streamalert.command(name="picarto", pass_context=True) + async def picarto_alert(self, ctx, stream: str): + """Adds/removes picarto alerts from the current channel""" + stream = escape_mass_mentions(stream) + regex = r'^(https?\:\/\/)?(www\.)?(picarto\.tv\/)' + stream = re.sub(regex, '', stream) + channel = ctx.message.channel + try: + await self.picarto_online(stream) + except StreamNotFound: + await self.bot.say("That stream doesn't exist.") + return + except APIError: + await self.bot.say("Error contacting the API.") + return + except OfflineStream: + pass + + enabled = self.enable_or_disable_if_active(self.picarto_streams, + stream, + channel) + + if enabled: + await self.bot.say("Alert activated. I will notify this channel " + "when {} is live.".format(stream)) + else: + await self.bot.say("Alert has been removed from this channel.") + + dataIO.save_json("data/streams/picarto.json", self.picarto_streams) + @streamalert.command(name="stop", pass_context=True) async def stop_alert(self, ctx): """Stops all streams alerts in the current channel""" @@ -339,6 +388,22 @@ class Streams: else: raise APIError() + async def picarto_online(self, stream): + url = "https://api.picarto.tv/v1/channel/name/" + stream + + async with aiohttp.get(url) as r: + data = await r.text(encoding='utf-8') + if r.status == 200: + data = json.loads(data) + if data["online"] is True: + return self.picarto_embed(data) + else: + raise OfflineStream() + elif r.status == 404: + raise StreamNotFound() + else: + raise APIError() + async def fetch_twitch_ids(self, *streams, raise_if_none=False): def chunks(l): for i in range(0, len(l), 100): @@ -426,6 +491,34 @@ class Streams: embed.set_footer(text="Playing: " + data["type"]["name"]) return embed + def picarto_embed(self, data): + avatar = ("https://picarto.tv/user_data/usrimg/{}/dsdefault.jpg{}" + "".format(data["name"].lower(), self.rnd_attr())) + url = "https://picarto.tv/" + data["name"] + thumbnail = ("https://thumb.picarto.tv/thumbnail/{}.jpg" + "".format(data["name"])) + embed = discord.Embed(title=data["title"], url=url) + embed.set_author(name=data["name"]) + embed.set_image(url=thumbnail + self.rnd_attr()) + embed.add_field(name="Followers", value=data["followers"]) + embed.add_field(name="Total views", value=data["viewers_total"]) + embed.set_thumbnail(url=avatar) + embed.color = 0x132332 + data["tags"] = ", ".join(data["tags"]) + + if not data["tags"]: + data["tags"] = "None" + + if data["adult"]: + data["adult"] = "NSFW | " + else: + data["adult"] = "" + + embed.color = 0x4C90F3 + embed.set_footer(text="{adult}Category: {category} | Tags: {tags}" + "".format(**data)) + return embed + def enable_or_disable_if_active(self, streams, stream, channel, _id=None): """Returns True if enabled or False if disabled""" for i, s in enumerate(streams): @@ -467,9 +560,10 @@ class Streams: while self == self.bot.get_cog("Streams"): save = False - streams = ((self.twitch_streams, self.twitch_online), - (self.hitbox_streams, self.hitbox_online), - (self.beam_streams, self.beam_online)) + streams = ((self.twitch_streams, self.twitch_online), + (self.hitbox_streams, self.hitbox_online), + (self.beam_streams, self.beam_online), + (self.picarto_streams, self.picarto_online)) for streams_list, parser in streams: if parser == self.twitch_online: @@ -513,6 +607,7 @@ class Streams: dataIO.save_json("data/streams/twitch.json", self.twitch_streams) dataIO.save_json("data/streams/hitbox.json", self.hitbox_streams) dataIO.save_json("data/streams/beam.json", self.beam_streams) + dataIO.save_json("data/streams/picarto.json", self.picarto_streams) await asyncio.sleep(CHECK_DELAY) @@ -566,7 +661,8 @@ def check_files(): stream_files = ( "twitch.json", "hitbox.json", - "beam.json" + "beam.json", + "picarto.json" ) for filename in stream_files: