diff --git a/redbot/cogs/streams/errors.py b/redbot/cogs/streams/errors.py index 81d66bf97..76c6ff356 100644 --- a/redbot/cogs/streams/errors.py +++ b/redbot/cogs/streams/errors.py @@ -6,10 +6,6 @@ class StreamNotFound(StreamsError): pass -class CommunityNotFound(StreamsError): - pass - - class APIError(StreamsError): pass @@ -24,7 +20,3 @@ class InvalidYoutubeCredentials(StreamsError): class OfflineStream(StreamsError): pass - - -class OfflineCommunity(StreamsError): - pass diff --git a/redbot/cogs/streams/streams.py b/redbot/cogs/streams/streams.py index 796a8edbb..0047bf67f 100644 --- a/redbot/cogs/streams/streams.py +++ b/redbot/cogs/streams/streams.py @@ -11,7 +11,6 @@ from .streamtypes import ( HitboxStream, MixerStream, PicartoStream, - TwitchCommunity, YoutubeStream, ) from .errors import ( @@ -19,8 +18,6 @@ from .errors import ( StreamNotFound, APIError, InvalidYoutubeCredentials, - CommunityNotFound, - OfflineCommunity, StreamsError, InvalidTwitchCredentials, ) @@ -39,7 +36,7 @@ _ = Translator("Streams", __file__) @cog_i18n(_) class Streams(commands.Cog): - global_defaults = {"tokens": {}, "streams": [], "communities": []} + global_defaults = {"tokens": {}, "streams": []} guild_defaults = {"autodelete": False, "mention_everyone": False, "mention_here": False} @@ -58,7 +55,6 @@ class Streams(commands.Cog): self.bot: Red = bot self.streams: List[Stream] = [] - self.communities: List[TwitchCommunity] = [] self.task: Optional[asyncio.Task] = None self.yt_cid_pattern = re.compile("^UC[-_A-Za-z0-9]{21}[AQgw]$") @@ -73,7 +69,6 @@ class Streams(commands.Cog): """Should be called straight after cog instantiation.""" await self.move_api_keys() self.streams = await self.load_streams() - self.communities = await self.load_communities() self.task = self.bot.loop.create_task(self._stream_alerts()) @@ -178,11 +173,6 @@ class Streams(commands.Cog): return await self.stream_alert(ctx, TwitchStream, channel_name.lower()) - @_twitch.command(name="community") - async def twitch_alert_community(self, ctx: commands.Context, community: str): - """Toggle alerts in this channel for a Twitch community.""" - await self.community_alert(ctx, TwitchCommunity, community.lower()) - @streamalert.command(name="youtube") async def youtube_alert(self, ctx: commands.Context, channel_name_or_id: str): """Toggle alerts in this channel for a YouTube stream.""" @@ -303,34 +293,6 @@ class Streams(commands.Cog): await self.add_or_remove(ctx, stream) - async def community_alert(self, ctx: commands.Context, _class, community_name): - community = self.get_community(_class, community_name) - if not community: - token = await self.bot.db.api_tokens.get_raw(_class.token_name, default=None) - community = _class(name=community_name, token=token) - try: - await community.get_community_streams() - except InvalidTwitchCredentials: - await ctx.send( - _( - "The Twitch token is either invalid or has not been set. See " - "`{prefix}streamset twitchtoken`." - ).format(prefix=ctx.prefix) - ) - return - except CommunityNotFound: - await ctx.send(_("That community doesn't seem to exist.")) - return - except APIError: - await ctx.send( - _("Something went wrong whilst trying to contact the stream service's API.") - ) - return - except OfflineCommunity: - pass - - await self.add_or_remove_community(ctx, community) - @commands.group() @checks.mod() async def streamset(self, ctx: commands.Context): @@ -393,9 +355,7 @@ class Streams(commands.Cog): await ctx.send(_("`@\u200beveryone` will no longer be mentioned for stream alerts.")) else: await self.db.guild(guild).mention_everyone.set(True) - await ctx.send( - _("When a stream or community is live, `@\u200beveryone` will be mentioned.") - ) + await ctx.send(_("When a stream is live, `@\u200beveryone` will be mentioned.")) @mention.command(aliases=["here"]) @commands.guild_only() @@ -408,9 +368,7 @@ class Streams(commands.Cog): await ctx.send(_("`@\u200bhere` will no longer be mentioned for stream alerts.")) else: await self.db.guild(guild).mention_here.set(True) - await ctx.send( - _("When a stream or community is live, `@\u200bhere` will be mentioned.") - ) + await ctx.send(_("When a stream is live, `@\u200bhere` will be mentioned.")) @mention.command() @commands.guild_only() @@ -470,29 +428,6 @@ class Streams(commands.Cog): await self.save_streams() - async def add_or_remove_community(self, ctx: commands.Context, community): - if ctx.channel.id not in community.channels: - community.channels.append(ctx.channel.id) - if community not in self.communities: - self.communities.append(community) - await ctx.send( - _( - "I'll send a notification in this channel when a " - "channel is live in the {community.name} community." - ).format(community=community) - ) - else: - community.channels.remove(ctx.channel.id) - if not community.channels: - self.communities.remove(community) - await ctx.send( - _( - "I won't send notifications about channels streaming " - "in the {community.name} community in this channel anymore." - ).format(community=community) - ) - await self.save_communities() - def get_stream(self, _class, name): for stream in self.streams: # if isinstance(stream, _class) and stream.name == name: @@ -510,11 +445,6 @@ class Streams(commands.Cog): elif stream.type == _class.__name__ and stream.name.lower() == name.lower(): return stream - def get_community(self, _class, name): - for community in self.communities: - if community.type == _class.__name__ and community.name.lower() == name.lower(): - return community - @staticmethod async def check_exists(stream): try: @@ -533,10 +463,6 @@ class Streams(commands.Cog): await self.check_streams() except asyncio.CancelledError: pass - try: - await self.check_communities() - except asyncio.CancelledError: - pass await asyncio.sleep(CHECK_DELAY) async def check_streams(self): @@ -600,52 +526,6 @@ class Streams(commands.Cog): mentions.append(role.mention) return " ".join(mentions), edited_roles - async def check_communities(self): - for community in self.communities: - with contextlib.suppress(Exception): - try: - stream_list = await community.get_community_streams() - except CommunityNotFound: - print( - _("The Community {community.name} was not found!").format( - community=community - ) - ) - continue - except OfflineCommunity: - if not community._messages_cache: - continue - for message in community._messages_cache: - with contextlib.suppress(Exception): - autodelete = await self.db.guild(message.guild).autodelete() - if autodelete: - await message.delete() - community._messages_cache.clear() - await self.save_communities() - else: - for channel in community.channels: - chn = self.bot.get_channel(channel) - streams = await self.filter_streams(stream_list, chn) - emb = await community.make_embed(streams) - chn_msg = [m for m in community._messages_cache if m.channel == chn] - if not chn_msg: - mentions, roles = await self._get_mention_str(chn.guild) - if mentions: - msg = await chn.send(mentions, embed=emb) - else: - msg = await chn.send(embed=emb) - community._messages_cache.append(msg) - if roles: - for role in roles: - await role.edit(mentionable=False) - await self.save_communities() - else: - chn_msg = sorted(chn_msg, key=lambda x: x.created_at, reverse=True)[0] - community._messages_cache.remove(chn_msg) - await chn_msg.edit(embed=emb) - community._messages_cache.append(chn_msg) - await self.save_communities() - async def filter_streams(self, streams: list, channel: discord.TextChannel) -> list: filtered = [] for stream in streams: @@ -683,34 +563,6 @@ class Streams(commands.Cog): return streams - async def load_communities(self): - communities = [] - - for raw_community in await self.db.communities(): - _class = getattr(_streamtypes, raw_community["type"], None) - if not _class: - continue - raw_msg_cache = raw_community["messages"] - raw_community["_messages_cache"] = [] - for raw_msg in raw_msg_cache: - chn = self.bot.get_channel(raw_msg["channel"]) - if chn is not None: - try: - msg = await chn.get_message(raw_msg["message"]) - except discord.HTTPException: - pass - else: - raw_community["_messages_cache"].append(msg) - token = await self.bot.db.api_tokens.get_raw(_class.token_name, default=None) - communities.append(_class(token=token, **raw_community)) - - # issue 1191 extended resolution: Remove this after suitable period - # Fast dedupe below - seen = set() - seen_add = seen.add - return [x for x in communities if not (x.name.lower() in seen or seen_add(x.name.lower()))] - # return communities - async def save_streams(self): raw_streams = [] for stream in self.streams: @@ -718,13 +570,6 @@ class Streams(commands.Cog): await self.db.streams.set(raw_streams) - async def save_communities(self): - raw_communities = [] - for community in self.communities: - raw_communities.append(community.export()) - - await self.db.communities.set(raw_communities) - def __unload(self): if self.task: self.task.cancel() diff --git a/redbot/cogs/streams/streamtypes.py b/redbot/cogs/streams/streamtypes.py index 63fbadd3f..b4d2a3cd4 100644 --- a/redbot/cogs/streams/streamtypes.py +++ b/redbot/cogs/streams/streamtypes.py @@ -2,8 +2,6 @@ from .errors import ( StreamNotFound, APIError, OfflineStream, - CommunityNotFound, - OfflineCommunity, InvalidYoutubeCredentials, InvalidTwitchCredentials, ) @@ -30,106 +28,6 @@ def rnd(url): return url + "?rnd=" + "".join([choice(ascii_letters) for i in range(6)]) -class TwitchCommunity: - - token_name = "twitch" - - def __init__(self, **kwargs): - self.name = kwargs.pop("name") - self.id = kwargs.pop("id", None) - self.channels = kwargs.pop("channels", []) - self._messages_cache = kwargs.pop("_messages_cache", []) - self._token = kwargs.pop("token", None) - self.type = self.__class__.__name__ - - async def get_community_id(self): - headers = { - "Accept": "application/vnd.twitchtv.v5+json", - "Client-ID": str(self._token["client_id"]), - } - params = {"name": self.name} - async with aiohttp.ClientSession() as session: - async with session.get( - TWITCH_COMMUNITIES_ENDPOINT, headers=headers, params=params - ) as r: - data = await r.json() - if r.status == 200: - return data["_id"] - elif r.status == 400: - raise InvalidTwitchCredentials() - elif r.status == 404: - raise CommunityNotFound() - else: - raise APIError() - - async def get_community_streams(self): - if not self.id: - try: - self.id = await self.get_community_id() - except CommunityNotFound: - raise - headers = { - "Accept": "application/vnd.twitchtv.v5+json", - "Client-ID": str(self._token["client_id"]), - } - params = {"community_id": self.id, "limit": 100} - url = TWITCH_BASE_URL + "/kraken/streams" - async with aiohttp.ClientSession() as session: - async with session.get(url, headers=headers, params=params) as r: - data = await r.json() - if r.status == 200: - if data["_total"] == 0: - raise OfflineCommunity() - else: - return data["streams"] - elif r.status == 400: - raise InvalidTwitchCredentials() - elif r.status == 404: - raise CommunityNotFound() - else: - raise APIError() - - async def make_embed(self, streams: list) -> discord.Embed: - headers = { - "Accept": "application/vnd.twitchtv.v5+json", - "Client-ID": str(self._token["client_id"]), - } - async with aiohttp.ClientSession() as session: - async with session.get( - "{}/{}".format(TWITCH_COMMUNITIES_ENDPOINT, self.id), headers=headers - ) as r: - data = await r.json() - - avatar = data["avatar_image_url"] - title = "Channels currently streaming to {}".format(data["display_name"]) - url = "https://www.twitch.tv/communities/{}".format(self.name) - embed = discord.Embed(title=title, url=url) - embed.set_image(url=avatar) - if len(streams) >= 10: - stream_list = sample(streams, 10) - else: - stream_list = streams - for stream in stream_list: - name = "[{}]({})".format(stream["channel"]["display_name"], stream["channel"]["url"]) - embed.add_field(name=stream["channel"]["status"], value=name, inline=False) - embed.color = 0x6441A4 - - return embed - - def export(self): - data = {} - for k, v in self.__dict__.items(): - if not k.startswith("_"): - data[k] = v - data["messages"] = [] - for m in self._messages_cache: - data["messages"].append({"channel": m.channel.id, "message": m.id}) - return data - - def __repr__(self): - return "<{0.__class__.__name__}: {0.name}>".format(self) - - class Stream: token_name: ClassVar[Optional[str]] = None