diff --git a/core/activitypub/actor_search.js b/core/activitypub/actor_search.js index a338a212..6ce5c563 100644 --- a/core/activitypub/actor_search.js +++ b/core/activitypub/actor_search.js @@ -3,8 +3,7 @@ const { Errors } = require('../enig_error'); const Actor = require('../activitypub/actor'); const moment = require('moment'); const { htmlToMessageBody } = require('./util'); -const { getJson } = require('../http_util'); -const { ActivityStreamMediaType } = require('./const'); +const Collection = require('./collection'); // deps const async = require('async'); @@ -156,35 +155,15 @@ exports.getModule = class ActivityPubActorSearch extends MenuModule { manualFollowersView.setText(remoteActor.manuallyApprovesFollowers); const followerCountView = v(MciViewIds.view.numberFollowers); - this._retrieveCountFromUrl( + this._updateViewWithCollectionItemCount( remoteActor.followers, - (err, followerCount) => { - if (err) { - this.client.log.warn( - { err: err }, - 'Unable to get follower count' - ); - followerCountView.setText('--'); - } else { - followerCountView.setText(followerCount); - } - } + followerCountView ); const followingCountView = v(MciViewIds.view.numberFollowing); - this._retrieveCountFromUrl( + this._updateViewWithCollectionItemCount( remoteActor.following, - (err, followingCount) => { - if (err) { - this.client.log.warn( - { err: err }, - 'Unable to get following count' - ); - followingCountView.setText('--'); - } else { - followingCountView.setText(followingCount); - } - } + followingCountView ); const summaryView = v(MciViewIds.view.summary); @@ -229,33 +208,28 @@ exports.getModule = class ActivityPubActorSearch extends MenuModule { ); } - _retrieveCountFromUrl(countUrl, cb) { - async.waterfall( - [ - callback => { - countUrl = countUrl.trim(); - if (isEmpty(countUrl)) { - return callback( - Errors.UnexpectedState('Count URL can not be empty.') - ); - } - const headers = { - Accept: ActivityStreamMediaType, - }; - getJson(countUrl, { headers }, (err, jsonResponse) => { - if (err) { - return callback(err, jsonResponse); - } - return callback(null, jsonResponse); - }); - }, - (jsonResponse, callback) => { - return callback(null, jsonResponse.totalItems); - }, - ], - (err, result) => { - return cb(err, result); + _updateViewWithCollectionItemCount(collectionUrl, view) { + this._retrieveCountFromCollectionUrl(collectionUrl, (err, count) => { + if (err) { + this.client.log.warn( + { err: err }, + `Unable to get Collection count for ${collectionUrl}` + ); + view.setText('--'); + } else { + view.setText(count); } - ); + }); + } + + _retrieveCountFromCollectionUrl(collectionUrl, cb) { + collectionUrl = collectionUrl.trim(); + if (isEmpty(collectionUrl)) { + return cb(Errors.UnexpectedState('Count URL can not be empty.')); + } + + Collection.getRemoteCollectionStats(collectionUrl, (err, stats) => { + return cb(err, stats.totalItems); + }); } }; diff --git a/core/activitypub/collection.js b/core/activitypub/collection.js index c62c8527..b8fb49d4 100644 --- a/core/activitypub/collection.js +++ b/core/activitypub/collection.js @@ -3,8 +3,12 @@ const ActivityPubObject = require('./object'); const apDb = require('../database').dbs.activitypub; const { getISOTimestampString } = require('../database'); const { Errors } = require('../enig_error.js'); -const { PublicCollectionId: APPublicCollectionId } = require('./const'); +const { + PublicCollectionId: APPublicCollectionId, + ActivityStreamMediaType, +} = require('./const'); const UserProps = require('../user_property'); +const { getJson } = require('../http_util'); // deps const { isString } = require('lodash'); @@ -18,6 +22,33 @@ module.exports = class Collection extends ActivityPubObject { return APPublicCollectionId; } + static getRemoteCollectionStats(collectionUrl, cb) { + const headers = { + Accept: ActivityStreamMediaType, + }; + getJson(collectionUrl, { headers }, (err, collection) => { + if (err) { + return cb(err); + } + + // :TODO: validate headers? + + collection = new Collection(collection); + if (!collection.isValid()) { + return cb(Errors.Invalid('Invalid Collection')); + } + + const { totalItems, type, id, summary } = collection; + + return cb(null, { + totalItems, + type, + id, + summary, + }); + }); + } + static followers(collectionId, page, cb) { return Collection.publicOrderedById( 'followers',