-import { values } from 'lodash'
-import { literal, Op, Transaction } from 'sequelize'
+import { literal, Op, QueryTypes, Transaction } from 'sequelize'
import {
AllowNull,
BelongsTo,
} from 'sequelize-typescript'
import { activityPubContextify } from '@server/lib/activitypub/context'
import { getBiggestActorImage } from '@server/lib/actor-image'
-import { ModelCache } from '@server/models/model-cache'
-import { getLowercaseExtension } from '@shared/core-utils'
+import { ModelCache } from '@server/models/shared/model-cache'
+import { forceNumber, getLowercaseExtension } from '@shared/core-utils'
import { ActivityIconObject, ActivityPubActorType, ActorImageType } from '@shared/models'
import { AttributesOnly } from '@shared/typescript-utils'
import {
MActorAccountChannelId,
MActorAPAccount,
MActorAPChannel,
+ MActorFollowersUrl,
MActorFormattable,
MActorFull,
MActorHost,
+ MActorId,
MActorServer,
MActorSummaryFormattable,
MActorUrl,
MActorWithInboxes
} from '../../types/models'
import { AccountModel } from '../account/account'
+import { getServerActor } from '../application/application'
import { ServerModel } from '../server/server'
-import { isOutdated, throwIfNotValid } from '../utils'
+import { buildSQLAttributes, isOutdated, throwIfNotValid } from '../shared'
import { VideoModel } from '../video/video'
import { VideoChannelModel } from '../video/video-channel'
import { ActorFollowModel } from './actor-follow'
FULL = 'FULL'
}
-export const unusedActorAttributesForAPI = [
+export const unusedActorAttributesForAPI: (keyof AttributesOnly<ActorModel>)[] = [
'publicKey',
'privateKey',
'inboxUrl',
export class ActorModel extends Model<Partial<AttributesOnly<ActorModel>>> {
@AllowNull(false)
- @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES)))
+ @Column(DataType.ENUM(...Object.values(ACTIVITY_PUB_ACTOR_TYPES)))
type: ActivityPubActorType
@AllowNull(false)
})
VideoChannel: VideoChannelModel
- static load (id: number): Promise<MActor> {
+ // ---------------------------------------------------------------------------
+
+ static getSQLAttributes (tableName: string, aliasPrefix = '') {
+ return buildSQLAttributes({
+ model: this,
+ tableName,
+ aliasPrefix
+ })
+ }
+
+ static getSQLAPIAttributes (tableName: string, aliasPrefix = '') {
+ return buildSQLAttributes({
+ model: this,
+ tableName,
+ aliasPrefix,
+ excludeAttributes: unusedActorAttributesForAPI
+ })
+ }
+
+ // ---------------------------------------------------------------------------
+
+ static async load (id: number): Promise<MActor> {
+ const actorServer = await getServerActor()
+ if (id === actorServer.id) return actorServer
+
return ActorModel.unscoped().findByPk(id)
}
return ActorModel.scope(ScopeNames.FULL).findByPk(id)
}
- static loadFromAccountByVideoId (videoId: number, transaction: Transaction): Promise<MActor> {
- const query = {
- include: [
- {
- attributes: [ 'id' ],
- model: AccountModel.unscoped(),
- required: true,
- include: [
- {
- attributes: [ 'id' ],
- model: VideoChannelModel.unscoped(),
- required: true,
- include: [
- {
- attributes: [ 'id' ],
- model: VideoModel.unscoped(),
- required: true,
- where: {
- id: videoId
- }
- }
- ]
- }
- ]
- }
- ],
+ static loadAccountActorFollowerUrlByVideoId (videoId: number, transaction: Transaction) {
+ const query = `SELECT "actor"."id" AS "id", "actor"."followersUrl" AS "followersUrl" ` +
+ `FROM "actor" ` +
+ `INNER JOIN "account" ON "actor"."id" = "account"."actorId" ` +
+ `INNER JOIN "videoChannel" ON "videoChannel"."accountId" = "account"."id" ` +
+ `INNER JOIN "video" ON "video"."channelId" = "videoChannel"."id" AND "video"."id" = :videoId`
+
+ const options = {
+ type: QueryTypes.SELECT as QueryTypes.SELECT,
+ replacements: { videoId },
+ plain: true as true,
transaction
}
- return ActorModel.unscoped().findOne(query)
- }
-
- static isActorUrlExist (url: string) {
- const query = {
- raw: true,
- where: {
- url
- }
- }
-
- return ActorModel.unscoped().findOne(query)
- .then(a => !!a)
+ return ActorModel.sequelize.query<MActorId & MActorFollowersUrl>(query, options)
}
static listByFollowersUrls (followersUrls: string[], transaction?: Transaction): Promise<MActorFull[]> {
}
static rebuildFollowsCount (ofId: number, type: 'followers' | 'following', transaction?: Transaction) {
- const sanitizedOfId = parseInt(ofId + '', 10)
+ const sanitizedOfId = forceNumber(ofId)
const where = { id: sanitizedOfId }
let columnToUpdate: string
}
return ActorModel.update({
- [columnToUpdate]: literal(`(SELECT COUNT(*) FROM "actorFollow" WHERE "${columnOfCount}" = ${sanitizedOfId})`)
+ [columnToUpdate]: literal(`(SELECT COUNT(*) FROM "actorFollow" WHERE "${columnOfCount}" = ${sanitizedOfId} AND "state" = 'accepted')`)
}, { where, transaction })
}