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) {
22 return this.setImportsEnabled(false)
26 return this.setImportsEnabled(true)
29 private setImportsEnabled (enabled: boolean) {
30 return this.updateExistingSubConfig({
47 private setChannelSyncEnabled (enabled: boolean) {
48 return this.updateExistingSubConfig({
51 videoChannelSynchronization: {
59 enableChannelSync () {
60 return this.setChannelSyncEnabled(true)
63 disableChannelSync () {
64 return this.setChannelSyncEnabled(false)
67 enableLive (options: {
70 resolutions?: 'min' | 'max' // Default max
72 const { allowReplay, transcoding, resolutions = 'max' } = options
74 return this.updateExistingSubConfig({
78 allowReplay: allowReplay ?? true,
80 enabled: transcoding ?? true,
81 resolutions: ConfigCommand.getCustomConfigResolutions(resolutions === 'max')
88 disableTranscoding () {
89 return this.updateExistingSubConfig({
101 enableTranscoding (webtorrent = true, hls = true) {
102 return this.updateExistingSubConfig({
107 allowAudioFiles: true,
108 allowAdditionalExtensions: true,
110 resolutions: ConfigCommand.getCustomConfigResolutions(true),
123 enableMinimumTranscoding (webtorrent = true, hls = true) {
124 return this.updateExistingSubConfig({
129 ...ConfigCommand.getCustomConfigResolutions(false),
146 return this.updateExistingSubConfig({
155 getConfig (options: OverrideCommandOptions = {}) {
156 const path = '/api/v1/config'
158 return this.getRequestBody<ServerConfig>({
162 implicitToken: false,
163 defaultExpectedStatus: HttpStatusCode.OK_200
167 async getIndexHTMLConfig (options: OverrideCommandOptions = {}) {
168 const text = await this.getRequestText({
172 implicitToken: false,
173 defaultExpectedStatus: HttpStatusCode.OK_200
176 const match = text.match('<script type="application/javascript">window.PeerTubeServerConfig = (".+?")</script>')
178 // We parse the string twice, first to extract the string and then to extract the JSON
179 return JSON.parse(JSON.parse(match[1])) as ServerConfig
182 getAbout (options: OverrideCommandOptions = {}) {
183 const path = '/api/v1/config/about'
185 return this.getRequestBody<About>({
189 implicitToken: false,
190 defaultExpectedStatus: HttpStatusCode.OK_200
194 getCustomConfig (options: OverrideCommandOptions = {}) {
195 const path = '/api/v1/config/custom'
197 return this.getRequestBody<CustomConfig>({
202 defaultExpectedStatus: HttpStatusCode.OK_200
206 updateCustomConfig (options: OverrideCommandOptions & {
207 newCustomConfig: CustomConfig
209 const path = '/api/v1/config/custom'
211 return this.putBodyRequest({
215 fields: options.newCustomConfig,
217 defaultExpectedStatus: HttpStatusCode.OK_200
221 deleteCustomConfig (options: OverrideCommandOptions = {}) {
222 const path = '/api/v1/config/custom'
224 return this.deleteRequest({
229 defaultExpectedStatus: HttpStatusCode.OK_200
233 async updateExistingSubConfig (options: OverrideCommandOptions & {
234 newConfig: DeepPartial<CustomConfig>
236 const existing = await this.getCustomConfig({ ...options, expectedStatus: HttpStatusCode.OK_200 })
238 return this.updateCustomConfig({ ...options, newCustomConfig: merge({}, existing, options.newConfig) })
241 updateCustomSubConfig (options: OverrideCommandOptions & {
242 newConfig: DeepPartial<CustomConfig>
244 const newCustomConfig: CustomConfig = {
246 name: 'PeerTube updated',
247 shortDescription: 'my short description',
248 description: 'my super description',
249 terms: 'my super terms',
250 codeOfConduct: 'my super coc',
252 creationReason: 'my super creation reason',
253 moderationInformation: 'my super moderation information',
254 administrator: 'Kuja',
255 maintenanceLifetime: 'forever',
256 businessModel: 'my super business model',
257 hardwareInformation: '2vCore 3GB RAM',
259 languages: [ 'en', 'es' ],
260 categories: [ 1, 2 ],
263 defaultNSFWPolicy: 'blur',
265 defaultClientRoute: '/videos/recently-added',
268 javascript: 'alert("coucou")',
269 css: 'body { background-color: red; }'
277 username: '@MySuperUsername',
284 preferAuthorDisplayName: false
289 redirectOnSingleExternalAuth: false
307 requiresEmailVerification: false,
311 email: 'superadmin1@example.com'
318 videoQuotaDaily: 318742
325 allowAdditionalExtensions: true,
326 allowAudioFiles: true,
341 alwaysTranscodeOriginalResolution: true,
356 maxInstanceLives: -1,
372 alwaysTranscodeOriginalResolution: true
388 videoChannelSynchronization: {
396 enabled: [ 'hot', 'most-viewed', 'most-liked' ],
411 manualApproval: false
420 indexUrl: 'https://instances.joinpeertube.org/api/v1/instances/hosts',
438 url: 'https://search.joinpeertube.org',
439 disableLocalSearch: true,
440 isDefaultSearch: true
445 merge(newCustomConfig, options.newConfig)
447 return this.updateCustomConfig({ ...options, newCustomConfig })