2019-03-10 16:42:12 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
2019-03-21 21:20:50 +01:00
|
|
|
"os/signal"
|
2019-03-10 16:42:12 +01:00
|
|
|
|
2019-03-26 17:06:25 +01:00
|
|
|
"github.com/gorilla/sessions"
|
2019-03-10 16:42:12 +01:00
|
|
|
"github.com/nareix/joy4/format"
|
|
|
|
"github.com/nareix/joy4/format/rtmp"
|
2019-03-24 23:51:39 +01:00
|
|
|
"github.com/zorchenhimer/MovieNight/common"
|
2019-03-10 16:42:12 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2019-06-02 01:41:28 +02:00
|
|
|
pullEmotes bool
|
|
|
|
addr string
|
2020-06-13 05:58:45 +02:00
|
|
|
rtmpAddr string
|
2019-06-02 01:41:28 +02:00
|
|
|
sKey string
|
|
|
|
stats = newStreamStats()
|
2020-04-18 22:02:41 +02:00
|
|
|
sAdminPass string
|
2019-03-10 16:42:12 +01:00
|
|
|
)
|
|
|
|
|
2019-03-26 16:44:19 +01:00
|
|
|
func setupSettings() error {
|
2019-03-25 04:54:24 +01:00
|
|
|
var err error
|
|
|
|
settings, err = LoadSettings("settings.json")
|
|
|
|
if err != nil {
|
2019-03-26 16:44:19 +01:00
|
|
|
return fmt.Errorf("Unable to load settings: %s", err)
|
2019-03-25 04:54:24 +01:00
|
|
|
}
|
|
|
|
if len(settings.StreamKey) == 0 {
|
2019-03-26 16:44:19 +01:00
|
|
|
return fmt.Errorf("Missing stream key is settings.json")
|
2019-03-25 04:54:24 +01:00
|
|
|
}
|
2019-03-21 21:20:50 +01:00
|
|
|
|
2020-04-18 22:02:41 +02:00
|
|
|
if sAdminPass != "" {
|
|
|
|
fmt.Println("Password provided at runtime; ignoring password in set in settings.")
|
|
|
|
settings.AdminPassword = sAdminPass
|
|
|
|
}
|
|
|
|
|
2019-03-26 17:06:25 +01:00
|
|
|
sstore = sessions.NewCookieStore([]byte(settings.SessionKey))
|
|
|
|
sstore.Options = &sessions.Options{
|
|
|
|
Path: "/",
|
|
|
|
MaxAge: 60 * 60 * 24, // one day
|
|
|
|
SameSite: http.SameSiteStrictMode,
|
|
|
|
}
|
|
|
|
|
2019-03-26 16:44:19 +01:00
|
|
|
return nil
|
2019-03-10 16:42:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
2020-06-13 05:58:45 +02:00
|
|
|
flag.StringVar(&addr, "l", "", "host:port of the HTTP server")
|
|
|
|
flag.StringVar(&rtmpAddr, "r", "", "host:port of the RTMP server")
|
2019-03-25 04:54:24 +01:00
|
|
|
flag.StringVar(&sKey, "k", "", "Stream key, to protect your stream")
|
2020-04-18 22:02:41 +02:00
|
|
|
flag.StringVar(&sAdminPass, "a", "", "Set admin password. Overrides configuration in settings.json. This will not write the password to settings.json.")
|
2019-06-02 01:41:28 +02:00
|
|
|
flag.BoolVar(&pullEmotes, "e", false, "Pull emotes")
|
2019-03-10 16:42:12 +01:00
|
|
|
flag.Parse()
|
|
|
|
|
2019-03-25 04:54:24 +01:00
|
|
|
format.RegisterAll()
|
|
|
|
|
2019-03-26 16:44:19 +01:00
|
|
|
if err := setupSettings(); err != nil {
|
|
|
|
fmt.Printf("Error loading settings: %v\n", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2019-03-25 04:54:24 +01:00
|
|
|
|
2019-06-02 01:41:28 +02:00
|
|
|
if pullEmotes {
|
|
|
|
common.LogInfoln("Pulling emotes")
|
|
|
|
err := getEmotes(settings.ApprovedEmotes)
|
|
|
|
if err != nil {
|
|
|
|
common.LogErrorf("Error downloading emotes: %+v\n", err)
|
|
|
|
common.LogErrorf("Error downloading emotes: %v\n", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-13 23:29:30 +02:00
|
|
|
if err := common.InitTemplates(); err != nil {
|
|
|
|
common.LogErrorln(err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2019-03-31 06:07:19 +02:00
|
|
|
exit := make(chan bool)
|
|
|
|
go handleInterrupt(exit)
|
|
|
|
|
2019-03-21 21:20:50 +01:00
|
|
|
// Load emotes before starting server.
|
|
|
|
var err error
|
2019-06-02 01:41:28 +02:00
|
|
|
chat, err = newChatRoom()
|
|
|
|
if err != nil {
|
2019-03-24 23:51:39 +01:00
|
|
|
common.LogErrorln(err)
|
2019-03-21 21:20:50 +01:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2019-05-05 19:35:36 +02:00
|
|
|
if addr == "" {
|
2019-03-21 21:20:50 +01:00
|
|
|
addr = settings.ListenAddress
|
|
|
|
}
|
|
|
|
|
2020-06-13 05:58:45 +02:00
|
|
|
if rtmpAddr == "" {
|
|
|
|
rtmpAddr = settings.RtmpListenAddress
|
2019-05-05 19:35:36 +02:00
|
|
|
}
|
|
|
|
|
2019-03-21 21:20:50 +01:00
|
|
|
// A stream key was passed on the command line. Use it, but don't save
|
|
|
|
// it over the stream key in the settings.json file.
|
|
|
|
if sKey != "" {
|
|
|
|
settings.SetTempKey(sKey)
|
|
|
|
}
|
|
|
|
|
2019-03-24 23:51:39 +01:00
|
|
|
common.LogInfoln("Stream key: ", settings.GetStreamKey())
|
|
|
|
common.LogInfoln("Admin password: ", settings.AdminPassword)
|
2020-06-13 05:58:45 +02:00
|
|
|
common.LogInfoln("HTTP server listening on: ", addr)
|
|
|
|
common.LogInfoln("RTMP server listening on: ", rtmpAddr)
|
2019-03-30 21:15:22 +01:00
|
|
|
common.LogInfoln("RoomAccess: ", settings.RoomAccess)
|
|
|
|
common.LogInfoln("RoomAccessPin: ", settings.RoomAccessPin)
|
2019-03-21 21:20:50 +01:00
|
|
|
|
2019-03-31 06:07:19 +02:00
|
|
|
go startServer()
|
|
|
|
go startRmtpServer()
|
|
|
|
|
|
|
|
<-exit
|
|
|
|
}
|
|
|
|
|
|
|
|
func startRmtpServer() {
|
2019-03-21 21:20:50 +01:00
|
|
|
server := &rtmp.Server{
|
|
|
|
HandlePlay: handlePlay,
|
|
|
|
HandlePublish: handlePublish,
|
2020-06-13 05:58:45 +02:00
|
|
|
Addr: rtmpAddr,
|
2019-03-21 21:20:50 +01:00
|
|
|
}
|
2019-03-31 06:07:19 +02:00
|
|
|
err := server.ListenAndServe()
|
|
|
|
if err != nil {
|
|
|
|
// If the server cannot start, don't pretend we can continue.
|
|
|
|
panic("Error trying to start rtmp server: " + err.Error())
|
2019-03-10 16:42:12 +01:00
|
|
|
}
|
2019-03-31 06:07:19 +02:00
|
|
|
}
|
2019-03-10 16:42:12 +01:00
|
|
|
|
2019-03-31 06:07:19 +02:00
|
|
|
func startServer() {
|
|
|
|
// Chat websocket
|
|
|
|
http.HandleFunc("/ws", wsHandler)
|
|
|
|
http.HandleFunc("/static/js/", wsStaticFiles)
|
|
|
|
http.HandleFunc("/static/css/", wsStaticFiles)
|
|
|
|
http.HandleFunc("/static/img/", wsImages)
|
|
|
|
http.HandleFunc("/static/main.wasm", wsWasmFile)
|
|
|
|
http.HandleFunc("/emotes/", wsEmotes)
|
|
|
|
http.HandleFunc("/favicon.ico", wsStaticFiles)
|
|
|
|
http.HandleFunc("/chat", handleIndexTemplate)
|
|
|
|
http.HandleFunc("/video", handleIndexTemplate)
|
|
|
|
http.HandleFunc("/help", handleHelpTemplate)
|
2019-03-31 06:09:42 +02:00
|
|
|
http.HandleFunc("/pin", handlePin)
|
2019-11-29 18:48:17 +01:00
|
|
|
http.HandleFunc("/emotes", handleEmoteTemplate)
|
2019-03-31 06:07:19 +02:00
|
|
|
|
|
|
|
http.HandleFunc("/", handleDefault)
|
|
|
|
|
|
|
|
err := http.ListenAndServe(addr, nil)
|
|
|
|
if err != nil {
|
|
|
|
// If the server cannot start, don't pretend we can continue.
|
|
|
|
panic("Error trying to start chat/http server: " + err.Error())
|
|
|
|
}
|
|
|
|
}
|
2019-03-26 16:41:31 +01:00
|
|
|
|
2019-03-31 06:07:19 +02:00
|
|
|
func handleInterrupt(exit chan bool) {
|
|
|
|
ch := make(chan os.Signal)
|
|
|
|
signal.Notify(ch, os.Interrupt)
|
|
|
|
<-ch
|
|
|
|
common.LogInfoln("Closing server")
|
|
|
|
if settings.StreamStats {
|
|
|
|
stats.Print()
|
|
|
|
}
|
|
|
|
exit <- true
|
2019-03-10 16:42:12 +01:00
|
|
|
}
|