Skip to content

Commit

Permalink
Added keyPrefix option, plus some trivial fixes
Browse files Browse the repository at this point in the history
Signed-off-by: Slava Fomin <slava@fomin.io>
  • Loading branch information
slavafomin committed Nov 23, 2024
1 parent b089ea9 commit 0d9a4ec
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/.idea/
node_modules/
package-lock.json
*.tsbuildinfo
Expand Down
11 changes: 6 additions & 5 deletions src/rateLimiter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,20 @@ import { RedisStore } from "./redisStore.ts";
export const limit = <C extends Context, RT extends RedisType>(
userOptions?: OptionsInterface<C, RT>,
) => {
const options = { ...defaultOptions, ...userOptions };
const options = { ...defaultOptions, ...(userOptions ?? {}) };
const store = options.storageClient === "MEMORY_STORE"
? new MemoryStore(options.timeFrame)
: new RedisStore(options.storageClient as RT, options.timeFrame);

const keyPrefix = userOptions?.keyPrefix ?? defaultOptions.keyPrefix;

const middlewareFunc = async (ctx: C, next: NextFunction) => {
const keyCheck = options.keyGenerator(ctx);
if (!keyCheck) {
const key = options.keyGenerator(ctx);
if (!key) {
return await next();
}

const key = "RATE_LIMITER" + keyCheck;
const hits = await store.increment(key);
const hits = await store.increment(keyPrefix + key);

if (hits === options.limit + 1 || (options.alwaysReply && hits > options.limit)) {
return options.onLimitExceeded(ctx, next);
Expand Down
15 changes: 11 additions & 4 deletions src/typesAndDefaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,24 @@ export interface OptionsInterface<C extends Context, RT extends RedisType> {

/**
* @param ctx Is the context object you get from grammy/telegraf.
* @returns A number in **string** format as the unique key (identifier).
* @description A function to generate a unique key for every user. You cound set it as any key you want (e.g group id)
* @returns A unique **string** key (identifier).
* @description A function to generate a unique key for every user. You could set it as any key you want (e.g. group id)
* @see [Getting Started](https://github.com/Amir-Zouerami/rateLimiter#-how-to-use)
*/
keyGenerator?: (ctx: C) => string | undefined;

/**
* @default "RATE_LIMITER"
* @description A string prefix that is getting added to the storage key after calling the `keyGenerator()`.
*/
keyPrefix?: string | undefined;
}

export const defaultOptions = {
export const defaultOptions: OptionsInterface<Context, RedisType> = {
timeFrame: 1000,
limit: 1,
onLimitExceeded: (_ctx: Context, _next: NextFunction) => {},
storageClient: "MEMORY_STORE",
keyGenerator: (ctx: Context) => ctx.from === undefined ? undefined : ctx.from.id.toString(),
keyGenerator: (ctx: Context) => ctx.from?.id.toString(),
keyPrefix: "RATE_LIMITER",
};

0 comments on commit 0d9a4ec

Please sign in to comment.