Skip to content

Instantly share code, notes, and snippets.

@rpdiss
Created October 24, 2017 22:17
Show Gist options
  • Select an option

  • Save rpdiss/42b5428d7de7b29dbb89f47bb799f731 to your computer and use it in GitHub Desktop.

Select an option

Save rpdiss/42b5428d7de7b29dbb89f47bb799f731 to your computer and use it in GitHub Desktop.

Revisions

  1. @eslachance eslachance revised this gist Jul 27, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -47,8 +47,8 @@ client.on("message", async message => {
    // e.g. if we have the message "+say Is this the real life?" , we'll get the following:
    // command = say
    // args = ["Is", "this", "the", "real", "life?"]
    const args = message.content.split(/\s+/g);
    const command = args.shift().slice(config.prefix.length).toLowerCase();
    const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
    const command = args.shift().toLowerCase();

    // Let's go with a few common example commands! Feel free to delete or change those.

  2. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -99,13 +99,13 @@ client.on("message", async message => {
    if(command === "ban") {
    // Most of this command is identical to kick, except that here we'll only let admins do it.
    // In the real world mods could ban too, but this is just an example, right? ;)
    if(!message.member.roles.some(r=>["Administrator", "Moderator"].includes(r.name)) )
    if(!message.member.roles.some(r=>["Administrator"].includes(r.name)) )
    return message.reply("Sorry, you don't have permissions to use this!");

    let member = message.mentions.members.first();
    if(!member)
    return message.reply("Please mention a valid member of this server");
    if(!member.kickable)
    if(!member.bannable)
    return message.reply("I cannot ban this user! Do they have a higher role? Do I have ban permissions?");

    let reason = args.slice(1).join(' ');
    @@ -128,7 +128,7 @@ client.on("message", async message => {
    return message.reply("Please provide a number between 2 and 100 for the number of messages to delete");

    // So we get our messages, and delete them. Simple enough, right?
    const fetched = await message.channel.fetchMessages({count: 100});
    const fetched = await message.channel.fetchMessages({count: deleteCount});
    message.channel.bulkDelete(fetched)
    .catch(error => message.reply(`Couldn't delete messages because of: ${error}`));
    }
  3. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion app.js
    Original file line number Diff line number Diff line change
    @@ -48,7 +48,7 @@ client.on("message", async message => {
    // command = say
    // args = ["Is", "this", "the", "real", "life?"]
    const args = message.content.split(/\s+/g);
    const command = args.shift().slice(config.prefix.length);
    const command = args.shift().slice(config.prefix.length).toLowerCase();

    // Let's go with a few common example commands! Feel free to delete or change those.

  4. @eslachance eslachance revised this gist Jun 18, 2017. 2 changed files with 3 additions and 2 deletions.
    2 changes: 1 addition & 1 deletion app.js
    Original file line number Diff line number Diff line change
    @@ -41,7 +41,7 @@ client.on("message", async message => {

    // Also good practice to ignore any message that does not start with our prefix,
    // which is set in the configuration file.
    if(!message.content.indexOf(config.prefix) === 0) return;
    if(message.content.indexOf(config.prefix) !== 0) return;

    // Here we separate our "command" name, and our "arguments" for the command.
    // e.g. if we have the message "+say Is this the real life?" , we'll get the following:
    3 changes: 2 additions & 1 deletion readme.md
    Original file line number Diff line number Diff line change
    @@ -42,4 +42,5 @@ If you've done things right, that should start the bot.
    Project created and maintained with the help of:

    - **eslachance#4611** , aka `〈evie.codes〉`, for the heavy lifting
    - **York#2400** , for pointing out mistakes, moral support and jester entertainment.
    - **York#2400** , for pointing out mistakes, moral support and jester entertainment.
    - **TrueBoxGuy#3692** for letting me know of a dumb thing I forgot, and an unfinished comment.
  5. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -22,11 +22,13 @@ client.on("ready", () => {
    client.on("guildCreate", guild => {
    // This event triggers when the bot joins a guild.
    console.log(`New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`);
    client.user.setGame(`on ${client.guilds.size} servers`);
    });

    client.on("guildDelete", guild => {
    // this event triggers when the bot is removed from a guild.
    console.log(`I have been removed from: ${guild.name} (id: ${guild.id})`);
    client.user.setGame(`on ${client.guilds.size} servers`);
    });


  6. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion app.js
    Original file line number Diff line number Diff line change
    @@ -132,5 +132,5 @@ client.on("message", async message => {
    }
    });

    client.log(config.token);
    client.login(config.token);

  7. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 8 additions and 5 deletions.
    13 changes: 8 additions & 5 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -53,7 +53,7 @@ client.on("message", async message => {
    if(command === "ping") {
    // Calculates ping between sending a message and editing it, giving a nice round-trip latency.
    // The second ping is an average latency between the bot and the websocket server (one-way, not round-trip)
    const m = await message.channel.send("Ping?")
    const m = await message.channel.send("Ping?");
    m.edit(`Pong! Latency is ${m.createdTimestamp - message.createdTimestamp}ms. API Latency is ${Math.round(client.ping)}ms`);
    }

    @@ -119,15 +119,18 @@ client.on("message", async message => {
    // This command removes all messages from all users in the channel, up to 100.

    // get the delete count, as an actual number.
    const deleteCount = parseInt(args[0]);
    const deleteCount = parseInt(args[0], 10);

    // Ooooh nice, combined conditions. <3
    if(!deleteCount || deleteCount < 2 || deleteCount > 100)
    return message.reply("Please provide a number between 2 and 100 for the number of messages to delete");

    // So we get our messages, and delete them. Simple enough, right?
    const fetched = await message.channel.fetchMessages({count: 100})
    message.channel.bulkDelete(messages)
    const fetched = await message.channel.fetchMessages({count: 100});
    message.channel.bulkDelete(fetched)
    .catch(error => message.reply(`Couldn't delete messages because of: ${error}`));
    }
    });
    });

    client.log(config.token);

  8. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion app.js
    Original file line number Diff line number Diff line change
    @@ -54,7 +54,7 @@ client.on("message", async message => {
    // Calculates ping between sending a message and editing it, giving a nice round-trip latency.
    // The second ping is an average latency between the bot and the websocket server (one-way, not round-trip)
    const m = await message.channel.send("Ping?")
    m.edit(`Pong! Latency is ${m.createdTimestamp - message.createdTimestamp}ms. API Latency is ${Math.round(client.ping)}ms`) );
    m.edit(`Pong! Latency is ${m.createdTimestamp - message.createdTimestamp}ms. API Latency is ${Math.round(client.ping)}ms`);
    }

    if(command === "say") {
  9. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion app.js
    Original file line number Diff line number Diff line change
    @@ -53,7 +53,7 @@ client.on("message", async message => {
    if(command === "ping") {
    // Calculates ping between sending a message and editing it, giving a nice round-trip latency.
    // The second ping is an average latency between the bot and the websocket server (one-way, not round-trip)
    const mmm = await message.channel.send("Ping?")
    const m = await message.channel.send("Ping?")
    m.edit(`Pong! Latency is ${m.createdTimestamp - message.createdTimestamp}ms. API Latency is ${Math.round(client.ping)}ms`) );
    }

  10. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion app.js
    Original file line number Diff line number Diff line change
    @@ -53,7 +53,8 @@ client.on("message", async message => {
    if(command === "ping") {
    // Calculates ping between sending a message and editing it, giving a nice round-trip latency.
    // The second ping is an average latency between the bot and the websocket server (one-way, not round-trip)
    message.channel.send("Ping?").then(m => m.edit(`Pong! Latency is ${m.createdTimestamp - message.createdTimestamp}ms. API Latency is ${Math.round(client.ping)}ms`) );
    const mmm = await message.channel.send("Ping?")
    m.edit(`Pong! Latency is ${m.createdTimestamp - message.createdTimestamp}ms. API Latency is ${Math.round(client.ping)}ms`) );
    }

    if(command === "say") {
  11. @eslachance eslachance revised this gist Jun 18, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion app.js
    Original file line number Diff line number Diff line change
    @@ -60,7 +60,7 @@ client.on("message", async message => {
    // makes the bot say something and delete the message. As an example, it's open to anyone to use.
    // To get the "message" itself we join the `args` back into a string with spaces:
    const sayMessage = args.join(" ");
    // Then we delete the command message (sneaky, right?). The catch just ignores the
    // Then we delete the command message (sneaky, right?). The catch just ignores the error with a cute smiley thing.
    message.delete().catch(O_o=>{});
    // And we get the bot to say the thing:
    message.channel.send(sayMessage);
  12. @eslachance eslachance created this gist Jun 18, 2017.
    132 changes: 132 additions & 0 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,132 @@
    // Load up the discord.js library
    const Discord = require("discord.js");

    // This is your client. Some people call it `bot`, some people call it `self`,
    // some might call it `cootchie`. Either way, when you see `client.something`, or `bot.something`,
    // this is what we're refering to. Your client.
    const client = new Discord.Client();

    // Here we load the config.json file that contains our token and our prefix values.
    const config = require("./config.json");
    // config.token contains the bot's token
    // config.prefix contains the message prefix.

    client.on("ready", () => {
    // This event will run if the bot starts, and logs in, successfully.
    console.log(`Bot has started, with ${client.users.size} users, in ${client.channels.size} channels of ${client.guilds.size} guilds.`);
    // Example of changing the bot's playing game to something useful. `client.user` is what the
    // docs refer to as the "ClientUser".
    client.user.setGame(`on ${client.guilds.size} servers`);
    });

    client.on("guildCreate", guild => {
    // This event triggers when the bot joins a guild.
    console.log(`New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`);
    });

    client.on("guildDelete", guild => {
    // this event triggers when the bot is removed from a guild.
    console.log(`I have been removed from: ${guild.name} (id: ${guild.id})`);
    });


    client.on("message", async message => {
    // This event will run on every single message received, from any channel or DM.

    // It's good practice to ignore other bots. This also makes your bot ignore itself
    // and not get into a spam loop (we call that "botception").
    if(message.author.bot) return;

    // Also good practice to ignore any message that does not start with our prefix,
    // which is set in the configuration file.
    if(!message.content.indexOf(config.prefix) === 0) return;

    // Here we separate our "command" name, and our "arguments" for the command.
    // e.g. if we have the message "+say Is this the real life?" , we'll get the following:
    // command = say
    // args = ["Is", "this", "the", "real", "life?"]
    const args = message.content.split(/\s+/g);
    const command = args.shift().slice(config.prefix.length);

    // Let's go with a few common example commands! Feel free to delete or change those.

    if(command === "ping") {
    // Calculates ping between sending a message and editing it, giving a nice round-trip latency.
    // The second ping is an average latency between the bot and the websocket server (one-way, not round-trip)
    message.channel.send("Ping?").then(m => m.edit(`Pong! Latency is ${m.createdTimestamp - message.createdTimestamp}ms. API Latency is ${Math.round(client.ping)}ms`) );
    }

    if(command === "say") {
    // makes the bot say something and delete the message. As an example, it's open to anyone to use.
    // To get the "message" itself we join the `args` back into a string with spaces:
    const sayMessage = args.join(" ");
    // Then we delete the command message (sneaky, right?). The catch just ignores the
    message.delete().catch(O_o=>{});
    // And we get the bot to say the thing:
    message.channel.send(sayMessage);
    }

    if(command === "kick") {
    // This command must be limited to mods and admins. In this example we just hardcode the role names.
    // Please read on Array.some() to understand this bit:
    // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/some?
    if(!message.member.roles.some(r=>["Administrator", "Moderator"].includes(r.name)) )
    return message.reply("Sorry, you don't have permissions to use this!");

    // Let's first check if we have a member and if we can kick them!
    // message.mentions.members is a collection of people that have been mentioned, as GuildMembers.
    let member = message.mentions.members.first();
    if(!member)
    return message.reply("Please mention a valid member of this server");
    if(!member.kickable)
    return message.reply("I cannot kick this user! Do they have a higher role? Do I have kick permissions?");

    // slice(1) removes the first part, which here should be the user mention!
    let reason = args.slice(1).join(' ');
    if(!reason)
    return message.reply("Please indicate a reason for the kick!");

    // Now, time for a swift kick in the nuts!
    await member.kick(reason)
    .catch(error => message.reply(`Sorry ${message.author} I couldn't kick because of : ${error}`));
    message.reply(`${member.user.tag} has been kicked by ${message.author.tag} because: ${reason}`);

    }

    if(command === "ban") {
    // Most of this command is identical to kick, except that here we'll only let admins do it.
    // In the real world mods could ban too, but this is just an example, right? ;)
    if(!message.member.roles.some(r=>["Administrator", "Moderator"].includes(r.name)) )
    return message.reply("Sorry, you don't have permissions to use this!");

    let member = message.mentions.members.first();
    if(!member)
    return message.reply("Please mention a valid member of this server");
    if(!member.kickable)
    return message.reply("I cannot ban this user! Do they have a higher role? Do I have ban permissions?");

    let reason = args.slice(1).join(' ');
    if(!reason)
    return message.reply("Please indicate a reason for the ban!");

    await member.ban(reason)
    .catch(error => message.reply(`Sorry ${message.author} I couldn't ban because of : ${error}`));
    message.reply(`${member.user.tag} has been banned by ${message.author.tag} because: ${reason}`);
    }

    if(command === "purge") {
    // This command removes all messages from all users in the channel, up to 100.

    // get the delete count, as an actual number.
    const deleteCount = parseInt(args[0]);

    // Ooooh nice, combined conditions. <3
    if(!deleteCount || deleteCount < 2 || deleteCount > 100)
    return message.reply("Please provide a number between 2 and 100 for the number of messages to delete");

    // So we get our messages, and delete them. Simple enough, right?
    const fetched = await message.channel.fetchMessages({count: 100})
    message.channel.bulkDelete(messages)
    .catch(error => message.reply(`Couldn't delete messages because of: ${error}`));
    }
    });
    45 changes: 45 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,45 @@
    # The Perfect Lil' Bot

    This bot example is the combined work of members of the Discord.js and Idiot Guide's community.
    It attempts to provide a "complete" starter example of a simple, one-file bot, with comments and
    information to properly understand each part and how it works.

    > I believe I should note that I'm a #speedwhore and the lines used in this example are *the fastest*
    in terms of performance, especially using Node 8. Though maybe "indexOf" might look ugly for example,
    it is faster than startsWith *by an order of magnitude*. I have the performance tests to prove it.

    There is also an upcoming example of a more complete bot with separate command files (command handler)
    as well as per-server configurations. You can find it at: [to be done!]

    If what you need is a selfbot, this won't do. I suggest taking a look at [evie.selfbot](http://github.com/eslachance/evie.selfbot)

    ## Setup

    - Create a new folder somewhere, give it a bot name, aka `MyBot` or `SuperBot`
    - Create a file called `app.js`, and paste in the contents of app.js below.
    - Create a file called `config.json` and give it the following content, using your real bot token:
    ```json
    { "token" : "MTg-this-IzNzU3OTA5NjA-is.not-DCeFB-a.real-r4DQlO-t0ken-qerT0",
    "prefix" : "+"
    }
    ```

    You then need to run a couple of things to make this work. Those things are run in console, which
    can be opened by using `SHIFT+Right-Click` in your folder, and selected `Open command prompt here`
    (your version of windows might say "PowerShell", don't worry it'll work fine!). In console, use
    the following commands:

    ```
    npm install discord.js
    node app.js
    ```

    If you've done things right, that should start the bot.


    ## Credits

    Project created and maintained with the help of:

    - **eslachance#4611** , aka `〈evie.codes〉`, for the heavy lifting
    - **York#2400** , for pointing out mistakes, moral support and jester entertainment.