"use strict";
var AccountBlocklistModel_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AccountBlocklistModel = void 0;
const tslib_1 = require("tslib");
const sequelize_1 = require("sequelize");
const sequelize_typescript_1 = require("sequelize-typescript");
const actors_1 = require("../../helpers/actors");
const actor_1 = require("../actor/actor");
const server_1 = require("../server/server");
const utils_1 = require("../utils");
const account_1 = require("./account");
let AccountBlocklistModel = AccountBlocklistModel_1 = class AccountBlocklistModel extends sequelize_typescript_1.Model {
    static isAccountMutedByAccounts(accountIds, targetAccountId) {
        const query = {
            attributes: ['accountId', 'id'],
            where: {
                accountId: {
                    [sequelize_1.Op.in]: accountIds
                },
                targetAccountId
            },
            raw: true
        };
        return AccountBlocklistModel_1.unscoped()
            .findAll(query)
            .then(rows => {
            const result = {};
            for (const accountId of accountIds) {
                result[accountId] = !!rows.find(r => r.accountId === accountId);
            }
            return result;
        });
    }
    static loadByAccountAndTarget(accountId, targetAccountId) {
        const query = {
            where: {
                accountId,
                targetAccountId
            }
        };
        return AccountBlocklistModel_1.findOne(query);
    }
    static listForApi(parameters) {
        const { start, count, sort, search, accountId } = parameters;
        const getQuery = (forCount) => {
            const query = {
                offset: start,
                limit: count,
                order: (0, utils_1.getSort)(sort),
                where: { accountId }
            };
            if (search) {
                Object.assign(query.where, {
                    [sequelize_1.Op.or]: [
                        (0, utils_1.searchAttribute)(search, '$BlockedAccount.name$'),
                        (0, utils_1.searchAttribute)(search, '$BlockedAccount.Actor.url$')
                    ]
                });
            }
            if (forCount !== true) {
                query.include = [
                    {
                        model: account_1.AccountModel,
                        required: true,
                        as: 'ByAccount'
                    },
                    {
                        model: account_1.AccountModel,
                        required: true,
                        as: 'BlockedAccount'
                    }
                ];
            }
            else if (search) {
                query.include = [
                    {
                        model: account_1.AccountModel.unscoped(),
                        required: true,
                        as: 'BlockedAccount',
                        include: [
                            {
                                model: actor_1.ActorModel.unscoped(),
                                required: true
                            }
                        ]
                    }
                ];
            }
            return query;
        };
        return Promise.all([
            AccountBlocklistModel_1.count(getQuery(true)),
            AccountBlocklistModel_1.findAll(getQuery(false))
        ]).then(([total, data]) => ({ total, data }));
    }
    static listHandlesBlockedBy(accountIds) {
        const query = {
            attributes: ['id'],
            where: {
                accountId: {
                    [sequelize_1.Op.in]: accountIds
                }
            },
            include: [
                {
                    attributes: ['id'],
                    model: account_1.AccountModel.unscoped(),
                    required: true,
                    as: 'BlockedAccount',
                    include: [
                        {
                            attributes: ['preferredUsername'],
                            model: actor_1.ActorModel.unscoped(),
                            required: true,
                            include: [
                                {
                                    attributes: ['host'],
                                    model: server_1.ServerModel.unscoped(),
                                    required: true
                                }
                            ]
                        }
                    ]
                }
            ]
        };
        return AccountBlocklistModel_1.findAll(query)
            .then(entries => entries.map(e => `${e.BlockedAccount.Actor.preferredUsername}@${e.BlockedAccount.Actor.Server.host}`));
    }
    static getBlockStatus(byAccountIds, handles) {
        const sanitizedHandles = (0, actors_1.handlesToNameAndHost)(handles);
        const localHandles = sanitizedHandles.filter(h => !h.host)
            .map(h => h.name);
        const remoteHandles = sanitizedHandles.filter(h => !!h.host)
            .map(h => ([h.name, h.host]));
        const handlesWhere = [];
        if (localHandles.length !== 0) {
            handlesWhere.push(`("actor"."preferredUsername" IN (:localHandles) AND "server"."id" IS NULL)`);
        }
        if (remoteHandles.length !== 0) {
            handlesWhere.push(`(("actor"."preferredUsername", "server"."host") IN (:remoteHandles))`);
        }
        const rawQuery = `SELECT "accountBlocklist"."accountId", "actor"."preferredUsername" AS "name", "server"."host" ` +
            `FROM "accountBlocklist" ` +
            `INNER JOIN "account" ON "account"."id" = "accountBlocklist"."targetAccountId" ` +
            `INNER JOIN "actor" ON "actor"."id" = "account"."actorId" ` +
            `LEFT JOIN "server" ON "server"."id" = "actor"."serverId" ` +
            `WHERE "accountBlocklist"."accountId" IN (${(0, utils_1.createSafeIn)(AccountBlocklistModel_1.sequelize, byAccountIds)}) ` +
            `AND (${handlesWhere.join(' OR ')})`;
        return AccountBlocklistModel_1.sequelize.query(rawQuery, {
            type: sequelize_1.QueryTypes.SELECT,
            replacements: { byAccountIds, localHandles, remoteHandles }
        });
    }
    toFormattedJSON() {
        return {
            byAccount: this.ByAccount.toFormattedJSON(),
            blockedAccount: this.BlockedAccount.toFormattedJSON(),
            createdAt: this.createdAt
        };
    }
};
tslib_1.__decorate([
    sequelize_typescript_1.CreatedAt,
    tslib_1.__metadata("design:type", Date)
], AccountBlocklistModel.prototype, "createdAt", void 0);
tslib_1.__decorate([
    sequelize_typescript_1.UpdatedAt,
    tslib_1.__metadata("design:type", Date)
], AccountBlocklistModel.prototype, "updatedAt", void 0);
tslib_1.__decorate([
    (0, sequelize_typescript_1.ForeignKey)(() => account_1.AccountModel),
    sequelize_typescript_1.Column,
    tslib_1.__metadata("design:type", Number)
], AccountBlocklistModel.prototype, "accountId", void 0);
tslib_1.__decorate([
    (0, sequelize_typescript_1.BelongsTo)(() => account_1.AccountModel, {
        foreignKey: {
            name: 'accountId',
            allowNull: false
        },
        as: 'ByAccount',
        onDelete: 'CASCADE'
    }),
    tslib_1.__metadata("design:type", account_1.AccountModel)
], AccountBlocklistModel.prototype, "ByAccount", void 0);
tslib_1.__decorate([
    (0, sequelize_typescript_1.ForeignKey)(() => account_1.AccountModel),
    sequelize_typescript_1.Column,
    tslib_1.__metadata("design:type", Number)
], AccountBlocklistModel.prototype, "targetAccountId", void 0);
tslib_1.__decorate([
    (0, sequelize_typescript_1.BelongsTo)(() => account_1.AccountModel, {
        foreignKey: {
            name: 'targetAccountId',
            allowNull: false
        },
        as: 'BlockedAccount',
        onDelete: 'CASCADE'
    }),
    tslib_1.__metadata("design:type", account_1.AccountModel)
], AccountBlocklistModel.prototype, "BlockedAccount", void 0);
AccountBlocklistModel = AccountBlocklistModel_1 = tslib_1.__decorate([
    (0, sequelize_typescript_1.Table)({
        tableName: 'accountBlocklist',
        indexes: [
            {
                fields: ['accountId', 'targetAccountId'],
                unique: true
            },
            {
                fields: ['targetAccountId']
            }
        ]
    })
], AccountBlocklistModel);
exports.AccountBlocklistModel = AccountBlocklistModel;
//# sourceMappingURL=account-blocklist.js.map