Skip to content

rigwild/discord-self-bot-console

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

47 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Discord self-bot console

A simple Discord Self-bot using console. Intended for quick scripts runnable directly from the devtools. Can also be used with Node.js for quick simple scripts!

Disclaimer

Automating user accounts is against Discord's Terms of Service. You might get banned if you abuse it (too much spam, unusual activity).

Usage

  1. Close Discord client (Quit Discord in system tray)
  2. Open the settings file, it's location depends on your OS:
    • Windows: %appdata%\discord\settings.json
    • macOS: ~/Library/Application Support/Discord/settings.json
    • Linux: ~/.config/discord/settings.json
  3. Add "DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING": true, (this is necessary since last update)
  4. Save the file
  5. Restart Discord client
  6. Open Chrome devtools on Discord using Ctrl + shift + i
  7. Go to the console tab and paste the entire index.js script
  8. Send a message in any channel/DM, this will automatically set your auth token into the script
  9. ...
  10. Profit!

If you want to disable the token from being automatically set, use autoUpdateToken = false at the start of your bot script. You can extract the auth token manually by doing this:

  1. Open Chrome devtools on Discord using Ctrl + shift + i
  2. Go to the console tab and paste the entire index.js script
  3. Go to the network tab and send a message in any channel/DM
  4. A new entry should appear, click it then copy the Authorization header (in the Request Headers section)
  5. Paste it in authHeader at the end of the script in the console

How to use video

You can now use any function provided by this script in the console like await api.someFunction(). Don't forget await or the server's response will not be printed to the console.

Use the api.id() function to update the variable gid guild id and cid channel id to what you are currently watching.

Note: It's a good idea to wrap your code in its own scope { code } or you might get an error when reusing the same variable names later!

Examples

Basic example

Update cid to the channel you are watching, get the last 100 messages, send a message, edit then delete.

{
  api.id()
  // or api.update_guildId_and_channelId_withCurrentlyVisible()

  let channelId = cid
  // or let channelId = api.getConfig().channelId

  // Send a message
  let sentMessage = await api.sendMessage(channelId, `Hello! πŸ‘‹ My name is ${user.username}!`)

  await api.delay(2000)

  // Edit a message
  let editedMessage = await api.editMessage(channelId, sentMessage.id, 'Hello, edited! ✌️')

  await api.delay(2000)

  // Delete a message
  await api.deleteMessage(channelId, editedMessage.id)

  await api.delay(2000)

  // Log the last 100 messages in the console
  let messages = await api.getMessages(channelId)
  console.log(messages)
}

Develop in IDE and get typings

Types are provided at types.d.ts. You can use them in your IDE to get typings and develop your script in a better environment. The typings are not fully complete, but it's better than nothing (PRs are welcome!).

The script will not work with Node.js (and not supposed to be made for it), you need to copy/paste it in the Discord console to run it.

Don't forget to paste the full index.js script in the console first to get the api variable!

git clone [email protected]:rigwild/discord-self-bot-console.git
# or
git clone https://github.com/rigwild/discord-self-bot-console.git

cd discord-self-bot-console
code .

Doing the following, you should be able to get typings. Open myScripts/example.js.

// myScripts/example.js

// @ts-check
const { api } = require('../index.js')

// Copy paste the below code inside the Discord console
;(async () => {
  const user = await api.getCurrentUser()

  console.log(user.username)
})()

Send an embed

SENDING EMBEDS AS A USER ACCOUNT IS NOT POSSIBLE ANYMORE, DISCORD UPDATED ITS API (see this reddit post)

See How to send an embed?

embed example

Run in Node.js

See Can I run it without opening Discord?

Use multiple account tokens

See Is it possible to use multiple tokens?

Use a bot account

This specific script only works for user accounts. If you want to use a bot account, you need to use the provided Node.js version (see above).

Why can't I use a bot account with the Discord client?

List all custom emojis urls from all guilds you are a member of

See How to list all custom emojis urls from all guilds you are a member of

React with emoji or custom emoji

See How to react with emoji or custom emoji ? πŸ€”

Send slash commands (/something)

See Send slash commands (/something)

Add and remove reactions to every message on a channel

See Add and remove reactions to every message on a channel

Open a thread

