FoundKey/packages/backend/src/remote/activitypub/kernel/move/index.ts
2022-11-26 16:27:27 +01:00

58 lines
1.8 KiB
TypeScript

import { CacheableRemoteUser } from '@/models/entities/user.js';
import { updatePerson } from '@/remote/activitypub/models/person.js';
import { Followings, Users } from '@/models/index.js';
import { createNotification } from '@/services/create-notification.js';
import Resolver from '../../resolver.js';
import { IMove, getApId } from '../../type.js';
export async function move(actor: CacheableRemoteUser, activity: IMove): Promise<void> {
const objectUri = getApId(activity);
// actor is not move origin
if (objectUri != actor.uri) return;
// actor already moved
if (actor.movedTo != null) return;
// no move target
if (activity.target == null) return;
const resolver = new Resolver();
/* the database resolver can not be used here, because:
* 1. It must be ensured that the latest data is used.
* 2. The AP representation is needed, because `alsoKnownAs`
* is not stored in the database.
*/
const movedToAp = resolver.resolve(activity.target);
// ensure the user exists
const movedTo = await resolvePerson(getApId(activity.target), resolver, movedToAp);
// move destination has not accepted
if (!Array.isArray(movedToAp.alsoKnownAs) || !moved_to.alsoKnownAs.includes(actor.id)) return;
// process move for local followers
const followingsQuery = Followings.createQueryBuilder('f')
.select('f.followerId')
.where('f.followeeId = :actorId', { actorId: actor.id })
.andWhere('f.followerHost IS NULL');
const followers = await UserProfiles.createQueryBuilder('profiles')
.where(`id IN (${ followingsQuery.getQuery() })`)
.getMany();
await Promise.all([
Users.update(actor.id, {
moved: movedTo.id,
}),
...followers.map(async (follower) => {
// TODO: autoAcceptMove?
await createNotification(follower.id, 'move', {
notifierId: actor.id,
});
}),
]);
}