summary refs log tree commit diff
path: root/rtc/src/models/User.ts
blob: c667e954c0daceac36e25c3ea425191856cc492c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
import { Activity, ActivitySchema } from "./Activity";
import { ClientStatus, Status } from "./Status";
import { Schema, Types, Document } from "mongoose";
import db from "../util/Database";
import toBigInt from "../util/toBigInt";

export const PublicUserProjection = {
	username: true,
	discriminator: true,
	id: true,
	public_flags: true,
	avatar: true,
	accent_color: true,
	banner: true,
	bio: true,
	bot: true,
};

export interface User {
	id: string;
	username: string; // username max length 32, min 2
	discriminator: string; // #0001 4 digit long string from #0001 - #9999
	avatar: string | null; // hash of the user avatar
	accent_color: number | null; // banner color of user
	banner: string | null;
	phone: string | null; // phone number of the user
	desktop: boolean; // if the user has desktop app installed
	mobile: boolean; // if the user has mobile app installed
	premium: boolean; // if user bought nitro
	premium_type: number; // nitro level
	bot: boolean; // if user is bot
	bio: string; // short description of the user (max 190 chars)
	system: boolean; // shouldn't be used, the api sents this field type true, if the genetaed message comes from a system generated author
	nsfw_allowed: boolean; // if the user is older than 18 (resp. Config)
	mfa_enabled: boolean; // if multi factor authentication is enabled
	created_at: Date; // registration date
	verified: boolean; // if the user is offically verified
	disabled: boolean; // if the account is disabled
	deleted: boolean; // if the user was deleted
	email: string | null; // email of the user
	flags: bigint; // UserFlags
	public_flags: bigint;
	user_settings: UserSettings;
	guilds: string[]; // array of guild ids the user is part of
	user_data: UserData;
	presence: {
		status: Status;
		activities: Activity[];
		client_status: ClientStatus;
	};
}

// Private user data:
export interface UserData {
	valid_tokens_since: Date; // all tokens with a previous issue date are invalid
	relationships: Relationship[];
	connected_accounts: ConnectedAccount[];
	hash: string; // hash of the password, salt is saved in password (bcrypt)
	fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
}

export interface UserDocument extends User, Document {
	id: string;
}

export interface PublicUser {
	id: string;
	discriminator: string;
	username: string;
	avatar: string | null;
	accent_color: number;
	banner: string | null;
	public_flags: bigint;
	bot: boolean;
}

export interface ConnectedAccount {
	access_token: string;
	friend_sync: boolean;
	id: string;
	name: string;
	revoked: boolean;
	show_activity: boolean;
	type: string;
	verifie: boolean;
	visibility: number;
}

export interface Relationship {
	id: string;
	nickname?: string;
	type: RelationshipType;
}

export enum RelationshipType {
	outgoing = 4,
	incoming = 3,
	blocked = 2,
	friends = 1,
}

export interface UserSettings {
	afk_timeout: number;
	allow_accessibility_detection: boolean;
	animate_emoji: boolean;
	animate_stickers: number;
	contact_sync_enabled: boolean;
	convert_emoticons: boolean;
	custom_status: {
		emoji_id: string | null;
		emoji_name: string | null;
		expires_at: number | null;
		text: string | null;
	};
	default_guilds_restricted: boolean;
	detect_platform_accounts: boolean;
	developer_mode: boolean;
	disable_games_tab: boolean;
	enable_tts_command: boolean;
	explicit_content_filter: number;
	friend_source_flags: { all: boolean };
	gateway_connected: boolean;
	gif_auto_play: boolean;
	guild_folders: // every top guild is displayed as a "folder"
	{
		color: number;
		guild_ids: string[];
		id: number;
		name: string;
	}[];
	guild_positions: string[]; // guild ids ordered by position
	inline_attachment_media: boolean;
	inline_embed_media: boolean;
	locale: string; // en_US
	message_display_compact: boolean;
	native_phone_integration_enabled: boolean;
	render_embeds: boolean;
	render_reactions: boolean;
	restricted_guilds: string[];
	show_current_game: boolean;
	status: "online" | "offline" | "dnd" | "idle";
	stream_notifications_enabled: boolean;
	theme: "dark" | "white"; // dark
	timezone_offset: number; // e.g -60
}

export const UserSchema = new Schema({
	id: String,
	username: String,
	discriminator: String,
	avatar: String,
	accent_color: Number,
	banner: String,
	phone: String,
	desktop: Boolean,
	mobile: Boolean,
	premium: Boolean,
	premium_type: Number,
	bot: Boolean,
	bio: String,
	system: Boolean,
	nsfw_allowed: Boolean,
	mfa_enabled: Boolean,
	created_at: Date,
	verified: Boolean,
	disabled: Boolean,
	deleted: Boolean,
	email: String,
	flags: { type: String, get: toBigInt }, // TODO: automatically convert Types.Long to BitField of UserFlags
	public_flags: { type: String, get: toBigInt },
	guilds: [String], // array of guild ids the user is part of
	user_data: {
		fingerprints: [String],
		hash: String, // hash of the password, salt is saved in password (bcrypt)
		valid_tokens_since: Date, // all tokens with a previous issue date are invalid
		relationships: [
			{
				id: { type: String, required: true },
				nickname: String,
				type: { type: Number },
			},
		],
		connected_accounts: [
			{
				access_token: String,
				friend_sync: Boolean,
				id: String,
				name: String,
				revoked: Boolean,
				show_activity: Boolean,
				type: { type: String },
				verifie: Boolean,
				visibility: Number,
			},
		],
	},
	user_settings: {
		afk_timeout: Number,
		allow_accessibility_detection: Boolean,
		animate_emoji: Boolean,
		animate_stickers: Number,
		contact_sync_enabled: Boolean,
		convert_emoticons: Boolean,
		custom_status: {
			emoji_id: String,
			emoji_name: String,
			expires_at: Number,
			text: String,
		},
		default_guilds_restricted: Boolean,
		detect_platform_accounts: Boolean,
		developer_mode: Boolean,
		disable_games_tab: Boolean,
		enable_tts_command: Boolean,
		explicit_content_filter: Number,
		friend_source_flags: { all: Boolean },
		gateway_connected: Boolean,
		gif_auto_play: Boolean,
		// every top guild is displayed as a "folder"
		guild_folders: [
			{
				color: Number,
				guild_ids: [String],
				id: Number,
				name: String,
			},
		],
		guild_positions: [String], // guild ids ordered by position
		inline_attachment_media: Boolean,
		inline_embed_media: Boolean,
		locale: String, // en_US
		message_display_compact: Boolean,
		native_phone_integration_enabled: Boolean,
		render_embeds: Boolean,
		render_reactions: Boolean,
		restricted_guilds: [String],
		show_current_game: Boolean,
		status: String,
		stream_notifications_enabled: Boolean,
		theme: String, // dark
		timezone_offset: Number, // e.g -60,
	},

	presence: {
		status: String,
		activities: [ActivitySchema],
		client_status: ClientStatus,
	},
});

// @ts-ignore
export const UserModel = db.model<UserDocument>("User", UserSchema, "users");