"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processFollowActivity = void 0;
const tslib_1 = require("tslib");
const application_1 = require("../../../models/application/application");
const activitypub_1 = require("../../../helpers/activitypub");
const database_utils_1 = require("../../../helpers/database-utils");
const logger_1 = require("../../../helpers/logger");
const config_1 = require("../../../initializers/config");
const database_1 = require("../../../initializers/database");
const actor_1 = require("../../../models/actor/actor");
const actor_follow_1 = require("../../../models/actor/actor-follow");
const notifier_1 = require("../../notifier");
const follow_1 = require("../follow");
const send_1 = require("../send");
function processFollowActivity(options) {
    return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
        const { activity, byActor } = options;
        const activityId = activity.id;
        const objectId = (0, activitypub_1.getAPId)(activity.object);
        return (0, database_utils_1.retryTransactionWrapper)(processFollow, byActor, activityId, objectId);
    });
}
exports.processFollowActivity = processFollowActivity;
function processFollow(byActor, activityId, targetActorURL) {
    return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
        const { actorFollow, created, isFollowingInstance, targetActor } = yield database_1.sequelizeTypescript.transaction((t) => (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
            const targetActor = yield actor_1.ActorModel.loadByUrlAndPopulateAccountAndChannel(targetActorURL, t);
            if (!targetActor)
                throw new Error('Unknown actor');
            if (targetActor.isOwned() === false)
                throw new Error('This is not a local actor.');
            const serverActor = yield (0, application_1.getServerActor)();
            const isFollowingInstance = targetActor.id === serverActor.id;
            if (isFollowingInstance && config_1.CONFIG.FOLLOWERS.INSTANCE.ENABLED === false) {
                logger_1.logger.info('Rejecting %s because instance followers are disabled.', targetActor.url);
                (0, send_1.sendReject)(activityId, byActor, targetActor);
                return { actorFollow: undefined };
            }
            const [actorFollow, created] = yield actor_follow_1.ActorFollowModel.findOrCreateCustom({
                byActor,
                targetActor,
                activityId,
                state: config_1.CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL
                    ? 'pending'
                    : 'accepted',
                transaction: t
            });
            if (actorFollow.state !== 'accepted' && (isFollowingInstance === false || config_1.CONFIG.FOLLOWERS.INSTANCE.MANUAL_APPROVAL === false)) {
                actorFollow.state = 'accepted';
                yield actorFollow.save({ transaction: t });
            }
            if (!actorFollow.url) {
                actorFollow.url = activityId;
                yield actorFollow.save({ transaction: t });
            }
            actorFollow.ActorFollower = byActor;
            actorFollow.ActorFollowing = targetActor;
            if (actorFollow.state === 'accepted') {
                (0, send_1.sendAccept)(actorFollow);
                yield (0, follow_1.autoFollowBackIfNeeded)(actorFollow, t);
            }
            return { actorFollow, created, isFollowingInstance, targetActor };
        }));
        if (!actorFollow)
            return;
        if (created) {
            const follower = yield actor_1.ActorModel.loadFull(byActor.id);
            const actorFollowFull = Object.assign(actorFollow, { ActorFollowing: targetActor, ActorFollower: follower });
            if (isFollowingInstance) {
                notifier_1.Notifier.Instance.notifyOfNewInstanceFollow(actorFollowFull);
            }
            else {
                notifier_1.Notifier.Instance.notifyOfNewUserFollow(actorFollowFull);
            }
        }
        logger_1.logger.info('Actor %s is followed by actor %s.', targetActorURL, byActor.url);
    });
}
//# sourceMappingURL=process-follow.js.map