Newer
Older
WeComCompanyPlugin / utils.js
/**
 * Utility helpers for the WeCom plugin.
 */
export class TTLCache {
  options;
  cache = new Map();
  checkPeriod;
  cleanupTimer;
  constructor(options) {
    this.options = options;
    this.checkPeriod = options.checkPeriod || options.ttl;
    this.startCleanup();
  }
  set(key, value, ttl) {
    const expiresAt = Date.now() + (ttl || this.options.ttl);
    this.cache.set(key, { value, expiresAt });
  }
  get(key) {
    const entry = this.cache.get(key);
    if (!entry) {
      return undefined;
    }
    if (Date.now() > entry.expiresAt) {
      this.cache.delete(key);
      return undefined;
    }
    return entry.value;
  }
  has(key) {
    return this.get(key) !== undefined;
  }
  delete(key) {
    return this.cache.delete(key);
  }
  clear() {
    this.cache.clear();
  }
  size() {
    this.cleanup();
    return this.cache.size;
  }
  cleanup() {
    const now = Date.now();
    for (const [key, entry] of this.cache.entries()) {
      if (now > entry.expiresAt) {
        this.cache.delete(key);
      }
    }
  }
  startCleanup() {
    this.cleanupTimer = setInterval(() => {
      this.cleanup();
    }, this.checkPeriod);
    // Don't prevent process from exiting
    if (this.cleanupTimer.unref) {
      this.cleanupTimer.unref();
    }
  }
  destroy() {
    if (this.cleanupTimer) {
      clearInterval(this.cleanupTimer);
    }
    this.cache.clear();
  }
}
// ============================================================================
// Message deduplication
// ============================================================================
export class MessageDeduplicator {
  seen = new TTLCache({ ttl: 300000 }); // 5 minutes
  isDuplicate(msgId) {
    if (this.seen.has(msgId)) {
      return true;
    }
    this.seen.set(msgId, true);
    return false;
  }
  markAsSeen(msgId) {
    this.seen.set(msgId, true);
  }
}
// ============================================================================
// Constants
// ============================================================================
export const CONSTANTS = {
  // AES/Crypto
  AES_BLOCK_SIZE: 32,
  AES_KEY_LENGTH: 43,
};