Repository: Pycord-Development/pycord

Issue:
Set `discord.ui.View.message` on an interaction followup
### Summary

`View.message` should be set when the message is sent via `Interaction.followup.send()`.

### What is the feature request for?

The core library

### The Problem

`Interaction.response.send_message()` sets the `View.message` property. For consistency, this property should also be set when using `Interaction.followup.send()`.

### The Ideal Solution

The following assertion should pass:
```py
view = SomeView()
await interaction.followup.send("My message", view=view)
assert view.message is not None
```
This would prevent errors if setting `disable_on_timeout=True` or otherwise manipulating the `message` property.

### The Current Solution

You must manually set `View.message` using the return value of `Interaction.followup.send()`.

### Additional Context

_No response_
Update `discord.ui.View.message` when editing a message with a new view
### Summary

`View.message` is sometimes `None` when it clearly is attached to a message

### What is the feature request for?

The core library

### The Problem

Sometimes (like in `View.on_timeout`) there is no reference to the message a view is attached to, and storing it beforehand is not viable.

### The Ideal Solution

For example:
```python
view1 = CustomView()
message = await channel.send("text", view=view)
await asyncio.sleep(2)
view2 = CustomView2()
await message.edit(view=view2)
```
After the edit, `view1.message` should be `None` and `view2.message` should be `message`. Currently it is the opposite way round.

### The Current Solution

_No response_

### Additional Context

_No response_


Discussion:

Resolving patch:
diff --git a/discord/interactions.py b/discord/interactions.py
--- a/discord/interactions.py
+++ b/discord/interactions.py
@@ -440,6 +440,7 @@ async def edit_original_response(
         state = _InteractionMessageState(self, self._state)
         message = InteractionMessage(state=state, channel=self.channel, data=data)  # type: ignore
         if view and not view.is_finished():
+            view.message = message
             self._state.store_view(view, message.id)
 
         if delete_after is not None:
@@ -976,6 +977,7 @@ async def edit_message(
                     file.close()
 
         if view and not view.is_finished():
+            view.message = msg
             state.store_view(view, message_id)
 
         self._responded = True
diff --git a/discord/message.py b/discord/message.py
--- a/discord/message.py
+++ b/discord/message.py
@@ -1468,6 +1468,7 @@ async def edit(
         message = Message(state=self._state, channel=self.channel, data=data)
 
         if view and not view.is_finished():
+            view.message = message
             self._state.store_view(view, self.id)
 
         if delete_after is not None:
@@ -2021,5 +2022,6 @@ async def edit(self, **fields: Any) -> Message | None:
             # data isn't unbound
             msg = self._state.create_message(channel=self.channel, data=data)  # type: ignore
             if view and not view.is_finished():
+                view.message = msg
                 self._state.store_view(view, self.id)
             return msg
diff --git a/discord/webhook/async_.py b/discord/webhook/async_.py
--- a/discord/webhook/async_.py
+++ b/discord/webhook/async_.py
@@ -1762,6 +1762,7 @@ async def send(
 
         if view is not MISSING and not view.is_finished():
             message_id = None if msg is None else msg.id
+            view.message = None if msg is None else msg
             self._state.store_view(view, message_id)
 
         if delete_after is not None:
@@ -1957,6 +1958,7 @@ async def edit_message(
 
         message = self._create_message(data)
         if view and not view.is_finished():
+            view.message = message
             self._state.store_view(view, message_id)
         return message
 


Test patch: