mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-29 12:30:11 +00:00
Compare commits
3 Commits
84a556dc19
...
8fcb76cf97
Author | SHA1 | Date | |
---|---|---|---|
8fcb76cf97 | |||
c54e4811df | |||
4c6a9e9ad8 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,5 +6,6 @@ data/
|
||||
version.go
|
||||
notes
|
||||
docs/*
|
||||
lang/langtostruct.py
|
||||
config-payload.json
|
||||
!docs/go.mod
|
||||
|
@ -1,6 +1,6 @@
|
||||
# ![jfa-go](images/banner.svg)
|
||||
|
||||
jfa-go is a user management app for [Jellyfin](https://github.com/jellyfin/jellyfin) that provides invite-based account creation as well as other features that make one's instance much easier to manage.
|
||||
jfa-go is a user management app for [Jellyfin](https://github.com/jellyfin/jellyfin) (and now [Emby](https://emby.media/)) that provides invite-based account creation as well as other features that make one's instance much easier to manage.
|
||||
|
||||
I chose to rewrite the python [jellyfin-accounts](https://github.com/hrfee/jellyfin-accounts) in Go mainly as a learning experience, but also to slightly improve speeds and efficiency.
|
||||
|
||||
|
1
api.go
1
api.go
@ -1050,6 +1050,7 @@ func (app *appContext) ApplySettings(gc *gin.Context) {
|
||||
"homescreen": map[string]string{},
|
||||
}
|
||||
for _, id := range req.ApplyTo {
|
||||
fmt.Printf("%+v\n", policy)
|
||||
status, err := app.jf.SetPolicy(id, policy)
|
||||
if !(status == 200 || status == 204) || err != nil {
|
||||
errors["policy"][id] = fmt.Sprintf("%d: %s", status, err)
|
||||
|
@ -82,5 +82,7 @@ func (app *appContext) loadConfig() error {
|
||||
|
||||
app.email = NewEmailer(app)
|
||||
|
||||
substituteStrings = app.config.Section("jellyfin").Key("substitute_jellyfin_strings").MustString("")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -65,7 +65,15 @@
|
||||
"emby"
|
||||
],
|
||||
"value": "jellyfin",
|
||||
"description": "Media server type."
|
||||
"description": "Note: Emby integration works is missing some features, such as Password Resets."
|
||||
},
|
||||
"substitute_jellyfin_strings": {
|
||||
"name": "Substitute occurrences of \"Jellyfin\"",
|
||||
"required": false,
|
||||
"requires_restart": true,
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"description": "Optionally substitute occurrences of \"Jellyfin\" in the account creation form with this. May result in bad grammar."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1,57 +0,0 @@
|
||||
import json
|
||||
|
||||
with open("config-formatted.json", "r") as f:
|
||||
config = json.load(f)
|
||||
|
||||
indent = 0
|
||||
|
||||
|
||||
def writeln(ln):
|
||||
global indent
|
||||
if "}" in ln and "{" not in ln:
|
||||
indent -= 1
|
||||
s.write(("\t" * indent) + ln + "\n")
|
||||
if "{" in ln and "}" not in ln:
|
||||
indent += 1
|
||||
|
||||
|
||||
with open("configStruct.go", "w") as s:
|
||||
writeln("package main")
|
||||
writeln("")
|
||||
writeln("type Metadata struct{")
|
||||
writeln('Name string `json:"name"`')
|
||||
writeln('Description string `json:"description"`')
|
||||
writeln("}")
|
||||
writeln("")
|
||||
writeln("type Config struct{")
|
||||
if "order" in config:
|
||||
writeln('Order []string `json:"order"`')
|
||||
for section in [x for x in config.keys() if x != "order"]:
|
||||
title = "".join([x.title() for x in section.split("_")])
|
||||
writeln(title + " struct{")
|
||||
if "order" in config[section]:
|
||||
writeln('Order []string `json:"order"`')
|
||||
if "meta" in config[section]:
|
||||
writeln('Meta Metadata `json:"meta"`')
|
||||
for setting in [
|
||||
x for x in config[section].keys() if x != "order" and x != "meta"
|
||||
]:
|
||||
name = "".join([x.title() for x in setting.split("_")])
|
||||
writeln(name + " struct{")
|
||||
writeln('Name string `json:"name"`')
|
||||
writeln('Required bool `json:"required"`')
|
||||
writeln('Restart bool `json:"requires_restart"`')
|
||||
writeln('Description string `json:"description"`')
|
||||
writeln('Type string `json:"type"`')
|
||||
dt = config[section][setting]["type"]
|
||||
if dt == "select":
|
||||
dt = "string"
|
||||
writeln('Options []string `json:"options"`')
|
||||
elif dt == "number":
|
||||
dt = "int"
|
||||
elif dt != "bool":
|
||||
dt = "string"
|
||||
writeln(f'Value {dt} `json:"value" cfg:"{setting}"`')
|
||||
writeln("} " + f'`json:"{setting}" cfg:"{setting}"`')
|
||||
writeln("} " + f'`json:"{section}"`')
|
||||
writeln("}")
|
21
main.go
21
main.go
@ -39,6 +39,8 @@ var serverTypes = map[string]string{
|
||||
"jellyfin": "Jellyfin",
|
||||
"emby": "Emby (experimental)",
|
||||
}
|
||||
var serverType = mediabrowser.JellyfinServer
|
||||
var substituteStrings = ""
|
||||
|
||||
// User is used for auth purposes.
|
||||
type User struct {
|
||||
@ -282,12 +284,6 @@ func start(asDaemon, firstCall bool) {
|
||||
if app.loadConfig() != nil {
|
||||
app.err.Fatalf("Failed to load config file \"%s\"", app.configPath)
|
||||
}
|
||||
lang := app.config.Section("ui").Key("language").MustString("en-us")
|
||||
app.storage.lang.FormPath = filepath.Join(app.localPath, "lang", "form", lang+".json")
|
||||
if _, err := os.Stat(app.storage.lang.FormPath); os.IsNotExist(err) {
|
||||
app.storage.lang.FormPath = filepath.Join(app.localPath, "lang", "form", "en-us.json")
|
||||
}
|
||||
app.storage.loadLang()
|
||||
app.version = app.config.Section("jellyfin").Key("version").String()
|
||||
// read from config...
|
||||
debugMode = app.config.Section("ui").Key("debug").MustBool(false)
|
||||
@ -446,13 +442,12 @@ func start(asDaemon, firstCall bool) {
|
||||
server := app.config.Section("jellyfin").Key("server").String()
|
||||
cacheTimeout := int(app.config.Section("jellyfin").Key("cache_timeout").MustUint(30))
|
||||
stringServerType := app.config.Section("jellyfin").Key("type").String()
|
||||
serverType := mediabrowser.JellyfinServer
|
||||
timeoutHandler := common.NewTimeoutHandler("Jellyfin", server, true)
|
||||
if stringServerType == "emby" {
|
||||
serverType = mediabrowser.EmbyServer
|
||||
timeoutHandler = common.NewTimeoutHandler("Emby", server, true)
|
||||
app.info.Println("Using Emby server type")
|
||||
fmt.Println(aurora.Yellow("WARNING: Emby compatibility is experimental, things may not work."))
|
||||
fmt.Println(aurora.Yellow("WARNING: Emby compatibility is experimental, and support is limited.\nPassword resets are not available."))
|
||||
} else {
|
||||
app.info.Println("Using Jellyfin server type")
|
||||
}
|
||||
@ -526,6 +521,14 @@ func start(asDaemon, firstCall bool) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lang := app.config.Section("ui").Key("language").MustString("en-us")
|
||||
app.storage.lang.FormPath = filepath.Join(app.localPath, "lang", "form", lang+".json")
|
||||
if _, err := os.Stat(app.storage.lang.FormPath); os.IsNotExist(err) {
|
||||
app.storage.lang.FormPath = filepath.Join(app.localPath, "lang", "form", "en-us.json")
|
||||
}
|
||||
app.storage.loadLang()
|
||||
|
||||
app.authJf, _ = mediabrowser.NewServer(serverType, server, "jfa-go", app.version, "auth", "auth", timeoutHandler, cacheTimeout)
|
||||
|
||||
app.loadStrftime()
|
||||
@ -552,7 +555,7 @@ func start(asDaemon, firstCall bool) {
|
||||
inviteDaemon := newRepeater(time.Duration(60*time.Second), app)
|
||||
go inviteDaemon.run()
|
||||
|
||||
if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
||||
if app.config.Section("password_resets").Key("enabled").MustBool(false) && serverType == mediabrowser.JellyfinServer {
|
||||
go app.StartPWR()
|
||||
}
|
||||
} else {
|
||||
|
15
storage.go
15
storage.go
@ -58,6 +58,21 @@ func (st *Storage) storeInvites() error {
|
||||
}
|
||||
|
||||
func (st *Storage) loadLang() error {
|
||||
if substituteStrings != "" {
|
||||
var file []byte
|
||||
var err error
|
||||
file, err = ioutil.ReadFile(st.lang.FormPath)
|
||||
if err != nil {
|
||||
file = []byte("{}")
|
||||
}
|
||||
// Replace Jellyfin with emby on form
|
||||
file = []byte(strings.ReplaceAll(string(file), "Jellyfin", substituteStrings))
|
||||
err = json.Unmarshal(file, &st.lang.Form)
|
||||
if err != nil {
|
||||
log.Printf("ERROR: Failed to read \"%s\": %s", st.lang.FormPath, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
err := loadJSON(st.lang.FormPath, &st.lang.Form)
|
||||
if err != nil {
|
||||
return err
|
||||
|
Loading…
Reference in New Issue
Block a user