Skip to content

Commit d0c2eb5

Browse files
committed
feat: message events
1 parent 97dac81 commit d0c2eb5

File tree

5 files changed

+270
-280
lines changed

5 files changed

+270
-280
lines changed

discord/app/cache.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ async def store_private_channel(self, channel: PrivateChannel) -> None:
152152
async def store_message(self, message: MessagePayload, channel: MessageableChannel) -> Message:
153153
...
154154

155+
async def upsert_message(self, message: Message) -> None:
156+
...
157+
155158
async def delete_message(self, message_id: int) -> None:
156159
...
157160

@@ -332,8 +335,13 @@ async def get_private_channel_by_user(self, user_id: int) -> PrivateChannel | No
332335

333336
# messages
334337

338+
async def upsert_message(self, message: Message) -> None:
339+
self._messages.append(message)
340+
335341
async def store_message(self, message: MessagePayload, channel: MessageableChannel) -> Message:
336342
msg = await Message._from_data(state=self._state, channel=channel, data=message)
343+
self._messages.append(msg)
344+
return msg
337345

338346
async def get_message(self, message_id: int) -> Message | None:
339347
return utils.find(lambda m: m.id == message_id, reversed(self._messages))

discord/app/state.py

Lines changed: 6 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -524,163 +524,6 @@ async def query_members(
524524
)
525525
raise
526526

