mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
159 lines
5.2 KiB
JavaScript
159 lines
5.2 KiB
JavaScript
import {
|
|
sendAcceptActivity,
|
|
sendRejectActivity,
|
|
extractNameFromId,
|
|
extractDomainFromUrl,
|
|
signAndSend
|
|
} from './utils'
|
|
import request from 'request'
|
|
import as from 'activitystrea.ms'
|
|
import NitroDatasource from './NitroDatasource'
|
|
import router from './routes'
|
|
import dotenv from 'dotenv'
|
|
import { resolve } from 'path'
|
|
const debug = require('debug')('ea')
|
|
|
|
let activityPub = null
|
|
|
|
export { activityPub }
|
|
|
|
export default class ActivityPub {
|
|
constructor (domain, port) {
|
|
if (domain === 'localhost') { this.domain = `${domain}:${port}` } else { this.domain = domain }
|
|
this.port = port
|
|
this.dataSource = new NitroDatasource(this.domain)
|
|
}
|
|
static init (server) {
|
|
if (!activityPub) {
|
|
dotenv.config({ path: resolve('src', 'activitypub', '.env') })
|
|
// const app = express()
|
|
activityPub = new ActivityPub(process.env.ACTIVITYPUB_DOMAIN || 'localhost', process.env.ACTIVITYPUB_PORT || 4100)
|
|
server.express.set('ap', activityPub)
|
|
server.express.use(router)
|
|
debug('ActivityPub service added to graphql endpoint')
|
|
} else {
|
|
debug('ActivityPub service already added to graphql endpoint')
|
|
}
|
|
}
|
|
|
|
getFollowersCollection (actorId) {
|
|
return this.dataSource.getFollowersCollection(actorId)
|
|
}
|
|
|
|
getFollowersCollectionPage (actorId) {
|
|
return this.dataSource.getFollowersCollectionPage(actorId)
|
|
}
|
|
|
|
getFollowingCollection (actorId) {
|
|
return this.dataSource.getFollowingCollection(actorId)
|
|
}
|
|
|
|
getFollowingCollectionPage (actorId) {
|
|
return this.dataSource.getFollowingCollectionPage(actorId)
|
|
}
|
|
|
|
getOutboxCollection (actorId) {
|
|
return this.dataSource.getOutboxCollection(actorId)
|
|
}
|
|
|
|
getOutboxCollectionPage (actorId) {
|
|
return this.dataSource.getOutboxCollectionPage(actorId)
|
|
}
|
|
|
|
handleFollowActivity (activity) {
|
|
debug(`inside FOLLOW ${activity.actor}`)
|
|
let toActorName = extractNameFromId(activity.object)
|
|
let fromDomain = extractDomainFromUrl(activity.actor)
|
|
const dataSource = this.dataSource
|
|
|
|
return new Promise((resolve, reject) => {
|
|
request({
|
|
url: activity.actor,
|
|
headers: {
|
|
'Accept': 'application/activity+json'
|
|
}
|
|
}, async (err, response, toActorObject) => {
|
|
if (err) return reject(err)
|
|
debug(`name = ${toActorName}@${this.domain}`)
|
|
// save shared inbox
|
|
await this.dataSource.addSharedInboxEndpoint(toActorObject.endpoints.sharedInbox)
|
|
|
|
let followersCollectionPage = await this.dataSource.getFollowersCollectionPage(activity.object)
|
|
|
|
const followActivity = as.follow()
|
|
.id(activity.id)
|
|
.actor(activity.actor)
|
|
.object(activity.object)
|
|
|
|
// add follower if not already in collection
|
|
if (followersCollectionPage.orderedItems.includes(activity.actor)) {
|
|
debug('follower already in collection!')
|
|
debug(`inbox = ${toActorObject.inbox}`)
|
|
resolve(sendRejectActivity(followActivity, toActorName, fromDomain, toActorObject.inbox))
|
|
} else {
|
|
followersCollectionPage.orderedItems.push(activity.actor)
|
|
}
|
|
debug(`toActorObject = ${toActorObject}`)
|
|
toActorObject = typeof toActorObject !== 'object' ? JSON.parse(toActorObject) : toActorObject
|
|
debug(`followers = ${JSON.stringify(followersCollectionPage.orderedItems, null, 2)}`)
|
|
debug(`inbox = ${toActorObject.inbox}`)
|
|
debug(`outbox = ${toActorObject.outbox}`)
|
|
debug(`followers = ${toActorObject.followers}`)
|
|
debug(`following = ${toActorObject.following}`)
|
|
|
|
// TODO save after accept activity for the corresponding follow is received
|
|
try {
|
|
await dataSource.saveFollowersCollectionPage(followersCollectionPage)
|
|
debug('follow activity saved')
|
|
resolve(sendAcceptActivity(followActivity, toActorName, fromDomain, toActorObject.inbox))
|
|
} catch (e) {
|
|
debug('followers update error!', e)
|
|
resolve(sendRejectActivity(followActivity, toActorName, fromDomain, toActorObject.inbox))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
handleUndoActivity (activity) {
|
|
debug('inside UNDO')
|
|
switch (activity.object.type) {
|
|
case 'Follow':
|
|
const followActivity = activity.object
|
|
return this.dataSource.undoFollowActivity(followActivity.actor, followActivity.object)
|
|
default:
|
|
}
|
|
}
|
|
|
|
handleCreateActivity (activity) {
|
|
debug('inside create')
|
|
switch (activity.object.type) {
|
|
case 'Article':
|
|
case 'Note':
|
|
const articleObject = activity.object
|
|
if (articleObject.inReplyTo) {
|
|
return this.dataSource.createComment(activity)
|
|
} else {
|
|
return this.dataSource.createPost(activity)
|
|
}
|
|
default:
|
|
}
|
|
}
|
|
|
|
handleDeleteActivity (activity) {
|
|
debug('inside delete')
|
|
}
|
|
|
|
async sendActivity (activity) {
|
|
if (Array.isArray(activity.to) && activity.to.includes('https://www.w3.org/ns/activitystreams#Public')) {
|
|
delete activity.send
|
|
const fromName = extractNameFromId(activity.actor)
|
|
const sharedInboxEndpoints = await this.dataSource.getSharedInboxEndpoints()
|
|
await Promise.all(
|
|
sharedInboxEndpoints.map((el) => {
|
|
return signAndSend(activity, fromName, new URL(el).host, el)
|
|
})
|
|
)
|
|
}
|
|
}
|
|
}
|