From 2cb03dc1f4e01ba491c36caff30c33fe9c5bad89 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 6 Apr 2021 17:01:35 +0200 Subject: Add banners support --- server/models/activitypub/actor-follow.ts | 7 --- server/models/activitypub/actor.ts | 47 +++++++++++++++-- server/models/video/video-channel.ts | 88 ++++++++++++++++--------------- 3 files changed, 87 insertions(+), 55 deletions(-) (limited to 'server/models') diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts index ce6a4e267..4c5f37620 100644 --- a/server/models/activitypub/actor-follow.ts +++ b/server/models/activitypub/actor-follow.ts @@ -248,13 +248,6 @@ export class ActorFollowModel extends Model { } return ActorFollowModel.findOne(query) - .then(result => { - if (result?.ActorFollowing.VideoChannel) { - result.ActorFollowing.VideoChannel.Actor = result.ActorFollowing - } - - return result - }) } static listSubscribedIn (actorId: number, targets: { name: string, host?: string }[]): Promise { diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index 09d96b24d..6595f11e2 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts @@ -29,11 +29,19 @@ import { isActorPublicKeyValid } from '../../helpers/custom-validators/activitypub/actor' import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' -import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' +import { + ACTIVITY_PUB, + ACTIVITY_PUB_ACTOR_TYPES, + CONSTRAINTS_FIELDS, + MIMETYPES, + SERVER_ACTOR_NAME, + WEBSERVER +} from '../../initializers/constants' import { MActor, MActorAccountChannelId, - MActorAP, + MActorAPAccount, + MActorAPChannel, MActorFormattable, MActorFull, MActorHost, @@ -104,6 +112,11 @@ export const unusedActorAttributesForAPI = [ model: ActorImageModel, as: 'Avatar', required: false + }, + { + model: ActorImageModel, + as: 'Banner', + required: false } ] } @@ -531,29 +544,46 @@ export class ActorModel extends Model { toFormattedJSON (this: MActorFormattable) { const base = this.toFormattedSummaryJSON() + let banner: ActorImage = null + if (this.bannerId) { + banner = this.Banner.toFormattedJSON() + } + return Object.assign(base, { id: this.id, hostRedundancyAllowed: this.getRedundancyAllowed(), followingCount: this.followingCount, followersCount: this.followersCount, + banner, createdAt: this.createdAt, updatedAt: this.updatedAt }) } - toActivityPubObject (this: MActorAP, name: string) { + toActivityPubObject (this: MActorAPChannel | MActorAPAccount, name: string) { let icon: ActivityIconObject + let image: ActivityIconObject if (this.avatarId) { const extension = extname(this.Avatar.filename) icon = { type: 'Image', - mediaType: extension === '.png' ? 'image/png' : 'image/jpeg', + mediaType: MIMETYPES.IMAGE.EXT_MIMETYPE[extension], url: this.getAvatarUrl() } } + if (this.bannerId) { + const extension = extname((this as MActorAPChannel).Banner.filename) + + image = { + type: 'Image', + mediaType: MIMETYPES.IMAGE.EXT_MIMETYPE[extension], + url: this.getBannerUrl() + } + } + const json = { type: this.type, id: this.url, @@ -573,7 +603,8 @@ export class ActorModel extends Model { owner: this.url, publicKeyPem: this.publicKey }, - icon + icon, + image } return activityPubContextify(json) @@ -643,6 +674,12 @@ export class ActorModel extends Model { return WEBSERVER.URL + this.Avatar.getStaticPath() } + getBannerUrl () { + if (!this.bannerId) return undefined + + return WEBSERVER.URL + this.Banner.getStaticPath() + } + isOutdated () { if (this.isOwned()) return false diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index 815fb16c0..74885edfb 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -28,10 +28,9 @@ import { import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants' import { sendDeleteActor } from '../../lib/activitypub/send' import { - MChannelAccountDefault, MChannelActor, - MChannelActorAccountDefaultVideos, MChannelAP, + MChannelBannerAccountDefault, MChannelFormattable, MChannelSummaryFormattable } from '../../types/models/video' @@ -49,6 +48,7 @@ export enum ScopeNames { SUMMARY = 'SUMMARY', WITH_ACCOUNT = 'WITH_ACCOUNT', WITH_ACTOR = 'WITH_ACTOR', + WITH_ACTOR_BANNER = 'WITH_ACTOR_BANNER', WITH_VIDEOS = 'WITH_VIDEOS', WITH_STATS = 'WITH_STATS' } @@ -168,6 +168,20 @@ export type SummaryOptions = { ActorModel ] }, + [ScopeNames.WITH_ACTOR_BANNER]: { + include: [ + { + model: ActorModel, + include: [ + { + model: ActorImageModel, + required: false, + as: 'Banner' + } + ] + } + ] + }, [ScopeNames.WITH_VIDEOS]: { include: [ VideoModel @@ -442,7 +456,7 @@ export class VideoChannelModel extends Model { where } - const scopes: string | ScopeOptions | (string | ScopeOptions)[] = [ ScopeNames.WITH_ACTOR ] + const scopes: string | ScopeOptions | (string | ScopeOptions)[] = [ ScopeNames.WITH_ACTOR_BANNER ] if (options.withStats === true) { scopes.push({ @@ -458,32 +472,13 @@ export class VideoChannelModel extends Model { }) } - static loadByIdAndPopulateAccount (id: number): Promise { - return VideoChannelModel.unscoped() - .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) - .findByPk(id) - } - - static loadByIdAndAccount (id: number, accountId: number): Promise { - const query = { - where: { - id, - accountId - } - } - - return VideoChannelModel.unscoped() - .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) - .findOne(query) - } - - static loadAndPopulateAccount (id: number): Promise { + static loadAndPopulateAccount (id: number): Promise { return VideoChannelModel.unscoped() - .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) + .scope([ ScopeNames.WITH_ACTOR_BANNER, ScopeNames.WITH_ACCOUNT ]) .findByPk(id) } - static loadByUrlAndPopulateAccount (url: string): Promise { + static loadByUrlAndPopulateAccount (url: string): Promise { const query = { include: [ { @@ -491,7 +486,14 @@ export class VideoChannelModel extends Model { required: true, where: { url - } + }, + include: [ + { + model: ActorImageModel, + required: false, + as: 'Banner' + } + ] } ] } @@ -509,7 +511,7 @@ export class VideoChannelModel extends Model { return VideoChannelModel.loadByNameAndHostAndPopulateAccount(name, host) } - static loadLocalByNameAndPopulateAccount (name: string): Promise { + static loadLocalByNameAndPopulateAccount (name: string): Promise { const query = { include: [ { @@ -518,17 +520,24 @@ export class VideoChannelModel extends Model { where: { preferredUsername: name, serverId: null - } + }, + include: [ + { + model: ActorImageModel, + required: false, + as: 'Banner' + } + ] } ] } return VideoChannelModel.unscoped() - .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) + .scope([ ScopeNames.WITH_ACCOUNT ]) .findOne(query) } - static loadByNameAndHostAndPopulateAccount (name: string, host: string): Promise { + static loadByNameAndHostAndPopulateAccount (name: string, host: string): Promise { const query = { include: [ { @@ -542,6 +551,11 @@ export class VideoChannelModel extends Model { model: ServerModel, required: true, where: { host } + }, + { + model: ActorImageModel, + required: false, + as: 'Banner' } ] } @@ -549,22 +563,10 @@ export class VideoChannelModel extends Model { } return VideoChannelModel.unscoped() - .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT ]) + .scope([ ScopeNames.WITH_ACCOUNT ]) .findOne(query) } - static loadAndPopulateAccountAndVideos (id: number): Promise { - const options = { - include: [ - VideoModel - ] - } - - return VideoChannelModel.unscoped() - .scope([ ScopeNames.WITH_ACTOR, ScopeNames.WITH_ACCOUNT, ScopeNames.WITH_VIDEOS ]) - .findByPk(id, options) - } - toFormattedSummaryJSON (this: MChannelSummaryFormattable): VideoChannelSummary { const actor = this.Actor.toFormattedSummaryJSON() -- cgit v1.2.3