diff options
Diffstat (limited to 'src/services')
| -rw-r--r-- | src/services/blocking/create.ts | 121 | ||||
| -rw-r--r-- | src/services/blocking/delete.ts | 28 | ||||
| -rw-r--r-- | src/services/following/create.ts | 30 | ||||
| -rw-r--r-- | src/services/following/requests/create.ts | 16 |
4 files changed, 195 insertions, 0 deletions
diff --git a/src/services/blocking/create.ts b/src/services/blocking/create.ts new file mode 100644 index 0000000000..11b2954af6 --- /dev/null +++ b/src/services/blocking/create.ts @@ -0,0 +1,121 @@ +import User, { isLocalUser, isRemoteUser, pack as packUser, IUser } from '../../models/user'; +import Following from '../../models/following'; +import FollowRequest from '../../models/follow-request'; +import { publishMainStream } from '../../stream'; +import pack from '../../remote/activitypub/renderer'; +import renderFollow from '../../remote/activitypub/renderer/follow'; +import renderUndo from '../../remote/activitypub/renderer/undo'; +import renderBlock from '../../remote/activitypub/renderer/block'; +import { deliver } from '../../queue'; +import renderReject from '../../remote/activitypub/renderer/reject'; +import perUserFollowingChart from '../../chart/per-user-following'; +import Blocking from '../../models/blocking'; + +export default async function(blocker: IUser, blockee: IUser) { + + await Promise.all([ + cancelRequest(blocker, blockee), + cancelRequest(blockee, blocker), + unFollow(blocker, blockee), + unFollow(blockee, blocker) + ]); + + await Blocking.insert({ + createdAt: new Date(), + blockerId: blocker._id, + blockeeId: blockee._id, + }); + + if (isLocalUser(blocker) && isRemoteUser(blockee)) { + const content = pack(renderBlock(blocker, blockee)); + deliver(blocker, content, blockee.inbox); + } +} + +async function cancelRequest(follower: IUser, followee: IUser) { + const request = await FollowRequest.findOne({ + followeeId: followee._id, + followerId: follower._id + }); + + if (request == null) { + return; + } + + await FollowRequest.remove({ + followeeId: followee._id, + followerId: follower._id + }); + + await User.update({ _id: followee._id }, { + $inc: { + pendingReceivedFollowRequestsCount: -1 + } + }); + + if (isLocalUser(followee)) { + packUser(followee, followee, { + detail: true + }).then(packed => publishMainStream(followee._id, 'meUpdated', packed)); + } + + if (isLocalUser(follower)) { + packUser(followee, follower).then(packed => publishMainStream(follower._id, 'unfollow', packed)); + } + + // リモートにフォローリクエストをしていたらUndoFollow送信 + if (isLocalUser(follower) && isRemoteUser(followee)) { + const content = pack(renderUndo(renderFollow(follower, followee), follower)); + deliver(follower, content, followee.inbox); + } + + // リモートからフォローリクエストを受けていたらReject送信 + if (isRemoteUser(follower) && isLocalUser(followee)) { + const content = pack(renderReject(renderFollow(follower, followee, request.requestId), followee)); + deliver(followee, content, follower.inbox); + } +} + +async function unFollow(follower: IUser, followee: IUser) { + const following = await Following.findOne({ + followerId: follower._id, + followeeId: followee._id + }); + + if (following == null) { + return; + } + + Following.remove({ + _id: following._id + }); + + //#region Decrement following count + User.update({ _id: follower._id }, { + $inc: { + followingCount: -1 + } + }); + //#endregion + + //#region Decrement followers count + User.update({ _id: followee._id }, { + $inc: { + followersCount: -1 + } + }); + //#endregion + + perUserFollowingChart.update(follower, followee, false); + + // Publish unfollow event + if (isLocalUser(follower)) { + packUser(followee, follower).then(packed => publishMainStream(follower._id, 'unfollow', packed)); + } + + // リモートにフォローをしていたらUndoFollow送信 + if (isLocalUser(follower) && isRemoteUser(followee)) { + const content = pack(renderUndo(renderFollow(follower, followee), follower)); + deliver(follower, content, followee.inbox); + } +} diff --git a/src/services/blocking/delete.ts b/src/services/blocking/delete.ts new file mode 100644 index 0000000000..bc331d491a --- /dev/null +++ b/src/services/blocking/delete.ts @@ -0,0 +1,28 @@ +import { isLocalUser, isRemoteUser, IUser } from '../../models/user'; +import Blocking from '../../models/blocking'; +import pack from '../../remote/activitypub/renderer'; +import renderBlock from '../../remote/activitypub/renderer/block'; +import renderUndo from '../../remote/activitypub/renderer/undo'; +import { deliver } from '../../queue'; + +export default async function(blocker: IUser, blockee: IUser) { + const blocking = await Blocking.findOne({ + blockerId: blocker._id, + blockeeId: blockee._id + }); + + if (blocking == null) { + console.warn('ブロック解除がリクエストされましたがブロックしていませんでした'); + return; + } + + Blocking.remove({ + _id: blocking._id + }); + + // deliver if remote bloking + if (isLocalUser(blocker) && isRemoteUser(blockee)) { + const content = pack(renderUndo(renderBlock(blocker, blockee), blocker)); + deliver(blocker, content, blockee.inbox); + } +} diff --git a/src/services/following/create.ts b/src/services/following/create.ts index 87d13c444b..38367399e3 100644 --- a/src/services/following/create.ts +++ b/src/services/following/create.ts @@ -1,15 +1,45 @@ import User, { isLocalUser, isRemoteUser, pack as packUser, IUser } from '../../models/user'; import Following from '../../models/following'; +import Blocking from '../../models/blocking'; import { publishMainStream } from '../../stream'; import notify from '../../notify'; import pack from '../../remote/activitypub/renderer'; import renderFollow from '../../remote/activitypub/renderer/follow'; import renderAccept from '../../remote/activitypub/renderer/accept'; +import renderReject from '../../remote/activitypub/renderer/reject'; import { deliver } from '../../queue'; import createFollowRequest from './requests/create'; import perUserFollowingChart from '../../chart/per-user-following'; export default async function(follower: IUser, followee: IUser, requestId?: string) { + // check blocking + const [ blocking, blocked ] = await Promise.all([ + Blocking.findOne({ + blockerId: follower._id, + blockeeId: followee._id, + }), + Blocking.findOne({ + blockerId: followee._id, + blockeeId: follower._id, + }) + ]); + + if (isRemoteUser(follower) && isLocalUser(followee) && blocked) { + // リモートフォローを受けてブロックしていた場合は、エラーにするのではなくRejectを送り返しておしまい。 + const content = pack(renderReject(renderFollow(follower, followee, requestId), followee)); + deliver(followee , content, follower.inbox); + return; + } else if (isRemoteUser(follower) && isLocalUser(followee) && blocking) { + // リモートフォローを受けてブロックされているはずの場合だったら、ブロック解除しておく。 + await Blocking.remove({ + _id: blocking._id + }); + } else { + // それ以外は単純に例外 + if (blocking != null) throw new Error('blocking'); + if (blocked != null) throw new Error('blocked'); + } + // フォロー対象が鍵アカウントである or // フォロワーがBotであり、フォロー対象がBotからのフォローに慎重である or // フォロワーがローカルユーザーであり、フォロー対象がリモートユーザーである diff --git a/src/services/following/requests/create.ts b/src/services/following/requests/create.ts index d28c93929a..a87e472ad8 100644 --- a/src/services/following/requests/create.ts +++ b/src/services/following/requests/create.ts @@ -5,8 +5,24 @@ import pack from '../../../remote/activitypub/renderer'; import renderFollow from '../../../remote/activitypub/renderer/follow'; import { deliver } from '../../../queue'; import FollowRequest from '../../../models/follow-request'; +import Blocking from '../../../models/blocking'; export default async function(follower: IUser, followee: IUser, requestId?: string) { + // check blocking + const [ blocking, blocked ] = await Promise.all([ + Blocking.findOne({ + blockerId: follower._id, + blockeeId: followee._id, + }), + Blocking.findOne({ + blockerId: followee._id, + blockeeId: follower._id, + }) + ]); + + if (blocking != null) throw new Error('blocking'); + if (blocked != null) throw new Error('blocked'); + await FollowRequest.insert({ createdAt: new Date(), followerId: follower._id, |