From 6642d797cf55ea2f51967d00904b063435fef8e7 Mon Sep 17 00:00:00 2001 From: Paillat-dev Date: Mon, 12 May 2025 11:50:17 +0200 Subject: [PATCH 1/5] :sparkles: Parse data as message in `parse_message_update` instead of using `_update` --- discord/message.py | 20 -------------------- discord/raw_models.py | 8 +++++++- discord/state.py | 19 +++++++------------ 3 files changed, 14 insertions(+), 33 deletions(-) diff --git a/discord/message.py b/discord/message.py index 55a6bfd6b4..e5d629e2a9 100644 --- a/discord/message.py +++ b/discord/message.py @@ -1012,26 +1012,6 @@ def _clear_emoji(self, emoji) -> Reaction | None: del self.reactions[index] return reaction - def _update(self, data): - # In an update scheme, 'author' key has to be handled before 'member' - # otherwise they overwrite each other which is undesirable. - # Since there's no good way to do this we have to iterate over every - # handler rather than iterating over the keys which is a little slower - for key, handler in self._HANDLERS: - try: - value = data[key] - except KeyError: - continue - else: - handler(self, value) - - # clear the cached properties - for attr in self._CACHED_SLOTS: - try: - delattr(self, attr) - except AttributeError: - pass - def _handle_edited_timestamp(self, value: str) -> None: self._edited_timestamp = utils.parse_time(value) diff --git a/discord/raw_models.py b/discord/raw_models.py index 73da688b7f..80cc490705 100644 --- a/discord/raw_models.py +++ b/discord/raw_models.py @@ -176,15 +176,21 @@ class RawMessageUpdateEvent(_RawReprMixin): cached_message: Optional[:class:`Message`] The cached message, if found in the internal message cache. Represents the message before it is modified by the data in :attr:`RawMessageUpdateEvent.data`. + new_message: Optional[:class:`Message`] + The new message object. Represents the message after it is modified by the data in + :attr:`RawMessageUpdateEvent.data`. + + .. versionadded:: 2.7 """ __slots__ = ("message_id", "channel_id", "guild_id", "data", "cached_message") - def __init__(self, data: MessageUpdateEvent) -> None: + def __init__(self, data: MessageUpdateEvent, new_message: Message) -> None: self.message_id: int = int(data["id"]) self.channel_id: int = int(data["channel_id"]) self.data: MessageUpdateEvent = data self.cached_message: Message | None = None + self.new_message: Message = new_message try: self.guild_id: int | None = int(data["guild_id"]) diff --git a/discord/state.py b/discord/state.py index 52a9cc0989..ded6a5a2c7 100644 --- a/discord/state.py +++ b/discord/state.py @@ -772,21 +772,16 @@ def parse_message_delete_bulk(self, data) -> None: self._messages.remove(msg) # type: ignore def parse_message_update(self, data) -> None: - raw = RawMessageUpdateEvent(data) - message = self._get_message(raw.message_id) - if message is not None: - older_message = copy.copy(message) - raw.cached_message = older_message - self.dispatch("raw_message_edit", raw) - message._update(data) - # Coerce the `after` parameter to take the new updated Member - # ref: #5999 - older_message.author = message.author - self.dispatch("message_edit", older_message, message) + old_message = self._get_message(raw.message_id) + channel, _ = self._get_guild_channel(data) + message = Message(channel=channel, data=data, state=self) + raw = RawMessageUpdateEvent(data, message) + self.dispatch("raw_message_edit", raw) + if old_message is not None: + self.dispatch("message_edit", old_message, message) else: if poll_data := data.get("poll"): self.store_raw_poll(poll_data, raw) - self.dispatch("raw_message_edit", raw) if "components" in data and self._view_store.is_message_tracked(raw.message_id): self._view_store.update_from_message(raw.message_id, data["components"]) From 96e3f3db3dd1ac2c2e8f71130cf5fdfa97580f31 Mon Sep 17 00:00:00 2001 From: Paillat-dev Date: Mon, 12 May 2025 11:58:29 +0200 Subject: [PATCH 2/5] :memo: CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e40955afe..a0808e0dd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,8 @@ These changes are available on the `master` branch, but have not yet been releas ([#2714](https://github.com/Pycord-Development/pycord/pull/2714)) - Added the ability to pass a `datetime.time` object to `format_dt` ([#2747](https://github.com/Pycord-Development/pycord/pull/2747)) +- Added `RawMessageUpdateEvent.new_message` - message update events now contain full + message objects ([#2780](https://github.com/Pycord-Development/pycord/pull/2780)) ### Fixed From d00554473a82e6fe1b2a7ba2a70414df889d0187 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 25 May 2025 18:35:08 +0200 Subject: [PATCH 3/5] :bug: Store updated message --- discord/state.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/discord/state.py b/discord/state.py index ded6a5a2c7..eb26753c9f 100644 --- a/discord/state.py +++ b/discord/state.py @@ -773,8 +773,11 @@ def parse_message_delete_bulk(self, data) -> None: def parse_message_update(self, data) -> None: old_message = self._get_message(raw.message_id) + if old_message is not None: + self._messages.remove(old_message) channel, _ = self._get_guild_channel(data) message = Message(channel=channel, data=data, state=self) + self._messages.append(message) raw = RawMessageUpdateEvent(data, message) self.dispatch("raw_message_edit", raw) if old_message is not None: From b52d71e979c512a1ae79a4fa82a98e7fba8ea8ce Mon Sep 17 00:00:00 2001 From: Lala Sabathil Date: Mon, 1 Sep 2025 18:25:15 +0200 Subject: [PATCH 4/5] fix: changelog entry position Signed-off-by: Lala Sabathil --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b43f571bc9..1bec9cc0b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ These changes are available on the `master` branch, but have not yet been releas ### Added +- Added `RawMessageUpdateEvent.new_message` - message update events now contain full + message objects ([#2780](https://github.com/Pycord-Development/pycord/pull/2780)) + ### Changed ### Fixed @@ -79,8 +82,6 @@ These changes are available on the `master` branch, but have not yet been releas ([#2714](https://github.com/Pycord-Development/pycord/pull/2714)) - Added the ability to pass a `datetime.time` object to `format_dt`. ([#2747](https://github.com/Pycord-Development/pycord/pull/2747)) -- Added `RawMessageUpdateEvent.new_message` - message update events now contain full - message objects ([#2780](https://github.com/Pycord-Development/pycord/pull/2780)) - Added various missing channel parameters and allow `default_reaction_emoji` to be `None`. ([#2772](https://github.com/Pycord-Development/pycord/pull/2772)) - Added support for type hinting slash command options with `typing.Annotated`. From 2293075e691eea8aa61a2fddd92f65edc66697fd Mon Sep 17 00:00:00 2001 From: Paillat Date: Wed, 3 Sep 2025 16:17:53 +0200 Subject: [PATCH 5/5] Update discord/raw_models.py Co-authored-by: Soheab <33902984+Soheab@users.noreply.github.com> Signed-off-by: Paillat --- discord/raw_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/raw_models.py b/discord/raw_models.py index ab2e3860df..86635b90e8 100644 --- a/discord/raw_models.py +++ b/discord/raw_models.py @@ -185,7 +185,7 @@ class RawMessageUpdateEvent(_RawReprMixin): cached_message: Optional[:class:`Message`] The cached message, if found in the internal message cache. Represents the message before it is modified by the data in :attr:`RawMessageUpdateEvent.data`. - new_message: Optional[:class:`Message`] + new_message: :class:`Message` The new message object. Represents the message after it is modified by the data in :attr:`RawMessageUpdateEvent.data`.