From 681067ab930ace5074f9f0a3ccae5e2455c57835 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Tue, 9 Aug 2022 22:09:43 -0700 Subject: [PATCH] Add custom offline message+api. Part of #1901 --- controllers/admin/config.go | 19 +++++++++++++++++++ controllers/admin/serverConfig.go | 2 ++ controllers/config.go | 2 ++ core/data/config.go | 12 ++++++++++++ router/router.go | 3 +++ test/automated/api/configmanagement.test.js | 8 ++++++++ test/populateContent.sh | 20 ++++++++++++++++++++ web/components/ui/Content/Content.tsx | 7 +++++-- web/interfaces/client-config.model.ts | 2 ++ 9 files changed, 73 insertions(+), 2 deletions(-) diff --git a/controllers/admin/config.go b/controllers/admin/config.go index df1c23785..79d5dab0b 100644 --- a/controllers/admin/config.go +++ b/controllers/admin/config.go @@ -141,6 +141,25 @@ func SetServerSummary(w http.ResponseWriter, r *http.Request) { controllers.WriteSimpleResponse(w, true, "changed") } +// SetCustomOfflineMessage will set a message to display when the server is offline. +func SetCustomOfflineMessage(w http.ResponseWriter, r *http.Request) { + if !requirePOST(w, r) { + return + } + + configValue, success := getValueFromRequest(w, r) + if !success { + return + } + + if err := data.SetCustomOfflineMessage(strings.TrimSpace(configValue.Value.(string))); err != nil { + controllers.WriteSimpleResponse(w, false, err.Error()) + return + } + + controllers.WriteSimpleResponse(w, true, "changed") +} + // SetServerWelcomeMessage will handle the web config request to set the welcome message text. func SetServerWelcomeMessage(w http.ResponseWriter, r *http.Request) { if !requirePOST(w, r) { diff --git a/controllers/admin/serverConfig.go b/controllers/admin/serverConfig.go index fceb9d9f4..7acc25fee 100644 --- a/controllers/admin/serverConfig.go +++ b/controllers/admin/serverConfig.go @@ -41,6 +41,7 @@ func GetServerConfig(w http.ResponseWriter, r *http.Request) { ExtraPageContent: data.GetExtraPageBodyContent(), StreamTitle: data.GetStreamTitle(), WelcomeMessage: data.GetServerWelcomeMessage(), + OfflineMessage: data.GetCustomOfflineMessage(), Logo: data.GetLogoPath(), SocialHandles: data.GetSocialHandles(), NSFW: data.GetNSFW(), @@ -126,6 +127,7 @@ type webConfigResponse struct { Name string `json:"name"` Summary string `json:"summary"` WelcomeMessage string `json:"welcomeMessage"` + OfflineMessage string `json:"offlineMessage"` Logo string `json:"logo"` Tags []string `json:"tags"` Version string `json:"version"` diff --git a/controllers/config.go b/controllers/config.go index 059d18a88..ef9567671 100644 --- a/controllers/config.go +++ b/controllers/config.go @@ -18,6 +18,7 @@ import ( type webConfigResponse struct { Name string `json:"name"` Summary string `json:"summary"` + OfflineMessage string `json:"offlineMessage"` Logo string `json:"logo"` Tags []string `json:"tags"` Version string `json:"version"` @@ -108,6 +109,7 @@ func GetWebConfig(w http.ResponseWriter, r *http.Request) { configuration := webConfigResponse{ Name: data.GetServerName(), Summary: serverSummary, + OfflineMessage: data.GetCustomOfflineMessage(), Logo: "/logo", Tags: data.GetServerMetadataTags(), Version: config.GetReleaseString(), diff --git a/core/data/config.go b/core/data/config.go index fc55bc027..09f1676b6 100644 --- a/core/data/config.go +++ b/core/data/config.go @@ -66,6 +66,7 @@ const ( twitterConfigurationKey = "twitter_configuration" hasConfiguredInitialNotificationsKey = "has_configured_initial_notifications" hideViewerCountKey = "hide_viewer_count" + customOfflineMessageKey = "custom_offline_message" ) // GetExtraPageBodyContent will return the user-supplied body content. @@ -920,3 +921,14 @@ func GetHideViewerCount() bool { func SetHideViewerCount(hide bool) error { return _datastore.SetBool(hideViewerCountKey, hide) } + +// GetCustomOfflineMessage will return the custom offline message. +func GetCustomOfflineMessage() string { + message, _ := _datastore.GetString(customOfflineMessageKey) + return message +} + +// SetCustomOfflineMessage will set the custom offline message. +func SetCustomOfflineMessage(message string) error { + return _datastore.SetString(customOfflineMessageKey, message) +} diff --git a/router/router.go b/router/router.go index c9962d8c9..cdb4969e2 100644 --- a/router/router.go +++ b/router/router.go @@ -185,6 +185,9 @@ func Start() error { // Server summary http.HandleFunc("/api/admin/config/serversummary", middleware.RequireAdminAuth(admin.SetServerSummary)) + // Offline message + http.HandleFunc("/api/admin/config/offlinemessage", middleware.RequireAdminAuth(admin.SetCustomOfflineMessage)) + // Server welcome message http.HandleFunc("/api/admin/config/welcomemessage", middleware.RequireAdminAuth(admin.SetServerWelcomeMessage)) diff --git a/test/automated/api/configmanagement.test.js b/test/automated/api/configmanagement.test.js index 972695be9..7e605b13e 100644 --- a/test/automated/api/configmanagement.test.js +++ b/test/automated/api/configmanagement.test.js @@ -4,6 +4,7 @@ request = request('http://127.0.0.1:8080'); const serverName = randomString(); const streamTitle = randomString(); const serverSummary = randomString(); +const offlineMessage = randomString(); const pageContent = `

