3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Repl.itでBotの機能を開発しまくったお話

Posted at

##:star:まずは皆様にご挨拶
皆様、初めまして!!:tada:
Repl.itでDiscordBotを開発している『姉だぁぁぁぁ』と申します。
私は、まだプログラミングを始めたばかりの学生で、このサイトを利用して投稿したりするのは本当に初めてですが、
良い記事の発行や、Botのプログラミング能力を高めたらと思い、このアカウントを作りました。よろしくお願いします。:bow:

では、本編に参りまっす!
#:star:JSで覚醒した沢山の機能を作ってみる
###:one:リアクションを使って、ページネーションを作成する。
ページネーションを早く、簡単に作成したい場合は下記のリンクを参照してください。
(InkoHXさん、ありがとうございます!)

リアクションを使って簡単にページネーションを作成する Discord.js 専用のパッケージ

↑このパッケージを使用することによって、Botのメッセージをリアクションのリアクションで、簡単にページネーションを作成する事ができます。

しかし、私は『できれば自分でページネーションを作成したい』と思ったので、数か月前にダウンロードしたソースコードを利用して、ようやくページネーションを作成することができました。
:star:▽▽▽そのソースコードは以下の通りです。▽▽▽

//ページネーションを作成
client.on('message',async message => {
   if (message.author.bot) { return; }
  if (message.content ===('!help')) {
  const pages = {
//埋め込みでページネーションを作る時に形式を[Java]にしました。
    1: new discord.MessageEmbed()
           .setTitle('(1/2)Title')
           .setDescription("Helpコマンドっす")
           .setAuthor(message.author.tag + 'が実行したな!!', message.author.avatarURL())
           .setColor(16719653)
           .setTimestamp(),
    2: new discord.MessageEmbed()
           .setTitle('(2/2)Title')
           .setDescription("EMBEDを作るのも https://leovoel.github.io/embed-visualizer/ を参照するといいと思う(多分)")
           .setAuthor(message.author.tag + 'が実行したな!!', message.author.avatarURL())
           .setColor(16719653)
           .setTimestamp()
         };
    const options = {
      limit: 15 * 1000,
      min: 1,
      max: 2,
      page: 1,
      pages: pages,
    };
   const awaitReactions = async (msg, m, options, filter) => {
  await m
    .awaitReactions(filter, { max: 1, time: 360000, errors: ["time"] })
    .then(async (collected) => {
//各リアクションをクリックした時の処理を作る↓↓↓
        const reaction = collected.first();
          if (reaction.emoji.name === "") {
            await removeReaction(m, msg, "");
            if (options.page != options.min) {
              options.page = options.page - 1;
              await m.edit(options.pages[options.page]);
            }
            await awaitReactions(msg, m, options, filter);
          } else if (reaction.emoji.name === "") {
            await removeReaction(m, msg, "");
            if (options.page != options.max) {
              options.page = options.page + 1;
              await m.edit(options.pages[options.page]);
            }
            await awaitReactions(msg, m, options, filter);
          } else {
            await awaitReactions(msg, m, options, filter);
          }
        })
        .catch((e) => console.log(e));
    };

    const removeReaction = async (m, msg, emoji) => {
      try {
        await m.reactions.cache
          .find((r) => r.emoji.name == emoji)
          .users.remove(msg.author.id);
      } catch (err) {
        console.log(err);
      }
    };
//メッセージを送信↓↓↓
    const m = await message.channel.send(options.pages[options.page]);
//リアクションの並び順を作る↓↓↓
    await m.react("");
    await m.react("");
//送信したメッセージにリアクション追加↓↓↓
    const filter = (reaction, user) =>
      ["",  ""].includes(reaction.emoji.name) &&
      user.id == message.author.id;
    await awaitReactions(message, m, options, filter);
  }
});
//ここまで

結構長いソースコードです…。
ですが、このソースコードを利用して任意のチャンネルにコマンドを実行すると、ちゃんと動いているんですよね…

実験画像
実験画像
この通りです♪

そんな感じですかね…
このソースコードを色んな風に使うと、様々な埋め込みをシンプルっぽくデザインすることができまっす。
リアクションが追加されない場合は、Botの権限の『リアクションの追加』をONにして下さい。


###:two:YouTube検索機能を作成する。
:star:!youtube [検索ワード]でYouTubeにある動画を検索できるソースコードは、以下の通りです。

//ようつべ検索
const yts = require('yt-search');//npmをインストール

client.on('message', async message => {
    if (message.content.startsWith("!youtube")) {
    if (message.author.bot) { return; }
  const AKB = message.content.split(" ").slice(1).join(" ")
//調べたい用語を入れなかった時のメッセージ↓↓↓
    if (!AKB) return message.channel.send({embed: {
        color: 16719653,
        description: '**調べたい用語を入れてね!**\n```使用例 : !youtube Discord```'
      }
    })
//YouTubeで検索中の時のメッセージ↓↓↓
    const msg = await message.channel.send({embed: {
        color: 16719653,
        author: {
          name: "Youtube内で検索中なんだ!!ちょっとまてよぉぉ!!",
        },
      }
    });
    yts(AKB, function(err, r) {
      const videos = r.videos
      const playlists = r.playlists || r.lists
      const channels = r.channels || r.accounts
//メッセージを編集して動画URLをうp↓↓↓
      msg.edit('✅動画が見つかったよぉぉぉ!!!', {
        embed: {
          color: 16719653,
          timestamp: new Date(),
          author: {
            name: message.author.tag + 'が実行したな!!',
            icon_url: message.author.avatarURL(),
          },
          title: videos[0].title,//動画のタイトル
          description: '**動画URL**\n> ' + videos[0].url + '\n\n**  そうかそういう動画か**'
        }
      })
    })
  }
});
//ここまで

そんな感じですね。
埋め込みで動画URLとかを貼り付けるので、おしゃれにできるはずです。
わざわざYoutube.comに飛んで検索しなくて済むから、便利と言えば便利かも知れないね…
yt-searchは必ずインストールしないと、このソースコードは使えません!


###:three:確認画面有りのKickコマンドを作る。
私が、Bot作る中で一番苦労したのは**『確認画面が有るKickコマンド』を作る事でしたね…。
良いコマンドにしたくて色んなソースコードを組み合わせたものの、Runボタンを押したら…沢山の所からエラー吐いて来たので始末することに
かなり時間が掛かりました。()**
:star:▽▽▽そのソースコードは以下の通りです。▽▽▽

//Kickコマンド
client.on('message', async message => {
  if (message.author.bot) { return; }
  if (message.content.startsWith('!kick') && message.guild) {
//コマンドを実行したユーザーの権限を確認↓↓↓
  if (!message.member.hasPermission('KICK_MEMBERS')) {
//Kickする権限が無ければメッセージを↓↓↓
      return message.channel.send({embed: {
          color: 16719653,
          description: '**Kickする権限ないよ!!**',
        }
      })
    }
    const user = message.mentions.users.first();
    if (user) {
      const member = message.guild.member(user);
//権限を持っている人がKickコマンドを実行したら確認画面を↓↓↓
      const msg = await message.channel.send({
        embed: {
          color: 16719653,
          timestamp: new Date(),
          author: {
            name: message.author.tag + 'が実行したな!!',
            icon_url: message.author.avatarURL(),
          },
          description: '**本当にこれでいいのかよ!?**\n```diff\n+ [ok],[no]のどれかを送信してクレメンス\n+ ok → mentionしたメンバーをKick。\n+ no → mentionしたメンバーをKickせず、処理を停止するぜ。```'
        }
      });
//回答による処理を作る↓↓↓
      const filter = msg => msg.author.id === message.author.id
      const collected = await message.channel.awaitMessages(filter, { max: 1, time: 300000 })
      const response = collected.first()
      if (!response) return message.channel.send('> **応答はやくしてよぉぉぉ!!!**')
      if (!['ok', 'no'].includes(response.content)) { return; }
//noを送信したら↓↓↓
      if (response.content === 'no') return msg.edit({embed: {
          color: 16719653,
          author: {
            name: 'Kickの処理を止めたよ!!',
          },
        }
      });
//okを送信したらKick!!↓↓↓
      if (response.content === 'ok') {
        if (member) {
          member
            .kick('監査ログに出されるやつ')
            .then(() => {
              msg.edit({embed: {
                  color: 16719653,
                  timestamp: new Date(),
                  author: {
                    name: message.author.tag + 'が実行したな!!',
                    icon_url: message.author.avatarURL(),
                  },
                  description: '**キィィィィック!!!**\n**' + `${user.tag}` + '**をKickしたよ!!',
                }
              })
            })
//エラーメッセージ↓↓↓
            .catch(err => {
              msg.edit({embed: {
                  color: 16719653,
                  description: 'Kickできなかったよ!!権限確認してよぉぉ!!'
                }
              });
              console.error(err);
            });
        } else {
//メンションされたユーザーがサーバーにいない時↓↓↓
          message.channel.send({embed: {
              color: 16719653,
              description: 'そいつここのサーバーにいないよぉぉ!!'
            }
          })
        };
      }
    } else {
//対象を指定していない時↓↓↓
      message.channel.send({embed: {
          color: 16719653,
          description: '**Kickしたいメンバーをメンションしてね!!**```使用例 : !#kick [@mention]```'
        }
      });
    }
  }
});
//ここまで

