aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/models
diff options
context:
space:
mode:
Diffstat (limited to 'server/models')
-rw-r--r--server/models/abuse/abuse-message.ts2
-rw-r--r--server/models/abuse/abuse.ts3
-rw-r--r--server/models/abuse/video-abuse.ts2
-rw-r--r--server/models/abuse/video-comment-abuse.ts2
-rw-r--r--server/models/account/account-blocklist.ts42
-rw-r--r--server/models/account/account-video-rate.ts7
-rw-r--r--server/models/account/account.ts2
-rw-r--r--server/models/actor/actor-follow.ts2
-rw-r--r--server/models/actor/actor-image.ts2
-rw-r--r--server/models/actor/actor.ts4
-rw-r--r--server/models/application/application.ts2
-rw-r--r--server/models/oauth/oauth-client.ts2
-rw-r--r--server/models/oauth/oauth-token.ts2
-rw-r--r--server/models/redundancy/video-redundancy.ts14
-rw-r--r--server/models/server/plugin.ts14
-rw-r--r--server/models/server/server-blocklist.ts21
-rw-r--r--server/models/server/server.ts2
-rw-r--r--server/models/server/tracker.ts2
-rw-r--r--server/models/server/video-tracker.ts2
-rw-r--r--server/models/user/user-notification-setting.ts2
-rw-r--r--server/models/user/user-notification.ts6
-rw-r--r--server/models/user/user-video-history.ts2
-rw-r--r--server/models/user/user.ts15
-rw-r--r--server/models/video/formatter/video-format-utils.ts2
-rw-r--r--server/models/video/schedule-video-update.ts2
-rw-r--r--server/models/video/sql/videos-id-list-query-builder.ts5
-rw-r--r--server/models/video/tag.ts2
-rw-r--r--server/models/video/thumbnail.ts2
-rw-r--r--server/models/video/video-blacklist.ts2
-rw-r--r--server/models/video/video-caption.ts4
-rw-r--r--server/models/video/video-change-ownership.ts2
-rw-r--r--server/models/video/video-channel.ts5
-rw-r--r--server/models/video/video-comment.ts2
-rw-r--r--server/models/video/video-file.ts7
-rw-r--r--server/models/video/video-import.ts4
-rw-r--r--server/models/video/video-job-info.ts17
-rw-r--r--server/models/video/video-live.ts2
-rw-r--r--server/models/video/video-playlist-element.ts4
-rw-r--r--server/models/video/video-playlist.ts5
-rw-r--r--server/models/video/video-share.ts2
-rw-r--r--server/models/video/video-streaming-playlist.ts13
-rw-r--r--server/models/video/video-tag.ts2
-rw-r--r--server/models/video/video-view.ts2
-rw-r--r--server/models/video/video.ts40
44 files changed, 186 insertions, 94 deletions
diff --git a/server/models/abuse/abuse-message.ts b/server/models/abuse/abuse-message.ts
index 2c5987e96..6a441a210 100644
--- a/server/models/abuse/abuse-message.ts
+++ b/server/models/abuse/abuse-message.ts
@@ -1,7 +1,7 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses' 2import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses'
3import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models' 3import { MAbuseMessage, MAbuseMessageFormattable } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { AbuseMessage } from '@shared/models' 5import { AbuseMessage } from '@shared/models'
6import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account' 6import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account'
7import { getSort, throwIfNotValid } from '../utils' 7import { getSort, throwIfNotValid } from '../utils'
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts
index 3518f5c02..4344df006 100644
--- a/server/models/abuse/abuse.ts
+++ b/server/models/abuse/abuse.ts
@@ -16,7 +16,7 @@ import {
16 UpdatedAt 16 UpdatedAt
17} from 'sequelize-typescript' 17} from 'sequelize-typescript'
18import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses' 18import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses'
19import { abusePredefinedReasonsMap, AttributesOnly } from '@shared/core-utils' 19import { abusePredefinedReasonsMap } from '@shared/core-utils'
20import { 20import {
21 AbuseFilter, 21 AbuseFilter,
22 AbuseObject, 22 AbuseObject,
@@ -30,6 +30,7 @@ import {
30 UserAbuse, 30 UserAbuse,
31 UserVideoAbuse 31 UserVideoAbuse
32} from '@shared/models' 32} from '@shared/models'
33import { AttributesOnly } from '@shared/typescript-utils'
33import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' 34import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
34import { MAbuseAdminFormattable, MAbuseAP, MAbuseFull, MAbuseReporter, MAbuseUserFormattable, MUserAccountId } from '../../types/models' 35import { MAbuseAdminFormattable, MAbuseAP, MAbuseFull, MAbuseReporter, MAbuseUserFormattable, MUserAccountId } from '../../types/models'
35import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' 36import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account'
diff --git a/server/models/abuse/video-abuse.ts b/server/models/abuse/video-abuse.ts
index 95bff50d0..773a9ebba 100644
--- a/server/models/abuse/video-abuse.ts
+++ b/server/models/abuse/video-abuse.ts
@@ -1,5 +1,5 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { AttributesOnly } from '@shared/core-utils' 2import { AttributesOnly } from '@shared/typescript-utils'
3import { VideoDetails } from '@shared/models' 3import { VideoDetails } from '@shared/models'
4import { VideoModel } from '../video/video' 4import { VideoModel } from '../video/video'
5import { AbuseModel } from './abuse' 5import { AbuseModel } from './abuse'
diff --git a/server/models/abuse/video-comment-abuse.ts b/server/models/abuse/video-comment-abuse.ts
index 32cb2ca64..337aaaa58 100644
--- a/server/models/abuse/video-comment-abuse.ts
+++ b/server/models/abuse/video-comment-abuse.ts
@@ -1,5 +1,5 @@
1import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { AttributesOnly } from '@shared/core-utils' 2import { AttributesOnly } from '@shared/typescript-utils'
3import { VideoCommentModel } from '../video/video-comment' 3import { VideoCommentModel } from '../video/video-comment'
4import { AbuseModel } from './abuse' 4import { AbuseModel } from './abuse'
5 5
diff --git a/server/models/account/account-blocklist.ts b/server/models/account/account-blocklist.ts
index b2375b006..1162962bf 100644
--- a/server/models/account/account-blocklist.ts
+++ b/server/models/account/account-blocklist.ts
@@ -1,11 +1,12 @@
1import { Op } from 'sequelize' 1import { Op, QueryTypes } from 'sequelize'
2import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 2import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
3import { handlesToNameAndHost } from '@server/helpers/actors'
3import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models' 4import { MAccountBlocklist, MAccountBlocklistAccounts, MAccountBlocklistFormattable } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 5import { AttributesOnly } from '@shared/typescript-utils'
5import { AccountBlock } from '../../../shared/models' 6import { AccountBlock } from '../../../shared/models'
6import { ActorModel } from '../actor/actor' 7import { ActorModel } from '../actor/actor'
7import { ServerModel } from '../server/server' 8import { ServerModel } from '../server/server'
8import { getSort, searchAttribute } from '../utils' 9import { createSafeIn, getSort, searchAttribute } from '../utils'
9import { AccountModel } from './account' 10import { AccountModel } from './account'
10 11
11enum ScopeNames { 12enum ScopeNames {
@@ -77,7 +78,7 @@ export class AccountBlocklistModel extends Model<Partial<AttributesOnly<AccountB
77 }) 78 })
78 BlockedAccount: AccountModel 79 BlockedAccount: AccountModel
79 80
80 static isAccountMutedByMulti (accountIds: number[], targetAccountId: number) { 81 static isAccountMutedByAccounts (accountIds: number[], targetAccountId: number) {
81 const query = { 82 const query = {
82 attributes: [ 'accountId', 'id' ], 83 attributes: [ 'accountId', 'id' ],
83 where: { 84 where: {
@@ -187,6 +188,39 @@ export class AccountBlocklistModel extends Model<Partial<AttributesOnly<AccountB
187 .then(entries => entries.map(e => `${e.BlockedAccount.Actor.preferredUsername}@${e.BlockedAccount.Actor.Server.host}`)) 188 .then(entries => entries.map(e => `${e.BlockedAccount.Actor.preferredUsername}@${e.BlockedAccount.Actor.Server.host}`))
188 } 189 }
189 190
191 static getBlockStatus (byAccountIds: number[], handles: string[]): Promise<{ name: string, host: string, accountId: number }[]> {
192 const sanitizedHandles = handlesToNameAndHost(handles)
193
194 const localHandles = sanitizedHandles.filter(h => !h.host)
195 .map(h => h.name)
196
197 const remoteHandles = sanitizedHandles.filter(h => !!h.host)
198 .map(h => ([ h.name, h.host ]))
199
200 const handlesWhere: string[] = []
201
202 if (localHandles.length !== 0) {
203 handlesWhere.push(`("actor"."preferredUsername" IN (:localHandles) AND "server"."id" IS NULL)`)
204 }
205
206 if (remoteHandles.length !== 0) {
207 handlesWhere.push(`(("actor"."preferredUsername", "server"."host") IN (:remoteHandles))`)
208 }
209
210 const rawQuery = `SELECT "accountBlocklist"."accountId", "actor"."preferredUsername" AS "name", "server"."host" ` +
211 `FROM "accountBlocklist" ` +
212 `INNER JOIN "account" ON "account"."id" = "accountBlocklist"."targetAccountId" ` +
213 `INNER JOIN "actor" ON "actor"."id" = "account"."actorId" ` +
214 `LEFT JOIN "server" ON "server"."id" = "actor"."serverId" ` +
215 `WHERE "accountBlocklist"."accountId" IN (${createSafeIn(AccountBlocklistModel.sequelize, byAccountIds)}) ` +
216 `AND (${handlesWhere.join(' OR ')})`
217
218 return AccountBlocklistModel.sequelize.query(rawQuery, {
219 type: QueryTypes.SELECT as QueryTypes.SELECT,
220 replacements: { byAccountIds, localHandles, remoteHandles }
221 })
222 }
223
190 toFormattedJSON (this: MAccountBlocklistFormattable): AccountBlock { 224 toFormattedJSON (this: MAccountBlocklistFormattable): AccountBlock {
191 return { 225 return {
192 byAccount: this.ByAccount.toFormattedJSON(), 226 byAccount: this.ByAccount.toFormattedJSON(),
diff --git a/server/models/account/account-video-rate.ts b/server/models/account/account-video-rate.ts
index ee6dbc6da..e89d31adf 100644
--- a/server/models/account/account-video-rate.ts
+++ b/server/models/account/account-video-rate.ts
@@ -6,10 +6,9 @@ import {
6 MAccountVideoRateAccountUrl, 6 MAccountVideoRateAccountUrl,
7 MAccountVideoRateAccountVideo, 7 MAccountVideoRateAccountVideo,
8 MAccountVideoRateFormattable 8 MAccountVideoRateFormattable
9} from '@server/types/models/video/video-rate' 9} from '@server/types/models'
10import { AttributesOnly } from '@shared/core-utils' 10import { AccountVideoRate, VideoRateType } from '@shared/models'
11import { AccountVideoRate } from '../../../shared' 11import { AttributesOnly } from '@shared/typescript-utils'
12import { VideoRateType } from '../../../shared/models/videos'
13import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 12import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
14import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants' 13import { CONSTRAINTS_FIELDS, VIDEO_RATE_TYPES } from '../../initializers/constants'
15import { ActorModel } from '../actor/actor' 14import { ActorModel } from '../actor/actor'
diff --git a/server/models/account/account.ts b/server/models/account/account.ts
index 71a9b8ccb..619a598dd 100644
--- a/server/models/account/account.ts
+++ b/server/models/account/account.ts
@@ -17,7 +17,7 @@ import {
17 UpdatedAt 17 UpdatedAt
18} from 'sequelize-typescript' 18} from 'sequelize-typescript'
19import { ModelCache } from '@server/models/model-cache' 19import { ModelCache } from '@server/models/model-cache'
20import { AttributesOnly } from '@shared/core-utils' 20import { AttributesOnly } from '@shared/typescript-utils'
21import { Account, AccountSummary } from '../../../shared/models/actors' 21import { Account, AccountSummary } from '../../../shared/models/actors'
22import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts' 22import { isAccountDescriptionValid } from '../../helpers/custom-validators/accounts'
23import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' 23import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants'
diff --git a/server/models/actor/actor-follow.ts b/server/models/actor/actor-follow.ts
index d6a2387a5..006282530 100644
--- a/server/models/actor/actor-follow.ts
+++ b/server/models/actor/actor-follow.ts
@@ -30,7 +30,7 @@ import {
30 MActorFollowFormattable, 30 MActorFollowFormattable,
31 MActorFollowSubscriptions 31 MActorFollowSubscriptions
32} from '@server/types/models' 32} from '@server/types/models'
33import { AttributesOnly } from '@shared/core-utils' 33import { AttributesOnly } from '@shared/typescript-utils'
34import { ActivityPubActorType } from '@shared/models' 34import { ActivityPubActorType } from '@shared/models'
35import { FollowState } from '../../../shared/models/actors' 35import { FollowState } from '../../../shared/models/actors'
36import { ActorFollow } from '../../../shared/models/actors/follow.model' 36import { ActorFollow } from '../../../shared/models/actors/follow.model'
diff --git a/server/models/actor/actor-image.ts b/server/models/actor/actor-image.ts
index 98a7f6fba..8edff5ab4 100644
--- a/server/models/actor/actor-image.ts
+++ b/server/models/actor/actor-image.ts
@@ -2,7 +2,7 @@ import { remove } from 'fs-extra'
2import { join } from 'path' 2import { join } from 'path'
3import { AfterDestroy, AllowNull, Column, CreatedAt, Default, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 3import { AfterDestroy, AllowNull, Column, CreatedAt, Default, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
4import { MActorImageFormattable } from '@server/types/models' 4import { MActorImageFormattable } from '@server/types/models'
5import { AttributesOnly } from '@shared/core-utils' 5import { AttributesOnly } from '@shared/typescript-utils'
6import { ActorImageType } from '@shared/models' 6import { ActorImageType } from '@shared/models'
7import { ActorImage } from '../../../shared/models/actors/actor-image.model' 7import { ActorImage } from '../../../shared/models/actors/actor-image.model'
8import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 8import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
diff --git a/server/models/actor/actor.ts b/server/models/actor/actor.ts
index 8df49951d..c12dcf634 100644
--- a/server/models/actor/actor.ts
+++ b/server/models/actor/actor.ts
@@ -16,9 +16,9 @@ import {
16 Table, 16 Table,
17 UpdatedAt 17 UpdatedAt
18} from 'sequelize-typescript' 18} from 'sequelize-typescript'
19import { getLowercaseExtension } from '@server/helpers/core-utils'
20import { ModelCache } from '@server/models/model-cache' 19import { ModelCache } from '@server/models/model-cache'
21import { AttributesOnly } from '@shared/core-utils' 20import { getLowercaseExtension } from '@shared/core-utils'
21import { AttributesOnly } from '@shared/typescript-utils'
22import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub' 22import { ActivityIconObject, ActivityPubActorType } from '../../../shared/models/activitypub'
23import { ActorImage } from '../../../shared/models/actors/actor-image.model' 23import { ActorImage } from '../../../shared/models/actors/actor-image.model'
24import { activityPubContextify } from '../../helpers/activitypub' 24import { activityPubContextify } from '../../helpers/activitypub'
diff --git a/server/models/application/application.ts b/server/models/application/application.ts
index e3939383b..a479de5d2 100644
--- a/server/models/application/application.ts
+++ b/server/models/application/application.ts
@@ -1,6 +1,6 @@
1import memoizee from 'memoizee' 1import memoizee from 'memoizee'
2import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Model, Table } from 'sequelize-typescript' 2import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Model, Table } from 'sequelize-typescript'
3import { AttributesOnly } from '@shared/core-utils' 3import { AttributesOnly } from '@shared/typescript-utils'
4import { AccountModel } from '../account/account' 4import { AccountModel } from '../account/account'
5 5
6export const getServerActor = memoizee(async function () { 6export const getServerActor = memoizee(async function () {
diff --git a/server/models/oauth/oauth-client.ts b/server/models/oauth/oauth-client.ts
index 890954bdb..860fa6f53 100644
--- a/server/models/oauth/oauth-client.ts
+++ b/server/models/oauth/oauth-client.ts
@@ -1,5 +1,5 @@
1import { AllowNull, Column, CreatedAt, DataType, HasMany, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, Column, CreatedAt, DataType, HasMany, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { AttributesOnly } from '@shared/core-utils' 2import { AttributesOnly } from '@shared/typescript-utils'
3import { OAuthTokenModel } from './oauth-token' 3import { OAuthTokenModel } from './oauth-token'
4 4
5@Table({ 5@Table({
diff --git a/server/models/oauth/oauth-token.ts b/server/models/oauth/oauth-token.ts
index af4b0ec42..f72423190 100644
--- a/server/models/oauth/oauth-token.ts
+++ b/server/models/oauth/oauth-token.ts
@@ -15,7 +15,7 @@ import {
15import { TokensCache } from '@server/lib/auth/tokens-cache' 15import { TokensCache } from '@server/lib/auth/tokens-cache'
16import { MUserAccountId } from '@server/types/models' 16import { MUserAccountId } from '@server/types/models'
17import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' 17import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token'
18import { AttributesOnly } from '@shared/core-utils' 18import { AttributesOnly } from '@shared/typescript-utils'
19import { logger } from '../../helpers/logger' 19import { logger } from '../../helpers/logger'
20import { AccountModel } from '../account/account' 20import { AccountModel } from '../account/account'
21import { ActorModel } from '../actor/actor' 21import { ActorModel } from '../actor/actor'
diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts
index e8d79a3ab..6f84747da 100644
--- a/server/models/redundancy/video-redundancy.ts
+++ b/server/models/redundancy/video-redundancy.ts
@@ -16,15 +16,17 @@ import {
16} from 'sequelize-typescript' 16} from 'sequelize-typescript'
17import { getServerActor } from '@server/models/application/application' 17import { getServerActor } from '@server/models/application/application'
18import { MActor, MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models' 18import { MActor, MVideoForRedundancyAPI, MVideoRedundancy, MVideoRedundancyAP, MVideoRedundancyVideo } from '@server/types/models'
19import { AttributesOnly } from '@shared/core-utils'
20import { VideoRedundanciesTarget } from '@shared/models/redundancy/video-redundancies-filters.model'
21import { 19import {
20 CacheFileObject,
22 FileRedundancyInformation, 21 FileRedundancyInformation,
23 StreamingPlaylistRedundancyInformation, 22 StreamingPlaylistRedundancyInformation,
24 VideoRedundancy 23 VideoPrivacy,
25} from '@shared/models/redundancy/video-redundancy.model' 24 VideoRedundanciesTarget,
26import { CacheFileObject, VideoPrivacy } from '../../../shared' 25 VideoRedundancy,
27import { VideoRedundancyStrategy, VideoRedundancyStrategyWithManual } from '../../../shared/models/redundancy' 26 VideoRedundancyStrategy,
27 VideoRedundancyStrategyWithManual
28} from '@shared/models'
29import { AttributesOnly } from '@shared/typescript-utils'
28import { isTestInstance } from '../../helpers/core-utils' 30import { isTestInstance } from '../../helpers/core-utils'
29import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc' 31import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
30import { logger } from '../../helpers/logger' 32import { logger } from '../../helpers/logger'
diff --git a/server/models/server/plugin.ts b/server/models/server/plugin.ts
index a8de64dd4..84f7a14e4 100644
--- a/server/models/server/plugin.ts
+++ b/server/models/server/plugin.ts
@@ -1,7 +1,7 @@
1import { FindAndCountOptions, json, QueryTypes } from 'sequelize' 1import { FindAndCountOptions, json, QueryTypes } from 'sequelize'
2import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { MPlugin, MPluginFormattable } from '@server/types/models' 3import { MPlugin, MPluginFormattable } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { PeerTubePlugin, PluginType, RegisterServerSettingOptions } from '../../../shared/models' 5import { PeerTubePlugin, PluginType, RegisterServerSettingOptions } from '../../../shared/models'
6import { 6import {
7 isPluginDescriptionValid, 7 isPluginDescriptionValid,
@@ -197,15 +197,11 @@ export class PluginModel extends Model<Partial<AttributesOnly<PluginModel>>> {
197 if (!c) return undefined 197 if (!c) return undefined
198 const value = c.value 198 const value = c.value
199 199
200 if (typeof value === 'string' && value.startsWith('{')) { 200 try {
201 try { 201 return JSON.parse(value)
202 return JSON.parse(value) 202 } catch {
203 } catch { 203 return value
204 return value
205 }
206 } 204 }
207
208 return c.value
209 }) 205 })
210 } 206 }
211 207
diff --git a/server/models/server/server-blocklist.ts b/server/models/server/server-blocklist.ts
index b3579d589..9f64eeb7f 100644
--- a/server/models/server/server-blocklist.ts
+++ b/server/models/server/server-blocklist.ts
@@ -1,10 +1,10 @@
1import { Op } from 'sequelize' 1import { Op, QueryTypes } from 'sequelize'
2import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 2import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
3import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models' 3import { MServerBlocklist, MServerBlocklistAccountServer, MServerBlocklistFormattable } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { ServerBlock } from '@shared/models' 5import { ServerBlock } from '@shared/models'
6import { AccountModel } from '../account/account' 6import { AccountModel } from '../account/account'
7import { getSort, searchAttribute } from '../utils' 7import { createSafeIn, getSort, searchAttribute } from '../utils'
8import { ServerModel } from './server' 8import { ServerModel } from './server'
9 9
10enum ScopeNames { 10enum ScopeNames {
@@ -76,7 +76,7 @@ export class ServerBlocklistModel extends Model<Partial<AttributesOnly<ServerBlo
76 }) 76 })
77 BlockedServer: ServerModel 77 BlockedServer: ServerModel
78 78
79 static isServerMutedByMulti (accountIds: number[], targetServerId: number) { 79 static isServerMutedByAccounts (accountIds: number[], targetServerId: number) {
80 const query = { 80 const query = {
81 attributes: [ 'accountId', 'id' ], 81 attributes: [ 'accountId', 'id' ],
82 where: { 82 where: {
@@ -141,6 +141,19 @@ export class ServerBlocklistModel extends Model<Partial<AttributesOnly<ServerBlo
141 .then(entries => entries.map(e => e.BlockedServer.host)) 141 .then(entries => entries.map(e => e.BlockedServer.host))
142 } 142 }
143 143
144 static getBlockStatus (byAccountIds: number[], hosts: string[]): Promise<{ host: string, accountId: number }[]> {
145 const rawQuery = `SELECT "server"."host", "serverBlocklist"."accountId" ` +
146 `FROM "serverBlocklist" ` +
147 `INNER JOIN "server" ON "server"."id" = "serverBlocklist"."targetServerId" ` +
148 `WHERE "server"."host" IN (:hosts) ` +
149 `AND "serverBlocklist"."accountId" IN (${createSafeIn(ServerBlocklistModel.sequelize, byAccountIds)})`
150
151 return ServerBlocklistModel.sequelize.query(rawQuery, {
152 type: QueryTypes.SELECT as QueryTypes.SELECT,
153 replacements: { hosts }
154 })
155 }
156
144 static listForApi (parameters: { 157 static listForApi (parameters: {
145 start: number 158 start: number
146 count: number 159 count: number
diff --git a/server/models/server/server.ts b/server/models/server/server.ts
index edbe92f73..ef42de090 100644
--- a/server/models/server/server.ts
+++ b/server/models/server/server.ts
@@ -1,7 +1,7 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, Column, CreatedAt, Default, HasMany, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { MServer, MServerFormattable } from '@server/types/models/server' 3import { MServer, MServerFormattable } from '@server/types/models/server'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { isHostValid } from '../../helpers/custom-validators/servers' 5import { isHostValid } from '../../helpers/custom-validators/servers'
6import { ActorModel } from '../actor/actor' 6import { ActorModel } from '../actor/actor'
7import { throwIfNotValid } from '../utils' 7import { throwIfNotValid } from '../utils'
diff --git a/server/models/server/tracker.ts b/server/models/server/tracker.ts
index c09fdd64b..ee087c4a3 100644
--- a/server/models/server/tracker.ts
+++ b/server/models/server/tracker.ts
@@ -1,7 +1,7 @@
1import { AllowNull, BelongsToMany, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsToMany, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { Transaction } from 'sequelize/types' 2import { Transaction } from 'sequelize/types'
3import { MTracker } from '@server/types/models/server/tracker' 3import { MTracker } from '@server/types/models/server/tracker'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { VideoModel } from '../video/video' 5import { VideoModel } from '../video/video'
6import { VideoTrackerModel } from './video-tracker' 6import { VideoTrackerModel } from './video-tracker'
7 7
diff --git a/server/models/server/video-tracker.ts b/server/models/server/video-tracker.ts
index c49fbd1c6..f14f3bd7d 100644
--- a/server/models/server/video-tracker.ts
+++ b/server/models/server/video-tracker.ts
@@ -1,5 +1,5 @@
1import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { AttributesOnly } from '@shared/core-utils' 2import { AttributesOnly } from '@shared/typescript-utils'
3import { VideoModel } from '../video/video' 3import { VideoModel } from '../video/video'
4import { TrackerModel } from './tracker' 4import { TrackerModel } from './tracker'
5 5
diff --git a/server/models/user/user-notification-setting.ts b/server/models/user/user-notification-setting.ts
index bee7d7851..f03b19e41 100644
--- a/server/models/user/user-notification-setting.ts
+++ b/server/models/user/user-notification-setting.ts
@@ -14,7 +14,7 @@ import {
14} from 'sequelize-typescript' 14} from 'sequelize-typescript'
15import { TokensCache } from '@server/lib/auth/tokens-cache' 15import { TokensCache } from '@server/lib/auth/tokens-cache'
16import { MNotificationSettingFormattable } from '@server/types/models' 16import { MNotificationSettingFormattable } from '@server/types/models'
17import { AttributesOnly } from '@shared/core-utils' 17import { AttributesOnly } from '@shared/typescript-utils'
18import { UserNotificationSetting, UserNotificationSettingValue } from '../../../shared/models/users/user-notification-setting.model' 18import { UserNotificationSetting, UserNotificationSettingValue } from '../../../shared/models/users/user-notification-setting.model'
19import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications' 19import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications'
20import { throwIfNotValid } from '../utils' 20import { throwIfNotValid } from '../utils'
diff --git a/server/models/user/user-notification.ts b/server/models/user/user-notification.ts
index 04c5513a9..edad10a55 100644
--- a/server/models/user/user-notification.ts
+++ b/server/models/user/user-notification.ts
@@ -1,9 +1,9 @@
1import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize' 1import { FindOptions, ModelIndexesOptions, Op, WhereOptions } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
3import { uuidToShort } from '@server/helpers/uuid'
4import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user' 3import { UserNotificationIncludes, UserNotificationModelForApi } from '@server/types/models/user'
5import { AttributesOnly } from '@shared/core-utils' 4import { uuidToShort } from '@shared/extra-utils'
6import { UserNotification, UserNotificationType } from '../../../shared' 5import { UserNotification, UserNotificationType } from '@shared/models'
6import { AttributesOnly } from '@shared/typescript-utils'
7import { isBooleanValid } from '../../helpers/custom-validators/misc' 7import { isBooleanValid } from '../../helpers/custom-validators/misc'
8import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications' 8import { isUserNotificationTypeValid } from '../../helpers/custom-validators/user-notifications'
9import { AbuseModel } from '../abuse/abuse' 9import { AbuseModel } from '../abuse/abuse'
diff --git a/server/models/user/user-video-history.ts b/server/models/user/user-video-history.ts
index 1aefdf02b..6d9f2e03f 100644
--- a/server/models/user/user-video-history.ts
+++ b/server/models/user/user-video-history.ts
@@ -1,7 +1,7 @@
1import { DestroyOptions, Op, Transaction } from 'sequelize' 1import { DestroyOptions, Op, Transaction } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, IsInt, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { MUserAccountId, MUserId } from '@server/types/models' 3import { MUserAccountId, MUserId } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { VideoModel } from '../video/video' 5import { VideoModel } from '../video/video'
6import { UserModel } from './user' 6import { UserModel } from './user'
7import { getServerActor } from '../application/application' 7import { getServerActor } from '../application/application'
diff --git a/server/models/user/user.ts b/server/models/user/user.ts
index b56f37e55..4ad76e5bc 100644
--- a/server/models/user/user.ts
+++ b/server/models/user/user.ts
@@ -31,7 +31,7 @@ import {
31 MUserWithNotificationSetting, 31 MUserWithNotificationSetting,
32 MVideoWithRights 32 MVideoWithRights
33} from '@server/types/models' 33} from '@server/types/models'
34import { AttributesOnly } from '@shared/core-utils' 34import { AttributesOnly } from '@shared/typescript-utils'
35import { hasUserRight, USER_ROLE_LABELS } from '../../../shared/core-utils/users' 35import { hasUserRight, USER_ROLE_LABELS } from '../../../shared/core-utils/users'
36import { AbuseState, MyUser, UserRight, VideoPlaylistType, VideoPrivacy } from '../../../shared/models' 36import { AbuseState, MyUser, UserRight, VideoPlaylistType, VideoPrivacy } from '../../../shared/models'
37import { User, UserRole } from '../../../shared/models/users' 37import { User, UserRole } from '../../../shared/models/users'
@@ -55,7 +55,7 @@ import {
55 isUserVideoQuotaDailyValid, 55 isUserVideoQuotaDailyValid,
56 isUserVideoQuotaValid, 56 isUserVideoQuotaValid,
57 isUserVideosHistoryEnabledValid, 57 isUserVideosHistoryEnabledValid,
58 isUserWebTorrentEnabledValid 58 isUserP2PEnabledValid
59} from '../../helpers/custom-validators/users' 59} from '../../helpers/custom-validators/users'
60import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto' 60import { comparePassword, cryptPassword } from '../../helpers/peertube-crypto'
61import { DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants' 61import { DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants'
@@ -267,10 +267,9 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
267 nsfwPolicy: NSFWPolicyType 267 nsfwPolicy: NSFWPolicyType
268 268
269 @AllowNull(false) 269 @AllowNull(false)
270 @Default(true) 270 @Is('p2pEnabled', value => throwIfNotValid(value, isUserP2PEnabledValid, 'P2P enabled'))
271 @Is('UserWebTorrentEnabled', value => throwIfNotValid(value, isUserWebTorrentEnabledValid, 'WebTorrent enabled'))
272 @Column 271 @Column
273 webTorrentEnabled: boolean 272 p2pEnabled: boolean
274 273
275 @AllowNull(false) 274 @AllowNull(false)
276 @Default(true) 275 @Default(true)
@@ -892,7 +891,11 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
892 emailVerified: this.emailVerified, 891 emailVerified: this.emailVerified,
893 892
894 nsfwPolicy: this.nsfwPolicy, 893 nsfwPolicy: this.nsfwPolicy,
895 webTorrentEnabled: this.webTorrentEnabled, 894
895 // FIXME: deprecated in 4.1
896 webTorrentEnabled: this.p2pEnabled,
897 p2pEnabled: this.p2pEnabled,
898
896 videosHistoryEnabled: this.videosHistoryEnabled, 899 videosHistoryEnabled: this.videosHistoryEnabled,
897 autoPlayVideo: this.autoPlayVideo, 900 autoPlayVideo: this.autoPlayVideo,
898 autoPlayNextVideo: this.autoPlayNextVideo, 901 autoPlayNextVideo: this.autoPlayNextVideo,
diff --git a/server/models/video/formatter/video-format-utils.ts b/server/models/video/formatter/video-format-utils.ts
index fd4da68ed..7456f37c5 100644
--- a/server/models/video/formatter/video-format-utils.ts
+++ b/server/models/video/formatter/video-format-utils.ts
@@ -1,7 +1,7 @@
1import { uuidToShort } from '@server/helpers/uuid'
2import { generateMagnetUri } from '@server/helpers/webtorrent' 1import { generateMagnetUri } from '@server/helpers/webtorrent'
3import { getLocalVideoFileMetadataUrl } from '@server/lib/video-urls' 2import { getLocalVideoFileMetadataUrl } from '@server/lib/video-urls'
4import { VideoViews } from '@server/lib/video-views' 3import { VideoViews } from '@server/lib/video-views'
4import { uuidToShort } from '@shared/extra-utils'
5import { VideoFile, VideosCommonQueryAfterSanitize } from '@shared/models' 5import { VideoFile, VideosCommonQueryAfterSanitize } from '@shared/models'
6import { ActivityTagObject, ActivityUrlObject, VideoObject } from '../../../../shared/models/activitypub/objects' 6import { ActivityTagObject, ActivityUrlObject, VideoObject } from '../../../../shared/models/activitypub/objects'
7import { Video, VideoDetails, VideoInclude } from '../../../../shared/models/videos' 7import { Video, VideoDetails, VideoInclude } from '../../../../shared/models/videos'
diff --git a/server/models/video/schedule-video-update.ts b/server/models/video/schedule-video-update.ts
index d462c20c7..b3cf26966 100644
--- a/server/models/video/schedule-video-update.ts
+++ b/server/models/video/schedule-video-update.ts
@@ -1,7 +1,7 @@
1import { Op, Transaction } from 'sequelize' 1import { Op, Transaction } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdate } from '@server/types/models' 3import { MScheduleVideoUpdateFormattable, MScheduleVideoUpdate } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { VideoPrivacy } from '../../../shared/models/videos' 5import { VideoPrivacy } from '../../../shared/models/videos'
6import { VideoModel } from './video' 6import { VideoModel } from './video'
7 7
diff --git a/server/models/video/sql/videos-id-list-query-builder.ts b/server/models/video/sql/videos-id-list-query-builder.ts
index d825225ab..76aafb883 100644
--- a/server/models/video/sql/videos-id-list-query-builder.ts
+++ b/server/models/video/sql/videos-id-list-query-builder.ts
@@ -367,9 +367,10 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
367 ' WHERE "videoShare"."videoId" = "video"."id"' + 367 ' WHERE "videoShare"."videoId" = "video"."id"' +
368 ' )' + 368 ' )' +
369 ' OR' + 369 ' OR' +
370 ' EXISTS (' + // Videos published by accounts we follow 370 ' EXISTS (' + // Videos published by channels or accounts we follow
371 ' SELECT 1 from "actorFollow" ' + 371 ' SELECT 1 from "actorFollow" ' +
372 ' WHERE "actorFollow"."targetActorId" = "account"."actorId" AND "actorFollow"."actorId" = :followerActorId ' + 372 ' WHERE ("actorFollow"."targetActorId" = "account"."actorId" OR "actorFollow"."targetActorId" = "videoChannel"."actorId") ' +
373 ' AND "actorFollow"."actorId" = :followerActorId ' +
373 ' AND "actorFollow"."state" = \'accepted\'' + 374 ' AND "actorFollow"."state" = \'accepted\'' +
374 ' )' 375 ' )'
375 376
diff --git a/server/models/video/tag.ts b/server/models/video/tag.ts
index 61dfb224d..7900e070d 100644
--- a/server/models/video/tag.ts
+++ b/server/models/video/tag.ts
@@ -1,7 +1,7 @@
1import { col, fn, QueryTypes, Transaction } from 'sequelize' 1import { col, fn, QueryTypes, Transaction } from 'sequelize'
2import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsToMany, Column, CreatedAt, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { MTag } from '@server/types/models' 3import { MTag } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { VideoPrivacy, VideoState } from '../../../shared/models/videos' 5import { VideoPrivacy, VideoState } from '../../../shared/models/videos'
6import { isVideoTagValid } from '../../helpers/custom-validators/videos' 6import { isVideoTagValid } from '../../helpers/custom-validators/videos'
7import { throwIfNotValid } from '../utils' 7import { throwIfNotValid } from '../utils'
diff --git a/server/models/video/thumbnail.ts b/server/models/video/thumbnail.ts
index 3388478d9..05c58cf19 100644
--- a/server/models/video/thumbnail.ts
+++ b/server/models/video/thumbnail.ts
@@ -17,7 +17,7 @@ import {
17} from 'sequelize-typescript' 17} from 'sequelize-typescript'
18import { afterCommitIfTransaction } from '@server/helpers/database-utils' 18import { afterCommitIfTransaction } from '@server/helpers/database-utils'
19import { MThumbnail, MThumbnailVideo, MVideo } from '@server/types/models' 19import { MThumbnail, MThumbnailVideo, MVideo } from '@server/types/models'
20import { AttributesOnly } from '@shared/core-utils' 20import { AttributesOnly } from '@shared/typescript-utils'
21import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' 21import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
22import { logger } from '../../helpers/logger' 22import { logger } from '../../helpers/logger'
23import { CONFIG } from '../../initializers/config' 23import { CONFIG } from '../../initializers/config'
diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts
index 98f4ec9c5..1cd8224c0 100644
--- a/server/models/video/video-blacklist.ts
+++ b/server/models/video/video-blacklist.ts
@@ -1,7 +1,7 @@
1import { FindOptions } from 'sequelize' 1import { FindOptions } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
3import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models' 3import { MVideoBlacklist, MVideoBlacklistFormattable } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' 5import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos'
6import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' 6import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist'
7import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 7import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
diff --git a/server/models/video/video-caption.ts b/server/models/video/video-caption.ts
index d24be56c3..6b240f116 100644
--- a/server/models/video/video-caption.ts
+++ b/server/models/video/video-caption.ts
@@ -15,9 +15,9 @@ import {
15 Table, 15 Table,
16 UpdatedAt 16 UpdatedAt
17} from 'sequelize-typescript' 17} from 'sequelize-typescript'
18import { buildUUID } from '@server/helpers/uuid'
19import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models' 18import { MVideo, MVideoCaption, MVideoCaptionFormattable, MVideoCaptionVideo } from '@server/types/models'
20import { AttributesOnly } from '@shared/core-utils' 19import { buildUUID } from '@shared/extra-utils'
20import { AttributesOnly } from '@shared/typescript-utils'
21import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model' 21import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model'
22import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions' 22import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions'
23import { logger } from '../../helpers/logger' 23import { logger } from '../../helpers/logger'
diff --git a/server/models/video/video-change-ownership.ts b/server/models/video/video-change-ownership.ts
index 7d20a954d..1a1b8c88d 100644
--- a/server/models/video/video-change-ownership.ts
+++ b/server/models/video/video-change-ownership.ts
@@ -1,6 +1,6 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
2import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership' 2import { MVideoChangeOwnershipFormattable, MVideoChangeOwnershipFull } from '@server/types/models/video/video-change-ownership'
3import { AttributesOnly } from '@shared/core-utils' 3import { AttributesOnly } from '@shared/typescript-utils'
4import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos' 4import { VideoChangeOwnership, VideoChangeOwnershipStatus } from '../../../shared/models/videos'
5import { AccountModel } from '../account/account' 5import { AccountModel } from '../account/account'
6import { getSort } from '../utils' 6import { getSort } from '../utils'
diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts
index b652d8531..2c6669bcb 100644
--- a/server/models/video/video-channel.ts
+++ b/server/models/video/video-channel.ts
@@ -17,8 +17,10 @@ import {
17 Table, 17 Table,
18 UpdatedAt 18 UpdatedAt
19} from 'sequelize-typescript' 19} from 'sequelize-typescript'
20import { CONFIG } from '@server/initializers/config'
20import { MAccountActor } from '@server/types/models' 21import { MAccountActor } from '@server/types/models'
21import { AttributesOnly, pick } from '@shared/core-utils' 22import { pick } from '@shared/core-utils'
23import { AttributesOnly } from '@shared/typescript-utils'
22import { ActivityPubActor } from '../../../shared/models/activitypub' 24import { ActivityPubActor } from '../../../shared/models/activitypub'
23import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos' 25import { VideoChannel, VideoChannelSummary } from '../../../shared/models/videos'
24import { 26import {
@@ -44,7 +46,6 @@ import { setAsUpdated } from '../shared'
44import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils' 46import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils'
45import { VideoModel } from './video' 47import { VideoModel } from './video'
46import { VideoPlaylistModel } from './video-playlist' 48import { VideoPlaylistModel } from './video-playlist'
47import { CONFIG } from '@server/initializers/config'
48 49
49export enum ScopeNames { 50export enum ScopeNames {
50 FOR_API = 'FOR_API', 51 FOR_API = 'FOR_API',
diff --git a/server/models/video/video-comment.ts b/server/models/video/video-comment.ts
index c89279c65..7f28b86b4 100644
--- a/server/models/video/video-comment.ts
+++ b/server/models/video/video-comment.ts
@@ -16,7 +16,7 @@ import {
16} from 'sequelize-typescript' 16} from 'sequelize-typescript'
17import { getServerActor } from '@server/models/application/application' 17import { getServerActor } from '@server/models/application/application'
18import { MAccount, MAccountId, MUserAccountId } from '@server/types/models' 18import { MAccount, MAccountId, MUserAccountId } from '@server/types/models'
19import { AttributesOnly } from '@shared/core-utils' 19import { AttributesOnly } from '@shared/typescript-utils'
20import { VideoPrivacy } from '@shared/models' 20import { VideoPrivacy } from '@shared/models'
21import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects' 21import { ActivityTagObject, ActivityTombstoneObject } from '../../../shared/models/activitypub/objects/common-objects'
22import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object' 22import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object'
diff --git a/server/models/video/video-file.ts b/server/models/video/video-file.ts
index 87311c0ed..6f03fae3a 100644
--- a/server/models/video/video-file.ts
+++ b/server/models/video/video-file.ts
@@ -26,8 +26,8 @@ import { extractVideo } from '@server/helpers/video'
26import { getHLSPublicFileUrl, getWebTorrentPublicFileUrl } from '@server/lib/object-storage' 26import { getHLSPublicFileUrl, getWebTorrentPublicFileUrl } from '@server/lib/object-storage'
27import { getFSTorrentFilePath } from '@server/lib/paths' 27import { getFSTorrentFilePath } from '@server/lib/paths'
28import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models' 28import { isStreamingPlaylist, MStreamingPlaylistVideo, MVideo, MVideoWithHost } from '@server/types/models'
29import { AttributesOnly } from '@shared/core-utils' 29import { VideoResolution, VideoStorage } from '@shared/models'
30import { VideoStorage } from '@shared/models' 30import { AttributesOnly } from '@shared/typescript-utils'
31import { 31import {
32 isVideoFileExtnameValid, 32 isVideoFileExtnameValid,
33 isVideoFileInfoHashValid, 33 isVideoFileInfoHashValid,
@@ -39,7 +39,6 @@ import {
39 LAZY_STATIC_PATHS, 39 LAZY_STATIC_PATHS,
40 MEMOIZE_LENGTH, 40 MEMOIZE_LENGTH,
41 MEMOIZE_TTL, 41 MEMOIZE_TTL,
42 MIMETYPES,
43 STATIC_DOWNLOAD_PATHS, 42 STATIC_DOWNLOAD_PATHS,
44 STATIC_PATHS, 43 STATIC_PATHS,
45 WEBSERVER 44 WEBSERVER
@@ -448,7 +447,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
448 } 447 }
449 448
450 isAudio () { 449 isAudio () {
451 return !!MIMETYPES.AUDIO.EXT_MIMETYPE[this.extname] 450 return this.resolution === VideoResolution.H_NOVIDEO
452 } 451 }
453 452
454 isLive () { 453 isLive () {
diff --git a/server/models/video/video-import.ts b/server/models/video/video-import.ts
index 5c73fb07c..c5c1a10f4 100644
--- a/server/models/video/video-import.ts
+++ b/server/models/video/video-import.ts
@@ -15,8 +15,8 @@ import {
15} from 'sequelize-typescript' 15} from 'sequelize-typescript'
16import { afterCommitIfTransaction } from '@server/helpers/database-utils' 16import { afterCommitIfTransaction } from '@server/helpers/database-utils'
17import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import' 17import { MVideoImportDefault, MVideoImportFormattable } from '@server/types/models/video/video-import'
18import { AttributesOnly } from '@shared/core-utils' 18import { VideoImport, VideoImportState } from '@shared/models'
19import { VideoImport, VideoImportState } from '../../../shared' 19import { AttributesOnly } from '@shared/typescript-utils'
20import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports' 20import { isVideoImportStateValid, isVideoImportTargetUrlValid } from '../../helpers/custom-validators/video-imports'
21import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos' 21import { isVideoMagnetUriValid } from '../../helpers/custom-validators/videos'
22import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants' 22import { CONSTRAINTS_FIELDS, VIDEO_IMPORT_STATES } from '../../initializers/constants'
diff --git a/server/models/video/video-job-info.ts b/server/models/video/video-job-info.ts
index 7da5128d7..7497addf1 100644
--- a/server/models/video/video-job-info.ts
+++ b/server/models/video/video-job-info.ts
@@ -1,6 +1,6 @@
1import { Op, QueryTypes, Transaction } from 'sequelize' 1import { Op, QueryTypes, Transaction } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, IsInt, Model, Table, Unique, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, IsInt, Model, Table, Unique, UpdatedAt } from 'sequelize-typescript'
3import { AttributesOnly } from '@shared/core-utils' 3import { AttributesOnly } from '@shared/typescript-utils'
4import { VideoModel } from './video' 4import { VideoModel } from './video'
5 5
6export type VideoJobInfoColumnType = 'pendingMove' | 'pendingTranscode' 6export type VideoJobInfoColumnType = 'pendingMove' | 'pendingTranscode'
@@ -99,4 +99,19 @@ export class VideoJobInfoModel extends Model<Partial<AttributesOnly<VideoJobInfo
99 99
100 return pendingMove 100 return pendingMove
101 } 101 }
102
103 static async abortAllTasks (videoUUID: string, column: VideoJobInfoColumnType): Promise<void> {
104 const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE, bind: { videoUUID } }
105
106 await VideoJobInfoModel.sequelize.query(`
107 UPDATE
108 "videoJobInfo"
109 SET
110 "${column}" = 0,
111 "updatedAt" = NOW()
112 FROM "video"
113 WHERE
114 "video"."id" = "videoJobInfo"."videoId" AND "video"."uuid" = $videoUUID
115 `, options)
116 }
102} 117}
diff --git a/server/models/video/video-live.ts b/server/models/video/video-live.ts
index 0bc8da022..e3fdcc0ba 100644
--- a/server/models/video/video-live.ts
+++ b/server/models/video/video-live.ts
@@ -1,7 +1,7 @@
1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, DefaultScope, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { AllowNull, BelongsTo, Column, CreatedAt, DataType, DefaultScope, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { WEBSERVER } from '@server/initializers/constants' 2import { WEBSERVER } from '@server/initializers/constants'
3import { MVideoLive, MVideoLiveVideo } from '@server/types/models' 3import { MVideoLive, MVideoLiveVideo } from '@server/types/models'
4import { AttributesOnly } from '@shared/core-utils' 4import { AttributesOnly } from '@shared/typescript-utils'
5import { LiveVideo, VideoState } from '@shared/models' 5import { LiveVideo, VideoState } from '@shared/models'
6import { VideoModel } from './video' 6import { VideoModel } from './video'
7import { VideoBlacklistModel } from './video-blacklist' 7import { VideoBlacklistModel } from './video-blacklist'
diff --git a/server/models/video/video-playlist-element.ts b/server/models/video/video-playlist-element.ts
index 82c832188..e20e32f8b 100644
--- a/server/models/video/video-playlist-element.ts
+++ b/server/models/video/video-playlist-element.ts
@@ -32,7 +32,7 @@ import { AccountModel } from '../account/account'
32import { getSort, throwIfNotValid } from '../utils' 32import { getSort, throwIfNotValid } from '../utils'
33import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video' 33import { ForAPIOptions, ScopeNames as VideoScopeNames, VideoModel } from './video'
34import { VideoPlaylistModel } from './video-playlist' 34import { VideoPlaylistModel } from './video-playlist'
35import { AttributesOnly } from '@shared/core-utils' 35import { AttributesOnly } from '@shared/typescript-utils'
36 36
37@Table({ 37@Table({
38 tableName: 'videoPlaylistElement', 38 tableName: 'videoPlaylistElement',
@@ -276,7 +276,7 @@ export class VideoPlaylistElementModel extends Model<Partial<AttributesOnly<Vide
276 } 276 }
277 277
278 const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`) 278 const positionQuery = Sequelize.literal(`${newPosition} + "position" - ${firstPosition}`)
279 return VideoPlaylistElementModel.update({ position: positionQuery as any }, query) 279 return VideoPlaylistElementModel.update({ position: positionQuery }, query)
280 } 280 }
281 281
282 static increasePositionOf ( 282 static increasePositionOf (
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts
index 630684a88..0d43c795e 100644
--- a/server/models/video/video-playlist.ts
+++ b/server/models/video/video-playlist.ts
@@ -17,9 +17,10 @@ import {
17 Table, 17 Table,
18 UpdatedAt 18 UpdatedAt
19} from 'sequelize-typescript' 19} from 'sequelize-typescript'
20import { buildUUID, uuidToShort } from '@server/helpers/uuid'
21import { MAccountId, MChannelId } from '@server/types/models' 20import { MAccountId, MChannelId } from '@server/types/models'
22import { AttributesOnly, buildPlaylistEmbedPath, buildPlaylistWatchPath, pick } from '@shared/core-utils' 21import { buildPlaylistEmbedPath, buildPlaylistWatchPath, pick } from '@shared/core-utils'
22import { buildUUID, uuidToShort } from '@shared/extra-utils'
23import { AttributesOnly } from '@shared/typescript-utils'
23import { ActivityIconObject } from '../../../shared/models/activitypub/objects' 24import { ActivityIconObject } from '../../../shared/models/activitypub/objects'
24import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' 25import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object'
25import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' 26import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
diff --git a/server/models/video/video-share.ts b/server/models/video/video-share.ts
index 505c305e2..f6659b992 100644
--- a/server/models/video/video-share.ts
+++ b/server/models/video/video-share.ts
@@ -1,6 +1,6 @@
1import { literal, Op, QueryTypes, Transaction } from 'sequelize' 1import { literal, Op, QueryTypes, Transaction } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
3import { AttributesOnly } from '@shared/core-utils' 3import { AttributesOnly } from '@shared/typescript-utils'
4import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 4import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
5import { CONSTRAINTS_FIELDS } from '../../initializers/constants' 5import { CONSTRAINTS_FIELDS } from '../../initializers/constants'
6import { MActorDefault } from '../../types/models' 6import { MActorDefault } from '../../types/models'
diff --git a/server/models/video/video-streaming-playlist.ts b/server/models/video/video-streaming-playlist.ts
index 4643c5452..9957ffee3 100644
--- a/server/models/video/video-streaming-playlist.ts
+++ b/server/models/video/video-streaming-playlist.ts
@@ -18,10 +18,10 @@ import {
18import { getHLSPublicFileUrl } from '@server/lib/object-storage' 18import { getHLSPublicFileUrl } from '@server/lib/object-storage'
19import { VideoFileModel } from '@server/models/video/video-file' 19import { VideoFileModel } from '@server/models/video/video-file'
20import { MStreamingPlaylist, MVideo } from '@server/types/models' 20import { MStreamingPlaylist, MVideo } from '@server/types/models'
21import { AttributesOnly } from '@shared/core-utils' 21import { sha1 } from '@shared/extra-utils'
22import { VideoStorage } from '@shared/models' 22import { VideoStorage } from '@shared/models'
23import { AttributesOnly } from '@shared/typescript-utils'
23import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' 24import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
24import { sha1 } from '../../helpers/core-utils'
25import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 25import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
26import { isArrayOf } from '../../helpers/custom-validators/misc' 26import { isArrayOf } from '../../helpers/custom-validators/misc'
27import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' 27import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos'
@@ -198,6 +198,15 @@ export class VideoStreamingPlaylistModel extends Model<Partial<AttributesOnly<Vi
198 return Object.assign(playlist, { videoId: video.id, Video: video }) 198 return Object.assign(playlist, { videoId: video.id, Video: video })
199 } 199 }
200 200
201 static doesOwnedHLSPlaylistExist (videoUUID: string) {
202 const query = `SELECT 1 FROM "videoStreamingPlaylist" ` +
203 `INNER JOIN "video" ON "video"."id" = "videoStreamingPlaylist"."videoId" ` +
204 `AND "video"."remote" IS FALSE AND "video"."uuid" = $videoUUID ` +
205 `AND "storage" = ${VideoStorage.FILE_SYSTEM} LIMIT 1`
206
207 return doesExist(query, { videoUUID })
208 }
209
201 assignP2PMediaLoaderInfoHashes (video: MVideo, files: unknown[]) { 210 assignP2PMediaLoaderInfoHashes (video: MVideo, files: unknown[]) {
202 const masterPlaylistUrl = this.getMasterPlaylistUrl(video) 211 const masterPlaylistUrl = this.getMasterPlaylistUrl(video)
203 212
diff --git a/server/models/video/video-tag.ts b/server/models/video/video-tag.ts
index 1285d375b..7e880c968 100644
--- a/server/models/video/video-tag.ts
+++ b/server/models/video/video-tag.ts
@@ -1,5 +1,5 @@
1import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript' 1import { Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { AttributesOnly } from '@shared/core-utils' 2import { AttributesOnly } from '@shared/typescript-utils'
3import { TagModel } from './tag' 3import { TagModel } from './tag'
4import { VideoModel } from './video' 4import { VideoModel } from './video'
5 5
diff --git a/server/models/video/video-view.ts b/server/models/video/video-view.ts
index b51f0f84d..d72df100f 100644
--- a/server/models/video/video-view.ts
+++ b/server/models/video/video-view.ts
@@ -1,6 +1,6 @@
1import { literal, Op } from 'sequelize' 1import { literal, Op } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table } from 'sequelize-typescript' 2import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table } from 'sequelize-typescript'
3import { AttributesOnly } from '@shared/core-utils' 3import { AttributesOnly } from '@shared/typescript-utils'
4import { VideoModel } from './video' 4import { VideoModel } from './video'
5 5
6@Table({ 6@Table({
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index 1050463d2..12b937574 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -25,7 +25,6 @@ import {
25 UpdatedAt 25 UpdatedAt
26} from 'sequelize-typescript' 26} from 'sequelize-typescript'
27import { buildNSFWFilter } from '@server/helpers/express-utils' 27import { buildNSFWFilter } from '@server/helpers/express-utils'
28import { uuidToShort } from '@server/helpers/uuid'
29import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' 28import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video'
30import { LiveManager } from '@server/lib/live/live-manager' 29import { LiveManager } from '@server/lib/live/live-manager'
31import { removeHLSObjectStorage, removeWebTorrentObjectStorage } from '@server/lib/object-storage' 30import { removeHLSObjectStorage, removeWebTorrentObjectStorage } from '@server/lib/object-storage'
@@ -33,13 +32,24 @@ import { getHLSDirectory, getHLSRedundancyDirectory } from '@server/lib/paths'
33import { VideoPathManager } from '@server/lib/video-path-manager' 32import { VideoPathManager } from '@server/lib/video-path-manager'
34import { getServerActor } from '@server/models/application/application' 33import { getServerActor } from '@server/models/application/application'
35import { ModelCache } from '@server/models/model-cache' 34import { ModelCache } from '@server/models/model-cache'
36import { AttributesOnly, buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils' 35import { buildVideoEmbedPath, buildVideoWatchPath, pick } from '@shared/core-utils'
37import { VideoFile, VideoInclude } from '@shared/models' 36import { ffprobePromise, getAudioStream, uuidToShort } from '@shared/extra-utils'
38import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' 37import {
39import { VideoObject } from '../../../shared/models/activitypub/objects' 38 ResultList,
40import { Video, VideoDetails, VideoRateType, VideoStorage } from '../../../shared/models/videos' 39 ThumbnailType,
41import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' 40 UserRight,
42import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' 41 Video,
42 VideoDetails,
43 VideoFile,
44 VideoInclude,
45 VideoObject,
46 VideoPrivacy,
47 VideoRateType,
48 VideoState,
49 VideoStorage,
50 VideoStreamingPlaylistType
51} from '@shared/models'
52import { AttributesOnly } from '@shared/typescript-utils'
43import { peertubeTruncate } from '../../helpers/core-utils' 53import { peertubeTruncate } from '../../helpers/core-utils'
44import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' 54import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
45import { exists, isBooleanValid } from '../../helpers/custom-validators/misc' 55import { exists, isBooleanValid } from '../../helpers/custom-validators/misc'
@@ -1668,12 +1678,20 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
1668 return peertubeTruncate(this.description, { length: maxLength }) 1678 return peertubeTruncate(this.description, { length: maxLength })
1669 } 1679 }
1670 1680
1671 getMaxQualityResolution () { 1681 getMaxQualityFileInfo () {
1672 const file = this.getMaxQualityFile() 1682 const file = this.getMaxQualityFile()
1673 const videoOrPlaylist = file.getVideoOrStreamingPlaylist() 1683 const videoOrPlaylist = file.getVideoOrStreamingPlaylist()
1674 1684
1675 return VideoPathManager.Instance.makeAvailableVideoFile(file.withVideoOrPlaylist(videoOrPlaylist), originalFilePath => { 1685 return VideoPathManager.Instance.makeAvailableVideoFile(file.withVideoOrPlaylist(videoOrPlaylist), async originalFilePath => {
1676 return getVideoFileResolution(originalFilePath) 1686 const probe = await ffprobePromise(originalFilePath)
1687
1688 const { audioStream } = await getAudioStream(originalFilePath, probe)
1689
1690 return {
1691 audioStream,
1692
1693 ...await getVideoFileResolution(originalFilePath, probe)
1694 }
1677 }) 1695 })
1678 } 1696 }
1679 1697