1 import { merge } from 'lodash'
2 import { About, CustomConfig, HttpStatusCode, ServerConfig } from '@shared/models'
3 import { DeepPartial } from '@shared/typescript-utils'
4 import { AbstractCommand, OverrideCommandOptions } from '../shared/abstract-command'
6 export class ConfigCommand extends AbstractCommand {
8 static getCustomConfigResolutions (enabled: boolean, with0p = false) {
10 '0p': enabled && with0p,
22 // ---------------------------------------------------------------------------
24 static getEmailOverrideConfig (emailPort: number) {
27 hostname: '127.0.0.1',
33 // ---------------------------------------------------------------------------
35 enableSignup (requiresApproval: boolean, limit = -1) {
36 return this.updateExistingSubConfig({
47 // ---------------------------------------------------------------------------
50 return this.setImportsEnabled(false)
54 return this.setImportsEnabled(true)
57 private setImportsEnabled (enabled: boolean) {
58 return this.updateExistingSubConfig({
75 // ---------------------------------------------------------------------------
77 enableChannelSync () {
78 return this.setChannelSyncEnabled(true)
81 disableChannelSync () {
82 return this.setChannelSyncEnabled(false)
85 private setChannelSyncEnabled (enabled: boolean) {
86 return this.updateExistingSubConfig({
89 videoChannelSynchronization: {
97 // ---------------------------------------------------------------------------
99 enableLive (options: {
100 allowReplay?: boolean
101 transcoding?: boolean
102 resolutions?: 'min' | 'max' // Default max
104 const { allowReplay, transcoding, resolutions = 'max' } = options
106 return this.updateExistingSubConfig({
110 allowReplay: allowReplay ?? true,
112 enabled: transcoding ?? true,
113 resolutions: ConfigCommand.getCustomConfigResolutions(resolutions === 'max')
120 disableTranscoding () {
121 return this.updateExistingSubConfig({
133 // TODO: convert args to object
134 enableTranscoding (webtorrent = true, hls = true, with0p = false) {
135 return this.updateExistingSubConfig({
140 allowAudioFiles: true,
141 allowAdditionalExtensions: true,
143 resolutions: ConfigCommand.getCustomConfigResolutions(true, with0p),
156 // TODO: convert args to object
157 enableMinimumTranscoding (webtorrent = true, hls = true) {
158 return this.updateExistingSubConfig({
163 ...ConfigCommand.getCustomConfigResolutions(false),
179 enableRemoteTranscoding () {
180 return this.updateExistingSubConfig({
198 enableRemoteStudio () {
199 return this.updateExistingSubConfig({
210 // ---------------------------------------------------------------------------
213 return this.updateExistingSubConfig({
222 // ---------------------------------------------------------------------------
224 getConfig (options: OverrideCommandOptions = {}) {
225 const path = '/api/v1/config'
227 return this.getRequestBody<ServerConfig>({
231 implicitToken: false,
232 defaultExpectedStatus: HttpStatusCode.OK_200
236 async getIndexHTMLConfig (options: OverrideCommandOptions = {}) {
237 const text = await this.getRequestText({
241 implicitToken: false,
242 defaultExpectedStatus: HttpStatusCode.OK_200
245 const match = text.match('<script type="application/javascript">window.PeerTubeServerConfig = (".+?")</script>')
247 // We parse the string twice, first to extract the string and then to extract the JSON
248 return JSON.parse(JSON.parse(match[1])) as ServerConfig
251 getAbout (options: OverrideCommandOptions = {}) {
252 const path = '/api/v1/config/about'
254 return this.getRequestBody<About>({
258 implicitToken: false,
259 defaultExpectedStatus: HttpStatusCode.OK_200
263 getCustomConfig (options: OverrideCommandOptions = {}) {
264 const path = '/api/v1/config/custom'
266 return this.getRequestBody<CustomConfig>({
271 defaultExpectedStatus: HttpStatusCode.OK_200
275 updateCustomConfig (options: OverrideCommandOptions & {
276 newCustomConfig: CustomConfig
278 const path = '/api/v1/config/custom'
280 return this.putBodyRequest({
284 fields: options.newCustomConfig,
286 defaultExpectedStatus: HttpStatusCode.OK_200
290 deleteCustomConfig (options: OverrideCommandOptions = {}) {
291 const path = '/api/v1/config/custom'
293 return this.deleteRequest({
298 defaultExpectedStatus: HttpStatusCode.OK_200
302 async updateExistingSubConfig (options: OverrideCommandOptions & {
303 newConfig: DeepPartial<CustomConfig>
305 const existing = await this.getCustomConfig({ ...options, expectedStatus: HttpStatusCode.OK_200 })
307 return this.updateCustomConfig({ ...options, newCustomConfig: merge({}, existing, options.newConfig) })
310 updateCustomSubConfig (options: OverrideCommandOptions & {
311 newConfig: DeepPartial<CustomConfig>
313 const newCustomConfig: CustomConfig = {
315 name: 'PeerTube updated',
316 shortDescription: 'my short description',
317 description: 'my super description',
318 terms: 'my super terms',
319 codeOfConduct: 'my super coc',
321 creationReason: 'my super creation reason',
322 moderationInformation: 'my super moderation information',
323 administrator: 'Kuja',
324 maintenanceLifetime: 'forever',
325 businessModel: 'my super business model',
326 hardwareInformation: '2vCore 3GB RAM',
328 languages: [ 'en', 'es' ],
329 categories: [ 1, 2 ],
332 defaultNSFWPolicy: 'blur',
334 defaultClientRoute: '/videos/recently-added',
337 javascript: 'alert("coucou")',
338 css: 'body { background-color: red; }'
346 username: '@MySuperUsername',
353 preferAuthorDisplayName: false
358 redirectOnSingleExternalAuth: false
376 requiresApproval: true,
377 requiresEmailVerification: false,
381 email: 'superadmin1@example.com'
393 videoQuotaDaily: 318742
403 allowAdditionalExtensions: true,
404 allowAudioFiles: true,
419 alwaysTranscodeOriginalResolution: true,
434 maxInstanceLives: -1,
453 alwaysTranscodeOriginalResolution: true
472 videoChannelSynchronization: {
480 enabled: [ 'hot', 'most-viewed', 'most-liked' ],
495 manualApproval: false
504 indexUrl: 'https://instances.joinpeertube.org/api/v1/instances/hosts',
522 url: 'https://search.joinpeertube.org',
523 disableLocalSearch: true,
524 isDefaultSearch: true
529 merge(newCustomConfig, options.newConfig)
531 return this.updateCustomConfig({ ...options, newCustomConfig })