{"version":3,"file":"privmsg.mjs","names":[],"sources":["../../../src/mixins/ratelimiters/privmsg.ts"],"sourcesContent":["import { Sema } from \"async-sema\";\n\nimport type { ClientMixin } from \"../base-mixin\";\nimport type { ChatClient } from \"~/client/client\";\nimport { canSpamFast } from \"./utils\";\nimport { applyReplacements } from \"~/utils/apply-function-replacements\";\n\nexport class PrivmsgMessageRateLimiter implements ClientMixin {\n  private readonly client: ChatClient;\n  private readonly highPrivmsgSemaphore: Sema;\n  private readonly lowPrivmsgSemaphore: Sema;\n\n  public constructor(client: ChatClient) {\n    this.client = client;\n\n    this.highPrivmsgSemaphore = new Sema(\n      this.client.configuration.rateLimits.highPrivmsgLimits,\n    );\n    this.lowPrivmsgSemaphore = new Sema(\n      this.client.configuration.rateLimits.lowPrivmsgLimits,\n    );\n  }\n\n  public applyToClient(client: ChatClient): void {\n    const genericReplacement = async <V, A extends unknown[]>(\n      oldFunction: (channelName: string, ...args: A) => Promise<V>,\n      channelName: string,\n      ...args: A\n    ): Promise<V> => {\n      const releaseFunction = await this.acquire(channelName);\n      try {\n        return await oldFunction(channelName, ...args);\n      } finally {\n        setTimeout(\n          releaseFunction,\n          this.client.configuration.rateLimits.privmsgInMs,\n        );\n      }\n    };\n\n    applyReplacements(this, client, {\n      say: genericReplacement,\n      me: genericReplacement,\n      privmsg: genericReplacement,\n    });\n  }\n\n  private async acquire(channelName: string): Promise<() => void> {\n    const { fastSpam } = canSpamFast(\n      channelName,\n      this.client.configuration.username,\n      this.client.userStateTracker,\n    );\n\n    const promises: Promise<unknown>[] = [];\n    promises.push(this.highPrivmsgSemaphore.acquire());\n    if (!fastSpam) {\n      promises.push(this.lowPrivmsgSemaphore.acquire());\n    }\n\n    const releaseFunction = (): void => {\n      if (!fastSpam) {\n        this.lowPrivmsgSemaphore.release();\n      }\n\n      this.highPrivmsgSemaphore.release();\n    };\n\n    await Promise.all(promises);\n    return releaseFunction;\n  }\n}\n"],"mappings":";;;;AAOA,IAAa,4BAAb,MAA8D;CAC5D;CACA;CACA;CAEA,YAAmB,QAAoB;AACrC,OAAK,SAAS;AAEd,OAAK,uBAAuB,IAAI,KAC9B,KAAK,OAAO,cAAc,WAAW,kBACtC;AACD,OAAK,sBAAsB,IAAI,KAC7B,KAAK,OAAO,cAAc,WAAW,iBACtC;;CAGH,cAAqB,QAA0B;EAC7C,MAAM,qBAAqB,OACzB,aACA,aACA,GAAG,SACY;GACf,MAAM,kBAAkB,MAAM,KAAK,QAAQ,YAAY;AACvD,OAAI;AACF,WAAO,MAAM,YAAY,aAAa,GAAG,KAAK;aACtC;AACR,eACE,iBACA,KAAK,OAAO,cAAc,WAAW,YACtC;;;AAIL,oBAAkB,MAAM,QAAQ;GAC9B,KAAK;GACL,IAAI;GACJ,SAAS;GACV,CAAC;;CAGJ,MAAc,QAAQ,aAA0C;EAC9D,MAAM,EAAE,aAAa,YACnB,aACA,KAAK,OAAO,cAAc,UAC1B,KAAK,OAAO,iBACb;EAED,MAAM,WAA+B,EAAE;AACvC,WAAS,KAAK,KAAK,qBAAqB,SAAS,CAAC;AAClD,MAAI,CAAC,SACH,UAAS,KAAK,KAAK,oBAAoB,SAAS,CAAC;EAGnD,MAAM,wBAA8B;AAClC,OAAI,CAAC,SACH,MAAK,oBAAoB,SAAS;AAGpC,QAAK,qBAAqB,SAAS;;AAGrC,QAAM,QAAQ,IAAI,SAAS;AAC3B,SAAO"}