Newer
Older
percord / src / schemas / api / users / User.ts
@Rory& Rory& on 25 Nov 5 KB add missing user flags
/*
	Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
	Copyright (C) 2025 Spacebar and Spacebar Contributors

	This program 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.

	This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
*/

import { ConnectedAccountSchema, Snowflake, UserSettingsSchema } from "@spacebar/schemas";
import { BitField } from "@spacebar/util/util";
import { Relationship, Session } from "@spacebar/util/entities";

interface UserEntityPleaseRewriteThankYou {
	id: Snowflake;
	username: string;
	discriminator: string;
	avatar?: string;
	accent_color?: number;
	banner?: string;
	theme_colors?: number[];
	pronouns?: string;
	phone?: string;
	desktop: boolean;
	mobile: boolean;
	premium: boolean;
	premium_type: number;
	bot: boolean;
	bio: string;
	system: boolean;
	nsfw_allowed: boolean;
	mfa_enabled: boolean;
	webauthn_enabled: boolean;
	created_at: Date;
	premium_since: Date;
	verified: boolean;
	disabled: boolean;
	deleted: boolean;
	email?: string;
	flags: number;
	public_flags: number;
	purchased_flags: number;
	premium_usage_flags: number;
	rights: string;
	sessions: Session[];
	relationships: Relationship[];
	connected_accounts: ConnectedAccountSchema[];
	fingerprints: string[];
	settings?: UserSettingsSchema;
	extended_settings: string;
	badge_ids?: string[];
}

export interface PartialUser {
	id: Snowflake;
	username: string;
	discriminator: string;
	global_name?: string | null;
	avatar: string | null;
	avatar_decoration_data?: AvatarDecorationData | null;
	collectibles?: Collectibles | null;
	display_name_styles?: DisplayNameStyle | null;
	primary_guild?: PrimaryGuild | null;
	bot?: boolean;
	system?: boolean;
	banner?: string | null;
	accent_color?: number | null;
	public_flags?: number;
}

export interface AvatarDecorationData {
	asset: string;
	sku_id: Snowflake;
	expires_at: string | null;
}

export interface Collectibles {
	nameplate: NameplateData | null;
}

export interface NameplateData {
	asset: string;
	sku_id: Snowflake;
	label: string;
	palette: string;
	expires_at: number | null;
}

export interface DisplayNameStyle {
	font_id: number;
	effect_id: number;
	colors: number;
}

export interface PrimaryGuild {
	identity_enabled: boolean | null;
	identity_guild_id: Snowflake | null;
	tag: string | null;
	badge: string | null;
}

export enum PublicUserEnum {
	username,
	discriminator,
	id,
	public_flags,
	avatar,
	accent_color,
	banner,
	bio,
	bot,
	premium_since,
	premium_type,
	theme_colors,
	pronouns,
	badge_ids,
}
export type PublicUserKeys = keyof typeof PublicUserEnum;

export enum PrivateUserEnum {
	flags,
	mfa_enabled,
	email,
	phone,
	verified,
	nsfw_allowed,
	premium,
	premium_type,
	purchased_flags,
	premium_usage_flags,
	disabled,
	settings,
	// locale
}

export type PrivateUserKeys = keyof typeof PrivateUserEnum | PublicUserKeys;

export const PublicUserProjection = Object.values(PublicUserEnum).filter((x) => typeof x === "string") as PublicUserKeys[];
export const PrivateUserProjection = [...PublicUserProjection, ...Object.values(PrivateUserEnum).filter((x) => typeof x === "string")] as PrivateUserKeys[];

// Private user data that should never get sent to the client
export type PublicUser = Pick<UserEntityPleaseRewriteThankYou, PublicUserKeys>;
export type PrivateUser = Pick<UserEntityPleaseRewriteThankYou, PrivateUserKeys>;

export interface UserPrivate extends Pick<UserEntityPleaseRewriteThankYou, PrivateUserKeys> {
	locale: string;
}

// This causes a failure in openapi.js...?
export class UserFlags extends BitField {
	static FLAGS = {
		DISCORD_EMPLOYEE: 1n << 0n,
		PARTNERED_SERVER_OWNER: 1n << 1n,
		HYPESQUAD_EVENTS: 1n << 2n,
		BUGHUNTER_LEVEL_1: 1n << 3n,
		MFA_SMS: 1n << 4n,
		PREMIUM_PROMO_DISMISSED: 1n << 5n,
		HOUSE_BRAVERY: 1n << 6n,
		HOUSE_BRILLIANCE: 1n << 7n,
		HOUSE_BALANCE: 1n << 8n,
		EARLY_SUPPORTER: 1n << 9n,
		TEAM_USER: 1n << 10n,
		TRUST_AND_SAFETY: 1n << 11n,
		SYSTEM: 1n << 12n,
		HAS_UNREAD_URGENT_MESSAGES: 1n << 13n,
		BUGHUNTER_LEVEL_2: 1n << 14n,
		UNDERAGE_DELETED: 1n << 15n,
		VERIFIED_BOT: 1n << 16n,
		EARLY_VERIFIED_BOT_DEVELOPER: 1n << 17n,
		CERTIFIED_MODERATOR: 1n << 18n,
		BOT_HTTP_INTERACTIONS: 1n << 19n,
		SPAMMER: 1n << 20n,
		// @deprecated
		DISABLE_PREMIUM: 1n << 21n,
		ACTIVE_DEVELOPER: 1n << 22n,
		PROVISIONAL_ACCOUNT: 1n << 23n,
		// Where did 24-32 go???
		HIGH_GLOBAL_RATE_LIMIT: 1n << 33n,
		DELETED: 1n << 34n,
		DISABLED_SUSPICIOUS_ACCOUNT: 1n << 35n,
		SELF_DELETED: 1n << 36n,
		PREMIUM_DISCIRMINATOR: 1n << 37n,
		USED_DESKTOP_CLIENT: 1n << 38n,
		USED_WEB_CLIENT: 1n << 39n,
		USED_MOBILE_CLIENT: 1n << 40n,
		DISABLED: 1n << 41n,
		// 42 is unknown...
		HAS_SESSION_STARTED: 1n << 43n,
		QUARANTINED: 1n << 44n,
		// 45 and 46 are unknown...
		PREMIUM_ELEGIBLE_FOR_UNIQUE_USERNAME: 1n << 47n,
		// 48 and 49 are unknown...
		COLLABORATOR: 1n << 50n,
		RESTRICTED_COLLABORATOR: 1n << 51n,
	};
}