1 import { Sequelize } from 'sequelize'
2 import { ModelBuilder } from '@server/models/shared'
3 import { parseRowCountResult } from '@server/models/utils'
4 import { MActorFollowActorsDefault } from '@server/types/models'
5 import { ActivityPubActorType, FollowState } from '@shared/models'
6 import { InstanceListFollowsQueryBuilder } from './shared/instance-list-follows-query-builder'
8 export interface ListFollowersOptions {
14 actorType?: ActivityPubActorType
18 export class InstanceListFollowersQueryBuilder extends InstanceListFollowsQueryBuilder <ListFollowersOptions> {
21 protected readonly sequelize: Sequelize,
22 protected readonly options: ListFollowersOptions
24 super(sequelize, options)
27 async listFollowers () {
30 const results = await this.runQuery({ nest: true })
31 const modelBuilder = new ModelBuilder<MActorFollowActorsDefault>(this.sequelize)
33 return modelBuilder.createModels(results, 'ActorFollow')
36 async countFollowers () {
37 this.buildCountQuery()
39 const result = await this.runQuery()
41 return parseRowCountResult(result)
44 protected getWhere () {
45 let where = 'WHERE "ActorFollowing"."id" IN (:actorIds) '
46 this.replacements.actorIds = this.options.actorIds
48 if (this.options.state) {
49 where += 'AND "ActorFollowModel"."state" = :state '
50 this.replacements.state = this.options.state
53 if (this.options.search) {
54 const escapedLikeSearch = this.sequelize.escape('%' + this.options.search + '%')
57 `"ActorFollower->Server"."host" ILIKE ${escapedLikeSearch} ` +
58 `OR "ActorFollower"."preferredUsername" ILIKE ${escapedLikeSearch} ` +
62 if (this.options.actorType) {
63 where += `AND "ActorFollower"."type" = :actorType `
64 this.replacements.actorType = this.options.actorType