Discord Botの作り方、まとめ（Node）

## はじめに
　Discord Botの作り方をまとめます。
　今回は以下の二つのbotを紹介します。
　　1.誰かが発言した内容をそのまま発言するbot

　　2.ユーザの動作によって対応を変えるbot
　　　・「天気は？」と言われるとAPIによって現在の天気を取得し通知
　　　・ゲームを始めた人と始めたゲームのタイトルを通知
　　　・決まった言葉に対して決まった言葉を通知
## 対象者
　　・とりあえずDiscordのbotを動かしたい方
　　・bot作成の流れを確認したい方
## 必要な物
　　・Node.js
　　・Discord
## 事前準備
　　まずはbot作成&トークン入手、↓のリンクから
　　　https://discordapp.com/developers/applications/me

　　作成したbotを↓のリンクからサーバに追加します(client_idは人それぞれです)

```
https://discordapp.com/oauth2/authorize?client_id=Your Client ID&scope=bot&permissions=0
```

　　詳しいやり方↓
　　　https://liginc.co.jp/370260
## コード
#### ・だれかが発言した内容をそのまま発言するbot
　　まずはApp.jsを用意します。
　　ファイルを置きたい場所に移動して

```
　　touch App.js
```
　　それから、Discord Botを操るための材料を入手します。

```
　　npm install discord.js
```
　　App.jsを編集します。


```javascript:App.js

const Discord = require("discord.js");
const client = new Discord.Client();    
const token = "Your token";

client.on("ready", ()=> {
    console.log("ready...");
});

client.on("message",message => {
    if(message.author.bot){
        return;
    }else{
        let msg = message.content;
        let channel = message.channel;
        let author = message.author.username;
        message.reply(msg)
            .then(message => console.log(`Sent message: ${msg}`))
            .catch(console.error);
        return;
   }
}
);

client.login(token);
```


　　コードの簡単な説明


```javascript:App.js
//npm install でインストールしたdiscord.jsをこのファイルでDiscordという名前で使えるようにします
const Discord = require("discord.js");
//Discord bot用の材料がたくさん詰まったDiscordを呼び出し、使いたい材料（client()）を取り出します
const client = new Discord.Client();    
//このtokenに入るトークンは人それぞれです
const token = "Your token";

//client.onでイベントを監視します
//ready＝（botがdiscordに接続されたとき）、二つ目の引数の関数を実行します
client.on("ready", ()=> {
    console.log("ready...");
});

//message＝（メッセージが送られてきたとき）、二つ目の引数messageにいろいろな情報が渡されます
client.on("message",message => {
//送られてきたメッセージがbotが送ったものかどうか判断します
//もしbotから送られてきたものだったら何も実行しないようにします
    if(message.author.bot){
        return;
    }else{
//msgに送られてきたメッセージを入れています
        let msg = message.content;
//メッセージを送るチャンネルを判断します
        let channel = message.channel;
//メッセージを送ってきた人の名前を取得します
        let author = message.author.username;
//msgを送信します
        message.reply(msg)
//メッセージを送信したら送信したメッセージをターミナルにも表示します
            .then(message => console.log(`Sent message: ${msg}`))
            .catch(console.error);
        return;
   }
}
);

client.login(token);
```
　　App.jsを実行します。

```
　　node App.js
```
　　botがログイン状態になると思います。
　　メッセージを送ると送ったメッセージがそのまま返されると思います。
#### ・ユーザの動作によって対応を変えるbot
　　botをもう一つ作るためにもう一度事前準備をします。
　　また、このbotは現在の天気を取得するために「天気API」を使用します。
　　そのため「天気API」のapi keyが必要です。
　　今回はopenweathermapというサイトから入手します。
###### 「天気API」のapi keyの入手方法
　　これらの記事を見てください。

```
　　https://openweathermap.org/appid　←公式
　　https://qiita.com/nownabe/items/aeac1ce0977be963a740　
```

　　ファイルを作ります。

```
　　touch second_App.js
```
　　材料を入手します、このbotでは2種類の材料を使います。

```
 npm install discord.js
　　npm install eris
```
　　second_App.jsを編集します。

