"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const chai_1 = require("chai");
const shared_1 = require("../../shared");
const server_commands_1 = require("../../../../shared/server-commands");
function checkServer1And2HasFollowers(servers, state = 'accepted') {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const fns = [
            servers[0].follows.getFollowings.bind(servers[0].follows),
            servers[1].follows.getFollowers.bind(servers[1].follows)
        ];
        for (const fn of fns) {
            const body = yield fn({ start: 0, count: 5, sort: 'createdAt' });
            (0, chai_1.expect)(body.total).to.equal(1);
            const follow = body.data[0];
            (0, chai_1.expect)(follow.state).to.equal(state);
            (0, chai_1.expect)(follow.follower.url).to.equal(servers[0].url + '/accounts/peertube');
            (0, chai_1.expect)(follow.following.url).to.equal(servers[1].url + '/accounts/peertube');
        }
    });
}
function checkFollows(options) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const { follower, followerState, followingState, following } = options;
        const followerUrl = follower.url + '/accounts/peertube';
        const followingUrl = following.url + '/accounts/peertube';
        const finder = (d) => d.follower.url === followerUrl && d.following.url === followingUrl;
        {
            const { data } = yield follower.follows.getFollowings();
            const follow = data.find(finder);
            if (followerState === 'deleted') {
                (0, chai_1.expect)(follow).to.not.exist;
            }
            else {
                (0, chai_1.expect)(follow.state).to.equal(followerState);
                (0, chai_1.expect)(follow.follower.url).to.equal(followerUrl);
                (0, chai_1.expect)(follow.following.url).to.equal(followingUrl);
            }
        }
        {
            const { data } = yield following.follows.getFollowers();
            const follow = data.find(finder);
            if (followingState === 'deleted') {
                (0, chai_1.expect)(follow).to.not.exist;
            }
            else {
                (0, chai_1.expect)(follow.state).to.equal(followingState);
                (0, chai_1.expect)(follow.follower.url).to.equal(followerUrl);
                (0, chai_1.expect)(follow.following.url).to.equal(followingUrl);
            }
        }
    });
}
function checkNoFollowers(servers) {
    return tslib_1.__awaiter(this, void 0, void 0, function* () {
        const fns = [
            servers[0].follows.getFollowings.bind(servers[0].follows),
            servers[1].follows.getFollowers.bind(servers[1].follows)
        ];
        for (const fn of fns) {
            const body = yield fn({ start: 0, count: 5, sort: 'createdAt', state: 'accepted' });
            (0, chai_1.expect)(body.total).to.equal(0);
        }
    });
}
describe('Test follows moderation', function () {
    let servers = [];
    let commands;
    before(function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.timeout(240000);
            servers = yield (0, server_commands_1.createMultipleServers)(3);
            yield (0, server_commands_1.setAccessTokensToServers)(servers);
            commands = servers.map(s => s.follows);
        });
    });
    describe('Default behaviour', function () {
        it('Should have server 1 following server 2', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(30000);
                yield commands[0].follow({ hosts: [servers[1].url] });
                yield (0, server_commands_1.waitJobs)(servers);
            });
        });
        it('Should have correct follows', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield checkServer1And2HasFollowers(servers);
            });
        });
        it('Should remove follower on server 2', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(10000);
                yield commands[1].removeFollower({ follower: servers[0] });
                yield (0, server_commands_1.waitJobs)(servers);
            });
        });
        it('Should not not have follows anymore', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield checkNoFollowers(servers);
            });
        });
    });
    describe('Disabled/Enabled followers', function () {
        it('Should disable followers on server 2', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(10000);
                const subConfig = {
                    followers: {
                        instance: {
                            enabled: false,
                            manualApproval: false
                        }
                    }
                };
                yield servers[1].config.updateCustomSubConfig({ newConfig: subConfig });
                yield commands[0].follow({ hosts: [servers[1].url] });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkNoFollowers(servers);
            });
        });
        it('Should re enable followers on server 2', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(10000);
                const subConfig = {
                    followers: {
                        instance: {
                            enabled: true,
                            manualApproval: false
                        }
                    }
                };
                yield servers[1].config.updateCustomSubConfig({ newConfig: subConfig });
                yield commands[0].follow({ hosts: [servers[1].url] });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkServer1And2HasFollowers(servers);
            });
        });
    });
    describe('Manual approbation', function () {
        it('Should manually approve followers', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(20000);
                yield commands[0].unfollow({ target: servers[1] });
                yield (0, server_commands_1.waitJobs)(servers);
                const subConfig = {
                    followers: {
                        instance: {
                            enabled: true,
                            manualApproval: true
                        }
                    }
                };
                yield servers[1].config.updateCustomSubConfig({ newConfig: subConfig });
                yield servers[2].config.updateCustomSubConfig({ newConfig: subConfig });
                yield commands[0].follow({ hosts: [servers[1].url] });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkServer1And2HasFollowers(servers, 'pending');
            });
        });
        it('Should accept a follower', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(10000);
                yield commands[1].acceptFollower({ follower: 'peertube@' + servers[0].host });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkServer1And2HasFollowers(servers);
            });
        });
        it('Should reject another follower', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                this.timeout(20000);
                yield commands[0].follow({ hosts: [servers[2].url] });
                yield (0, server_commands_1.waitJobs)(servers);
                {
                    const body = yield commands[0].getFollowings();
                    (0, chai_1.expect)(body.total).to.equal(2);
                }
                {
                    const body = yield commands[1].getFollowers();
                    (0, chai_1.expect)(body.total).to.equal(1);
                }
                {
                    const body = yield commands[2].getFollowers();
                    (0, chai_1.expect)(body.total).to.equal(1);
                }
                yield commands[2].rejectFollower({ follower: 'peertube@' + servers[0].host });
                yield (0, server_commands_1.waitJobs)(servers);
                {
                    {
                        const { data } = yield commands[0].getFollowings({ state: 'accepted' });
                        (0, chai_1.expect)(data).to.have.lengthOf(1);
                    }
                    {
                        const { data } = yield commands[0].getFollowings({ state: 'rejected' });
                        (0, chai_1.expect)(data).to.have.lengthOf(1);
                        (0, shared_1.expectStartWith)(data[0].following.url, servers[2].url);
                    }
                }
                {
                    {
                        const { data } = yield commands[2].getFollowers({ state: 'accepted' });
                        (0, chai_1.expect)(data).to.have.lengthOf(0);
                    }
                    {
                        const { data } = yield commands[2].getFollowers({ state: 'rejected' });
                        (0, chai_1.expect)(data).to.have.lengthOf(1);
                        (0, shared_1.expectStartWith)(data[0].follower.url, servers[0].url);
                    }
                }
            });
        });
        it('Should still auto accept channel followers', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield commands[0].follow({ handles: ['root_channel@' + servers[1].host] });
                yield (0, server_commands_1.waitJobs)(servers);
                const body = yield commands[0].getFollowings();
                const follow = body.data[0];
                (0, chai_1.expect)(follow.following.name).to.equal('root_channel');
                (0, chai_1.expect)(follow.state).to.equal('accepted');
            });
        });
    });
    describe('Accept/reject state', function () {
        it('Should not change the follow on refollow with and without auto accept', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                const run = () => tslib_1.__awaiter(this, void 0, void 0, function* () {
                    yield commands[0].follow({ hosts: [servers[2].url] });
                    yield (0, server_commands_1.waitJobs)(servers);
                    yield checkFollows({
                        follower: servers[0],
                        followerState: 'rejected',
                        following: servers[2],
                        followingState: 'rejected'
                    });
                });
                yield servers[2].config.updateExistingSubConfig({ newConfig: { followers: { instance: { manualApproval: false } } } });
                yield run();
                yield servers[2].config.updateExistingSubConfig({ newConfig: { followers: { instance: { manualApproval: true } } } });
                yield run();
            });
        });
        it('Should not change the rejected status on unfollow', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield commands[0].unfollow({ target: servers[2] });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkFollows({
                    follower: servers[0],
                    followerState: 'deleted',
                    following: servers[2],
                    followingState: 'rejected'
                });
            });
        });
        it('Should delete the follower and add again the follower', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield commands[2].removeFollower({ follower: servers[0] });
                yield (0, server_commands_1.waitJobs)(servers);
                yield commands[0].follow({ hosts: [servers[2].url] });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkFollows({
                    follower: servers[0],
                    followerState: 'pending',
                    following: servers[2],
                    followingState: 'pending'
                });
            });
        });
        it('Should be able to reject a previously accepted follower', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield commands[1].rejectFollower({ follower: 'peertube@' + servers[0].host });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkFollows({
                    follower: servers[0],
                    followerState: 'rejected',
                    following: servers[1],
                    followingState: 'rejected'
                });
            });
        });
        it('Should be able to re accept a previously rejected follower', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield commands[1].acceptFollower({ follower: 'peertube@' + servers[0].host });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkFollows({
                    follower: servers[0],
                    followerState: 'accepted',
                    following: servers[1],
                    followingState: 'accepted'
                });
            });
        });
    });
    describe('Muted servers', function () {
        it('Should ignore follow requests of muted servers', function () {
            return tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield servers[1].blocklist.addToServerBlocklist({ server: servers[0].host });
                yield commands[0].unfollow({ target: servers[1] });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkFollows({
                    follower: servers[0],
                    followerState: 'deleted',
                    following: servers[1],
                    followingState: 'deleted'
                });
                yield commands[0].follow({ hosts: [servers[1].host] });
                yield (0, server_commands_1.waitJobs)(servers);
                yield checkFollows({
                    follower: servers[0],
                    followerState: 'rejected',
                    following: servers[1],
                    followingState: 'deleted'
                });
            });
        });
    });
    after(function () {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            yield (0, server_commands_1.cleanupTests)(servers);
        });
    });
});
//# sourceMappingURL=follows-moderation.js.map