|
|
|
@ -46,6 +46,7 @@ type appContext struct {
|
|
|
|
|
info, debug, err *log.Logger
|
|
|
|
|
host string
|
|
|
|
|
port int
|
|
|
|
|
version string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func GenerateSecret(length int) (string, error) {
|
|
|
|
@ -103,7 +104,7 @@ func main() {
|
|
|
|
|
port := flag.Int("port", 0, "alternate port to host web ui on.")
|
|
|
|
|
|
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
|
|
fmt.Println(*dataPath, *configPath, *host, *port)
|
|
|
|
|
if ctx.config_path == *configPath && ctx.data_path != *dataPath {
|
|
|
|
|
ctx.config_path = filepath.Join(*dataPath, "config.ini")
|
|
|
|
|
} else {
|
|
|
|
@ -111,12 +112,24 @@ func main() {
|
|
|
|
|
ctx.data_path = *dataPath
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//var firstRun bool
|
|
|
|
|
// Env variables are necessary because syscall.Exec for self-restarts doesn't doesn't work with arguments for some reason.
|
|
|
|
|
|
|
|
|
|
if v := os.Getenv("JFA_CONFIGPATH"); v != "" {
|
|
|
|
|
ctx.config_path = v
|
|
|
|
|
}
|
|
|
|
|
if v := os.Getenv("JFA_DATAPATH"); v != "" {
|
|
|
|
|
ctx.data_path = v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
os.Setenv("JFA_CONFIGPATH", ctx.config_path)
|
|
|
|
|
os.Setenv("JFA_DATAPATH", ctx.data_path)
|
|
|
|
|
|
|
|
|
|
var firstRun bool
|
|
|
|
|
if _, err := os.Stat(ctx.data_path); os.IsNotExist(err) {
|
|
|
|
|
os.Mkdir(ctx.data_path, 0700)
|
|
|
|
|
}
|
|
|
|
|
if _, err := os.Stat(ctx.config_path); os.IsNotExist(err) {
|
|
|
|
|
//firstRun = true
|
|
|
|
|
firstRun = true
|
|
|
|
|
dConfigPath := filepath.Join(ctx.local_path, "config-default.ini")
|
|
|
|
|
var dConfig *os.File
|
|
|
|
|
dConfig, err = os.Open(dConfigPath)
|
|
|
|
@ -136,11 +149,21 @@ func main() {
|
|
|
|
|
}
|
|
|
|
|
ctx.info.Printf("Copied default configuration to \"%s\"", ctx.config_path)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var debugMode bool
|
|
|
|
|
var address string
|
|
|
|
|
if ctx.loadConfig() != nil {
|
|
|
|
|
ctx.err.Fatalf("Failed to load config file \"%s\"", ctx.config_path)
|
|
|
|
|
}
|
|
|
|
|
ctx.version = ctx.config.Section("jellyfin").Key("version").String()
|
|
|
|
|
|
|
|
|
|
debugMode = ctx.config.Section("ui").Key("debug").MustBool(true)
|
|
|
|
|
if debugMode {
|
|
|
|
|
ctx.debug = log.New(os.Stdout, "[DEBUG] ", log.Ltime|log.Lshortfile)
|
|
|
|
|
} else {
|
|
|
|
|
ctx.debug = log.New(ioutil.Discard, "", 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !firstRun {
|
|
|
|
|
ctx.host = ctx.config.Section("ui").Key("host").String()
|
|
|
|
|
ctx.port = ctx.config.Section("ui").Key("port").MustInt(8056)
|
|
|
|
|
|
|
|
|
@ -151,14 +174,18 @@ func main() {
|
|
|
|
|
ctx.port = *port
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
address := fmt.Sprintf("%s:%d", ctx.host, ctx.port)
|
|
|
|
|
|
|
|
|
|
debugMode := ctx.config.Section("ui").Key("debug").MustBool(true)
|
|
|
|
|
if debugMode {
|
|
|
|
|
ctx.debug = log.New(os.Stdout, "[DEBUG] ", log.Ltime|log.Lshortfile)
|
|
|
|
|
} else {
|
|
|
|
|
ctx.debug = log.New(ioutil.Discard, "", 0)
|
|
|
|
|
if h := os.Getenv("JFA_HOST"); h != "" {
|
|
|
|
|
ctx.host = h
|
|
|
|
|
if p := os.Getenv("JFA_PORT"); p != "" {
|
|
|
|
|
var port int
|
|
|
|
|
_, err := fmt.Sscan(p, &port)
|
|
|
|
|
if err == nil {
|
|
|
|
|
ctx.port = port
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
address = fmt.Sprintf("%s:%d", ctx.host, ctx.port)
|
|
|
|
|
|
|
|
|
|
ctx.debug.Printf("Loaded config file \"%s\"", ctx.config_path)
|
|
|
|
|
|
|
|
|
@ -214,14 +241,14 @@ func main() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server := ctx.config.Section("jellyfin").Key("server").String()
|
|
|
|
|
ctx.jf.init(server, "jfa-go", "0.1", "hrfee-arch", "hrfee-arch")
|
|
|
|
|
ctx.jf.init(server, "jfa-go", ctx.version, "hrfee-arch", "hrfee-arch")
|
|
|
|
|
var status int
|
|
|
|
|
_, status, err = ctx.jf.authenticate(ctx.config.Section("jellyfin").Key("username").String(), ctx.config.Section("jellyfin").Key("password").String())
|
|
|
|
|
if status != 200 || err != nil {
|
|
|
|
|
ctx.err.Fatalf("Failed to authenticate with Jellyfin @ %s: Code %d", server, status)
|
|
|
|
|
}
|
|
|
|
|
ctx.info.Printf("Authenticated with %s", server)
|
|
|
|
|
ctx.authJf.init(server, "jfa-go", "0.1", "auth", "auth")
|
|
|
|
|
ctx.authJf.init(server, "jfa-go", ctx.version, "auth", "auth")
|
|
|
|
|
|
|
|
|
|
ctx.loadStrftime()
|
|
|
|
|
|
|
|
|
@ -247,6 +274,11 @@ func main() {
|
|
|
|
|
if ctx.config.Section("password_resets").Key("enabled").MustBool(false) {
|
|
|
|
|
go ctx.StartPWR()
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
debugMode = false
|
|
|
|
|
gin.SetMode(gin.ReleaseMode)
|
|
|
|
|
address = "0.0.0.0:8056"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx.info.Println("Loading routes")
|
|
|
|
|
router := gin.New()
|
|
|
|
@ -255,13 +287,14 @@ func main() {
|
|
|
|
|
|
|
|
|
|
router.Use(gin.Recovery())
|
|
|
|
|
router.Use(static.Serve("/", static.LocalFile("data/static", false)))
|
|
|
|
|
router.Use(static.Serve("/invite/", static.LocalFile("data/static", false)))
|
|
|
|
|
router.LoadHTMLGlob("data/templates/*")
|
|
|
|
|
router.NoRoute(ctx.NoRouteHandler)
|
|
|
|
|
if !firstRun {
|
|
|
|
|
router.GET("/", ctx.AdminPage)
|
|
|
|
|
router.GET("/getToken", ctx.GetToken)
|
|
|
|
|
router.POST("/newUser", ctx.NewUser)
|
|
|
|
|
router.GET("/invite/:invCode", ctx.InviteProxy)
|
|
|
|
|
router.NoRoute(ctx.NoRouteHandler)
|
|
|
|
|
router.Use(static.Serve("/invite/", static.LocalFile("data/static", false)))
|
|
|
|
|
api := router.Group("/", ctx.webAuth())
|
|
|
|
|
api.POST("/generateInvite", ctx.GenerateInvite)
|
|
|
|
|
api.GET("/getInvites", ctx.GetInvites)
|
|
|
|
@ -273,5 +306,13 @@ func main() {
|
|
|
|
|
api.GET("/getConfig", ctx.GetConfig)
|
|
|
|
|
api.POST("/modifyConfig", ctx.ModifyConfig)
|
|
|
|
|
ctx.info.Printf("Starting router @ %s", address)
|
|
|
|
|
} else {
|
|
|
|
|
router.GET("/", func(gc *gin.Context) {
|
|
|
|
|
gc.HTML(200, "setup.html", gin.H{})
|
|
|
|
|
})
|
|
|
|
|
router.POST("/testJF", ctx.TestJF)
|
|
|
|
|
router.POST("/modifyConfig", ctx.ModifyConfig)
|
|
|
|
|
ctx.info.Printf("Loading setup @ %s", address)
|
|
|
|
|
}
|
|
|
|
|
router.Run(address)
|
|
|
|
|
}
|
|
|
|
|