forked from OpenWF/SpaceNinjaServer
		
	feat: batch remove friends (#2032)
Closes #1947 Reviewed-on: OpenWF/SpaceNinjaServer#2032 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									ab32728c47
								
							
						
					
					
						commit
						31043b55de
					
				@ -1,8 +1,13 @@
 | 
				
			|||||||
import { toOid } from "@/src/helpers/inventoryHelpers";
 | 
					import { toOid } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
 | 
					import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
import { Friendship } from "@/src/models/friendModel";
 | 
					import { Friendship } from "@/src/models/friendModel";
 | 
				
			||||||
 | 
					import { Account } from "@/src/models/loginModel";
 | 
				
			||||||
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { IOid } from "@/src/types/commonTypes";
 | 
					import { IOid } from "@/src/types/commonTypes";
 | 
				
			||||||
 | 
					import { parallelForeach } from "@/src/utils/async-utils";
 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					import { Types } from "mongoose";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const removeFriendGetController: RequestHandler = async (req, res) => {
 | 
					export const removeFriendGetController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
@ -22,7 +27,7 @@ export const removeFriendGetController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        await Promise.all(promises);
 | 
					        await Promise.all(promises);
 | 
				
			||||||
        res.json({
 | 
					        res.json({
 | 
				
			||||||
            Friends: friends
 | 
					            Friends: friends
 | 
				
			||||||
        });
 | 
					        } satisfies IRemoveFriendsResponse);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        const friendId = req.query.friendId as string;
 | 
					        const friendId = req.query.friendId as string;
 | 
				
			||||||
        await Promise.all([
 | 
					        await Promise.all([
 | 
				
			||||||
@ -30,7 +35,65 @@ export const removeFriendGetController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
            Friendship.deleteOne({ owner: friendId, friend: accountId })
 | 
					            Friendship.deleteOne({ owner: friendId, friend: accountId })
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
        res.json({
 | 
					        res.json({
 | 
				
			||||||
            Friends: [{ $oid: friendId } satisfies IOid]
 | 
					            Friends: [{ $oid: friendId }]
 | 
				
			||||||
        });
 | 
					        } satisfies IRemoveFriendsResponse);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const removeFriendPostController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
 | 
					    const data = getJSONfromString<IBatchRemoveFriendsRequest>(String(req.body));
 | 
				
			||||||
 | 
					    const friends = new Set((await Friendship.find({ owner: accountId }, "friend")).map(x => x.friend));
 | 
				
			||||||
 | 
					    // TOVERIFY: Should pending friendships also be kept?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Keep friends that have been online within threshold
 | 
				
			||||||
 | 
					    await parallelForeach([...friends], async friend => {
 | 
				
			||||||
 | 
					        const account = (await Account.findById(friend, "LastLogin"))!;
 | 
				
			||||||
 | 
					        const daysLoggedOut = (Date.now() - account.LastLogin.getTime()) / 86400_000;
 | 
				
			||||||
 | 
					        if (daysLoggedOut < data.DaysLoggedOut) {
 | 
				
			||||||
 | 
					            friends.delete(friend);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (data.SkipClanmates) {
 | 
				
			||||||
 | 
					        const inventory = await getInventory(accountId, "GuildId");
 | 
				
			||||||
 | 
					        if (inventory.GuildId) {
 | 
				
			||||||
 | 
					            await parallelForeach([...friends], async friend => {
 | 
				
			||||||
 | 
					                const friendInventory = await getInventory(friend.toString(), "GuildId");
 | 
				
			||||||
 | 
					                if (friendInventory.GuildId?.equals(inventory.GuildId)) {
 | 
				
			||||||
 | 
					                    friends.delete(friend);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Remove all remaining friends that aren't in SkipFriendIds & give response.
 | 
				
			||||||
 | 
					    const promises = [];
 | 
				
			||||||
 | 
					    const response: IOid[] = [];
 | 
				
			||||||
 | 
					    for (const friend of friends) {
 | 
				
			||||||
 | 
					        if (!data.SkipFriendIds.find(skipFriendId => checkFriendId(skipFriendId, friend))) {
 | 
				
			||||||
 | 
					            promises.push(Friendship.deleteOne({ owner: accountId, friend: friend }));
 | 
				
			||||||
 | 
					            promises.push(Friendship.deleteOne({ owner: friend, friend: accountId }));
 | 
				
			||||||
 | 
					            response.push(toOid(friend));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    await Promise.all(promises);
 | 
				
			||||||
 | 
					    res.json({
 | 
				
			||||||
 | 
					        Friends: response
 | 
				
			||||||
 | 
					    } satisfies IRemoveFriendsResponse);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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.
 | 
				
			||||||
 | 
					const checkFriendId = (friendId: string, b: Types.ObjectId): boolean => {
 | 
				
			||||||
 | 
					    return friendId.substring(6, 6 + 8) == b.toString().substring(6, 6 + 8);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IBatchRemoveFriendsRequest {
 | 
				
			||||||
 | 
					    DaysLoggedOut: number;
 | 
				
			||||||
 | 
					    SkipClanmates: boolean;
 | 
				
			||||||
 | 
					    SkipFriendIds: string[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IRemoveFriendsResponse {
 | 
				
			||||||
 | 
					    Friends: IOid[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -103,7 +103,7 @@ import { questControlController } from "@/src/controllers/api/questControlContro
 | 
				
			|||||||
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
 | 
					import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
 | 
				
			||||||
import { redeemPromoCodeController } from "@/src/controllers/api/redeemPromoCodeController";
 | 
					import { redeemPromoCodeController } from "@/src/controllers/api/redeemPromoCodeController";
 | 
				
			||||||
import { releasePetController } from "@/src/controllers/api/releasePetController";
 | 
					import { releasePetController } from "@/src/controllers/api/releasePetController";
 | 
				
			||||||
import { removeFriendGetController } from "@/src/controllers/api/removeFriendController";
 | 
					import { removeFriendGetController, removeFriendPostController } from "@/src/controllers/api/removeFriendController";
 | 
				
			||||||
import { removeFromAllianceController } from "@/src/controllers/api/removeFromAllianceController";
 | 
					import { removeFromAllianceController } from "@/src/controllers/api/removeFromAllianceController";
 | 
				
			||||||
import { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController";
 | 
					import { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController";
 | 
				
			||||||
import { removeIgnoredUserController } from "@/src/controllers/api/removeIgnoredUserController";
 | 
					import { removeIgnoredUserController } from "@/src/controllers/api/removeIgnoredUserController";
 | 
				
			||||||
@ -290,6 +290,7 @@ apiRouter.post("/purchase.php", purchaseController);
 | 
				
			|||||||
apiRouter.post("/questControl.php", questControlController); // U17
 | 
					apiRouter.post("/questControl.php", questControlController); // U17
 | 
				
			||||||
apiRouter.post("/redeemPromoCode.php", redeemPromoCodeController);
 | 
					apiRouter.post("/redeemPromoCode.php", redeemPromoCodeController);
 | 
				
			||||||
apiRouter.post("/releasePet.php", releasePetController);
 | 
					apiRouter.post("/releasePet.php", releasePetController);
 | 
				
			||||||
 | 
					apiRouter.post("/removeFriend.php", removeFriendPostController);
 | 
				
			||||||
apiRouter.post("/removeFromGuild.php", removeFromGuildController);
 | 
					apiRouter.post("/removeFromGuild.php", removeFromGuildController);
 | 
				
			||||||
apiRouter.post("/removeIgnoredUser.php", removeIgnoredUserController);
 | 
					apiRouter.post("/removeIgnoredUser.php", removeIgnoredUserController);
 | 
				
			||||||
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
 | 
					apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user