config.go 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. package data
  2. import (
  3. "os"
  4. "path/filepath"
  5. "sort"
  6. "strings"
  7. "time"
  8. "github.com/owncast/owncast/config"
  9. "github.com/owncast/owncast/models"
  10. "github.com/owncast/owncast/static"
  11. "github.com/owncast/owncast/utils"
  12. "github.com/pkg/errors"
  13. log "github.com/sirupsen/logrus"
  14. )
  15. const (
  16. extraContentKey = "extra_page_content"
  17. streamTitleKey = "stream_title"
  18. adminPasswordKey = "admin_password_key"
  19. logoPathKey = "logo_path"
  20. logoUniquenessKey = "logo_uniqueness"
  21. serverSummaryKey = "server_summary"
  22. serverWelcomeMessageKey = "server_welcome_message"
  23. serverNameKey = "server_name"
  24. serverURLKey = "server_url"
  25. httpPortNumberKey = "http_port_number"
  26. httpListenAddressKey = "http_listen_address"
  27. websocketHostOverrideKey = "websocket_host_override"
  28. rtmpPortNumberKey = "rtmp_port_number"
  29. serverMetadataTagsKey = "server_metadata_tags"
  30. directoryEnabledKey = "directory_enabled"
  31. directoryRegistrationKeyKey = "directory_registration_key"
  32. socialHandlesKey = "social_handles"
  33. peakViewersSessionKey = "peak_viewers_session"
  34. peakViewersOverallKey = "peak_viewers_overall"
  35. lastDisconnectTimeKey = "last_disconnect_time"
  36. ffmpegPathKey = "ffmpeg_path"
  37. nsfwKey = "nsfw"
  38. s3StorageConfigKey = "s3_storage_config"
  39. videoLatencyLevel = "video_latency_level"
  40. videoStreamOutputVariantsKey = "video_stream_output_variants"
  41. chatDisabledKey = "chat_disabled"
  42. externalActionsKey = "external_actions"
  43. customStylesKey = "custom_styles"
  44. customJavascriptKey = "custom_javascript"
  45. videoCodecKey = "video_codec"
  46. blockedUsernamesKey = "blocked_usernames"
  47. publicKeyKey = "public_key"
  48. privateKeyKey = "private_key"
  49. serverInitDateKey = "server_init_date"
  50. federationEnabledKey = "federation_enabled"
  51. federationUsernameKey = "federation_username"
  52. federationPrivateKey = "federation_private"
  53. federationGoLiveMessageKey = "federation_go_live_message"
  54. federationShowEngagementKey = "federation_show_engagement"
  55. federationBlockedDomainsKey = "federation_blocked_domains"
  56. suggestedUsernamesKey = "suggested_usernames"
  57. chatJoinMessagesEnabledKey = "chat_join_messages_enabled"
  58. chatEstablishedUsersOnlyModeKey = "chat_established_users_only_mode"
  59. chatSpamProtectionEnabledKey = "chat_spam_protection_enabled"
  60. chatSlurFilterEnabledKey = "chat_slur_filter_enabled"
  61. notificationsEnabledKey = "notifications_enabled"
  62. discordConfigurationKey = "discord_configuration"
  63. browserPushConfigurationKey = "browser_push_configuration"
  64. browserPushPublicKeyKey = "browser_push_public_key"
  65. // nolint:gosec
  66. browserPushPrivateKeyKey = "browser_push_private_key"
  67. hasConfiguredInitialNotificationsKey = "has_configured_initial_notifications"
  68. hideViewerCountKey = "hide_viewer_count"
  69. customOfflineMessageKey = "custom_offline_message"
  70. customColorVariableValuesKey = "custom_color_variable_values"
  71. streamKeysKey = "stream_keys"
  72. disableSearchIndexingKey = "disable_search_indexing"
  73. videoServingEndpointKey = "video_serving_endpoint"
  74. )
  75. // GetExtraPageBodyContent will return the user-supplied body content.
  76. func GetExtraPageBodyContent() string {
  77. content, err := _datastore.GetString(extraContentKey)
  78. if err != nil {
  79. log.Traceln(extraContentKey, err)
  80. return config.GetDefaults().PageBodyContent
  81. }
  82. return content
  83. }
  84. // SetExtraPageBodyContent will set the user-supplied body content.
  85. func SetExtraPageBodyContent(content string) error {
  86. return _datastore.SetString(extraContentKey, content)
  87. }
  88. // GetStreamTitle will return the name of the current stream.
  89. func GetStreamTitle() string {
  90. title, err := _datastore.GetString(streamTitleKey)
  91. if err != nil {
  92. return ""
  93. }
  94. return title
  95. }
  96. // SetStreamTitle will set the name of the current stream.
  97. func SetStreamTitle(title string) error {
  98. return _datastore.SetString(streamTitleKey, title)
  99. }
  100. // GetAdminPassword will return the admin password.
  101. func GetAdminPassword() string {
  102. key, _ := _datastore.GetString(adminPasswordKey)
  103. return key
  104. }
  105. // SetAdminPassword will set the admin password.
  106. func SetAdminPassword(key string) error {
  107. hashed_pass, err := utils.HashPassword(key)
  108. if err != nil {
  109. return err
  110. }
  111. return _datastore.SetString(adminPasswordKey, hashed_pass)
  112. }
  113. // GetLogoPath will return the path for the logo, relative to webroot.
  114. func GetLogoPath() string {
  115. logo, err := _datastore.GetString(logoPathKey)
  116. if err != nil {
  117. log.Traceln(logoPathKey, err)
  118. return config.GetDefaults().Logo
  119. }
  120. if logo == "" {
  121. return config.GetDefaults().Logo
  122. }
  123. return logo
  124. }
  125. // SetLogoPath will set the path for the logo, relative to webroot.
  126. func SetLogoPath(logo string) error {
  127. return _datastore.SetString(logoPathKey, logo)
  128. }
  129. // SetLogoUniquenessString will set the logo cache busting string.
  130. func SetLogoUniquenessString(uniqueness string) error {
  131. return _datastore.SetString(logoUniquenessKey, uniqueness)
  132. }
  133. // GetLogoUniquenessString will return the logo cache busting string.
  134. func GetLogoUniquenessString() string {
  135. uniqueness, err := _datastore.GetString(logoUniquenessKey)
  136. if err != nil {
  137. log.Traceln(logoUniquenessKey, err)
  138. return ""
  139. }
  140. return uniqueness
  141. }
  142. // GetServerSummary will return the server summary text.
  143. func GetServerSummary() string {
  144. summary, err := _datastore.GetString(serverSummaryKey)
  145. if err != nil {
  146. log.Traceln(serverSummaryKey, err)
  147. return ""
  148. }
  149. return summary
  150. }
  151. // SetServerSummary will set the server summary text.
  152. func SetServerSummary(summary string) error {
  153. return _datastore.SetString(serverSummaryKey, summary)
  154. }
  155. // GetServerWelcomeMessage will return the server welcome message text.
  156. func GetServerWelcomeMessage() string {
  157. welcomeMessage, err := _datastore.GetString(serverWelcomeMessageKey)
  158. if err != nil {
  159. log.Traceln(serverWelcomeMessageKey, err)
  160. return config.GetDefaults().ServerWelcomeMessage
  161. }
  162. return welcomeMessage
  163. }
  164. // SetServerWelcomeMessage will set the server welcome message text.
  165. func SetServerWelcomeMessage(welcomeMessage string) error {
  166. return _datastore.SetString(serverWelcomeMessageKey, welcomeMessage)
  167. }
  168. // GetServerName will return the server name text.
  169. func GetServerName() string {
  170. name, err := _datastore.GetString(serverNameKey)
  171. if err != nil {
  172. log.Traceln(serverNameKey, err)
  173. return config.GetDefaults().Name
  174. }
  175. return name
  176. }
  177. // SetServerName will set the server name text.
  178. func SetServerName(name string) error {
  179. return _datastore.SetString(serverNameKey, name)
  180. }
  181. // GetServerURL will return the server URL.
  182. func GetServerURL() string {
  183. url, err := _datastore.GetString(serverURLKey)
  184. if err != nil {
  185. return ""
  186. }
  187. return url
  188. }
  189. // SetServerURL will set the server URL.
  190. func SetServerURL(url string) error {
  191. return _datastore.SetString(serverURLKey, url)
  192. }
  193. // GetHTTPPortNumber will return the server HTTP port.
  194. func GetHTTPPortNumber() int {
  195. port, err := _datastore.GetNumber(httpPortNumberKey)
  196. if err != nil {
  197. log.Traceln(httpPortNumberKey, err)
  198. return config.GetDefaults().WebServerPort
  199. }
  200. if port == 0 {
  201. return config.GetDefaults().WebServerPort
  202. }
  203. return int(port)
  204. }
  205. // SetWebsocketOverrideHost will set the host override for websockets.
  206. func SetWebsocketOverrideHost(host string) error {
  207. return _datastore.SetString(websocketHostOverrideKey, host)
  208. }
  209. // GetWebsocketOverrideHost will return the host override for websockets.
  210. func GetWebsocketOverrideHost() string {
  211. host, _ := _datastore.GetString(websocketHostOverrideKey)
  212. return host
  213. }
  214. // SetHTTPPortNumber will set the server HTTP port.
  215. func SetHTTPPortNumber(port float64) error {
  216. return _datastore.SetNumber(httpPortNumberKey, port)
  217. }
  218. // GetHTTPListenAddress will return the HTTP listen address.
  219. func GetHTTPListenAddress() string {
  220. address, err := _datastore.GetString(httpListenAddressKey)
  221. if err != nil {
  222. log.Traceln(httpListenAddressKey, err)
  223. return config.GetDefaults().WebServerIP
  224. }
  225. return address
  226. }
  227. // SetHTTPListenAddress will set the server HTTP listen address.
  228. func SetHTTPListenAddress(address string) error {
  229. return _datastore.SetString(httpListenAddressKey, address)
  230. }
  231. // GetRTMPPortNumber will return the server RTMP port.
  232. func GetRTMPPortNumber() int {
  233. port, err := _datastore.GetNumber(rtmpPortNumberKey)
  234. if err != nil {
  235. log.Traceln(rtmpPortNumberKey, err)
  236. return config.GetDefaults().RTMPServerPort
  237. }
  238. if port == 0 {
  239. return config.GetDefaults().RTMPServerPort
  240. }
  241. return int(port)
  242. }
  243. // SetRTMPPortNumber will set the server RTMP port.
  244. func SetRTMPPortNumber(port float64) error {
  245. return _datastore.SetNumber(rtmpPortNumberKey, port)
  246. }
  247. // GetServerMetadataTags will return the metadata tags.
  248. func GetServerMetadataTags() []string {
  249. tagsString, err := _datastore.GetString(serverMetadataTagsKey)
  250. if tagsString == "" {
  251. return []string{}
  252. }
  253. if err != nil {
  254. log.Traceln(serverMetadataTagsKey, err)
  255. return []string{}
  256. }
  257. return strings.Split(tagsString, ",")
  258. }
  259. // SetServerMetadataTags will return the metadata tags.
  260. func SetServerMetadataTags(tags []string) error {
  261. tagString := strings.Join(tags, ",")
  262. return _datastore.SetString(serverMetadataTagsKey, tagString)
  263. }
  264. // GetDirectoryEnabled will return if this server should register to YP.
  265. func GetDirectoryEnabled() bool {
  266. enabled, err := _datastore.GetBool(directoryEnabledKey)
  267. if err != nil {
  268. return config.GetDefaults().YPEnabled
  269. }
  270. return enabled
  271. }
  272. // SetDirectoryEnabled will set if this server should register to YP.
  273. func SetDirectoryEnabled(enabled bool) error {
  274. return _datastore.SetBool(directoryEnabledKey, enabled)
  275. }
  276. // SetDirectoryRegistrationKey will set the YP protocol registration key.
  277. func SetDirectoryRegistrationKey(key string) error {
  278. return _datastore.SetString(directoryRegistrationKeyKey, key)
  279. }
  280. // GetDirectoryRegistrationKey will return the YP protocol registration key.
  281. func GetDirectoryRegistrationKey() string {
  282. key, _ := _datastore.GetString(directoryRegistrationKeyKey)
  283. return key
  284. }
  285. // GetSocialHandles will return the external social links.
  286. func GetSocialHandles() []models.SocialHandle {
  287. var socialHandles []models.SocialHandle
  288. configEntry, err := _datastore.Get(socialHandlesKey)
  289. if err != nil {
  290. log.Traceln(socialHandlesKey, err)
  291. return socialHandles
  292. }
  293. if err := configEntry.getObject(&socialHandles); err != nil {
  294. log.Traceln(err)
  295. return socialHandles
  296. }
  297. return socialHandles
  298. }
  299. // SetSocialHandles will set the external social links.
  300. func SetSocialHandles(socialHandles []models.SocialHandle) error {
  301. configEntry := ConfigEntry{Key: socialHandlesKey, Value: socialHandles}
  302. return _datastore.Save(configEntry)
  303. }
  304. // GetPeakSessionViewerCount will return the max number of viewers for this stream.
  305. func GetPeakSessionViewerCount() int {
  306. count, err := _datastore.GetNumber(peakViewersSessionKey)
  307. if err != nil {
  308. return 0
  309. }
  310. return int(count)
  311. }
  312. // SetPeakSessionViewerCount will set the max number of viewers for this stream.
  313. func SetPeakSessionViewerCount(count int) error {
  314. return _datastore.SetNumber(peakViewersSessionKey, float64(count))
  315. }
  316. // GetPeakOverallViewerCount will return the overall max number of viewers.
  317. func GetPeakOverallViewerCount() int {
  318. count, err := _datastore.GetNumber(peakViewersOverallKey)
  319. if err != nil {
  320. return 0
  321. }
  322. return int(count)
  323. }
  324. // SetPeakOverallViewerCount will set the overall max number of viewers.
  325. func SetPeakOverallViewerCount(count int) error {
  326. return _datastore.SetNumber(peakViewersOverallKey, float64(count))
  327. }
  328. // GetLastDisconnectTime will return the time the last stream ended.
  329. func GetLastDisconnectTime() (*utils.NullTime, error) {
  330. var disconnectTime utils.NullTime
  331. configEntry, err := _datastore.Get(lastDisconnectTimeKey)
  332. if err != nil {
  333. return nil, err
  334. }
  335. if err := configEntry.getObject(&disconnectTime); err != nil {
  336. return nil, err
  337. }
  338. if !disconnectTime.Valid || disconnectTime.Time.IsZero() {
  339. return nil, err
  340. }
  341. return &disconnectTime, nil
  342. }
  343. // SetLastDisconnectTime will set the time the last stream ended.
  344. func SetLastDisconnectTime(disconnectTime time.Time) error {
  345. savedDisconnectTime := utils.NullTime{Time: disconnectTime, Valid: true}
  346. configEntry := ConfigEntry{Key: lastDisconnectTimeKey, Value: savedDisconnectTime}
  347. return _datastore.Save(configEntry)
  348. }
  349. // SetNSFW will set if this stream has NSFW content.
  350. func SetNSFW(isNSFW bool) error {
  351. return _datastore.SetBool(nsfwKey, isNSFW)
  352. }
  353. // GetNSFW will return if this stream has NSFW content.
  354. func GetNSFW() bool {
  355. nsfw, err := _datastore.GetBool(nsfwKey)
  356. if err != nil {
  357. return false
  358. }
  359. return nsfw
  360. }
  361. // SetFfmpegPath will set the custom ffmpeg path.
  362. func SetFfmpegPath(path string) error {
  363. return _datastore.SetString(ffmpegPathKey, path)
  364. }
  365. // GetFfMpegPath will return the ffmpeg path.
  366. func GetFfMpegPath() string {
  367. path, err := _datastore.GetString(ffmpegPathKey)
  368. if err != nil {
  369. return ""
  370. }
  371. return path
  372. }
  373. // GetS3Config will return the external storage configuration.
  374. func GetS3Config() models.S3 {
  375. configEntry, err := _datastore.Get(s3StorageConfigKey)
  376. if err != nil {
  377. return models.S3{Enabled: false}
  378. }
  379. var s3Config models.S3
  380. if err := configEntry.getObject(&s3Config); err != nil {
  381. return models.S3{Enabled: false}
  382. }
  383. return s3Config
  384. }
  385. // SetS3Config will set the external storage configuration.
  386. func SetS3Config(config models.S3) error {
  387. configEntry := ConfigEntry{Key: s3StorageConfigKey, Value: config}
  388. return _datastore.Save(configEntry)
  389. }
  390. // GetStreamLatencyLevel will return the stream latency level.
  391. func GetStreamLatencyLevel() models.LatencyLevel {
  392. level, err := _datastore.GetNumber(videoLatencyLevel)
  393. if err != nil {
  394. level = 2 // default
  395. } else if level > 4 {
  396. level = 4 // highest
  397. }
  398. return models.GetLatencyLevel(int(level))
  399. }
  400. // SetStreamLatencyLevel will set the stream latency level.
  401. func SetStreamLatencyLevel(level float64) error {
  402. return _datastore.SetNumber(videoLatencyLevel, level)
  403. }
  404. // GetStreamOutputVariants will return all of the stream output variants.
  405. func GetStreamOutputVariants() []models.StreamOutputVariant {
  406. configEntry, err := _datastore.Get(videoStreamOutputVariantsKey)
  407. if err != nil {
  408. return config.GetDefaults().StreamVariants
  409. }
  410. var streamOutputVariants []models.StreamOutputVariant
  411. if err := configEntry.getObject(&streamOutputVariants); err != nil {
  412. return config.GetDefaults().StreamVariants
  413. }
  414. if len(streamOutputVariants) == 0 {
  415. return config.GetDefaults().StreamVariants
  416. }
  417. return streamOutputVariants
  418. }
  419. // SetStreamOutputVariants will set the stream output variants.
  420. func SetStreamOutputVariants(variants []models.StreamOutputVariant) error {
  421. configEntry := ConfigEntry{Key: videoStreamOutputVariantsKey, Value: variants}
  422. return _datastore.Save(configEntry)
  423. }
  424. // SetChatDisabled will disable chat if set to true.
  425. func SetChatDisabled(disabled bool) error {
  426. return _datastore.SetBool(chatDisabledKey, disabled)
  427. }
  428. // GetChatDisabled will return if chat is disabled.
  429. func GetChatDisabled() bool {
  430. disabled, err := _datastore.GetBool(chatDisabledKey)
  431. if err == nil {
  432. return disabled
  433. }
  434. return false
  435. }
  436. // SetChatEstablishedUsersOnlyMode sets the state of established user only mode.
  437. func SetChatEstablishedUsersOnlyMode(enabled bool) error {
  438. return _datastore.SetBool(chatEstablishedUsersOnlyModeKey, enabled)
  439. }
  440. // GetChatEstbalishedUsersOnlyMode returns the state of established user only mode.
  441. func GetChatEstbalishedUsersOnlyMode() bool {
  442. enabled, err := _datastore.GetBool(chatEstablishedUsersOnlyModeKey)
  443. if err == nil {
  444. return enabled
  445. }
  446. return false
  447. }
  448. // SetChatSpamProtectionEnabled will enable chat spam protection if set to true.
  449. func SetChatSpamProtectionEnabled(enabled bool) error {
  450. return _datastore.SetBool(chatSpamProtectionEnabledKey, enabled)
  451. }
  452. // GetChatSpamProtectionEnabled will return if chat spam protection is enabled.
  453. func GetChatSpamProtectionEnabled() bool {
  454. enabled, err := _datastore.GetBool(chatSpamProtectionEnabledKey)
  455. if err == nil {
  456. return enabled
  457. }
  458. return true
  459. }
  460. // SetChatSlurFilterEnabled will enable the chat slur filter.
  461. func SetChatSlurFilterEnabled(enabled bool) error {
  462. return _datastore.SetBool(chatSlurFilterEnabledKey, enabled)
  463. }
  464. // GetChatSlurFilterEnabled will return if the chat slur filter is enabled.
  465. func GetChatSlurFilterEnabled() bool {
  466. enabled, err := _datastore.GetBool(chatSlurFilterEnabledKey)
  467. if err == nil {
  468. return enabled
  469. }
  470. return false
  471. }
  472. // GetExternalActions will return the registered external actions.
  473. func GetExternalActions() []models.ExternalAction {
  474. configEntry, err := _datastore.Get(externalActionsKey)
  475. if err != nil {
  476. return []models.ExternalAction{}
  477. }
  478. var externalActions []models.ExternalAction
  479. if err := configEntry.getObject(&externalActions); err != nil {
  480. return []models.ExternalAction{}
  481. }
  482. return externalActions
  483. }
  484. // SetExternalActions will save external actions.
  485. func SetExternalActions(actions []models.ExternalAction) error {
  486. configEntry := ConfigEntry{Key: externalActionsKey, Value: actions}
  487. return _datastore.Save(configEntry)
  488. }
  489. // SetCustomStyles will save a string with CSS to insert into the page.
  490. func SetCustomStyles(styles string) error {
  491. return _datastore.SetString(customStylesKey, styles)
  492. }
  493. // GetCustomStyles will return a string with CSS to insert into the page.
  494. func GetCustomStyles() string {
  495. style, err := _datastore.GetString(customStylesKey)
  496. if err != nil {
  497. return ""
  498. }
  499. return style
  500. }
  501. // SetCustomJavascript will save a string with Javascript to insert into the page.
  502. func SetCustomJavascript(styles string) error {
  503. return _datastore.SetString(customJavascriptKey, styles)
  504. }
  505. // GetCustomJavascript will return a string with Javascript to insert into the page.
  506. func GetCustomJavascript() string {
  507. style, err := _datastore.GetString(customJavascriptKey)
  508. if err != nil {
  509. return ""
  510. }
  511. return style
  512. }
  513. // SetVideoCodec will set the codec used for video encoding.
  514. func SetVideoCodec(codec string) error {
  515. return _datastore.SetString(videoCodecKey, codec)
  516. }
  517. // GetVideoCodec returns the codec to use for transcoding video.
  518. func GetVideoCodec() string {
  519. codec, err := _datastore.GetString(videoCodecKey)
  520. if codec == "" || err != nil {
  521. return "libx264" // Default value
  522. }
  523. return codec
  524. }
  525. // VerifySettings will perform a sanity check for specific settings values.
  526. func VerifySettings() error {
  527. if len(GetStreamKeys()) == 0 && config.TemporaryStreamKey == "" {
  528. log.Errorln("No stream key set. Streaming is disabled. Please set one via the admin or command line arguments")
  529. }
  530. if GetAdminPassword() == "" {
  531. return errors.New("no admin password set. Please set one via the admin or command line arguments")
  532. }
  533. logoPath := GetLogoPath()
  534. if !utils.DoesFileExists(filepath.Join(config.DataDirectory, logoPath)) {
  535. log.Traceln(logoPath, "not found in the data directory. copying a default logo.")
  536. logo := static.GetLogo()
  537. if err := os.WriteFile(filepath.Join(config.DataDirectory, "logo.png"), logo, 0o600); err != nil {
  538. return errors.Wrap(err, "failed to write logo to disk")
  539. }
  540. if err := SetLogoPath("logo.png"); err != nil {
  541. return errors.Wrap(err, "failed to save logo filename")
  542. }
  543. }
  544. return nil
  545. }
  546. // FindHighestVideoQualityIndex will return the highest quality from a slice of variants.
  547. func FindHighestVideoQualityIndex(qualities []models.StreamOutputVariant) (int, bool) {
  548. type IndexedQuality struct {
  549. quality models.StreamOutputVariant
  550. index int
  551. }
  552. if len(qualities) < 2 {
  553. return 0, qualities[0].IsVideoPassthrough
  554. }
  555. indexedQualities := make([]IndexedQuality, 0)
  556. for index, quality := range qualities {
  557. indexedQuality := IndexedQuality{quality, index}
  558. indexedQualities = append(indexedQualities, indexedQuality)
  559. }
  560. sort.Slice(indexedQualities, func(a, b int) bool {
  561. if indexedQualities[a].quality.IsVideoPassthrough && !indexedQualities[b].quality.IsVideoPassthrough {
  562. return true
  563. }
  564. if !indexedQualities[a].quality.IsVideoPassthrough && indexedQualities[b].quality.IsVideoPassthrough {
  565. return false
  566. }
  567. return indexedQualities[a].quality.VideoBitrate > indexedQualities[b].quality.VideoBitrate
  568. })
  569. // nolint:gosec
  570. selectedQuality := indexedQualities[0]
  571. return selectedQuality.index, selectedQuality.quality.IsVideoPassthrough
  572. }
  573. // GetForbiddenUsernameList will return the blocked usernames as a comma separated string.
  574. func GetForbiddenUsernameList() []string {
  575. usernames, err := _datastore.GetStringSlice(blockedUsernamesKey)
  576. if err != nil {
  577. return config.DefaultForbiddenUsernames
  578. }
  579. if len(usernames) == 0 {
  580. return config.DefaultForbiddenUsernames
  581. }
  582. return usernames
  583. }
  584. // SetForbiddenUsernameList set the username blocklist as a comma separated string.
  585. func SetForbiddenUsernameList(usernames []string) error {
  586. return _datastore.SetStringSlice(blockedUsernamesKey, usernames)
  587. }
  588. // GetSuggestedUsernamesList will return the suggested usernames.
  589. // If the number of suggested usernames is smaller than 10, the number pool is
  590. // not used (see code in the CreateAnonymousUser function).
  591. func GetSuggestedUsernamesList() []string {
  592. usernames, err := _datastore.GetStringSlice(suggestedUsernamesKey)
  593. if err != nil || len(usernames) == 0 {
  594. return []string{}
  595. }
  596. return usernames
  597. }
  598. // SetSuggestedUsernamesList sets the username suggestion list.
  599. func SetSuggestedUsernamesList(usernames []string) error {
  600. return _datastore.SetStringSlice(suggestedUsernamesKey, usernames)
  601. }
  602. // GetServerInitTime will return when the server was first setup.
  603. func GetServerInitTime() (*utils.NullTime, error) {
  604. var t utils.NullTime
  605. configEntry, err := _datastore.Get(serverInitDateKey)
  606. if err != nil {
  607. return nil, err
  608. }
  609. if err := configEntry.getObject(&t); err != nil {
  610. return nil, err
  611. }
  612. if !t.Valid {
  613. return nil, err
  614. }
  615. return &t, nil
  616. }
  617. // SetServerInitTime will set when the server was first created.
  618. func SetServerInitTime(t time.Time) error {
  619. nt := utils.NullTime{Time: t, Valid: true}
  620. configEntry := ConfigEntry{Key: serverInitDateKey, Value: nt}
  621. return _datastore.Save(configEntry)
  622. }
  623. // SetFederationEnabled will enable federation if set to true.
  624. func SetFederationEnabled(enabled bool) error {
  625. return _datastore.SetBool(federationEnabledKey, enabled)
  626. }
  627. // GetFederationEnabled will return if federation is enabled.
  628. func GetFederationEnabled() bool {
  629. enabled, err := _datastore.GetBool(federationEnabledKey)
  630. if err == nil {
  631. return enabled
  632. }
  633. return false
  634. }
  635. // SetFederationUsername will set the username used in federated activities.
  636. func SetFederationUsername(username string) error {
  637. return _datastore.SetString(federationUsernameKey, username)
  638. }
  639. // GetFederationUsername will return the username used in federated activities.
  640. func GetFederationUsername() string {
  641. username, err := _datastore.GetString(federationUsernameKey)
  642. if username == "" || err != nil {
  643. return config.GetDefaults().FederationUsername
  644. }
  645. return username
  646. }
  647. // SetFederationGoLiveMessage will set the message sent when going live.
  648. func SetFederationGoLiveMessage(message string) error {
  649. return _datastore.SetString(federationGoLiveMessageKey, message)
  650. }
  651. // GetFederationGoLiveMessage will return the message sent when going live.
  652. func GetFederationGoLiveMessage() string {
  653. // Empty message means it's disabled.
  654. message, err := _datastore.GetString(federationGoLiveMessageKey)
  655. if err != nil {
  656. log.Traceln("unable to fetch go live message.", err)
  657. }
  658. return message
  659. }
  660. // SetFederationIsPrivate will set if federation activity is private.
  661. func SetFederationIsPrivate(isPrivate bool) error {
  662. return _datastore.SetBool(federationPrivateKey, isPrivate)
  663. }
  664. // GetFederationIsPrivate will return if federation is private.
  665. func GetFederationIsPrivate() bool {
  666. isPrivate, err := _datastore.GetBool(federationPrivateKey)
  667. if err == nil {
  668. return isPrivate
  669. }
  670. return false
  671. }
  672. // SetFederationShowEngagement will set if fediverse engagement shows in chat.
  673. func SetFederationShowEngagement(showEngagement bool) error {
  674. return _datastore.SetBool(federationShowEngagementKey, showEngagement)
  675. }
  676. // GetFederationShowEngagement will return if fediverse engagement shows in chat.
  677. func GetFederationShowEngagement() bool {
  678. showEngagement, err := _datastore.GetBool(federationShowEngagementKey)
  679. if err == nil {
  680. return showEngagement
  681. }
  682. return true
  683. }
  684. // SetBlockedFederatedDomains will set the blocked federated domains.
  685. func SetBlockedFederatedDomains(domains []string) error {
  686. return _datastore.SetString(federationBlockedDomainsKey, strings.Join(domains, ","))
  687. }
  688. // GetBlockedFederatedDomains will return a list of blocked federated domains.
  689. func GetBlockedFederatedDomains() []string {
  690. domains, err := _datastore.GetString(federationBlockedDomainsKey)
  691. if err != nil {
  692. return []string{}
  693. }
  694. if domains == "" {
  695. return []string{}
  696. }
  697. return strings.Split(domains, ",")
  698. }
  699. // SetChatJoinMessagesEnabled will set if chat join messages are enabled.
  700. func SetChatJoinMessagesEnabled(enabled bool) error {
  701. return _datastore.SetBool(chatJoinMessagesEnabledKey, enabled)
  702. }
  703. // GetChatJoinPartMessagesEnabled will return if chat join messages are enabled.
  704. func GetChatJoinPartMessagesEnabled() bool {
  705. enabled, err := _datastore.GetBool(chatJoinMessagesEnabledKey)
  706. if err != nil {
  707. return true
  708. }
  709. return enabled
  710. }
  711. // SetNotificationsEnabled will save the enabled state of notifications.
  712. func SetNotificationsEnabled(enabled bool) error {
  713. return _datastore.SetBool(notificationsEnabledKey, enabled)
  714. }
  715. // GetNotificationsEnabled will return the enabled state of notifications.
  716. func GetNotificationsEnabled() bool {
  717. enabled, _ := _datastore.GetBool(notificationsEnabledKey)
  718. return enabled
  719. }
  720. // GetDiscordConfig will return the Discord configuration.
  721. func GetDiscordConfig() models.DiscordConfiguration {
  722. configEntry, err := _datastore.Get(discordConfigurationKey)
  723. if err != nil {
  724. return models.DiscordConfiguration{Enabled: false}
  725. }
  726. var config models.DiscordConfiguration
  727. if err := configEntry.getObject(&config); err != nil {
  728. return models.DiscordConfiguration{Enabled: false}
  729. }
  730. return config
  731. }
  732. // SetDiscordConfig will set the Discord configuration.
  733. func SetDiscordConfig(config models.DiscordConfiguration) error {
  734. configEntry := ConfigEntry{Key: discordConfigurationKey, Value: config}
  735. return _datastore.Save(configEntry)
  736. }
  737. // GetBrowserPushConfig will return the browser push configuration.
  738. func GetBrowserPushConfig() models.BrowserNotificationConfiguration {
  739. configEntry, err := _datastore.Get(browserPushConfigurationKey)
  740. if err != nil {
  741. return models.BrowserNotificationConfiguration{Enabled: false}
  742. }
  743. var config models.BrowserNotificationConfiguration
  744. if err := configEntry.getObject(&config); err != nil {
  745. return models.BrowserNotificationConfiguration{Enabled: false}
  746. }
  747. return config
  748. }
  749. // SetBrowserPushConfig will set the browser push configuration.
  750. func SetBrowserPushConfig(config models.BrowserNotificationConfiguration) error {
  751. configEntry := ConfigEntry{Key: browserPushConfigurationKey, Value: config}
  752. return _datastore.Save(configEntry)
  753. }
  754. // SetBrowserPushPublicKey will set the public key for browser pushes.
  755. func SetBrowserPushPublicKey(key string) error {
  756. return _datastore.SetString(browserPushPublicKeyKey, key)
  757. }
  758. // GetBrowserPushPublicKey will return the public key for browser pushes.
  759. func GetBrowserPushPublicKey() (string, error) {
  760. return _datastore.GetString(browserPushPublicKeyKey)
  761. }
  762. // SetBrowserPushPrivateKey will set the private key for browser pushes.
  763. func SetBrowserPushPrivateKey(key string) error {
  764. return _datastore.SetString(browserPushPrivateKeyKey, key)
  765. }
  766. // GetBrowserPushPrivateKey will return the private key for browser pushes.
  767. func GetBrowserPushPrivateKey() (string, error) {
  768. return _datastore.GetString(browserPushPrivateKeyKey)
  769. }
  770. // SetHasPerformedInitialNotificationsConfig sets when performed initial setup.
  771. func SetHasPerformedInitialNotificationsConfig(hasConfigured bool) error {
  772. return _datastore.SetBool(hasConfiguredInitialNotificationsKey, true)
  773. }
  774. // GetHasPerformedInitialNotificationsConfig gets when performed initial setup.
  775. func GetHasPerformedInitialNotificationsConfig() bool {
  776. configured, _ := _datastore.GetBool(hasConfiguredInitialNotificationsKey)
  777. return configured
  778. }
  779. // GetHideViewerCount will return if the viewer count shold be hidden.
  780. func GetHideViewerCount() bool {
  781. hide, _ := _datastore.GetBool(hideViewerCountKey)
  782. return hide
  783. }
  784. // SetHideViewerCount will set if the viewer count should be hidden.
  785. func SetHideViewerCount(hide bool) error {
  786. return _datastore.SetBool(hideViewerCountKey, hide)
  787. }
  788. // GetCustomOfflineMessage will return the custom offline message.
  789. func GetCustomOfflineMessage() string {
  790. message, _ := _datastore.GetString(customOfflineMessageKey)
  791. return message
  792. }
  793. // SetCustomOfflineMessage will set the custom offline message.
  794. func SetCustomOfflineMessage(message string) error {
  795. return _datastore.SetString(customOfflineMessageKey, message)
  796. }
  797. // SetCustomColorVariableValues sets CSS variable names and values.
  798. func SetCustomColorVariableValues(variables map[string]string) error {
  799. return _datastore.SetStringMap(customColorVariableValuesKey, variables)
  800. }
  801. // GetCustomColorVariableValues gets CSS variable names and values.
  802. func GetCustomColorVariableValues() map[string]string {
  803. values, _ := _datastore.GetStringMap(customColorVariableValuesKey)
  804. return values
  805. }
  806. // GetStreamKeys will return valid stream keys.
  807. func GetStreamKeys() []models.StreamKey {
  808. configEntry, err := _datastore.Get(streamKeysKey)
  809. if err != nil {
  810. return []models.StreamKey{}
  811. }
  812. var streamKeys []models.StreamKey
  813. if err := configEntry.getObject(&streamKeys); err != nil {
  814. return []models.StreamKey{}
  815. }
  816. return streamKeys
  817. }
  818. // SetStreamKeys will set valid stream keys.
  819. func SetStreamKeys(actions []models.StreamKey) error {
  820. configEntry := ConfigEntry{Key: streamKeysKey, Value: actions}
  821. return _datastore.Save(configEntry)
  822. }
  823. // SetDisableSearchIndexing will set if the web server should be indexable.
  824. func SetDisableSearchIndexing(disableSearchIndexing bool) error {
  825. return _datastore.SetBool(disableSearchIndexingKey, disableSearchIndexing)
  826. }
  827. // GetDisableSearchIndexing will return if the web server should be indexable.
  828. func GetDisableSearchIndexing() bool {
  829. disableSearchIndexing, err := _datastore.GetBool(disableSearchIndexingKey)
  830. if err != nil {
  831. return false
  832. }
  833. return disableSearchIndexing
  834. }
  835. // GetVideoServingEndpoint returns the custom video endpont.
  836. func GetVideoServingEndpoint() string {
  837. message, _ := _datastore.GetString(videoServingEndpointKey)
  838. return message
  839. }
  840. // SetVideoServingEndpoint sets the custom video endpoint.
  841. func SetVideoServingEndpoint(message string) error {
  842. return _datastore.SetString(videoServingEndpointKey, message)
  843. }