mirror of
https://github.com/owncast/owncast.git
synced 2024-11-28 03:01:32 +03:00
Start cleaning up linter errors. (#358)
* Start cleaning up linter errors. For #357 * Fix unmarshalling NullTime values * More linter fixes * Remove commented code * Move defer up * Consolidate error check lines * Move error check to make sure row iteration was successful * Cleaner error check + do not recreate pipe if it exists * Consolidate hashing to generate client id
This commit is contained in:
parent
c76b7229a5
commit
4d2066a76d
34 changed files with 248 additions and 143 deletions
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/owncast/owncast/metrics"
|
"github.com/owncast/owncast/metrics"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetHardwareStats will return hardware utilization over time.
|
// GetHardwareStats will return hardware utilization over time.
|
||||||
|
@ -12,5 +13,8 @@ func GetHardwareStats(w http.ResponseWriter, r *http.Request) {
|
||||||
m := metrics.Metrics
|
m := metrics.Metrics
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(m)
|
err := json.NewEncoder(w).Encode(m)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ func ServeAdmin(w http.ResponseWriter, r *http.Request) {
|
||||||
f, err := pkger.Open(path)
|
f, err := pkger.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnln(err, path)
|
log.Warnln(err, path)
|
||||||
errorHandler(w, r, http.StatusNotFound)
|
errorHandler(w, http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,11 @@ func ServeAdmin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
mimeType := mime.TypeByExtension(filepath.Ext(path))
|
mimeType := mime.TypeByExtension(filepath.Ext(path))
|
||||||
w.Header().Set("Content-Type", mimeType)
|
w.Header().Set("Content-Type", mimeType)
|
||||||
w.Write(b)
|
if _, err = w.Write(b); err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorHandler(w http.ResponseWriter, r *http.Request, status int) {
|
func errorHandler(w http.ResponseWriter, status int) {
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/owncast/owncast/logging"
|
"github.com/owncast/owncast/logging"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetLogs will return all logs.
|
// GetLogs will return all logs.
|
||||||
|
@ -19,7 +20,10 @@ func GetLogs(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(response)
|
err := json.NewEncoder(w).Encode(response)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWarnings will return only warning and error logs.
|
// GetWarnings will return only warning and error logs.
|
||||||
|
@ -32,7 +36,10 @@ func GetWarnings(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(response)
|
err := json.NewEncoder(w).Encode(response)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type logsResponse struct {
|
type logsResponse struct {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/owncast/owncast/config"
|
"github.com/owncast/owncast/config"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetServerConfig gets the config details of the server.
|
// GetServerConfig gets the config details of the server.
|
||||||
|
@ -35,7 +36,10 @@ func GetServerConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(response)
|
err := json.NewEncoder(w).Encode(response)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type serverConfigAdminResponse struct {
|
type serverConfigAdminResponse struct {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/owncast/owncast/config"
|
"github.com/owncast/owncast/config"
|
||||||
"github.com/owncast/owncast/core"
|
"github.com/owncast/owncast/core"
|
||||||
"github.com/owncast/owncast/models"
|
"github.com/owncast/owncast/models"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Status gets the details of the inbound broadcaster.
|
// Status gets the details of the inbound broadcaster.
|
||||||
|
@ -25,7 +26,10 @@ func Status(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(response)
|
err := json.NewEncoder(w).Encode(response)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type adminStatusResponse struct {
|
type adminStatusResponse struct {
|
||||||
|
|
|
@ -5,11 +5,15 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/owncast/owncast/metrics"
|
"github.com/owncast/owncast/metrics"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetViewersOverTime will return the number of viewers at points in time.
|
// GetViewersOverTime will return the number of viewers at points in time.
|
||||||
func GetViewersOverTime(w http.ResponseWriter, r *http.Request) {
|
func GetViewersOverTime(w http.ResponseWriter, r *http.Request) {
|
||||||
viewersOverTime := metrics.Metrics.Viewers
|
viewersOverTime := metrics.Metrics.Viewers
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
json.NewEncoder(w).Encode(viewersOverTime)
|
err := json.NewEncoder(w).Encode(viewersOverTime)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/owncast/owncast/core"
|
"github.com/owncast/owncast/core"
|
||||||
"github.com/owncast/owncast/models"
|
"github.com/owncast/owncast/models"
|
||||||
"github.com/owncast/owncast/router/middleware"
|
"github.com/owncast/owncast/router/middleware"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetChatMessages gets all of the chat messages.
|
// GetChatMessages gets all of the chat messages.
|
||||||
|
@ -17,7 +18,10 @@ func GetChatMessages(w http.ResponseWriter, r *http.Request) {
|
||||||
case http.MethodGet:
|
case http.MethodGet:
|
||||||
messages := core.GetAllChatMessages()
|
messages := core.GetAllChatMessages()
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(messages)
|
err := json.NewEncoder(w).Encode(messages)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
var message models.ChatMessage
|
var message models.ChatMessage
|
||||||
if err := json.NewDecoder(r.Body).Decode(&message); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&message); err != nil {
|
||||||
|
@ -30,9 +34,14 @@ func GetChatMessages(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(j{"success": true})
|
if err := json.NewEncoder(w).Encode(j{"success": true}); err != nil {
|
||||||
|
internalErrorHandler(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
w.WriteHeader(http.StatusNotImplemented)
|
w.WriteHeader(http.StatusNotImplemented)
|
||||||
json.NewEncoder(w).Encode(j{"error": "method not implemented (PRs are accepted)"})
|
if err := json.NewEncoder(w).Encode(j{"error": "method not implemented (PRs are accepted)"}); err != nil {
|
||||||
|
internalErrorHandler(w, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,5 +14,7 @@ func GetWebConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
configuration := config.Config.InstanceDetails
|
configuration := config.Config.InstanceDetails
|
||||||
configuration.Version = config.Config.VersionInfo
|
configuration.Version = config.Config.VersionInfo
|
||||||
json.NewEncoder(w).Encode(configuration)
|
if err := json.NewEncoder(w).Encode(configuration); err != nil {
|
||||||
|
badRequestHandler(w, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,7 @@ func GetConnectedClients(w http.ResponseWriter, r *http.Request) {
|
||||||
clients := core.GetClients()
|
clients := core.GetClients()
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(clients)
|
if err := json.NewEncoder(w).Encode(clients); err != nil {
|
||||||
|
internalErrorHandler(w, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,9 @@ func internalErrorHandler(w http.ResponseWriter, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
json.NewEncoder(w).Encode(j{"error": err.Error()})
|
if err := json.NewEncoder(w).Encode(j{"error": err.Error()}); err != nil {
|
||||||
|
internalErrorHandler(w, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func badRequestHandler(w http.ResponseWriter, err error) {
|
func badRequestHandler(w http.ResponseWriter, err error) {
|
||||||
|
@ -24,7 +26,9 @@ func badRequestHandler(w http.ResponseWriter, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
json.NewEncoder(w).Encode(j{"error": err.Error()})
|
if err := json.NewEncoder(w).Encode(j{"error": err.Error()}); err != nil {
|
||||||
|
internalErrorHandler(w, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteSimpleResponse(w http.ResponseWriter, success bool, message string) {
|
func WriteSimpleResponse(w http.ResponseWriter, success bool, message string) {
|
||||||
|
@ -33,5 +37,7 @@ func WriteSimpleResponse(w http.ResponseWriter, success bool, message string) {
|
||||||
Message: message,
|
Message: message,
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
json.NewEncoder(w).Encode(response)
|
if err := json.NewEncoder(w).Encode(response); err != nil {
|
||||||
|
internalErrorHandler(w, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,11 @@ func GetCustomEmoji(w http.ResponseWriter, r *http.Request) {
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
name := strings.TrimSuffix(f.Name(), path.Ext(f.Name()))
|
name := strings.TrimSuffix(f.Name(), path.Ext(f.Name()))
|
||||||
emojiPath := filepath.Join(emojiDir, f.Name())
|
emojiPath := filepath.Join(emojiDir, f.Name())
|
||||||
singleEmoji := models.CustomEmoji{name, emojiPath}
|
singleEmoji := models.CustomEmoji{Name: name, Emoji: emojiPath}
|
||||||
emojiList = append(emojiList, singleEmoji)
|
emojiList = append(emojiList, singleEmoji)
|
||||||
}
|
}
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(emojiList)
|
if err := json.NewEncoder(w).Encode(emojiList); err != nil {
|
||||||
|
internalErrorHandler(w, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,7 @@ func GetStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
status := core.GetStatus()
|
status := core.GetStatus()
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(status)
|
if err := json.NewEncoder(w).Encode(status); err != nil {
|
||||||
|
internalErrorHandler(w, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,12 +40,9 @@ func Start() error {
|
||||||
|
|
||||||
ticker := time.NewTicker(30 * time.Second)
|
ticker := time.NewTicker(30 * time.Second)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for range ticker.C {
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
_server.ping()
|
_server.ping()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
_server.Listen()
|
_server.Listen()
|
||||||
|
|
|
@ -94,13 +94,21 @@ func (c *Client) listenWrite() {
|
||||||
select {
|
select {
|
||||||
// Send a PING keepalive
|
// Send a PING keepalive
|
||||||
case msg := <-c.pingch:
|
case msg := <-c.pingch:
|
||||||
websocket.JSON.Send(c.ws, msg)
|
err := websocket.JSON.Send(c.ws, msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
// send message to the client
|
// send message to the client
|
||||||
case msg := <-c.ch:
|
case msg := <-c.ch:
|
||||||
// log.Println("Send:", msg)
|
err := websocket.JSON.Send(c.ws, msg)
|
||||||
websocket.JSON.Send(c.ws, msg)
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
case msg := <-c.usernameChangeChannel:
|
case msg := <-c.usernameChangeChannel:
|
||||||
websocket.JSON.Send(c.ws, msg)
|
err := websocket.JSON.Send(c.ws, msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
// receive done request
|
// receive done request
|
||||||
case <-c.doneCh:
|
case <-c.doneCh:
|
||||||
_server.remove(c)
|
_server.remove(c)
|
||||||
|
@ -114,7 +122,6 @@ func (c *Client) listenWrite() {
|
||||||
func (c *Client) listenRead() {
|
func (c *Client) listenRead() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
|
||||||
// receive done request
|
// receive done request
|
||||||
case <-c.doneCh:
|
case <-c.doneCh:
|
||||||
_server.remove(c)
|
_server.remove(c)
|
||||||
|
|
|
@ -32,7 +32,10 @@ func createTable() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
defer stmt.Close()
|
defer stmt.Close()
|
||||||
stmt.Exec()
|
_, err = stmt.Exec()
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addMessage(message models.ChatMessage) {
|
func addMessage(message models.ChatMessage) {
|
||||||
|
@ -41,16 +44,20 @@ func addMessage(message models.ChatMessage) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
stmt, err := tx.Prepare("INSERT INTO messages(id, author, body, messageType, visible, timestamp) values(?, ?, ?, ?, ?, ?)")
|
stmt, err := tx.Prepare("INSERT INTO messages(id, author, body, messageType, visible, timestamp) values(?, ?, ?, ?, ?, ?)")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
|
||||||
_, err = stmt.Exec(message.ID, message.Author, message.Body, message.MessageType, 1, message.Timestamp)
|
_, err = stmt.Exec(message.ID, message.Author, message.Body, message.MessageType, 1, message.Timestamp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
tx.Commit()
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
defer stmt.Close()
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getChatHistory() []models.ChatMessage {
|
func getChatHistory() []models.ChatMessage {
|
||||||
|
@ -89,5 +96,9 @@ func getChatHistory() []models.ChatMessage {
|
||||||
history = append(history, message)
|
history = append(history, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
return history
|
return history
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,6 @@ func (s *server) SendToAll(msg models.ChatMessage) {
|
||||||
s.sendAllCh <- msg
|
s.sendAllCh <- msg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done marks the server as done.
|
|
||||||
func (s *server) done() {
|
|
||||||
s.doneCh <- true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Err handles an error.
|
// Err handles an error.
|
||||||
func (s *server) err(err error) {
|
func (s *server) err(err error) {
|
||||||
s.errCh <- err
|
s.errCh <- err
|
||||||
|
@ -140,18 +135,7 @@ func (s *server) sendWelcomeMessageToClient(c *Client) {
|
||||||
time.Sleep(7 * time.Second)
|
time.Sleep(7 * time.Second)
|
||||||
|
|
||||||
initialChatMessageText := fmt.Sprintf("Welcome to %s! %s", config.Config.InstanceDetails.Title, config.Config.InstanceDetails.Summary)
|
initialChatMessageText := fmt.Sprintf("Welcome to %s! %s", config.Config.InstanceDetails.Title, config.Config.InstanceDetails.Summary)
|
||||||
initialMessage := models.ChatMessage{"owncast-server", config.Config.InstanceDetails.Name, initialChatMessageText, "initial-message-1", "SYSTEM", true, time.Now()}
|
initialMessage := models.ChatMessage{ClientID: "owncast-server", Author: config.Config.InstanceDetails.Name, Body: initialChatMessageText, ID: "initial-message-1", MessageType: "SYSTEM", Visible: true, Timestamp: time.Now()}
|
||||||
c.Write(initialMessage)
|
c.Write(initialMessage)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) getClientForClientID(clientID string) *Client {
|
|
||||||
for _, client := range s.Clients {
|
|
||||||
if client.ClientID == clientID {
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
43
core/core.go
43
core/core.go
|
@ -99,7 +99,10 @@ func transitionToOfflineVideoStreamContent() {
|
||||||
_transcoder.Start()
|
_transcoder.Start()
|
||||||
|
|
||||||
// Copy the logo to be the thumbnail
|
// Copy the logo to be the thumbnail
|
||||||
utils.Copy(filepath.Join("webroot", config.Config.InstanceDetails.Logo.Large), "webroot/thumbnail.jpg")
|
err := utils.Copy(filepath.Join("webroot", config.Config.InstanceDetails.Logo.Large), "webroot/thumbnail.jpg")
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Delete the preview Gif
|
// Delete the preview Gif
|
||||||
os.Remove(path.Join(config.WebRoot, "preview.gif"))
|
os.Remove(path.Join(config.WebRoot, "preview.gif"))
|
||||||
|
@ -111,8 +114,15 @@ func resetDirectories() {
|
||||||
// Wipe the public, web-accessible hls data directory
|
// Wipe the public, web-accessible hls data directory
|
||||||
os.RemoveAll(config.PublicHLSStoragePath)
|
os.RemoveAll(config.PublicHLSStoragePath)
|
||||||
os.RemoveAll(config.PrivateHLSStoragePath)
|
os.RemoveAll(config.PrivateHLSStoragePath)
|
||||||
os.MkdirAll(config.PublicHLSStoragePath, 0777)
|
err := os.MkdirAll(config.PublicHLSStoragePath, 0777)
|
||||||
os.MkdirAll(config.PrivateHLSStoragePath, 0777)
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(config.PrivateHLSStoragePath, 0777)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the previous thumbnail
|
// Remove the previous thumbnail
|
||||||
os.Remove(filepath.Join(config.WebRoot, "thumbnail.jpg"))
|
os.Remove(filepath.Join(config.WebRoot, "thumbnail.jpg"))
|
||||||
|
@ -120,14 +130,31 @@ func resetDirectories() {
|
||||||
// Create private hls data dirs
|
// Create private hls data dirs
|
||||||
if len(config.Config.VideoSettings.StreamQualities) != 0 {
|
if len(config.Config.VideoSettings.StreamQualities) != 0 {
|
||||||
for index := range config.Config.VideoSettings.StreamQualities {
|
for index := range config.Config.VideoSettings.StreamQualities {
|
||||||
os.MkdirAll(path.Join(config.PrivateHLSStoragePath, strconv.Itoa(index)), 0777)
|
err = os.MkdirAll(path.Join(config.PrivateHLSStoragePath, strconv.Itoa(index)), 0777)
|
||||||
os.MkdirAll(path.Join(config.PublicHLSStoragePath, strconv.Itoa(index)), 0777)
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(path.Join(config.PublicHLSStoragePath, strconv.Itoa(index)), 0777)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
os.MkdirAll(path.Join(config.PrivateHLSStoragePath, strconv.Itoa(0)), 0777)
|
err = os.MkdirAll(path.Join(config.PrivateHLSStoragePath, strconv.Itoa(0)), 0777)
|
||||||
os.MkdirAll(path.Join(config.PublicHLSStoragePath, strconv.Itoa(0)), 0777)
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.MkdirAll(path.Join(config.PublicHLSStoragePath, strconv.Itoa(0)), 0777)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the previous thumbnail
|
// Remove the previous thumbnail
|
||||||
utils.Copy(config.Config.InstanceDetails.Logo.Large, "webroot/thumbnail.jpg")
|
err = utils.Copy(path.Join(config.WebRoot, config.Config.InstanceDetails.Logo.Large), "webroot/thumbnail.jpg")
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,14 +60,14 @@ func (s *FileWriterReceiverService) uploadHandler(w http.ResponseWriter, r *http
|
||||||
|
|
||||||
f, err := os.Create(writePath)
|
f, err := os.Create(writePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnError(err, w, r)
|
returnError(err, w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
_, err = f.Write(data)
|
_, err = f.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnError(err, w, r)
|
returnError(err, w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,6 @@ func (s *FileWriterReceiverService) fileWritten(path string) {
|
||||||
|
|
||||||
if utils.GetRelativePathFromAbsolutePath(path) == "hls/stream.m3u8" {
|
if utils.GetRelativePathFromAbsolutePath(path) == "hls/stream.m3u8" {
|
||||||
s.callbacks.MasterPlaylistWritten(path)
|
s.callbacks.MasterPlaylistWritten(path)
|
||||||
|
|
||||||
} else if strings.HasSuffix(path, ".ts") {
|
} else if strings.HasSuffix(path, ".ts") {
|
||||||
performanceMonitorKey := "segmentWritten-" + index
|
performanceMonitorKey := "segmentWritten-" + index
|
||||||
averagePerformance := utils.GetAveragePerformance(performanceMonitorKey)
|
averagePerformance := utils.GetAveragePerformance(performanceMonitorKey)
|
||||||
|
@ -98,13 +97,12 @@ func (s *FileWriterReceiverService) fileWritten(path string) {
|
||||||
} else {
|
} else {
|
||||||
_inWarningState = false
|
_inWarningState = false
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if strings.HasSuffix(path, ".m3u8") {
|
} else if strings.HasSuffix(path, ".m3u8") {
|
||||||
s.callbacks.VariantPlaylistWritten(path)
|
s.callbacks.VariantPlaylistWritten(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func returnError(err error, w http.ResponseWriter, r *http.Request) {
|
func returnError(err error, w http.ResponseWriter) {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError)+": "+err.Error(), http.StatusInternalServerError)
|
http.Error(w, http.StatusText(http.StatusInternalServerError)+": "+err.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,12 @@ func HandleConn(c *rtmp.Conn, nc net.Conn) {
|
||||||
log.Infoln("Incoming RTMP connected.")
|
log.Infoln("Incoming RTMP connected.")
|
||||||
|
|
||||||
pipePath := utils.GetTemporaryPipePath()
|
pipePath := utils.GetTemporaryPipePath()
|
||||||
syscall.Mkfifo(pipePath, 0666)
|
if !utils.DoesFileExists(pipePath) {
|
||||||
|
err := syscall.Mkfifo(pipePath, 0666)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_hasInboundRTMPConnection = true
|
_hasInboundRTMPConnection = true
|
||||||
_setStreamAsConnected()
|
_setStreamAsConnected()
|
||||||
|
@ -119,7 +124,6 @@ func HandleConn(c *rtmp.Conn, nc net.Conn) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleDisconnect(conn net.Conn) {
|
func handleDisconnect(conn net.Conn) {
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/owncast/owncast/models"
|
|
||||||
"github.com/nareix/joy5/format/flv/flvio"
|
"github.com/nareix/joy5/format/flv/flvio"
|
||||||
|
"github.com/owncast/owncast/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getInboundDetailsFromMetadata(metadata []interface{}) (models.RTMPStreamMetadata, error) {
|
func getInboundDetailsFromMetadata(metadata []interface{}) (models.RTMPStreamMetadata, error) {
|
||||||
|
@ -21,8 +21,8 @@ func getInboundDetailsFromMetadata(metadata []interface{}) (models.RTMPStreamMet
|
||||||
|
|
||||||
metadataJSONString := submatchall[0]
|
metadataJSONString := submatchall[0]
|
||||||
var details models.RTMPStreamMetadata
|
var details models.RTMPStreamMetadata
|
||||||
json.Unmarshal([]byte(metadataJSONString), &details)
|
err := json.Unmarshal([]byte(metadataJSONString), &details)
|
||||||
return details, nil
|
return details, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAudioCodec(codec interface{}) string {
|
func getAudioCodec(codec interface{}) string {
|
||||||
|
|
|
@ -29,14 +29,11 @@ func setupStats() error {
|
||||||
|
|
||||||
statsSaveTimer := time.NewTicker(1 * time.Minute)
|
statsSaveTimer := time.NewTicker(1 * time.Minute)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for range statsSaveTimer.C {
|
||||||
select {
|
|
||||||
case <-statsSaveTimer.C:
|
|
||||||
if err := saveStatsToFile(); err != nil {
|
if err := saveStatsToFile(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -137,12 +134,12 @@ func getSavedStats() (models.Stats, error) {
|
||||||
|
|
||||||
jsonFile, err := ioutil.ReadFile(config.StatsFile)
|
jsonFile, err := ioutil.ReadFile(config.StatsFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, nil
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(jsonFile, &result); err != nil {
|
if err := json.Unmarshal(jsonFile, &result); err != nil {
|
||||||
return result, nil
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,6 @@ import (
|
||||||
"github.com/owncast/owncast/core/storageproviders"
|
"github.com/owncast/owncast/core/storageproviders"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
usingExternalStorage = false
|
|
||||||
)
|
|
||||||
|
|
||||||
func setupStorage() error {
|
func setupStorage() error {
|
||||||
handler.Storage = _storage
|
handler.Storage = _storage
|
||||||
|
|
||||||
|
|
|
@ -23,19 +23,19 @@ func (s *LocalStorage) Setup() error {
|
||||||
// as all HLS segments have to be publicly available on disk to keep a recording of them.
|
// as all HLS segments have to be publicly available on disk to keep a recording of them.
|
||||||
_onlineCleanupTicker = time.NewTicker(1 * time.Minute)
|
_onlineCleanupTicker = time.NewTicker(1 * time.Minute)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for range _onlineCleanupTicker.C {
|
||||||
select {
|
|
||||||
case <-_onlineCleanupTicker.C:
|
|
||||||
ffmpeg.CleanupOldContent(config.PublicHLSStoragePath)
|
ffmpeg.CleanupOldContent(config.PublicHLSStoragePath)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SegmentWritten is called when a single segment of video is written.
|
// SegmentWritten is called when a single segment of video is written.
|
||||||
func (s *LocalStorage) SegmentWritten(localFilePath string) {
|
func (s *LocalStorage) SegmentWritten(localFilePath string) {
|
||||||
s.Save(localFilePath, 0)
|
_, err := s.Save(localFilePath, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VariantPlaylistWritten is called when a variant hls playlist is written.
|
// VariantPlaylistWritten is called when a variant hls playlist is written.
|
||||||
|
@ -49,7 +49,10 @@ func (s *LocalStorage) VariantPlaylistWritten(localFilePath string) {
|
||||||
|
|
||||||
// MasterPlaylistWritten is called when the master hls playlist is written.
|
// MasterPlaylistWritten is called when the master hls playlist is written.
|
||||||
func (s *LocalStorage) MasterPlaylistWritten(localFilePath string) {
|
func (s *LocalStorage) MasterPlaylistWritten(localFilePath string) {
|
||||||
s.Save(localFilePath, 0)
|
_, err := s.Save(localFilePath, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save a local filepath using the storage provider.
|
// Save will save a local filepath using the storage provider.
|
||||||
|
@ -63,7 +66,6 @@ func (s *LocalStorage) Save(filePath string, retryCount int) (string, error) {
|
||||||
newPath = filepath.Join(config.WebRoot, filePath)
|
newPath = filepath.Join(config.WebRoot, filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.Copy(filePath, newPath)
|
err := utils.Copy(filePath, newPath)
|
||||||
|
return newPath, err
|
||||||
return newPath, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
// If we try to upload a playlist but it is not yet on disk
|
// If we try to upload a playlist but it is not yet on disk
|
||||||
// then keep a reference to it here.
|
// then keep a reference to it here.
|
||||||
var _queuedPlaylistUpdates = make(map[string]string, 0)
|
var _queuedPlaylistUpdates = make(map[string]string)
|
||||||
|
|
||||||
// S3Storage is the s3 implementation of the ChunkStorageProvider.
|
// S3Storage is the s3 implementation of the ChunkStorageProvider.
|
||||||
type S3Storage struct {
|
type S3Storage struct {
|
||||||
|
@ -118,7 +118,10 @@ func (s *S3Storage) VariantPlaylistWritten(localFilePath string) {
|
||||||
// MasterPlaylistWritten is called when the master hls playlist is written.
|
// MasterPlaylistWritten is called when the master hls playlist is written.
|
||||||
func (s *S3Storage) MasterPlaylistWritten(localFilePath string) {
|
func (s *S3Storage) MasterPlaylistWritten(localFilePath string) {
|
||||||
// Rewrite the playlist to use absolute remote S3 URLs
|
// Rewrite the playlist to use absolute remote S3 URLs
|
||||||
s.rewriteRemotePlaylist(localFilePath)
|
err := s.rewriteRemotePlaylist(localFilePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save saves the file to the s3 bucket.
|
// Save saves the file to the s3 bucket.
|
||||||
|
@ -192,6 +195,9 @@ func (s *S3Storage) rewriteRemotePlaylist(filePath string) error {
|
||||||
|
|
||||||
p := m3u8.NewMasterPlaylist()
|
p := m3u8.NewMasterPlaylist()
|
||||||
err = p.DecodeFrom(bufio.NewReader(f), false)
|
err = p.DecodeFrom(bufio.NewReader(f), false)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
|
|
||||||
for _, item := range p.Variants {
|
for _, item := range p.Variants {
|
||||||
item.URI = s.host + filepath.Join("/hls", item.URI)
|
item.URI = s.host + filepath.Join("/hls", item.URI)
|
||||||
|
|
|
@ -26,8 +26,8 @@ var _onlineCleanupTicker *time.Ticker
|
||||||
// setStreamAsConnected sets the stream as connected.
|
// setStreamAsConnected sets the stream as connected.
|
||||||
func setStreamAsConnected() {
|
func setStreamAsConnected() {
|
||||||
_stats.StreamConnected = true
|
_stats.StreamConnected = true
|
||||||
_stats.LastConnectTime = utils.NullTime{time.Now(), true}
|
_stats.LastConnectTime = utils.NullTime{Time: time.Now(), Valid: true}
|
||||||
_stats.LastDisconnectTime = utils.NullTime{time.Now(), false}
|
_stats.LastDisconnectTime = utils.NullTime{Time: time.Now(), Valid: false}
|
||||||
|
|
||||||
StopOfflineCleanupTimer()
|
StopOfflineCleanupTimer()
|
||||||
startOnlineCleanupTimer()
|
startOnlineCleanupTimer()
|
||||||
|
@ -44,7 +44,6 @@ func setStreamAsConnected() {
|
||||||
go func() {
|
go func() {
|
||||||
_transcoder = ffmpeg.NewTranscoder()
|
_transcoder = ffmpeg.NewTranscoder()
|
||||||
_transcoder.TranscoderCompleted = func(error) {
|
_transcoder.TranscoderCompleted = func(error) {
|
||||||
|
|
||||||
SetStreamAsDisconnected()
|
SetStreamAsDisconnected()
|
||||||
}
|
}
|
||||||
_transcoder.Start()
|
_transcoder.Start()
|
||||||
|
@ -56,7 +55,7 @@ func setStreamAsConnected() {
|
||||||
// SetStreamAsDisconnected sets the stream as disconnected.
|
// SetStreamAsDisconnected sets the stream as disconnected.
|
||||||
func SetStreamAsDisconnected() {
|
func SetStreamAsDisconnected() {
|
||||||
_stats.StreamConnected = false
|
_stats.StreamConnected = false
|
||||||
_stats.LastDisconnectTime = utils.NullTime{time.Now(), true}
|
_stats.LastDisconnectTime = utils.NullTime{Time: time.Now(), Valid: true}
|
||||||
_broadcaster = nil
|
_broadcaster = nil
|
||||||
|
|
||||||
offlineFilename := "offline.ts"
|
offlineFilename := "offline.ts"
|
||||||
|
@ -73,9 +72,14 @@ func SetStreamAsDisconnected() {
|
||||||
playlistFilePath := fmt.Sprintf(filepath.Join(config.PrivateHLSStoragePath, "%d/stream.m3u8"), index)
|
playlistFilePath := fmt.Sprintf(filepath.Join(config.PrivateHLSStoragePath, "%d/stream.m3u8"), index)
|
||||||
segmentFilePath := fmt.Sprintf(filepath.Join(config.PrivateHLSStoragePath, "%d/%s"), index, offlineFilename)
|
segmentFilePath := fmt.Sprintf(filepath.Join(config.PrivateHLSStoragePath, "%d/%s"), index, offlineFilename)
|
||||||
|
|
||||||
utils.Copy(offlineFilePath, segmentFilePath)
|
err := utils.Copy(offlineFilePath, segmentFilePath)
|
||||||
_storage.Save(segmentFilePath, 0)
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
|
_, err = _storage.Save(segmentFilePath, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
if utils.DoesFileExists(playlistFilePath) {
|
if utils.DoesFileExists(playlistFilePath) {
|
||||||
f, err := os.OpenFile(playlistFilePath, os.O_CREATE|os.O_RDWR, os.ModePerm)
|
f, err := os.OpenFile(playlistFilePath, os.O_CREATE|os.O_RDWR, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -84,13 +88,23 @@ func SetStreamAsDisconnected() {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
playlist, _, err := m3u8.DecodeFrom(bufio.NewReader(f), true)
|
playlist, _, err := m3u8.DecodeFrom(bufio.NewReader(f), true)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
|
||||||
variantPlaylist := playlist.(*m3u8.MediaPlaylist)
|
variantPlaylist := playlist.(*m3u8.MediaPlaylist)
|
||||||
if len(variantPlaylist.Segments) > config.Config.GetMaxNumberOfReferencedSegmentsInPlaylist() {
|
if len(variantPlaylist.Segments) > config.Config.GetMaxNumberOfReferencedSegmentsInPlaylist() {
|
||||||
variantPlaylist.Segments = variantPlaylist.Segments[:len(variantPlaylist.Segments)]
|
variantPlaylist.Segments = variantPlaylist.Segments[:len(variantPlaylist.Segments)]
|
||||||
}
|
}
|
||||||
|
|
||||||
err = variantPlaylist.Append(offlineFilename, 8.0, "")
|
err = variantPlaylist.Append(offlineFilename, 8.0, "")
|
||||||
variantPlaylist.SetDiscontinuity()
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
err = variantPlaylist.SetDiscontinuity()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
_, err = f.WriteAt(variantPlaylist.Encode().Bytes(), 0)
|
_, err = f.WriteAt(variantPlaylist.Encode().Bytes(), 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
|
@ -118,7 +132,10 @@ func SetStreamAsDisconnected() {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_storage.Save(playlistFilePath, 0)
|
_, err = _storage.Save(playlistFilePath, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartOfflineCleanupTimer()
|
StartOfflineCleanupTimer()
|
||||||
|
@ -129,15 +146,12 @@ func SetStreamAsDisconnected() {
|
||||||
func StartOfflineCleanupTimer() {
|
func StartOfflineCleanupTimer() {
|
||||||
_offlineCleanupTimer = time.NewTimer(5 * time.Minute)
|
_offlineCleanupTimer = time.NewTimer(5 * time.Minute)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for range _offlineCleanupTimer.C {
|
||||||
select {
|
|
||||||
case <-_offlineCleanupTimer.C:
|
|
||||||
// Reset the session count since the session is over
|
// Reset the session count since the session is over
|
||||||
_stats.SessionMaxViewerCount = 0
|
_stats.SessionMaxViewerCount = 0
|
||||||
resetDirectories()
|
resetDirectories()
|
||||||
transitionToOfflineVideoStreamContent()
|
transitionToOfflineVideoStreamContent()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,12 +165,9 @@ func StopOfflineCleanupTimer() {
|
||||||
func startOnlineCleanupTimer() {
|
func startOnlineCleanupTimer() {
|
||||||
_onlineCleanupTicker = time.NewTicker(1 * time.Minute)
|
_onlineCleanupTicker = time.NewTicker(1 * time.Minute)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for range _onlineCleanupTicker.C {
|
||||||
select {
|
|
||||||
case <-_onlineCleanupTicker.C:
|
|
||||||
ffmpeg.CleanupOldContent(config.PrivateHLSStoragePath)
|
ffmpeg.CleanupOldContent(config.PrivateHLSStoragePath)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,5 +80,4 @@ func FetchGeoForIP(ip string) {
|
||||||
|
|
||||||
_geoIPCache[ip] = response
|
_geoIPCache[ip] = response
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
8
main.go
8
main.go
|
@ -31,7 +31,7 @@ func main() {
|
||||||
|
|
||||||
log.Infoln(getReleaseString())
|
log.Infoln(getReleaseString())
|
||||||
// Enable bundling of admin assets
|
// Enable bundling of admin assets
|
||||||
pkger.Include("/admin")
|
_ = pkger.Include("/admin")
|
||||||
|
|
||||||
configFile := flag.String("configFile", "config.yaml", "Config File full path. Defaults to current folder")
|
configFile := flag.String("configFile", "config.yaml", "Config File full path. Defaults to current folder")
|
||||||
dbFile := flag.String("database", "", "Path to the database file.")
|
dbFile := flag.String("database", "", "Path to the database file.")
|
||||||
|
@ -67,13 +67,11 @@ func main() {
|
||||||
|
|
||||||
// starts the core
|
// starts the core
|
||||||
if err := core.Start(); err != nil {
|
if err := core.Start(); err != nil {
|
||||||
log.Error("failed to start the core package")
|
log.Fatalln("failed to start the core package", err)
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := router.Start(); err != nil {
|
if err := router.Start(); err != nil {
|
||||||
log.Error("failed to start/run the router")
|
log.Fatalln("failed to start/run the router", err)
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,5 +51,5 @@ func handleDiskAlerting() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func recentAverage(values []timestampedValue) int {
|
func recentAverage(values []timestampedValue) int {
|
||||||
return int((values[len(values)-1].Value + values[len(values)-2].Value) / 2)
|
return (values[len(values)-1].Value + values[len(values)-2].Value) / 2
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,12 @@ func Start() error {
|
||||||
http.HandleFunc("/api/emoji", controllers.GetCustomEmoji)
|
http.HandleFunc("/api/emoji", controllers.GetCustomEmoji)
|
||||||
|
|
||||||
// websocket chat server
|
// websocket chat server
|
||||||
go chat.Start()
|
go func() {
|
||||||
|
err := chat.Start()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// chat rest api
|
// chat rest api
|
||||||
http.HandleFunc("/api/chat", controllers.GetChatMessages)
|
http.HandleFunc("/api/chat", controllers.GetChatMessages)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5" //nolint
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -18,9 +18,8 @@ func GenerateClientIDFromRequest(req *http.Request) string {
|
||||||
clientID := strings.Join(ipAddressComponents, ":") + req.UserAgent()
|
clientID := strings.Join(ipAddressComponents, ":") + req.UserAgent()
|
||||||
|
|
||||||
// Create a MD5 hash of this ip + useragent
|
// Create a MD5 hash of this ip + useragent
|
||||||
hasher := md5.New()
|
b := md5.Sum([]byte(clientID)) // nolint
|
||||||
hasher.Write([]byte(clientID))
|
return hex.EncodeToString(b[:])
|
||||||
return hex.EncodeToString(hasher.Sum(nil))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetIPAddressFromRequest returns the IP address from a http request.
|
// GetIPAddressFromRequest returns the IP address from a http request.
|
||||||
|
|
|
@ -17,7 +17,7 @@ func (nt *NullTime) Scan(value interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Value implements the driver Valuer interface.
|
// Value implements the driver Value interface.
|
||||||
func (nt NullTime) Value() (driver.Value, error) {
|
func (nt NullTime) Value() (driver.Value, error) {
|
||||||
if !nt.Valid {
|
if !nt.Valid {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -32,3 +32,19 @@ func (nt NullTime) MarshalJSON() ([]byte, error) {
|
||||||
val := fmt.Sprintf("\"%s\"", nt.Time.Format(time.RFC3339))
|
val := fmt.Sprintf("\"%s\"", nt.Time.Format(time.RFC3339))
|
||||||
return []byte(val), nil
|
return []byte(val), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (nt NullTime) UnmarshalJSON(data []byte) error {
|
||||||
|
dateString := string(data)
|
||||||
|
if dateString == "null" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dateStringWithoutQuotes := dateString[1 : len(dateString)-1]
|
||||||
|
parsedDateTime, err := time.Parse(time.RFC3339, dateStringWithoutQuotes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
nt.Time = parsedDateTime
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ func Copy(source, destination string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ioutil.WriteFile(destination, input, 0644)
|
return ioutil.WriteFile(destination, input, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move moves the file to destination.
|
// Move moves the file to destination.
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/owncast/owncast/config"
|
"github.com/owncast/owncast/config"
|
||||||
"github.com/owncast/owncast/utils"
|
"github.com/owncast/owncast/utils"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ypDetailsResponse struct {
|
type ypDetailsResponse struct {
|
||||||
|
@ -41,6 +42,8 @@ func GetYPResponse(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(response)
|
err := json.NewEncoder(w).Encode(response)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
15
yp/yp.go
15
yp/yp.go
|
@ -47,15 +47,9 @@ func NewYP(getStatusFunc func() models.Status) *YP {
|
||||||
// Start is run when a live stream begins to start pinging YP.
|
// Start is run when a live stream begins to start pinging YP.
|
||||||
func (yp *YP) Start() {
|
func (yp *YP) Start() {
|
||||||
yp.timer = time.NewTicker(pingInterval)
|
yp.timer = time.NewTicker(pingInterval)
|
||||||
|
for range yp.timer.C {
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-yp.timer.C:
|
|
||||||
yp.ping()
|
yp.ping()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
yp.ping()
|
yp.ping()
|
||||||
}
|
}
|
||||||
|
@ -92,7 +86,7 @@ func (yp *YP) ping() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pingURL := config.Config.GetYPServiceHost() + "/ping"
|
pingURL := config.Config.GetYPServiceHost() + "/ping"
|
||||||
resp, err := http.Post(pingURL, "application/json", bytes.NewBuffer(req))
|
resp, err := http.Post(pingURL, "application/json", bytes.NewBuffer(req)) //nolint
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
return
|
return
|
||||||
|
@ -105,7 +99,10 @@ func (yp *YP) ping() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pingResponse := ypPingResponse{}
|
pingResponse := ypPingResponse{}
|
||||||
json.Unmarshal(body, &pingResponse)
|
err = json.Unmarshal(body, &pingResponse)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
|
|
||||||
if !pingResponse.Success {
|
if !pingResponse.Success {
|
||||||
if !_inErrorState {
|
if !_inErrorState {
|
||||||
|
|
Loading…
Reference in a new issue