527-
528-
def parse_message_update(self, data) -> None:
529-
raw = RawMessageUpdateEvent(data)
530-
message = self._get_message(raw.message_id)
531-
if message is not None:
532-
older_message = copy.copy(message)
533-
raw.cached_message = older_message
534-
self.dispatch("raw_message_edit", raw)
535-
message._update(data)
536-
# Coerce the `after` parameter to take the new updated Member
537-
# ref: #5999
538-
older_message.author = message.author
539-
self.dispatch("message_edit", older_message, message)
540-
else:
541-
if poll_data := data.get("poll"):
542-
self.store_raw_poll(poll_data, raw)
543-
self.dispatch("raw_message_edit", raw)
544-
545-
if "components" in data and self._view_store.is_message_tracked(raw.message_id):
546-
self._view_store.update_from_message(raw.message_id, data["components"])
547-
548-
def parse_message_reaction_add(self, data) -> None:
549-
emoji = data["emoji"]
550-
emoji_id = utils._get_as_snowflake(emoji, "id")
551-
emoji = PartialEmoji.with_state(
552-
self, id=emoji_id, animated=emoji.get("animated", False), name=emoji["name"]
553-
)
554-
raw = RawReactionActionEvent(data, emoji, "REACTION_ADD")
555-
556-
member_data = data.get("member")
557-
if member_data:
558-
guild = self._get_guild(raw.guild_id)
559-
if guild is not None:
560-
raw.member = Member(data=member_data, guild=guild, state=self)
561-
else:
562-
raw.member = None
563-
else:
564-
raw.member = None
565-
self.dispatch("raw_reaction_add", raw)
566-
567-
# rich interface here
568-
message = self._get_message(raw.message_id)
569-
if message is not None:
570-
emoji = self._upgrade_partial_emoji(emoji)
571-
reaction = message._add_reaction(data, emoji, raw.user_id)
572-
user = raw.member or self._get_reaction_user(message.channel, raw.user_id)
573-
574-
if user:
575-
self.dispatch("reaction_add", reaction, user)
576-
577-
def parse_message_reaction_remove_all(self, data) -> None:
578-
raw = RawReactionClearEvent(data)
579-
self.dispatch("raw_reaction_clear", raw)
580-
581-
message = self._get_message(raw.message_id)
582-
if message is not None:
583-
old_reactions = message.reactions.copy()
584-
message.reactions.clear()
585-
self.dispatch("reaction_clear", message, old_reactions)
586-
587-
def parse_message_reaction_remove(self, data) -> None:
588-
emoji = data["emoji"]
589-
emoji_id = utils._get_as_snowflake(emoji, "id")
590-
emoji = PartialEmoji.with_state(self, id=emoji_id, name=emoji["name"])
591-
raw = RawReactionActionEvent(data, emoji, "REACTION_REMOVE")
592-
593-
member_data = data.get("member")
594-
if member_data:
595-
guild = self._get_guild(raw.guild_id)
596-
if guild is not None:
597-
raw.member = Member(data=member_data, guild=guild, state=self)
598-
else:
599-
raw.member = None
600-
else:
601-
raw.member = None
602-
603-
self.dispatch("raw_reaction_remove", raw)
604-
605-
message = self._get_message(raw.message_id)
606-
if message is not None:
607-
emoji = self._upgrade_partial_emoji(emoji)
608-
try:
609-
reaction = message._remove_reaction(data, emoji, raw.user_id)
610-
except (AttributeError, ValueError): # eventual consistency lol
611-
pass
612-
else:
613-
user = self._get_reaction_user(message.channel, raw.user_id)
614-
if user:
615-
self.dispatch("reaction_remove", reaction, user)
616-
617-
def parse_message_reaction_remove_emoji(self, data) -> None:
618-
emoji = data["emoji"]
619-
emoji_id = utils._get_as_snowflake(emoji, "id")
620-
emoji = PartialEmoji.with_state(self, id=emoji_id, name=emoji["name"])
621-
raw = RawReactionClearEmojiEvent(data, emoji)
622-
self.dispatch("raw_reaction_clear_emoji", raw)
623-
624-
message = self._get_message(raw.message_id)
625-
if message is not None:
626-
try:
627-
reaction = message._clear_emoji(emoji)
628-
except (AttributeError, ValueError): # eventual consistency lol
629-
pass
630-
else:
631-
if reaction:
632-
self.dispatch("reaction_clear_emoji", reaction)
633-
634-
def parse_message_poll_vote_add(self, data) -> None:
635-
raw = RawMessagePollVoteEvent(data, True)
636-
guild = self._get_guild(raw.guild_id)
637-
if guild:
638-
user = guild.get_member(raw.user_id)
639-
else:
640-
user = self.get_user(raw.user_id)
641-
self.dispatch("raw_poll_vote_add", raw)
642-
643-
self._get_message(raw.message_id)
644-
poll = self.get_poll(raw.message_id)
645-
# if message was cached, poll has already updated but votes haven't
646-
if poll and poll.results:
647-
answer = poll.get_answer(raw.answer_id)
648-
counts = poll.results._answer_counts
649-
if answer is not None:
650-
if answer.id in counts:
651-
counts[answer.id].count += 1
652-
else:
653-
counts[answer.id] = PollAnswerCount(
654-
{"id": answer.id, "count": 1, "me_voted": False}
655-
)
656-
if poll is not None and user is not None:
657-
answer = poll.get_answer(raw.answer_id)
658-
if answer is not None:
659-
self.dispatch("poll_vote_add", poll, user, answer)
660-
661-
def parse_message_poll_vote_remove(self, data) -> None:
662-
raw = RawMessagePollVoteEvent(data, False)
663-
guild = self._get_guild(raw.guild_id)
664-
if guild:
665-
user = guild.get_member(raw.user_id)
666-
else:
667-
user = self.get_user(raw.user_id)
668-
self.dispatch("raw_poll_vote_remove", raw)
669-
670-
self._get_message(raw.message_id)
671-
poll = self.get_poll(raw.message_id)
672-
# if message was cached, poll has already updated but votes haven't
673-
if poll and poll.results:
674-
answer = poll.get_answer(raw.answer_id)
675-
counts = poll.results._answer_counts
676-
if answer is not None:
677-
if answer.id in counts:
678-
counts[answer.id].count -= 1
679-
if poll is not None and user is not None:
680-
answer = poll.get_answer(raw.answer_id)
681-
if answer is not None:
682-
self.dispatch("poll_vote_remove", poll, user, answer)
683-
684527
def parse_interaction_create(self, data) -> None:
685528
interaction = Interaction(data=data, state=self)
686529
if data["type"] == 3: # interaction component
@@ -1711,21 +1554,21 @@ def _get_typing_user(
17111554

17121555
return self.get_user(user_id)
17131556

1714-
def _get_reaction_user(
1557+
async def _get_reaction_user(
17151558
self, channel: MessageableChannel, user_id: int
17161559
) -> User | Member | None:
17171560
if isinstance(channel, TextChannel):
17181561
return channel.guild.get_member(user_id)
1719-
return self.get_user(user_id)
1562+
return await self.get_user(user_id)
17201563

1721-
def get_reaction_emoji(self, data) -> GuildEmoji | AppEmoji | PartialEmoji:
1564+
async def get_reaction_emoji(self, data) -> GuildEmoji | AppEmoji | PartialEmoji:
17221565
emoji_id = utils._get_as_snowflake(data, "id")
17231566

17241567
if not emoji_id:
17251568
return data["name"]
17261569

17271570
try:
1728-
return self._emojis[emoji_id]
1571+
return await self.cache.get_emoji(emoji_id)
17291572
except KeyError:
17301573
return PartialEmoji.with_state(
17311574
self,
@@ -1734,16 +1577,13 @@ def get_reaction_emoji(self, data) -> GuildEmoji | AppEmoji | PartialEmoji:
17341577
name=data["name"],
17351578
)
17361579

1737-
def _upgrade_partial_emoji(
1580+
async def _upgrade_partial_emoji(
17381581
self, emoji: PartialEmoji
17391582
) -> GuildEmoji | AppEmoji | PartialEmoji | str:
17401583
emoji_id = emoji.id
17411584
if not emoji_id:
17421585
return emoji.name
1743-
try:
1744-
return self._emojis[emoji_id]
1745-
except KeyError:
1746-
return emoji
1586+
return await self.cache.get_emoji(emoji_id) or emoji
17471587

17481588
async def get_channel(self, id: int | None) -> Channel | Thread | None:
17491589
if id is None:

discord/events/gateway.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
class Resumed(Event):
4444
__event_name__ = "RESUMED"
4545

46+
@classmethod
47+
async def __load__(cls, _data: Any, _state: ConnectionState) -> Self | None:
48+
return cls()
49+
4650

4751
class Ready(Event):
4852
__event_name__ = "READY"

0 commit comments

Comments
 (0)