From 9d3ef9fe052ed29bd67566754cb28662bd122234 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 23 Apr 2018 14:39:52 +0200 Subject: [PATCH] Use ISO 639 for languages --- client/src/app/core/server/server.service.ts | 13 +- .../src/app/shared/video/video-edit.model.ts | 2 +- client/src/app/shared/video/video.model.ts | 2 +- package.json | 1 + .../custom-validators/activitypub/videos.ts | 13 +- server/helpers/custom-validators/videos.ts | 9 +- server/helpers/database-utils.ts | 2 +- server/initializers/constants.ts | 70 ++++---- .../migrations/0210-video-language.ts | 162 ++++++++++++++++++ server/lib/activitypub/videos.ts | 10 +- server/models/video/video.ts | 10 +- server/tests/api/check-params/videos.ts | 8 +- server/tests/api/server/follows.ts | 2 +- server/tests/api/server/handle-down.ts | 4 +- server/tests/api/videos/multiple-servers.ts | 20 +-- server/tests/api/videos/single-server.ts | 14 +- server/tests/real-world/real-world.ts | 2 +- server/tests/utils/videos/videos.ts | 12 +- server/tools/import-videos.ts | 6 +- server/tools/upload.ts | 2 +- shared/models/videos/video-create.model.ts | 2 +- shared/models/videos/video-update.model.ts | 2 +- shared/models/videos/video.model.ts | 4 +- support/doc/api/openapi.yaml | 25 +-- yarn.lock | 4 + 25 files changed, 292 insertions(+), 109 deletions(-) create mode 100644 server/initializers/migrations/0210-video-language.ts diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index a8beb242d..a71c6d0bf 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts @@ -6,6 +6,7 @@ import { ReplaySubject } from 'rxjs/ReplaySubject' import { ServerConfig } from '../../../../../shared' import { About } from '../../../../../shared/models/server/about.model' import { environment } from '../../../environments/environment' +import { VideoConstant, VideoPrivacy } from '../../../../../shared/models/videos' @Injectable() export class ServerService { @@ -57,10 +58,10 @@ export class ServerService { videoQuota: -1 } } - private videoCategories: Array<{ id: number, label: string }> = [] - private videoLicences: Array<{ id: number, label: string }> = [] - private videoLanguages: Array<{ id: number, label: string }> = [] - private videoPrivacies: Array<{ id: number, label: string }> = [] + private videoCategories: Array> = [] + private videoLicences: Array> = [] + private videoLanguages: Array> = [] + private videoPrivacies: Array> = [] constructor (private http: HttpClient) { this.loadConfigLocally() @@ -118,7 +119,7 @@ export class ServerService { private loadVideoAttributeEnum ( attributeName: 'categories' | 'licences' | 'languages' | 'privacies', - hashToPopulate: { id: number, label: string }[], + hashToPopulate: VideoConstant[], notifier: ReplaySubject, sort = false ) { @@ -127,7 +128,7 @@ export class ServerService { Object.keys(data) .forEach(dataKey => { hashToPopulate.push({ - id: parseInt(dataKey, 10), + id: dataKey, label: data[dataKey] }) }) diff --git a/client/src/app/shared/video/video-edit.model.ts b/client/src/app/shared/video/video-edit.model.ts index c1a70d1b3..39826d71e 100644 --- a/client/src/app/shared/video/video-edit.model.ts +++ b/client/src/app/shared/video/video-edit.model.ts @@ -4,7 +4,7 @@ import { VideoPrivacy } from '../../../../../shared/models/videos/video-privacy. export class VideoEdit { category: number licence: number - language: number + language: string description: string name: string tags: string[] diff --git a/client/src/app/shared/video/video.model.ts b/client/src/app/shared/video/video.model.ts index e25c172e0..a284c1688 100644 --- a/client/src/app/shared/video/video.model.ts +++ b/client/src/app/shared/video/video.model.ts @@ -13,7 +13,7 @@ export class Video implements VideoServerModel { publishedAt: Date category: VideoConstant licence: VideoConstant - language: VideoConstant + language: VideoConstant privacy: VideoConstant description: string duration: number diff --git a/package.json b/package.json index 5f7299b9d..5776f9fc6 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "express-rate-limit": "^2.11.0", "express-validator": "^5.0.0", "fluent-ffmpeg": "^2.1.0", + "iso-639-3": "^1.0.1", "js-yaml": "^3.5.4", "jsonld": "^1.0.1", "jsonld-signatures": "https://github.com/Chocobozzz/jsonld-signatures#rsa2017", diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts index d8986b2a0..8ec7df49a 100644 --- a/server/helpers/custom-validators/activitypub/videos.ts +++ b/server/helpers/custom-validators/activitypub/videos.ts @@ -49,9 +49,9 @@ function isVideoTorrentObjectValid (video: any) { isActivityPubVideoDurationValid(video.duration) && isUUIDValid(video.uuid) && setValidRemoteTags(video) && - (!video.category || isRemoteIdentifierValid(video.category)) && - (!video.licence || isRemoteIdentifierValid(video.licence)) && - (!video.language || isRemoteIdentifierValid(video.language)) && + (!video.category || isRemoteNumberIdentifierValid(video.category)) && + (!video.licence || isRemoteNumberIdentifierValid(video.licence)) && + (!video.language || isRemoteStringIdentifierValid(video.language)) && isVideoViewsValid(video.views) && isBooleanValid(video.sensitive) && isBooleanValid(video.commentsEnabled) && @@ -72,6 +72,7 @@ export { isVideoTorrentCreateActivityValid, isVideoTorrentUpdateActivityValid, isVideoTorrentDeleteActivityValid, + isRemoteStringIdentifierValid, isVideoFlagValid, isVideoTorrentObjectValid } @@ -89,10 +90,14 @@ function setValidRemoteTags (video: any) { return true } -function isRemoteIdentifierValid (data: any) { +function isRemoteNumberIdentifierValid (data: any) { return validator.isInt(data.identifier, { min: 0 }) } +function isRemoteStringIdentifierValid (data: any) { + return typeof data.identifier === 'string' +} + function isRemoteVideoContentValid (mediaType: string, content: string) { return mediaType === 'text/markdown' && isVideoTruncatedDescriptionValid(content) } diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index a46d715ba..23d2d8ac6 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts @@ -18,16 +18,17 @@ import { exists, isArray, isFileValid } from './misc' const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES -function isVideoCategoryValid (value: number) { +function isVideoCategoryValid (value: any) { return value === null || VIDEO_CATEGORIES[value] !== undefined } -function isVideoLicenceValid (value: number) { +function isVideoLicenceValid (value: any) { return value === null || VIDEO_LICENCES[value] !== undefined } -function isVideoLanguageValid (value: number) { - return value === null || VIDEO_LANGUAGES[value] !== undefined +function isVideoLanguageValid (value: any) { + return value === null || + (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE)) } function isVideoDurationValid (value: string) { diff --git a/server/helpers/database-utils.ts b/server/helpers/database-utils.ts index 47a0abfd2..b3ff42a37 100644 --- a/server/helpers/database-utils.ts +++ b/server/helpers/database-utils.ts @@ -28,7 +28,7 @@ function transactionRetryer (func: (err: any, data: T) => any) { errorFilter: err => { const willRetry = (err.name === 'SequelizeDatabaseError') - logger.debug('Maybe retrying the transaction function.', { willRetry }) + logger.debug('Maybe retrying the transaction function.', { willRetry, err }) return willRetry } }, func, (err, data) => err ? rej(err) : res(data)) diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index d1915586a..9c9c3afc0 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -13,7 +13,7 @@ let config: IConfig = require('config') // --------------------------------------------------------------------------- -const LAST_MIGRATION_VERSION = 205 +const LAST_MIGRATION_VERSION = 210 // --------------------------------------------------------------------------- @@ -196,6 +196,7 @@ const CONSTRAINTS_FIELDS = { }, VIDEOS: { NAME: { min: 3, max: 120 }, // Length + LANGUAGE: { min: 1, max: 10 }, // Length TRUNCATED_DESCRIPTION: { min: 3, max: 250 }, // Length DESCRIPTION: { min: 3, max: 10000 }, // Length SUPPORT: { min: 3, max: 300 }, // Length @@ -291,38 +292,7 @@ const VIDEO_LICENCES = { 7: 'Public Domain Dedication' } -// See https://en.wikipedia.org/wiki/List_of_languages_by_number_of_native_speakers#Nationalencyklopedin -const VIDEO_LANGUAGES = { - 1: 'English', - 2: 'Spanish', - 3: 'Mandarin', - 4: 'Hindi', - 5: 'Arabic', - 6: 'Portuguese', - 7: 'Bengali', - 8: 'Russian', - 9: 'Japanese', - 10: 'Punjabi', - 11: 'German', - 12: 'Korean', - 13: 'French', - 14: 'Italian', - 1000: 'Sign Language', - 1001: 'American Sign Language', - 1002: 'Arab Sign Language', - 1003: 'British Sign Language', - 1004: 'Brazilian Sign Language', - 1005: 'Chinese Sign Language', - 1006: 'Czech Sign Language', - 1007: 'Danish Sign Language', - 1008: 'French Sign Language', - 1009: 'German Sign Language', - 1010: 'Indo-Pakistani Sign Language', - 1011: 'Japanese Sign Language', - 1012: 'South African Sign Language', - 1013: 'Swedish Sign Language', - 1014: 'Russian Sign Language' -} +const VIDEO_LANGUAGES = buildLanguages() const VIDEO_PRIVACIES = { [VideoPrivacy.PUBLIC]: 'Public', @@ -521,6 +491,40 @@ function updateWebserverConfig () { CONFIG.WEBSERVER.HOST = sanitizeHost(CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT, REMOTE_SCHEME.HTTP) } +function buildLanguages () { + const iso639 = require('iso-639-3') + + const languages: { [ id: string ]: string } = {} + + const signLanguages = [ + 'sgn', // Sign languages (macro language) + 'ase', // American + 'sdl', // Arabian + 'bfi', // British + 'bzs', // Brazilian + 'csl', // Chinese + 'cse', // Czech + 'dsl', // Danish + 'fsl', // French + 'gsg', // German + 'pks', // Pakistan + 'jsl', // Japanese + 'sfs', // South African + 'swl', // Swedish + 'rsl' // Russian + ] + + // Only add ISO639-1 languages and some sign languages (ISO639-3) + iso639 + .filter(l => { + return (l.iso6391 !== null && l.type === 'living') || + signLanguages.indexOf(l.iso6393) !== -1 + }) + .forEach(l => languages[l.iso6391 || l.iso6393] = l.name) + + return languages +} + export function reloadConfig () { function directory () { diff --git a/server/initializers/migrations/0210-video-language.ts b/server/initializers/migrations/0210-video-language.ts new file mode 100644 index 000000000..b7ec90905 --- /dev/null +++ b/server/initializers/migrations/0210-video-language.ts @@ -0,0 +1,162 @@ +import * as Sequelize from 'sequelize' +import { CONSTRAINTS_FIELDS } from '../index' + +async function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize +}): Promise { + + { + await utils.queryInterface.renameColumn('video', 'language', 'oldLanguage') + } + + { + const data = { + type: Sequelize.STRING(CONSTRAINTS_FIELDS.VIDEOS.LANGUAGE.max), + allowNull: true, + defaultValue: null + } + await utils.queryInterface.addColumn('video', 'language', data) + } + + { + const languages = [ + { + oldLanguage: 1, + newLanguage: 'en' + }, + { + oldLanguage: 2, + newLanguage: 'es' + }, + { + oldLanguage: 3, + newLanguage: 'zh' + }, + { + oldLanguage: 4, + newLanguage: 'hi' + }, + { + oldLanguage: 5, + newLanguage: 'ar' + }, + { + oldLanguage: 6, + newLanguage: 'pt' + }, + { + oldLanguage: 7, + newLanguage: 'bn' + }, + { + oldLanguage: 8, + newLanguage: 'ru' + }, + { + oldLanguage: 9, + newLanguage: 'ja' + }, + { + oldLanguage: 10, + newLanguage: 'pa' + }, + { + oldLanguage: 11, + newLanguage: 'de' + }, + { + oldLanguage: 12, + newLanguage: 'ko' + }, + { + oldLanguage: 13, + newLanguage: 'fr' + }, + { + oldLanguage: 14, + newLanguage: 'it' + }, + { + oldLanguage: 1000, + newLanguage: 'sgn' + }, + { + oldLanguage: 1001, + newLanguage: 'ase' + }, + { + oldLanguage: 1002, + newLanguage: 'sdl' + }, + { + oldLanguage: 1003, + newLanguage: 'bfi' + }, + { + oldLanguage: 1004, + newLanguage: 'bzs' + }, + { + oldLanguage: 1005, + newLanguage: 'csl' + }, + { + oldLanguage: 1006, + newLanguage: 'cse' + }, + { + oldLanguage: 1007, + newLanguage: 'dsl' + }, + { + oldLanguage: 1008, + newLanguage: 'fsl' + }, + { + oldLanguage: 1009, + newLanguage: 'gsg' + }, + { + oldLanguage: 1010, + newLanguage: 'pks' + }, + { + oldLanguage: 1011, + newLanguage: 'jsl' + }, + { + oldLanguage: 1012, + newLanguage: 'sfs' + }, + { + oldLanguage: 1013, + newLanguage: 'swl' + }, + { + oldLanguage: 1014, + newLanguage: 'rsl' + } + ] + + for (const language of languages) { + const query = 'UPDATE "video" SET "language" = \'' + language.newLanguage + '\' WHERE "oldLanguage" = ' + language.oldLanguage + await utils.sequelize.query(query) + } + } + + { + await utils.queryInterface.removeColumn('video', 'oldLanguage') + } + +} + +function down (options) { + throw new Error('Not implemented.') +} + +export { + up, + down +} diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index ffba1570b..7cb1fe240 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts @@ -58,19 +58,19 @@ async function videoActivityObjectToDBAttributes (videoChannel: VideoChannelMode videoObject: VideoTorrentObject, to: string[] = []) { const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED - const duration = videoObject.duration.replace(/[^\d]+/, '') - let language = null + + let language: string = null if (videoObject.language) { - language = parseInt(videoObject.language.identifier, 10) + language = videoObject.language.identifier } - let category = null + let category: number = null if (videoObject.category) { category = parseInt(videoObject.category.identifier, 10) } - let licence = null + let licence: number = null if (videoObject.licence) { licence = parseInt(videoObject.licence.identifier, 10) } diff --git a/server/models/video/video.ts b/server/models/video/video.ts index aef75d206..b0fff6526 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -322,8 +322,8 @@ export class VideoModel extends Model { @AllowNull(true) @Default(null) @Is('VideoLanguage', value => throwIfNotValid(value, isVideoLanguageValid, 'language')) - @Column - language: number + @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.LANGUAGE.max)) + language: string @AllowNull(false) @Is('VideoPrivacy', value => throwIfNotValid(value, isVideoPrivacyValid, 'privacy')) @@ -877,8 +877,10 @@ export class VideoModel extends Model { return licenceLabel } - private static getLanguageLabel (id: number) { + private static getLanguageLabel (id: string) { let languageLabel = VIDEO_LANGUAGES[id] + console.log(VIDEO_LANGUAGES) + console.log(id) if (!languageLabel) languageLabel = 'Unknown' return languageLabel @@ -1083,7 +1085,7 @@ export class VideoModel extends Model { let language if (this.language) { language = { - identifier: this.language + '', + identifier: this.language, name: VideoModel.getLanguageLabel(this.language) } } diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts index 1d19daa60..da41f515b 100644 --- a/server/tests/api/check-params/videos.ts +++ b/server/tests/api/check-params/videos.ts @@ -105,7 +105,7 @@ describe('Test videos API validator', function () { name: 'my super name', category: 5, licence: 1, - language: 6, + language: 'pt', nsfw: false, commentsEnabled: true, description: 'my super description', @@ -151,7 +151,7 @@ describe('Test videos API validator', function () { }) it('Should fail with a bad language', async function () { - const fields = immutableAssign(baseCorrectParams, { language: 125 }) + const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) }) const attaches = baseCorrectAttaches await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) @@ -359,7 +359,7 @@ describe('Test videos API validator', function () { name: 'my super name', category: 5, licence: 2, - language: 6, + language: 'pt', nsfw: false, commentsEnabled: false, description: 'my super description', @@ -413,7 +413,7 @@ describe('Test videos API validator', function () { }) it('Should fail with a bad language', async function () { - const fields = immutableAssign(baseCorrectParams, { language: 125 }) + const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) }) await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields }) }) diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts index 010b488d8..9d619a7de 100644 --- a/server/tests/api/server/follows.ts +++ b/server/tests/api/server/follows.ts @@ -277,7 +277,7 @@ describe('Test follows', function () { name: 'server3-4', category: 2, licence: 6, - language: 3, + language: 'zh', nsfw: true, description: 'my super description', support: 'my super support text', diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts index f5ff3e9e5..889825936 100644 --- a/server/tests/api/server/handle-down.ts +++ b/server/tests/api/server/handle-down.ts @@ -32,7 +32,7 @@ describe('Test handle downs', function () { name: 'my super name for server 1', category: 5, licence: 4, - language: 9, + language: 'ja', nsfw: true, privacy: VideoPrivacy.PUBLIC, description: 'my super description for server 1', @@ -49,7 +49,7 @@ describe('Test handle downs', function () { name: 'my super name for server 1', category: 5, licence: 4, - language: 9, + language: 'ja', nsfw: true, description: 'my super description for server 1', support: 'my super support text for server 1', diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts index e31c7febd..2563939ec 100644 --- a/server/tests/api/videos/multiple-servers.ts +++ b/server/tests/api/videos/multiple-servers.ts @@ -89,7 +89,7 @@ describe('Test multiple servers', function () { name: 'my super name for server 1', category: 5, licence: 4, - language: 9, + language: 'ja', nsfw: true, description: 'my super description for server 1', support: 'my super support text for server 1', @@ -108,7 +108,7 @@ describe('Test multiple servers', function () { name: 'my super name for server 1', category: 5, licence: 4, - language: 9, + language: 'ja', nsfw: true, description: 'my super description for server 1', support: 'my super support text for server 1', @@ -159,7 +159,7 @@ describe('Test multiple servers', function () { name: 'my super name for server 2', category: 4, licence: 3, - language: 11, + language: 'de', nsfw: true, description: 'my super description for server 2', support: 'my super support text for server 2', @@ -180,7 +180,7 @@ describe('Test multiple servers', function () { name: 'my super name for server 2', category: 4, licence: 3, - language: 11, + language: 'de', nsfw: true, description: 'my super description for server 2', support: 'my super support text for server 2', @@ -238,7 +238,7 @@ describe('Test multiple servers', function () { name: 'my super name for server 3', category: 6, licence: 5, - language: 11, + language: 'de', nsfw: true, description: 'my super description for server 3', support: 'my super support text for server 3', @@ -251,7 +251,7 @@ describe('Test multiple servers', function () { name: 'my super name for server 3-2', category: 7, licence: 6, - language: 12, + language: 'ko', nsfw: false, description: 'my super description for server 3-2', support: 'my super support text for server 3-2', @@ -286,7 +286,7 @@ describe('Test multiple servers', function () { name: 'my super name for server 3', category: 6, licence: 5, - language: 11, + language: 'de', nsfw: true, description: 'my super description for server 3', support: 'my super support text for server 3', @@ -318,7 +318,7 @@ describe('Test multiple servers', function () { name: 'my super name for server 3-2', category: 7, licence: 6, - language: 12, + language: 'ko', nsfw: false, description: 'my super description for server 3-2', support: 'my super support text for server 3-2', @@ -597,7 +597,7 @@ describe('Test multiple servers', function () { name: 'my super video updated', category: 10, licence: 7, - language: 13, + language: 'fr', nsfw: true, description: 'my super description updated', support: 'my super support text updated', @@ -626,7 +626,7 @@ describe('Test multiple servers', function () { name: 'my super video updated', category: 10, licence: 7, - language: 13, + language: 'fr', nsfw: true, description: 'my super description updated', support: 'my super support text updated', diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts index 7c4bdf8bc..5e163e9df 100644 --- a/server/tests/api/videos/single-server.ts +++ b/server/tests/api/videos/single-server.ts @@ -23,7 +23,7 @@ describe('Test a single server', function () { name: 'my super name', category: 2, licence: 6, - language: 3, + language: 'zh', nsfw: true, description: 'my super description', support: 'my super support text', @@ -54,7 +54,7 @@ describe('Test a single server', function () { name: 'my super video updated', category: 4, licence: 2, - language: 5, + language: 'ar', nsfw: false, description: 'my super description updated', support: 'my super support text updated', @@ -115,7 +115,7 @@ describe('Test a single server', function () { const languages = res.body expect(Object.keys(languages)).to.have.length.above(5) - expect(languages[3]).to.equal('Mandarin') + expect(languages['ru']).to.equal('Russian') }) it('Should list video privacies', async function () { @@ -222,8 +222,8 @@ describe('Test a single server', function () { // expect(video.categoryLabel).to.equal('Films') // expect(video.licence).to.equal(6) // expect(video.licenceLabel).to.equal('Attribution - Non Commercial - No Derivatives') - // expect(video.language).to.equal(3) - // expect(video.languageLabel).to.equal('Mandarin') + // expect(video.language).to.equal('zh') + // expect(video.languageLabel).to.equal('Chinese') // expect(video.nsfw).to.be.ok // expect(video.description).to.equal('my super description') // expect(video.account.name).to.equal('root') @@ -292,7 +292,7 @@ describe('Test a single server', function () { description: video + ' description', category: 2, licence: 1, - language: 1, + language: 'en', nsfw: true, tags: [ 'tag1', 'tag2', 'tag3' ], fixture: video @@ -458,7 +458,7 @@ describe('Test a single server', function () { name: 'my super video updated', category: 4, licence: 2, - language: 5, + language: 'ar', nsfw: false, description: 'my super description updated', commentsEnabled: false, diff --git a/server/tests/real-world/real-world.ts b/server/tests/real-world/real-world.ts index ae02ef64d..b7375f778 100644 --- a/server/tests/real-world/real-world.ts +++ b/server/tests/real-world/real-world.ts @@ -182,7 +182,7 @@ function upload (servers: ServerInfo[], numServer: number) { category: 4, nsfw: false, licence: 2, - language: 1, + language: 'en', description: Date.now() + ' description', tags: [ Date.now().toString().substring(0, 5) + 't1', Date.now().toString().substring(0, 5) + 't2' ], fixture: 'video_short1.webm' diff --git a/server/tests/utils/videos/videos.ts b/server/tests/utils/videos/videos.ts index 5e186147e..943c85cc7 100644 --- a/server/tests/utils/videos/videos.ts +++ b/server/tests/utils/videos/videos.ts @@ -24,7 +24,7 @@ type VideoAttributes = { name?: string category?: number licence?: number - language?: number + language?: string nsfw?: boolean commentsEnabled?: boolean description?: string @@ -284,7 +284,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg name: 'my super video', category: 5, licence: 4, - language: 3, + language: 'zh', channelId: defaultChannelId, nsfw: true, description: 'my super description', @@ -403,7 +403,7 @@ async function completeVideoCheck ( name: string category: number licence: number - language: number + language: string nsfw: boolean commentsEnabled: boolean description: string @@ -437,11 +437,11 @@ async function completeVideoCheck ( expect(video.name).to.equal(attributes.name) expect(video.category.id).to.equal(attributes.category) - expect(video.category.label).to.equal(VIDEO_CATEGORIES[attributes.category] || 'Misc') + expect(video.category.label).to.equal(attributes.category !== null ? VIDEO_CATEGORIES[attributes.category] : 'Misc') expect(video.licence.id).to.equal(attributes.licence) - expect(video.licence.label).to.equal(VIDEO_LICENCES[attributes.licence] || 'Unknown') + expect(video.licence.label).to.equal(attributes.licence !== null ? VIDEO_LICENCES[attributes.licence] : 'Unknown') expect(video.language.id).to.equal(attributes.language) - expect(video.language.label).to.equal(VIDEO_LANGUAGES[attributes.language] || 'Unknown') + expect(video.language.label).to.equal(attributes.language !== null ? VIDEO_LANGUAGES[attributes.language] : 'Unknown') expect(video.privacy.id).to.deep.equal(attributes.privacy) expect(video.privacy.label).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy]) expect(video.nsfw).to.equal(attributes.nsfw) diff --git a/server/tools/import-videos.ts b/server/tools/import-videos.ts index e6272a433..f773208ab 100644 --- a/server/tools/import-videos.ts +++ b/server/tools/import-videos.ts @@ -16,7 +16,7 @@ program .option('-U, --username ', 'Username') .option('-p, --password ', 'Password') .option('-t, --target-url ', 'Video target URL') - .option('-l, --language ', 'Language code') + .option('-l, --language ', 'Language ISO 639 code (fr or en...)') .option('-v, --verbose', 'Verbose mode') .parse(process.argv) @@ -82,7 +82,7 @@ async function run () { }) } -function processVideo (info: any, languageCode: number) { +function processVideo (info: any, languageCode: string) { return new Promise(async res => { if (program['verbose']) console.log('Fetching object.', info) @@ -121,7 +121,7 @@ function processVideo (info: any, languageCode: number) { }) } -async function uploadVideoOnPeerTube (videoInfo: any, videoPath: string, language?: number) { +async function uploadVideoOnPeerTube (videoInfo: any, videoPath: string, language?: string) { const category = await getCategory(videoInfo.categories) const licence = getLicence(videoInfo.license) let tags = [] diff --git a/server/tools/upload.ts b/server/tools/upload.ts index 765e9618a..177d849f3 100644 --- a/server/tools/upload.ts +++ b/server/tools/upload.ts @@ -18,7 +18,7 @@ program .option('-c, --category ', 'Category number') .option('-m, --comments-enabled', 'Enable comments') .option('-l, --licence ', 'Licence number') - .option('-L, --language ', 'Language number') + .option('-L, --language ', 'Language ISO 639 code (fr or en...)') .option('-d, --video-description ', 'Video description') .option('-t, --tags ', 'Video tags', list) .option('-b, --thumbnail ', 'Thumbnail path') diff --git a/shared/models/videos/video-create.model.ts b/shared/models/videos/video-create.model.ts index 567a4c79a..562bc1bf2 100644 --- a/shared/models/videos/video-create.model.ts +++ b/shared/models/videos/video-create.model.ts @@ -3,7 +3,7 @@ import { VideoPrivacy } from './video-privacy.enum' export interface VideoCreate { category?: number licence?: number - language?: number + language?: string description?: string support?: string channelId: number diff --git a/shared/models/videos/video-update.model.ts b/shared/models/videos/video-update.model.ts index b281ace9a..3a205bb83 100644 --- a/shared/models/videos/video-update.model.ts +++ b/shared/models/videos/video-update.model.ts @@ -4,7 +4,7 @@ export interface VideoUpdate { name?: string category?: number licence?: number - language?: number + language?: string description?: string support?: string privacy?: VideoPrivacy diff --git a/shared/models/videos/video.model.ts b/shared/models/videos/video.model.ts index 70132c050..259826689 100644 --- a/shared/models/videos/video.model.ts +++ b/shared/models/videos/video.model.ts @@ -5,7 +5,7 @@ import { VideoChannel } from './video-channel.model' import { VideoPrivacy } from './video-privacy.enum' export interface VideoConstant { - id: number + id: T label: string } @@ -25,7 +25,7 @@ export interface Video { publishedAt: Date | string category: VideoConstant licence: VideoConstant - language: VideoConstant + language: VideoConstant privacy: VideoConstant description: string duration: number diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml index 0729ac8ec..10f60175d 100644 --- a/support/doc/api/openapi.yaml +++ b/support/doc/api/openapi.yaml @@ -82,9 +82,9 @@ paths: get: tags: - Feeds - consumes: - - application/json produces: + - application/atom+xml + - application/rss+xml - application/json parameters: - name: format @@ -107,9 +107,6 @@ paths: responses: '200': description: successful operation - content: - application/json: - application/xml: /jobs: get: security: @@ -660,7 +657,7 @@ paths: description: 'Video licence' - name: language in: formData - type: number + type: string description: 'Video language' - name: description in: formData @@ -804,7 +801,7 @@ paths: description: 'Video licence' - name: language in: formData - type: number + type: string description: 'Video language' - name: description in: formData @@ -1245,12 +1242,18 @@ paths: '204': description: successful operation definitions: - VideoConstant: + VideoConstantNumber: properties: id: type: number label: type: string + VideoConstantString: + properties: + id: + type: string + label: + type: string VideoPrivacy: type: string enum: [Public, Unlisted, Private] @@ -1267,11 +1270,11 @@ definitions: updatedAt: type: string category: - $ref: "#/definitions/VideoConstant" + $ref: "#/definitions/VideoConstantNumber" licence: - $ref: "#/definitions/VideoConstant" + $ref: "#/definitions/VideoConstantNumber" language: - $ref: "#/definitions/VideoConstant" + $ref: "#/definitions/VideoConstantString" privacy: $ref: "#/definitions/VideoPrivacy" description: diff --git a/yarn.lock b/yarn.lock index 73488620a..9a43aa182 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3239,6 +3239,10 @@ isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" +iso-639-3@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/iso-639-3/-/iso-639-3-1.0.1.tgz#ebdf945e1e691bc8225e41e4520fe6a51083e647" + isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" -- 2.25.1