```javascript:second_App.js
const Discord = require("discord.js");
const client = new Discord.Client();
const token = "Your token";
const http = require("http");

const Eris = require("eris");
const bot = new Eris(token);

client.on("ready", () => {
    console.log("ready...");
});

client.on("message", message => {
    if (message.author.bot) {
        return;
    }

    if (message.content.match(/天気は？/)) {
        let location = "Nagano";
        let APIKEY = "Your apikey";
        let URL = "http://api.openweathermap.org/data/2.5/weather?q=" + location + "&appid=" + APIKEY;

        http.get(URL, (res) => {
            let body = "";
            res.setEncoding("utf8");

            res.on("data", (chunk) => {
                body += chunk;
            });

            res.on("end", (res) => {
                res = JSON.parse(body);
                console.log(res);
                let channel = message.channel;
                let temp = res.main.temp - 273;
                message.channel.send({
                    embed: {
                        color: 3447003,
                        author: {
                            name: 'OpenWeatherMap',
                            icon_url: 'https://png.icons8.com/dusk/64/summer.png',
                        },
                        title: '長野のお天気情報',
                        url: 'https://openweathermap.org',
                        description: 'OpenWeatherMapのAPI叩いたデータです。',
                        fields: [
                            { name: '天気', value: res.weather[0].main },
                            { name: '気温', value: temp.toFixed(2) + '°C' },
                            { name: '風力', value: res.wind.speed + 'm' },
                            { name: '雲量', value: res.clouds.all + '%' },
                        ],
                        timestamp: new Date(),
                        footer: {
                            icon_url: 'http://openweathermap.org/img/w/' + res.weather[0].icon.replace('n', 'd') + '.png',
                            text: 'OverWatchから逃げるな！私ですか？逃げました',
                        },
                    }
                })
            });
        }).on("error", (e) => {
            console.log(e.message);
        });
    }

    if (message.content.match(/デデドン/)) {
        let channel = message.channel;
        let author = message.author.username;
        let reply_text = `なんだこいつぅぅう！！！！！！！！！！！！！`;
        message.reply(reply_text)
            .then(message => console.log(`Sent message: ${reply_text}`))
            .catch(console.error);
        return;
    }

    if (message.content.match(/登録したよ/)) {
        let channel = message.channel;
        let author = message.author.username;
        let reply_text = `登録ありがとうございます。感謝します。`;
        message.reply(reply_text)
            .then(message => console.log(`Sent message: ${reply_text}`))
            .catch(console.error);
        return;
    }

});
client.login(token);


bot.on("presenceUpdate", (other, oldPresence) => {
    const textChannel = other.guild.channels.find((channel) => channel.type === 0);
    const userName = other.user.username;

    if (other.game) {
        const gameName = other.game.name;
        bot.createMessage(textChannel.id, userName + "が" + gameName + "を始めました");
    } else if (oldPresence.game) {
        const gameName = oldPresence.game.name;
        bot.createMessage(textChannel.id, userName + "が" + gameName + "を終了しました");
    }
});

bot.on("voiceChannelJoin", (member, newChannel) => {
    const textChannel = newChannel.guild.channels.find((channel) => channel.type === 0);
    const msg = member.username + "が通話を始めました";
    bot.createMessage(textChannel.id, msg);
});

bot.on("voiceChannelLeave", (member, oldChannel) => {
    const textChannel = oldChannel.guild.channels.find((channel) => channel.type === 0);
    const msg = member.username + "が通話をやめました";
    bot.createMessage(textChannel.id, msg);
});
bot.connect();
```
　　second_App.jsを実行します。

```
　　node second_App.js
```
　　botがログインすると思います。

　　　・「天気は？」のメッセージに対して現在の長野の天気を通知します。
　　　・ゲームを始めた人の名前とゲームタイトルを通知します。
　　　・ゲームをやめた人の名前とゲームタイトルを通知します。
　　　・通話を開始した人の名前を通知します。
　　　・通話を終了した人の名前を通知します。
　　　
　　他にも機能があるので探してみてください。
　　　＊ヒント
　　　　このbotはDeToNator所属のあの大人気有名ストリーマー、StylishNoobに
　　　　インスピレーションを受けています。
## 最後に
　　二つ目のbotに関して説明がありませんが、決してめんどくさかったという訳
　　ではありません。俗に言う割愛っていうやつです。
　　最後まで読んでくださった方ありがとうございます。来年はもっといい記事を
　　書けるように（死亡フラグ）頑張ります。
##　参考、出典など
- https://liginc.co.jp/370260
- https://qiita.com/misskotocoin/items/5d8c503e02093eca1f9b
- https://qiita.com/sbhr/items/43320a828e62eadbd77a　
- https://github.com/yuta0801/Discord-Weather-Bot
- https://abal.moe/Eris/
- https://discord.js.org/#/