[APPROVED] JojoCogs

Discord Name:
Jojo#7791
GitHub Repository (Must be V3):
https://github.com/Just-Jojo/JojoCogs
Description:

A collection of fun and useful cogs for Red V3. This includes a todo list for keeping track of projects and other utility cogs for bot owners

2 Likes

Hi Jojo, thanks for your patience while I reviewed your repo. None of these are very critical besides perhaps the interaction I listed between AdvancedBlacklist and ErrorBlacklist, under the ErrorBlacklist section.

AdvancedBlacklist

  • format_help_for_context needs an extra backtick in the authors line, to complete the string format.

  • Your converters.py seems to suggest that if I try to blacklist a bot owner, bot, or myself, there should be a friendly message returned, but instead it just provides the command help to the user instead. This also occurs on trying to whitelist a bot.

  • The arg β€œusers” is described as β€œuser” in the command docstring for [p]blacklist add, [p]whitelist add, [p]localblacklist add, [p]localwhitelist add, [p]blacklist remove, [p]localblacklist remove

AdvancedInvite

  • Cool little buttons implementation without having to install other packages.

  • You may want to put some information in the class help or command help that directs people to try to use [p]invite settings as I had to look through the code to find the invite settings.

  • Consider suggesting a public way/PRing a public way to access the β€œinvite_commands_scope” setting in core Red instead of reading from the private Config attribute for the bot in the _invite_url function.

Note that for the following points, I had an existing settings.json from this cog when I previously tested it a few months ago, in case that matters:

  • [p]invite set footer doesn’t seem to set a footer for me when using the [p]invite command.

  • The footer text set could be displayed in the invite settings embed as it’s not at the moment (seeing that you use .all() for settings display, maybe there’s something going on there)

  • The [p]invite set embed toggle seems to not work for me - the message is always sent as an embed.

  • [p]invite set public could use a describing definition for toggle, like you have in [p]invite set embed

AdvancedLog

  • Very minor and not really important, but the β€œNote” header on [p]modnote list is not lined up with the content (note text is 5 spaces ahead of the Note header)

CmdLogger

  • Consider checking for perms on sending messages to the command logger channel.
