diff options
Diffstat (limited to 'server/models')
-rw-r--r-- | server/models/account/user.ts | 14 | ||||
-rw-r--r-- | server/models/video/video.ts | 52 |
2 files changed, 42 insertions, 24 deletions
diff --git a/server/models/account/user.ts b/server/models/account/user.ts index 8afd246b2..56af2f30a 100644 --- a/server/models/account/user.ts +++ b/server/models/account/user.ts | |||
@@ -21,7 +21,7 @@ import { hasUserRight, USER_ROLE_LABELS, UserRight } from '../../../shared' | |||
21 | import { User, UserRole } from '../../../shared/models/users' | 21 | import { User, UserRole } from '../../../shared/models/users' |
22 | import { | 22 | import { |
23 | isUserAutoPlayVideoValid, | 23 | isUserAutoPlayVideoValid, |
24 | isUserDisplayNSFWValid, | 24 | isUserNSFWPolicyValid, |
25 | isUserPasswordValid, | 25 | isUserPasswordValid, |
26 | isUserRoleValid, | 26 | isUserRoleValid, |
27 | isUserUsernameValid, | 27 | isUserUsernameValid, |
@@ -32,6 +32,9 @@ import { OAuthTokenModel } from '../oauth/oauth-token' | |||
32 | import { getSort, throwIfNotValid } from '../utils' | 32 | import { getSort, throwIfNotValid } from '../utils' |
33 | import { VideoChannelModel } from '../video/video-channel' | 33 | import { VideoChannelModel } from '../video/video-channel' |
34 | import { AccountModel } from './account' | 34 | import { AccountModel } from './account' |
35 | import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type' | ||
36 | import { values } from 'lodash' | ||
37 | import { NSFW_POLICY_TYPES } from '../../initializers' | ||
35 | 38 | ||
36 | @DefaultScope({ | 39 | @DefaultScope({ |
37 | include: [ | 40 | include: [ |
@@ -83,10 +86,9 @@ export class UserModel extends Model<UserModel> { | |||
83 | email: string | 86 | email: string |
84 | 87 | ||
85 | @AllowNull(false) | 88 | @AllowNull(false) |
86 | @Default(false) | 89 | @Is('UserNSFWPolicy', value => throwIfNotValid(value, isUserNSFWPolicyValid, 'NSFW policy')) |
87 | @Is('UserDisplayNSFW', value => throwIfNotValid(value, isUserDisplayNSFWValid, 'display NSFW boolean')) | 90 | @Column(DataType.ENUM(values(NSFW_POLICY_TYPES))) |
88 | @Column | 91 | nsfwPolicy: NSFWPolicyType |
89 | displayNSFW: boolean | ||
90 | 92 | ||
91 | @AllowNull(false) | 93 | @AllowNull(false) |
92 | @Default(true) | 94 | @Default(true) |
@@ -265,7 +267,7 @@ export class UserModel extends Model<UserModel> { | |||
265 | id: this.id, | 267 | id: this.id, |
266 | username: this.username, | 268 | username: this.username, |
267 | email: this.email, | 269 | email: this.email, |
268 | displayNSFW: this.displayNSFW, | 270 | nsfwPolicy: this.nsfwPolicy, |
269 | autoPlayVideo: this.autoPlayVideo, | 271 | autoPlayVideo: this.autoPlayVideo, |
270 | role: this.role, | 272 | role: this.role, |
271 | roleLabel: USER_ROLE_LABELS[ this.role ], | 273 | roleLabel: USER_ROLE_LABELS[ this.role ], |
diff --git a/server/models/video/video.ts b/server/models/video/video.ts index a7923b477..aef75d206 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts | |||
@@ -95,7 +95,7 @@ enum ScopeNames { | |||
95 | } | 95 | } |
96 | 96 | ||
97 | @Scopes({ | 97 | @Scopes({ |
98 | [ScopeNames.AVAILABLE_FOR_LIST]: (actorId: number, filter?: VideoFilter, withFiles?: boolean) => { | 98 | [ScopeNames.AVAILABLE_FOR_LIST]: (actorId: number, hideNSFW: boolean, filter?: VideoFilter, withFiles?: boolean) => { |
99 | const query: IFindOptions<VideoModel> = { | 99 | const query: IFindOptions<VideoModel> = { |
100 | where: { | 100 | where: { |
101 | id: { | 101 | id: { |
@@ -161,6 +161,11 @@ enum ScopeNames { | |||
161 | }) | 161 | }) |
162 | } | 162 | } |
163 | 163 | ||
164 | // Hide nsfw videos? | ||
165 | if (hideNSFW === true) { | ||
166 | query.where['nsfw'] = false | ||
167 | } | ||
168 | |||
164 | return query | 169 | return query |
165 | }, | 170 | }, |
166 | [ScopeNames.WITH_ACCOUNT_DETAILS]: { | 171 | [ScopeNames.WITH_ACCOUNT_DETAILS]: { |
@@ -640,7 +645,7 @@ export class VideoModel extends Model<VideoModel> { | |||
640 | }) | 645 | }) |
641 | } | 646 | } |
642 | 647 | ||
643 | static listAccountVideosForApi (accountId: number, start: number, count: number, sort: string, withFiles = false) { | 648 | static listAccountVideosForApi (accountId: number, start: number, count: number, sort: string, hideNSFW: boolean, withFiles = false) { |
644 | const query: IFindOptions<VideoModel> = { | 649 | const query: IFindOptions<VideoModel> = { |
645 | offset: start, | 650 | offset: start, |
646 | limit: count, | 651 | limit: count, |
@@ -669,6 +674,12 @@ export class VideoModel extends Model<VideoModel> { | |||
669 | }) | 674 | }) |
670 | } | 675 | } |
671 | 676 | ||
677 | if (hideNSFW === true) { | ||
678 | query.where = { | ||
679 | nsfw: false | ||
680 | } | ||
681 | } | ||
682 | |||
672 | return VideoModel.findAndCountAll(query).then(({ rows, count }) => { | 683 | return VideoModel.findAndCountAll(query).then(({ rows, count }) => { |
673 | return { | 684 | return { |
674 | data: rows, | 685 | data: rows, |
@@ -677,7 +688,7 @@ export class VideoModel extends Model<VideoModel> { | |||
677 | }) | 688 | }) |
678 | } | 689 | } |
679 | 690 | ||
680 | static async listForApi (start: number, count: number, sort: string, filter?: VideoFilter, withFiles = false) { | 691 | static async listForApi (start: number, count: number, sort: string, hideNSFW: boolean, filter?: VideoFilter, withFiles = false) { |
681 | const query = { | 692 | const query = { |
682 | offset: start, | 693 | offset: start, |
683 | limit: count, | 694 | limit: count, |
@@ -685,8 +696,7 @@ export class VideoModel extends Model<VideoModel> { | |||
685 | } | 696 | } |
686 | 697 | ||
687 | const serverActor = await getServerActor() | 698 | const serverActor = await getServerActor() |
688 | 699 | return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW, filter, withFiles ] }) | |
689 | return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, filter, withFiles ] }) | ||
690 | .findAndCountAll(query) | 700 | .findAndCountAll(query) |
691 | .then(({ rows, count }) => { | 701 | .then(({ rows, count }) => { |
692 | return { | 702 | return { |
@@ -696,7 +706,7 @@ export class VideoModel extends Model<VideoModel> { | |||
696 | }) | 706 | }) |
697 | } | 707 | } |
698 | 708 | ||
699 | static async searchAndPopulateAccountAndServer (value: string, start: number, count: number, sort: string) { | 709 | static async searchAndPopulateAccountAndServer (value: string, start: number, count: number, sort: string, hideNSFW: boolean) { |
700 | const query: IFindOptions<VideoModel> = { | 710 | const query: IFindOptions<VideoModel> = { |
701 | offset: start, | 711 | offset: start, |
702 | limit: count, | 712 | limit: count, |
@@ -724,7 +734,7 @@ export class VideoModel extends Model<VideoModel> { | |||
724 | 734 | ||
725 | const serverActor = await getServerActor() | 735 | const serverActor = await getServerActor() |
726 | 736 | ||
727 | return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id ] }) | 737 | return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW ] }) |
728 | .findAndCountAll(query) | 738 | .findAndCountAll(query) |
729 | .then(({ rows, count }) => { | 739 | .then(({ rows, count }) => { |
730 | return { | 740 | return { |
@@ -874,6 +884,13 @@ export class VideoModel extends Model<VideoModel> { | |||
874 | return languageLabel | 884 | return languageLabel |
875 | } | 885 | } |
876 | 886 | ||
887 | private static getPrivacyLabel (id: number) { | ||
888 | let privacyLabel = VIDEO_PRIVACIES[id] | ||
889 | if (!privacyLabel) privacyLabel = 'Unknown' | ||
890 | |||
891 | return privacyLabel | ||
892 | } | ||
893 | |||
877 | getOriginalFile () { | 894 | getOriginalFile () { |
878 | if (Array.isArray(this.VideoFiles) === false) return undefined | 895 | if (Array.isArray(this.VideoFiles) === false) return undefined |
879 | 896 | ||
@@ -927,8 +944,11 @@ export class VideoModel extends Model<VideoModel> { | |||
927 | return join(CONFIG.STORAGE.VIDEOS_DIR, this.getVideoFilename(videoFile)) | 944 | return join(CONFIG.STORAGE.VIDEOS_DIR, this.getVideoFilename(videoFile)) |
928 | } | 945 | } |
929 | 946 | ||
930 | createTorrentAndSetInfoHash = async function (videoFile: VideoFileModel) { | 947 | async createTorrentAndSetInfoHash (videoFile: VideoFileModel) { |
931 | const options = { | 948 | const options = { |
949 | // Keep the extname, it's used by the client to stream the file inside a web browser | ||
950 | name: `${this.name} ${videoFile.resolution}p${videoFile.extname}`, | ||
951 | createdBy: 'PeerTube', | ||
932 | announceList: [ | 952 | announceList: [ |
933 | [ CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT + '/tracker/socket' ], | 953 | [ CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT + '/tracker/socket' ], |
934 | [ CONFIG.WEBSERVER.URL + '/tracker/announce' ] | 954 | [ CONFIG.WEBSERVER.URL + '/tracker/announce' ] |
@@ -980,6 +1000,10 @@ export class VideoModel extends Model<VideoModel> { | |||
980 | id: this.language, | 1000 | id: this.language, |
981 | label: VideoModel.getLanguageLabel(this.language) | 1001 | label: VideoModel.getLanguageLabel(this.language) |
982 | }, | 1002 | }, |
1003 | privacy: { | ||
1004 | id: this.privacy, | ||
1005 | label: VideoModel.getPrivacyLabel(this.privacy) | ||
1006 | }, | ||
983 | nsfw: this.nsfw, | 1007 | nsfw: this.nsfw, |
984 | description: this.getTruncatedDescription(), | 1008 | description: this.getTruncatedDescription(), |
985 | isLocal: this.isOwned(), | 1009 | isLocal: this.isOwned(), |
@@ -1006,15 +1030,7 @@ export class VideoModel extends Model<VideoModel> { | |||
1006 | toFormattedDetailsJSON (): VideoDetails { | 1030 | toFormattedDetailsJSON (): VideoDetails { |
1007 | const formattedJson = this.toFormattedJSON() | 1031 | const formattedJson = this.toFormattedJSON() |
1008 | 1032 | ||
1009 | // Maybe our server is not up to date and there are new privacy settings since our version | ||
1010 | let privacyLabel = VIDEO_PRIVACIES[this.privacy] | ||
1011 | if (!privacyLabel) privacyLabel = 'Unknown' | ||
1012 | |||
1013 | const detailsJson = { | 1033 | const detailsJson = { |
1014 | privacy: { | ||
1015 | id: this.privacy, | ||
1016 | label: privacyLabel | ||
1017 | }, | ||
1018 | support: this.support, | 1034 | support: this.support, |
1019 | descriptionPath: this.getDescriptionPath(), | 1035 | descriptionPath: this.getDescriptionPath(), |
1020 | channel: this.VideoChannel.toFormattedJSON(), | 1036 | channel: this.VideoChannel.toFormattedJSON(), |
@@ -1227,7 +1243,7 @@ export class VideoModel extends Model<VideoModel> { | |||
1227 | return peertubeTruncate(this.description, maxLength) | 1243 | return peertubeTruncate(this.description, maxLength) |
1228 | } | 1244 | } |
1229 | 1245 | ||
1230 | optimizeOriginalVideofile = async function () { | 1246 | async optimizeOriginalVideofile () { |
1231 | const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR | 1247 | const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR |
1232 | const newExtname = '.mp4' | 1248 | const newExtname = '.mp4' |
1233 | const inputVideoFile = this.getOriginalFile() | 1249 | const inputVideoFile = this.getOriginalFile() |
@@ -1264,7 +1280,7 @@ export class VideoModel extends Model<VideoModel> { | |||
1264 | } | 1280 | } |
1265 | } | 1281 | } |
1266 | 1282 | ||
1267 | transcodeOriginalVideofile = async function (resolution: VideoResolution, isPortraitMode: boolean) { | 1283 | async transcodeOriginalVideofile (resolution: VideoResolution, isPortraitMode: boolean) { |
1268 | const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR | 1284 | const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR |
1269 | const extname = '.mp4' | 1285 | const extname = '.mp4' |
1270 | 1286 | ||