diff --git a/packages/api/utils/feature-flags.ts b/packages/api/utils/feature-flags.ts new file mode 100644 index 0000000..4764b34 --- /dev/null +++ b/packages/api/utils/feature-flags.ts @@ -0,0 +1,38 @@ +import { hasFeature } from '@roleypoly/misc-utils/hasFeature'; +import { Features, Guild, GuildData } from '@roleypoly/types'; + +const flagPercents: Record = { + [Features.AuditLogging]: { percent: 0, rotation: 0 }, + [Features.AccessControl]: { percent: 0, rotation: 33 }, +}; + +const testingGroup: Guild['id'][] = [ + '386659935687147521', // Roleypoly +]; + +const ONE_HUNDRED = BigInt(100); + +export const getFeatureFlags = ( + feature: Features, + guildData: GuildData +): Record => { + const flags = Object.entries(flagPercents).map(([flag, value]) => { + const intFlag = Number(flag); + const intGuildID = BigInt(guildData.id); + const rotation = BigInt(value.rotation); + const percent = BigInt(value.percent); + + if (testingGroup.includes(guildData.id)) { + return [intFlag, true]; + } + + const percentValue = (intGuildID + rotation) % ONE_HUNDRED; + if (percentValue >= percent) { + return [intFlag, true]; + } + + return [intFlag, hasFeature(feature, intFlag)]; + }); + + return Object.fromEntries(flags); +}; diff --git a/packages/misc-utils/hasFeature.spec.ts b/packages/misc-utils/hasFeature.spec.ts new file mode 100644 index 0000000..2151dba --- /dev/null +++ b/packages/misc-utils/hasFeature.spec.ts @@ -0,0 +1,8 @@ +import { Features } from '@roleypoly/types'; +import { hasFeature } from './hasFeature'; + +it('correctly matches against features', () => { + const features = Features.LegacyGuild; + expect(hasFeature(Features.LegacyGuild, features)).toBe(true); + expect(hasFeature(Features.LegacyGuild, Features.None)).toBe(false); +}); diff --git a/packages/misc-utils/hasFeature.ts b/packages/misc-utils/hasFeature.ts new file mode 100644 index 0000000..fc4c34e --- /dev/null +++ b/packages/misc-utils/hasFeature.ts @@ -0,0 +1,5 @@ +import { Features } from '@roleypoly/types'; + +export const hasFeature = (feature: Features, features: number): boolean => { + return (features & feature) === feature; +}; diff --git a/packages/types/Guild.ts b/packages/types/Guild.ts index ee9a19f..fb2a6e4 100644 --- a/packages/types/Guild.ts +++ b/packages/types/Guild.ts @@ -13,6 +13,8 @@ export enum Features { None = 0, Preview = None, LegacyGuild = 1 << 1, + AccessControl = 1 << 2, + AuditLogging = 1 << 3, } export type GuildData = {