refactor; move logger to module

This commit is contained in:
Harvey Tindall 2021-05-01 00:13:57 +01:00
parent 570e3a1e54
commit 9944cc2db9
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
7 changed files with 143 additions and 117 deletions

69
api.go
View File

@ -1468,37 +1468,38 @@ func (app *appContext) SetEmail(gc *gin.Context) {
respondBool(400, false, gc)
return
}
if id == "UserCreated" {
switch id {
case "UserCreated":
app.storage.customEmails.UserCreated.Content = req.Content
app.storage.customEmails.UserCreated.Enabled = true
} else if id == "InviteExpiry" {
case "InviteExpiry":
app.storage.customEmails.InviteExpiry.Content = req.Content
app.storage.customEmails.InviteExpiry.Enabled = true
} else if id == "PasswordReset" {
case "PasswordReset":
app.storage.customEmails.PasswordReset.Content = req.Content
app.storage.customEmails.PasswordReset.Enabled = true
} else if id == "UserDeleted" {
case "UserDeleted":
app.storage.customEmails.UserDeleted.Content = req.Content
app.storage.customEmails.UserDeleted.Enabled = true
} else if id == "UserDisabled" {
case "UserDisabled":
app.storage.customEmails.UserDisabled.Content = req.Content
app.storage.customEmails.UserDisabled.Enabled = true
} else if id == "UserEnabled" {
case "UserEnabled":
app.storage.customEmails.UserEnabled.Content = req.Content
app.storage.customEmails.UserEnabled.Enabled = true
} else if id == "InviteEmail" {
case "InviteEmail":
app.storage.customEmails.InviteEmail.Content = req.Content
app.storage.customEmails.InviteEmail.Enabled = true
} else if id == "WelcomeEmail" {
case "WelcomeEmail":
app.storage.customEmails.WelcomeEmail.Content = req.Content
app.storage.customEmails.WelcomeEmail.Enabled = true
} else if id == "EmailConfirmation" {
case "EmailConfirmation":
app.storage.customEmails.EmailConfirmation.Content = req.Content
app.storage.customEmails.EmailConfirmation.Enabled = true
} else if id == "UserExpired" {
case "UserExpired":
app.storage.customEmails.UserExpired.Content = req.Content
app.storage.customEmails.UserExpired.Enabled = true
} else {
default:
respondBool(400, false, gc)
return
}
@ -1525,27 +1526,28 @@ func (app *appContext) SetEmailState(gc *gin.Context) {
} else if s != "disable" {
respondBool(400, false, gc)
}
if id == "UserCreated" {
switch id {
case "UserCreated":
app.storage.customEmails.UserCreated.Enabled = enabled
} else if id == "InviteExpiry" {
case "InviteExpiry":
app.storage.customEmails.InviteExpiry.Enabled = enabled
} else if id == "PasswordReset" {
case "PasswordReset":
app.storage.customEmails.PasswordReset.Enabled = enabled
} else if id == "UserDeleted" {
case "UserDeleted":
app.storage.customEmails.UserDeleted.Enabled = enabled
} else if id == "UserDisabled" {
case "UserDisabled":
app.storage.customEmails.UserDisabled.Enabled = enabled
} else if id == "UserEnabled" {
case "UserEnabled":
app.storage.customEmails.UserEnabled.Enabled = enabled
} else if id == "InviteEmail" {
case "InviteEmail":
app.storage.customEmails.InviteEmail.Enabled = enabled
} else if id == "WelcomeEmail" {
case "WelcomeEmail":
app.storage.customEmails.WelcomeEmail.Enabled = enabled
} else if id == "EmailConfirmation" {
case "EmailConfirmation":
app.storage.customEmails.EmailConfirmation.Enabled = enabled
} else if id == "UserExpired" {
case "UserExpired":
app.storage.customEmails.UserExpired.Enabled = enabled
} else {
default:
respondBool(400, false, gc)
return
}
@ -1576,7 +1578,8 @@ func (app *appContext) GetEmail(gc *gin.Context) {
newEmail := false
username := app.storage.lang.Email[lang].Strings.get("username")
emailAddress := app.storage.lang.Email[lang].Strings.get("emailAddress")
if id == "UserCreated" {
switch id {
case "UserCreated":
content = app.storage.customEmails.UserCreated.Content
if content == "" {
newEmail = true
@ -1588,7 +1591,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
writeVars = func(variables []string) { app.storage.customEmails.UserCreated.Variables = variables }
values = app.email.createdValues("xxxxxx", username, emailAddress, Invite{}, app, false)
// app.storage.customEmails.UserCreated = content
} else if id == "InviteExpiry" {
case "InviteExpiry":
content = app.storage.customEmails.InviteExpiry.Content
if content == "" {
newEmail = true
@ -1600,7 +1603,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
writeVars = func(variables []string) { app.storage.customEmails.InviteExpiry.Variables = variables }
values = app.email.expiryValues("xxxxxx", Invite{}, app, false)
// app.storage.customEmails.InviteExpiry = content
} else if id == "PasswordReset" {
case "PasswordReset":
content = app.storage.customEmails.PasswordReset.Content
if content == "" {
newEmail = true
@ -1612,7 +1615,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
writeVars = func(variables []string) { app.storage.customEmails.PasswordReset.Variables = variables }
values = app.email.resetValues(PasswordReset{Pin: "12-34-56", Username: username}, app, false)
// app.storage.customEmails.PasswordReset = content
} else if id == "UserDeleted" {
case "UserDeleted":
content = app.storage.customEmails.UserDeleted.Content
if content == "" {
newEmail = true
@ -1624,7 +1627,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
writeVars = func(variables []string) { app.storage.customEmails.UserDeleted.Variables = variables }
values = app.email.deletedValues(app.storage.lang.Email[lang].Strings.get("reason"), app, false)
// app.storage.customEmails.UserDeleted = content
} else if id == "UserDisabled" {
case "UserDisabled":
content = app.storage.customEmails.UserDisabled.Content
if content == "" {
newEmail = true
@ -1636,7 +1639,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
writeVars = func(variables []string) { app.storage.customEmails.UserDisabled.Variables = variables }
values = app.email.deletedValues(app.storage.lang.Email[lang].Strings.get("reason"), app, false)
// app.storage.customEmails.UserDeleted = content
} else if id == "UserEnabled" {
case "UserEnabled":
content = app.storage.customEmails.UserEnabled.Content
if content == "" {
newEmail = true
@ -1648,7 +1651,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
writeVars = func(variables []string) { app.storage.customEmails.UserEnabled.Variables = variables }
values = app.email.deletedValues(app.storage.lang.Email[lang].Strings.get("reason"), app, false)
// app.storage.customEmails.UserEnabled = content
} else if id == "InviteEmail" {
case "InviteEmail":
content = app.storage.customEmails.InviteEmail.Content
if content == "" {
newEmail = true
@ -1660,7 +1663,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
writeVars = func(variables []string) { app.storage.customEmails.InviteEmail.Variables = variables }
values = app.email.inviteValues("xxxxxx", Invite{}, app, false)
// app.storage.customEmails.InviteEmail = content
} else if id == "WelcomeEmail" {
case "WelcomeEmail":
content = app.storage.customEmails.WelcomeEmail.Content
conditionals = []string{"{yourAccountWillExpire}"}
app.storage.customEmails.WelcomeEmail.Conditionals = conditionals
@ -1676,7 +1679,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
}
// app.storage.customEmails.WelcomeEmail = content
values = app.email.welcomeValues(username, time.Now(), app, false, true)
} else if id == "EmailConfirmation" {
case "EmailConfirmation":
content = app.storage.customEmails.EmailConfirmation.Content
if content == "" {
newEmail = true
@ -1688,7 +1691,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
writeVars = func(variables []string) { app.storage.customEmails.EmailConfirmation.Variables = variables }
values = app.email.confirmationValues("xxxxxx", username, "xxxxxx", app, false)
// app.storage.customEmails.EmailConfirmation = content
} else if id == "UserExpired" {
case "UserExpired":
content = app.storage.customEmails.UserExpired.Content
if content == "" {
newEmail = true
@ -1699,7 +1702,7 @@ func (app *appContext) GetEmail(gc *gin.Context) {
}
writeVars = func(variables []string) { app.storage.customEmails.UserExpired.Variables = variables }
values = app.email.userExpiredValues(app, false)
} else {
default:
respondBool(400, false, gc)
return
}

View File

@ -6,9 +6,75 @@ import (
"flag"
"fmt"
"os"
"path/filepath"
"strings"
)
func (app *appContext) loadArgs(firstCall bool) {
if firstCall {
flag.Usage = helpFunc
help := flag.Bool("help", false, "prints this message.")
flag.BoolVar(help, "h", false, "SHORTHAND")
DATA = flag.String("data", app.dataPath, "alternate path to data directory.")
flag.StringVar(DATA, "d", app.dataPath, "SHORTHAND")
CONFIG = flag.String("config", app.configPath, "alternate path to config file.")
flag.StringVar(CONFIG, "c", app.configPath, "SHORTHAND")
HOST = flag.String("host", "", "alternate address to host web ui on.")
PORT = flag.Int("port", 0, "alternate port to host web ui on.")
flag.IntVar(PORT, "p", 0, "SHORTHAND")
DEBUG = flag.Bool("debug", false, "Enables debug logging.")
PPROF = flag.Bool("pprof", false, "Exposes pprof profiler on /debug/pprof.")
SWAGGER = flag.Bool("swagger", false, "Enable swagger at /swagger/index.html")
flag.Parse()
if *help {
flag.Usage()
os.Exit(0)
}
if *SWAGGER {
os.Setenv("SWAGGER", "1")
}
if *DEBUG {
os.Setenv("DEBUG", "1")
}
if *PPROF {
os.Setenv("PPROF", "1")
}
}
if os.Getenv("SWAGGER") == "1" {
*SWAGGER = true
}
if os.Getenv("DEBUG") == "1" {
*DEBUG = true
}
if os.Getenv("PPROF") == "1" {
*PPROF = true
}
// attempt to apply command line flags correctly
if app.configPath == *CONFIG && app.dataPath != *DATA {
app.dataPath = *DATA
app.configPath = filepath.Join(app.dataPath, "config.ini")
} else if app.configPath != *CONFIG && app.dataPath == *DATA {
app.configPath = *CONFIG
} else {
app.configPath = *CONFIG
app.dataPath = *DATA
}
// Previously used for self-restarts but leaving them here as they might be useful.
if v := os.Getenv("JFA_CONFIGPATH"); v != "" {
app.configPath = v
}
if v := os.Getenv("JFA_DATAPATH"); v != "" {
app.dataPath = v
}
os.Setenv("JFA_CONFIGPATH", app.configPath)
os.Setenv("JFA_DATAPATH", app.dataPath)
}
/* Adds start/stop/systemd to help message, and
also gets rid of usage for shorthand flags, and merge them with the full-length one.
implementation is 🤢, will clean this up eventually.

3
go.mod
View File

@ -8,6 +8,8 @@ replace github.com/hrfee/jfa-go/common => ./common
replace github.com/hrfee/jfa-go/ombi => ./ombi
replace github.com/hrfee/jfa-go/logger => ./logger
require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fatih/color v1.10.0
@ -24,6 +26,7 @@ require (
github.com/google/uuid v1.1.2 // indirect
github.com/hrfee/jfa-go/common v0.0.0-20210105184019-fdc97b4e86cc
github.com/hrfee/jfa-go/docs v0.0.0-20201112212552-b6f3cd7c1f71
github.com/hrfee/jfa-go/logger v0.0.0-00010101000000-000000000000 // indirect
github.com/hrfee/jfa-go/ombi v0.0.0-20201112212552-b6f3cd7c1f71
github.com/hrfee/mediabrowser v0.3.3
github.com/itchyny/timefmt-go v0.1.2

5
logger/go.mod Normal file
View File

@ -0,0 +1,5 @@
module github.com/hrfee/jfa-go/logger
go 1.16
require github.com/fatih/color v1.10.0

9
logger/go.sum Normal file
View File

@ -0,0 +1,9 @@
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -1,4 +1,5 @@
package main
// Package logger provides a wrapper around log that adds color support with github.com/fatih/color.
package logger
import (
"io"
@ -99,10 +100,10 @@ func (l logger) Fatalf(format string, v ...interface{}) {
l.logger.Fatal(out)
}
type emptyLogger bool
type EmptyLogger bool
func (l emptyLogger) Printf(format string, v ...interface{}) {}
func (l emptyLogger) Print(v ...interface{}) {}
func (l emptyLogger) Println(v ...interface{}) {}
func (l emptyLogger) Fatal(v ...interface{}) {}
func (l emptyLogger) Fatalf(format string, v ...interface{}) {}
func (l EmptyLogger) Printf(format string, v ...interface{}) {}
func (l EmptyLogger) Print(v ...interface{}) {}
func (l EmptyLogger) Println(v ...interface{}) {}
func (l EmptyLogger) Fatal(v ...interface{}) {}
func (l EmptyLogger) Fatalf(format string, v ...interface{}) {}

93
main.go
View File

@ -5,7 +5,6 @@ import (
"crypto/rand"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io/fs"
"log"
@ -24,6 +23,7 @@ import (
"github.com/fatih/color"
"github.com/hrfee/jfa-go/common"
_ "github.com/hrfee/jfa-go/docs"
"github.com/hrfee/jfa-go/logger"
"github.com/hrfee/jfa-go/ombi"
"github.com/hrfee/mediabrowser"
"github.com/lithammer/shortuuid/v3"
@ -93,7 +93,7 @@ type appContext struct {
storage Storage
validator Validator
email *Emailer
info, debug, err Logger
info, debug, err logger.Logger
host string
port int
version string
@ -165,71 +165,10 @@ func start(asDaemon, firstCall bool) {
fs: localFS,
}
app.info = NewLogger(os.Stdout, "[INFO] ", log.Ltime, color.FgHiWhite)
app.err = NewLogger(os.Stdout, "[ERROR] ", log.Ltime, color.FgRed)
app.info = logger.NewLogger(os.Stdout, "[INFO] ", log.Ltime, color.FgHiWhite)
app.err = logger.NewLogger(os.Stdout, "[ERROR] ", log.Ltime|log.Lshortfile, color.FgRed)
if firstCall {
flag.Usage = helpFunc
help := flag.Bool("help", false, "prints this message.")
flag.BoolVar(help, "h", false, "SHORTHAND")
DATA = flag.String("data", app.dataPath, "alternate path to data directory.")
flag.StringVar(DATA, "d", app.dataPath, "SHORTHAND")
CONFIG = flag.String("config", app.configPath, "alternate path to config file.")
flag.StringVar(CONFIG, "c", app.configPath, "SHORTHAND")
HOST = flag.String("host", "", "alternate address to host web ui on.")
PORT = flag.Int("port", 0, "alternate port to host web ui on.")
flag.IntVar(PORT, "p", 0, "SHORTHAND")
DEBUG = flag.Bool("debug", false, "Enables debug logging.")
PPROF = flag.Bool("pprof", false, "Exposes pprof profiler on /debug/pprof.")
SWAGGER = flag.Bool("swagger", false, "Enable swagger at /swagger/index.html")
flag.Parse()
if *help {
flag.Usage()
os.Exit(0)
}
if *SWAGGER {
os.Setenv("SWAGGER", "1")
}
if *DEBUG {
os.Setenv("DEBUG", "1")
}
if *PPROF {
os.Setenv("PPROF", "1")
}
}
if os.Getenv("SWAGGER") == "1" {
*SWAGGER = true
}
if os.Getenv("DEBUG") == "1" {
*DEBUG = true
}
if os.Getenv("PPROF") == "1" {
*PPROF = true
}
// attempt to apply command line flags correctly
if app.configPath == *CONFIG && app.dataPath != *DATA {
app.dataPath = *DATA
app.configPath = filepath.Join(app.dataPath, "config.ini")
} else if app.configPath != *CONFIG && app.dataPath == *DATA {
app.configPath = *CONFIG
} else {
app.configPath = *CONFIG
app.dataPath = *DATA
}
// Previously used for self-restarts but leaving them here as they might be useful.
if v := os.Getenv("JFA_CONFIGPATH"); v != "" {
app.configPath = v
}
if v := os.Getenv("JFA_DATAPATH"); v != "" {
app.dataPath = v
}
os.Setenv("JFA_CONFIGPATH", app.configPath)
os.Setenv("JFA_DATAPATH", app.dataPath)
app.loadArgs(firstCall)
var firstRun bool
if _, err := os.Stat(app.dataPath); os.IsNotExist(err) {
@ -256,8 +195,8 @@ func start(asDaemon, firstCall bool) {
var debugMode bool
var address string
if app.loadConfig() != nil {
app.err.Fatalf("Failed to load config file \"%s\"", app.configPath)
if err := app.loadConfig(); err != nil {
app.err.Fatalf("Failed to load config file \"%s\": %v", app.configPath, err)
}
app.version = app.config.Section("jellyfin").Key("version").String()
// read from config...
@ -267,9 +206,9 @@ func start(asDaemon, firstCall bool) {
debugMode = true
}
if debugMode {
app.debug = NewLogger(os.Stdout, "[DEBUG] ", log.Ltime|log.Lshortfile, color.FgYellow)
app.debug = logger.NewLogger(os.Stdout, "[DEBUG] ", log.Ltime|log.Lshortfile, color.FgYellow)
} else {
app.debug = emptyLogger(false)
app.debug = logger.EmptyLogger(false)
}
if *PPROF {
app.info.Print(warning("\n\nWARNING: Don't use pprof in production.\n\n"))
@ -278,9 +217,8 @@ func start(asDaemon, firstCall bool) {
// Starts listener to receive commands over a unix socket. Use with 'jfa-go start/stop'
if asDaemon {
go func() {
socket := SOCK
os.Remove(socket)
listener, err := net.Listen("unix", socket)
os.Remove(SOCK)
listener, err := net.Listen("unix", SOCK)
if err != nil {
app.err.Fatalf("Couldn't establish socket connection at %s\n", SOCK)
}
@ -288,7 +226,7 @@ func start(asDaemon, firstCall bool) {
signal.Notify(c, os.Interrupt)
go func() {
<-c
os.Remove(socket)
os.Remove(SOCK)
os.Exit(1)
}()
defer func() {
@ -298,13 +236,13 @@ func start(asDaemon, firstCall bool) {
for {
con, err := listener.Accept()
if err != nil {
app.err.Printf("Couldn't read message on %s: %s", socket, err)
app.err.Printf("Couldn't read message on %s: %s", SOCK, err)
continue
}
buf := make([]byte, 512)
nr, err := con.Read(buf)
if err != nil {
app.err.Printf("Couldn't read message on %s: %s", socket, err)
app.err.Printf("Couldn't read message on %s: %s", SOCK, err)
continue
}
command := string(buf[0:nr])
@ -390,6 +328,7 @@ func start(asDaemon, firstCall bool) {
app.storage.profiles_path = app.config.Section("files").Key("user_profiles").String()
app.storage.loadProfiles()
// Migrate from pre-0.2.0 user templates to profiles
if !(app.storage.policy.BlockedTags == nil && app.storage.configuration.GroupedFolders == nil && len(app.storage.displayprefs) == 0) {
app.info.Println("Migrating user template files to new profile format")
app.storage.migrateToProfile()
@ -428,7 +367,7 @@ func start(asDaemon, firstCall bool) {
"Jellyfin (Dark)": "dark-theme",
"Default (Light)": "light-theme",
}
// For move from Bootstrap to a17t
// For move from Bootstrap to a17t (0.2.5)
if app.config.Section("ui").Key("theme").String() == "Bootstrap (Light)" {
app.config.Section("ui").Key("theme").SetValue("Default (Light)")
}