${randomString()}

`; const tags = [randomString(), randomString(), randomString()]; const latencyLevel = Math.floor(Math.random() * 4); @@ -97,12 +98,18 @@ test('set hide viewer count', async (done) => { done(); }); +test('set offline message', async (done) => { + const res = await sendConfigChangeRequest('offlinemessage', offlineMessage); + done(); +}); + test('verify updated config values', async (done) => { const res = await request.get('/api/config'); expect(res.body.name).toBe(serverName); expect(res.body.streamTitle).toBe(streamTitle); expect(res.body.summary).toBe(`${serverSummary}`); expect(res.body.extraPageContent).toBe(pageContent); + expect(res.body.offlineMessage).toBe(offlineMessage); expect(res.body.logo).toBe('/logo'); expect(res.body.socialHandles).toStrictEqual(socialHandles); done(); @@ -134,6 +141,7 @@ test('admin configuration is correct', (done) => { .then((res) => { expect(res.body.instanceDetails.name).toBe(serverName); expect(res.body.instanceDetails.summary).toBe(serverSummary); + expect(res.body.instanceDetails.offlineMessage).toBe(offlineMessage); expect(res.body.instanceDetails.tags).toStrictEqual(tags); expect(res.body.instanceDetails.socialHandles).toStrictEqual( socialHandles diff --git a/test/populateContent.sh b/test/populateContent.sh index c3f473c9c..2b8e4e1ba 100644 --- a/test/populateContent.sh +++ b/test/populateContent.sh @@ -124,3 +124,23 @@ curl 'http://localhost:8080/api/admin/config/externalactions' \ -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36' \ --data-raw '{"value":[{"url":"https://owncast.online/docs","title":"Documentation","description":"","icon":"","color":"","openExternally":false},{"url":"https://media1.giphy.com/media/Ju7l5y9osyymQ/giphy.gif?cid=ecf05e47otegqpl9mqfz880pi861dnjm5loy6kyrquy9lku0&rid=giphy.gif&ct=g","title":"Important","description":"","icon":"https://findicons.com/files/icons/1184/quickpix_2008/128/rick_roll_d.png","color":"#c87fd7","openExternally":false},{"url":"https://randommer.io/random-images","title":"New Tab","description":"","icon":"","color":"","openExternally":true}]}' \ --compressed + +# Offline message + +curl 'http://localhost:8080/api/admin/config/offlinemessage' \ + -H 'Accept: */*' \ + -H 'Accept-Language: en-US,en;q=0.9' \ + -H 'Authorization: Basic YWRtaW46YWJjMTIz' \ + -H 'Cache-Control: no-cache' \ + -H 'Connection: keep-alive' \ + -H 'Content-Type: text/plain;charset=UTF-8' \ + -H 'Origin: http://localhost:8080' \ + -H 'Pragma: no-cache' \ + -H 'Referer: http://localhost:8080/admin/config-public-details/' \ + -H 'Sec-Fetch-Dest: empty' \ + -H 'Sec-Fetch-Mode: cors' \ + -H 'Sec-Fetch-Site: same-origin' \ + -H 'Sec-GPC: 1' \ + -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36' \ + --data-raw '{"value":"Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. I am offline. This is my message."}' \ + --compressed diff --git a/web/components/ui/Content/Content.tsx b/web/components/ui/Content/Content.tsx index 1d0b6583d..d74bf4458 100644 --- a/web/components/ui/Content/Content.tsx +++ b/web/components/ui/Content/Content.tsx @@ -53,7 +53,7 @@ export default function ContentComponent() { const chatUserId = useRecoilValue(chatUserIdAtom); const { viewerCount, lastConnectTime, lastDisconnectTime } = useRecoilValue(serverStatusState); - const { extraPageContent, version, name, externalActions } = clientConfig; + const { extraPageContent, version, name, externalActions, offlineMessage } = clientConfig; const [showNotifyReminder, setShowNotifyReminder] = useState(false); const [showNotifyPopup, setShowNotifyPopup] = useState(false); @@ -109,7 +109,10 @@ export default function ContentComponent() { {!online && ( )}