| 
									
										
										
										
											2023-05-17 13:13:30 -04:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const nconf = require('nconf'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 14:59:47 -04:00
										 |  |  | const user = require('../../user'); | 
					
						
							| 
									
										
										
										
											2023-06-21 17:16:37 -04:00
										 |  |  | const activitypub = require('../../activitypub'); | 
					
						
							| 
									
										
										
										
											2023-12-08 10:55:16 -05:00
										 |  |  | const api = require('../../api'); | 
					
						
							| 
									
										
										
										
											2023-06-28 14:59:39 -04:00
										 |  |  | const helpers = require('../helpers'); | 
					
						
							| 
									
										
										
										
											2023-05-17 13:13:30 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | const Controller = module.exports; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 17:16:37 -04:00
										 |  |  | Controller.profiles = require('./profiles'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-17 13:13:30 -04:00
										 |  |  | Controller.getActor = async (req, res) => { | 
					
						
							|  |  |  | 	// todo: view:users priv gate
 | 
					
						
							|  |  |  | 	const { userslug } = req.params; | 
					
						
							|  |  |  | 	const { uid } = res.locals; | 
					
						
							|  |  |  | 	const { username, aboutme, picture, 'cover:url': cover } = await user.getUserData(uid); | 
					
						
							|  |  |  | 	const publicKey = await activitypub.getPublicKey(uid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	res.status(200).json({ | 
					
						
							|  |  |  | 		'@context': [ | 
					
						
							|  |  |  | 			'https://www.w3.org/ns/activitystreams', | 
					
						
							|  |  |  | 			'https://w3id.org/security/v1', | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 		id: `${nconf.get('url')}/user/${userslug}`, | 
					
						
							|  |  |  | 		url: `${nconf.get('url')}/user/${userslug}`, | 
					
						
							|  |  |  | 		followers: `${nconf.get('url')}/user/${userslug}/followers`, | 
					
						
							|  |  |  | 		following: `${nconf.get('url')}/user/${userslug}/following`, | 
					
						
							|  |  |  | 		inbox: `${nconf.get('url')}/user/${userslug}/inbox`, | 
					
						
							|  |  |  | 		outbox: `${nconf.get('url')}/user/${userslug}/outbox`, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		type: 'Person', | 
					
						
							|  |  |  | 		preferredUsername: username, | 
					
						
							|  |  |  | 		summary: aboutme, | 
					
						
							|  |  |  | 		icon: picture ? `${nconf.get('url')}${picture}` : null, | 
					
						
							|  |  |  | 		image: cover ? `${nconf.get('url')}${cover}` : null, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		publicKey: { | 
					
						
							| 
									
										
										
										
											2023-06-19 17:29:22 -04:00
										 |  |  | 			id: `${nconf.get('url')}/user/${userslug}#key`, | 
					
						
							|  |  |  | 			owner: `${nconf.get('url')}/user/${userslug}`, | 
					
						
							| 
									
										
										
										
											2023-05-17 13:13:30 -04:00
										 |  |  | 			publicKeyPem: publicKey, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-05-25 14:29:06 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-28 15:42:29 -04:00
										 |  |  | Controller.getFollowing = async (req, res) => { | 
					
						
							|  |  |  | 	const { followingCount: totalItems } = await user.getUserFields(res.locals.uid, ['followingCount']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const page = parseInt(req.query.page, 10) || 1; | 
					
						
							|  |  |  | 	const resultsPerPage = 50; | 
					
						
							|  |  |  | 	const start = Math.max(0, page - 1) * resultsPerPage; | 
					
						
							|  |  |  | 	const stop = start + resultsPerPage - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	let orderedItems = await user.getFollowing(res.locals.uid, start, stop); | 
					
						
							|  |  |  | 	orderedItems = orderedItems.map(({ userslug }) => `${nconf.get('url')}/user/${userslug}`); | 
					
						
							|  |  |  | 	res.status(200).json({ | 
					
						
							|  |  |  | 		'@context': 'https://www.w3.org/ns/activitystreams', | 
					
						
							|  |  |  | 		type: 'OrderedCollection', | 
					
						
							|  |  |  | 		totalItems, | 
					
						
							|  |  |  | 		orderedItems, | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Controller.getFollowers = async (req, res) => { | 
					
						
							|  |  |  | 	const { followerCount: totalItems } = await user.getUserFields(res.locals.uid, ['followerCount']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const page = parseInt(req.query.page, 10) || 1; | 
					
						
							|  |  |  | 	const resultsPerPage = 50; | 
					
						
							|  |  |  | 	const start = Math.max(0, page - 1) * resultsPerPage; | 
					
						
							|  |  |  | 	const stop = start + resultsPerPage - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	let orderedItems = await user.getFollowers(res.locals.uid, start, stop); | 
					
						
							|  |  |  | 	orderedItems = orderedItems.map(({ userslug }) => `${nconf.get('url')}/user/${userslug}`); | 
					
						
							|  |  |  | 	res.status(200).json({ | 
					
						
							|  |  |  | 		'@context': 'https://www.w3.org/ns/activitystreams', | 
					
						
							|  |  |  | 		type: 'OrderedCollection', | 
					
						
							|  |  |  | 		totalItems, | 
					
						
							|  |  |  | 		orderedItems, | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-25 14:29:06 -04:00
										 |  |  | Controller.getOutbox = async (req, res) => { | 
					
						
							|  |  |  | 	// stub
 | 
					
						
							|  |  |  | 	res.status(200).json({ | 
					
						
							|  |  |  | 		'@context': 'https://www.w3.org/ns/activitystreams', | 
					
						
							|  |  |  | 		type: 'OrderedCollection', | 
					
						
							|  |  |  | 		totalItems: 0, | 
					
						
							|  |  |  | 		orderedItems: [], | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Controller.postOutbox = async (req, res) => { | 
					
						
							|  |  |  | 	// This is a client-to-server feature so it is deliberately not implemented at this time.
 | 
					
						
							|  |  |  | 	res.sendStatus(405); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Controller.getInbox = async (req, res) => { | 
					
						
							|  |  |  | 	// This is a client-to-server feature so it is deliberately not implemented at this time.
 | 
					
						
							|  |  |  | 	res.sendStatus(405); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Controller.postInbox = async (req, res) => { | 
					
						
							| 
									
										
										
										
											2023-12-08 10:55:16 -05:00
										 |  |  | 	// Note: internal-only, hence no exposure via src/api
 | 
					
						
							| 
									
										
										
										
											2023-06-28 14:59:39 -04:00
										 |  |  | 	switch (req.body.type) { | 
					
						
							|  |  |  | 		case 'Follow': { | 
					
						
							|  |  |  | 			await activitypub.inbox.follow(req.body.actor.name, req.body.object.name); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case 'Unfollow': { | 
					
						
							|  |  |  | 			await activitypub.inbox.unfollow(req.body.actor.name, req.body.object.name); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-12-13 13:15:03 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case 'Accept': { | 
					
						
							|  |  |  | 			await activitypub.inbox.accept(req); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case 'Undo': { | 
					
						
							|  |  |  | 			await activitypub.inbox.undo(req); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: { | 
					
						
							|  |  |  | 			console.log('Unhandled Activity!!!'); | 
					
						
							|  |  |  | 			console.log(req.body); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-06-28 14:59:39 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-06-19 17:29:22 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	res.sendStatus(201); | 
					
						
							| 
									
										
										
										
											2023-05-25 14:29:06 -04:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2023-06-23 14:59:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Main ActivityPub verbs | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Controller.follow = async (req, res) => { | 
					
						
							| 
									
										
										
										
											2023-12-08 10:55:16 -05:00
										 |  |  | 	const { uid: actorId } = req.params; | 
					
						
							|  |  |  | 	helpers.formatApiResponse(200, res, await api.activitypub.follow(req, { actorId })); | 
					
						
							| 
									
										
										
										
											2023-06-23 14:59:47 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Controller.unfollow = async (req, res) => { | 
					
						
							| 
									
										
										
										
											2023-12-08 10:55:16 -05:00
										 |  |  | 	const { uid: actorId } = req.params; | 
					
						
							|  |  |  | 	helpers.formatApiResponse(200, res, await api.activitypub.unfollow(req, { actorId })); | 
					
						
							| 
									
										
										
										
											2023-06-23 14:59:47 -04:00
										 |  |  | }; |