diff --git a/src/remote/activitypub/kernel/undo/follow.ts b/src/remote/activitypub/kernel/undo/follow.ts index 763d5723c4..7377984616 100644 --- a/src/remote/activitypub/kernel/undo/follow.ts +++ b/src/remote/activitypub/kernel/undo/follow.ts @@ -2,7 +2,9 @@ import * as mongo from 'mongodb'; import User, { IRemoteUser } from '../../../../models/user'; import config from '../../../../config'; import unfollow from '../../../../services/following/delete'; +import cancelRequest from '../../../../services/following/requests/cancel'; import { IFollow } from '../../type'; +import FollowRequest from '../../../../models/follow-request'; export default async (actor: IRemoteUser, activity: IFollow): Promise => { const id = typeof activity.object == 'string' ? activity.object : activity.object.id; @@ -23,5 +25,14 @@ export default async (actor: IRemoteUser, activity: IFollow): Promise => { throw new Error('フォロー解除しようとしているユーザーはローカルユーザーではありません'); } - await unfollow(actor, followee); + const req = await FollowRequest.findOne({ + followerId: actor._id, + followeeId: followee._id + }); + + if (req) { + await cancelRequest(actor, followee); + } else { + await unfollow(actor, followee); + } }; diff --git a/src/services/following/create.ts b/src/services/following/create.ts index 39cecfddfb..03db72c332 100644 --- a/src/services/following/create.ts +++ b/src/services/following/create.ts @@ -8,44 +8,11 @@ import pack from '../../remote/activitypub/renderer'; import renderFollow from '../../remote/activitypub/renderer/follow'; import renderAccept from '../../remote/activitypub/renderer/accept'; import { deliver } from '../../queue'; -import FollowRequest from '../../models/follow-request'; +import createFollowRequest from './requests/create'; export default async function(follower: IUser, followee: IUser) { if (followee.isLocked) { - await FollowRequest.insert({ - createdAt: new Date(), - followerId: follower._id, - followeeId: followee._id, - - // 非正規化 - _follower: { - host: follower.host, - inbox: isRemoteUser(follower) ? follower.inbox : undefined - }, - _followee: { - host: followee.host, - inbox: isRemoteUser(followee) ? followee.inbox : undefined - } - }); - - User.update({ _id: followee._id }, { - $inc: { - pendingReceivedFollowRequestsCount: 1 - } - }); - - // Publish reciveRequest event - if (isLocalUser(followee)) { - packUser(follower, followee).then(packed => event(followee._id, 'reciveRequest', packed)), - - // 通知を作成 - notify(followee._id, follower._id, 'reciveRequest'); - } - - if (isLocalUser(follower) && isRemoteUser(followee)) { - const content = pack(renderFollow(follower, followee)); - deliver(follower, content, followee.inbox); - } + await createFollowRequest(follower, followee); } else { const following = await Following.insert({ createdAt: new Date(), diff --git a/src/services/following/requests/cancel.ts b/src/services/following/requests/cancel.ts new file mode 100644 index 0000000000..840f70264c --- /dev/null +++ b/src/services/following/requests/cancel.ts @@ -0,0 +1,24 @@ +import User, { IUser, isRemoteUser, ILocalUser } from "../../../models/user"; +import FollowRequest from "../../../models/follow-request"; +import pack from '../../../remote/activitypub/renderer'; +import renderFollow from '../../../remote/activitypub/renderer/follow'; +import renderUndo from '../../../remote/activitypub/renderer/undo'; +import { deliver } from '../../../queue'; + +export default async function(followee: IUser, follower: IUser) { + if (isRemoteUser(followee)) { + const content = pack(renderUndo(renderFollow(follower, followee))); + deliver(follower as ILocalUser, content, followee.inbox); + } + + await FollowRequest.remove({ + followeeId: followee._id, + followerId: follower._id + }); + + User.update({ _id: followee._id }, { + $inc: { + pendingReceivedFollowRequestsCount: -1 + } + }); +} diff --git a/src/services/following/requests/create.ts b/src/services/following/requests/create.ts new file mode 100644 index 0000000000..1285c21ea8 --- /dev/null +++ b/src/services/following/requests/create.ts @@ -0,0 +1,46 @@ +import User, { isLocalUser, isRemoteUser, pack as packUser, IUser } from '../../../models/user'; +import event from '../../../publishers/stream'; +import notify from '../../../publishers/notify'; +import pack from '../../../remote/activitypub/renderer'; +import renderFollow from '../../../remote/activitypub/renderer/follow'; +import { deliver } from '../../../queue'; +import FollowRequest from '../../../models/follow-request'; + +export default async function(follower: IUser, followee: IUser) { + if (!followee.isLocked) throw '対象のアカウントは鍵アカウントではありません'; + + await FollowRequest.insert({ + createdAt: new Date(), + followerId: follower._id, + followeeId: followee._id, + + // 非正規化 + _follower: { + host: follower.host, + inbox: isRemoteUser(follower) ? follower.inbox : undefined + }, + _followee: { + host: followee.host, + inbox: isRemoteUser(followee) ? followee.inbox : undefined + } + }); + + User.update({ _id: followee._id }, { + $inc: { + pendingReceivedFollowRequestsCount: 1 + } + }); + + // Publish reciveRequest event + if (isLocalUser(followee)) { + packUser(follower, followee).then(packed => event(followee._id, 'reciveRequest', packed)), + + // 通知を作成 + notify(followee._id, follower._id, 'reciveRequest'); + } + + if (isLocalUser(follower) && isRemoteUser(followee)) { + const content = pack(renderFollow(follower, followee)); + deliver(follower, content, followee.inbox); + } +}