0
Help us understand the problem. What are the problem?

posted at

updated at

Discord.jsを利用してインスタグラムのDMにメッセージを送信する

初めに

レポートの合間の息抜きに組んでみました
概要としたらDiscordでユーザーIDとパスワードを入力したら自動でログインをしてインスタにDMするようになっています
詳しい説明は暇になってから書きます

必要なもの

  • 技術
  • Discord.js(v13)
  • Node.js v16
  • dotenv(必要な人のみ)
  • instagram-private-api
    npm i instagram-private-api Discord.js@13 dotenv

コード

/* ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * ぶり wrote this file. As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.
 */
const maxtime = 5; //最高待機時間(BAN回避のため)
const { IgApiClient } = require('instagram-private-api');
const fs = require("node:fs");
if (!fs.readdirSync('./').some(name => name == "tmp.json")) {
  fs.writeFileSync('./tmp.json', "{}", 'utf8');
  console.log("tmpファイルがないため作成しました");
};
if (!fs.readdirSync('./').some(name => name == ".env")) {
  fs.writeFileSync('./.env', "token='あなたのトークン'", 'utf8');
  console.log(".envファイルがないため作成しましました");
};
if (!fs.readdirSync('./').some(name => name == ".gitignore")) {
  fs.writeFileSync('./.gitignore', "/node_modules\n.env", 'utf8');
  console.log(".gitignoreファイルがないため作成しましました");
};
const tmp = require('./tmp.json');
const ig = new IgApiClient();
const wait = require('util').promisify(setTimeout);
const { Client, Intents, MessageActionRow, Modal, TextInputComponent, MessageButton } = require('discord.js');
require('dotenv').config();
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
const button = new MessageActionRow()
  .addComponents(
    new MessageButton()
      .setCustomId('loop')
      .setLabel('Loop')
      .setStyle('PRIMARY'),
  )
  .addComponents(
    new MessageButton()
      .setCustomId('stop')
      .setLabel('Stop')
      .setStyle('PRIMARY'),
  );
