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 { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
			
		||||
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 { IOid } from "@/src/types/commonTypes";
 | 
			
		||||
import { parallelForeach } from "@/src/utils/async-utils";
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
 | 
			
		||||
export const removeFriendGetController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const accountId = await getAccountIdForRequest(req);
 | 
			
		||||
@ -22,7 +27,7 @@ export const removeFriendGetController: RequestHandler = async (req, res) => {
 | 
			
		||||
        await Promise.all(promises);
 | 
			
		||||
        res.json({
 | 
			
		||||
            Friends: friends
 | 
			
		||||
        });
 | 
			
		||||
        } satisfies IRemoveFriendsResponse);
 | 
			
		||||
    } else {
 | 
			
		||||
        const friendId = req.query.friendId as string;
 | 
			
		||||
        await Promise.all([
 | 
			
		||||
@ -30,7 +35,65 @@ export const removeFriendGetController: RequestHandler = async (req, res) => {
 | 
			
		||||
            Friendship.deleteOne({ owner: friendId, friend: accountId })
 | 
			
		||||
        ]);
 | 
			
		||||
        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 { redeemPromoCodeController } from "@/src/controllers/api/redeemPromoCodeController";
 | 
			
		||||
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 { removeFromGuildController } from "@/src/controllers/api/removeFromGuildController";
 | 
			
		||||
import { removeIgnoredUserController } from "@/src/controllers/api/removeIgnoredUserController";
 | 
			
		||||
@ -290,6 +290,7 @@ apiRouter.post("/purchase.php", purchaseController);
 | 
			
		||||
apiRouter.post("/questControl.php", questControlController); // U17
 | 
			
		||||
apiRouter.post("/redeemPromoCode.php", redeemPromoCodeController);
 | 
			
		||||
apiRouter.post("/releasePet.php", releasePetController);
 | 
			
		||||
apiRouter.post("/removeFriend.php", removeFriendPostController);
 | 
			
		||||
apiRouter.post("/removeFromGuild.php", removeFromGuildController);
 | 
			
		||||
apiRouter.post("/removeIgnoredUser.php", removeIgnoredUserController);
 | 
			
		||||
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user