summaryrefslogtreecommitdiff
path: root/packages/backend/src/core/UserFollowingService.ts
diff options
context:
space:
mode:
authorJulia <julia@insertdomain.name>2025-06-19 21:35:18 +0000
committerJulia <julia@insertdomain.name>2025-06-19 21:35:18 +0000
commita77c32b17da63d3932b219f74152cce023a30f4a (patch)
treed2a05796e942c8f250bbd01369eab0cbe5a14531 /packages/backend/src/core/UserFollowingService.ts
parentmerge: release 2025.4.2 (!1051) (diff)
parentMerge branch 'develop' into release/2025.4.3 (diff)
downloadsharkey-a77c32b17da63d3932b219f74152cce023a30f4a.tar.gz
sharkey-a77c32b17da63d3932b219f74152cce023a30f4a.tar.bz2
sharkey-a77c32b17da63d3932b219f74152cce023a30f4a.zip
merge: prepare release 2025.4.3 (!1125)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1125 Approved-by: Marie <github@yuugi.dev> Approved-by: Julia <julia@insertdomain.name>
Diffstat (limited to 'packages/backend/src/core/UserFollowingService.ts')
-rw-r--r--packages/backend/src/core/UserFollowingService.ts125
1 files changed, 47 insertions, 78 deletions
diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts
index 897b950022..8470872eac 100644
--- a/packages/backend/src/core/UserFollowingService.ts
+++ b/packages/backend/src/core/UserFollowingService.ts
@@ -29,6 +29,7 @@ import { AccountMoveService } from '@/core/AccountMoveService.js';
import { UtilityService } from '@/core/UtilityService.js';
import type { ThinUser } from '@/queue/types.js';
import { LoggerService } from '@/core/LoggerService.js';
+import { InternalEventService } from '@/core/InternalEventService.js';
import type Logger from '../logger.js';
type Local = MiLocalUser | {
@@ -86,6 +87,7 @@ export class UserFollowingService implements OnModuleInit {
private accountMoveService: AccountMoveService,
private perUserFollowingChart: PerUserFollowingChart,
private instanceChart: InstanceChart,
+ private readonly internalEventService: InternalEventService,
loggerService: LoggerService,
) {
@@ -145,12 +147,7 @@ export class UserFollowingService implements OnModuleInit {
if (blocked) throw new IdentifiableError('3338392a-f764-498d-8855-db939dcf8c48', 'blocked');
}
- if (await this.followingsRepository.exists({
- where: {
- followerId: follower.id,
- followeeId: followee.id,
- },
- })) {
+ if (await this.cacheService.isFollowing(follower, followee)) {
// すでにフォロー関係が存在している場合
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
// リモート → ローカル: acceptを送り返しておしまい
@@ -178,24 +175,14 @@ export class UserFollowingService implements OnModuleInit {
let autoAccept = false;
// 鍵アカウントであっても、既にフォローされていた場合はスルー
- const isFollowing = await this.followingsRepository.exists({
- where: {
- followerId: follower.id,
- followeeId: followee.id,
- },
- });
+ const isFollowing = await this.cacheService.isFollowing(follower, followee);
if (isFollowing) {
autoAccept = true;
}
// フォローしているユーザーは自動承認オプション
if (!autoAccept && (this.userEntityService.isLocalUser(followee) && followeeProfile.autoAcceptFollowed)) {
- const isFollowed = await this.followingsRepository.exists({
- where: {
- followerId: followee.id,
- followeeId: follower.id,
- },
- });
+ const isFollowed = await this.cacheService.isFollowing(followee, follower); // intentionally reversed parameters
if (isFollowed) autoAccept = true;
}
@@ -204,12 +191,7 @@ export class UserFollowingService implements OnModuleInit {
if (followee.isLocked && !autoAccept) {
autoAccept = !!(await this.accountMoveService.validateAlsoKnownAs(
follower,
- (oldSrc, newSrc) => this.followingsRepository.exists({
- where: {
- followeeId: followee.id,
- followerId: newSrc.id,
- },
- }),
+ (oldSrc, newSrc) => this.cacheService.isFollowing(newSrc, followee),
true,
));
}
@@ -264,7 +246,8 @@ export class UserFollowingService implements OnModuleInit {
}
});
- this.cacheService.userFollowingsCache.refresh(follower.id);
+ // Handled by CacheService
+ //this.cacheService.userFollowingsCache.refresh(follower.id);
const requestExist = await this.followRequestsRepository.exists({
where: {
@@ -291,7 +274,7 @@ export class UserFollowingService implements OnModuleInit {
}, followee.id);
}
- this.globalEventService.publishInternalEvent('follow', { followerId: follower.id, followeeId: followee.id });
+ await this.internalEventService.emit('follow', { followerId: follower.id, followeeId: followee.id });
const [followeeUser, followerUser] = await Promise.all([
this.usersRepository.findOneByOrFail({ id: followee.id }),
@@ -363,31 +346,29 @@ export class UserFollowingService implements OnModuleInit {
},
silent = false,
): Promise<void> {
- const following = await this.followingsRepository.findOne({
- relations: {
- follower: true,
- followee: true,
- },
- where: {
- followerId: follower.id,
- followeeId: followee.id,
- },
- });
+ const [
+ followerUser,
+ followeeUser,
+ following,
+ ] = await Promise.all([
+ this.cacheService.findUserById(follower.id),
+ this.cacheService.findUserById(followee.id),
+ this.cacheService.userFollowingsCache.fetch(follower.id).then(fs => fs.get(followee.id)),
+ ]);
- if (following === null || !following.follower || !following.followee) {
+ if (following == null) {
this.logger.warn('フォロー解除がリクエストされましたがフォローしていませんでした');
return;
}
await this.followingsRepository.delete(following.id);
+ await this.internalEventService.emit('unfollow', { followerId: follower.id, followeeId: followee.id });
- this.cacheService.userFollowingsCache.refresh(follower.id);
-
- this.decrementFollowing(following.follower, following.followee);
+ this.decrementFollowing(followerUser, followeeUser);
if (!silent && this.userEntityService.isLocalUser(follower)) {
// Publish unfollow event
- this.userEntityService.pack(followee.id, follower, {
+ this.userEntityService.pack(followeeUser, follower, {
schema: 'UserDetailedNotMe',
}).then(async packed => {
this.globalEventService.publishMainStream(follower.id, 'unfollow', packed);
@@ -412,8 +393,6 @@ export class UserFollowingService implements OnModuleInit {
follower: MiUser,
followee: MiUser,
): Promise<void> {
- this.globalEventService.publishInternalEvent('unfollow', { followerId: follower.id, followeeId: followee.id });
-
// Neither followee nor follower has moved.
if (!follower.movedToUri && !followee.movedToUri) {
//#region Decrement following / followers counts
@@ -687,22 +666,22 @@ export class UserFollowingService implements OnModuleInit {
*/
@bindThis
private async removeFollow(followee: Both, follower: Both): Promise<void> {
- const following = await this.followingsRepository.findOne({
- relations: {
- followee: true,
- follower: true,
- },
- where: {
- followeeId: followee.id,
- followerId: follower.id,
- },
- });
+ const [
+ followerUser,
+ followeeUser,
+ following,
+ ] = await Promise.all([
+ this.cacheService.findUserById(follower.id),
+ this.cacheService.findUserById(followee.id),
+ this.cacheService.userFollowingsCache.fetch(follower.id).then(fs => fs.get(followee.id)),
+ ]);
- if (!following || !following.followee || !following.follower) return;
+ if (!following) return;
await this.followingsRepository.delete(following.id);
+ await this.internalEventService.emit('unfollow', { followerId: follower.id, followeeId: followee.id });
- this.decrementFollowing(following.follower, following.followee);
+ this.decrementFollowing(followerUser, followeeUser);
}
/**
@@ -733,36 +712,26 @@ export class UserFollowingService implements OnModuleInit {
}
@bindThis
- public getFollowees(userId: MiUser['id']) {
- return this.followingsRepository.createQueryBuilder('following')
- .select('following.followeeId')
- .where('following.followerId = :followerId', { followerId: userId })
- .getMany();
+ public async getFollowees(userId: MiUser['id']) {
+ const followings = await this.cacheService.userFollowingsCache.fetch(userId);
+ return Array.from(followings.values());
}
@bindThis
- public isFollowing(followerId: MiUser['id'], followeeId: MiUser['id']) {
- return this.followingsRepository.exists({
- where: {
- followerId,
- followeeId,
- },
- });
+ public async isFollowing(followerId: MiUser['id'], followeeId: MiUser['id']) {
+ return this.cacheService.isFollowing(followerId, followeeId);
}
@bindThis
public async isMutual(aUserId: MiUser['id'], bUserId: MiUser['id']) {
- const count = await this.followingsRepository.createQueryBuilder('following')
- .where(new Brackets(qb => {
- qb.where('following.followerId = :aUserId', { aUserId })
- .andWhere('following.followeeId = :bUserId', { bUserId });
- }))
- .orWhere(new Brackets(qb => {
- qb.where('following.followerId = :bUserId', { bUserId })
- .andWhere('following.followeeId = :aUserId', { aUserId });
- }))
- .getCount();
+ const [
+ isFollowing,
+ isFollowed,
+ ] = await Promise.all([
+ this.isFollowing(aUserId, bUserId),
+ this.isFollowing(bUserId, aUserId),
+ ]);
- return count === 2;
+ return isFollowing && isFollowed;
}
}