mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-22 02:12:40 +01:00
initial pomelo implementation
This commit is contained in:
parent
b0989ff88c
commit
9f4f7cac65
@ -1359,6 +1359,12 @@
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"discriminator": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -1524,6 +1530,9 @@
|
||||
"$ref": "#/components/schemas/SecurityKey"
|
||||
}
|
||||
},
|
||||
"handle": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
@ -1541,6 +1550,8 @@
|
||||
"extended_settings",
|
||||
"fingerprints",
|
||||
"flags",
|
||||
"global_name",
|
||||
"handle",
|
||||
"id",
|
||||
"mfa_enabled",
|
||||
"mobile",
|
||||
@ -3486,6 +3497,12 @@
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"discriminator": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -3521,6 +3538,7 @@
|
||||
"bio",
|
||||
"bot",
|
||||
"discriminator",
|
||||
"global_name",
|
||||
"id",
|
||||
"premium_since",
|
||||
"premium_type",
|
||||
@ -3946,25 +3964,32 @@
|
||||
"MinimalPublicUserDTO": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"avatar": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"discriminator": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"discriminator": {
|
||||
"type": "string"
|
||||
},
|
||||
"public_flags": {
|
||||
"type": "integer"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
"avatar": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"discriminator",
|
||||
"global_name",
|
||||
"id",
|
||||
"public_flags",
|
||||
"username"
|
||||
@ -6355,6 +6380,15 @@
|
||||
"discriminator": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -6372,6 +6406,8 @@
|
||||
"required": [
|
||||
"avatar",
|
||||
"discriminator",
|
||||
"display_name",
|
||||
"global_name",
|
||||
"id",
|
||||
"public_flags",
|
||||
"username"
|
||||
@ -6615,6 +6651,15 @@
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"discriminator": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -6636,6 +6681,8 @@
|
||||
"avatar",
|
||||
"avatar_url",
|
||||
"discriminator",
|
||||
"display_name",
|
||||
"global_name",
|
||||
"id",
|
||||
"status",
|
||||
"username"
|
||||
@ -6997,6 +7044,12 @@
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"discriminator": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -7058,6 +7111,7 @@
|
||||
"disabled",
|
||||
"discriminator",
|
||||
"flags",
|
||||
"global_name",
|
||||
"id",
|
||||
"mfa_enabled",
|
||||
"nsfw_allowed",
|
||||
@ -7114,6 +7168,12 @@
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"discriminator": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -7175,6 +7235,7 @@
|
||||
"disabled",
|
||||
"discriminator",
|
||||
"flags",
|
||||
"global_name",
|
||||
"id",
|
||||
"mfa_enabled",
|
||||
"nsfw_allowed",
|
||||
@ -7273,6 +7334,10 @@
|
||||
"autoCreateBotUsers": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"pomeloEnabled": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@ -7284,6 +7349,7 @@
|
||||
"instanceDescription",
|
||||
"instanceId",
|
||||
"instanceName",
|
||||
"pomeloEnabled",
|
||||
"tosPage"
|
||||
]
|
||||
},
|
||||
@ -7845,6 +7911,12 @@
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"global_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"discriminator": {
|
||||
"type": "string"
|
||||
},
|
||||
@ -7857,6 +7929,7 @@
|
||||
},
|
||||
"required": [
|
||||
"discriminator",
|
||||
"global_name",
|
||||
"id",
|
||||
"public_flags",
|
||||
"username"
|
||||
|
5808
assets/schemas.json
5808
assets/schemas.json
File diff suppressed because it is too large
Load Diff
@ -111,7 +111,7 @@ router.post(
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
`Failed to send password reset email to ${user.username}#${user.discriminator}: ${e}`,
|
||||
`Failed to send password reset email to ${user.handle}: ${e}`,
|
||||
);
|
||||
throw new HTTPError("Failed to send password reset email", 500);
|
||||
});
|
||||
|
@ -43,6 +43,7 @@ router.post(
|
||||
username: "",
|
||||
avatar: "",
|
||||
discriminator: "",
|
||||
global_name: "",
|
||||
public_flags: 64,
|
||||
},
|
||||
attachments: [],
|
||||
|
@ -171,11 +171,14 @@ router.get(
|
||||
if ((y.user_ids || []).includes(req.user_id)) y.me = true;
|
||||
delete y.user_ids;
|
||||
});
|
||||
const { pomeloEnabled } = Config.get().general;
|
||||
if (!x.author)
|
||||
x.author = User.create({
|
||||
id: "4",
|
||||
discriminator: "0000",
|
||||
discriminator: pomeloEnabled ? "0" : "0000",
|
||||
username: "Spacebar Ghost",
|
||||
global_name: "spacebarghost",
|
||||
display_name: "Spacebar Ghost",
|
||||
public_flags: 0,
|
||||
});
|
||||
x.attachments?.forEach((y: Attachment) => {
|
||||
|
@ -70,6 +70,8 @@ router.get(
|
||||
user: {
|
||||
username: user.username,
|
||||
discriminator: user.discriminator,
|
||||
global_name: user.global_name,
|
||||
display_name: user.display_name,
|
||||
id: user.id,
|
||||
avatar: user.avatar,
|
||||
public_flags: user.public_flags,
|
||||
|
@ -149,6 +149,8 @@ router.get(
|
||||
avatar: x.author?.avatar,
|
||||
avatar_decoration: null,
|
||||
discriminator: x.author?.discriminator,
|
||||
global_name: x.author?.global_name,
|
||||
display_name: x.author?.display_name,
|
||||
public_flags: x.author?.public_flags,
|
||||
},
|
||||
attachments: x.attachments,
|
||||
|
@ -89,6 +89,8 @@ router.get(
|
||||
"username",
|
||||
"avatar",
|
||||
"discriminator",
|
||||
"global_name",
|
||||
"display_name",
|
||||
"public_flags",
|
||||
],
|
||||
});
|
||||
@ -137,6 +139,8 @@ router.get(
|
||||
avatar: user.avatar,
|
||||
avatar_decoration: null, // TODO
|
||||
discriminator: user.discriminator,
|
||||
global_name: user.global_name,
|
||||
display_name: user.display_name,
|
||||
public_flags: user.public_flags,
|
||||
},
|
||||
application: {
|
||||
@ -159,6 +163,8 @@ router.get(
|
||||
avatar: bot.avatar,
|
||||
avatar_decoration: null, // TODO
|
||||
discriminator: bot.discriminator,
|
||||
global_name: bot.global_name,
|
||||
display_name: bot.display_name,
|
||||
public_flags: bot.public_flags,
|
||||
bot: true,
|
||||
approximated_guild_count: 0, // TODO
|
||||
|
@ -58,6 +58,8 @@ router.get(
|
||||
username: relation_user.username,
|
||||
avatar: relation_user.avatar,
|
||||
discriminator: relation_user.discriminator,
|
||||
global_name: relation_user.global_name,
|
||||
display_name: relation_user.display_name,
|
||||
public_flags: relation_user.public_flags,
|
||||
});
|
||||
}
|
||||
|
@ -140,6 +140,7 @@ router.patch(
|
||||
newToken = (await generateToken(user.id)) as string;
|
||||
}
|
||||
|
||||
// TODO: pomelo: disallow if pomelo is enabled
|
||||
if (body.username) {
|
||||
const check_username = body?.username?.replace(/\s/g, "");
|
||||
if (!check_username) {
|
||||
@ -162,6 +163,7 @@ router.patch(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: pomelo: disallow if pomelo is enabled
|
||||
if (body.discriminator) {
|
||||
if (
|
||||
await User.findOne({
|
||||
|
@ -114,19 +114,26 @@ router.post(
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
const { pomeloEnabled } = Config.get().general;
|
||||
const where = pomeloEnabled
|
||||
? {
|
||||
// TODO: pomelo: should we use username or add global_name property to the request?
|
||||
global_name: req.body.username,
|
||||
}
|
||||
: {
|
||||
discriminator: String(req.body.discriminator).padStart(
|
||||
4,
|
||||
"0",
|
||||
), //Discord send the discriminator as integer, we need to add leading zeroes
|
||||
username: req.body.username,
|
||||
};
|
||||
return await updateRelationship(
|
||||
req,
|
||||
res,
|
||||
await User.findOneOrFail({
|
||||
relations: ["relationships", "relationships.to"],
|
||||
select: userProjection,
|
||||
where: {
|
||||
discriminator: String(req.body.discriminator).padStart(
|
||||
4,
|
||||
"0",
|
||||
), //Discord send the discriminator as integer, we need to add leading zeroes
|
||||
username: req.body.username,
|
||||
},
|
||||
where,
|
||||
}),
|
||||
req.body.type,
|
||||
);
|
||||
|
@ -31,6 +31,8 @@ interface UserResponse {
|
||||
id: string;
|
||||
username: string;
|
||||
discriminator: string;
|
||||
global_name: string;
|
||||
display_name?: string;
|
||||
avatar_url: string | null;
|
||||
}
|
||||
|
||||
@ -128,6 +130,7 @@ export default class DiscordConnection extends Connection {
|
||||
|
||||
if (exists) return null;
|
||||
|
||||
// TODO: pomelo
|
||||
return await this.createConnection({
|
||||
user_id: userId,
|
||||
external_id: userInfo.id,
|
||||
|
@ -29,4 +29,5 @@ export class GeneralConfiguration {
|
||||
image: string | null = null;
|
||||
instanceId: string = Snowflake.generate();
|
||||
autoCreateBotUsers: boolean = false;
|
||||
pomeloEnabled: boolean = false;
|
||||
}
|
||||
|
@ -19,17 +19,21 @@
|
||||
import { User } from "../entities";
|
||||
|
||||
export class MinimalPublicUserDTO {
|
||||
avatar?: string | null;
|
||||
discriminator: string;
|
||||
id: string;
|
||||
public_flags: number;
|
||||
username: string;
|
||||
global_name: string;
|
||||
display_name?: string;
|
||||
discriminator: string;
|
||||
public_flags: number;
|
||||
avatar?: string | null;
|
||||
|
||||
constructor(user: User) {
|
||||
this.avatar = user.avatar;
|
||||
this.discriminator = user.discriminator;
|
||||
this.id = user.id;
|
||||
this.public_flags = user.public_flags;
|
||||
this.username = user.username;
|
||||
this.global_name = user.global_name;
|
||||
this.display_name = user.display_name;
|
||||
this.discriminator = user.discriminator;
|
||||
this.public_flags = user.public_flags;
|
||||
this.avatar = user.avatar;
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ import { UserSettings } from "./UserSettings";
|
||||
|
||||
export enum PublicUserEnum {
|
||||
username,
|
||||
global_name,
|
||||
display_name,
|
||||
discriminator,
|
||||
id,
|
||||
public_flags,
|
||||
@ -90,8 +92,14 @@ export class User extends BaseClass {
|
||||
@Column()
|
||||
username: string; // username max length 32, min 2 (should be configurable)
|
||||
|
||||
@Column({nullable: true})
|
||||
global_name: string; // puyo: pomelo
|
||||
|
||||
@Column({nullable: true})
|
||||
display_name?: string; // puyo: pomelo
|
||||
|
||||
@Column()
|
||||
discriminator: string; // opaque string: 4 digits on discord.com
|
||||
discriminator: string; // opaque string: 4 digits on discord.com, 0 for pomelo
|
||||
|
||||
@Column({ nullable: true })
|
||||
avatar?: string; // hash of the user avatar
|
||||
@ -323,6 +331,13 @@ export class User extends BaseClass {
|
||||
}
|
||||
}
|
||||
|
||||
public get handle(): string {
|
||||
const {pomeloEnabled} = Config.get().general;
|
||||
|
||||
// if pomelo is enabled, global_name should be set
|
||||
return pomeloEnabled ? this.global_name as string : `${this.username}#${this.discriminator}`;
|
||||
}
|
||||
|
||||
static async register({
|
||||
email,
|
||||
username,
|
||||
@ -337,19 +352,25 @@ export class User extends BaseClass {
|
||||
id?: string;
|
||||
req?: Request;
|
||||
}) {
|
||||
const {pomeloEnabled} = Config.get().general;
|
||||
|
||||
// trim special uf8 control characters -> Backspace, Newline, ...
|
||||
username = trimSpecial(username);
|
||||
|
||||
const discriminator = await User.generateDiscriminator(username);
|
||||
if (!discriminator) {
|
||||
// We've failed to generate a valid and unused discriminator
|
||||
throw FieldErrors({
|
||||
username: {
|
||||
code: "USERNAME_TOO_MANY_USERS",
|
||||
message:
|
||||
req?.t("auth:register.USERNAME_TOO_MANY_USERS") || "",
|
||||
},
|
||||
});
|
||||
let discriminator: string | undefined;
|
||||
if(pomeloEnabled) discriminator = "0";
|
||||
else {
|
||||
discriminator = await User.generateDiscriminator(username);
|
||||
if (!discriminator) {
|
||||
// We've failed to generate a valid and unused discriminator
|
||||
throw FieldErrors({
|
||||
username: {
|
||||
code: "USERNAME_TOO_MANY_USERS",
|
||||
message:
|
||||
req?.t("auth:register.USERNAME_TOO_MANY_USERS") || "",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: save date_of_birth
|
||||
@ -364,6 +385,8 @@ export class User extends BaseClass {
|
||||
|
||||
const user = User.create({
|
||||
username: username,
|
||||
global_name: username, // TODO: convert to lowercase, strip special characters,etc???
|
||||
// display_name: username, // TODO: how should we do this?
|
||||
discriminator,
|
||||
id: id || Snowflake.generate(),
|
||||
email: email,
|
||||
@ -391,7 +414,7 @@ export class User extends BaseClass {
|
||||
if (!Config.get().defaults.user.verified && email) {
|
||||
await Email.sendVerifyEmail(user, email).catch((e) => {
|
||||
console.error(
|
||||
`Failed to send verification email to ${user.username}#${user.discriminator}: ${e}`,
|
||||
`Failed to send verification email to ${user.handle}: ${e}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// TODO: pomelo?
|
||||
export interface RelationshipPostSchema {
|
||||
discriminator: string;
|
||||
username: string;
|
||||
|
@ -21,6 +21,8 @@ export interface GuildBansResponse {
|
||||
user: {
|
||||
username: string;
|
||||
discriminator: string;
|
||||
global_name: string;
|
||||
display_name: string | null;
|
||||
id: string;
|
||||
avatar: string | null;
|
||||
public_flags: number;
|
||||
|
@ -30,6 +30,8 @@ export interface GuildWidgetJsonResponse {
|
||||
members: {
|
||||
id: string;
|
||||
username: string;
|
||||
global_name: string;
|
||||
display_name: string | null;
|
||||
discriminator: string;
|
||||
avatar: string | null;
|
||||
status: ClientStatus;
|
||||
|
@ -19,6 +19,8 @@ import { User } from "@spacebar/util";
|
||||
|
||||
export type UserRelationsResponse = (Pick<User, "id"> &
|
||||
Pick<User, "username"> &
|
||||
Pick<User, "global_name"> &
|
||||
Pick<User, "display_name"> &
|
||||
Pick<User, "discriminator"> &
|
||||
Pick<User, "avatar"> &
|
||||
Pick<User, "public_flags">)[];
|
||||
|
@ -112,9 +112,12 @@ export const Email: {
|
||||
) {
|
||||
const { instanceName } = Config.get().general;
|
||||
|
||||
// TODO: pomelo: display_name should take precedence over username if pomelo is enabled. maybe we should use global_name as the username?
|
||||
const replacements = [
|
||||
["{instanceName}", instanceName],
|
||||
["{userUsername}", user.username],
|
||||
["{userGlobalName}", user.global_name],
|
||||
["{userDisplayName}", user.display_name],
|
||||
["{userDiscriminator}", user.discriminator],
|
||||
["{userId}", user.id],
|
||||
["{phoneNumber}", user.phone?.slice(-4)],
|
||||
|
Loading…
Reference in New Issue
Block a user