Repository: Cog-Creators/Red-DiscordBot

Issue:
[Permissions] Schema checking gives unrelated errors
# Command bugs

#### Command name

`[p]permissions acl setglobal/setserver/updateglobal/updateserver`

#### What cog is this command from?

Permissions

#### What were you expecting to happen?

Either get error about incorrect type of key or have Permissions automatically convert int to str.

#### What actually happened?

I got error "Top-level keys must be either `COG` or `COMMAND`"

#### How can we reproduce this issue?

1. Create such yaml permissions file:
```yaml
COMMAND:
  8:
    176070082584248320: true
```
2. Upload it using one of the commands: `[p]permissions acl setglobal/setserver/updateglobal/updateserver`
3. See error.

---

The above is reproduction for issue that was already fixed, but the unrelated errors can still happen for yaml file like this:
```yaml
COMMAND:
  ping:
    default_but_spelt_incorrectly: false
```



Discussion:
For anyone currently experiencing this issue:

Wrapping a numeric command in quotes will work fine.

```yaml
COMMAND:
  "8":
    176070082584248320: true
```

I'm not sure if we should actually consider this as a bug with permissions, this was intended to catch a mistake like

```yaml
COMMAND:
  176070082584248320: true
```

and quoting the command makes sure it was an explicit choice. I think we can be a little more intelligent about it, or at least give a more useful error if/when it occurs so that if it is intentional, people know how to handle it.
The latter example wouldn't be valid because `true` is not a dict so it should still be possible to differentiate these 2 errors, right? 
We can definitely be smarter about the rror handling here. Just requires someone to update the schema handling for this.

Resolving patch:
diff --git a/redbot/cogs/permissions/permissions.py b/redbot/cogs/permissions/permissions.py
--- a/redbot/cogs/permissions/permissions.py
+++ b/redbot/cogs/permissions/permissions.py
@@ -40,12 +40,13 @@
         {
             UseOptional(COMMAND): Or(
                 {
-                    str: And(
+                    Or(str, int): Or(
                         {
                             Or(int, "default"): And(
                                 bool, error=_("Rules must be either `true` or `false`.")
                             )
                         },
+                        {},
                         error=_("Keys under command names must be IDs (numbers) or `default`."),
                     )
                 },
@@ -54,7 +55,7 @@
             ),
             UseOptional(COG): Or(
                 {
-                    str: Or(
+                    Or(str, int): Or(
                         {
                             Or(int, "default"): And(
                                 bool, error=_("Rules must be either `true` or `false`.")
@@ -664,7 +665,7 @@ async def _yaml_set_acl(self, source: discord.Attachment, guild_id: int, update:
             for cmd_name, cmd_rules in rules_dict.items():
                 cmd_rules = {str(model_id): rule for model_id, rule in cmd_rules.items()}
                 await conf.set_raw(cmd_name, str(guild_id), value=cmd_rules)
-                cmd_obj = getter(cmd_name)
+                cmd_obj = getter(str(cmd_name))
                 if cmd_obj is not None:
                     self._load_rules_for(cmd_obj, {guild_id: cmd_rules})
 


Test patch: