为什么我的 Discord.js 机器人一直断开连接

Why does my Discord.js robot keep disconnecting

我的 discord.js 机器人在夜间一直与 Discord 断开连接。我的 discord 机器人可以工作,我将它托管在 replit 上并使用 UptimeRobot 来 ping 我的机器人。它在白天工作,但在夜间的某个时候,它会断开连接。有人有解决办法吗?

const express = require('express');
const app = express();
const port = 3000;
const Database = require("@replit/database")
const db = new Database()


app.get('/', (req, res) => res.send('Bot Online')); // Tells when the bot is online

app.listen(port, () => console.log(`App port online!`)); // Tells when the port is up

// ================= START BOT CODE ===================
const Discord = require('discord.js');
const client = new Discord.Client(); // Makes a new Discord Client

const prefix = "toast "

client.on('message', message => {
  if (!message.content.startsWith(prefix) || message.author.bot) return; //Checks if the message sent starts with the prefix

  const args = message.content.slice(prefix.length).split(/ +/); // Splits the prefix from the command
  const command = args.shift().toLowerCase(); // Makes the command lowercase

  // Command Start

  if (command == 'online') {  // Checks if user types !hello
    message.channel.send('I am online, and you can start selling toast using the command "toast help"') // Says Hi! in the same channel the command was sent
  }
  if (command == 'shop') {
    var user = message.author.id
    db.get(user).then(value => {
      if (!value) {
        db.set(user, "true")
        db.set(user + "money", "50")
        db.set(user + "toast", "0")
        db.set(user + "shop", "1")
        db.set(user + "toaster", "1")
        db.set(user + "cooldown", "0")
        message.reply('You have created a shop. Please use "toast help" to see all commands, and "toast tutorial" for a tutorial. You have started with ')
      }

      if (value) {
        const mentionuser = message.mentions.users.first();
        if (mentionuser == undefined) {

          var user = message.author.id


          db.get(user + "money").then(value => {
            var money = value
            db.get(user + "toast").then(value => {
              var toast = value
              db.get(user + "shop").then(value => {
                var shop = value
                db.get(user + "toaster").then(value => {
                  var toaster = value

                  function shopfinder() {
                    if (shop == "1") {
                      return "Shack"
                    }
                    if (shop == "2") {
                      return "Toast Truck"
                    }
                    if (shop == "3") {
                      return "Strip Mall Shop"
                    }
                    if (shop == "4") {
                      return "Mall Shop"
                    }
                    if (shop == "5") {
                      return "Small Shop"
                    }
                    if (shop == "6") {
                      return "Medium Shop"
                    }
                    if (shop == "7") {
                      return "Large Shop"
                    }
                    if (shop == "8") {
                      return "Sky Shop"
                    }
                    if (shop == "9") {
                      return "Small Alien Shop"
                    }
                    if (shop == "10") {
                      return "Medium Alien Shop"
                    }
                    if (shop == "11") {
                      return "Large Alien Shop"
                    }
                    if (shop == "12") {
                      return "Milky Way Shop"
                    }
                    if (shop == "13") {
                      return "Galaxy Shop"
                    }
                    if (shop == "14") {
                      return "Black Matter Shop"
                    }
                    if (shop == "15") {
                      return "Infinite Shop"
                    }
                    if (Number(shop) > 15) {
                      return "Off The Charts Shop"
                    }
                  }

                  const embed = new Discord.MessageEmbed()
                    .setColor('#FF7F27')
                    .setTitle('Your Toast Shop')
                    .setDescription('This shows all of your statistics for your toast shop')
                    .addFields(
                      { name: 'Money', value: '$' + money, inline: true },
                      { name: 'Toast', value: toast + ' toast', inline: true },
                      { name: 'Shop', value: shopfinder(), inline: true },
                      { name: 'Toasters', value: toaster + ' toasters', inline: true },
                    )
                    .setTimestamp()
                    .setFooter('Created by op#1000');

                  message.reply(embed);
                });
              });
            });
          });
        }
        if (mentionuser != undefined) {

          var user = mentionuser.id;
          var username = mentionuser.username;
          db.get(user + "money").then(value => {
            var money = value
            db.get(user + "toast").then(value => {
              var toast = value
              db.get(user + "shop").then(value => {
                var shop = value
                db.get(user + "toaster").then(value => {
                  var toaster = value


                  db.get(user).then(value => {
                    if (value == undefined) {
                      message.reply("This user has not signed up for Toast Shop.")
                    }
                    if (value != undefined) {
                      function shopfinder() {
                        if (shop == "1") {
                          return "Shack"
                        }
                        if (shop == "2") {
                          return "Toast Truck"
                        }
                        if (shop == "3") {
                          return "Strip Mall Shop"
                        }
                        if (shop == "4") {
                          return "Mall Shop"
                        }
                        if (shop == "5") {
                          return "Small Shop"
                        }
                        if (shop == "6") {
                          return "Medium Shop"
                        }
                        if (shop == "7") {
                          return "Large Shop"
                        }
                        if (shop == "8") {
                          return "Sky Shop"
                        }
                        if (shop == "9") {
                          return "Small Alien Shop"
                        }
                        if (shop == "10") {
                          return "Medium Alien Shop"
                        }
                        if (shop == "11") {
                          return "Large Alien Shop"
                        }
                        if (shop == "12") {
                          return "Milky Way Shop"
                        }
                        if (shop == "13") {
                          return "Galaxy Shop"
                        }
                        if (shop == "14") {
                          return "Black Matter Shop"
                        }
                        if (shop == "15") {
                          return "Infinite Shop"
                        }
                        if (Number(shop) > 15) {
                          return "Off The Charts Shop"
                        }
                      }

                      const embed = new Discord.MessageEmbed()
                        .setColor('#FF7F27')
                        .setTitle(username + "'s" + ' Toast Shop')
                        .setDescription('This shows all of ' + username + "'s" + ' statistics for their toast shop')
                        .addFields(
                          { name: 'Money', value: '$' + money, inline: true },
                          { name: 'Toast', value: toast + ' toast', inline: true },
                          { name: 'Shop', value: shopfinder(), inline: true },
                          { name: 'Toasters', value: toaster + ' toasters', inline: true },
                        )
                        .setTimestamp()
                        .setFooter('Created by op#1000');

                      message.reply(embed);
                    }
                  });
                });
              });
            });
          });
        }
      }
    });

  }

  if (command == "open") {
    var user = message.author.id
    db.get(user).then(value => {
      if (value) {


        db.get(user + "cooldown").then(value => {
          var time = Number(value)
          const d = new Date();
          var current = d.getTime();
          if (time <= Number(current)) {


            db.get(user + "toaster").then(value => {
              var maxtoastercount = value * 10
              message.reply('How much toast do you want to make? It will take 1 dollar to make toast, and you can make a maximum of ' + maxtoastercount + " toast.")

              async function startday() {
                var filter = m => m.author.id == message.author.id;
                try {
                  var collectedMessages = await message.channel.awaitMessages(filter, { time: 60000, max: 1, errors: ['time'] });
                } catch (e) { return message.reply("Your day has been canceled due to not specifing how much toast you want to produce in time."); };
                var response = collectedMessages.first().content;

                var toast = Number(response)
                if (isNaN(response) == true) {
                  message.reply("Your day has been canceled due to not having a valid number. Must be a number.")
                }
                if (isNaN(response) == false) {
                  // Continue
                  if (toast <= 0) {
                    message.reply("Your day has been canceled due to not having a valid number. Must be more than 0.")
                  }
                  if (toast > 0) {

                    if (toast > Number(maxtoastercount)) {
                      message.reply("Your day has been canceled due to exceeding your maximum toast count.")
                    }
                    if (toast <= Number(maxtoastercount)) {
                      // Checks completed, start day.

                      db.get(user + "toaster").then(value => {
                        var toasters = Number(value)

                        db.get(user + "shop").then(value => {
                          var shoplevel = value

                          function shoplevelfun() {
                            return shoplevel * 10
                          }

                          var sales = Math.floor(Math.random() * shoplevelfun()) + 1;


                          db.get(user + "money").then(value => {
                            var totalmoney = Number(value)

                            function sold() {
                              if (toast >= sales) {
                                return sales
                              }
                              if (toast < sales) {
                                return toast
                              }
                            }

                            function extratoast() {
                              if (toast > sales) {
                                return (toast - sales)
                              }
                              if (toast <= sales) {
                                return "0"
                              }
                            }
                            function customerslost() {
                              if (toast < sales) {
                                return (sales - toast)
                              }
                              if (toast >= sales) {
                                return "0"
                              }
                            }
                            function earned() {
                              if (sales > toast) {
                                return Number((toast * 2) - toast)
                              }
                              if (toast > sales) {
                                return Number((sales * 2) - toast)
                              }
                              if (toast = sales) {
                                return Number((sales * 2) - toast)
                              }
                            }

                            const embed = new Discord.MessageEmbed()
                              .setColor('#FF7F27')
                              .setTitle('End of day')
                              .setDescription('This shows you how your toast shop performed at the end of the day')
                              .addFields(
                                { name: 'Toast Made', value: toast + ' toast', inline: true },
                                { name: 'Toast Sold', value: sold() + ' toast', inline: true },
                                { name: 'Extra Toast', value: extratoast() + ' toast', inline: true },
                                { name: 'Customers Lost', value: customerslost() + ' customers', inline: true },
                                { name: 'Customer Count', value: sales, inline: true },
                                { name: 'Money Earned', value: '$' + earned(), inline: true },
                                { name: 'Bank Account', value: '$' + (Number(earned()) + totalmoney), inline: true },
                              )
                              .setTimestamp()
                              .setFooter('Created by op#1000');

                            message.reply(embed);
                            db.get(user + "money").then(value => {
                              var val = Number(value)
                              db.set(user + "money", (Number(earned()) + val))
                              const d = new Date();
                              var current = d.getTime();
                              var currentplus = (current + 60000)

                              db.set(user + "cooldown", currentplus)
                              if ((Number(earned()) + totalmoney) < 0) {
                                message.reply("It looks like you are in debt! If you would like to create a new shop, please run" + ' the command "toast reset" and follow the instructions provided.')
                              }
                            });
                          });
                        });
                      });
                    }
                  }
                }


              }
              startday();
            });

          }
          if (time > Number(current)) {
            message.reply("Your day has been canceled. Please wait " + Math.abs(Math.round((Number(current) - Number(value)) / 1000)) + " seconds to start another day.")
          }
        });

      }





      if (!value) {
        message.reply('You must open a toast shop using "toast shop"')
      }
    });
  }

  if (command == "reset") {
    var user = message.author.id

    db.get(user).then(value => {
      if (value) {
        message.reply("Are you sure you want to reset your account? This action is permanent. If so, please send your 6 digit verification code that you should have received in your dms. If you didn't receive the message, make sure to let server members in this server send you dms.")
        var code = Math.floor(Math.random() * 999999) + 100000
        message.author.send("Your Toast Shop verification code is " + code + ". Do not share this code with anyone but the robot.")

        async function findmsg() {
          var filter = m => m.author.id == message.author.id;

          try {
            var collectedMessages = await message.channel.awaitMessages(filter, { time: 60000, max: 1, errors: ['time'] });
          }
          catch (e) { return message.reply("I didn't receive your verification code in time."); };
          var response = collectedMessages.first().content;

          if (response == code) {

            db.delete(user)
            message.reply("You have successfully reset your Toast Shop progress. Make a new shop using " + '"toast shop".')

          }
          if (response != code) {
            message.reply("Your code is invalid. Please generate a new code.")
          }

        }
        findmsg()
      }
      if (!value) {
        message.reply('You must open a toast shop using "toast shop"')
      }
    });
  }

  if (command == "resetother") {
    var user = message.author.id
    if (user == "607341305994936320") {
      db.delete(args[0]).then(() => {
        message.reply("Reset successful")
      });
    }
    if (user !== "607341305994936320") {
      message.reply("You do not have permission to use this command. Please check your authority and try again.")
    }
  }

  if (command == "help") {

    const embed = new Discord.MessageEmbed()
      .setColor('#FF7F27')
      .setTitle('Help menu')
      .setDescription('Use this helpful menu to navigate this fun bot.')
      .addFields(
        { name: 'help', value: 'Activates this help menu', inline: true },
        { name: 'shop', value: 'Opens a new shop, or shows you your shop statistics. Mention someone in this command to check their shop statistics.', inline: true },
        { name: 'open', value: 'Starts a day of toast shop', inline: true },
        { name: 'upgrade', value: 'Upgrade your toaster or shop', inline: true },
        { name: 'reset', value: 'Permanently resets all of your progress', inline: true },
      )
      .setTimestamp()
      .setFooter('Created by op#1000');

    message.reply(embed);

  }

  if (command == "tutorial") {
    message.reply("Sorry, but this feature isn't available yet! Watch out in the future. For now, please use the command " + '"toast help" for help.')
  }

  if (command == "upgrade") {
    var user = message.author.id

    db.get(user).then(value => {
      if (!value) {
        message.reply('You must open a toast shop using "toast shop"')
      }
      if (value) {
        db.get(user + "money").then(value => {
          var money = value
          db.get(user + "toast").then(value => {
            var toast = value
            db.get(user + "shop").then(value => {
              var shop = value
              db.get(user + "toaster").then(value => {
                var toaster = value

                function shopnamefinder() {
                  if (shop == "1") {
                    return "Shack"
                  }
                  if (shop == "2") {
                    return "Toast Truck"
                  }
                  if (shop == "3") {
                    return "Strip Mall Shop"
                  }
                  if (shop == "4") {
                    return "Mall Shop"
                  }
                  if (shop == "5") {
                    return "Small Shop"
                  }
                  if (shop == "6") {
                    return "Medium Shop"
                  }
                  if (shop == "7") {
                    return "Large Shop"
                  }
                  if (shop == "8") {
                    return "Sky Shop"
                  }
                  if (shop == "9") {
                    return "Small Alien Shop"
                  }
                  if (shop == "10") {
                    return "Medium Alien Shop"
                  }
                  if (shop == "11") {
                    return "Large Alien Shop"
                  }
                  if (shop == "12") {
                    return "Milky Way Shop"
                  }
                  if (shop == "13") {
                    return "Galaxy Shop"
                  }
                  if (shop == "14") {
                    return "Black Matter Shop"
                  }
                  if (shop == "15") {
                    return "Infinite Shop"
                  }
                  if (Number(shop) > 15) {
                    return "Off The Charts Shop"
                  }

                }

                function toasterfinder() {
                  return ((Number(toaster) * 5) + 50)
                }
                function shopfinder() {
                  return ((Number(shop) * 5) + 50)
                }

                const embed = new Discord.MessageEmbed()
                  .setColor('#FF7F27')
                  .setTitle('Upgrade Your Toast Shop')
                  .setDescription('Upgrade your items by adding a reaction')
                  .addFields(
                    { name: 'Money', value: '$' + money, inline: true },
                    { name: 'Toast', value: toast + ' toast', inline: true },
                    { name: '\u200b', value: "\u200b", inline: false },
                    { name: 'Shop ', value: shopnamefinder(), inline: true },
                    { name: 'Toasters ', value: toaster + ' Toasters', inline: true },
                    { name: '\u200b', value: "\u200b", inline: false },
                    { name: '$' + shopfinder() + " ", value: "A shop lets you get more customers", inline: true },
                    { name: '$' + toasterfinder() + " ", value: "A toaster lets you make more toast", inline: true },
                  )
                  .setTimestamp()
                  .setFooter('Created by op#1000');
                (async () => {
                  let embedsent = await message.reply(embed);
                  await embedsent.react('');
                  await embedsent.react('');

                  const filter = (reaction, user) => {
                    return ['', ''].includes(reaction.emoji.name) && !user.bot;
                  };

                  // Create the collector
                  const collector = embedsent.createReactionCollector(filter, {
                    max: 1,
                    time: 15000
                  });

                  collector.on('end', (collected, reason) => {
                    if (reason === 'time') {
                      message.reply("You ran out of time to select an option.")
                    } else {
                      // Grab the first reaction in the array
                      let userReaction = collected.array()[0];
                      // Grab the name of the reaction (which is the emoji itself)
                      let emoji = userReaction._emoji.name;

                      // Handle accordingly
                      if (emoji === '') {

                        if (Number(money) >= Number(shopfinder())) {
                          db.set(user + "shop", (Number(shop) + 1))
                          db.set(user + "money", (Number(money) - Number(shopfinder())))
                          message.reply("You upgraded your " + shopnamefinder() + "!")
                        }
                        if (Number(money) < Number(shopfinder())) {
                          message.reply("You don't have enough money! You need $" + (Number(shopfinder()) - Number(money)) + " more.")
                        }

                      } else if (emoji === '') {

                        var toaster = value
                        if (Number(money) >= Number(toasterfinder())) {
                          db.set(user + "toaster", (Number(toaster) + 1))
                          db.set(user + "money", (Number(money) - Number(toasterfinder())))
                          message.reply("You now own " + (Number(toaster) + 1) + " toasters!")
                        }
                        if (Number(money) < Number(toasterfinder())) {
                          message.reply("You don't have enough money to buy this! You need $" + Math.abs(Number(money) - toasterfinder()) + " more.")
                        }

                      } else {
                        // This should be filtered out, but handle it just in case
                        msg.reply("Error: I didn't understand the inputted emoji");
                      }
                    }
                  })
                })();
              })
            })

          })
        });
      }
    })
  }


  // Command End
})





client.login(process.env.token); // Logs into the bot client using the token

我的代码在一天的大部分时间都可以正常工作,但在晚上,它会随机从 discord 下线,但 replit 仍然是 运行。控制台中没有出现错误,我一直在研究。我可能怀疑这可能与未使用的不和谐超时机器人有关,但我真的不知道。请问有人能帮忙吗?

The problem with repl.it is that the team can not afford to keep all the code running constantly as that would be too expensive and would take to much bandwidth. The team at repl.it created an algorithm that only imitates your repl to always work but in reality when you are inactive for some time, it stops. There are 2 possible solutions. One buy the hacker plan which has the option to have 5 repls that are always on no matter what. Even after you exit the browser. This is the more reliable way but you could also ping your repl every few minutes or so so that it will be on. This will be more laggy and may not always work but at least its free.

你的代码没有问题。错误是 repl.it here 或 UptimeRobot.

经过更多研究和 Agan 的帮助,我遇到了这段代码:

client.on('disconnect', function(erMsg, code) {
  console.log('----- Bot disconnected from Discord with code', code, 'for reason:', erMsg, '-----');
  client.connect();
});

当 Discord 因不活动而使机器人超时时,这将重新连接到 discord 的 api。