Skip to content

Instantly share code, notes, and snippets.

@ciel
Created April 30, 2018 01:18
Show Gist options
  • Select an option

  • Save ciel/fd4a18e1b06a3911bb9a46b3ee04a1a6 to your computer and use it in GitHub Desktop.

Select an option

Save ciel/fd4a18e1b06a3911bb9a46b3ee04a1a6 to your computer and use it in GitHub Desktop.

Revisions

  1. @eslachance eslachance revised this gist Apr 3, 2018. 2 changed files with 9 additions and 12 deletions.
    18 changes: 9 additions & 9 deletions app.js
    Original file line number Diff line number Diff line change
    @@ -16,19 +16,19 @@ client.on("ready", () => {
    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.user.setActivity(`Serving ${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.user.setGame(`on ${client.guilds.size} servers`);
    client.user.setActivity(`Serving ${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`);
    client.user.setActivity(`Serving ${client.guilds.size} servers`);
    });


    @@ -78,16 +78,17 @@ client.on("message", async message => {

    // 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();
    // We can also support getting the member by ID, which would be args[0]
    let member = message.mentions.members.first() || message.guild.members.get(args[0]);
    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!
    // slice(1) removes the first part, which here should be the user mention or ID
    // join(' ') takes all the various parts to make it a single string.
    let reason = args.slice(1).join(' ');
    if(!reason)
    return message.reply("Please indicate a reason for the kick!");
    if(!reason) reason = "No reason provided";

    // Now, time for a swift kick in the nuts!
    await member.kick(reason)
    @@ -109,8 +110,7 @@ client.on("message", async message => {
    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!");
    if(!reason) reason = "No reason provided";

    await member.ban(reason)
    .catch(error => message.reply(`Sorry ${message.author} I couldn't ban because of : ${error}`));
    3 changes: 0 additions & 3 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -8,9 +8,6 @@ information to properly understand each part and how it works.
    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!]

    ## Setup

    - Create a new folder somewhere, give it a bot name, aka `MyBot` or `SuperBot`
  2. @eslachance eslachance revised this gist Mar 23, 2018. 1 changed file with 6 additions and 2 deletions.
    8 changes: 6 additions & 2 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -11,8 +11,6 @@ it is faster than startsWith *by an order of magnitude*. I have the performance
    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`
    @@ -36,6 +34,12 @@ node app.js

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

    ## Support
    All support for bot code is offered in the Idiot's Guide Official Server.

    [![](http://proof.evie-banned.me/lasBU8E)](http://discord.gg/9ESEZAx)

    **COMMENTS BELOW ARE NOT MONITORED AND YOU WILL NOT RECEIVE SUPPORT HERE**

    ## Credits

  3. @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.

  4. @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}`));
    }
  5. @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.

  6. @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.
  7. @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`);
    });


  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
    @@ -132,5 +132,5 @@ client.on("message", async message => {
    }
    });

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

  9. @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);

  10. @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") {
  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
    @@ -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`) );
    }

  12. @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") {
  13. @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);
  14. @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.