OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-social / bridge-irc / lib / irc-client.js

103 lines · javascript ref:
import IRC from 'irc-framework'

class IrcClient {
  constructor (opts) {
    this.server = opts.server
    this.port = opts.port || 6667
    this.tls = opts.tls ?? (opts.port === 6697)
    this.nick = opts.nick || 'keet-bridge'
    this.channel = opts.channel
    this.password = opts.password || null

    this._client = null
    this._connected = false
    this._onMessage = opts.onMessage || null
    this._onJoin = opts.onJoin || null
    this._onPart = opts.onPart || null
    this._onError = opts.onError || null
  }

  connect () {
    return new Promise((resolve, reject) => {
      this._client = new IRC.Client()

      this._client.connect({
        host: this.server,
        port: this.port,
        nick: this.nick,
        tls: this.tls,
        password: this.password
      })

      this._client.on('registered', () => {
        this._connected = true
        if (this.channel) {
          this._client.join(this.channel)
        }
        resolve()
      })

      this._client.on('message', (event) => {
        if (event.target === this.channel && this._onMessage) {
          this._onMessage(event.nick, event.message)
        }
      })

      this._client.on('action', (event) => {
        if (event.target === this.channel && this._onMessage) {
          this._onMessage(event.nick, `\x01ACTION ${event.message}\x01`)
        }
      })

      this._client.on('join', (event) => {
        if (event.channel === this.channel && this._onJoin) {
          this._onJoin(event.nick)
        }
      })

      this._client.on('part', (event) => {
        if (event.channel === this.channel && this._onPart) {
          this._onPart(event.nick, event.message)
        }
      })

      this._client.on('close', () => {
        this._connected = false
      })

      this._client.on('socket close', () => {
        this._connected = false
      })

      const errorTimeout = setTimeout(() => {
        if (!this._connected) reject(new Error('Connection timeout'))
      }, 15000)

      this._client.on('registered', () => clearTimeout(errorTimeout))
    })
  }

  say (text) {
    if (!this._connected || !this._client) return
    this._client.say(this.channel, text)
  }

  action (text) {
    if (!this._connected || !this._client) return
    this._client.action(this.channel, text)
  }

  disconnect (reason) {
    if (this._client) {
      this._client.quit(reason || 'Bridge shutting down')
      this._connected = false
    }
  }

  get connected () {
    return this._connected
  }
}

export { IrcClient }