generated at
Raw Eventsを使って未キャッシュのデータも処理する
Discord.js v11以前では、キャッシュされていないデータをイベントで受け取る専用の方法(partial)がなかった
なので代わりにDiscord APIから流れてくる生データを元に処理していた
文字通り生のデータだから決して扱いやすいわけではなく比較的複雑なDiscord APIのドキュメントを見る必要もあるので、可能ならv12で追加されたpartialを使うか、事前にfetchしておくなどの別の方法で代替したほうが良いかも知れない

詳細はRaw Events - An Idiot's Guideを参照(以下は全てのリアクションに反応するコードの抜粋)
js
client.on('raw', packet => { // We don't want this to run on unrelated packets if (!['MESSAGE_REACTION_ADD', 'MESSAGE_REACTION_REMOVE'].includes(packet.t)) return; // Grab the channel to check the message from const channel = client.channels.get(packet.d.channel_id); // There's no need to emit if the message is cached, because the event will fire anyway for that if (channel.messages.has(packet.d.message_id)) return; // Since we have confirmed the message is not cached, let's fetch it channel.fetchMessage(packet.d.message_id).then(message => { // Emojis can have identifiers of name:id format, so we have to account for that case as well const emoji = packet.d.emoji.id ? `${packet.d.emoji.name}:${packet.d.emoji.id}` : packet.d.emoji.name; // This gives us the reaction we need to emit the event properly, in top of the message object const reaction = message.reactions.get(emoji); // Adds the currently reacting user to the reaction's users collection. if (reaction) reaction.users.set(packet.d.user_id, client.users.get(packet.d.user_id)); // Check which type of event it is before emitting if (packet.t === 'MESSAGE_REACTION_ADD') { client.emit('messageReactionAdd', reaction, client.users.get(packet.d.user_id)); } if (packet.t === 'MESSAGE_REACTION_REMOVE') { client.emit('messageReactionRemove', reaction, client.users.get(packet.d.user_id)); } }); });