refactor progress

This commit is contained in:
Hampus Kraft
2026-02-17 12:22:36 +00:00
parent cb31608523
commit d5abd1a7e4
8257 changed files with 1190207 additions and 761040 deletions

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const AdminRateLimitConfigs = {
ADMIN_LOOKUP: {
bucket: 'admin:lookup',
config: {limit: 200, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_USER_MODIFY: {
bucket: 'admin:user:modify',
config: {limit: 100, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_GUILD_MODIFY: {
bucket: 'admin:guild:modify',
config: {limit: 100, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_BAN_OPERATION: {
bucket: 'admin:ban:operation',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_BULK_OPERATION: {
bucket: 'admin:bulk:operation',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_GATEWAY_RELOAD: {
bucket: 'admin:gateway:reload',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_MESSAGE_OPERATION: {
bucket: 'admin:message:operation',
config: {limit: 100, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_CODE_GENERATION: {
bucket: 'admin:code:generation',
config: {limit: 30, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_AUDIT_LOG: {
bucket: 'admin:audit_log',
config: {limit: 100, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
ADMIN_GENERAL: {
bucket: 'admin:general',
config: {limit: 200, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
VISIONARY_SLOT_OPERATION: {
bucket: 'admin:visionary_slot:operation',
config: {limit: 50, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const AuthRateLimitConfigs = {
AUTH_REGISTER: {
bucket: 'auth:register',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
AUTH_LOGIN: {
bucket: 'auth:login',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
AUTH_SSO_START: {
bucket: 'auth:sso:start',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
AUTH_SSO_COMPLETE: {
bucket: 'auth:sso:complete',
config: {limit: 15, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
AUTH_LOGIN_MFA: {
bucket: 'auth:login:mfa',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_VERIFY_EMAIL: {
bucket: 'auth:verify',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_RESEND_VERIFICATION: {
bucket: 'auth:verify:resend',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_FORGOT_PASSWORD: {
bucket: 'auth:forgot',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_RESET_PASSWORD: {
bucket: 'auth:reset',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_EMAIL_REVERT: {
bucket: 'auth:email_revert',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_SESSIONS_GET: {
bucket: 'auth:sessions',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
AUTH_SESSIONS_LOGOUT: {
bucket: 'auth:sessions:logout',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
AUTH_AUTHORIZE_IP: {
bucket: 'auth:authorize_ip',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_IP_AUTHORIZATION_RESEND: {
bucket: 'auth:ip_authorization_resend',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_IP_AUTHORIZATION_POLL: {
bucket: 'auth:ip_authorization_poll',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_LOGOUT: {
bucket: 'auth:logout',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
AUTH_WEBAUTHN_OPTIONS: {
bucket: 'auth:webauthn:options',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
AUTH_WEBAUTHN_AUTHENTICATE: {
bucket: 'auth:webauthn:authenticate',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
MFA_SMS_ENABLE: {
bucket: 'mfa:sms:enable',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
MFA_SMS_DISABLE: {
bucket: 'mfa:sms:disable',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
MFA_WEBAUTHN_LIST: {
bucket: 'mfa:webauthn:list',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
MFA_WEBAUTHN_REGISTRATION_OPTIONS: {
bucket: 'mfa:webauthn:registration_options',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
MFA_WEBAUTHN_REGISTER: {
bucket: 'mfa:webauthn:register',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
MFA_WEBAUTHN_UPDATE: {
bucket: 'mfa:webauthn:update',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
MFA_WEBAUTHN_DELETE: {
bucket: 'mfa:webauthn:delete',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
PHONE_SEND_VERIFICATION: {
bucket: 'phone:send_verification',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
PHONE_VERIFY_CODE: {
bucket: 'phone:verify_code',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
PHONE_ADD: {
bucket: 'phone:add',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
PHONE_REMOVE: {
bucket: 'phone:remove',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_HANDOFF_INITIATE: {
bucket: 'auth:handoff:initiate',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_HANDOFF_COMPLETE: {
bucket: 'auth:handoff:complete',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_HANDOFF_STATUS: {
bucket: 'auth:handoff:status',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
AUTH_HANDOFF_CANCEL: {
bucket: 'auth:handoff:cancel',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
SUDO_SMS_SEND: {
bucket: 'sudo:sms:send',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
SUDO_WEBAUTHN_OPTIONS: {
bucket: 'sudo:webauthn:options',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
SUDO_MFA_METHODS: {
bucket: 'sudo:mfa:methods',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,143 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const ChannelRateLimitConfigs = {
CHANNEL_GET: {
bucket: 'channel:read::channel_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_UPDATE: {
bucket: 'channel:update::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_DELETE: {
bucket: 'channel:delete::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_READ_STATE_DELETE: {
bucket: 'channel:read_state:delete::channel_id',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_MESSAGES_GET: {
bucket: 'channel:messages:read::channel_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_MESSAGE_GET: {
bucket: 'channel:message:read::channel_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_MESSAGE_CREATE: {
bucket: 'channel:message:create::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_MESSAGE_UPDATE: {
bucket: 'channel:message:update::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_MESSAGE_DELETE: {
bucket: 'channel:message:delete::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_MESSAGE_BULK_DELETE: {
bucket: 'channel:message:bulk_delete::channel_id',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_MESSAGE_ACK: {
bucket: 'channel:message:ack::channel_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_SEARCH: {
bucket: 'channel:search::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_ATTACHMENT_UPLOAD: {
bucket: 'channel:attachment:upload::channel_id',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
ATTACHMENT_DELETE: {
bucket: 'attachment:delete',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_TYPING: {
bucket: 'channel:typing::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_PINS: {
bucket: 'channel:pins::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_REACTIONS: {
bucket: 'channel:reactions::channel_id',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_CALL_GET: {
bucket: 'channel:call:get::channel_id',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_CALL_UPDATE: {
bucket: 'channel:call:update::channel_id',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_CALL_RING: {
bucket: 'channel:call:ring::channel_id',
config: {limit: 5, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_CALL_STOP_RINGING: {
bucket: 'channel:call:stop_ringing::channel_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_STREAM_UPDATE: {
bucket: 'channel:stream:update::stream_key',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_STREAM_PREVIEW_GET: {
bucket: 'channel:stream:preview:get::stream_key',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
CHANNEL_STREAM_PREVIEW_POST: {
bucket: 'channel:stream:preview:post::stream_key',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const ConnectionRateLimitConfigs = {
CONNECTION_LIST: {
bucket: 'connection:list',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
CONNECTION_CREATE: {
bucket: 'connection:create',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
CONNECTION_UPDATE: {
bucket: 'connection:update',
config: {limit: 30, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
CONNECTION_DELETE: {
bucket: 'connection:delete',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
CONNECTION_VERIFY: {
bucket: 'connection:verify',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
CONNECTION_VERIFY_AND_CREATE: {
bucket: 'connection:verify_and_create',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const DiscoveryRateLimitConfigs = {
DISCOVERY_SEARCH: {
bucket: 'discovery:search',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
DISCOVERY_CATEGORIES: {
bucket: 'discovery:categories',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
DISCOVERY_JOIN: {
bucket: 'discovery:join',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DISCOVERY_APPLY: {
bucket: 'discovery:apply::guild_id',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DISCOVERY_STATUS: {
bucket: 'discovery:status::guild_id',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
DISCOVERY_ADMIN_LIST: {
bucket: 'discovery:admin:list',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
DISCOVERY_ADMIN_ACTION: {
bucket: 'discovery:admin:action',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const DonationRateLimitConfigs = {
DONATION_REQUEST_LINK: {
bucket: 'donation:request_link',
config: {limit: 3, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
DONATION_MANAGE: {
bucket: 'donation:manage',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DONATION_CHECKOUT: {
bucket: 'donation:checkout',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,198 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const GuildRateLimitConfigs = {
GUILD_CREATE: {
bucket: 'guild:create',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_LIST: {
bucket: 'guild:list',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_GET: {
bucket: 'guild:read::guild_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_UPDATE: {
bucket: 'guild:update::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_DELETE: {
bucket: 'guild:delete::guild_id',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_LEAVE: {
bucket: 'guild:leave::guild_id',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_VANITY_URL_GET: {
bucket: 'guild:vanity_url:get::guild_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_VANITY_URL_PATCH: {
bucket: 'guild:vanity_url:patch::guild_id',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_MEMBERS: {
bucket: 'guild:members::guild_id',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_MEMBER_UPDATE: {
bucket: 'guild:member:update::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_MEMBER_REMOVE: {
bucket: 'guild:member:remove::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_MEMBER_ROLE_ADD: {
bucket: 'guild:member:role:add::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_MEMBER_ROLE_REMOVE: {
bucket: 'guild:member:role:remove::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_CHANNELS_LIST: {
bucket: 'guild:channels:list::guild_id',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_CHANNEL_CREATE: {
bucket: 'guild:channel:create::guild_id',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_CHANNEL_POSITIONS: {
bucket: 'guild:channel:positions::guild_id',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_SEARCH: {
bucket: 'guild:search::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_AUDIT_LOGS: {
bucket: 'guild:audit_logs::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_ROLE_CREATE: {
bucket: 'guild:role:create::guild_id',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_ROLE_UPDATE: {
bucket: 'guild:role:update::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_ROLE_DELETE: {
bucket: 'guild:role:delete::guild_id',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_ROLE_POSITIONS: {
bucket: 'guild:role:positions::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_ROLE_LIST: {
bucket: 'guild:role:list::guild_id',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_ROLE_HOIST_POSITIONS: {
bucket: 'guild:role:hoist_positions::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_ROLE_HOIST_POSITIONS_RESET: {
bucket: 'guild:role:hoist_positions_reset::guild_id',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_EMOJIS_LIST: {
bucket: 'guild:emojis:list::guild_id',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_EMOJI_CREATE: {
bucket: 'guild:emoji:create::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_EMOJI_BULK_CREATE: {
bucket: 'guild:emoji:bulk_create::guild_id',
config: {limit: 6, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_EMOJI_UPDATE: {
bucket: 'guild:emoji:update::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_EMOJI_DELETE: {
bucket: 'guild:emoji:delete::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_STICKERS_LIST: {
bucket: 'guild:sticker:list::guild_id',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_STICKER_CREATE: {
bucket: 'guild:sticker:create::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_STICKER_BULK_CREATE: {
bucket: 'guild:sticker:bulk_create::guild_id',
config: {limit: 6, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GUILD_STICKER_UPDATE: {
bucket: 'guild:sticker:update::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GUILD_STICKER_DELETE: {
bucket: 'guild:sticker:delete::guild_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const IntegrationRateLimitConfigs = {
KLIPY_SEARCH: {
bucket: 'klipy:search',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
KLIPY_FEATURED: {
bucket: 'klipy:featured',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
KLIPY_TRENDING: {
bucket: 'klipy:trending',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
KLIPY_SUGGEST: {
bucket: 'klipy:suggest',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
KLIPY_REGISTER_SHARE: {
bucket: 'klipy:register_share',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
TENOR_SEARCH: {
bucket: 'tenor:search',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
TENOR_FEATURED: {
bucket: 'tenor:featured',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
TENOR_TRENDING: {
bucket: 'tenor:trending',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
TENOR_SUGGEST: {
bucket: 'tenor:suggest',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
TENOR_REGISTER_SHARE: {
bucket: 'tenor:register_share',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
STRIPE_VISIONARY_SLOTS: {
bucket: 'stripe:visionary:slots',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
STRIPE_PRICE_IDS: {
bucket: 'stripe:price:ids',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
STRIPE_CHECKOUT_SUBSCRIPTION: {
bucket: 'stripe:checkout:subscription',
config: {limit: 3, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
STRIPE_CHECKOUT_GIFT: {
bucket: 'stripe:checkout:gift',
config: {limit: 3, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
STRIPE_CUSTOMER_PORTAL: {
bucket: 'stripe:customer_portal',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
STRIPE_SUBSCRIPTION_CANCEL: {
bucket: 'stripe:subscription:cancel',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
STRIPE_SUBSCRIPTION_REACTIVATE: {
bucket: 'stripe:subscription:reactivate',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
STRIPE_VISIONARY_REJOIN: {
bucket: 'stripe:visionary:rejoin',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GIFT_CODE_GET: {
bucket: 'gift:get',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GIFT_CODE_REDEEM: {
bucket: 'gift:redeem',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
GIFTS_LIST: {
bucket: 'gifts:list',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const InviteRateLimitConfigs = {
INVITE_GET: {
bucket: 'invite:read::invite_code',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
INVITE_ACCEPT: {
bucket: 'invite:accept',
config: {limit: 10, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
INVITE_CREATE: {
bucket: 'invite:create::channel_id',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
INVITE_DELETE: {
bucket: 'invite:delete::invite_code',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
INVITE_LIST_CHANNEL: {
bucket: 'invite:list::channel_id',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
INVITE_LIST_GUILD: {
bucket: 'invite:list::guild_id',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const MiscRateLimitConfigs = {
INSTANCE_INFO: {
bucket: 'instance:info',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DOWNLOAD_DESKTOP_LATEST: {
bucket: 'download:desktop:latest',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DOWNLOAD_DESKTOP_METADATA: {
bucket: 'download:desktop:metadata',
config: {limit: 120, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DOWNLOAD_ARTIFACT: {
bucket: 'download:artifact',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DOWNLOAD_PACKAGE: {
bucket: 'download:package',
config: {limit: 5, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DOWNLOAD_STORE_REDIRECT: {
bucket: 'download:store:redirect',
config: {limit: 30, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
DOWNLOAD_MODULE: {
bucket: 'download:module',
config: {limit: 30, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
READ_STATE_ACK_BULK: {
bucket: 'read_state:ack_bulk',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
REPORT_CREATE: {
bucket: 'report:create',
config: {limit: 10, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
DSA_REPORT_EMAIL_SEND: {
bucket: 'dsa:report:email:send',
config: {limit: 5, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
DSA_REPORT_EMAIL_VERIFY: {
bucket: 'dsa:report:email:verify',
config: {limit: 10, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
DSA_REPORT_CREATE: {
bucket: 'dsa:report:create',
config: {limit: 5, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
REPORT_LIST: {
bucket: 'report:list',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
FAVORITE_MEME_LIST: {
bucket: 'favorite_meme:list',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
FAVORITE_MEME_GET: {
bucket: 'favorite_meme:get',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
FAVORITE_MEME_CREATE_FROM_MESSAGE: {
bucket: 'favorite_meme:create:message',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
FAVORITE_MEME_CREATE_FROM_URL: {
bucket: 'favorite_meme:create:url',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
FAVORITE_MEME_UPDATE: {
bucket: 'favorite_meme:update',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
FAVORITE_MEME_DELETE: {
bucket: 'favorite_meme:delete',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
GATEWAY_BOT_INFO: {
bucket: 'gateway:bot_info',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
THEME_SHARE_CREATE: {
bucket: 'theme:share:create',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
SEARCH_MESSAGES: {
bucket: 'search:messages',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
DEFAULT: {
bucket: 'default',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const OAuthRateLimitConfigs = {
OAUTH_AUTHORIZE: {
bucket: 'oauth:authorize',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_CONSENT: {
bucket: 'oauth:consent',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_TOKEN: {
bucket: 'oauth:token',
config: {limit: 120, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_INTROSPECT: {
bucket: 'oauth:introspect',
config: {limit: 120, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_REVOKE: {
bucket: 'oauth:revoke',
config: {limit: 120, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_CLIENTS_LIST: {
bucket: 'oauth_dev:clients:list',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_CLIENT_CREATE: {
bucket: 'oauth_dev:clients:create',
config: {limit: 10, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
OAUTH_DEV_CLIENT_UPDATE: {
bucket: 'oauth_dev:clients:update::client_id',
config: {limit: 30, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_CLIENT_ROTATE_SECRET: {
bucket: 'oauth_dev:clients:rotate_secret::client_id',
config: {limit: 10, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
OAUTH_DEV_CLIENT_DELETE: {
bucket: 'oauth_dev:clients:delete::client_id',
config: {limit: 10, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
OAUTH_DEV_TEAMS_LIST: {
bucket: 'oauth_dev:teams:list',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_TEAM_CREATE: {
bucket: 'oauth_dev:teams:create',
config: {limit: 15, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
OAUTH_DEV_TEAM_DELETE: {
bucket: 'oauth_dev:teams:delete::team_id',
config: {limit: 15, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
OAUTH_DEV_TEAM_MEMBERS_LIST: {
bucket: 'oauth_dev:teams:members:list::team_id',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_TEAM_MEMBER_ADD: {
bucket: 'oauth_dev:teams:members:add::team_id',
config: {limit: 30, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_TEAM_MEMBER_REMOVE: {
bucket: 'oauth_dev:teams:members:remove::team_id::user_id',
config: {limit: 30, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_BOT_TOKENS_LIST: {
bucket: 'oauth_dev:bot_tokens:list::client_id',
config: {limit: 60, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_BOT_TOKENS_CREATE: {
bucket: 'oauth_dev:bot_tokens:create::client_id',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
OAUTH_DEV_BOT_TOKEN_REVOKE: {
bucket: 'oauth_dev:bot_tokens:revoke',
config: {limit: 40, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const PackRateLimitConfigs = {
PACKS_LIST: {
bucket: 'packs:list',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_CREATE: {
bucket: 'packs:create',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_UPDATE: {
bucket: 'packs:update::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_DELETE: {
bucket: 'packs:delete::pack_id',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
PACKS_INSTALL: {
bucket: 'packs:install::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_INVITES_LIST: {
bucket: 'packs:invite:list::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_INVITES_CREATE: {
bucket: 'packs:invite:create::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_EMOJIS_LIST: {
bucket: 'packs:emoji:list::pack_id',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_EMOJI_CREATE: {
bucket: 'packs:emoji:create::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_EMOJI_BULK_CREATE: {
bucket: 'packs:emoji:bulk_create::pack_id',
config: {limit: 6, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
PACKS_EMOJI_UPDATE: {
bucket: 'packs:emoji:update::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_EMOJI_DELETE: {
bucket: 'packs:emoji:delete::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_STICKERS_LIST: {
bucket: 'packs:sticker:list::pack_id',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_STICKER_CREATE: {
bucket: 'packs:sticker:create::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_STICKER_BULK_CREATE: {
bucket: 'packs:sticker:bulk_create::pack_id',
config: {limit: 6, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
PACKS_STICKER_UPDATE: {
bucket: 'packs:sticker:update::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
PACKS_STICKER_DELETE: {
bucket: 'packs:sticker:delete::pack_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
export type RateLimitSection = {readonly [key: string]: RouteRateLimitConfig};
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
export function mergeRateLimitSections<T extends ReadonlyArray<RateLimitSection>>(
...sections: T
): UnionToIntersection<T[number]> {
return Object.assign({}, ...sections) as UnionToIntersection<T[number]>;
}

View File

@@ -0,0 +1,263 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const UserRateLimitConfigs = {
USER_GET: {
bucket: 'user:read::user_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_GET_PROFILE: {
bucket: 'user:profile::target_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_CHECK_TAG: {
bucket: 'user:check_tag',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_UPDATE_SELF: {
bucket: 'user:update',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_START: {
bucket: 'user:email_change:start',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_RESEND_ORIGINAL: {
bucket: 'user:email_change:resend_original',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_VERIFY_ORIGINAL: {
bucket: 'user:email_change:verify_original',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_REQUEST_NEW: {
bucket: 'user:email_change:request_new',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_RESEND_NEW: {
bucket: 'user:email_change:resend_new',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_VERIFY_NEW: {
bucket: 'user:email_change:verify_new',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_BOUNCED_REQUEST_NEW: {
bucket: 'user:email_change:bounced:request_new',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_BOUNCED_RESEND_NEW: {
bucket: 'user:email_change:bounced:resend_new',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_EMAIL_CHANGE_BOUNCED_VERIFY_NEW: {
bucket: 'user:email_change:bounced:verify_new',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_PASSWORD_CHANGE_START: {
bucket: 'user:password_change:start',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_PASSWORD_CHANGE_RESEND: {
bucket: 'user:password_change:resend',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_PASSWORD_CHANGE_VERIFY: {
bucket: 'user:password_change:verify',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_PASSWORD_CHANGE_COMPLETE: {
bucket: 'user:password_change:complete',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_ACCOUNT_DISABLE: {
bucket: 'user:account:disable',
config: {limit: 5, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
USER_ACCOUNT_DELETE: {
bucket: 'user:account:delete',
config: {limit: 5, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
USER_DATA_HARVEST: {
bucket: 'user:data:harvest',
config: {limit: 1, windowMs: ms('1 hour')},
} as RouteRateLimitConfig,
USER_PRELOAD_MESSAGES: {
bucket: 'user:preload_messages',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_BULK_MESSAGE_DELETE: {
bucket: 'user:messages:bulk_delete',
config: {limit: 6, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_SETTINGS_GET: {
bucket: 'user:settings:get',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_SETTINGS_UPDATE: {
bucket: 'user:settings:update',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_GUILD_SETTINGS_UPDATE: {
bucket: 'user:guild_settings:update',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_CHANNELS: {
bucket: 'user:channels',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_RELATIONSHIPS_LIST: {
bucket: 'user:relationships:list',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_FRIEND_REQUEST_SEND: {
bucket: 'user:friend_request:send',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_FRIEND_REQUEST_ACCEPT: {
bucket: 'user:friend_request:accept',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_BLOCK: {
bucket: 'user:block',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_RELATIONSHIP_DELETE: {
bucket: 'user:relationship:delete',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_RELATIONSHIP_UPDATE: {
bucket: 'user:relationship:update',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_NOTES_READ: {
bucket: 'user:notes:read',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_NOTES_WRITE: {
bucket: 'user:notes:write',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_MENTIONS_READ: {
bucket: 'user:mentions:read',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_MENTIONS_DELETE: {
bucket: 'user:mentions:delete',
config: {limit: 60, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_SAVED_MESSAGES_READ: {
bucket: 'user:saved_messages:read',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_SAVED_MESSAGES_WRITE: {
bucket: 'user:saved_messages:write',
config: {limit: 30, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_MFA_TOTP_ENABLE: {
bucket: 'user:mfa:totp:enable',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_MFA_TOTP_DISABLE: {
bucket: 'user:mfa:totp:disable',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_AUTHORIZED_IPS_FORGET: {
bucket: 'user:authorized_ips:forget',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_MFA_BACKUP_CODES: {
bucket: 'user:mfa:backup_codes',
config: {limit: 6, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_PUSH_SUBSCRIBE: {
bucket: 'user:push:subscribe',
config: {limit: 20, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_PUSH_UNSUBSCRIBE: {
bucket: 'user:push:unsubscribe',
config: {limit: 40, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
USER_PUSH_LIST: {
bucket: 'user:push:list',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_HARVEST_LATEST: {
bucket: 'user:harvest:latest',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_HARVEST_STATUS: {
bucket: 'user:harvest:status',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
USER_HARVEST_DOWNLOAD: {
bucket: 'user:harvest:download',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
} as const;

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {RouteRateLimitConfig} from '@fluxer/api/src/middleware/RateLimitMiddleware';
import {ms} from 'itty-time';
export const WebhookRateLimitConfigs = {
WEBHOOK_LIST_GUILD: {
bucket: 'webhook:list::guild_id',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
WEBHOOK_LIST_CHANNEL: {
bucket: 'webhook:list::channel_id',
config: {limit: 40, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
WEBHOOK_CREATE: {
bucket: 'webhook:create::channel_id',
config: {limit: 10, windowMs: ms('1 minute')},
} as RouteRateLimitConfig,
WEBHOOK_GET: {
bucket: 'webhook:read::webhook_id',
config: {limit: 100, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
WEBHOOK_UPDATE: {
bucket: 'webhook:update::webhook_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
WEBHOOK_DELETE: {
bucket: 'webhook:delete::webhook_id',
config: {limit: 20, windowMs: ms('10 seconds')},
} as RouteRateLimitConfig,
WEBHOOK_EXECUTE: {
bucket: 'webhook:execute::webhook_id',
config: {limit: 60, windowMs: ms('1 minute'), exemptFromGlobal: true},
} as RouteRateLimitConfig,
WEBHOOK_GITHUB: {
bucket: 'webhook:github::webhook_id',
config: {limit: 200, windowMs: ms('1 minute'), exemptFromGlobal: true},
} as RouteRateLimitConfig,
} as const;