{
  api.id()
  let channelId = cid

  const sentMessage = await api.sendMessage(channelId, 'Hello, please open a thread here! πŸ’•')

  // A new thread opened in reply to a message
  const createdThread = await api.createThread(channelId, sentMessage.id, 'A cool thread πŸ€”')
  const sentMessage2 = await api.sendMessage(createdThread.id, 'Here it is, this is a thread! 😁')
  await api.replyToMessage(createdThread.id, sentMessage2.id, 'Thanks! ✌️')

  // A clean new thread without any message in it (not opened on any message!)
  await api.createThreadWithoutMessage(channelId, 'Another thread 😁')
}

Farm XP

Send a message to a channel (channelId) every minute then delete it (useful for XP farming in some servers).

You can use loop = false at any time to stop it.

{
  api.id()
  let channelId = cid
  let message = 'Hi, I like spamming 🦜'

  var loop = true
  let count = 0
  while (loop) {
    const sentMessage = await api.sendMessage(channelId, message)
    await api.deleteMessage(channelId, sentMessage.id)
    console.log(`Sent ${++count} messages`)
    await api.delay(61000) // 61 seconds
  }
}

To farm XP with multiple accounts, check Is it possible to farm XP using multiple tokens?

Clear messages of user

Delete the amount messages from user (userId) sent to a channel/DM (channelId) appearing before message (beforeMessageId) and wait delayMs milliseconds everytime.

I use sometimes to fully clear my DMs as Discord does not offer it as a feature.

You can use loop = false at any time to stop it.

Discord recently made its rate limiting strictier. I recommend 1100ms as a minimum to not get rate limited. Make it even bigger if you are affraid of getting banned.

{
  api.id()
  let channelId = cid
  let userId = '012345678987654321'
  let amount = 99999999
  let delayMs = 1100

  let beforeMessageId = '8999999999999999999' // Leave it like this to delete from latest

  let deletionCount = 0
  var loop = true
  while (loop) {
    const messages = await api.getMessages(channelId, 100, { before: beforeMessageId })

    // We reached the start of the conversation
    if (messages.length < 100 && messages.filter(x => x.author.id === userId && (x.type === 0 || x.type === 19)).length === 0) {
      loop = false
      console.log(`[${deletionCount}/${amount}] Reached the start of the conversations! Ending.`)
      continue
    }

    // Update last message snowflake for next iteration
    beforeMessageId = messages[0].id

    for (const aMessage of messages) {
      if (loop === false) break

      // Check if the max amount was reached
      if (deletionCount >= amount) {
        loop = false
        console.log(`[${deletionCount}/${amount}] Deleted the requested amount of messages! Ending.`)
        break
      }

      // Update last message snowflake for next iteration
      beforeMessageId = aMessage.id

      // Check if the message should be deleted
      if (aMessage.author.id === userId && (aMessage.type === 0 || aMessage.type === 19)) {
        await api.deleteMessage(channelId, aMessage.id)
        deletionCount++
        console.log(`[${deletionCount}/${amount}] Deleted a message!`)
        if (deletionCount < amount) await api.delay(delayMs)
      }
    }
    await api.delay(delayMs)
  }
}

Do anything to every messages in a text channel

Pass your custom function!

This example will apply all reactions already there on all messages, then add πŸ‘‹ if message says hi!! or hello.

{
  api.id()
  let channelId = cid
  let amount = 99999999
  let delayMs = 500

  let actionFn = async (channelId, message) => {
    //
    // Your custom code here
    //
    let wasActiontriggered = false

    // Copy all reactions already present on message
    for (const reaction of message.reactions || []) {
      let reactionToAdd = reaction.emoji.id ? `${reaction.emoji.name}:${reaction.emoji.id}` : reaction.emoji.name
      await api.addReaction(channelId, message.id, reactionToAdd)
      wasActiontriggered = true
      await api.delay(delayMs)
    }

    // If person said `hello!!!` or `hi!`, react with waving hand πŸ‘‹
    if (message.content.match(/^(?:hi|hello)!*$/)) {
      await api.addReaction(channelId, message.id, 'πŸ‘‹')
      wasActiontriggered = true
    }

    // Return a boolean indicating if you did something to the message
    // If true, will log and apply delay
    return wasActiontriggered
  }

  let beforeMessageId = '8999999999999999999' // Leave it like this to react from latest

  let count = 0
  var loop = true
  while (loop) {
    const messages = await api.getMessages(channelId, 100, { before: beforeMessageId })

    // We reached the start of the conversation
    if (messages.length < 100 && messages.filter(x => x.type === 0 || x.type === 19).length === 0) {
      loop = false
      console.log(`[${count}/${amount}] Reached the start of the conversation! Ending.`)
      continue
    }

    // Update last message snowflake for next iteration
    beforeMessageId = messages[0].id

    for (const aMessage of messages) {
      if (loop === false) break

      // Check if the max amount was reached
      if (count >= amount) {
        loop = false
        console.log(`[${count}/${amount}] Treated the requested amount of messages! Ending.`)
        break
      }

      // Update last message snowflake for next iteration
      beforeMessageId = aMessage.id

      // Check if the message should be reacted
      if (aMessage.type === 0 || aMessage.type === 19) {
        let wasActiontriggered = await actionFn(channelId, aMessage)
        // Apply delay and log only if return true
        if (wasActiontriggered) {
          count++
          console.log(`[${count}/${amount}] Treated a message! ID=${aMessage.id}`)
          if (count < amount) await api.delay(delayMs)
        }
      }
    }
    await api.delay(delayMs)
  }
}

FAQ

Will I get banned if I do x?

I don't know, maybe. I have used lots of scripts in the past, often deleted 100k+ messages of mine accross private messages and servers and never got banned, ever.

But I can't guarantee anything. Use at your own risk.

Automating user accounts is againt Discord's Terms of Service.

Listen to events, do some advanced stuff

This is intended for small scripts, not to implement a full-featured bot.

If you need to listen to events or do something more advanced you can use the discord.js package with your user token (with v11.3.2 and below though, they deprecated user token support starting v11.4.0!).

Note: As they don't support user bots anymore, it may break at any time (with Discord changing their APIs).

Can it do x? Can you help me?

Post your requests in the Discussions tab. Please search if your request was not mentionned in an earlier post before asking.

I made a nice/useful script, can I share?

Of course! Post it in the Discussions tab. Please search if a similar script was shared earlier before posting.

Why this repo?

Initially, this was posted as a gist for myself. As there's interest for such a thing, I figured out making a proper repo was better to share scripts.

API

Full list

The full list of available functions is available in types.d.ts.

api.id()
api.update_guildId_and_channelId_withCurrentlyVisible()
api.delay(ms)
api.apiCall(apiPath, body, method = 'GET')

api.getMessages(channelOrThreadId, limit?, params = {})
api.sendMessage(channelOrThreadId, message, tts?, body = {})
api.replyToMessage(channelOrThreadId, repliedMessageId, message, tts?, body = {})
api.editMessage(channelOrThreadId, messageId, newMessage, body = {})
api.deleteMessage(channelOrThreadId, messageId)

api.createThread(channelId, toOpenThreadInmessageId, name, autoArchiveDuration?, body = {})

api.getCurrentUser()
api.editCurrentUser(username?, bio?, body = {})
// and more...

api.delay(ms)

api.delay(ms: number) => Promise<void>

Wait for ms milliseconds.

await delay(1500)
await api.delay(1500)

api.downloadFileByUrl(url, filename)

api.downloadFileByUrl(url: string, filename: string) => Promise<void>

Download a file at url and name it filename.

See How to download attachments (file, image) from a message?

await api.downloadFileByUrl('https://cataas.com/cat', 'cat.png')
await api.downloadFileByUrl(messages[0].attachments[0].url, messages[0].attachments[0].filename)

api.id()

api.id() => void (old alias)

api.update_guildId_and_channelId_withCurrentlyVisible() => void

Update the variable gid guild id and cid channel id to what you are currently watching in the Discord client.

id()
api.id()

api.getConfig()

api.getConfig(): Readonly<{
  authHeader: string,
  autoUpdateToken: boolean,
  guildId: string,
  channelId: string,
  gid: string,
  cid: string,
}>

Returns the current configuration, read-only. Useful if you want to use typings in your IDE.

Set configuration

api.setConfigAutoUpdateToken(autoUpdateToken: boolean): void
api.setConfigGid(guildId: string): void
api.setConfigGuildId(guildId: string): void
api.setConfigCid(channelId: string): void
api.setConfigChannelId(channelId: string): void

Variables

  • authHeader: You Discord account auth token
  • autoUpdateToken: If true, the token will be automatically updated in the bot when a request is sent from the client (e.g sending a message)
  • gid: Current guild id (update to what you are currently watching using api.id())
  • cid: Current channel id (update to what you are currently watching using api.id())

License

The MIT License