Users can now accept a follow request; Deny and remove next
This commit is contained in:
parent
d5ab53ecad
commit
460070e61d
Binary file not shown.
|
@ -1321,7 +1321,7 @@
|
||||||
activityPubSocialManager: {
|
activityPubSocialManager: {
|
||||||
config: {
|
config: {
|
||||||
selectedActorInfoFormat: "|00|15{preferredUsername} |08(|02{name}|08)\n|07following|08: {statusIndicator}\n\n|06{plainTextSummary}"
|
selectedActorInfoFormat: "|00|15{preferredUsername} |08(|02{name}|08)\n|07following|08: {statusIndicator}\n\n|06{plainTextSummary}"
|
||||||
statusIndicatorEnabled: "|00|10√"
|
statusFollowing: "|00|10√"
|
||||||
staticIndicatorDisabled: "|00|12X"
|
staticIndicatorDisabled: "|00|12X"
|
||||||
}
|
}
|
||||||
0: {
|
0: {
|
||||||
|
@ -1339,7 +1339,7 @@
|
||||||
height: 15
|
height: 15
|
||||||
width: 34
|
width: 34
|
||||||
}
|
}
|
||||||
TM3: {
|
HM3: {
|
||||||
focusTextStyle: first lower
|
focusTextStyle: first lower
|
||||||
styleSGR1: "|00|08"
|
styleSGR1: "|00|08"
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,17 @@ module.exports = class Collection extends ActivityPubObject {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static followRequests(owningUser, page, cb) {
|
||||||
|
return Collection.ownedOrderedByUser(
|
||||||
|
Collections.FollowRequests,
|
||||||
|
owningUser,
|
||||||
|
true, // private
|
||||||
|
page,
|
||||||
|
null, // return full Follow Request Activity
|
||||||
|
cb
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static outbox(collectionId, page, cb) {
|
static outbox(collectionId, page, cb) {
|
||||||
return Collection.publicOrderedById(
|
return Collection.publicOrderedById(
|
||||||
Collections.Outbox,
|
Collections.Outbox,
|
||||||
|
@ -97,16 +108,16 @@ module.exports = class Collection extends ActivityPubObject {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static addFollowRequest(owningUser, requestingActor, ignoreDupes, cb) {
|
static addFollowRequest(owningUser, requestActivity, cb) {
|
||||||
const collectionId = Endpoints.makeUserUrl(owningUser) + 'follow-requests';
|
const collectionId = Endpoints.makeUserUrl(owningUser) + '/follow-requests';
|
||||||
return Collection.addToCollection(
|
return Collection.addToCollection(
|
||||||
Collections.FollowRequests,
|
Collections.FollowRequests,
|
||||||
owningUser,
|
owningUser,
|
||||||
collectionId,
|
collectionId,
|
||||||
requestingActor.id, // Actor requesting to follow owningUser
|
requestActivity.id,
|
||||||
requestingActor,
|
requestActivity,
|
||||||
true,
|
true, // private
|
||||||
ignoreDupes,
|
true, // ignoreDupes
|
||||||
cb
|
cb
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -549,7 +560,12 @@ module.exports = class Collection extends ActivityPubObject {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
entries = entries || [];
|
try {
|
||||||
|
entries = (entries || []).map(e => JSON.parse(e.object_json));
|
||||||
|
} catch (e) {
|
||||||
|
Log.error(`Collection "${collectionId}" error: ${e.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
if (mapper && entries.length > 0) {
|
if (mapper && entries.length > 0) {
|
||||||
entries = entries.map(mapper);
|
entries = entries.map(mapper);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,14 @@ const ActivityPubObject = require('./object');
|
||||||
const UserProps = require('../user_property');
|
const UserProps = require('../user_property');
|
||||||
const { Errors } = require('../enig_error');
|
const { Errors } = require('../enig_error');
|
||||||
const Collection = require('./collection');
|
const Collection = require('./collection');
|
||||||
|
const Actor = require('./actor');
|
||||||
|
const Activity = require('./activity');
|
||||||
|
|
||||||
|
const async = require('async');
|
||||||
|
|
||||||
exports.sendFollowRequest = sendFollowRequest;
|
exports.sendFollowRequest = sendFollowRequest;
|
||||||
exports.sendUnfollowRequest = sendUnfollowRequest;
|
exports.sendUnfollowRequest = sendUnfollowRequest;
|
||||||
|
exports.acceptFollowRequest = acceptFollowRequest;
|
||||||
|
|
||||||
function sendFollowRequest(fromUser, toActor, cb) {
|
function sendFollowRequest(fromUser, toActor, cb) {
|
||||||
const fromActorId = fromUser.getProperty(UserProps.ActivityPubActorId);
|
const fromActorId = fromUser.getProperty(UserProps.ActivityPubActorId);
|
||||||
|
@ -81,3 +86,55 @@ function sendUnfollowRequest(fromUser, toActor, cb) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function acceptFollowRequest(localUser, remoteActor, requestActivity, cb) {
|
||||||
|
async.series(
|
||||||
|
[
|
||||||
|
callback => {
|
||||||
|
return Collection.addFollower(
|
||||||
|
localUser,
|
||||||
|
remoteActor,
|
||||||
|
true, // ignore dupes
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
},
|
||||||
|
callback => {
|
||||||
|
Actor.fromLocalUser(localUser, (err, localActor) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
const accept = Activity.makeAccept(localActor.id, requestActivity);
|
||||||
|
|
||||||
|
accept.sendTo(remoteActor.inbox, localUser, (err, respBody, res) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(Errors.HttpError(err.message, err.code));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.statusCode !== 202 && res.statusCode !== 200) {
|
||||||
|
return callback(
|
||||||
|
Errors.HttpError(
|
||||||
|
`Unexpected HTTP status code ${res.statusCode}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
callback => {
|
||||||
|
// remove from local requests Collection
|
||||||
|
return Collection.removeOwnedById(
|
||||||
|
Collections.FollowRequests,
|
||||||
|
localUser,
|
||||||
|
requestActivity.id,
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
err => {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,13 @@ const stringFormat = require('../string_format');
|
||||||
const { pipeToAnsi } = require('../color_codes');
|
const { pipeToAnsi } = require('../color_codes');
|
||||||
const MultiLineEditTextView =
|
const MultiLineEditTextView =
|
||||||
require('../multi_line_edit_text_view').MultiLineEditTextView;
|
require('../multi_line_edit_text_view').MultiLineEditTextView;
|
||||||
const { sendFollowRequest, sendUnfollowRequest } = require('./follow_util');
|
const {
|
||||||
|
sendFollowRequest,
|
||||||
|
sendUnfollowRequest,
|
||||||
|
acceptFollowRequest,
|
||||||
|
} = require('./follow_util');
|
||||||
const { Collections } = require('./const');
|
const { Collections } = require('./const');
|
||||||
|
const EnigAssert = require('../enigma_assert');
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
|
@ -42,11 +47,37 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
|
|
||||||
this.followingActors = [];
|
this.followingActors = [];
|
||||||
this.followerActors = [];
|
this.followerActors = [];
|
||||||
|
this.followRequests = [];
|
||||||
this.currentCollection = Collections.Following;
|
this.currentCollection = Collections.Following;
|
||||||
|
this.currentHelpText = '';
|
||||||
|
|
||||||
this.menuMethods = {
|
this.menuMethods = {
|
||||||
spaceKeyPressed: (formData, extraArgs, cb) => {
|
actorListKeyPressed: (formData, extraArgs, cb) => {
|
||||||
return this._toggleSelectedActorStatus(cb);
|
switch (formData.key.name) {
|
||||||
|
case 'space':
|
||||||
|
{
|
||||||
|
if (this.currentCollection === Collections.Following) {
|
||||||
|
return this._toggleFollowing(cb);
|
||||||
|
} else if (
|
||||||
|
this.currentCollection === Collections.FollowRequests
|
||||||
|
) {
|
||||||
|
return this._acceptFollowRequest(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
{
|
||||||
|
if (this.currentCollection === Collections.Followers) {
|
||||||
|
return this._removeFollower(cb);
|
||||||
|
} else if (
|
||||||
|
this.currentCollection === Collections.FollowRequests
|
||||||
|
) {
|
||||||
|
return this._denyFollowRequest(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
listKeyPressed: (formData, extraArgs, cb) => {
|
listKeyPressed: (formData, extraArgs, cb) => {
|
||||||
const actorListView = this.getView('main', MciViewIds.main.actorList);
|
const actorListView = this.getView('main', MciViewIds.main.actorList);
|
||||||
|
@ -110,32 +141,7 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
callback => {
|
callback => {
|
||||||
this._fetchActorList(
|
return this._populateActorLists(callback);
|
||||||
Collections.Following,
|
|
||||||
(err, followingActors) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
return this._fetchActorList(
|
|
||||||
Collections.Followers,
|
|
||||||
(err, followerActors) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapper = a => {
|
|
||||||
a.plainTextSummary = htmlToMessageBody(a.summary);
|
|
||||||
return a;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.followingActors = followingActors.map(mapper);
|
|
||||||
this.followerActors = followerActors.map(mapper);
|
|
||||||
|
|
||||||
return callback(null);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
callback => {
|
callback => {
|
||||||
const v = id => this.getView('main', id);
|
const v = id => this.getView('main', id);
|
||||||
|
@ -156,11 +162,12 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
});
|
});
|
||||||
|
|
||||||
navMenuView.on('index update', index => {
|
navMenuView.on('index update', index => {
|
||||||
if (0 === index) {
|
const collectionName = [
|
||||||
this._switchTo(Collections.Following);
|
Collections.Following,
|
||||||
} else {
|
Collections.Followers,
|
||||||
this._switchTo(Collections.Followers);
|
Collections.FollowRequests,
|
||||||
}
|
][index];
|
||||||
|
this._switchTo(collectionName);
|
||||||
});
|
});
|
||||||
|
|
||||||
return callback(null);
|
return callback(null);
|
||||||
|
@ -175,11 +182,28 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
_switchTo(collectionName) {
|
_switchTo(collectionName) {
|
||||||
this.currentCollection = collectionName;
|
this.currentCollection = collectionName;
|
||||||
const actorListView = this.getView('main', MciViewIds.main.actorList);
|
const actorListView = this.getView('main', MciViewIds.main.actorList);
|
||||||
if (Collections.Following === collectionName) {
|
|
||||||
actorListView.setItems(this.followingActors);
|
let list;
|
||||||
} else {
|
switch (collectionName) {
|
||||||
actorListView.setItems(this.followerActors);
|
case Collections.Following:
|
||||||
|
list = this.followingActors;
|
||||||
|
this.currentHelpText =
|
||||||
|
this.config.helpTextFollowing || 'SPC = Toggle Follower';
|
||||||
|
break;
|
||||||
|
case Collections.Followers:
|
||||||
|
list = this.followerActors;
|
||||||
|
this.currentHelpText =
|
||||||
|
this.config.helpTextFollowers || 'DEL = Remove Follower';
|
||||||
|
break;
|
||||||
|
case Collections.FollowRequests:
|
||||||
|
list = this.followRequests;
|
||||||
|
this.currentHelpText =
|
||||||
|
this.config.helpTextFollowRequests || 'SPC = Accept\r\nDEL = Deny';
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
EnigAssert(list);
|
||||||
|
|
||||||
|
actorListView.setItems(list);
|
||||||
actorListView.redraw();
|
actorListView.redraw();
|
||||||
|
|
||||||
const selectedActor = this._getSelectedActorItem(
|
const selectedActor = this._getSelectedActorItem(
|
||||||
|
@ -193,14 +217,23 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
this._updateSelectedActorInfo(selectedActorInfoView, selectedActor);
|
this._updateSelectedActorInfo(selectedActorInfoView, selectedActor);
|
||||||
} else {
|
} else {
|
||||||
selectedActorInfoView.setText('');
|
selectedActorInfoView.setText('');
|
||||||
|
this.updateCustomViewTextsWithFilter(
|
||||||
|
'main',
|
||||||
|
MciViewIds.main.customRangeStart,
|
||||||
|
this._getCustomInfoFormatObject(null),
|
||||||
|
{ pipeSupport: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSelectedActorItem(index) {
|
_getSelectedActorItem(index) {
|
||||||
if (this.currentCollection === Collections.Following) {
|
switch (this.currentCollection) {
|
||||||
return this.followingActors[index];
|
case Collections.Following:
|
||||||
} else {
|
return this.followingActors[index];
|
||||||
return this.followerActors[index];
|
case Collections.Followers:
|
||||||
|
return this.followerActors[index];
|
||||||
|
case Collections.FollowRequests:
|
||||||
|
return this.followRequests[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,11 +264,12 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
this.updateCustomViewTextsWithFilter(
|
this.updateCustomViewTextsWithFilter(
|
||||||
'main',
|
'main',
|
||||||
MciViewIds.main.customRangeStart,
|
MciViewIds.main.customRangeStart,
|
||||||
this._getCustomInfoFormatObject(actorInfo)
|
this._getCustomInfoFormatObject(actorInfo),
|
||||||
|
{ pipeSupport: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_toggleSelectedActorStatus(cb) {
|
_toggleFollowing(cb) {
|
||||||
const actorListView = this.getView('main', MciViewIds.main.actorList);
|
const actorListView = this.getView('main', MciViewIds.main.actorList);
|
||||||
const selectedActor = this._getSelectedActorItem(
|
const selectedActor = this._getSelectedActorItem(
|
||||||
actorListView.getFocusItemIndex()
|
actorListView.getFocusItemIndex()
|
||||||
|
@ -274,6 +308,49 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_acceptFollowRequest(cb) {
|
||||||
|
EnigAssert(Collections.FollowRequests === this.currentCollection);
|
||||||
|
|
||||||
|
const actorListView = this.getView('main', MciViewIds.main.actorList);
|
||||||
|
const selectedActor = this._getSelectedActorItem(
|
||||||
|
actorListView.getFocusItemIndex()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!selectedActor) {
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = selectedActor.request;
|
||||||
|
EnigAssert(request);
|
||||||
|
|
||||||
|
acceptFollowRequest(this.client.user, selectedActor, request, err => {
|
||||||
|
if (err) {
|
||||||
|
this.client.log.error(
|
||||||
|
{ error: err.message },
|
||||||
|
'Failed to fully accept Follow request'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const followingActor = this.followRequests.splice(
|
||||||
|
actorListView.getFocusItemIndex(),
|
||||||
|
1
|
||||||
|
)[0];
|
||||||
|
this.followerActors.push(followingActor); // move to followers
|
||||||
|
|
||||||
|
this._switchTo(this.currentCollection); // redraw
|
||||||
|
|
||||||
|
return cb(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_removeFollower(cb) {
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
_denyFollowRequest(cb) {
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
_followingActorToggled(actorInfo, cb) {
|
_followingActorToggled(actorInfo, cb) {
|
||||||
// Local user/Actor wants to follow or un-follow
|
// Local user/Actor wants to follow or un-follow
|
||||||
const wantsToFollow = actorInfo.status;
|
const wantsToFollow = actorInfo.status;
|
||||||
|
@ -327,6 +404,7 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
selectedActorStatus: actorInfo ? actorInfo.status : false,
|
selectedActorStatus: actorInfo ? actorInfo.status : false,
|
||||||
selectedActorStatusIndicator: v('statusIndicator'),
|
selectedActorStatusIndicator: v('statusIndicator'),
|
||||||
text: v('name'),
|
text: v('name'),
|
||||||
|
helpText: this.currentHelpText,
|
||||||
});
|
});
|
||||||
|
|
||||||
return formatObj;
|
return formatObj;
|
||||||
|
@ -334,8 +412,90 @@ exports.getModule = class activityPubSocialManager extends MenuModule {
|
||||||
|
|
||||||
_getStatusIndicator(enabled) {
|
_getStatusIndicator(enabled) {
|
||||||
return enabled
|
return enabled
|
||||||
? this.config.statusIndicatorEnabled || '√'
|
? this.config.statusFollowing || '√'
|
||||||
: this.config.statusIndicatorDisabled || 'X';
|
: this.config.statusNotFollowing || 'X';
|
||||||
|
}
|
||||||
|
|
||||||
|
_populateActorLists(cb) {
|
||||||
|
async.waterfall(
|
||||||
|
[
|
||||||
|
callback => {
|
||||||
|
return this._fetchActorList(Collections.Following, callback);
|
||||||
|
},
|
||||||
|
(following, callback) => {
|
||||||
|
this._fetchActorList(Collections.Followers, (err, followers) => {
|
||||||
|
return callback(err, following, followers);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(following, followers, callback) => {
|
||||||
|
this._fetchFollowRequestActors((err, followRequests) => {
|
||||||
|
return callback(err, following, followers, followRequests);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(following, followers, followRequests, callback) => {
|
||||||
|
const mapper = a => {
|
||||||
|
a.plainTextSummary = htmlToMessageBody(a.summary);
|
||||||
|
return a;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.followingActors = following.map(mapper);
|
||||||
|
this.followerActors = followers.map(mapper);
|
||||||
|
this.followRequests = followRequests.map(mapper);
|
||||||
|
|
||||||
|
return callback(null);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
err => {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fetchFollowRequestActors(cb) {
|
||||||
|
Collection.followRequests(this.client.user, 'all', (err, collection) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!collection.orderedItems || collection.orderedItems.length < 1) {
|
||||||
|
return cb(null, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusIndicator = this._getStatusIndicator(false);
|
||||||
|
|
||||||
|
async.mapLimit(
|
||||||
|
collection.orderedItems,
|
||||||
|
4,
|
||||||
|
(request, nextRequest) => {
|
||||||
|
const actorId = request.actor;
|
||||||
|
Actor.fromId(actorId, (err, actor, subject) => {
|
||||||
|
if (err) {
|
||||||
|
this.client.log.warn({ actorId }, 'Failed to retrieve Actor');
|
||||||
|
return nextRequest(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add some of our own properties
|
||||||
|
Object.assign(actor, {
|
||||||
|
subject,
|
||||||
|
status: false,
|
||||||
|
statusIndicator,
|
||||||
|
text: actor.preferredUsername,
|
||||||
|
request,
|
||||||
|
});
|
||||||
|
|
||||||
|
return nextRequest(null, actor);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(err, actorsList) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
actorsList = actorsList.filter(f => f); // drop nulls
|
||||||
|
return cb(null, actorsList);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_fetchActorList(collectionName, cb) {
|
_fetchActorList(collectionName, cb) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ const MultiLineEditTextView =
|
||||||
const Errors = require('../core/enig_error.js').Errors;
|
const Errors = require('../core/enig_error.js').Errors;
|
||||||
const { getPredefinedMCIValue } = require('../core/predefined_mci.js');
|
const { getPredefinedMCIValue } = require('../core/predefined_mci.js');
|
||||||
const EnigAssert = require('./enigma_assert');
|
const EnigAssert = require('./enigma_assert');
|
||||||
|
const { pipeToAnsi } = require('./color_codes.js');
|
||||||
|
|
||||||
// deps
|
// deps
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
|
@ -774,10 +775,25 @@ exports.MenuModule = class MenuModule extends PluginModule {
|
||||||
const format = config[view.key];
|
const format = config[view.key];
|
||||||
const text = stringFormat(format, fmtObj);
|
const text = stringFormat(format, fmtObj);
|
||||||
|
|
||||||
if (options.appendMultiLine && view instanceof MultiLineEditTextView) {
|
if (view instanceof MultiLineEditTextView) {
|
||||||
view.addText(text);
|
if (options.appendMultiLine) {
|
||||||
|
view.addText(text);
|
||||||
|
} else {
|
||||||
|
if (options.pipeSupport) {
|
||||||
|
const ansi = pipeToAnsi(text, this.client);
|
||||||
|
if (view.getData() !== ansi) {
|
||||||
|
view.setAnsi(ansi);
|
||||||
|
} else {
|
||||||
|
view.redraw();
|
||||||
|
}
|
||||||
|
} else if (view.getData() !== text) {
|
||||||
|
view.setText(text);
|
||||||
|
} else {
|
||||||
|
view.redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (view.getData() != text) {
|
if (view.getData() !== text) {
|
||||||
view.setText(text);
|
view.setText(text);
|
||||||
} else {
|
} else {
|
||||||
view.redraw();
|
view.redraw();
|
||||||
|
|
|
@ -6,6 +6,7 @@ const {
|
||||||
getActorId,
|
getActorId,
|
||||||
prepareLocalUserAsActor,
|
prepareLocalUserAsActor,
|
||||||
} = require('../../../activitypub/util');
|
} = require('../../../activitypub/util');
|
||||||
|
const { acceptFollowRequest } = require('../../../activitypub/follow_util');
|
||||||
const SysLog = require('../../../logger').log;
|
const SysLog = require('../../../logger').log;
|
||||||
const {
|
const {
|
||||||
ActivityStreamMediaType,
|
ActivityStreamMediaType,
|
||||||
|
@ -750,26 +751,36 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
|
||||||
return this.webServer.resourceNotFound(resp);
|
return this.webServer.resourceNotFound(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// User accepts any followers automatically
|
const addReq = () => {
|
||||||
const activityPubSettings = ActivityPubSettings.fromUser(localUser);
|
// User manually approves requests; add them to their requests collection
|
||||||
if (!activityPubSettings.manuallyApproveFollowers) {
|
// :FIXME: We need to store the Activity and fetch the Actor as needed later;
|
||||||
this._recordAcceptedFollowRequest(localUser, remoteActor, activity);
|
// when accepting a request, we send back the Activity!
|
||||||
return this.webServer.accepted(resp);
|
Collection.addFollowRequest(localUser, activity, err => {
|
||||||
}
|
|
||||||
|
|
||||||
// User manually approves requests; add them to their requests collection
|
|
||||||
Collection.addFollowRequest(
|
|
||||||
localUser,
|
|
||||||
remoteActor,
|
|
||||||
true, // ignore dupes
|
|
||||||
err => {
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return this.internalServerError(resp, err);
|
return this.internalServerError(resp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.webServer.accepted(resp);
|
return this.webServer.accepted(resp);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// User accepts any followers automatically
|
||||||
|
const activityPubSettings = ActivityPubSettings.fromUser(localUser);
|
||||||
|
if (activityPubSettings.manuallyApproveFollowers) {
|
||||||
|
return addReq();
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptFollowRequest(localUser, remoteActor, activity, err => {
|
||||||
|
if (err) {
|
||||||
|
this.log.warn(
|
||||||
|
{ error: err.message },
|
||||||
|
'Failed to post Accept. Recording to requests instead.'
|
||||||
|
);
|
||||||
|
return addReq();
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
return this.webServer.accepted(resp);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1105,81 +1116,6 @@ exports.getModule = class ActivityPubWebHandler extends WebHandlerModule {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_recordAcceptedFollowRequest(localUser, remoteActor, requestActivity) {
|
|
||||||
async.series(
|
|
||||||
[
|
|
||||||
callback => {
|
|
||||||
return Collection.addFollower(
|
|
||||||
localUser,
|
|
||||||
remoteActor,
|
|
||||||
true, // ignore dupes
|
|
||||||
callback
|
|
||||||
);
|
|
||||||
},
|
|
||||||
callback => {
|
|
||||||
Actor.fromLocalUser(localUser, (err, localActor) => {
|
|
||||||
if (err) {
|
|
||||||
this.log.warn(
|
|
||||||
{ inbox: remoteActor.inbox, error: err.message },
|
|
||||||
'Failed to load local Actor for "Accept"'
|
|
||||||
);
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
const accept = Activity.makeAccept(
|
|
||||||
localActor.id,
|
|
||||||
requestActivity
|
|
||||||
);
|
|
||||||
|
|
||||||
accept.sendTo(
|
|
||||||
remoteActor.inbox,
|
|
||||||
localUser,
|
|
||||||
(err, respBody, res) => {
|
|
||||||
if (err) {
|
|
||||||
this.log.warn(
|
|
||||||
{
|
|
||||||
inbox: remoteActor.inbox,
|
|
||||||
error: err.message,
|
|
||||||
},
|
|
||||||
'Failed POSTing "Accept" to inbox'
|
|
||||||
);
|
|
||||||
return callback(null); // just a warning
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.statusCode !== 202 && res.statusCode !== 200) {
|
|
||||||
this.log.warn(
|
|
||||||
{
|
|
||||||
inbox: remoteActor.inbox,
|
|
||||||
statusCode: res.statusCode,
|
|
||||||
},
|
|
||||||
'Unexpected status code'
|
|
||||||
);
|
|
||||||
return callback(null); // just a warning
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log.info(
|
|
||||||
{ inbox: remoteActor.inbox },
|
|
||||||
'Remote server received our "Accept" successfully'
|
|
||||||
);
|
|
||||||
|
|
||||||
return callback(null);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
],
|
|
||||||
err => {
|
|
||||||
if (err) {
|
|
||||||
// :TODO: move this request to the "Request queue" for the user to try later
|
|
||||||
this.log.error(
|
|
||||||
{ error: err.message },
|
|
||||||
'Failed processing Follow request'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_selfAsActorHandler(localUser, localActor, req, resp) {
|
_selfAsActorHandler(localUser, localActor, req, resp) {
|
||||||
this.log.info(
|
this.log.info(
|
||||||
{ username: localUser.username },
|
{ username: localUser.username },
|
||||||
|
|
|
@ -209,7 +209,7 @@
|
||||||
MT2: {mode: "preview", acceptsFocus: false, acceptsInput: false}
|
MT2: {mode: "preview", acceptsFocus: false, acceptsInput: false}
|
||||||
TM3: {
|
TM3: {
|
||||||
focus: true
|
focus: true
|
||||||
items: ["following", "followers"]
|
items: ["following", "followers", "pending requests"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actionKeys: [
|
actionKeys: [
|
||||||
|
|
Loading…
Reference in New Issue