OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / hyper-social / bridge-discord / lib / discord-client.js

99 lines · javascript ref:
import { Client, GatewayIntentBits, Events } from 'discord.js'

class DiscordClient {
  constructor (opts) {
    this.token = opts.token
    this.channelId = opts.channelId
    this.guildId = opts.guildId || null

    this._client = null
    this._channel = null
    this._connected = false
    this._onMessage = opts.onMessage || null
    this._onReaction = opts.onReaction || null
    this._onError = opts.onError || null
  }

  connect () {
    return new Promise((resolve, reject) => {
      this._client = new Client({
        intents: [
          GatewayIntentBits.Guilds,
          GatewayIntentBits.GuildMessages,
          GatewayIntentBits.MessageContent,
          GatewayIntentBits.GuildMessageReactions
        ]
      })

      this._client.once(Events.ClientReady, async () => {
        this._connected = true

        // Find channel
        this._channel = this._client.channels.cache.get(this.channelId)
        if (!this._channel) {
          try {
            this._channel = await this._client.channels.fetch(this.channelId)
          } catch (err) {
            return reject(new Error(`Channel ${this.channelId} not found: ${err.message}`))
          }
        }

        resolve()
      })

      this._client.on(Events.MessageCreate, (message) => {
        if (message.channelId !== this.channelId) return
        if (message.author.id === this._client.user.id) return // skip self
        if (this._onMessage) this._onMessage(message)
      })

      this._client.on(Events.MessageReactionAdd, (reaction, user) => {
        if (reaction.message.channelId !== this.channelId) return
        if (user.id === this._client.user.id) return
        if (this._onReaction) this._onReaction(reaction, user)
      })

      this._client.on(Events.Error, (err) => {
        if (this._onError) this._onError(err)
      })

      this._client.login(this.token).catch(reject)
    })
  }

  async send (text) {
    if (!this._connected || !this._channel) return
    await this._channel.send(text)
  }

  async sendEmbed (opts) {
    if (!this._connected || !this._channel) return
    await this._channel.send({ embeds: [opts] })
  }

  async sendFile (url, text) {
    if (!this._connected || !this._channel) return
    await this._channel.send({
      content: text || '',
      files: [url]
    })
  }

  disconnect () {
    if (this._client) {
      this._client.destroy()
      this._connected = false
    }
  }

  get connected () {
    return this._connected
  }

  get botUser () {
    return this._client?.user || null
  }
}

export { DiscordClient }