Repository: Pycord-Development/pycord

Issue:
Attribute error when checking for permissions with has_permissions
### Summary

When inviting bot only with applications.commands scope has_permissions will fail due to an attribute error.

### Reproduction Steps

Register a command with @has_permissions(administrator=True) for example.
Invite the bot only with applications.commands scope.
Try to execute the command.

See how you get an attribute error in the console.
AttributeError: 'PartialMessageable' object has no attribute 'permissions_for'

### Minimal Reproducible Code

```python
import discord
from discord.ext.commands import has_permissions

bot = discord.Bot()


@bot.event
async def on_ready():
    print(f"We have logged in as {bot.user}")


@has_permissions(administrator=True)
@bot.slash_command(guild_ids=[guild_id])
async def hello(ctx):
    await ctx.respond("Hello!")


bot.run("TOKEN")
```


### Expected Results

We should get a more telling error message that the channel was not cached and for that reason we cant check permissions.

### Actual Results

We get an error 
AttributeError: 'PartialMessageable' object has no attribute 'permissions_for'

Since we did not get an GUILD_CREATE event for the guild because it was not invited with the bot scope

Traceback:
Ignoring exception in on_interaction
Traceback (most recent call last):
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\client.py", line 378, in _run_event
    await coro(*args, **kwargs)
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\bot.py", line 1167, in on_interaction
    await self.process_application_commands(interaction)
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\bot.py", line 848, in process_application_commands
    await self.invoke_application_command(ctx)
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\bot.py", line 1114, in invoke_application_command
    await ctx.command.invoke(ctx)
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\commands\core.py", line 372, in invoke
    await self.prepare(ctx)
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\commands\core.py", line 292, in prepare
    if not await self.can_run(ctx):
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\commands\core.py", line 400, in can_run
    return await async_all(predicate(ctx) for predicate in predicates)  # type: ignore
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\utils.py", line 699, in async_all
    for elem in gen:
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\commands\core.py", line 400, in <genexpr>
    return await async_all(predicate(ctx) for predicate in predicates)  # type: ignore
  File "C:\Users\Mihito\PycharmProjects\pythonProject\venv\lib\site-packages\discord\ext\commands\core.py", line 2129, in predicate
    permissions = ctx.channel.permissions_for(ctx.author)  # type: ignore
AttributeError: 'PartialMessageable' object has no attribute 'permissions_for'

### Intents

default

### System Information

- Python v3.9.13-final
- py-cord v2.4.1-final
- aiohttp v3.8.4
- system info: Windows 10 10.0.19045


### Checklist

- [X] I have searched the open issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have removed my token from display, if visible.

### Additional Context

_No response_


Discussion:
Inviting bots only with app command scope is meant for http interaction bots normally.
> Inviting bots only with app command scope is meant for http interaction bots normally.
While this is true in my opinion there should still be a type check.

The type hints explicitly say that this can be a PartialMessagable.
Of course its a very niche problem but imo still worth to fix.


Resolving patch:
diff --git a/discord/abc.py b/discord/abc.py
--- a/discord/abc.py
+++ b/discord/abc.py
@@ -712,7 +712,7 @@ def permissions_for(self, obj: Member | Role, /) -> Permissions:
             return Permissions.all()
 
         default = self.guild.default_role
-        base = Permissions(default.permissions.value)
+        base = Permissions(default.permissions.value if default else 0)
 
         # Handle the role case first
         if isinstance(obj, Role):
diff --git a/discord/interactions.py b/discord/interactions.py
--- a/discord/interactions.py
+++ b/discord/interactions.py
@@ -149,6 +149,8 @@ class Interaction:
         "custom_id",
         "_channel_data",
         "_message_data",
+        "_guild_data",
+        "_guild",
         "_permissions",
         "_app_permissions",
         "_state",
@@ -188,6 +190,11 @@ def _from_data(self, data: InteractionPayload):
         self.user: User | Member | None = None
         self._permissions: int = 0
 
+        self._guild: Guild | None = None
+        self._guild_data = data.get("guild")
+        if self.guild is None and self._guild_data:
+            self._guild = Guild(data=self._guild_data, state=self)
+
         # TODO: there's a potential data loss here
         if self.guild_id:
             guild = (
@@ -246,6 +253,8 @@ def client(self) -> Client:
     @property
     def guild(self) -> Guild | None:
         """The guild the interaction was sent from."""
+        if self._guild:
+            return self._guild
         return self._state and self._state._get_guild(self.guild_id)
 
     def is_command(self) -> bool:


Test patch: