enigma-bbs/core/activitypub/collection.js

127 lines
3.7 KiB
JavaScript

const { makeUserUrl } = require('./util');
const ActivityPubObject = require('./object');
const apDb = require('../database').dbs.activitypub;
const { getISOTimestampString } = require('../database');
const { isString, get } = require('lodash');
module.exports = class Collection extends ActivityPubObject {
constructor(obj) {
super(obj);
}
static followers(owningUser, page, webServer, cb) {
return Collection.getOrdered(
'followers',
owningUser,
false,
page,
e => e.id,
webServer,
cb
);
}
static following(owningUser, page, webServer, cb) {
return Collection.getOrdered(
'following',
owningUser,
false,
page,
e => get(e, 'object.id'),
webServer,
cb
);
}
static addFollower(owningUser, followingActor, cb) {
return Collection.addToCollection('followers', owningUser, followingActor, cb);
}
static getOrdered(name, owningUser, includePrivate, page, mapper, webServer, cb) {
// :TODD: |includePrivate| handling
const followersUrl =
makeUserUrl(webServer, owningUser, '/ap/users/') + `/${name}`;
if (!page) {
return apDb.get(
`SELECT COUNT(id) AS count
FROM collection_entry
WHERE name = ?;`,
[name],
(err, row) => {
if (err) {
return cb(err);
}
let obj;
if (row.count > 0) {
obj = {
id: followersUrl,
type: 'OrderedCollection',
first: `${followersUrl}?page=1`,
totalItems: row.count,
};
} else {
obj = {
id: followersUrl,
type: 'OrderedCollection',
totalItems: 0,
orderedItems: [],
};
}
return cb(null, new Collection(obj));
}
);
}
// :TODO: actual paging...
apDb.all(
`SELECT entry_json
FROM collection_entry
WHERE user_id = ? AND name = ?
ORDER BY timestamp;`,
[owningUser.userId, name],
(err, entries) => {
if (err) {
return cb(err);
}
entries = entries || [];
if (mapper && entries.length > 0) {
entries = entries.map(mapper);
}
const obj = {
id: `${followersUrl}/page=${page}`,
type: 'OrderedCollectionPage',
totalItems: entries.length,
orderedItems: entries,
partOf: followersUrl,
};
return cb(null, new Collection(obj));
}
);
}
static addToCollection(name, owningUser, entry, cb) {
if (!isString(entry)) {
entry = JSON.stringify(entry);
}
apDb.run(
`INSERT OR IGNORE INTO collection_entry (name, timestamp, user_id, entry_json)
VALUES (?, ?, ?, ?);`,
[name, getISOTimestampString(), owningUser.userId, entry],
function res(err) {
// non-arrow for 'this' scope
if (err) {
return cb(err);
}
return cb(err, this.lastID);
}
);
}
};