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 // ---------------------------------------------------------------------------
201 return this.updateExistingSubConfig({
210 // ---------------------------------------------------------------------------
212 getConfig (options: OverrideCommandOptions = {}) {
213 const path = '/api/v1/config'
215 return this.getRequestBody<ServerConfig>({
219 implicitToken: false,
220 defaultExpectedStatus: HttpStatusCode.OK_200
224 async getIndexHTMLConfig (options: OverrideCommandOptions = {}) {
225 const text = await this.getRequestText({
229 implicitToken: false,
230 defaultExpectedStatus: HttpStatusCode.OK_200
233 const match = text.match('<script type="application/javascript">window.PeerTubeServerConfig = (".+?")</script>')
235 // We parse the string twice, first to extract the string and then to extract the JSON
236 return JSON.parse(JSON.parse(match[1])) as ServerConfig
239 getAbout (options: OverrideCommandOptions = {}) {
240 const path = '/api/v1/config/about'
242 return this.getRequestBody<About>({
246 implicitToken: false,
247 defaultExpectedStatus: HttpStatusCode.OK_200
251 getCustomConfig (options: OverrideCommandOptions = {}) {
252 const path = '/api/v1/config/custom'
254 return this.getRequestBody<CustomConfig>({
259 defaultExpectedStatus: HttpStatusCode.OK_200
263 updateCustomConfig (options: OverrideCommandOptions & {
264 newCustomConfig: CustomConfig
266 const path = '/api/v1/config/custom'
268 return this.putBodyRequest({
272 fields: options.newCustomConfig,
274 defaultExpectedStatus: HttpStatusCode.OK_200
278 deleteCustomConfig (options: OverrideCommandOptions = {}) {
279 const path = '/api/v1/config/custom'
281 return this.deleteRequest({
286 defaultExpectedStatus: HttpStatusCode.OK_200
290 async updateExistingSubConfig (options: OverrideCommandOptions & {
291 newConfig: DeepPartial<CustomConfig>
293 const existing = await this.getCustomConfig({ ...options, expectedStatus: HttpStatusCode.OK_200 })
295 return this.updateCustomConfig({ ...options, newCustomConfig: merge({}, existing, options.newConfig) })
298 updateCustomSubConfig (options: OverrideCommandOptions & {
299 newConfig: DeepPartial<CustomConfig>
301 const newCustomConfig: CustomConfig = {
303 name: 'PeerTube updated',
304 shortDescription: 'my short description',
305 description: 'my super description',
306 terms: 'my super terms',
307 codeOfConduct: 'my super coc',
309 creationReason: 'my super creation reason',
310 moderationInformation: 'my super moderation information',
311 administrator: 'Kuja',
312 maintenanceLifetime: 'forever',
313 businessModel: 'my super business model',
314 hardwareInformation: '2vCore 3GB RAM',
316 languages: [ 'en', 'es' ],
317 categories: [ 1, 2 ],
320 defaultNSFWPolicy: 'blur',
322 defaultClientRoute: '/videos/recently-added',
325 javascript: 'alert("coucou")',
326 css: 'body { background-color: red; }'
334 username: '@MySuperUsername',
341 preferAuthorDisplayName: false
346 redirectOnSingleExternalAuth: false
364 requiresApproval: true,
365 requiresEmailVerification: false,
369 email: 'superadmin1@example.com'
381 videoQuotaDaily: 318742
391 allowAdditionalExtensions: true,
392 allowAudioFiles: true,
407 alwaysTranscodeOriginalResolution: true,
422 maxInstanceLives: -1,
441 alwaysTranscodeOriginalResolution: true
457 videoChannelSynchronization: {
465 enabled: [ 'hot', 'most-viewed', 'most-liked' ],
480 manualApproval: false
489 indexUrl: 'https://instances.joinpeertube.org/api/v1/instances/hosts',
507 url: 'https://search.joinpeertube.org',
508 disableLocalSearch: true,
509 isDefaultSearch: true
514 merge(newCustomConfig, options.newConfig)
516 return this.updateCustomConfig({ ...options, newCustomConfig })