DiscordBot 機能制作の流れ

# 「プログラミングしてみよう!!」

## 1\.はじめに
こんにちは。 アドカレと言う文化をついこないだ知った人です。
N中等部生です。

今回は私がいつもDiscordのBotを作る時の機能面で気をつけていることなどを、できるだけわかりやすく初心者の解説をつけながら話したいと思います。
#### ※この記事はJavaScriptを使用していますが、JavaScriptがわからなくても読めるような解説を目指しています
<details><summary>プログラミングをあまり知らない人向け</summary>

以下はほぼ全てのプログラミング言語に共通することです。
### 1\.ドット
ドット(.)は「その中の」みたいな意味で
```js:dot.js
root.image()
```
は``rootの中のimage()``
という感じ。
これを覚えとくだけでプログラム大体読めるって言っても過言なぐらいです。
### 2\.コメントアウト
``//``はコメントアウトと言い、プログラムの処理から除外されます
コード内に書けるメモです
```js:commentout.js
console.log("Hello World"); //プログラムの後ろでもコメントアウトできる

/*
これでも
大丈夫
*/
```
```py:commentout.py
#言語によってはシャープ(#)だったりします。
```
### 3\.果てしない括弧たち
小括弧()、中括弧{}、大括弧[]
大体全部名前の通りです。
配列(Array)と言うものを読み解く時に頭の片隅に置いてるとちょっと読みやすくなります。
### 4\.プラスとかイコールとか
プラス(+)とかイコール(=)は大体そのまんまです。
### 5\.イコールが二つあるやつとか
イコールが二つあるやつは等価演算子(==)といいます。
厳密投下演算子(===)とかもあります。
論理和(||)というOR演算とかもあります。
論理積(&&)というAND演算とかもあります。

わけわかんないんで雰囲気で覚えてます。
</details>

<br>
<br>

- ### 今回作りたい機能(目標)
1\.Botに一つの機能を実装させる
- ### 環境
| 名前 | ver |
| ---- | ---- |
| MacOS | Sonoma 14.0 |
| Node.js | 18.16.0 |
| Discord.js | 14.11.0 |


## 2\.大まかに作りたいものを決める
イラストなどで言うラフ、音楽でいうコード そんな感じです
これがなけりゃ何も始まりませんね。
ここは他人からもらった方がたくさんいただけるので私の場合は人に聞いてみることが多いです
今回は「メッセージの編集の履歴を残す機能」を追加したいと思います

