Infochannel develop (#106)
* Unneeded requirements * No need for lambda or function * Remove Cog backwards compatibility, and reformatting * Address rate limits? * More error checks, better help, common sense channel edits, and rate limit checks * Black formatting as well
This commit is contained in:
		
							parent
							
								
									acaa5b8fb9
								
							
						
					
					
						commit
						24c2791f89
					
				@ -1,15 +1,18 @@
 | 
			
		||||
import asyncio
 | 
			
		||||
 | 
			
		||||
import discord
 | 
			
		||||
from redbot.core import Config, checks, commands
 | 
			
		||||
from redbot.core.bot import Red
 | 
			
		||||
from redbot.core.commands import Cog
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Cog: Any = getattr(commands, "Cog", object)
 | 
			
		||||
# listener = getattr(commands.Cog, "listener", None)  # Trusty + Sinbad
 | 
			
		||||
# if listener is None:
 | 
			
		||||
#     def listener(name=None):
 | 
			
		||||
#         return lambda x: x
 | 
			
		||||
 | 
			
		||||
RATE_LIMIT_DELAY = 60 * 10  # If you're willing to risk rate limiting, you can decrease the delay
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InfoChannel(Cog):
 | 
			
		||||
    """
 | 
			
		||||
@ -19,6 +22,7 @@ class InfoChannel(Cog):
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, bot: Red):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
        self.bot = bot
 | 
			
		||||
        self.config = Config.get_conf(
 | 
			
		||||
            self, identifier=731101021116710497110110101108, force_registration=True
 | 
			
		||||
@ -35,6 +39,8 @@ class InfoChannel(Cog):
 | 
			
		||||
 | 
			
		||||
        self.config.register_guild(**default_guild)
 | 
			
		||||
 | 
			
		||||
        self._critical_section_wooah_ = 0
 | 
			
		||||
 | 
			
		||||
    @commands.command()
 | 
			
		||||
    @checks.admin()
 | 
			
		||||
    async def infochannel(self, ctx: commands.Context):
 | 
			
		||||
@ -70,9 +76,13 @@ class InfoChannel(Cog):
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if channel is None:
 | 
			
		||||
            try:
 | 
			
		||||
                await self.make_infochannel(guild)
 | 
			
		||||
            except discord.Forbidden:
 | 
			
		||||
                await ctx.send("Failure: Missing permission to create voice channel")
 | 
			
		||||
                return
 | 
			
		||||
        else:
 | 
			
		||||
            await self.delete_infochannel(guild, channel)
 | 
			
		||||
            await self.delete_all_infochannels(guild)
 | 
			
		||||
 | 
			
		||||
        if not await ctx.tick():
 | 
			
		||||
            await ctx.send("Done!")
 | 
			
		||||
@ -83,6 +93,8 @@ class InfoChannel(Cog):
 | 
			
		||||
        """
 | 
			
		||||
        Toggle different types of infochannels
 | 
			
		||||
        """
 | 
			
		||||
        if not ctx.invoked_subcommand:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    @infochannelset.command(name="botcount")
 | 
			
		||||
    async def _infochannelset_botcount(self, ctx: commands.Context, enabled: bool = None):
 | 
			
		||||
@ -92,7 +104,10 @@ class InfoChannel(Cog):
 | 
			
		||||
        guild = ctx.guild
 | 
			
		||||
        if enabled is None:
 | 
			
		||||
            enabled = not await self.config.guild(guild).bot_count()
 | 
			
		||||
 | 
			
		||||
        await self.config.guild(guild).bot_count.set(enabled)
 | 
			
		||||
        await self.make_infochannel(ctx.guild)
 | 
			
		||||
 | 
			
		||||
        if enabled:
 | 
			
		||||
            await ctx.send("InfoChannel for bot count has been enabled.")
 | 
			
		||||
        else:
 | 
			
		||||
@ -106,7 +121,10 @@ class InfoChannel(Cog):
 | 
			
		||||
        guild = ctx.guild
 | 
			
		||||
        if enabled is None:
 | 
			
		||||
            enabled = not await self.config.guild(guild).online_count()
 | 
			
		||||
 | 
			
		||||
        await self.config.guild(guild).online_count.set(enabled)
 | 
			
		||||
        await self.make_infochannel(ctx.guild)
 | 
			
		||||
 | 
			
		||||
        if enabled:
 | 
			
		||||
            await ctx.send("InfoChannel for online user count has been enabled.")
 | 
			
		||||
        else:
 | 
			
		||||
@ -120,25 +138,49 @@ class InfoChannel(Cog):
 | 
			
		||||
            guild.me: discord.PermissionOverwrite(manage_channels=True, connect=True),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #  Remove the old info channel first
 | 
			
		||||
        channel_id = await self.config.guild(guild).channel_id()
 | 
			
		||||
        if channel_id is not None:
 | 
			
		||||
            channel: discord.VoiceChannel = guild.get_channel(channel_id)
 | 
			
		||||
            if channel:
 | 
			
		||||
                await channel.delete(reason="InfoChannel delete")
 | 
			
		||||
 | 
			
		||||
        # Then create the new one
 | 
			
		||||
        channel = await guild.create_voice_channel(
 | 
			
		||||
            "Placeholder", reason="InfoChannel make", overwrites=overwrites
 | 
			
		||||
            "Total Humans:", reason="InfoChannel make", overwrites=overwrites
 | 
			
		||||
        )
 | 
			
		||||
        await self.config.guild(guild).channel_id.set(channel.id)
 | 
			
		||||
 | 
			
		||||
        if botcount:
 | 
			
		||||
            # Remove the old bot channel first
 | 
			
		||||
            botchannel_id = await self.config.guild(guild).botchannel_id()
 | 
			
		||||
            if channel_id is not None:
 | 
			
		||||
                botchannel: discord.VoiceChannel = guild.get_channel(botchannel_id)
 | 
			
		||||
                if botchannel:
 | 
			
		||||
                    await botchannel.delete(reason="InfoChannel delete")
 | 
			
		||||
 | 
			
		||||
            # Then create the new one
 | 
			
		||||
            botchannel = await guild.create_voice_channel(
 | 
			
		||||
                "Placeholder", reason="InfoChannel botcount", overwrites=overwrites
 | 
			
		||||
                "Bots:", reason="InfoChannel botcount", overwrites=overwrites
 | 
			
		||||
            )
 | 
			
		||||
            await self.config.guild(guild).botchannel_id.set(botchannel.id)
 | 
			
		||||
        if onlinecount:
 | 
			
		||||
            # Remove the old online channel first
 | 
			
		||||
            onlinechannel_id = await self.config.guild(guild).onlinechannel_id()
 | 
			
		||||
            if channel_id is not None:
 | 
			
		||||
                onlinechannel: discord.VoiceChannel = guild.get_channel(onlinechannel_id)
 | 
			
		||||
                if onlinechannel:
 | 
			
		||||
                    await onlinechannel.delete(reason="InfoChannel delete")
 | 
			
		||||
 | 
			
		||||
            # Then create the new one
 | 
			
		||||
            onlinechannel = await guild.create_voice_channel(
 | 
			
		||||
                "Placeholder", reason="InfoChannel onlinecount", overwrites=overwrites
 | 
			
		||||
                "Online:", reason="InfoChannel onlinecount", overwrites=overwrites
 | 
			
		||||
            )
 | 
			
		||||
            await self.config.guild(guild).onlinechannel_id.set(onlinechannel.id)
 | 
			
		||||
 | 
			
		||||
        await self.update_infochannel(guild)
 | 
			
		||||
 | 
			
		||||
    async def delete_infochannel(self, guild: discord.Guild, channel: discord.VoiceChannel):
 | 
			
		||||
    async def delete_all_infochannels(self, guild: discord.Guild):
 | 
			
		||||
        guild_data = await self.config.guild(guild).all()
 | 
			
		||||
        botchannel_id = guild_data["botchannel_id"]
 | 
			
		||||
        onlinechannel_id = guild_data["onlinechannel_id"]
 | 
			
		||||
@ -151,6 +193,7 @@ class InfoChannel(Cog):
 | 
			
		||||
            await botchannel.delete(reason="InfoChannel delete")
 | 
			
		||||
        if onlinechannel_id is not None:
 | 
			
		||||
            await onlinechannel.delete(reason="InfoChannel delete")
 | 
			
		||||
 | 
			
		||||
        await self.config.guild(guild).clear()
 | 
			
		||||
 | 
			
		||||
    async def update_infochannel(self, guild: discord.Guild):
 | 
			
		||||
@ -162,23 +205,23 @@ class InfoChannel(Cog):
 | 
			
		||||
        # bots = lambda x: x.bot
 | 
			
		||||
        # def bots(x): return x.bot
 | 
			
		||||
 | 
			
		||||
        num = len([m for m in guild.members if m.bot])
 | 
			
		||||
        bot_msg = f"Bots: {num}"
 | 
			
		||||
        bot_num = len([m for m in guild.members if m.bot])
 | 
			
		||||
        # bot_msg = f"Bots: {num}"
 | 
			
		||||
 | 
			
		||||
        # Gets count of online users
 | 
			
		||||
        members = guild.member_count
 | 
			
		||||
        offline = len(list(filter(lambda m: m.status is discord.Status.offline, guild.members)))
 | 
			
		||||
        num = members - offline
 | 
			
		||||
        online_msg = f"Online: {num}"
 | 
			
		||||
        online_num = members - offline
 | 
			
		||||
        # online_msg = f"Online: {num}"
 | 
			
		||||
 | 
			
		||||
        # Gets count of actual users
 | 
			
		||||
        total = lambda x: not x.bot
 | 
			
		||||
        num = len([m for m in guild.members if total(m)])
 | 
			
		||||
        human_msg = f"Total Humans: {num}"
 | 
			
		||||
        human_num = len([m for m in guild.members if total(m)])
 | 
			
		||||
        # human_msg = f"Total Humans: {num}"
 | 
			
		||||
 | 
			
		||||
        channel_id = guild_data["channel_id"]
 | 
			
		||||
        if channel_id is None:
 | 
			
		||||
            return
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        botchannel_id = guild_data["botchannel_id"]
 | 
			
		||||
        onlinechannel_id = guild_data["onlinechannel_id"]
 | 
			
		||||
@ -188,28 +231,53 @@ class InfoChannel(Cog):
 | 
			
		||||
        onlinechannel: discord.VoiceChannel = guild.get_channel(onlinechannel_id)
 | 
			
		||||
 | 
			
		||||
        if guild_data["member_count"]:
 | 
			
		||||
            name = "{} ".format(human_msg)
 | 
			
		||||
            name = f"{channel.name.split(':')[0]}: {human_num}"
 | 
			
		||||
 | 
			
		||||
            await channel.edit(reason="InfoChannel update", name=name)
 | 
			
		||||
 | 
			
		||||
        if botcount:
 | 
			
		||||
            name = "{} ".format(bot_msg)
 | 
			
		||||
            name = f"{botchannel.name.split(':')[0]}: {bot_num}"
 | 
			
		||||
            await botchannel.edit(reason="InfoChannel update", name=name)
 | 
			
		||||
 | 
			
		||||
        if onlinecount:
 | 
			
		||||
            name = "{} ".format(online_msg)
 | 
			
		||||
            name = f"{onlinechannel.name.split(':')[0]}: {online_num}"
 | 
			
		||||
            await onlinechannel.edit(reason="InfoChannel update", name=name)
 | 
			
		||||
 | 
			
		||||
    async def update_infochannel_with_cooldown(self, guild):
 | 
			
		||||
        """My attempt at preventing rate limits, lets see how it goes"""
 | 
			
		||||
        if self._critical_section_wooah_:
 | 
			
		||||
            if self._critical_section_wooah_ == 2:
 | 
			
		||||
                print("Already pending, skipping")
 | 
			
		||||
                return  # Another one is already pending, don't queue more than one
 | 
			
		||||
            print("Queuing another update")
 | 
			
		||||
            self._critical_section_wooah_ = 2
 | 
			
		||||
 | 
			
		||||
            while self._critical_section_wooah_:
 | 
			
		||||
                await asyncio.sleep(
 | 
			
		||||
                    RATE_LIMIT_DELAY // 4
 | 
			
		||||
                )  # Max delay ends up as 1.25 * RATE_LIMIT_DELAY
 | 
			
		||||
 | 
			
		||||
            print("Issuing queued update")
 | 
			
		||||
            return await self.update_infochannel_with_cooldown(guild)
 | 
			
		||||
 | 
			
		||||
        print("Entering critical")
 | 
			
		||||
        self._critical_section_wooah_ = 1
 | 
			
		||||
        await self.update_infochannel(guild)
 | 
			
		||||
        await asyncio.sleep(RATE_LIMIT_DELAY)
 | 
			
		||||
        self._critical_section_wooah_ = 0
 | 
			
		||||
        print("Exiting critical")
 | 
			
		||||
 | 
			
		||||
    @Cog.listener()
 | 
			
		||||
    async def on_member_join(self, member: discord.Member):
 | 
			
		||||
        await self.update_infochannel(member.guild)
 | 
			
		||||
        await self.update_infochannel_with_cooldown(member.guild)
 | 
			
		||||
 | 
			
		||||
    @Cog.listener()
 | 
			
		||||
    async def on_member_remove(self, member: discord.Member):
 | 
			
		||||
        await self.update_infochannel(member.guild)
 | 
			
		||||
        await self.update_infochannel_with_cooldown(member.guild)
 | 
			
		||||
 | 
			
		||||
    @Cog.listener()
 | 
			
		||||
    async def on_member_update(self, before: discord.Member, after: discord.Member):
 | 
			
		||||
        onlinecount = await self.config.guild(after.guild).online_count()
 | 
			
		||||
        if onlinecount:
 | 
			
		||||
            if before.status != after.status:
 | 
			
		||||
                await self.update_infochannel(after.guild)
 | 
			
		||||
                await self.update_infochannel_with_cooldown(after.guild)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user