そんな感じですね。
これで、確認画面有りのKickコマンドが作れます。
確認画面の下の方のこれ↓↓↓

      const filter = msg => msg.author.id === message.author.id
      const collected = await message.channel.awaitMessages(filter, { max: 1, time: 300000 })
      const response = collected.first()
      if (!response) return message.channel.send('> **応答はやくしてよぉぉぉ!!!**')
      if (!['ok', 'no'].includes(response.content)) { return; }
      if (response.content === 'no') return messsage.channel.send('なんでnoだにゃーん');
      if (response.content === 'ok') { message.channel.send('んにゃ')}

結構色んなコマンドの所で使えるので、是非試してみて下さい!


###:four:ステータスを変える方法
Botのステータス(カスタムステータス含む)を変えるには、下記のリンクを参照にするといいです。
(作成者様、ありがとうございます!)

Discord.js 例文 (v12.2.0)

:star:カスタムステータスの所のソースコードは、以下の通りです。

client.on('ready', message => {
  console.log('準備完了っす!');
  client.user.setActivity('にゃーん', { type: "PLAYING" });
       /*
        typeの値:
            https://discord.js.org/#/docs/main/stable/class/ClientUser?scrollTo=setActivity
                'PLAYING': 〇〇 をプレイ中
                'STREAMING': 〇〇 を配信中
                'WATCHING': 〇〇 を視聴中
                'LISTENING': 〇〇 を再生中
        */
});

カスタムステータスの所はこの通りに簡単に変えることができますが、『じゃあ、退席中等のステータスの所は?』と言いますと…それは、status値を使って変える事ができます。

  status: "online"
       /*
                'online': オンライン
                'idle': 退席中
                'dnd': 邪魔しないで下さい
                'offline': オフライン
         ただしスマホステータスにしたい場合は別になる。
        */

これを入れればできると思います。
スマホステータスに変えたい場合は、クライアントを作るところをいじればできるはず。
:star:ソースコードは以下の通りです。

const client = new discord.Client({ ws: { properties: { $browser: "Discord iOS" } } });

これでしばらくすると、ステータスがスマホマークになります。
#:star:最後に
結構沢山の所のねたばらしみたいな感じになってしまいましたが…私は、まだDiscord.jsのことをまだ完全に理解しているという訳ではないのでできれば大目に見てくれると幸いです。
そして、こんなjsのソースコードだらけの記事を最後まで見て下さり、誠にありがとうございました。

もし、最後まで見て「あれ?」と思う事がございましたら、この記事にコメントをするか、
Discordの[姉だぁぁぁぁ#1985]にDMを下さい。

できる限りの事はお答えします!
ありがとうございました。

3
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?