diff --git a/src/gateway/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts
index 42e76312..479efec3 100644
--- a/src/gateway/opcodes/VoiceStateUpdate.ts
+++ b/src/gateway/opcodes/VoiceStateUpdate.ts
@@ -6,13 +6,12 @@ import {
emitEvent,
Guild,
Member,
- Region,
VoiceServerUpdateEvent,
VoiceState,
VoiceStateUpdateEvent,
VoiceStateUpdateSchema,
} from "@fosscord/util";
-
+import { Region } from "@fosscord/util/src/config";
// TODO: check if a voice server is setup
// Notice: Bot users respect the voice channel's user limit, if set.
diff --git a/src/util/config/Config.ts b/src/util/config/Config.ts
new file mode 100644
index 00000000..b703040f
--- /dev/null
+++ b/src/util/config/Config.ts
@@ -0,0 +1,22 @@
+import { ApiConfiguration, ClientConfiguration, DefaultsConfiguration, EndpointConfiguration, GeneralConfiguration, GifConfiguration, GuildConfiguration, KafkaConfiguration, LimitsConfiguration, LoginConfiguration, MetricsConfiguration, RabbitMQConfiguration, RegionConfiguration, RegisterConfiguration, SecurityConfiguration, SentryConfiguration, TemplateConfiguration } from "../config";
+
+export class ConfigValue {
+ gateway: EndpointConfiguration = new EndpointConfiguration();
+ cdn: EndpointConfiguration = new EndpointConfiguration();
+ api: ApiConfiguration = new ApiConfiguration();
+ general: GeneralConfiguration = new GeneralConfiguration();
+ limits: LimitsConfiguration = new LimitsConfiguration();
+ security: SecurityConfiguration = new SecurityConfiguration();
+ login: LoginConfiguration = new LoginConfiguration();
+ register: RegisterConfiguration = new RegisterConfiguration();
+ regions: RegionConfiguration = new RegionConfiguration();
+ guild: GuildConfiguration = new GuildConfiguration();
+ gif: GifConfiguration = new GifConfiguration();
+ rabbitmq: RabbitMQConfiguration = new RabbitMQConfiguration();
+ kafka: KafkaConfiguration = new KafkaConfiguration();
+ templates: TemplateConfiguration = new TemplateConfiguration();
+ client: ClientConfiguration = new ClientConfiguration();
+ metrics: MetricsConfiguration = new MetricsConfiguration();
+ sentry: SentryConfiguration = new SentryConfiguration();
+ defaults: DefaultsConfiguration = new DefaultsConfiguration();
+}
\ No newline at end of file
diff --git a/src/util/config/index.ts b/src/util/config/index.ts
new file mode 100644
index 00000000..0a9b58ae
--- /dev/null
+++ b/src/util/config/index.ts
@@ -0,0 +1,2 @@
+export * from "./Config";
+export * from "./types/index";
diff --git a/src/util/config/types/ApiConfiguration.ts b/src/util/config/types/ApiConfiguration.ts
new file mode 100644
index 00000000..16b1efba
--- /dev/null
+++ b/src/util/config/types/ApiConfiguration.ts
@@ -0,0 +1,5 @@
+export class ApiConfiguration {
+ defaultVersion: string = "9";
+ activeVersions: string[] = ["6", "7", "8", "9"];
+ useFosscordEnhancements: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/ClientConfiguration.ts b/src/util/config/types/ClientConfiguration.ts
new file mode 100644
index 00000000..1adda1e2
--- /dev/null
+++ b/src/util/config/types/ClientConfiguration.ts
@@ -0,0 +1,8 @@
+import { ClientReleaseConfiguration } from ".";
+
+export class ClientConfiguration {
+ //classes
+ releases: ClientReleaseConfiguration = new ClientReleaseConfiguration();
+ //base types
+ useTestClient: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/DefaultsConfiguration.ts b/src/util/config/types/DefaultsConfiguration.ts
new file mode 100644
index 00000000..c3171a01
--- /dev/null
+++ b/src/util/config/types/DefaultsConfiguration.ts
@@ -0,0 +1,5 @@
+import { GuildDefaults } from ".";
+
+export class DefaultsConfiguration {
+ guild: GuildDefaults = new GuildDefaults();
+}
\ No newline at end of file
diff --git a/src/util/config/types/EndpointConfiguration.ts b/src/util/config/types/EndpointConfiguration.ts
new file mode 100644
index 00000000..87baea31
--- /dev/null
+++ b/src/util/config/types/EndpointConfiguration.ts
@@ -0,0 +1,5 @@
+export class EndpointConfiguration {
+ endpointClient: string | null = null;
+ endpointPrivate: string | null = null;
+ endpointPublic: string | null = null;
+}
\ No newline at end of file
diff --git a/src/util/config/types/GeneralConfiguration.ts b/src/util/config/types/GeneralConfiguration.ts
new file mode 100644
index 00000000..55848b44
--- /dev/null
+++ b/src/util/config/types/GeneralConfiguration.ts
@@ -0,0 +1,12 @@
+import { Snowflake } from "../../util";
+
+export class GeneralConfiguration {
+ instanceName: string = "Fosscord Instance";
+ instanceDescription: string | null = "This is a Fosscord instance made in the pre-release days";
+ frontPage: string | null = null;
+ tosPage: string | null = null;
+ correspondenceEmail: string | null = "noreply@localhost.local";
+ correspondenceUserID: string | null = null;
+ image: string | null = null;
+ instanceId: string = Snowflake.generate();
+}
\ No newline at end of file
diff --git a/src/util/config/types/GifConfiguration.ts b/src/util/config/types/GifConfiguration.ts
new file mode 100644
index 00000000..6a2d520d
--- /dev/null
+++ b/src/util/config/types/GifConfiguration.ts
@@ -0,0 +1,5 @@
+export class GifConfiguration {
+ enabled: boolean = true;
+ provider: "tenor" = "tenor"; // more coming soon
+ apiKey?: string = "LIVDSRZULELA";
+}
\ No newline at end of file
diff --git a/src/util/config/types/GuildConfiguration.ts b/src/util/config/types/GuildConfiguration.ts
new file mode 100644
index 00000000..3d43b368
--- /dev/null
+++ b/src/util/config/types/GuildConfiguration.ts
@@ -0,0 +1,6 @@
+import { DiscoveryConfiguration, AutoJoinConfiguration } from ".";
+
+export class GuildConfiguration {
+ discovery: DiscoveryConfiguration = new DiscoveryConfiguration();
+ autoJoin: AutoJoinConfiguration = new AutoJoinConfiguration();
+}
diff --git a/src/util/config/types/KafkaConfiguration.ts b/src/util/config/types/KafkaConfiguration.ts
new file mode 100644
index 00000000..7932f49e
--- /dev/null
+++ b/src/util/config/types/KafkaConfiguration.ts
@@ -0,0 +1,5 @@
+import { KafkaBroker } from ".";
+
+export class KafkaConfiguration {
+ brokers: KafkaBroker[] | null = null;
+}
\ No newline at end of file
diff --git a/src/util/config/types/LimitConfigurations.ts b/src/util/config/types/LimitConfigurations.ts
new file mode 100644
index 00000000..bcc2e7e2
--- /dev/null
+++ b/src/util/config/types/LimitConfigurations.ts
@@ -0,0 +1,9 @@
+import { ChannelLimits, GuildLimits, MessageLimits, RateLimits, UserLimits } from ".";
+
+export class LimitsConfiguration {
+ user: UserLimits = new UserLimits();
+ guild: GuildLimits = new GuildLimits();
+ message: MessageLimits = new MessageLimits();
+ channel: ChannelLimits = new ChannelLimits();
+ rate: RateLimits = new RateLimits();
+}
\ No newline at end of file
diff --git a/src/util/config/types/LoginConfiguration.ts b/src/util/config/types/LoginConfiguration.ts
new file mode 100644
index 00000000..255c9451
--- /dev/null
+++ b/src/util/config/types/LoginConfiguration.ts
@@ -0,0 +1,3 @@
+export class LoginConfiguration {
+ requireCaptcha: boolean = false;
+}
\ No newline at end of file
diff --git a/src/util/config/types/MetricsConfiguration.ts b/src/util/config/types/MetricsConfiguration.ts
new file mode 100644
index 00000000..d7cd4937
--- /dev/null
+++ b/src/util/config/types/MetricsConfiguration.ts
@@ -0,0 +1,3 @@
+export class MetricsConfiguration {
+ timeout: number = 30000;
+}
\ No newline at end of file
diff --git a/src/util/config/types/RabbitMQConfiguration.ts b/src/util/config/types/RabbitMQConfiguration.ts
new file mode 100644
index 00000000..ce4a9123
--- /dev/null
+++ b/src/util/config/types/RabbitMQConfiguration.ts
@@ -0,0 +1,3 @@
+export class RabbitMQConfiguration {
+ host: string | null = null;
+}
\ No newline at end of file
diff --git a/src/util/config/types/RegionConfiguration.ts b/src/util/config/types/RegionConfiguration.ts
new file mode 100644
index 00000000..09d9271c
--- /dev/null
+++ b/src/util/config/types/RegionConfiguration.ts
@@ -0,0 +1,16 @@
+import { Region } from ".";
+
+export class RegionConfiguration {
+ default: string = "fosscord";
+ useDefaultAsOptimal: boolean = true;
+ available: Region[] = [
+ {
+ id: "fosscord",
+ name: "Fosscord",
+ endpoint: "127.0.0.1:3004",
+ vip: false,
+ custom: false,
+ deprecated: false,
+ },
+ ];
+}
\ No newline at end of file
diff --git a/src/util/config/types/RegisterConfiguration.ts b/src/util/config/types/RegisterConfiguration.ts
new file mode 100644
index 00000000..a0dc97c5
--- /dev/null
+++ b/src/util/config/types/RegisterConfiguration.ts
@@ -0,0 +1,18 @@
+import { DateOfBirthConfiguration, EmailConfiguration, PasswordConfiguration } from ".";
+
+export class RegisterConfiguration {
+ //classes
+ email: EmailConfiguration = new EmailConfiguration();
+ dateOfBirth: DateOfBirthConfiguration = new DateOfBirthConfiguration();
+ password: PasswordConfiguration = new PasswordConfiguration();
+ //base types
+ disabled: boolean = false;
+ requireCaptcha: boolean = true;
+ requireInvite: boolean = false;
+ guestsRequireInvite: boolean = true;
+ allowNewRegistration: boolean = true;
+ allowMultipleAccounts: boolean = true;
+ blockProxies: boolean = true;
+ incrementingDiscriminators: boolean = false; // random otherwise
+ defaultRights: string = "0";
+}
diff --git a/src/util/config/types/SecurityConfiguration.ts b/src/util/config/types/SecurityConfiguration.ts
new file mode 100644
index 00000000..405b86ac
--- /dev/null
+++ b/src/util/config/types/SecurityConfiguration.ts
@@ -0,0 +1,17 @@
+import crypto from "crypto";
+import { CaptchaConfiguration, TwoFactorConfiguration } from ".";
+
+export class SecurityConfiguration {
+ //classes
+ captcha: CaptchaConfiguration = new CaptchaConfiguration();
+ twoFactor: TwoFactorConfiguration = new TwoFactorConfiguration();
+ //base types
+ autoUpdate: boolean | number = true;
+ requestSignature: string = crypto.randomBytes(32).toString("base64");
+ jwtSecret: string = crypto.randomBytes(256).toString("base64");
+ // header to get the real user ip address
+ // X-Forwarded-For for nginx/reverse proxies
+ // CF-Connecting-IP for cloudflare
+ forwadedFor: string | null = null;
+ ipdataApiKey: string | null = "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9";
+}
diff --git a/src/util/config/types/SentryConfiguration.ts b/src/util/config/types/SentryConfiguration.ts
new file mode 100644
index 00000000..836094a1
--- /dev/null
+++ b/src/util/config/types/SentryConfiguration.ts
@@ -0,0 +1,8 @@
+import { hostname } from "os";
+
+export class SentryConfiguration {
+ enabled: boolean = false;
+ endpoint: string = "https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6";
+ traceSampleRate: number = 1.0;
+ environment: string = hostname();
+}
\ No newline at end of file
diff --git a/src/util/config/types/TemplateConfiguration.ts b/src/util/config/types/TemplateConfiguration.ts
new file mode 100644
index 00000000..4a9aa8f2
--- /dev/null
+++ b/src/util/config/types/TemplateConfiguration.ts
@@ -0,0 +1,6 @@
+export class TemplateConfiguration {
+ enabled: boolean = true;
+ allowTemplateCreation: boolean = true;
+ allowDiscordTemplates: boolean = true;
+ allowRaws: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/index.ts b/src/util/config/types/index.ts
new file mode 100644
index 00000000..608503a0
--- /dev/null
+++ b/src/util/config/types/index.ts
@@ -0,0 +1,18 @@
+export * from "./ApiConfiguration";
+export * from "./ClientConfiguration";
+export * from "./DefaultsConfiguration";
+export * from "./EndpointConfiguration";
+export * from "./GeneralConfiguration";
+export * from "./GifConfiguration";
+export * from "./GuildConfiguration";
+export * from "./KafkaConfiguration";
+export * from "./LimitConfigurations";
+export * from "./LoginConfiguration";
+export * from "./MetricsConfiguration";
+export * from "./RabbitMQConfiguration";
+export * from "./RegionConfiguration";
+export * from "./RegisterConfiguration";
+export * from "./SecurityConfiguration";
+export * from "./SentryConfiguration";
+export * from "./TemplateConfiguration";
+export * from "./subconfigurations/index";
diff --git a/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts b/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts
new file mode 100644
index 00000000..54e7f365
--- /dev/null
+++ b/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts
@@ -0,0 +1,4 @@
+export class ClientReleaseConfiguration {
+ useLocalRelease: boolean = true; //TODO
+ upstreamVersion: string = "0.0.264";
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/client/index.ts b/src/util/config/types/subconfigurations/client/index.ts
new file mode 100644
index 00000000..96bbb0ca
--- /dev/null
+++ b/src/util/config/types/subconfigurations/client/index.ts
@@ -0,0 +1 @@
+export * from "./ClientReleaseConfiguration";
diff --git a/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts b/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts
new file mode 100644
index 00000000..d6ff7697
--- /dev/null
+++ b/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts
@@ -0,0 +1,8 @@
+export class GuildDefaults {
+ maxPresences: number = 250000;
+ maxVideoChannelUsers: number = 200;
+ afkTimeout: number = 300;
+ defaultMessageNotifications: number = 1;
+ explicitContentFilter: number = 0;
+ test: number = 123;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/defaults/index.ts b/src/util/config/types/subconfigurations/defaults/index.ts
new file mode 100644
index 00000000..f40c5cd2
--- /dev/null
+++ b/src/util/config/types/subconfigurations/defaults/index.ts
@@ -0,0 +1 @@
+export * from "./GuildDefaults";
diff --git a/src/util/config/types/subconfigurations/guild/AutoJoin.ts b/src/util/config/types/subconfigurations/guild/AutoJoin.ts
new file mode 100644
index 00000000..47dfe5ec
--- /dev/null
+++ b/src/util/config/types/subconfigurations/guild/AutoJoin.ts
@@ -0,0 +1,5 @@
+export class AutoJoinConfiguration {
+ enabled: boolean = true;
+ guilds: string[] = [];
+ canLeave: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/guild/Discovery.ts b/src/util/config/types/subconfigurations/guild/Discovery.ts
new file mode 100644
index 00000000..59d8a8ae
--- /dev/null
+++ b/src/util/config/types/subconfigurations/guild/Discovery.ts
@@ -0,0 +1,6 @@
+export class DiscoveryConfiguration {
+ showAllGuilds: boolean = false;
+ useRecommendation: boolean = false; // TODO: Recommendation, privacy concern?
+ offset: number = 0;
+ limit: number = 24;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/guild/index.ts b/src/util/config/types/subconfigurations/guild/index.ts
new file mode 100644
index 00000000..e9614856
--- /dev/null
+++ b/src/util/config/types/subconfigurations/guild/index.ts
@@ -0,0 +1,2 @@
+export * from "./AutoJoin";
+export * from "./Discovery";
diff --git a/src/util/config/types/subconfigurations/index.ts b/src/util/config/types/subconfigurations/index.ts
new file mode 100644
index 00000000..bfbadc92
--- /dev/null
+++ b/src/util/config/types/subconfigurations/index.ts
@@ -0,0 +1,8 @@
+export * from "./client/index";
+export * from "./defaults/index";
+export * from "./guild/index";
+export * from "./kafka/index";
+export * from "./limits/index";
+export * from "./region/index";
+export * from "./register/index";
+export * from "./security/index";
diff --git a/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts b/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts
new file mode 100644
index 00000000..4f9a5e51
--- /dev/null
+++ b/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts
@@ -0,0 +1,4 @@
+export interface KafkaBroker {
+ ip: string;
+ port: number;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/kafka/index.ts b/src/util/config/types/subconfigurations/kafka/index.ts
new file mode 100644
index 00000000..2c633950
--- /dev/null
+++ b/src/util/config/types/subconfigurations/kafka/index.ts
@@ -0,0 +1 @@
+export * from "./KafkaBroker";
diff --git a/src/util/config/types/subconfigurations/limits/ChannelLimits.ts b/src/util/config/types/subconfigurations/limits/ChannelLimits.ts
new file mode 100644
index 00000000..2f8f9485
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ChannelLimits.ts
@@ -0,0 +1,5 @@
+export class ChannelLimits {
+ maxPins: number = 500;
+ maxTopic: number = 1024;
+ maxWebhooks: number = 100;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/GuildLimits.ts b/src/util/config/types/subconfigurations/limits/GuildLimits.ts
new file mode 100644
index 00000000..91ad39ae
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/GuildLimits.ts
@@ -0,0 +1,8 @@
+export class GuildLimits {
+ maxRoles: number = 1000;
+ maxEmojis: number = 2000;
+ maxMembers: number = 25000000;
+ maxChannels: number = 65535;
+ maxChannelsInCategory: number = 65535;
+ hideOfflineMember: number = 3;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/MessageLimits.ts b/src/util/config/types/subconfigurations/limits/MessageLimits.ts
new file mode 100644
index 00000000..51576b90
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/MessageLimits.ts
@@ -0,0 +1,8 @@
+export class MessageLimits {
+ maxCharacters: number = 1048576;
+ maxTTSCharacters: number = 160;
+ maxReactions: number = 2048;
+ maxAttachmentSize: number = 1024 * 1024 * 1024;
+ maxBulkDelete: number = 1000;
+ maxEmbedDownloadSize: number = 1024 * 1024 * 5;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/RateLimits.ts b/src/util/config/types/subconfigurations/limits/RateLimits.ts
new file mode 100644
index 00000000..25e7a1e0
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/RateLimits.ts
@@ -0,0 +1,18 @@
+import { RouteRateLimit, RateLimitOptions } from ".";
+
+export class RateLimits {
+ disabled: boolean = true;
+ ip: Omit<RateLimitOptions, "bot_count"> = {
+ count: 500,
+ window: 5
+ };
+ global: RateLimitOptions = {
+ count: 250,
+ window: 5
+ };
+ error: RateLimitOptions = {
+ count: 10,
+ window: 5
+ };
+ routes: RouteRateLimit;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/UserLimits.ts b/src/util/config/types/subconfigurations/limits/UserLimits.ts
new file mode 100644
index 00000000..0d10e0b3
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/UserLimits.ts
@@ -0,0 +1,5 @@
+export class UserLimits {
+ maxGuilds: number = 1048576;
+ maxUsername: number = 127;
+ maxFriends: number = 5000;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/index.ts b/src/util/config/types/subconfigurations/limits/index.ts
new file mode 100644
index 00000000..0b7304f6
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/index.ts
@@ -0,0 +1,6 @@
+export * from "./ChannelLimits";
+export * from "./GuildLimits";
+export * from "./MessageLimits";
+export * from "./RateLimits";
+export * from "./UserLimits";
+export * from "./ratelimits/index";
diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts b/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts
new file mode 100644
index 00000000..df171044
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts
@@ -0,0 +1,12 @@
+import { RateLimitOptions } from "./RateLimitOptions";
+
+export class AuthRateLimit {
+ login: RateLimitOptions = {
+ count: 5,
+ window: 60
+ };
+ register: RateLimitOptions = {
+ count: 2,
+ window: 60 * 60 * 12
+ };
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts b/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts
new file mode 100644
index 00000000..7089e28e
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts
@@ -0,0 +1,6 @@
+export interface RateLimitOptions {
+ bot?: number;
+ count: number;
+ window: number;
+ onyIp?: boolean;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts b/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts
new file mode 100644
index 00000000..3012a8a8
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts
@@ -0,0 +1,19 @@
+import { AuthRateLimit } from ".";
+import { RateLimitOptions } from "./RateLimitOptions";
+
+export class RouteRateLimit {
+ guild: RateLimitOptions = {
+ count: 5,
+ window: 5
+ };
+ webhook: RateLimitOptions = {
+ count: 10,
+ window: 5
+ };
+ channel: RateLimitOptions = {
+ count: 10,
+ window: 5
+ };
+ auth: AuthRateLimit;
+ // TODO: rate limit configuration for all routes
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/index.ts b/src/util/config/types/subconfigurations/limits/ratelimits/index.ts
new file mode 100644
index 00000000..432eb601
--- /dev/null
+++ b/src/util/config/types/subconfigurations/limits/ratelimits/index.ts
@@ -0,0 +1,3 @@
+export * from "./Auth";
+export * from "./RateLimitOptions";
+export * from "./Route";
diff --git a/src/util/config/types/subconfigurations/region/Region.ts b/src/util/config/types/subconfigurations/region/Region.ts
new file mode 100644
index 00000000..a8717e1f
--- /dev/null
+++ b/src/util/config/types/subconfigurations/region/Region.ts
@@ -0,0 +1,12 @@
+export interface Region {
+ id: string;
+ name: string;
+ endpoint: string;
+ location?: {
+ latitude: number;
+ longitude: number;
+ };
+ vip: boolean;
+ custom: boolean;
+ deprecated: boolean;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/region/index.ts b/src/util/config/types/subconfigurations/region/index.ts
new file mode 100644
index 00000000..2beb8de7
--- /dev/null
+++ b/src/util/config/types/subconfigurations/region/index.ts
@@ -0,0 +1 @@
+export * from "./Region";
diff --git a/src/util/config/types/subconfigurations/register/DateOfBirth.ts b/src/util/config/types/subconfigurations/register/DateOfBirth.ts
new file mode 100644
index 00000000..5a3c4e9d
--- /dev/null
+++ b/src/util/config/types/subconfigurations/register/DateOfBirth.ts
@@ -0,0 +1,4 @@
+export class DateOfBirthConfiguration {
+ required: boolean = true;
+ minimum: number = 13; // in years
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/register/Email.ts b/src/util/config/types/subconfigurations/register/Email.ts
new file mode 100644
index 00000000..115d49e0
--- /dev/null
+++ b/src/util/config/types/subconfigurations/register/Email.ts
@@ -0,0 +1,7 @@
+export class EmailConfiguration {
+ required: boolean = false;
+ allowlist: boolean = false;
+ blocklist: boolean = true;
+ domains: string[] = [];// TODO: efficiently save domain blocklist in database
+ // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"),
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/register/Password.ts b/src/util/config/types/subconfigurations/register/Password.ts
new file mode 100644
index 00000000..977473ac
--- /dev/null
+++ b/src/util/config/types/subconfigurations/register/Password.ts
@@ -0,0 +1,7 @@
+export class PasswordConfiguration {
+ required: boolean = false;
+ minLength: number = 8;
+ minNumbers: number = 2;
+ minUpperCase: number =2;
+ minSymbols: number = 0;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/register/index.ts b/src/util/config/types/subconfigurations/register/index.ts
new file mode 100644
index 00000000..d9738120
--- /dev/null
+++ b/src/util/config/types/subconfigurations/register/index.ts
@@ -0,0 +1,3 @@
+export * from "./DateOfBirth";
+export * from "./Email";
+export * from "./Password";
diff --git a/src/util/config/types/subconfigurations/security/Captcha.ts b/src/util/config/types/subconfigurations/security/Captcha.ts
new file mode 100644
index 00000000..ad6aa762
--- /dev/null
+++ b/src/util/config/types/subconfigurations/security/Captcha.ts
@@ -0,0 +1,6 @@
+export class CaptchaConfiguration {
+ enabled: boolean = false;
+ service: "recaptcha" | "hcaptcha" | null = null; // TODO: hcaptcha, custom
+ sitekey: string | null = null;
+ secret: string | null = null;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/security/TwoFactor.ts b/src/util/config/types/subconfigurations/security/TwoFactor.ts
new file mode 100644
index 00000000..33a47385
--- /dev/null
+++ b/src/util/config/types/subconfigurations/security/TwoFactor.ts
@@ -0,0 +1,3 @@
+export class TwoFactorConfiguration {
+ generateBackupCodes: boolean = true;
+}
\ No newline at end of file
diff --git a/src/util/config/types/subconfigurations/security/index.ts b/src/util/config/types/subconfigurations/security/index.ts
new file mode 100644
index 00000000..17619589
--- /dev/null
+++ b/src/util/config/types/subconfigurations/security/index.ts
@@ -0,0 +1,2 @@
+export * from "./Captcha";
+export * from "./TwoFactor";
diff --git a/src/util/entities/Config.ts b/src/util/entities/Config.ts
index 646737a0..fc33bb65 100644
--- a/src/util/entities/Config.ts
+++ b/src/util/entities/Config.ts
@@ -1,8 +1,5 @@
import { Column, Entity } from "typeorm";
import { BaseClassWithoutId, PrimaryIdColumn } from "./BaseClass";
-import crypto from "crypto";
-import { Snowflake } from "../util/Snowflake";
-import { hostname } from "os";
@Entity("config")
export class ConfigEntity extends BaseClassWithoutId {
@@ -12,414 +9,3 @@ export class ConfigEntity extends BaseClassWithoutId {
@Column({ type: "simple-json", nullable: true })
value: number | boolean | null | string | undefined;
}
-
-export interface RateLimitOptions {
- bot?: number;
- count: number;
- window: number;
- onyIp?: boolean;
-}
-
-export interface Region {
- id: string;
- name: string;
- endpoint: string;
- location?: {
- latitude: number;
- longitude: number;
- };
- vip: boolean;
- custom: boolean;
- deprecated: boolean;
-}
-
-export interface KafkaBroker {
- ip: string;
- port: number;
-}
-
-export interface ConfigValue {
- gateway: {
- endpointClient: string | null;
- endpointPrivate: string | null;
- endpointPublic: string | null;
- };
- cdn: {
- endpointClient: string | null;
- endpointPublic: string | null;
- endpointPrivate: string | null;
- resizeHeightMax: number | null;
- resizeWidthMax: number | null;
- imagorServerUrl: string | null;
- };
- api: {
- defaultVersion: string;
- activeVersions: string[];
- useFosscordEnhancements: boolean;
- };
- general: {
- instanceName: string;
- instanceDescription: string | null;
- frontPage: string | null;
- tosPage: string | null;
- correspondenceEmail: string | null;
- correspondenceUserID: string | null;
- image: string | null;
- instanceId: string;
- };
- limits: {
- user: {
- maxGuilds: number;
- maxUsername: number;
- maxFriends: number;
- };
- guild: {
- maxRoles: number;
- maxEmojis: number;
- maxMembers: number;
- maxChannels: number;
- maxChannelsInCategory: number;
- hideOfflineMember: number;
- };
- message: {
- maxCharacters: number;
- maxTTSCharacters: number;
- maxReactions: number;
- maxAttachmentSize: number;
- maxBulkDelete: number;
- maxEmbedDownloadSize: number;
- };
- channel: {
- maxPins: number;
- maxTopic: number;
- maxWebhooks: number;
- };
- rate: {
- disabled: boolean;
- ip: Omit<RateLimitOptions, "bot_count">;
- global: RateLimitOptions;
- error: RateLimitOptions;
- routes: {
- guild: RateLimitOptions;
- webhook: RateLimitOptions;
- channel: RateLimitOptions;
- auth: {
- login: RateLimitOptions;
- register: RateLimitOptions;
- };
- // TODO: rate limit configuration for all routes
- };
- };
- };
- security: {
- autoUpdate: boolean | number;
- requestSignature: string;
- jwtSecret: string;
- forwadedFor: string | null; // header to get the real user ip address
- captcha: {
- enabled: boolean;
- service: "recaptcha" | "hcaptcha" | null; // TODO: hcaptcha, custom
- sitekey: string | null;
- secret: string | null;
- };
- ipdataApiKey: string | null;
- defaultRights: string;
- };
- login: {
- requireCaptcha: boolean;
- };
- register: {
- email: {
- required: boolean;
- allowlist: boolean;
- blocklist: boolean;
- domains: string[];
- };
- dateOfBirth: {
- required: boolean;
- minimum: number; // in years
- };
- disabled: boolean;
- requireCaptcha: boolean;
- requireInvite: boolean;
- guestsRequireInvite: boolean;
- allowNewRegistration: boolean;
- allowMultipleAccounts: boolean;
- blockProxies: boolean;
- password: {
- required: boolean;
- minLength: number;
- minNumbers: number;
- minUpperCase: number;
- minSymbols: number;
- };
- incrementingDiscriminators: boolean; // random otherwise
- };
- regions: {
- default: string;
- useDefaultAsOptimal: boolean;
- available: Region[];
- };
- guild: {
- discovery: {
- showAllGuilds: boolean;
- useRecommendation: boolean; // TODO: Recommendation, privacy concern?
- offset: number;
- limit: number;
- };
- autoJoin: {
- enabled: boolean;
- guilds: string[];
- canLeave: boolean;
- };
- defaultFeatures: string[];
- };
- gif: {
- enabled: boolean;
- provider: "tenor"; // more coming soon
- apiKey?: string;
- };
- rabbitmq: {
- host: string | null;
- };
- kafka: {
- brokers: KafkaBroker[] | null;
- };
- templates: {
- enabled: Boolean;
- allowTemplateCreation: Boolean;
- allowDiscordTemplates: Boolean;
- allowRaws: Boolean;
- };
- client: {
- useTestClient: Boolean;
- releases: {
- useLocalRelease: Boolean; //TODO
- upstreamVersion: string;
- };
- };
- metrics: {
- timeout: number;
- };
- sentry: {
- enabled: boolean;
- endpoint: string;
- traceSampleRate: number;
- environment: string;
- };
- external: {
- twitter: string | null;
- };
-}
-
-export const DefaultConfigOptions: ConfigValue = {
- gateway: {
- endpointClient: null,
- endpointPrivate: null,
- endpointPublic: null,
- },
- cdn: {
- endpointClient: null,
- endpointPrivate: null,
- endpointPublic: null,
- resizeHeightMax: 1000,
- resizeWidthMax: 1000,
- imagorServerUrl: null,
- },
- api: {
- defaultVersion: "9",
- activeVersions: ["6", "7", "8", "9"],
- useFosscordEnhancements: true,
- },
- general: {
- instanceName: "Fosscord Instance",
- instanceDescription:
- "This is a Fosscord instance made in pre-release days",
- frontPage: null,
- tosPage: null,
- correspondenceEmail: "noreply@localhost.local",
- correspondenceUserID: null,
- image: null,
- instanceId: Snowflake.generate(),
- },
- limits: {
- user: {
- maxGuilds: 1048576,
- maxUsername: 127,
- maxFriends: 5000,
- },
- guild: {
- maxRoles: 1000,
- maxEmojis: 2000,
- maxMembers: 25000000,
- maxChannels: 65535,
- maxChannelsInCategory: 65535,
- hideOfflineMember: 3,
- },
- message: {
- maxCharacters: 1048576,
- maxTTSCharacters: 160,
- maxReactions: 2048,
- maxAttachmentSize: 1024 * 1024 * 1024,
- maxEmbedDownloadSize: 1024 * 1024 * 5,
- maxBulkDelete: 1000,
- },
- channel: {
- maxPins: 500,
- maxTopic: 1024,
- maxWebhooks: 100,
- },
- rate: {
- disabled: true,
- ip: {
- count: 500,
- window: 5,
- },
- global: {
- count: 250,
- window: 5,
- },
- error: {
- count: 10,
- window: 5,
- },
- routes: {
- guild: {
- count: 5,
- window: 5,
- },
- webhook: {
- count: 10,
- window: 5,
- },
- channel: {
- count: 10,
- window: 5,
- },
- auth: {
- login: {
- count: 5,
- window: 60,
- },
- register: {
- count: 2,
- window: 60 * 60 * 12,
- },
- },
- },
- },
- },
- security: {
- autoUpdate: true,
- requestSignature: crypto.randomBytes(32).toString("base64"),
- jwtSecret: crypto.randomBytes(256).toString("base64"),
- forwadedFor: null,
- // forwadedFor: "X-Forwarded-For" // nginx/reverse proxy
- // forwadedFor: "CF-Connecting-IP" // cloudflare:
- captcha: {
- enabled: false,
- service: null,
- sitekey: null,
- secret: null,
- },
- ipdataApiKey:
- "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9",
- defaultRights: "30644591655940", // See `npm run generate:rights`
- },
- login: {
- requireCaptcha: false,
- },
- register: {
- email: {
- required: false,
- allowlist: false,
- blocklist: true,
- domains: [], // TODO: efficiently save domain blocklist in database
- // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"),
- },
- dateOfBirth: {
- required: true,
- minimum: 13,
- },
- disabled: false,
- requireInvite: false,
- guestsRequireInvite: true,
- requireCaptcha: true,
- allowNewRegistration: true,
- allowMultipleAccounts: true,
- blockProxies: true,
- password: {
- required: false,
- minLength: 8,
- minNumbers: 2,
- minUpperCase: 2,
- minSymbols: 0,
- },
- incrementingDiscriminators: false,
- },
- regions: {
- default: "fosscord",
- useDefaultAsOptimal: true,
- available: [
- {
- id: "fosscord",
- name: "Fosscord",
- endpoint: "127.0.0.1:3004",
- vip: false,
- custom: false,
- deprecated: false,
- },
- ],
- },
- guild: {
- discovery: {
- showAllGuilds: false,
- useRecommendation: false,
- offset: 0,
- limit: 24,
- },
- autoJoin: {
- enabled: true,
- canLeave: true,
- guilds: [],
- },
- defaultFeatures: [],
- },
- gif: {
- enabled: true,
- provider: "tenor",
- apiKey: "LIVDSRZULELA",
- },
- rabbitmq: {
- host: null,
- },
- kafka: {
- brokers: null,
- },
- templates: {
- enabled: true,
- allowTemplateCreation: true,
- allowDiscordTemplates: true,
- allowRaws: false,
- },
- client: {
- useTestClient: true,
- releases: {
- useLocalRelease: true,
- upstreamVersion: "0.0.264",
- },
- },
- metrics: {
- timeout: 30000,
- },
- sentry: {
- enabled: false,
- endpoint:
- "https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6",
- traceSampleRate: 1.0,
- environment: hostname(),
- },
- external: {
- twitter: null,
- }
-};
diff --git a/src/util/util/Config.ts b/src/util/util/Config.ts
index 55d7fab1..ff2feb36 100644
--- a/src/util/util/Config.ts
+++ b/src/util/util/Config.ts
@@ -1,11 +1,6 @@
-import "missing-native-js-functions";
-import {
- ConfigValue,
- ConfigEntity,
- DefaultConfigOptions,
-} from "../entities/Config";
-import path from "path";
+import { ConfigEntity } from "../entities/Config";
import fs from "fs";
+import { ConfigValue } from "../config";
// TODO: yaml instead of json
const overridePath = process.env.CONFIG_PATH ?? "";
@@ -19,9 +14,10 @@ var pairs: ConfigEntity[];
export const Config = {
init: async function init() {
if (config) return config;
+ console.log('[Config] Loading configuration...')
pairs = await ConfigEntity.find();
config = pairsToConfig(pairs);
- config = (config || {}).merge(DefaultConfigOptions);
+ config = (config || {}).merge(new ConfigValue());
if (process.env.CONFIG_PATH) {
console.log(`[Config] Using config path from environment rather than database.`);
|