🐛 fix relationship
This commit is contained in:
parent
4f1b926d09
commit
9e3bc94e9d
@ -31,7 +31,7 @@ router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request
|
|||||||
return await updateRelationship(
|
return await updateRelationship(
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
await User.findOneOrFail({ id: req.params.id }, { relations: ["relationships"], select: userProjection }),
|
await User.findOneOrFail({ id: req.params.id }, { relations: ["relationships", "relationships.to"], select: userProjection }),
|
||||||
req.body.type
|
req.body.type
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -46,7 +46,7 @@ router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request,
|
|||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
await User.findOneOrFail({
|
await User.findOneOrFail({
|
||||||
relations: ["relationships"],
|
relations: ["relationships", "relationships.to"],
|
||||||
select: userProjection,
|
select: userProjection,
|
||||||
where: req.body as { discriminator: string; username: string }
|
where: req.body as { discriminator: string; username: string }
|
||||||
}),
|
}),
|
||||||
@ -61,37 +61,40 @@ router.delete("/:id", route({}), async (req: Request, res: Response) => {
|
|||||||
const user = await User.findOneOrFail({ id: req.user_id }, { select: userProjection, relations: ["relationships"] });
|
const user = await User.findOneOrFail({ id: req.user_id }, { select: userProjection, relations: ["relationships"] });
|
||||||
const friend = await User.findOneOrFail({ id: id }, { select: userProjection, relations: ["relationships"] });
|
const friend = await User.findOneOrFail({ id: id }, { select: userProjection, relations: ["relationships"] });
|
||||||
|
|
||||||
const relationship = user.relationships.find((x) => x.id === id);
|
const relationship = user.relationships.find((x) => x.to_id === id);
|
||||||
const friendRequest = friend.relationships.find((x) => x.id === req.user_id);
|
const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id);
|
||||||
|
|
||||||
|
if (!relationship) throw new HTTPError("You are not friends with the user", 404);
|
||||||
if (relationship?.type === RelationshipType.blocked) {
|
if (relationship?.type === RelationshipType.blocked) {
|
||||||
// unblock user
|
// unblock user
|
||||||
user.relationships.remove(relationship);
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
user.save(),
|
Relationship.delete({ id: relationship.id }),
|
||||||
emitEvent({ event: "RELATIONSHIP_REMOVE", user_id: req.user_id, data: relationship } as RelationshipRemoveEvent)
|
emitEvent({
|
||||||
|
event: "RELATIONSHIP_REMOVE",
|
||||||
|
user_id: req.user_id,
|
||||||
|
data: relationship.toPublicRelationship()
|
||||||
|
} as RelationshipRemoveEvent)
|
||||||
]);
|
]);
|
||||||
return res.sendStatus(204);
|
return res.sendStatus(204);
|
||||||
}
|
}
|
||||||
if (!relationship || !friendRequest) throw new HTTPError("You are not friends with the user", 404);
|
if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
|
||||||
if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you");
|
await Promise.all([
|
||||||
|
Relationship.delete({ id: friendRequest.id }),
|
||||||
user.relationships.remove(relationship);
|
await emitEvent({
|
||||||
friend.relationships.remove(friendRequest);
|
event: "RELATIONSHIP_REMOVE",
|
||||||
|
data: friendRequest.toPublicRelationship(),
|
||||||
|
user_id: id
|
||||||
|
} as RelationshipRemoveEvent)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
user.save(),
|
Relationship.delete({ id: relationship.id }),
|
||||||
friend.save(),
|
|
||||||
emitEvent({
|
emitEvent({
|
||||||
event: "RELATIONSHIP_REMOVE",
|
event: "RELATIONSHIP_REMOVE",
|
||||||
data: relationship,
|
data: relationship.toPublicRelationship(),
|
||||||
user_id: req.user_id
|
user_id: req.user_id
|
||||||
} as RelationshipRemoveEvent),
|
|
||||||
emitEvent({
|
|
||||||
event: "RELATIONSHIP_REMOVE",
|
|
||||||
data: friendRequest,
|
|
||||||
user_id: id
|
|
||||||
} as RelationshipRemoveEvent)
|
} as RelationshipRemoveEvent)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -104,44 +107,40 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
|
|||||||
const id = friend.id;
|
const id = friend.id;
|
||||||
if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend");
|
if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend");
|
||||||
|
|
||||||
const user = await User.findOneOrFail({ id: req.user_id }, { relations: ["relationships"], select: userProjection });
|
const user = await User.findOneOrFail(
|
||||||
|
{ id: req.user_id },
|
||||||
|
{ relations: ["relationships", "relationships.to"], select: userProjection }
|
||||||
|
);
|
||||||
|
|
||||||
var relationship = user.relationships.find((x) => x.id === id);
|
var relationship = user.relationships.find((x) => x.to_id === id);
|
||||||
const friendRequest = friend.relationships.find((x) => x.id === req.user_id);
|
const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id);
|
||||||
|
|
||||||
// TODO: you can add infinitely many blocked users (should this be prevented?)
|
// TODO: you can add infinitely many blocked users (should this be prevented?)
|
||||||
if (type === RelationshipType.blocked) {
|
if (type === RelationshipType.blocked) {
|
||||||
if (relationship) {
|
if (relationship) {
|
||||||
if (relationship.type === RelationshipType.blocked) throw new HTTPError("You already blocked the user");
|
if (relationship.type === RelationshipType.blocked) throw new HTTPError("You already blocked the user");
|
||||||
relationship.type = RelationshipType.blocked;
|
relationship.type = RelationshipType.blocked;
|
||||||
|
await relationship.save();
|
||||||
} else {
|
} else {
|
||||||
relationship = new Relationship({ id, type: RelationshipType.blocked });
|
relationship = await new Relationship({ to_id: id, type: RelationshipType.blocked, from_id: req.user_id }).save();
|
||||||
user.relationships.push(relationship);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
|
if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
|
||||||
friend.relationships.remove(friendRequest);
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
user.save(),
|
Relationship.delete({ id: friendRequest.id }),
|
||||||
emitEvent({
|
emitEvent({
|
||||||
event: "RELATIONSHIP_REMOVE",
|
event: "RELATIONSHIP_REMOVE",
|
||||||
data: friendRequest,
|
data: friendRequest.toPublicRelationship(),
|
||||||
user_id: id
|
user_id: id
|
||||||
} as RelationshipRemoveEvent)
|
} as RelationshipRemoveEvent)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await emitEvent({
|
||||||
user.save(),
|
event: "RELATIONSHIP_ADD",
|
||||||
emitEvent({
|
data: relationship.toPublicRelationship(),
|
||||||
event: "RELATIONSHIP_ADD",
|
user_id: req.user_id
|
||||||
data: {
|
} as RelationshipAddEvent);
|
||||||
...relationship,
|
|
||||||
user: { ...friend }
|
|
||||||
},
|
|
||||||
user_id: req.user_id
|
|
||||||
} as RelationshipAddEvent)
|
|
||||||
]);
|
|
||||||
|
|
||||||
return res.sendStatus(204);
|
return res.sendStatus(204);
|
||||||
}
|
}
|
||||||
@ -149,40 +148,43 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
|
|||||||
const { maxFriends } = Config.get().limits.user;
|
const { maxFriends } = Config.get().limits.user;
|
||||||
if (user.relationships.length >= maxFriends) throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends);
|
if (user.relationships.length >= maxFriends) throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends);
|
||||||
|
|
||||||
var incoming_relationship = new Relationship({ nickname: undefined, type: RelationshipType.incoming, id: req.user_id });
|
var incoming_relationship = new Relationship({ nickname: undefined, type: RelationshipType.incoming, to: user, from: friend });
|
||||||
var outgoing_relationship = new Relationship({ nickname: undefined, type: RelationshipType.outgoing, id });
|
var outgoing_relationship = new Relationship({
|
||||||
|
nickname: undefined,
|
||||||
|
type: RelationshipType.outgoing,
|
||||||
|
to: friend,
|
||||||
|
from: user
|
||||||
|
});
|
||||||
|
|
||||||
if (friendRequest) {
|
if (friendRequest) {
|
||||||
if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you");
|
if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you");
|
||||||
|
if (friendRequest.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
|
||||||
// accept friend request
|
// accept friend request
|
||||||
incoming_relationship = friendRequest;
|
incoming_relationship = friendRequest;
|
||||||
incoming_relationship.type = RelationshipType.friends;
|
incoming_relationship.type = RelationshipType.friends;
|
||||||
outgoing_relationship.type = RelationshipType.friends;
|
}
|
||||||
} else friend.relationships.push(incoming_relationship);
|
|
||||||
|
|
||||||
if (relationship) {
|
if (relationship) {
|
||||||
if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request");
|
if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request");
|
||||||
if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request");
|
if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request");
|
||||||
if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
|
if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
|
||||||
} else user.relationships.push(outgoing_relationship);
|
outgoing_relationship = relationship;
|
||||||
|
outgoing_relationship.type = RelationshipType.friends;
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
user.save(),
|
incoming_relationship.save(),
|
||||||
friend.save(),
|
outgoing_relationship.save(),
|
||||||
emitEvent({
|
emitEvent({
|
||||||
event: "RELATIONSHIP_ADD",
|
event: "RELATIONSHIP_ADD",
|
||||||
data: {
|
data: outgoing_relationship.toPublicRelationship(),
|
||||||
...outgoing_relationship,
|
|
||||||
user: { ...friend }
|
|
||||||
},
|
|
||||||
user_id: req.user_id
|
user_id: req.user_id
|
||||||
} as RelationshipAddEvent),
|
} as RelationshipAddEvent),
|
||||||
emitEvent({
|
emitEvent({
|
||||||
event: "RELATIONSHIP_ADD",
|
event: "RELATIONSHIP_ADD",
|
||||||
data: {
|
data: {
|
||||||
...incoming_relationship,
|
...incoming_relationship.toPublicRelationship(),
|
||||||
should_notify: true,
|
should_notify: true
|
||||||
user: { ...user }
|
|
||||||
},
|
},
|
||||||
user_id: id
|
user_id: id
|
||||||
} as RelationshipAddEvent)
|
} as RelationshipAddEvent)
|
||||||
|
@ -104,7 +104,10 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
|||||||
}
|
}
|
||||||
return x.channel;
|
return x.channel;
|
||||||
});
|
});
|
||||||
const user = await User.findOneOrFail({ id: this.user_id });
|
const user = await User.findOneOrFail({
|
||||||
|
where: { id: this.user_id },
|
||||||
|
relations: ["relationships", "relationships.to"],
|
||||||
|
});
|
||||||
if (!user) return this.close(CLOSECODES.Authentication_failed);
|
if (!user) return this.close(CLOSECODES.Authentication_failed);
|
||||||
|
|
||||||
const public_user = {
|
const public_user = {
|
||||||
@ -171,7 +174,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
|||||||
}),
|
}),
|
||||||
guild_experiments: [], // TODO
|
guild_experiments: [], // TODO
|
||||||
geo_ordered_rtc_regions: [], // TODO
|
geo_ordered_rtc_regions: [], // TODO
|
||||||
relationships: user.relationships,
|
relationships: user.relationships.map((x) => x.toPublicRelationship()),
|
||||||
read_state: {
|
read_state: {
|
||||||
// TODO
|
// TODO
|
||||||
entries: [],
|
entries: [],
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
|
import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm";
|
||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
import { User } from "./User";
|
import { User } from "./User";
|
||||||
|
|
||||||
@ -10,18 +10,36 @@ export enum RelationshipType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Entity("relationships")
|
@Entity("relationships")
|
||||||
|
@Index(["from_id", "to_id"], { unique: true })
|
||||||
export class Relationship extends BaseClass {
|
export class Relationship extends BaseClass {
|
||||||
@Column({ nullable: true })
|
@Column({})
|
||||||
@RelationId((relationship: Relationship) => relationship.user)
|
@RelationId((relationship: Relationship) => relationship.from)
|
||||||
user_id: string;
|
from_id: string;
|
||||||
|
|
||||||
@JoinColumn({ name: "user_id" })
|
@JoinColumn({ name: "from_id" })
|
||||||
@ManyToOne(() => User)
|
@ManyToOne(() => User)
|
||||||
user: User;
|
from: User;
|
||||||
|
|
||||||
|
@Column({})
|
||||||
|
@RelationId((relationship: Relationship) => relationship.to)
|
||||||
|
to_id: string;
|
||||||
|
|
||||||
|
@JoinColumn({ name: "to_id" })
|
||||||
|
@ManyToOne(() => User)
|
||||||
|
to: User;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
|
|
||||||
@Column({ type: "simple-enum", enum: RelationshipType })
|
@Column({ type: "simple-enum", enum: RelationshipType })
|
||||||
type: RelationshipType;
|
type: RelationshipType;
|
||||||
|
|
||||||
|
toPublicRelationship() {
|
||||||
|
return {
|
||||||
|
id: this.to?.id || this.to_id,
|
||||||
|
type: this.type,
|
||||||
|
nickname: this.nickname,
|
||||||
|
user: this.to?.toPublicUser(),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import { VoiceState } from "../entities/VoiceState";
|
|||||||
import { ApplicationCommand } from "../entities/Application";
|
import { ApplicationCommand } from "../entities/Application";
|
||||||
import { Interaction } from "./Interaction";
|
import { Interaction } from "./Interaction";
|
||||||
import { ConnectedAccount } from "../entities/ConnectedAccount";
|
import { ConnectedAccount } from "../entities/ConnectedAccount";
|
||||||
import { Relationship } from "../entities/Relationship";
|
import { Relationship, RelationshipType } from "../entities/Relationship";
|
||||||
import { Presence } from "./Presence";
|
import { Presence } from "./Presence";
|
||||||
|
|
||||||
export interface Event {
|
export interface Event {
|
||||||
@ -28,6 +28,12 @@ export interface InvalidatedEvent extends Event {
|
|||||||
event: "INVALIDATED";
|
event: "INVALIDATED";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PublicRelationship {
|
||||||
|
id: string;
|
||||||
|
user: PublicUser;
|
||||||
|
type: RelationshipType;
|
||||||
|
}
|
||||||
|
|
||||||
// ! END Custom Events that shouldn't get sent to the client but processed by the server
|
// ! END Custom Events that shouldn't get sent to the client but processed by the server
|
||||||
|
|
||||||
export interface ReadyEventData {
|
export interface ReadyEventData {
|
||||||
@ -72,7 +78,7 @@ export interface ReadyEventData {
|
|||||||
guild_join_requests?: any[]; // ? what is this? this is new
|
guild_join_requests?: any[]; // ? what is this? this is new
|
||||||
shard?: [number, number];
|
shard?: [number, number];
|
||||||
user_settings?: UserSettings;
|
user_settings?: UserSettings;
|
||||||
relationships?: Relationship[]; // TODO
|
relationships?: PublicRelationship[]; // TODO
|
||||||
read_state: {
|
read_state: {
|
||||||
entries: any[]; // TODO
|
entries: any[]; // TODO
|
||||||
partial: boolean;
|
partial: boolean;
|
||||||
@ -412,7 +418,7 @@ export interface MessageAckEvent extends Event {
|
|||||||
|
|
||||||
export interface RelationshipAddEvent extends Event {
|
export interface RelationshipAddEvent extends Event {
|
||||||
event: "RELATIONSHIP_ADD";
|
event: "RELATIONSHIP_ADD";
|
||||||
data: Relationship & {
|
data: PublicRelationship & {
|
||||||
should_notify?: boolean;
|
should_notify?: boolean;
|
||||||
user: PublicUser;
|
user: PublicUser;
|
||||||
};
|
};
|
||||||
@ -420,7 +426,7 @@ export interface RelationshipAddEvent extends Event {
|
|||||||
|
|
||||||
export interface RelationshipRemoveEvent extends Event {
|
export interface RelationshipRemoveEvent extends Event {
|
||||||
event: "RELATIONSHIP_REMOVE";
|
event: "RELATIONSHIP_REMOVE";
|
||||||
data: Omit<Relationship, "nickname">;
|
data: Omit<PublicRelationship, "nickname">;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EventData =
|
export type EventData =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user