Ignoring exception in on_command_completion
Traceback (most recent call last):
  File "C:\joker\cogs\CogManager\cogs\cmdlogger\core.py", line 181, in on_command_completion
    await self.log_channel.send(msg)
  File "c:\envs\joker3.4\lib\site-packages\discord\abc.py", line 1065, in send
    data = await state.http.send_message(channel.id, content, tts=tts, embed=embed,
  File "c:\envs\joker3.4\lib\site-packages\discord\http.py", line 248, in request
    raise Forbidden(r, data)
discord.errors.Forbidden: 403 Forbidden (error code: 50001): Missing Access

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\envs\joker3.4\lib\site-packages\discord\client.py", line 343, in _run_event
    await coro(*args, **kwargs)
  File "C:\joker\cogs\CogManager\cogs\cmdlogger\core.py", line 183, in on_command_completion
    log.warning(f"I could not send a message to channel '{channel.name}'")
UnboundLocalError: local variable 'channel' referenced before assignment
  • Using a command name that doesn’t exist with [p]cmdlogger delete or [p]cmdlogger add will cause a traceback
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Traceback (most recent call last) ──────────────────────────────────────────────────────────────────────────────┐
β”‚ c:\envs\joker3.4\lib\site-packages\discord\ext\commands\core.py:85 in wrapped                                                                                                                β”‚
β”‚ >   85             ret = await coro(*args, **kwargs)                                                                                                                                         β”‚
β”‚ C:\joker\cogs\CogManager\cogs\cmdlogger\core.py:112 in cmd_add                                                                                                                               β”‚
β”‚ > 112         cmd = command.qualified_name                                                                                                                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 
AttributeError: 'NoneType' object has no attribute 'qualified_name'

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ Traceback (most recent call last) ──────────────────────────────────────────────────────────────────────────────┐
β”‚ c:\envs\joker3.4\lib\site-packages\discord\ext\commands\core.py:85 in wrapped                                                                                                                β”‚
β”‚ >   85             ret = await coro(*args, **kwargs)                                                                                                                                         β”‚
β”‚ C:\joker\cogs\CogManager\cogs\cmdlogger\core.py:131 in cmd_remove                                                                                                                            β”‚
β”‚ > 131         cmd = command.qualified_name                                                                                                                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 
AttributeError: 'NoneType' object has no attribute 'qualified_name'
  • Possibly add a link to the [p]cmdlogger delete message for: If this command is being tracked, please make an issue on my github or some other way to let the owner know what to do (they may have forgotten your gh by the time they try to use this command this way)

CycleStatus

  • Consider implementing a status length to [p]status add - setting a very long status will show no status when that status comes around

Depypher

Pretty straighforward, no comments here

ErrorBlacklist

  • I have AdvancedBlacklist loaded alongside ErrorBlacklist, and I set up an β€œerror” command that would raise a NotImplementedError and after using mock to mock a user using it to the [p]errorblacklist amount limit, there was a recursion error in AdvancedBlacklist:
Ignoring exception in on_command_error
Traceback (most recent call last):
  File "c:\envs\joker3.4\lib\site-packages\discord\client.py", line 343, in _run_event
    await coro(*args, **kwargs)
  File "C:\joker\cogs\CogManager\cogs\errorblacklist\errorblacklist.py", line 378, in on_command_error
    await add_to_blacklist(self.bot, {user})
  File "c:\envs\joker3.4\lib\site-packages\redbot\core\bot.py", line 550, in add_to_blacklist
    await self._whiteblacklist_cache.add_to_blacklist(guild, to_add)
  File "C:\joker\cogs\CogManager\cogs\advancedblacklist\monkey.py", line 23, in add_to_blacklist
    d = await _FUNCS[0](self, guild, role_or_user)
  File "C:\joker\cogs\CogManager\cogs\advancedblacklist\monkey.py", line 23, in add_to_blacklist
    d = await _FUNCS[0](self, guild, role_or_user)
  File "C:\joker\cogs\CogManager\cogs\advancedblacklist\monkey.py", line 23, in add_to_blacklist
    d = await _FUNCS[0](self, guild, role_or_user)
  [Previous line repeated 983 more times]
RecursionError: maximum recursion depth exceeded

Unloading AdvancedBlacklist did not unload the monkeypatch, and I had to restart the bot to continue testing this command (the mock error worked fine after the restart/not having AB loaded)

  • [p]errorblacklist whitelist add’s docstring has β€œitme” in it, which I’m not quite sure what that is based on the other instructions/docstrings

Thanks for taking the time to review my cogs :smiley:

For AdvancedBlacklist and ErrorBlacklist, I have recently rewritten AdvancedBlacklist so these problems should be fixed.

For AdvancedInvite I fixed the embed issue, added the footer to the invite command, and made the cog’s docstring point to [p]invite set's existence. As for the invite_commands_scope this is purely for backwards compatibility and as such, I don’t think it would benefit from having a new method added to Red.

For CmdLogger I fixed the UnboundLocalError in the listener and the AttributeError in the remove command, I also added a reference to my github page for reporting issues.

For CycleStatus I implemented a maximum length for statuses.

Once again, thank you for reviewing my cogs :slightly_smiling_face:

Hi Jojo, thanks for your patience.

This review is using the commit: https://github.com/Just-Jojo/JojoCogs/commit/faed6049cbc133b5ae2336dee1544371ddb61164

AdvancedBlacklist

If there are users on the bot blacklist before AdvancedBlacklist is loaded, those users will not be present on the blacklist list when the command is used. They are also still blacklisted, and using [p]blacklist remove on this cog with their id will say that the user is not on the blacklist. When the cog is unloaded the list is properly restored and using the default [p]blacklist list will show the blacklisted users/ids.

Cyclestatus
Use [p]cstatus forcenext multiple times with 2x statuses and got:

[14:10:05] ERROR [red] Exception in command 'cyclestatus forcenext'
Traceback (most recent call last)
c:\envs\sass3.4\lib\site-packages\discord\ext\commands\core.py:85 in wrapped
85 ret = await coro(*args, **kwargs)
C:\sass\cogs\CogManager\cogs\cyclestatus\cycle_status.py:92 in forcenext
92 status = (statuses := await self.config.statuses())[nl]
IndexError: list index out of range 

This seems to be intermittent, or if you give it enough time inbetween usages of the command, it doesn’t seem to fail.

ErrorBlacklist

In the help for errorblacklist whitelist add, the argument variable listed is user_com_or_cog while the argument area below says `user_or_command.

ToDo

Used [p]todo move 1 3 with no todos.

[14:19:53] ERROR [red] Exception in command 'todo reorder'
Traceback (most recent call last)
c:\envs\sass3.4\lib\site-packages\discord\ext\commands\core.py:85 in wrapped
85 ret = await coro(*args, **kwargs)
C:\sass\cogs\CogManager\cogs\todo\core.py:311 in todo_reorder
311 return await ctx.send(self._no_todo_message.format(ctx.clean_prefix))
KeyError: 'prefix'

[p]todo shared pin @user 3 says β€œYou are a manager of that user’s list” when I am not (there are no todos at this point in testing, for any user).

Hi there, thanks again for reviewing my cogs.

For AdvancedBlacklist I added a check in the methods for fetching the blacklist from the config to also check the bot’s internal blacklist cache and I added a startup method for the cog to update the cog’s config.

For CycleStatus I catch the index error and reset the next status back to 0.

For ErrorBlacklist I updated the variables in the code.

For ToDo I added prefix= for formatting and I updated the message for todo shared pinned

Hello Jojo, the commit I used to review this was https://github.com/Just-Jojo/JojoCogs/commit/ef4dc434c264144d8e63a9a8d56e6b78fccf71a0

When you ignore the index error for cstatus forcenext being used repeatedly, the status does not change on the command use. This isn’t a terribly big deal in regards to this review - I’m sure your users will let you know if this is an issue. Just writing it here so you know about it.

The last thing I can find for you to take a look at is the [p]todo shared pin @user 3 comment again: I received a traceback when trying this command with an empty todo list.

[16:51:54] ERROR    [red] ConversionError
β”Œβ”€ Traceback (most recent call last) ──
β”‚c:\...\lib\site-packages\discord\ext\commands\core.py:451 in _actual_conversion                                                                                                                                                                    
β”‚ >  451                     ret = await instance.convert(ctx, argument)                                                                                                                                                                                      
β”‚ c:\...\cogs\CogManager\cogs\todo\utils\converters.py:38 in convert                                                                                                                                                                                         
β”‚ > 38             member = await super().convert(ctx, arg)                                                                                                                                                                                                   
β”‚c:\...\lib\site-packages\discord\ext\commands\converter.py:168 in convert                                                                                                                                                                          
β”‚ > 168         match = self._get_id_match(argument) or re.match(r'<@!?([0-9]+)>$', argument)                                                                                                                                                                 
β”‚c:\...\lib\site-packages\discord\ext\commands\converter.py:111 in _get_id_match                                                                                                                                                                    
β”‚ > 111         return self._id_regex.match(argument)                                                                                                                                                                                                         
└──
AttributeError: 'NonBotMember' object has no attribute '_id_regex'

The above exception was the direct cause of the following exception:

β”Œβ”€ Traceback (most recent call last) ──
β”‚c:\...\lib\site-packages\discord\ext\commands\bot.py:939 in invoke                                                                                                                                                                                 
β”‚ >  939                     await ctx.command.invoke(ctx)                                                                                                                                                                                                    
β”‚c:\...\lib\site-packages\redbot\core\commands\commands.py:832 in invoke                                                                                                                                                                            
β”‚ >  832         await super().invoke(ctx)                                                                                                                                                                                                                    
β”‚c:\...\lib\site-packages\discord\ext\commands\core.py:1348 in invoke                                                                                                                                                                               
β”‚ > 1348             await ctx.invoked_subcommand.invoke(ctx)                                                                                                                                                                                                 
β”‚c:\...\lib\site-packages\redbot\core\commands\commands.py:832 in invoke                                                                                                                                                                            
β”‚ >  832         await super().invoke(ctx)                                                                                                                                                                                                                    
β”‚c:\...\lib\site-packages\discord\ext\commands\core.py:1348 in invoke                                                                                                                                                                               
β”‚ > 1348             await ctx.invoked_subcommand.invoke(ctx)                                                                                                                                                                                                 
β”‚c:\...\lib\site-packages\discord\ext\commands\core.py:855 in invoke                                                                                                                                                                                
β”‚ >  855         await self.prepare(ctx)                                                                                                                                                                                                                      
β”‚c:\...\lib\site-packages\redbot\core\commands\commands.py:497 in prepare                                                                                                                                                                           
β”‚ >  497                 await self._parse_arguments(ctx)                                                                                                                                                                                                     
β”‚c:\...\lib\site-packages\discord\ext\commands\core.py:697 in _parse_arguments                                                                                                                                                                      
β”‚ >  697                 transformed = await self.transform(ctx, param)                                                                                                                                                                                       
β”‚c:\...\lib\site-packages\discord\ext\commands\core.py:552 in transform                                                                                                                                                                             
β”‚ >  552         return await self.do_conversion(ctx, converter, argument, param)                                                                                                                                                                             
β”‚c:\...\lib\site-packages\redbot\core\commands\commands.py:526 in do_conversion                                                                                                                                                                     
β”‚ >  526             return await super().do_conversion(ctx, converter, argument, param)                                                                                                                                                                      
β”‚c:\...\lib\site-packages\discord\ext\commands\core.py:505 in do_conversion                                                                                                                                                                         
β”‚ >  505         return await self._actual_conversion(ctx, converter, argument, param)                                                                                                                                                                        
β”‚c:\...\lib\site-packages\discord\ext\commands\core.py:464 in _actual_conversion                                                                                                                                                                    
β”‚ >  464             raise ConversionError(converter, exc) from exc                                                                                                                                                                                           
└──
ConversionError: (<class 'todo.utils.converters.NonBotMember'>, AttributeError("'NonBotMember' object has no attribute '_id_regex'"))

Once again, thanks for your review!

I’ll probably take a look at cstatus forcenext at some point soon but as it’s not too bothersome at the moment I won’t worry about it too much.

And for todo’s traceback I was missing a call to super().__init__ which resolved the error.

Thanks!

Hi Jojo,

Thanks, you’re all set. Get ready for some pings as your role is assigned in various places :wink: