mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-10-26 19:14:12 +00:00 
			
		
		
		
	Implement remote follow
This commit is contained in:
		
							parent
							
								
									cba73d6bc1
								
							
						
					
					
						commit
						dc529711ce
					
				
					 11 changed files with 114 additions and 32 deletions
				
			
		|  | @ -1,8 +1,8 @@ | ||||||
| import * as mongo from 'mongodb'; | import * as mongo from 'mongodb'; | ||||||
| import Notification from '../../../models/notification'; | import Notification from '../models/notification'; | ||||||
| import Mute from '../../../models/mute'; | import Mute from '../models/mute'; | ||||||
| import event from '../../../common/event'; | import event from './event'; | ||||||
| import { pack } from '../../../models/notification'; | import { pack } from '../models/notification'; | ||||||
| 
 | 
 | ||||||
| export default ( | export default ( | ||||||
| 	notifiee: mongo.ObjectID, | 	notifiee: mongo.ObjectID, | ||||||
							
								
								
									
										8
									
								
								src/common/remote/activitypub/renderer/follow.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/common/remote/activitypub/renderer/follow.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | import config from '../../../../conf'; | ||||||
|  | import { IRemoteAccount } from '../../../../models/user'; | ||||||
|  | 
 | ||||||
|  | export default ({ username }, { account }) => ({ | ||||||
|  | 	type: 'Follow', | ||||||
|  | 	actor: `${config.url}/@${username}`, | ||||||
|  | 	object: (account as IRemoteAccount).uri | ||||||
|  | }); | ||||||
|  | @ -66,6 +66,7 @@ export default async (value, usernameLower, hostLower, acctLower) => { | ||||||
| 				id: object.publicKey.id, | 				id: object.publicKey.id, | ||||||
| 				publicKeyPem: object.publicKey.publicKeyPem | 				publicKeyPem: object.publicKey.publicKeyPem | ||||||
| 			}, | 			}, | ||||||
|  | 			inbox: object.inbox, | ||||||
| 			uri: object.id, | 			uri: object.id, | ||||||
| 		}, | 		}, | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| const WebFinger = require('webfinger.js'); | const WebFinger = require('webfinger.js'); | ||||||
| 
 | 
 | ||||||
| const webFinger = new WebFinger({}); | const webFinger = new WebFinger({ tls_only: false }); | ||||||
| 
 | 
 | ||||||
| type ILink = { | type ILink = { | ||||||
|   href: string; |   href: string; | ||||||
|  |  | ||||||
|  | @ -70,6 +70,7 @@ export type ILocalAccount = { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export type IRemoteAccount = { | export type IRemoteAccount = { | ||||||
|  | 	inbox: string; | ||||||
| 	uri: string; | 	uri: string; | ||||||
| 	publicKey: { | 	publicKey: { | ||||||
| 		id: string; | 		id: string; | ||||||
|  |  | ||||||
							
								
								
									
										89
									
								
								src/processor/http/follow.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/processor/http/follow.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | ||||||
|  | import { request } from 'https'; | ||||||
|  | import { sign } from 'http-signature'; | ||||||
|  | import { URL } from 'url'; | ||||||
|  | import User, { ILocalAccount, IRemoteAccount, pack as packUser } from '../../models/user'; | ||||||
|  | import Following from '../../models/following'; | ||||||
|  | import event from '../../common/event'; | ||||||
|  | import notify from '../../common/notify'; | ||||||
|  | import context from '../../common/remote/activitypub/renderer/context'; | ||||||
|  | import render from '../../common/remote/activitypub/renderer/follow'; | ||||||
|  | import config from '../../conf'; | ||||||
|  | 
 | ||||||
|  | export default ({ data }, done) => Following.findOne({ _id: data.following }).then(({ followerId, followeeId }) => { | ||||||
|  | 	const promisedFollower = User.findOne({ _id: followerId }); | ||||||
|  | 	const promisedFollowee = User.findOne({ _id: followeeId }); | ||||||
|  | 
 | ||||||
|  | 	return Promise.all([ | ||||||
|  | 		// Increment following count
 | ||||||
|  | 		User.update(followerId, { | ||||||
|  | 			$inc: { | ||||||
|  | 				followingCount: 1 | ||||||
|  | 			} | ||||||
|  | 		}), | ||||||
|  | 
 | ||||||
|  | 		// Increment followers count
 | ||||||
|  | 		User.update({ _id: followeeId }, { | ||||||
|  | 			$inc: { | ||||||
|  | 				followersCount: 1 | ||||||
|  | 			} | ||||||
|  | 		}), | ||||||
|  | 
 | ||||||
|  | 		// Notify
 | ||||||
|  | 		promisedFollowee.then(followee => followee.host === null ? | ||||||
|  | 			notify(followeeId, followerId, 'follow') : null), | ||||||
|  | 
 | ||||||
|  | 		// Publish follow event
 | ||||||
|  | 		Promise.all([promisedFollower, promisedFollowee]).then(([follower, followee]) => { | ||||||
|  | 			const followerEvent = packUser(followee, follower) | ||||||
|  | 				.then(packed => event(follower._id, 'follow', packed)); | ||||||
|  | 			let followeeEvent; | ||||||
|  | 
 | ||||||
|  | 			if (followee.host === null) { | ||||||
|  | 				followeeEvent = packUser(follower, followee) | ||||||
|  | 					.then(packed => event(followee._id, 'followed', packed)); | ||||||
|  | 			} else { | ||||||
|  | 				followeeEvent = new Promise((resolve, reject) => { | ||||||
|  | 					const { | ||||||
|  | 						protocol, | ||||||
|  | 						hostname, | ||||||
|  | 						port, | ||||||
|  | 						pathname, | ||||||
|  | 						search | ||||||
|  | 					} = new URL(followee.account as IRemoteAccount).inbox); | ||||||
|  | 
 | ||||||
|  | 					const req = request({ | ||||||
|  | 						protocol, | ||||||
|  | 						hostname, | ||||||
|  | 						port, | ||||||
|  | 						method: 'POST', | ||||||
|  | 						path: pathname + search, | ||||||
|  | 					}, res => { | ||||||
|  | 						res.on('close', () => { | ||||||
|  | 							if (res.statusCode >= 200 && res.statusCode < 300) { | ||||||
|  | 								resolve(); | ||||||
|  | 							} else { | ||||||
|  | 								reject(res); | ||||||
|  | 							} | ||||||
|  | 						}); | ||||||
|  | 
 | ||||||
|  | 						res.on('data', () => {}); | ||||||
|  | 						res.on('error', reject); | ||||||
|  | 					}); | ||||||
|  | 
 | ||||||
|  | 					sign(req, { | ||||||
|  | 						authorizationHeaderName: 'Signature', | ||||||
|  | 						key: (follower.account as ILocalAccount).keypair, | ||||||
|  | 						keyId: `acct:${follower.username}@${config.host}` | ||||||
|  | 					}); | ||||||
|  | 
 | ||||||
|  | 					const rendered = render(follower, followee); | ||||||
|  | 					rendered['@context'] = context; | ||||||
|  | 
 | ||||||
|  | 					req.end(JSON.stringify(rendered)); | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return Promise.all([followerEvent, followeeEvent]); | ||||||
|  | 		}) | ||||||
|  | 	]); | ||||||
|  | }).then(done, done); | ||||||
|  | @ -1,7 +1,9 @@ | ||||||
|  | import follow from './follow'; | ||||||
| import performActivityPub from './perform-activitypub'; | import performActivityPub from './perform-activitypub'; | ||||||
| import reportGitHubFailure from './report-github-failure'; | import reportGitHubFailure from './report-github-failure'; | ||||||
| 
 | 
 | ||||||
| const handlers = { | const handlers = { | ||||||
|  |   follow, | ||||||
|   performActivityPub, |   performActivityPub, | ||||||
|   reportGitHubFailure, |   reportGitHubFailure, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -2,10 +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 notify from '../../common/notify'; | import queue from '../../../../queue'; | ||||||
| import event from '../../../../common/event'; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Follow a user |  * Follow a user | ||||||
|  | @ -52,33 +51,15 @@ module.exports = (params, user) => new Promise(async (res, rej) => { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Create following
 | 	// Create following
 | ||||||
| 	await Following.insert({ | 	const { _id } = await Following.insert({ | ||||||
| 		createdAt: new Date(), | 		createdAt: new Date(), | ||||||
| 		followerId: follower._id, | 		followerId: follower._id, | ||||||
| 		followeeId: followee._id | 		followeeId: followee._id | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
|  | 	queue.create('http', { type: 'follow', following: _id }).save(); | ||||||
|  | 
 | ||||||
| 	// Send response
 | 	// Send response
 | ||||||
| 	res(); | 	res(); | ||||||
| 
 | 
 | ||||||
| 	// Increment following count
 |  | ||||||
| 	User.update(follower._id, { |  | ||||||
| 		$inc: { |  | ||||||
| 			followingCount: 1 |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| 
 |  | ||||||
| 	// Increment followers count
 |  | ||||||
| 	User.update({ _id: followee._id }, { |  | ||||||
| 		$inc: { |  | ||||||
| 			followersCount: 1 |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| 
 |  | ||||||
| 	// Publish follow event
 |  | ||||||
| 	event(follower._id, 'follow', await packUser(followee, follower)); |  | ||||||
| 	event(followee._id, 'followed', await packUser(follower, followee)); |  | ||||||
| 
 |  | ||||||
| 	// Notify
 |  | ||||||
| 	notify(followee._id, follower._id, 'follow'); |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | @ -14,9 +14,9 @@ import DriveFile from '../../../../models/drive-file'; | ||||||
| import Watching from '../../../../models/post-watching'; | import Watching from '../../../../models/post-watching'; | ||||||
| import ChannelWatching from '../../../../models/channel-watching'; | import ChannelWatching from '../../../../models/channel-watching'; | ||||||
| import { pack } from '../../../../models/post'; | import { pack } from '../../../../models/post'; | ||||||
| import notify from '../../common/notify'; |  | ||||||
| import watch from '../../common/watch-post'; | import watch from '../../common/watch-post'; | ||||||
| import event, { pushSw, publishChannelStream } from '../../../../common/event'; | import event, { pushSw, publishChannelStream } from '../../../../common/event'; | ||||||
|  | import notify from '../../../../common/notify'; | ||||||
| import getAcct from '../../../../common/user/get-acct'; | import getAcct from '../../../../common/user/get-acct'; | ||||||
| import parseAcct from '../../../../common/user/parse-acct'; | import parseAcct from '../../../../common/user/parse-acct'; | ||||||
| import config from '../../../../conf'; | import config from '../../../../conf'; | ||||||
|  |  | ||||||
|  | @ -5,9 +5,9 @@ import $ from 'cafy'; | ||||||
| import Vote from '../../../../../models/poll-vote'; | import Vote from '../../../../../models/poll-vote'; | ||||||
| import Post from '../../../../../models/post'; | import Post from '../../../../../models/post'; | ||||||
| import Watching from '../../../../../models/post-watching'; | import Watching from '../../../../../models/post-watching'; | ||||||
| import notify from '../../../common/notify'; |  | ||||||
| import watch from '../../../common/watch-post'; | import watch from '../../../common/watch-post'; | ||||||
| import { publishPostStream } from '../../../../../common/event'; | import { publishPostStream } from '../../../../../common/event'; | ||||||
|  | import notify from '../../../../../common/notify'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Vote poll of a post |  * Vote poll of a post | ||||||
|  |  | ||||||
|  | @ -6,9 +6,9 @@ import Reaction from '../../../../../models/post-reaction'; | ||||||
| import Post, { pack as packPost } from '../../../../../models/post'; | import Post, { pack as packPost } from '../../../../../models/post'; | ||||||
| import { pack as packUser } from '../../../../../models/user'; | import { pack as packUser } from '../../../../../models/user'; | ||||||
| import Watching from '../../../../../models/post-watching'; | import Watching from '../../../../../models/post-watching'; | ||||||
| import notify from '../../../common/notify'; |  | ||||||
| import watch from '../../../common/watch-post'; | import watch from '../../../common/watch-post'; | ||||||
| import { publishPostStream, pushSw } from '../../../../../common/event'; | import { publishPostStream, pushSw } from '../../../../../common/event'; | ||||||
|  | import notify from '../../../../../common/notify'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * React to a post |  * React to a post | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue