Merge pull request #1373 from akihikodaki/misc
Implement Follow activity
This commit is contained in:
		
						commit
						4fc04acdc1
					
				
					 4 changed files with 65 additions and 5 deletions
				
			
		| 
						 | 
					@ -2,6 +2,7 @@ import * as mongo from 'mongodb';
 | 
				
			||||||
import db from '../db/mongodb';
 | 
					import db from '../db/mongodb';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Following = db.get<IFollowing>('following');
 | 
					const Following = db.get<IFollowing>('following');
 | 
				
			||||||
 | 
					Following.createIndex(['followerId', 'followeeId'], { unique: true });
 | 
				
			||||||
export default Following;
 | 
					export default Following;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type IFollowing = {
 | 
					export type IFollowing = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
import { request } from 'https';
 | 
					import { request } from 'https';
 | 
				
			||||||
import { sign } from 'http-signature';
 | 
					import { sign } from 'http-signature';
 | 
				
			||||||
import { URL } from 'url';
 | 
					import { URL } from 'url';
 | 
				
			||||||
import User, { isLocalUser, pack as packUser, ILocalUser } from '../../models/user';
 | 
					import User, { isLocalUser, pack as packUser } from '../../models/user';
 | 
				
			||||||
import Following from '../../models/following';
 | 
					import Following from '../../models/following';
 | 
				
			||||||
import event from '../../publishers/stream';
 | 
					import event from '../../publishers/stream';
 | 
				
			||||||
import notify from '../../publishers/notify';
 | 
					import notify from '../../publishers/notify';
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ import render from '../../remote/activitypub/renderer/follow';
 | 
				
			||||||
import config from '../../config';
 | 
					import config from '../../config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default ({ data }, done) => Following.findOne({ _id: data.following }).then(({ followerId, followeeId }) => {
 | 
					export default ({ data }, done) => Following.findOne({ _id: data.following }).then(({ followerId, followeeId }) => {
 | 
				
			||||||
	const promisedFollower: Promise<ILocalUser> = User.findOne({ _id: followerId });
 | 
						const promisedFollower = User.findOne({ _id: followerId });
 | 
				
			||||||
	const promisedFollowee = User.findOne({ _id: followeeId });
 | 
						const promisedFollowee = User.findOne({ _id: followeeId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return Promise.all([
 | 
						return Promise.all([
 | 
				
			||||||
| 
						 | 
					@ -34,14 +34,18 @@ export default ({ data }, done) => Following.findOne({ _id: data.following }).th
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Publish follow event
 | 
							// Publish follow event
 | 
				
			||||||
		Promise.all([promisedFollower, promisedFollowee]).then(([follower, followee]) => {
 | 
							Promise.all([promisedFollower, promisedFollowee]).then(([follower, followee]) => {
 | 
				
			||||||
			const followerEvent = packUser(followee, follower)
 | 
								let followerEvent;
 | 
				
			||||||
				.then(packed => event(follower._id, 'follow', packed));
 | 
					 | 
				
			||||||
			let followeeEvent;
 | 
								let followeeEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (isLocalUser(follower)) {
 | 
				
			||||||
 | 
									followerEvent = packUser(followee, follower)
 | 
				
			||||||
 | 
										.then(packed => event(follower._id, 'follow', packed));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (isLocalUser(followee)) {
 | 
								if (isLocalUser(followee)) {
 | 
				
			||||||
				followeeEvent = packUser(follower, followee)
 | 
									followeeEvent = packUser(follower, followee)
 | 
				
			||||||
					.then(packed => event(followee._id, 'followed', packed));
 | 
										.then(packed => event(followee._id, 'followed', packed));
 | 
				
			||||||
			} else {
 | 
								} else if (isLocalUser(follower)) {
 | 
				
			||||||
				followeeEvent = new Promise((resolve, reject) => {
 | 
									followeeEvent = new Promise((resolve, reject) => {
 | 
				
			||||||
					const {
 | 
										const {
 | 
				
			||||||
						protocol,
 | 
											protocol,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										51
									
								
								src/remote/activitypub/act/follow.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/remote/activitypub/act/follow.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,51 @@
 | 
				
			||||||
 | 
					import { MongoError } from 'mongodb';
 | 
				
			||||||
 | 
					import parseAcct from '../../../acct/parse';
 | 
				
			||||||
 | 
					import Following from '../../../models/following';
 | 
				
			||||||
 | 
					import User from '../../../models/user';
 | 
				
			||||||
 | 
					import config from '../../../config';
 | 
				
			||||||
 | 
					import queue from '../../../queue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async (actor, activity) => {
 | 
				
			||||||
 | 
						const prefix = config.url + '/@';
 | 
				
			||||||
 | 
						const id = activity.object.id || activity.object;
 | 
				
			||||||
 | 
						let following;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!id.startsWith(prefix)) {
 | 
				
			||||||
 | 
							return null;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const { username, host } = parseAcct(id.slice(prefix.length));
 | 
				
			||||||
 | 
						if (host !== null) {
 | 
				
			||||||
 | 
							throw new Error();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const followee = await User.findOne({ username, host });
 | 
				
			||||||
 | 
						if (followee === null) {
 | 
				
			||||||
 | 
							throw new Error();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							following = await Following.insert({
 | 
				
			||||||
 | 
								createdAt: new Date(),
 | 
				
			||||||
 | 
								followerId: actor._id,
 | 
				
			||||||
 | 
								followeeId: followee._id
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						} catch (exception) {
 | 
				
			||||||
 | 
							// duplicate key error
 | 
				
			||||||
 | 
							if (exception instanceof MongoError && exception.code === 11000) {
 | 
				
			||||||
 | 
								return null;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							throw exception;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						await new Promise((resolve, reject) => {
 | 
				
			||||||
 | 
							queue.create('http', { type: 'follow', following: following._id }).save(error => {
 | 
				
			||||||
 | 
								if (error) {
 | 
				
			||||||
 | 
									reject(error);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									resolve(null);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
import create from './create';
 | 
					import create from './create';
 | 
				
			||||||
 | 
					import follow from './follow';
 | 
				
			||||||
import createObject from '../create';
 | 
					import createObject from '../create';
 | 
				
			||||||
import Resolver from '../resolver';
 | 
					import Resolver from '../resolver';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +16,9 @@ export default (actor, value, distribute) => {
 | 
				
			||||||
		case 'Create':
 | 
							case 'Create':
 | 
				
			||||||
			return create(resolver, actor, object, distribute);
 | 
								return create(resolver, actor, object, distribute);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case 'Follow':
 | 
				
			||||||
 | 
								return follow(actor, object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			return null;
 | 
								return null;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue