Plugin

ValidReply

Fixes "Message could not be loaded" upon hovering over the reply

Chat Utility
index.ts
Download

Source

src/plugins/validReply/index.ts
1import { Devs } from "@utils/constants";
2import definePlugin from "@utils/types";
3import { Channel, Message, User } from "@vencord/discord-types";
4import { findByCodeLazy } from "@webpack";
5import { FluxDispatcher, RestAPI } from "@webpack/common";
6
7const enum ReferencedMessageState {
8 Loaded,
9 NotLoaded,
10 Deleted
11}
12
13interface Reply {
14 baseAuthor: User,
15 baseMessage: Message;
16 channel: Channel;
17 referencedMessage: { state: ReferencedMessageState; };
18 compact: boolean;
19 isReplyAuthorBlocked: boolean;
20}
21
22const fetching = new Map<string, string>();
23let ReplyStore: any;
24
25const createMessageRecord = findByCodeLazy(".createFromServer(", ".isBlockedForMessage", "messageReference:");
26
27export default definePlugin({
28 name: "ValidReply",
29 description: &#039;Fixes "Message could not be loaded" upon hovering over the reply&#039;,
30 tags: ["Chat", "Utility"],
31 authors: [Devs.newwares],
32 patches: [
33 {
34 // Same find as in ReplyTimestamp
35 find: "#{intl::REPLY_QUOTE_MESSAGE_NOT_LOADED}",
36 replacement: {
37 match: /#{intl::REPLY_QUOTE_MESSAGE_NOT_LOADED}\)/,
38 replace: "$&,onMouseEnter:()=>$self.fetchReply(arguments[0])"
39 }
40 },
41 {
42 find: "ReferencedMessageStore",
43 replacement: [
44 {
45 match: /_channelCaches=new Map;/,
46 replace: "$&_=$self.setReplyStore(this);"
47 }
48 ]
49 }
50 ],
51
52 setReplyStore(store: any) {
53 ReplyStore = store;
54 },
55
56 async fetchReply(reply: Reply) {
57 const { channel_id: channelId, message_id: messageId } = reply.baseMessage.messageReference!;
58
59 if (fetching.has(messageId)) {
60 return;
61 }
62 fetching.set(messageId, channelId);
63
64 RestAPI.get({
65 url: `/channels/${channelId}/messages`,
66 query: {
67 limit: 1,
68 around: messageId
69 },
70 retries: 2
71 })
72 .then(res => {
73 const reply: Message | undefined = res?.body?.[0];
74 if (!reply) return;
75
76 if (reply.id !== messageId) {
77 ReplyStore.set(channelId, messageId, {
78 state: ReferencedMessageState.Deleted
79 });
80
81 FluxDispatcher.dispatch({
82 type: "MESSAGE_DELETE",
83 channelId: channelId,
84 message: messageId
85 });
86 } else {
87 ReplyStore.set(reply.channel_id, reply.id, {
88 state: ReferencedMessageState.Loaded,
89 message: createMessageRecord(reply)
90 });
91
92 FluxDispatcher.dispatch({
93 type: "MESSAGE_UPDATE",
94 message: reply
95 });
96 }
97 })
98 .catch(() => { })
99 .finally(() => {
100 fetching.delete(messageId);
101 });
102 }
103});
104