背景
この記事は豊田高専 Advent Calendar 2021 6日目(3本目)の記事です。
専攻科の同級生に誘われたため、このお祭りに参加しました。
私が所属してるDiscordのコミュニティでは、見つけた面白そうな技術記事やレポジトリをとりあえず投稿するチャンネルがあります。
通称、「後で読む」チャンネルです。
各自が空いた時間に投稿されたものを読み返して為になると感じたら、チャンネルの参加者はその投稿に対してReactionを付けます。
他の参加者は後から有益な記事をReaction数という指標で探すことができるようになります。
本当に良い記事かを精査せずにとりあえず投稿できることが、このチャンネルの目的ですが、時が経つにつれて記事が玉石混合になり、辿るのも一苦労という現状がありました。
そこで、一定のReaction数があった場合にその投稿をピン止めをする Botを作成することにしました。
目次
#1. 使用した技術
Discord.js v13.3.1を用いて開発し、作成したBotのデプロイ先としてherokuを使用しました。
また、ローカルでのテストを動かすためにdotenvを使用しました。
dotenvはソースコードに埋め込みたくないため、dotenvをdevDependenciesに記述し、npm run devで起動するようにpackage.jsonに記述しました。
{
"devDependencies": {
"dotenv": "^10.0.0"
},
"scripts": {
"dev": "npm run build && node -r dotenv/config dest/index.js"
},
}
参考:
#2. Reactionイベントの取得
投稿にReactionがついたイベントを取得するには以下のコードを使用します。
Discord.jsのv13から追加されたIntentsのIntents.FLAGS.GUILD_MESSAGE_REACTIONS
が必要です。
また、Bot起動以前の投稿に対してもイベントが発生するように、partialsに'MESSAGE', 'CHANNEL', 'REACTION'
を追加しました。
import { Client, Intents } from 'discord.js';
const client = new Client({
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MESSAGE_REACTIONS
],
partials: ['MESSAGE', 'CHANNEL', 'REACTION']
});
// メッセージにリアクションがついた
client.on('messageReactionAdd', async (reaction, user) => {
console.log(`${user.username} reacted with "${reaction.emoji.name}".`);
});
// メッセージのリアクションが外れた
client.on('messageReactionRemove', async (reaction, user) => {
console.log(`${user.username} removed their "${reaction.emoji.name}" reaction.`);
});
参考:
#3. Reaction数を取得
Reactionされた数を取得
client.on('messageReactionAdd', async (reaction, user) => {
console.log(reaction.count);
});
Reaction.countでReactionされたのと同じReactionの数を取得できます。例えば、👀のReactionを押したときに、
↑で押されたReaction👀と同じReactionの数である3が取得できて
↑で1が取得できます。
特定のReaction数を取得
特定のReaction(例えば👍だけに反応)を取得したいときは.cache.get('👍')?.count
で取得できます。
reaction.message
.fetch()
.then(async (message) => {
const reactionCount = message.reactions.cache.get('👍')?.count;
.catch((e) => {
console.error('Something went wrong when fetching the message: ', e);
});
})
#4. ピン止めをする
Reactionされた投稿に対してピン止めを行いました。
Reactionされたメッセージをピン止めする
reaction.message
.fetch()
.then(async (message) => {
// メッセージをピン止め
await message.pin();
})
Reactionされたメッセージのピン止めを外す
reaction.message
.fetch()
.then(async (message) => {
// ピン止めを外す
await message.unpin();
})
#5. 終わりに
作成した機能は以下のレポジトリのBotに追加しました。
実際に運用してみて、コミュニティが活発に活動するとログがむちゃくちゃ出てしまうので、Discordではなく外部に出力するか、一定周期(週一とか)で一気に取得する方がいいかもですね。
今回みたいに自分の所属している(いた)コミュニティが盛り上がるイベントには積極的に参加していきたいと思ってます。
ぜひ誘ってください。