let mr = new Object();
client.on("ready", async () => {
  console.log("コマンド登録開始")
  await client.application.commands.set([{
    "name": "dm",
    "description": "dmに送信します"
  }],
    '');
  console.log("スラッシュ準備完了");
});
client.on("interactionCreate", async interaction => {
  if (interaction.isCommand()) {
    if (interaction.commandName == "dm") {
      const modal = new Modal()
        .setCustomId('DMsend')
        .setTitle('DMsend');
      const user_name = new TextInputComponent()
        .setCustomId('user_name')
        .setLabel("あなたのユーザー名を入れてください")
        .setPlaceholder("ここにあなたのInstagramのユーザーIDを入力してください")
        .setRequired(true)
        .setStyle('SHORT');
      const send_user_name = new TextInputComponent()
        .setCustomId('send_user_name')
        .setLabel("送信先のユーザー名を入れてください")
        .setPlaceholder("ここにDM送信相手のIDを入れてください")
        .setRequired(true)
        .setStyle('SHORT');
      const password = new TextInputComponent()
        .setCustomId('password')
        .setLabel("パスワードを入れてください")
        .setPlaceholder("ここにあなたのInstagramのアカウントのパスワードを入力してください")
        .setRequired(true)
        .setStyle('SHORT');
      const dm = new TextInputComponent()
        .setCustomId('dm')
        .setLabel("送信メッセージを入力")
        .setRequired(true)
        .setPlaceholder("改行で送信を分けます")
        .setStyle('PARAGRAPH');
      const trus = new TextInputComponent()
        .setCustomId('user_name')
        .setLabel("ユーザーIDを変える場合は変えてください")
        .setRequired(true)
        .setPlaceholder("ユーザーIDを入力")
        .setValue(String(tmp[interaction.user.id]?.name))
        .setStyle('SHORT');
      const trpas = new TextInputComponent()
        .setCustomId('password')
        .setLabel("パスワードを変える場合は変えてください")
        .setRequired(true)
        .setPlaceholder("パスワードを入力")
        .setValue(String(tmp[interaction.user.id]?.pass))
        .setStyle('SHORT');
      const ActionRow0 = new MessageActionRow().addComponents(send_user_name);
      const ActionRow1 = new MessageActionRow().addComponents(user_name);
      const ActionRow2 = new MessageActionRow().addComponents(password);
      const ActionRow3 = new MessageActionRow().addComponents(dm);
      const ActionRow4 = new MessageActionRow().addComponents(trus);
      const ActionRow5 = new MessageActionRow().addComponents(trpas);
      (tmp[interaction.user.id]) ? modal.addComponents(ActionRow4, ActionRow5, ActionRow0, ActionRow3) : modal.addComponents(ActionRow0, ActionRow1, ActionRow2, ActionRow3);
      interaction.showModal(modal);
    };
  };
  if (interaction.isModalSubmit()) {
    const name = tmp[interaction.user.id]?.name || interaction.fields.getTextInputValue('user_name');
    const send_user = interaction.fields.getTextInputValue('send_user_name');
    const pass = tmp[interaction.user.id]?.pass || interaction.fields.getTextInputValue('password');
    const send_content = interaction.fields.getTextInputValue('dm').split("\n").filter(x => x);
    if (0 == send_content.length) return await interaction.reply({
      embeds: [{
        title: "エラー",
        description: "コンテンツが見つかりませんでした",
        color: 0xFF0000
      }]
    });
    await interaction.reply({
      embeds: [{
        title: "ログイン中",
        description: `ログインを開始しています\nユーザー名:${name}\n送る相手:${send_user}`,
        color: 0x00FF00
      }],
      components: [button]
    });
    ig.state.generateDevice(name);
    const check = await ig.account.login(name, pass).catch(() => { });
    if (String(JSON.stringify(check)) == "undefined") {
      await interaction.editReply({
        embeds: [{
          title: "ログイン失敗",
          description: "パスワードまたはユーザー名が違います",
          color: 0xFF0000
        }]
      });
      delete tmp[interaction.user.id];
      fs.writeFileSync('./tmp.json', JSON.stringify(tmp), 'utf8');
    } else {
      await interaction.editReply({
        embeds: [{
          title: "ログイン完了",
          description: "送信準備",
          color: 0x00FF00
        }],
        components: [button]
      });
      const userId = await ig.user.getIdByUsername(send_user).catch(() => { });
      if (!userId) return await interaction.editReply({
        embeds: [{
          title: "送信相手が見つかりませんでした",
          description: "DM解放失敗",
          color: 0xFF0000
        }]
      });
      tmp[interaction.user.id] = { name: name, pass: pass };
      fs.writeFileSync('./tmp.json', JSON.stringify(tmp), 'utf8');
      const thread = ig.entity.directThread([userId.toString()]);
      await interaction.editReply({
        embeds: [{
          title: "送信相手のDMを開きました",
          description: "送信準備",
          color: 0x00FF00
        }],
        components: [button]
      });
      for (let i = 0; i < send_content.length;) {
        const data = mr[interaction.user.id];
        let time = (Math.random() * maxtime - 1) + 1
        await wait(time * 1000);
        interaction.editReply({
          embeds: [{
            title: "送信中です。",
            description: `${i++}回目の\n${send_content[i - 1]}を送信しました\n待機時間:${time}秒\n残りの回数:${send_content.length - i}`,
            color: 0x00FF00,
          }],
          components: [button]
        });
        const check = await thread.broadcastText(send_content[i - 1]).catch(() => { });
        if (!check) {
          i = send_content.length + 2
          await interaction.editReply({
            embeds: [{
              title: "エラー",
              description: `送信を完了できませんでした\n終了します`,
              color: 0xFF0000
            }]
          });
        };
        if (data?.l) {
          if (i == send_content.length) i = 0
        };
        if (data?.s) {
          i = send_content.length;
        };
        if (i == send_content.length) {
          if (data?.s) {
            await interaction.editReply({
              embeds: [{
                title: "停止",
                description: `送信を中断しました`,
                color: 0x00FF00
              }],
              components: []
            });
            mr[interaction.user.id] = { s: false, l: mr[interaction.user.id]?.l || false }
          } else {
            await interaction.editReply({
              embeds: [{
                title: "すべての送信が完了しました",
                description: `送信数:${i}`,
                color: 0x00FF00
              }],
              components: []
            });
          };
        };

      };
    };
  };
  if (interaction.isButton()) {
    if (interaction.customId == "stop") {
      mr[interaction.user.id] = { s: true, l: mr[interaction.user.id]?.l || false };
      interaction.reply({
        embeds: [{
          title: "成功",
          description: "stopしました"
        }],
        ephemeral: true
      })
    };
    if (interaction.customId == "loop") {
      mr[interaction.user.id] = { s: mr[interaction.user.id]?.s || false, l: (mr[interaction.user.id]?.l) ? false : true }
      interaction.reply({
        embeds: [{
          title: "成功",
          description: `loopを${(mr[interaction.user.id]?.l) ? "有効" : "無効"}にしました`
        }],
        ephemeral: true
      })
    };
  };
});
client.login(process.env.token).catch(() => console.log("トークンを入れてください"));

実行結果

image.png

image.png

最後に

質問などはBR#9515まで

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?