0.4.0.0.a2
- Bugfix for commands not fully populating docs site - Deployed version uses global commands. The docs site should now pick these up as well
This commit is contained in:
		
							parent
							
								
									47cc285919
								
							
						
					
					
						commit
						66447865f5
					
				
							
								
								
									
										2
									
								
								bot.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								bot.py
									
									
									
									
									
								
							@ -9,7 +9,7 @@ from modules.common.boot_notice import post_boot_notice
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Version consists of:
 | 
					# Version consists of:
 | 
				
			||||||
# Major.Enhancement.Minor.Patch.Test  (Test is alphanumeric; doesn’t trigger auto update)
 | 
					# Major.Enhancement.Minor.Patch.Test  (Test is alphanumeric; doesn’t trigger auto update)
 | 
				
			||||||
VERSION = "0.4.0.0.a1"
 | 
					VERSION = "0.4.0.0.a2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ---------- Env loading ----------
 | 
					# ---------- Env loading ----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -323,42 +323,60 @@ def _safe_extras(obj: Any) -> Optional[Dict[str, Any]]:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
def _gather_slash(bot: commands.Bot) -> List[Dict[str, Any]]:
 | 
					def _gather_slash(bot: commands.Bot) -> List[Dict[str, Any]]:
 | 
				
			||||||
    rows: List[Dict[str, Any]] = []
 | 
					    rows: List[Dict[str, Any]] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Collect paths from all scopes (global + each guild)
 | 
				
			||||||
 | 
					    collected: List[Tuple[str, app_commands.Command, str]] = []
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        cmds = bot.tree.get_commands()
 | 
					        for scope, top in _iter_all_app_commands(bot):
 | 
				
			||||||
 | 
					            # walk each top-level into leaves
 | 
				
			||||||
 | 
					            for path, leaf in _walk_app_tree(top, prefix=""):
 | 
				
			||||||
 | 
					                collected.append((scope, leaf, path))
 | 
				
			||||||
    except Exception:
 | 
					    except Exception:
 | 
				
			||||||
        traceback.print_exc()
 | 
					        traceback.print_exc()
 | 
				
			||||||
        cmds = []
 | 
					 | 
				
			||||||
    for cmd in cmds or []:
 | 
					 | 
				
			||||||
        for path, leaf in _walk_app_tree(cmd, prefix=""):
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                is_mod, perms = _is_mod_command_slash(leaf)
 | 
					 | 
				
			||||||
                binding = getattr(leaf, "binding", None)
 | 
					 | 
				
			||||||
                callback = getattr(leaf, "callback", None)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                display = "/" + path.lstrip("/").replace("/", " ")
 | 
					    # De-dupe by canonical path (e.g. "power/restart"), regardless of scope
 | 
				
			||||||
                options = getattr(leaf, "options", None) or getattr(leaf, "parameters", None) or getattr(leaf, "_params", None)
 | 
					    seen_paths = set()
 | 
				
			||||||
                usage_full = _command_usage_slash_like(path.lstrip("/").replace("/", " "), options)
 | 
					    for scope, leaf, path in collected:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
                row = {
 | 
					            canon = path.lstrip("/")  # e.g. "power/restart"
 | 
				
			||||||
                    "type": "slash",
 | 
					            if canon in seen_paths:
 | 
				
			||||||
                    "name": path,               # canonical '/group/sub'
 | 
					 | 
				
			||||||
                    "display_name": display,    # shown without the leading '/'
 | 
					 | 
				
			||||||
                    "help": (getattr(leaf, "description", "") or "").strip(),
 | 
					 | 
				
			||||||
                    "brief": "",
 | 
					 | 
				
			||||||
                    "usage": usage_full,
 | 
					 | 
				
			||||||
                    "usage_prefix": None,
 | 
					 | 
				
			||||||
                    "usage_slash": usage_full,
 | 
					 | 
				
			||||||
                    "cog": binding.__class__.__name__ if binding else None,
 | 
					 | 
				
			||||||
                    "module": getattr(callback, "__module__", None) if callback else None,
 | 
					 | 
				
			||||||
                    "moderator_only": bool(is_mod),
 | 
					 | 
				
			||||||
                    "required_permissions": perms,
 | 
					 | 
				
			||||||
                    "extras": _safe_extras(leaf),
 | 
					 | 
				
			||||||
                    "dm_permission": getattr(leaf, "dm_permission", None),
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                rows.append(row)
 | 
					 | 
				
			||||||
            except Exception:
 | 
					 | 
				
			||||||
                traceback.print_exc()
 | 
					 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
 | 
					            seen_paths.add(canon)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            is_mod, perms = _is_mod_command_slash(leaf)
 | 
				
			||||||
 | 
					            binding = getattr(leaf, "binding", None)
 | 
				
			||||||
 | 
					            callback = getattr(leaf, "callback", None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # UI shows "power restart" (title), but usage keeps "/power restart ..."
 | 
				
			||||||
 | 
					            display = canon.replace("/", " ")
 | 
				
			||||||
 | 
					            options = (
 | 
				
			||||||
 | 
					                getattr(leaf, "options", None)
 | 
				
			||||||
 | 
					                or getattr(leaf, "parameters", None)
 | 
				
			||||||
 | 
					                or getattr(leaf, "_params", None)
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            usage_full = _command_usage_slash_like(display, options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            row = {
 | 
				
			||||||
 | 
					                "type": "slash",
 | 
				
			||||||
 | 
					                "name": "/" + canon,            # canonical with leading slash
 | 
				
			||||||
 | 
					                "display_name": "/" + display,  # shown without the leading slash in UI
 | 
				
			||||||
 | 
					                "help": (getattr(leaf, "description", "") or "").strip(),
 | 
				
			||||||
 | 
					                "brief": "",
 | 
				
			||||||
 | 
					                "usage": usage_full,
 | 
				
			||||||
 | 
					                "usage_prefix": None,
 | 
				
			||||||
 | 
					                "usage_slash": usage_full,
 | 
				
			||||||
 | 
					                "cog": binding.__class__.__name__ if binding else None,
 | 
				
			||||||
 | 
					                "module": getattr(callback, "__module__", None) if callback else None,
 | 
				
			||||||
 | 
					                "moderator_only": bool(is_mod),
 | 
				
			||||||
 | 
					                "required_permissions": perms,
 | 
				
			||||||
 | 
					                "extras": _safe_extras(leaf),
 | 
				
			||||||
 | 
					                "dm_permission": getattr(leaf, "dm_permission", None),
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            rows.append(row)
 | 
				
			||||||
 | 
					        except Exception:
 | 
				
			||||||
 | 
					            traceback.print_exc()
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return rows
 | 
					    return rows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -517,6 +535,35 @@ def _merge_hybrid_slash(rows: List[Dict[str, Any]]) -> None:
 | 
				
			|||||||
    for i in sorted(to_remove, reverse=True):
 | 
					    for i in sorted(to_remove, reverse=True):
 | 
				
			||||||
        rows.pop(i)
 | 
					        rows.pop(i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# =============================
 | 
				
			||||||
 | 
					# Global commands helper
 | 
				
			||||||
 | 
					# =============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _iter_all_app_commands(bot: commands.Bot):
 | 
				
			||||||
 | 
					    """Yield (path, app_commands.Command) for global and per-guild trees."""
 | 
				
			||||||
 | 
					    out = []
 | 
				
			||||||
 | 
					    # Global
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        for cmd in bot.tree.get_commands():
 | 
				
			||||||
 | 
					            out.append(("", cmd))  # empty scope tag
 | 
				
			||||||
 | 
					    except Exception:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Per-guild (guild-specific commands live here)
 | 
				
			||||||
 | 
					    for g in list(getattr(bot, "guilds", []) or []):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            cmds = bot.tree.get_commands(guild=g)
 | 
				
			||||||
 | 
					        except TypeError:
 | 
				
			||||||
 | 
					            # older d.py variants accept Snowflake-like instead of Guild
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                cmds = bot.tree.get_commands(guild=discord.Object(id=g.id))
 | 
				
			||||||
 | 
					            except Exception:
 | 
				
			||||||
 | 
					                cmds = []
 | 
				
			||||||
 | 
					        except Exception:
 | 
				
			||||||
 | 
					            cmds = []
 | 
				
			||||||
 | 
					        for cmd in cmds or []:
 | 
				
			||||||
 | 
					            out.append((str(g.id), cmd))  # scope tag = guild id as string
 | 
				
			||||||
 | 
					    return out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# =============================
 | 
					# =============================
 | 
				
			||||||
# Schema builder
 | 
					# Schema builder
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user