OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / hyper-social / bridge-irc / lib / router.js

71 lines · javascript ref:
import { createHash } from 'crypto'

class Router {
  constructor (opts = {}) {
    this._seen = new Map()
    this._maxSeen = opts.maxSeen || 10000
    this._ttl = opts.ttl || 60000 // 1 minute dedup window
    this._onIrcMessage = opts.onIrcMessage || null
    this._onKeetMessage = opts.onKeetMessage || null
  }

  _hash (text, author) {
    return createHash('sha256')
      .update(author || '')
      .update(text || '')
      .digest('hex')
      .slice(0, 16)
  }

  _isDuplicate (hash) {
    const now = Date.now()

    // Cleanup old entries
    if (this._seen.size > this._maxSeen) {
      for (const [k, ts] of this._seen) {
        if (now - ts > this._ttl) this._seen.delete(k)
      }
    }

    if (this._seen.has(hash)) {
      const ts = this._seen.get(hash)
      if (now - ts < this._ttl) return true
    }

    this._seen.set(hash, now)
    return false
  }

  // Called when IRC receives a message — relay to Keet
  routeToKeet (nick, text) {
    const hash = this._hash(text, nick)
    if (this._isDuplicate(hash)) return false

    if (this._onKeetMessage) {
      this._onKeetMessage(nick, text)
    }
    return true
  }

  // Called when Keet receives a message — relay to IRC
  routeToIrc (name, text) {
    const hash = this._hash(text, name)
    if (this._isDuplicate(hash)) return false

    if (this._onIrcMessage) {
      this._onIrcMessage(name, text)
    }
    return true
  }

  get seenCount () {
    return this._seen.size
  }

  clearSeen () {
    this._seen.clear()
  }
}

export { Router }