22from discord import app_commands
33from discord .ext import commands
44
5- from src .utils import Embeds , Error
5+ from src .utils import Embeds , Error , ViewPageScroller
6+ from typing import Optional , List
67
78
89class Help (commands .Cog ):
@@ -32,75 +33,124 @@ async def on_ready(self):
3233 @app_commands .describe (
3334 query = 'Module\' s or Command\' s name'
3435 )
35- @commands .cooldown (1 , 15 )
36- async def help (self , ctx : commands .Context , query : str = None ):
37- """Shows all modules of that bot"""
38-
39- embed = Embeds (
40- title = 'Commands' ,
41- description = f'Use `/help <module>` or `/help <command>` for more information about that module or command\n \u200d '
42- )
43- embed .color = discord .Color .blurple ()
44-
36+ @commands .cooldown (1 , 15 , commands .BucketType .user )
37+ async def help (self , ctx : commands .Context , * , query : Optional [str ] = None ):
38+ """
39+ **Help command of the bot**
40+
41+ > **Arguments**
42+ ```
43+ query | string | default=None
44+ ```
45+
46+ > **Example**
47+ ```
48+ /help
49+ /help ping
50+ ```
51+ """
52+ embed_data : dict [str , list [list ]] = {}
53+ page_limit = 1
54+
55+ async def load_cog_commands (cog , cmds ):
56+ if str (self .client .cogs [cog ].__doc__ ).startswith ('hidden' ): return
57+ if not cog in embed_data :
58+ embed_data [cog ] = [[]]
59+
60+ for i in cmds :
61+ if i .hidden or str (i .help ).startswith ('hidden' ) or not await i .can_run (ctx ): continue
62+ if len (embed_data [cog ][- 1 ]) >= page_limit :
63+ embed_data [cog ].append ([i ])
64+ else :
65+ embed_data [cog ][- 1 ].append (i )
66+
67+
4568 if not query :
46- available_cogs = []
47- for cog in self .client .cogs :
48- available_commands = []
49- for cmd in self .client .get_cog (cog ).walk_commands ():
50- if not cmd .hidden and not str (cmd .help ).startswith ('hidden' ) and await cmd .can_run (ctx ):
51- available_commands .append (cmd )
52-
53- if len (available_commands ) > 0 :
54- available_cogs .append (cog )
55-
56- embed .add_field (
57- name = 'Modules' ,
58- value = '\n \u200d \n ' .join (
59- f'**{ cog } **\n ```{ str (self .client .cogs [cog ].__doc__ ).lstrip ().rstrip ()} ```' for cog in available_cogs if (
60- not str (self .client .cogs [cog ].__doc__ ).startswith ('hidden' )
61- )
62- ),
63- inline = False
64- )
69+ for cogname in self .client .cogs :
70+ if str (self .client .cogs [cogname ].__doc__ ).startswith ('hidden' ): continue # Skip hidden cogs
71+
72+ cog = self .client .get_cog (cogname )
73+ if cog :
74+ await load_cog_commands (cogname , cog .walk_commands ())
6575
6676 else :
67- found = False
68- async def add_to_embed (cmd ):
69- if await cmd .can_run (ctx ):
70- embed .add_field (
71- name = f'/{ cmd .qualified_name } ' ,
72- value = f'{ str (cmd .help ).lstrip ().rstrip ()} \n ' ,
73- inline = False
74- )
75-
76- for cog in self .client .cogs :
77- if query .lower () == cog .lower () and not str (self .client .cogs [cog ].__doc__ ).startswith ('hidden' ):
78- embed .description += f'\n **{ cog } \' s commands**\n \u200d '
79- available_commands_cog = []
80-
81- for cmd in self .client .get_cog (cog ).walk_commands ():
82- if (not cmd .hidden and not str (cmd .help ).startswith ('hidden' )) and await cmd .can_run (ctx ):
83- available_commands_cog .append (cmd )
84-
85- if len (available_commands_cog ) > 0 :
86- for i in available_commands_cog : await add_to_embed (i )
87- found = True
77+ query = '' .join (query )
78+ for cogname in self .client .cogs :
79+ if query .lower () == cogname .lower () and not str (self .client .cogs [cogname ].__doc__ ).startswith ('hidden' ):
80+ cog = self .client .get_cog (cogname )
81+ if not cog : continue
82+
83+ await load_cog_commands (cogname , cog .walk_commands ())
8884 break
8985
90- elif not str (self .client .cogs [cog ].__doc__ ).startswith ('hidden' ):
91- for cmd in self .client .get_cog (cog ).walk_commands ():
92- if (not cmd .hidden and not str (cmd .help ).startswith ('hidden' )):
93- if query .lower ().strip () in cmd .qualified_name .lower ().strip ():
94- found = True
95- await add_to_embed (cmd )
86+ elif not str (self .client .cogs [cogname ].__doc__ ).startswith ('hidden' ):
87+ cog = self .client .get_cog (cogname )
88+ if not cog : continue
89+
90+ for cmd in cog .walk_commands ():
91+ if query .lower ().strip () in cmd .qualified_name .lower ().strip ():
92+ await load_cog_commands (cogname , [cmd ])
93+
94+
95+ if not embed_data :
96+ raise Error (
97+ description = f'Unable to locate module or command' + ((query and f'[{ query } ]' ) or '' )
98+ )
99+
100+ else : #clean up
101+ cleaned = []
102+ for cogName , pages in embed_data .items ():
103+ for page in pages :
104+ cleaned .append ([cogName , list (page )])
105+
106+
107+ #Setup embed screen navigation
108+ def load_page (data : tuple ):
109+ if not self .client .user :
110+ raise Error ('Client not logged in!' )
111+
112+ embed = Embeds (
113+ title = 'Commands' ,
114+ description = f'Use `/help <module>` or `/help <command>` for more information about that module or command\n \n **{ data [0 ]} \' s commands**\n \u200d '
115+ )
116+ embed .color = discord .Color .blurple ()
117+ embed .set_author (name = self .client .user .name , icon_url = self .client .user .display_avatar )
118+
119+ for i in data [1 ]:
120+ embed .add_field (
121+ name = f'/{ i .qualified_name } ' ,
122+ value = f'{ str (i .help ).lstrip ().rstrip ()} \n ' ,
123+ inline = False
124+ )
125+
126+ return embed
127+
128+ scroll_embed = ViewPageScroller (
129+ ownerid = ctx .author .id ,
130+ load_page = load_page ,
131+ pages = cleaned ,
132+ timeout = 180
133+ )
134+
135+ await scroll_embed .send_message (ctx )
136+
96137
97- if found : break
98- if not found :
99- raise Error (description = f'Unable to locate module or command [{ query } ]' )
138+ @help .autocomplete ('query' )
139+ async def help_autocomplete (self , ctx , current : str ) -> List [app_commands .Choice [str ]]:
140+ data = []
141+ command_names = []
142+ for i in self .client .commands :
143+ if i .hidden or str (i .help ).startswith ('hidden' ): continue
144+ command_names += list (i .aliases ) + [i .name ]
100145
101- await ctx .reply (embed = embed )
146+ for name in [cog for cog in self .client .cogs if not str (self .client .cogs [cog ].__doc__ ).startswith ('hidden' )] + command_names :
147+ if current .lower () in name .lower ():
148+ data .append (app_commands .Choice (
149+ name = name ,
150+ value = name
151+ ))
152+ return data [0 :24 ]
102153
103154
104- async def setup (client : commands . Bot ):
155+ async def setup (client ):
105156 await client .add_cog (Help (client ))
106-
0 commit comments