Implement remote account unfollow

This commit is contained in:
Akihiko Odaki 2018-04-03 17:18:06 +09:00
parent 6b66ec1231
commit 4b507ed349
6 changed files with 81 additions and 47 deletions

View file

@ -3,6 +3,7 @@ import follow from './follow';
import performActivityPub from './perform-activitypub'; import performActivityPub from './perform-activitypub';
import processInbox from './process-inbox'; import processInbox from './process-inbox';
import reportGitHubFailure from './report-github-failure'; import reportGitHubFailure from './report-github-failure';
import unfollow from './unfollow';
const handlers = { const handlers = {
deliverPost, deliverPost,
@ -10,6 +11,7 @@ const handlers = {
performActivityPub, performActivityPub,
processInbox, processInbox,
reportGitHubFailure, reportGitHubFailure,
unfollow
}; };
export default (job, done) => handlers[job.data.type](job).then(() => done(), done); export default (job, done) => handlers[job.data.type](job).then(() => done(), done);

View file

@ -0,0 +1,54 @@
import FollowedLog from '../../models/followed-log';
import Following from '../../models/following';
import FollowingLog from '../../models/following-log';
import User, { isRemoteUser, pack as packUser } from '../../models/user';
import stream from '../../publishers/stream';
import renderFollow from '../../remote/activitypub/renderer/follow';
import renderUndo from '../../remote/activitypub/renderer/undo';
import context from '../../remote/activitypub/renderer/context';
import request from '../../remote/request';
export default async ({ data }) => {
// Delete following
const following = await Following.findOneAndDelete({ _id: data.id });
if (following === null) {
return;
}
const promisedFollower = User.findOne({ _id: following.followerId });
const promisedFollowee = User.findOne({ _id: following.followeeId });
await Promise.all([
// Decrement following count
User.update({ _id: following.followerId }, { $inc: { followingCount: -1 } }),
promisedFollower.then(({ followingCount }) => FollowingLog.insert({
userId: following.followerId,
count: followingCount - 1
})),
// Decrement followers count
User.update({ _id: following.followeeId }, { $inc: { followersCount: -1 } }),
promisedFollowee.then(({ followersCount }) => FollowedLog.insert({
userId: following.followeeId,
count: followersCount - 1
})),
// Publish follow event
Promise.all([promisedFollower, promisedFollowee]).then(async ([follower, followee]) => {
if (isRemoteUser(follower)) {
return;
}
const promisedPackedUser = packUser(followee, follower);
if (isRemoteUser(followee)) {
const undo = renderUndo(renderFollow(follower, followee));
undo['@context'] = context;
await request(follower, followee.account.inbox, undo);
}
stream(follower._id, 'unfollow', promisedPackedUser);
})
]);
};

View file

@ -15,7 +15,7 @@ export default async (resolver, actor, activity) => {
switch (result.object.$ref) { switch (result.object.$ref) {
case 'following': case 'following':
await unfollow(result.resolver, result.object); await unfollow(result.object);
} }
})); }));

View file

@ -1,24 +1,11 @@
import FollowedLog from '../../../../models/followed-log'; import queue from '../../../../queue';
import Following from '../../../../models/following';
import FollowingLog from '../../../../models/following-log';
import User from '../../../../models/user';
export default async (resolver, { $id }) => { export default ({ $id }) => new Promise((resolve, reject) => {
const following = await Following.findOneAndDelete({ _id: $id }); queue.create('http', { type: 'unfollow', id: $id }).save(error => {
if (following === null) { if (error) {
return; reject(error);
} else {
resolve();
} }
});
await Promise.all([ });
User.update({ _id: following.followerId }, { $inc: { followingCount: -1 } }),
User.findOne({ _id: following.followerId }).then(({ followingCount }) => FollowingLog.insert({
userId: following.followerId,
count: followingCount - 1
})),
User.update({ _id: following.followeeId }, { $inc: { followersCount: -1 } }),
User.findOne({ _id: following.followeeId }).then(({ followersCount }) => FollowedLog.insert({
userId: following.followeeId,
count: followersCount - 1
})),
]);
};

View file

@ -0,0 +1,4 @@
export default object => ({
type: 'Undo',
object
});

View file

@ -2,9 +2,9 @@
* Module dependencies * Module dependencies
*/ */
import $ from 'cafy'; import $ from 'cafy';
import User, { pack as packUser } from '../../../../models/user'; import User from '../../../../models/user';
import Following from '../../../../models/following'; import Following from '../../../../models/following';
import event from '../../../../publishers/stream'; import queue from '../../../../queue';
/** /**
* Unfollow a user * Unfollow a user
@ -49,28 +49,15 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
return rej('already not following'); return rej('already not following');
} }
// Delete following queue.create('http', {
await Following.findOneAndDelete({ type: 'unfollow',
_id: exist._id id: exist._id
}); }).save(error => {
if (error) {
return rej('unfollow failed');
}
// Send response // Send response
res(); res();
// Decrement following count
User.update({ _id: follower._id }, {
$inc: {
followingCount: -1
}
}); });
// Decrement followers count
User.update({ _id: followee._id }, {
$inc: {
followersCount: -1
}
});
// Publish follow event
event(follower._id, 'unfollow', await packUser(followee, follower));
}); });