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
sherlock_initial
bobloy 5 years ago committed by GitHub
parent acaa5b8fb9
commit 24c2791f89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,15 +1,18 @@
import asyncio
import discord import discord
from redbot.core import Config, checks, commands from redbot.core import Config, checks, commands
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.commands import Cog from redbot.core.commands import Cog
# Cog: Any = getattr(commands, "Cog", object) # Cog: Any = getattr(commands, "Cog", object)
# listener = getattr(commands.Cog, "listener", None) # Trusty + Sinbad # listener = getattr(commands.Cog, "listener", None) # Trusty + Sinbad
# if listener is None: # if listener is None:
# def listener(name=None): # def listener(name=None):
# return lambda x: x # 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): class InfoChannel(Cog):
""" """
@ -19,6 +22,7 @@ class InfoChannel(Cog):
""" """
def __init__(self, bot: Red): def __init__(self, bot: Red):
super().__init__()
self.bot = bot self.bot = bot
self.config = Config.get_conf( self.config = Config.get_conf(
self, identifier=731101021116710497110110101108, force_registration=True self, identifier=731101021116710497110110101108, force_registration=True
@ -35,6 +39,8 @@ class InfoChannel(Cog):
self.config.register_guild(**default_guild) self.config.register_guild(**default_guild)
self._critical_section_wooah_ = 0
@commands.command() @commands.command()
@checks.admin() @checks.admin()
async def infochannel(self, ctx: commands.Context): async def infochannel(self, ctx: commands.Context):
@ -70,9 +76,13 @@ class InfoChannel(Cog):
return return
if channel is None: if channel is None:
await self.make_infochannel(guild) try:
await self.make_infochannel(guild)
except discord.Forbidden:
await ctx.send("Failure: Missing permission to create voice channel")
return
else: else:
await self.delete_infochannel(guild, channel) await self.delete_all_infochannels(guild)
if not await ctx.tick(): if not await ctx.tick():
await ctx.send("Done!") await ctx.send("Done!")
@ -83,6 +93,8 @@ class InfoChannel(Cog):
""" """
Toggle different types of infochannels Toggle different types of infochannels
""" """
if not ctx.invoked_subcommand:
pass
@infochannelset.command(name="botcount") @infochannelset.command(name="botcount")
async def _infochannelset_botcount(self, ctx: commands.Context, enabled: bool = None): async def _infochannelset_botcount(self, ctx: commands.Context, enabled: bool = None):
@ -92,7 +104,10 @@ class InfoChannel(Cog):
guild = ctx.guild guild = ctx.guild
if enabled is None: if enabled is None:
enabled = not await self.config.guild(guild).bot_count() enabled = not await self.config.guild(guild).bot_count()
await self.config.guild(guild).bot_count.set(enabled) await self.config.guild(guild).bot_count.set(enabled)
await self.make_infochannel(ctx.guild)
if enabled: if enabled:
await ctx.send("InfoChannel for bot count has been enabled.") await ctx.send("InfoChannel for bot count has been enabled.")
else: else:
@ -106,7 +121,10 @@ class InfoChannel(Cog):
guild = ctx.guild guild = ctx.guild
if enabled is None: if enabled is None:
enabled = not await self.config.guild(guild).online_count() enabled = not await self.config.guild(guild).online_count()
await self.config.guild(guild).online_count.set(enabled) await self.config.guild(guild).online_count.set(enabled)
await self.make_infochannel(ctx.guild)
if enabled: if enabled:
await ctx.send("InfoChannel for online user count has been enabled.") await ctx.send("InfoChannel for online user count has been enabled.")
else: else:
@ -120,25 +138,49 @@ class InfoChannel(Cog):
guild.me: discord.PermissionOverwrite(manage_channels=True, connect=True), 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( 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) await self.config.guild(guild).channel_id.set(channel.id)
if botcount: 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( 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) await self.config.guild(guild).botchannel_id.set(botchannel.id)
if onlinecount: 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( 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.config.guild(guild).onlinechannel_id.set(onlinechannel.id)
await self.update_infochannel(guild) 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() guild_data = await self.config.guild(guild).all()
botchannel_id = guild_data["botchannel_id"] botchannel_id = guild_data["botchannel_id"]
onlinechannel_id = guild_data["onlinechannel_id"] onlinechannel_id = guild_data["onlinechannel_id"]
@ -151,6 +193,7 @@ class InfoChannel(Cog):
await botchannel.delete(reason="InfoChannel delete") await botchannel.delete(reason="InfoChannel delete")
if onlinechannel_id is not None: if onlinechannel_id is not None:
await onlinechannel.delete(reason="InfoChannel delete") await onlinechannel.delete(reason="InfoChannel delete")
await self.config.guild(guild).clear() await self.config.guild(guild).clear()
async def update_infochannel(self, guild: discord.Guild): async def update_infochannel(self, guild: discord.Guild):
@ -162,23 +205,23 @@ class InfoChannel(Cog):
# bots = lambda x: x.bot # bots = lambda x: x.bot
# def bots(x): return x.bot # def bots(x): return x.bot
num = len([m for m in guild.members if m.bot]) bot_num = len([m for m in guild.members if m.bot])
bot_msg = f"Bots: {num}" # bot_msg = f"Bots: {num}"
# Gets count of online users # Gets count of online users
members = guild.member_count members = guild.member_count
offline = len(list(filter(lambda m: m.status is discord.Status.offline, guild.members))) offline = len(list(filter(lambda m: m.status is discord.Status.offline, guild.members)))
num = members - offline online_num = members - offline
online_msg = f"Online: {num}" # online_msg = f"Online: {num}"
# Gets count of actual users # Gets count of actual users
total = lambda x: not x.bot total = lambda x: not x.bot
num = len([m for m in guild.members if total(m)]) human_num = len([m for m in guild.members if total(m)])
human_msg = f"Total Humans: {num}" # human_msg = f"Total Humans: {num}"
channel_id = guild_data["channel_id"] channel_id = guild_data["channel_id"]
if channel_id is None: if channel_id is None:
return return False
botchannel_id = guild_data["botchannel_id"] botchannel_id = guild_data["botchannel_id"]
onlinechannel_id = guild_data["onlinechannel_id"] onlinechannel_id = guild_data["onlinechannel_id"]
@ -188,28 +231,53 @@ class InfoChannel(Cog):
onlinechannel: discord.VoiceChannel = guild.get_channel(onlinechannel_id) onlinechannel: discord.VoiceChannel = guild.get_channel(onlinechannel_id)
if guild_data["member_count"]: 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) await channel.edit(reason="InfoChannel update", name=name)
if botcount: if botcount:
name = "{} ".format(bot_msg) name = f"{botchannel.name.split(':')[0]}: {bot_num}"
await botchannel.edit(reason="InfoChannel update", name=name) await botchannel.edit(reason="InfoChannel update", name=name)
if onlinecount: if onlinecount:
name = "{} ".format(online_msg) name = f"{onlinechannel.name.split(':')[0]}: {online_num}"
await onlinechannel.edit(reason="InfoChannel update", name=name) 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() @Cog.listener()
async def on_member_join(self, member: discord.Member): 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() @Cog.listener()
async def on_member_remove(self, member: discord.Member): 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() @Cog.listener()
async def on_member_update(self, before: discord.Member, after: discord.Member): async def on_member_update(self, before: discord.Member, after: discord.Member):
onlinecount = await self.config.guild(after.guild).online_count() onlinecount = await self.config.guild(after.guild).online_count()
if onlinecount: if onlinecount:
if before.status != after.status: if before.status != after.status:
await self.update_infochannel(after.guild) await self.update_infochannel_with_cooldown(after.guild)

Loading…
Cancel
Save