返回提交历史
Modified
src/controllers/api/removeFriendController.ts
+66
-3
Modified
src/routes/api.ts
+2
-1
XFEstudio/XFESpaceNinjaServer
feat: batch remove friends (#2032)
Closes #1947 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2032 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
31043b55
代码差异
2 个文件
+68
-4
@@ -1,8 +1,13 @@
1
1
import { toOid } from "@/src/helpers/inventoryHelpers";
2
import { getJSONfromString } from "@/src/helpers/stringHelpers";
2
3
import { Friendship } from "@/src/models/friendModel";
4
import { Account } from "@/src/models/loginModel";
5
import { getInventory } from "@/src/services/inventoryService";
3
6
import { getAccountIdForRequest } from "@/src/services/loginService";
4
7
import { IOid } from "@/src/types/commonTypes";
8
import { parallelForeach } from "@/src/utils/async-utils";
5
9
import { RequestHandler } from "express";
10
import { Types } from "mongoose";
6
11
7
12
export const removeFriendGetController: RequestHandler = async (req, res) => {
8
13
const accountId = await getAccountIdForRequest(req);
@@ -22,7 +27,7 @@ export const removeFriendGetController: RequestHandler = async (req, res) => {
22
27
await Promise.all(promises);
23
28
res.json({
24
29
Friends: friends
25
});
30
} satisfies IRemoveFriendsResponse);
26
31
} else {
27
32
const friendId = req.query.friendId as string;
28
33
await Promise.all([
@@ -30,7 +35,65 @@ export const removeFriendGetController: RequestHandler = async (req, res) => {
30
35
Friendship.deleteOne({ owner: friendId, friend: accountId })
31
36
]);
32
37
res.json({
33
Friends: [{ $oid: friendId } satisfies IOid]
34
});
38
Friends: [{ $oid: friendId }]
39
} satisfies IRemoveFriendsResponse);
35
40
}
36
41
};
42
43
export const removeFriendPostController: RequestHandler = async (req, res) => {
44
const accountId = await getAccountIdForRequest(req);
45
const data = getJSONfromString<IBatchRemoveFriendsRequest>(String(req.body));
46
const friends = new Set((await Friendship.find({ owner: accountId }, "friend")).map(x => x.friend));
47
// TOVERIFY: Should pending friendships also be kept?
48
49
// Keep friends that have been online within threshold
50
await parallelForeach([...friends], async friend => {
51
const account = (await Account.findById(friend, "LastLogin"))!;
52
const daysLoggedOut = (Date.now() - account.LastLogin.getTime()) / 86400_000;
53
if (daysLoggedOut < data.DaysLoggedOut) {
54
friends.delete(friend);
55
}
56
});
57
58
if (data.SkipClanmates) {
59
const inventory = await getInventory(accountId, "GuildId");
60
if (inventory.GuildId) {
61
await parallelForeach([...friends], async friend => {
62
const friendInventory = await getInventory(friend.toString(), "GuildId");
63
if (friendInventory.GuildId?.equals(inventory.GuildId)) {
64
friends.delete(friend);
65
}
66
});
67
}
68
}
69
70
// Remove all remaining friends that aren't in SkipFriendIds & give response.
71
const promises = [];
72
const response: IOid[] = [];
73
for (const friend of friends) {
74
if (!data.SkipFriendIds.find(skipFriendId => checkFriendId(skipFriendId, friend))) {
75
promises.push(Friendship.deleteOne({ owner: accountId, friend: friend }));
76
promises.push(Friendship.deleteOne({ owner: friend, friend: accountId }));
77
response.push(toOid(friend));
78
}
79
}
80
await Promise.all(promises);
81
res.json({
82
Friends: response
83
} satisfies IRemoveFriendsResponse);
84
};
85
86
// The friend ids format is a bit weird, e.g. when 6633b81e9dba0b714f28ff02 (A) is friends with 67cdac105ef1f4b49741c267 (B), A's friend id for B is 808000105ef1f40560ca079e and B's friend id for A is 8000b81e9dba0b06408a8075.
87
const checkFriendId = (friendId: string, b: Types.ObjectId): boolean => {
88
return friendId.substring(6, 6 + 8) == b.toString().substring(6, 6 + 8);
89
};
90
91
interface IBatchRemoveFriendsRequest {
92
DaysLoggedOut: number;
93
SkipClanmates: boolean;
94
SkipFriendIds: string[];
95
}
96
97
interface IRemoveFriendsResponse {
98
Friends: IOid[];
99
}
@@ -103,7 +103,7 @@ import { questControlController } from "@/src/controllers/api/questControlContro
103
103
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
104
104
import { redeemPromoCodeController } from "@/src/controllers/api/redeemPromoCodeController";
105
105
import { releasePetController } from "@/src/controllers/api/releasePetController";
106
import { removeFriendGetController } from "@/src/controllers/api/removeFriendController";
106
import { removeFriendGetController, removeFriendPostController } from "@/src/controllers/api/removeFriendController";
107
107
import { removeFromAllianceController } from "@/src/controllers/api/removeFromAllianceController";
108
108
import { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController";
109
109
import { removeIgnoredUserController } from "@/src/controllers/api/removeIgnoredUserController";
@@ -290,6 +290,7 @@ apiRouter.post("/purchase.php", purchaseController);
290
290
apiRouter.post("/questControl.php", questControlController); // U17
291
291
apiRouter.post("/redeemPromoCode.php", redeemPromoCodeController);
292
292
apiRouter.post("/releasePet.php", releasePetController);
293
apiRouter.post("/removeFriend.php", removeFriendPostController);
293
294
apiRouter.post("/removeFromGuild.php", removeFromGuildController);
294
295
apiRouter.post("/removeIgnoredUser.php", removeIgnoredUserController);
295
296
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);