## 3\.軽く実装してみる
とりあえずは実装してみます
```js:test.js
// ~~略~~
//説明書きをしているので無駄なところが多いです

//メッセージが編集された時に実行されるmessageUpdateというものを使う
//oldMessageには編集前 newMessageには編集後のメッセージのデータが入っている
client.on('messageUpdate', (oldMessage, newMessage) => {
    //編集前のメッセージの中身を取得
    var oldContent = oldMessage.cleanContent
    //編集後のメッセージの中身を取得
    var newContent = newMessage.cleanContent
    //コンソールに出力
    console.log(oldContent + "==>" + newContent);
});

// ~~略~~
```
ひとつひとつ順を追って説明すると
```js
client.on('messageUpdate', (oldMessage, newMessage) => {
});
```
これはイベントです。
"messageUpdate"という条件が実行された場合この中に書いてあるコードが実行されます。
この場合はメッセージが編集された時に実行されます。
```js
var oldContent = oldMessage.cleanContent
var newContent = newMessage.cleanContent
```
これは変数に内容を入れています
メッセージが編集された時に古いメッセージと新しいメッセージのデータが取得できるので、そこからクリーンコンテンツ(メンションなどを文字のまま取得したもの)を代入しています
```js
console.log(oldContent + "==>" + newContent);
```
これは言うまでもなくコンソール(実行しているデバッグ画面)にメッセージを流すものです
ここに変数を入れることで先ほど代入したデータを取り出すことができます。
ダブルクォーテーション(")やシングルクォーテーション(')で囲むことでテキストをそのまま入れることが可能です。

#### 日本語で書くと
```
メッセージ編集されたよ! oldMessageとnewMessageにメッセージの詳細入れとくね。

oldContentにoldMessageの内容のテキスト入れとくね

newContentにnewMessageの内容のテキスト入れとくね

コンソールの画面にoldContentと「==>」ってテキストとnewContentを出力しとくね
```
こんな感じです。
<br>

<details><summary>ちなみに...</summary>
めちゃくちゃまとめることが可能なので縮めることができます

```js:test.js
// ~~略~~

client.on('messageUpdate', (oldMessage, newMessage) => {
    console.log(`${oldMessage.cleanContent} ==> ${newMessage.cleanContent}`);
});

// ~~略~~
```
気になる人は調べてみてください

</details>

## 4\.ここまで実装して思ったこと
実装して動かしてみて思ったことや、他人に使ってもらって思ったことなどを書き出してみます
こう言う時こそ、コメントアウトを使うことをおすすめします

- もっと他の人が見れる方がいいな
- 誰のメッセージかわかる方がいいな
- リンクとかもあれば嬉しいな

今回はこれらに絞って対処します


## 5\.他の人が見れるように
コンソールに出力するのではなく、Discordのチャンネルに出力するようにしましょう。

Discordのチャンネルにメッセージを送る方法は
```js
client.guilds.cache.get("ギルドのID").channels.cache.get("チャンネルのID").send("メッセージ");
```
です。
なお、idを指定しない場合はメッセージが送られた場所のギルドやチャンネルが指定されます。

<br>
とりあえず、実装するところからですね。

```js:test-2.js
// ~~略~~
//説明書きをしているので無駄なところが多いです

client.on('messageUpdate', (oldMessage, newMessage) => {
    var oldContent = oldMessage.cleanContent
    var newContent = newMessage.cleanContent

    //console.log(oldContent + "==>" + newContent);
    //これを置き換える
    //ギルドとチャンネルのIDは履歴を送信したいギルドとチャンネルを指定してください
    client.guilds.cache.get("ギルドのID").channels.cache.get("チャンネルのID").send(oldContent + "==>" + newContent);
});

// ~~略~~
```
これでチャンネルの権限をいじることで、表示する人を調整することができるので解決ですね。

## 6\.誰のメッセージなのか
これは比較的簡単で、メッセージの情報にはAuthorという送信した人の情報が入っている変数があるので、それを使用します。
出力部分のメッセージを変えるだけです
```js:test-3.js
// ~~略~~

message.send(newMessage.author.name + ":" + oldContent + "==>" + newContent);

// ~~略~~
```
これで解決ですね。
<details><summary>余談</summary>
メッセージの情報には

- ギルドの情報(.guild)
- チャンネルの情報(.channel)
- 送信者の名前(.author)
- 添付ファイル(.attachments)
- テキスト(.content)

などなど色々含まれます
興味があるなら調べてみては。
</details>

## 7\.リンクもついでに
URLの取得は先ほどとの.authorなどのようなものがないので、メッセージのURLを分解して考えます

```https://discord.com/channels/aaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbb/ccccccccccccccccccc```
このようなURLが基礎になっていて、
aaaaaaaaaaaaaaaaaaaはギルドID
bbbbbbbbbbbbbbbbbbbはチャンネルID
cccccccccccccccccccはメッセージID
です。
手順はどうであれ、このような構成になっています。

なので今まで見ていたらおそらく簡単ですね。
```js:test-4.js
// ~~略~~

message.send("https://discord.com/channels/"+newMessage.guild.id+"/"+newMessage.channel.id+"/"+newMessage.message.id);

// ~~略~~
```

これでできます。

## 8\.全部まとめると
```js:example.js
// ~~略~~
//説明書きをしているので無駄なところが多いです

//メッセージが編集された時に実行されるmessageUpdateというものを使う
//oldMessageには編集前 newMessageには編集後のメッセージのデータが入っている
client.on('messageUpdate', (oldMessage, newMessage) => {
    //編集前のメッセージの中身を取得
    var oldContent = oldMessage.cleanContent
    //編集後のメッセージの中身を取得
    var newContent = newMessage.cleanContent
    //ギルドとチャンネルのIDは履歴を送信したいギルドとチャンネルを指定してください
    client.guilds.cache.get("ギルドのID").channels.cache.get("チャンネルのID").send(newMessage.author.name + ":" + oldContent + "==>" + newContent + "\n" + "https://discord.com/channels/"+newMessage.guild.id+"/"+newMessage.channel.id+"/"+newMessage.message.id)
});

// ~~略~~
```
結局は出力のところをどれだけ見やすくするかだと思います。
処理が単純でも、視認性を追求するのは終わりがないです。

## 9\.余談
私が極力今回のコードを短くすれば以下のようになります
```js:example-2.js
// ~~略~~
client.on('messageUpdate', (oldMessage, newMessage) => {
    client.guilds.cache.get("ギルドのID").channels.cache.get("チャンネルのID").send(`${newMessage.author.name}:${oldMessage.cleanContent}==>${newMessage.cleanContent}\n https://discord.com/channels/${newMessage.guildId}/${newMessage.channelId}/${newMessage.message.id}`)
});
// ~~略~~
```
## 10\.おわりに
初心者、いつまで名乗れるかわかりませんが完全に独学&我流、なので本当によわよわです

Discord.jsにかなりハマってるので、アドバイスくれる人がいればぜひ教えてください...!!

アドカレ初めてでしたがこんなのでいいんですかね...とにかく書いてる私は楽しかったです!