Split some settings into new "messages" section

Most email dependant sections now depend on this. Also renamed more
email things.
This commit is contained in:
Harvey Tindall 2021-05-07 21:53:29 +01:00
parent 51f2f4cc6a
commit ea0293bd4e
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
21 changed files with 289 additions and 219 deletions

22
api.go
View File

@ -39,9 +39,9 @@ func respondBool(code int, val bool, gc *gin.Context) {
} }
func (app *appContext) loadStrftime() { func (app *appContext) loadStrftime() {
app.datePattern = app.config.Section("email").Key("date_format").String() app.datePattern = app.config.Section("messages").Key("date_format").String()
app.timePattern = `%H:%M` app.timePattern = `%H:%M`
if val, _ := app.config.Section("email").Key("use_24h").Bool(); !val { if val, _ := app.config.Section("messages").Key("use_24h").Bool(); !val {
app.timePattern = `%I:%M %p` app.timePattern = `%I:%M %p`
} }
return return
@ -331,7 +331,7 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
return return
} }
telegramTokenIndex := -1 telegramTokenIndex := -1
if app.config.Section("telegram").Key("enabled").MustBool(false) { if telegramEnabled {
if req.TelegramPIN == "" { if req.TelegramPIN == "" {
if app.config.Section("telegram").Key("required").MustBool(false) { if app.config.Section("telegram").Key("required").MustBool(false) {
f = func(gc *gin.Context) { f = func(gc *gin.Context) {
@ -480,7 +480,7 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
} }
} }
if app.config.Section("telegram").Key("enabled").MustBool(false) && telegramTokenIndex != -1 { if telegramEnabled && telegramTokenIndex != -1 {
tgToken := app.telegram.verifiedTokens[telegramTokenIndex] tgToken := app.telegram.verifiedTokens[telegramTokenIndex]
tgUser := TelegramUser{ tgUser := TelegramUser{
ChatID: tgToken.ChatID, ChatID: tgToken.ChatID,
@ -579,7 +579,7 @@ func (app *appContext) EnableDisableUsers(gc *gin.Context) {
"GetUser": map[string]string{}, "GetUser": map[string]string{},
"SetPolicy": map[string]string{}, "SetPolicy": map[string]string{},
} }
sendMail := emailEnabled || app.config.Section("telegram").Key("enabled").MustBool(false) sendMail := messagesEnabled
var msg *Message var msg *Message
var err error var err error
if sendMail { if sendMail {
@ -636,7 +636,7 @@ func (app *appContext) DeleteUsers(gc *gin.Context) {
gc.BindJSON(&req) gc.BindJSON(&req)
errors := map[string]string{} errors := map[string]string{}
ombiEnabled := app.config.Section("ombi").Key("enabled").MustBool(false) ombiEnabled := app.config.Section("ombi").Key("enabled").MustBool(false)
sendMail := emailEnabled || app.config.Section("telegram").Key("enabled").MustBool(false) sendMail := messagesEnabled
var msg *Message var msg *Message
var err error var err error
if sendMail { if sendMail {
@ -730,7 +730,7 @@ func (app *appContext) ExtendExpiry(gc *gin.Context) {
func (app *appContext) Announce(gc *gin.Context) { func (app *appContext) Announce(gc *gin.Context) {
var req announcementDTO var req announcementDTO
gc.BindJSON(&req) gc.BindJSON(&req)
if !(emailEnabled || app.config.Section("telegram").Key("enabled").MustBool(false)) { if !messagesEnabled {
respondBool(400, false, gc) respondBool(400, false, gc)
return return
} }
@ -1384,6 +1384,10 @@ func (app *appContext) GetConfig(gc *gin.Context) {
el := resp.Sections["email"].Settings["language"] el := resp.Sections["email"].Settings["language"]
el.Options = emailOptions el.Options = emailOptions
el.Value = app.config.Section("email").Key("language").MustString("en-us") el.Value = app.config.Section("email").Key("language").MustString("en-us")
telegramOptions := app.storage.lang.Email.getOptions()
tl := resp.Sections["telegram"].Settings["language"]
tl.Options = telegramOptions
tl.Value = app.config.Section("telegram").Key("language").MustString("en-us")
if updater == "" { if updater == "" {
delete(resp.Sections, "updates") delete(resp.Sections, "updates")
for i, v := range resp.Order { for i, v := range resp.Order {
@ -1412,6 +1416,7 @@ func (app *appContext) GetConfig(gc *gin.Context) {
resp.Sections["ui"].Settings["language-admin"] = al resp.Sections["ui"].Settings["language-admin"] = al
resp.Sections["email"].Settings["language"] = el resp.Sections["email"].Settings["language"] = el
resp.Sections["password_resets"].Settings["language"] = pl resp.Sections["password_resets"].Settings["language"] = pl
resp.Sections["telegram"].Settings["language"] = tl
gc.JSON(200, resp) gc.JSON(200, resp)
} }
@ -1436,6 +1441,9 @@ func (app *appContext) ModifyConfig(gc *gin.Context) {
tempConfig.NewSection(section) tempConfig.NewSection(section)
} }
for setting, value := range settings.(map[string]interface{}) { for setting, value := range settings.(map[string]interface{}) {
if section == "email" && setting == "method" && value == "disabled" {
value = ""
}
if value.(string) != app.config.Section(section).Key(setting).MustString("") { if value.(string) != app.config.Section(section).Key(setting).MustString("") {
tempConfig.Section(section).Key(setting).SetValue(value.(string)) tempConfig.Section(section).Key(setting).SetValue(value.(string))
} }

View File

@ -12,6 +12,8 @@ import (
) )
var emailEnabled = false var emailEnabled = false
var messagesEnabled = false
var telegramEnabled = false
func (app *appContext) GetPath(sect, key string) (fs.FS, string) { func (app *appContext) GetPath(sect, key string) (fs.FS, string) {
val := app.config.Section(sect).Key(key).MustString("") val := app.config.Section(sect).Key(key).MustString("")
@ -83,12 +85,19 @@ func (app *appContext) loadConfig() error {
app.config.Section("jellyfin").Key("version").SetValue(version) app.config.Section("jellyfin").Key("version").SetValue(version)
app.config.Section("jellyfin").Key("device").SetValue("jfa-go") app.config.Section("jellyfin").Key("device").SetValue("jfa-go")
app.config.Section("jellyfin").Key("device_id").SetValue(fmt.Sprintf("jfa-go-%s-%s", version, commit)) app.config.Section("jellyfin").Key("device_id").SetValue(fmt.Sprintf("jfa-go-%s-%s", version, commit))
messagesEnabled = app.config.Section("messages").Key("enabled").MustBool(false)
if app.config.Section("email").Key("method").MustString("") == "" { telegramEnabled = app.config.Section("telegram").Key("enabled").MustBool(false)
if !messagesEnabled {
emailEnabled = false
telegramEnabled = false
} else if app.config.Section("email").Key("method").MustString("") == "" {
emailEnabled = false emailEnabled = false
} else { } else {
emailEnabled = true emailEnabled = true
} }
if !emailEnabled && !telegramEnabled {
messagesEnabled = false
}
app.MustSetValue("updates", "enabled", "true") app.MustSetValue("updates", "enabled", "true")
releaseChannel := app.config.Section("updates").Key("channel").String() releaseChannel := app.config.Section("updates").Key("channel").String()
@ -134,3 +143,28 @@ func (app *appContext) loadConfig() error {
return nil return nil
} }
func (app *appContext) migrateEmailConfig() {
tempConfig, _ := ini.Load(app.configPath)
fmt.Println(warning("Part of your email configuration will be migrated to the new \"messages\" section.\nA backup will be made."))
err := tempConfig.SaveTo(app.configPath + "_" + commit + ".bak")
if err != nil {
app.err.Fatalf("Failed to backup config: %v", err)
return
}
for _, setting := range []string{"use_24h", "date_format", "message"} {
if val := app.config.Section("email").Key(setting).Value(); val != "" {
tempConfig.Section("email").Key(setting).SetValue("")
tempConfig.Section("messages").Key(setting).SetValue(val)
}
}
if app.config.Section("messages").Key("enabled").MustBool(false) || app.config.Section("telegram").Key("enabled").MustBool(false) {
tempConfig.Section("messages").Key("enabled").SetValue("true")
}
err = tempConfig.SaveTo(app.configPath)
if err != nil {
app.err.Fatalf("Failed to save config: %v", err)
return
}
app.loadConfig()
}

View File

@ -345,33 +345,20 @@
} }
} }
}, },
"email": { "messages": {
"order": [], "order": [],
"meta": { "meta": {
"name": "Email", "name": "Messages/Notifications",
"description": "General email settings." "description": "General settings for emails/messages."
}, },
"settings": { "settings": {
"language": { "enabled": {
"name": "Email Language", "name": "Enabled",
"required": false, "required": true,
"requires_restart": false, "requires_restart": true,
"depends_true": "method",
"type": "select",
"options": [
["en-us", "English (US)"]
],
"value": "en-us",
"description": "Default email language. Submit a PR on github if you'd like to translate."
},
"no_username": {
"name": "Use email addresses as username",
"required": false,
"requires_restart": false,
"depends_true": "method",
"type": "bool", "type": "bool",
"value": false, "value": true,
"description": "Use email address from invite form as username on Jellyfin." "description": "Enable the sending of emails/messages such as password resets, announcements, etc."
}, },
"use_24h": { "use_24h": {
"name": "Use 24h time", "name": "Use 24h time",
@ -399,6 +386,37 @@
"type": "text", "type": "text",
"value": "Need help? contact me.", "value": "Need help? contact me.",
"description": "Message displayed at bottom of emails." "description": "Message displayed at bottom of emails."
}
}
},
"email": {
"order": [],
"meta": {
"name": "Email",
"description": "General email settings.",
"depends_true": "messages|enabled"
},
"settings": {
"language": {
"name": "Email Language",
"required": false,
"requires_restart": false,
"depends_true": "method",
"type": "select",
"options": [
["en-us", "English (US)"]
],
"value": "en-us",
"description": "Default email language. Submit a PR on github if you'd like to translate."
},
"no_username": {
"name": "Use email addresses as username",
"required": false,
"requires_restart": false,
"depends_true": "method",
"type": "bool",
"value": false,
"description": "Use email address from invite form as username on Jellyfin."
}, },
"method": { "method": {
"name": "Email method", "name": "Email method",
@ -443,12 +461,143 @@
} }
} }
}, },
"mailgun": {
"order": [],
"meta": {
"name": "Mailgun (Email)",
"description": "Mailgun API connection settings",
"depends_true": "email|method"
},
"settings": {
"api_url": {
"name": "API URL",
"required": false,
"requires_restart": false,
"type": "text",
"value": "https://api.mailgun.net..."
},
"api_key": {
"name": "API Key",
"required": false,
"requires_restart": false,
"type": "text",
"value": "your api key"
}
}
},
"smtp": {
"order": [],
"meta": {
"name": "SMTP (Email)",
"description": "SMTP Server connection settings.",
"depends_true": "email|method"
},
"settings": {
"username": {
"name": "Username",
"required": false,
"requires_restart": false,
"type": "text",
"value": "",
"description": "Username for SMTP. Leave blank to user send from address as username."
},
"encryption": {
"name": "Encryption Method",
"required": false,
"requires_restart": false,
"type": "select",
"options": [
["ssl_tls", "SSL/TLS"],
["starttls", "STARTTLS"]
],
"value": "starttls",
"description": "Your email provider should provide different ports for each encryption method. Generally 465 for ssl_tls, 587 for starttls."
},
"server": {
"name": "Server address",
"required": false,
"requires_restart": false,
"type": "text",
"value": "smtp.jellyf.in",
"description": "SMTP Server address."
},
"port": {
"name": "Port",
"required": false,
"requires_restart": false,
"type": "number",
"value": 465
},
"password": {
"name": "Password",
"required": false,
"requires_restart": false,
"type": "password",
"value": "smtp password"
},
"ssl_cert": {
"name": "Path to custom SSL certificate",
"required": false,
"requires_restart": false,
"advanced": true,
"type": "text",
"value": "",
"description": "Use if your SMTP server's SSL Certificate is not trusted by the system."
}
}
},
"telegram": {
"order": [],
"meta": {
"name": "Telegram",
"description": "Settings for Telegram signup/notifications"
},
"settings": {
"enabled": {
"name": "Enabled",
"required": false,
"requires_restart": true,
"type": "bool",
"value": false,
"description": "Enable signup verification through Telegram and the sending of notifications through it."
},
"required": {
"name": "Require on sign-up",
"required": false,
"required_restart": true,
"type": "bool",
"value": false,
"description": "Require telegram connection on sign-up."
},
"token": {
"name": "API Token",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "Telegram Bot API Token."
},
"language": {
"name": "Language",
"required": false,
"requires_restart": false,
"depends_true": "enabled",
"type": "select",
"options": [
["en-us", "English (US)"]
],
"value": "en-us",
"description": "Default telegram message language. Visit weblate if you'd like to translate."
}
}
},
"password_resets": { "password_resets": {
"order": [], "order": [],
"meta": { "meta": {
"name": "Password Resets", "name": "Password Resets",
"description": "Settings for the password reset handler.", "description": "Settings for the password reset handler.",
"depends_true": "email|method" "depends_true": "messages|enabled"
}, },
"settings": { "settings": {
"enabled": { "enabled": {
@ -580,7 +729,7 @@
"meta": { "meta": {
"name": "Notifications", "name": "Notifications",
"description": "Notification related settings.", "description": "Notification related settings.",
"depends_true": "email|method" "depends_true": "messages|enabled"
}, },
"settings": { "settings": {
"enabled": { "enabled": {
@ -633,91 +782,6 @@
} }
} }
}, },
"mailgun": {
"order": [],
"meta": {
"name": "Mailgun (Email)",
"description": "Mailgun API connection settings",
"depends_true": "email|method"
},
"settings": {
"api_url": {
"name": "API URL",
"required": false,
"requires_restart": false,
"type": "text",
"value": "https://api.mailgun.net..."
},
"api_key": {
"name": "API Key",
"required": false,
"requires_restart": false,
"type": "text",
"value": "your api key"
}
}
},
"smtp": {
"order": [],
"meta": {
"name": "SMTP (Email)",
"description": "SMTP Server connection settings.",
"depends_true": "email|method"
},
"settings": {
"username": {
"name": "Username",
"required": false,
"requires_restart": false,
"type": "text",
"value": "",
"description": "Username for SMTP. Leave blank to user send from address as username."
},
"encryption": {
"name": "Encryption Method",
"required": false,
"requires_restart": false,
"type": "select",
"options": [
["ssl_tls", "SSL/TLS"],
["starttls", "STARTTLS"]
],
"value": "starttls",
"description": "Your email provider should provide different ports for each encryption method. Generally 465 for ssl_tls, 587 for starttls."
},
"server": {
"name": "Server address",
"required": false,
"requires_restart": false,
"type": "text",
"value": "smtp.jellyf.in",
"description": "SMTP Server address."
},
"port": {
"name": "Port",
"required": false,
"requires_restart": false,
"type": "number",
"value": 465
},
"password": {
"name": "Password",
"required": false,
"requires_restart": false,
"type": "password",
"value": "smtp password"
},
"ssl_cert": {
"name": "Path to custom SSL certificate",
"required": false,
"requires_restart": false,
"advanced": true,
"type": "text",
"value": "",
"description": "Use if your SMTP server's SSL Certificate is not trusted by the system."
}
}
},
"ombi": { "ombi": {
"order": [], "order": [],
"meta": { "meta": {
@ -756,9 +820,9 @@
"welcome_email": { "welcome_email": {
"order": [], "order": [],
"meta": { "meta": {
"name": "Welcome Emails", "name": "Welcome Message",
"description": "Optionally send a welcome email to new users with the Jellyfin URL and their username.", "description": "Optionally send a welcome message to new users with the Jellyfin URL and their username.",
"depends_true": "email|method" "depends_true": "messages|enabled"
}, },
"settings": { "settings": {
"enabled": { "enabled": {
@ -865,14 +929,14 @@
"requires_restart": false, "requires_restart": false,
"type": "bool", "type": "bool",
"value": true, "value": true,
"depends_true": "email|method", "depends_true": "messages|enabled",
"description": "Send an email when a user's account expires." "description": "Send an email when a user's account expires."
}, },
"subject": { "subject": {
"name": "Email subject", "name": "Email subject",
"required": false, "required": false,
"requires_restart": false, "requires_restart": false,
"depends_true": "email|method", "depends_true": "messages|enabled",
"type": "text", "type": "text",
"value": "", "value": "",
"description": "Subject of user expiry emails." "description": "Subject of user expiry emails."
@ -882,7 +946,7 @@
"required": false, "required": false,
"requires_restart": false, "requires_restart": false,
"advanced": true, "advanced": true,
"depends_true": "email|method", "depends_true": "messages|enabled",
"type": "text", "type": "text",
"value": "", "value": "",
"description": "Path to custom email html" "description": "Path to custom email html"
@ -892,7 +956,7 @@
"required": false, "required": false,
"requires_restart": false, "requires_restart": false,
"advanced": true, "advanced": true,
"depends_true": "email|method", "depends_true": "messages|enabled",
"type": "text", "type": "text",
"value": "", "value": "",
"description": "Path to custom email in plain text" "description": "Path to custom email in plain text"
@ -904,7 +968,7 @@
"meta": { "meta": {
"name": "Account Disabling/Enabling", "name": "Account Disabling/Enabling",
"description": "Subject/email files for account disabling/enabling emails.", "description": "Subject/email files for account disabling/enabling emails.",
"depends_true": "email|method" "depends_true": "messages|enabled"
}, },
"settings": { "settings": {
"subject_disabled": { "subject_disabled": {
@ -966,7 +1030,7 @@
"meta": { "meta": {
"name": "Account Deletion", "name": "Account Deletion",
"description": "Subject/email files for account deletion emails.", "description": "Subject/email files for account deletion emails.",
"depends_true": "email|method" "depends_true": "messages|enabled"
}, },
"settings": { "settings": {
"subject": { "subject": {
@ -997,53 +1061,6 @@
} }
} }
}, },
"telegram": {
"order": [],
"meta": {
"name": "Telegram",
"description": "Settings for Telegram signup/notifications"
},
"settings": {
"enabled": {
"name": "Enabled",
"required": false,
"requires_restart": true,
"type": "bool",
"value": false,
"description": "Enable signup verification through Telegram and the sending of notifications through it."
},
"required": {
"name": "Require on sign-up",
"required": false,
"required_restart": true,
"type": "bool",
"value": false,
"description": "Require telegram connection on sign-up."
},
"token": {
"name": "API Token",
"required": false,
"requires_restart": true,
"depends_true": "enabled",
"type": "text",
"value": "",
"description": "Telegram Bot API Token."
},
"language": {
"name": "Language",
"required": false,
"requires_restart": false,
"depends_true": "enabled",
"type": "select",
"options": [
["en-us", "English (US)"]
],
"value": "en-us",
"description": "Default telegram message language. Visit weblate if you'd like to translate."
}
}
},
"files": { "files": {
"order": [], "order": [],
"meta": { "meta": {

View File

@ -289,7 +289,7 @@ func (emailer *Emailer) confirmationValues(code, username, key string, app *appC
template[v] = "{" + v + "}" template[v] = "{" + v + "}"
} }
} else { } else {
message := app.config.Section("email").Key("message").String() message := app.config.Section("messages").Key("message").String()
inviteLink := app.config.Section("invite_emails").Key("url_base").String() inviteLink := app.config.Section("invite_emails").Key("url_base").String()
inviteLink = fmt.Sprintf("%s/%s?key=%s", inviteLink, code, key) inviteLink = fmt.Sprintf("%s/%s?key=%s", inviteLink, code, key)
template["helloUser"] = emailer.lang.Strings.template("helloUser", tmpl{"username": username}) template["helloUser"] = emailer.lang.Strings.template("helloUser", tmpl{"username": username})
@ -327,7 +327,7 @@ func (emailer *Emailer) constructTemplate(subject, md string, app *appContext) (
renderer := html.NewRenderer(html.RendererOptions{Flags: html.Smartypants}) renderer := html.NewRenderer(html.RendererOptions{Flags: html.Smartypants})
html := markdown.ToHTML([]byte(md), nil, renderer) html := markdown.ToHTML([]byte(md), nil, renderer)
text := stripMarkdown(md) text := stripMarkdown(md)
message := app.config.Section("email").Key("message").String() message := app.config.Section("messages").Key("message").String()
var err error var err error
email.HTML, email.Text, email.Markdown, err = emailer.construct(app, "template_email", "email_", map[string]interface{}{ email.HTML, email.Text, email.Markdown, err = emailer.construct(app, "template_email", "email_", map[string]interface{}{
"text": template.HTML(html), "text": template.HTML(html),
@ -344,7 +344,7 @@ func (emailer *Emailer) constructTemplate(subject, md string, app *appContext) (
func (emailer *Emailer) inviteValues(code string, invite Invite, app *appContext, noSub bool) map[string]interface{} { func (emailer *Emailer) inviteValues(code string, invite Invite, app *appContext, noSub bool) map[string]interface{} {
expiry := invite.ValidTill expiry := invite.ValidTill
d, t, expiresIn := emailer.formatExpiry(expiry, false, app.datePattern, app.timePattern) d, t, expiresIn := emailer.formatExpiry(expiry, false, app.datePattern, app.timePattern)
message := app.config.Section("email").Key("message").String() message := app.config.Section("messages").Key("message").String()
inviteLink := app.config.Section("invite_emails").Key("url_base").String() inviteLink := app.config.Section("invite_emails").Key("url_base").String()
inviteLink = fmt.Sprintf("%s/%s", inviteLink, code) inviteLink = fmt.Sprintf("%s/%s", inviteLink, code)
template := map[string]interface{}{ template := map[string]interface{}{
@ -489,7 +489,7 @@ func (emailer *Emailer) constructCreated(code, username, address string, invite
func (emailer *Emailer) resetValues(pwr PasswordReset, app *appContext, noSub bool) map[string]interface{} { func (emailer *Emailer) resetValues(pwr PasswordReset, app *appContext, noSub bool) map[string]interface{} {
d, t, expiresIn := emailer.formatExpiry(pwr.Expiry, true, app.datePattern, app.timePattern) d, t, expiresIn := emailer.formatExpiry(pwr.Expiry, true, app.datePattern, app.timePattern)
message := app.config.Section("email").Key("message").String() message := app.config.Section("messages").Key("message").String()
template := map[string]interface{}{ template := map[string]interface{}{
"someoneHasRequestedReset": emailer.lang.PasswordReset.get("someoneHasRequestedReset"), "someoneHasRequestedReset": emailer.lang.PasswordReset.get("someoneHasRequestedReset"),
"ifItWasNotYou": emailer.lang.Strings.get("ifItWasNotYou"), "ifItWasNotYou": emailer.lang.Strings.get("ifItWasNotYou"),
@ -574,7 +574,7 @@ func (emailer *Emailer) deletedValues(reason string, app *appContext, noSub bool
} }
} else { } else {
template["reason"] = reason template["reason"] = reason
template["message"] = app.config.Section("email").Key("message").String() template["message"] = app.config.Section("messages").Key("message").String()
} }
return template return template
} }
@ -615,7 +615,7 @@ func (emailer *Emailer) disabledValues(reason string, app *appContext, noSub boo
} }
} else { } else {
template["reason"] = reason template["reason"] = reason
template["message"] = app.config.Section("email").Key("message").String() template["message"] = app.config.Section("messages").Key("message").String()
} }
return template return template
} }
@ -656,7 +656,7 @@ func (emailer *Emailer) enabledValues(reason string, app *appContext, noSub bool
} }
} else { } else {
template["reason"] = reason template["reason"] = reason
template["message"] = app.config.Section("email").Key("message").String() template["message"] = app.config.Section("messages").Key("message").String()
} }
return template return template
} }
@ -701,7 +701,7 @@ func (emailer *Emailer) welcomeValues(username string, expiry time.Time, app *ap
} else { } else {
template["jellyfinURL"] = app.config.Section("jellyfin").Key("public_server").String() template["jellyfinURL"] = app.config.Section("jellyfin").Key("public_server").String()
template["username"] = username template["username"] = username
template["message"] = app.config.Section("email").Key("message").String() template["message"] = app.config.Section("messages").Key("message").String()
exp := app.formatDatetime(expiry) exp := app.formatDatetime(expiry)
if !expiry.IsZero() { if !expiry.IsZero() {
if custom { if custom {
@ -756,7 +756,7 @@ func (emailer *Emailer) userExpiredValues(app *appContext, noSub bool) map[strin
"message": "", "message": "",
} }
if !noSub { if !noSub {
template["message"] = app.config.Section("email").Key("message").String() template["message"] = app.config.Section("messages").Key("message").String()
} }
return template return template
} }
@ -790,10 +790,9 @@ func (emailer *Emailer) send(email *Message, address ...string) error {
} }
func (app *appContext) sendByID(email *Message, ID ...string) error { func (app *appContext) sendByID(email *Message, ID ...string) error {
tgEnabled := app.config.Section("telegram").Key("enabled").MustBool(false)
for _, id := range ID { for _, id := range ID {
var err error var err error
if tgChat, ok := app.storage.telegram[id]; ok && tgChat.Contact && tgEnabled { if tgChat, ok := app.storage.telegram[id]; ok && tgChat.Contact && telegramEnabled {
err = app.telegram.Send(email, tgChat.ChatID) err = app.telegram.Send(email, tgChat.ChatID)
} else if address, ok := app.storage.emails[id]; ok { } else if address, ok := app.storage.emails[id]; ok {
err = app.email.send(email, address.(string)) err = app.email.send(email, address.(string))
@ -806,8 +805,7 @@ func (app *appContext) sendByID(email *Message, ID ...string) error {
} }
func (app *appContext) getAddressOrName(jfID string) string { func (app *appContext) getAddressOrName(jfID string) string {
tgEnabled := app.config.Section("telegram").Key("enabled").MustBool(false) if tgChat, ok := app.storage.telegram[jfID]; ok && tgChat.Contact && telegramEnabled {
if tgChat, ok := app.storage.telegram[jfID]; ok && tgChat.Contact && tgEnabled {
return "@" + tgChat.Username return "@" + tgChat.Username
} }
if addr, ok := app.storage.emails[jfID]; ok { if addr, ok := app.storage.emails[jfID]; ok {

View File

@ -180,8 +180,8 @@
</div> </div>
<div id="modal-customize" class="modal"> <div id="modal-customize" class="modal">
<div class="modal-content card"> <div class="modal-content card">
<span class="heading">{{ .strings.customizeEmails }} <span class="modal-close">&times;</span></span> <span class="heading">{{ .strings.customizeMessages }} <span class="modal-close">&times;</span></span>
<p class="content">{{ .strings.customizeEmailsDescription }}</p> <p class="content">{{ .strings.customizeMessagesDescription }}</p>
<div class="table-responsive"> <div class="table-responsive">
<table class="table"> <table class="table">
<thead> <thead>

View File

@ -69,8 +69,8 @@
"preview": "Vorschau", "preview": "Vorschau",
"reset": "Zurücksetzen", "reset": "Zurücksetzen",
"edit": "Bearbeiten", "edit": "Bearbeiten",
"customizeEmails": "E-Mails anpassen", "customizeMessages": "E-Mails anpassen",
"customizeEmailsDescription": "Wenn du jfa-go's E-Mail-Vorlagen nicht benutzen willst, kannst du deinen eigenen unter Verwendung von Markdown erstellen.", "customizeMessagesDescription": "Wenn du jfa-go's E-Mail-Vorlagen nicht benutzen willst, kannst du deinen eigenen unter Verwendung von Markdown erstellen.",
"announce": "Ankündigen", "announce": "Ankündigen",
"subject": "E-Mail-Betreff", "subject": "E-Mail-Betreff",
"message": "Nachricht", "message": "Nachricht",

View File

@ -69,9 +69,9 @@
"preview": "Προεπισκόπηση", "preview": "Προεπισκόπηση",
"reset": "Επαναφορά", "reset": "Επαναφορά",
"edit": "Επεξεργασία", "edit": "Επεξεργασία",
"customizeEmails": "Παραμετροποίηση Emails", "customizeMessages": "Παραμετροποίηση Emails",
"advancedSettings": "Προχωρημένες Ρυθμίσεις", "advancedSettings": "Προχωρημένες Ρυθμίσεις",
"customizeEmailsDescription": "Αν δεν θέλετε να ζρησιμοποιήσετε τα πρότυπα email του jfa-go, μπορείτε να δημιουργήσετε τα δικά σας με χρήση Markdown.", "customizeMessagesDescription": "Αν δεν θέλετε να ζρησιμοποιήσετε τα πρότυπα email του jfa-go, μπορείτε να δημιουργήσετε τα δικά σας με χρήση Markdown.",
"updates": "Ενημερώσεις", "updates": "Ενημερώσεις",
"update": "Ενημέρωση", "update": "Ενημέρωση",
"download": "Λήψη", "download": "Λήψη",

View File

@ -55,8 +55,8 @@
"edit": "Edit", "edit": "Edit",
"donate": "Donate", "donate": "Donate",
"extendExpiry": "Extend expiry", "extendExpiry": "Extend expiry",
"customizeEmails": "Customize Emails", "customizeMessages": "Customize Messages",
"customizeEmailsDescription": "If you don't want to use jfa-go's message templates, you can create your own using Markdown.", "customizeMessagesDescription": "If you don't want to use jfa-go's message templates, you can create your own using Markdown.",
"markdownSupported": "Markdown is supported.", "markdownSupported": "Markdown is supported.",
"modifySettings": "Modify Settings", "modifySettings": "Modify Settings",
"modifySettingsDescription": "Apply settings from an existing profile, or source them directly from a user.", "modifySettingsDescription": "Apply settings from an existing profile, or source them directly from a user.",

View File

@ -53,8 +53,8 @@
"reset": "Reiniciar", "reset": "Reiniciar",
"edit": "Editar", "edit": "Editar",
"extendExpiry": "Extender el vencimiento", "extendExpiry": "Extender el vencimiento",
"customizeEmails": "Personalizar emails", "customizeMessages": "Personalizar emails",
"customizeEmailsDescription": "Si no desea utilizar las plantillas de correo electrónico de jfa-go, puede crear las suyas propias con Markdown.", "customizeMessagesDescription": "Si no desea utilizar las plantillas de correo electrónico de jfa-go, puede crear las suyas propias con Markdown.",
"markdownSupported": "Se admite Markdown.", "markdownSupported": "Se admite Markdown.",
"modifySettings": "Modificar configuración", "modifySettings": "Modificar configuración",
"modifySettingsDescription": "Aplique la configuración de un perfil existente u obténgalos directamente de un usuario.", "modifySettingsDescription": "Aplique la configuración de un perfil existente u obténgalos directamente de un usuario.",

View File

@ -71,12 +71,12 @@
"subject": "Sujet", "subject": "Sujet",
"message": "Message", "message": "Message",
"markdownSupported": "Markdown est pris en charge.", "markdownSupported": "Markdown est pris en charge.",
"customizeEmailsDescription": "Si vous ne souhaitez pas utiliser les modèles d'e-mails de jfa-go, vous pouvez créer les vôtres à l'aide de Markdown.", "customizeMessagesDescription": "Si vous ne souhaitez pas utiliser les modèles d'e-mails de jfa-go, vous pouvez créer les vôtres à l'aide de Markdown.",
"variables": "Variables", "variables": "Variables",
"preview": "Aperçu", "preview": "Aperçu",
"reset": "Réinitialiser", "reset": "Réinitialiser",
"edit": "Éditer", "edit": "Éditer",
"customizeEmails": "Personnaliser les e-mails", "customizeMessages": "Personnaliser les e-mails",
"inviteDuration": "Durée de l'invitation", "inviteDuration": "Durée de l'invitation",
"enabled": "Activé", "enabled": "Activé",
"disabled": "Désactivé", "disabled": "Désactivé",

View File

@ -69,8 +69,8 @@
"preview": "Pratinjau", "preview": "Pratinjau",
"reset": "Setel ulang", "reset": "Setel ulang",
"edit": "Edit", "edit": "Edit",
"customizeEmails": "Sesuaikan Email", "customizeMessages": "Sesuaikan Email",
"customizeEmailsDescription": "Jika Anda tidak ingin menggunakan templat email jfa-go, Anda dapat membuatnya sendiri menggunakan Markdown.", "customizeMessagesDescription": "Jika Anda tidak ingin menggunakan templat email jfa-go, Anda dapat membuatnya sendiri menggunakan Markdown.",
"announce": "Mengumumkan", "announce": "Mengumumkan",
"subject": "Subjek Email", "subject": "Subjek Email",
"message": "Pesan", "message": "Pesan",

View File

@ -70,11 +70,11 @@
"subject": "E-mailonderwerp", "subject": "E-mailonderwerp",
"message": "Bericht", "message": "Bericht",
"variables": "Variabelen", "variables": "Variabelen",
"customizeEmailsDescription": "Als je de e-mailsjablonen van jfa-go niet wilt gebruiken, kun je met gebruik van Markdown je eigen aanmaken.", "customizeMessagesDescription": "Als je de e-mailsjablonen van jfa-go niet wilt gebruiken, kun je met gebruik van Markdown je eigen aanmaken.",
"preview": "Voorbeeld", "preview": "Voorbeeld",
"reset": "Resetten", "reset": "Resetten",
"edit": "Bewerken", "edit": "Bewerken",
"customizeEmails": "E-mails aanpassen", "customizeMessages": "E-mails aanpassen",
"inviteDuration": "Geldigheidsduur uitnodiging", "inviteDuration": "Geldigheidsduur uitnodiging",
"userExpiryDescription": "Een bepaalde tijd na elke aanmelding, wordt de account verwijderd/uitgeschakeld door jfa-go. Dit kan aangepast worden in de instellingen.", "userExpiryDescription": "Een bepaalde tijd na elke aanmelding, wordt de account verwijderd/uitgeschakeld door jfa-go. Dit kan aangepast worden in de instellingen.",
"enabled": "Ingeschakeld", "enabled": "Ingeschakeld",

View File

@ -69,12 +69,12 @@
"subject": "Assunto do email", "subject": "Assunto do email",
"message": "Mensagem", "message": "Mensagem",
"markdownSupported": "Suporte a Markdown.", "markdownSupported": "Suporte a Markdown.",
"customizeEmailsDescription": "Se não quiser usar os modelos de email do jfa-go, você pode criar o seu próprio usando o Markdown.", "customizeMessagesDescription": "Se não quiser usar os modelos de email do jfa-go, você pode criar o seu próprio usando o Markdown.",
"variables": "Variáveis", "variables": "Variáveis",
"preview": "Pre-visualizar", "preview": "Pre-visualizar",
"reset": "Reiniciar", "reset": "Reiniciar",
"edit": "Editar", "edit": "Editar",
"customizeEmails": "Customizar Emails", "customizeMessages": "Customizar Emails",
"disabled": "Desativado", "disabled": "Desativado",
"userExpiryDescription": "Após um determinado período de tempo de cada inscrição, o jfa-go apagará/desabilitará a conta. Você pode alterar essa opção nas configurações.", "userExpiryDescription": "Após um determinado período de tempo de cada inscrição, o jfa-go apagará/desabilitará a conta. Você pode alterar essa opção nas configurações.",
"inviteDuration": "Duração do Convite", "inviteDuration": "Duração do Convite",

View File

@ -37,8 +37,8 @@
"preview": "Förhandsvisning", "preview": "Förhandsvisning",
"reset": "Återställ", "reset": "Återställ",
"edit": "Redigera", "edit": "Redigera",
"customizeEmails": "Anpassa e-post", "customizeMessages": "Anpassa e-post",
"customizeEmailsDescription": "Om du inte vill använda jfa-go's e-postmallar, så kan du skapa dina egna med Markdown.", "customizeMessagesDescription": "Om du inte vill använda jfa-go's e-postmallar, så kan du skapa dina egna med Markdown.",
"markdownSupported": "Markdown stöds.", "markdownSupported": "Markdown stöds.",
"modifySettings": "Ändra inställningar", "modifySettings": "Ändra inställningar",
"modifySettingsDescription": "Tillämpa inställningar från en befintlig profil eller kopiera dem direkt från en användare.", "modifySettingsDescription": "Tillämpa inställningar från en befintlig profil eller kopiera dem direkt från en användare.",

View File

@ -3,7 +3,7 @@
"name": "English (US)" "name": "English (US)"
}, },
"strings": { "strings": {
"ifItWasNotYou": "If this wasn't you, please ignore this email.", "ifItWasNotYou": "If this wasn't you, please ignore this.",
"helloUser": "Hi {username},", "helloUser": "Hi {username},",
"reason": "Reason" "reason": "Reason"
}, },
@ -55,7 +55,7 @@
"linkButton": "Setup your account" "linkButton": "Setup your account"
}, },
"welcomeEmail": { "welcomeEmail": {
"name": "Welcome email", "name": "Welcome",
"title": "Welcome to Jellyfin", "title": "Welcome to Jellyfin",
"welcome": "Welcome to Jellyfin!", "welcome": "Welcome to Jellyfin!",
"youCanLoginWith": "You can login with the details below", "youCanLoginWith": "You can login with the details below",

View File

@ -199,6 +199,12 @@ func start(asDaemon, firstCall bool) {
if err := app.loadConfig(); err != nil { if err := app.loadConfig(); err != nil {
app.err.Fatalf("Failed to load config file \"%s\": %v", app.configPath, err) app.err.Fatalf("Failed to load config file \"%s\": %v", app.configPath, err)
} }
// Some message settings have been moved from "email" to "messages", this will switch them.
if app.config.Section("email").Key("use_24h").Value() != "" {
app.migrateEmailConfig()
}
app.version = app.config.Section("jellyfin").Key("version").String() app.version = app.config.Section("jellyfin").Key("version").String()
// read from config... // read from config...
debugMode = app.config.Section("ui").Key("debug").MustBool(false) debugMode = app.config.Section("ui").Key("debug").MustBool(false)
@ -548,7 +554,7 @@ func start(asDaemon, firstCall bool) {
go app.checkForUpdates() go app.checkForUpdates()
} }
if app.config.Section("telegram").Key("enabled").MustBool(false) { if telegramEnabled {
app.telegram, err = newTelegramDaemon(app) app.telegram, err = newTelegramDaemon(app)
if err != nil { if err != nil {
app.err.Printf("Failed to authenticate with Telegram: %v", err) app.err.Printf("Failed to authenticate with Telegram: %v", err)

View File

@ -118,7 +118,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
router.POST(p+"/newUser", app.NewUser) router.POST(p+"/newUser", app.NewUser)
router.Use(static.Serve(p+"/invite/", app.webFS)) router.Use(static.Serve(p+"/invite/", app.webFS))
router.GET(p+"/invite/:invCode", app.InviteProxy) router.GET(p+"/invite/:invCode", app.InviteProxy)
if app.config.Section("telegram").Key("enabled").MustBool(false) { if telegramEnabled {
router.GET(p+"/invite/:invCode/telegram/verified/:pin", app.TelegramVerifiedInvite) router.GET(p+"/invite/:invCode/telegram/verified/:pin", app.TelegramVerifiedInvite)
} }
} }
@ -158,7 +158,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
api.GET(p+"/config", app.GetConfig) api.GET(p+"/config", app.GetConfig)
api.POST(p+"/config", app.ModifyConfig) api.POST(p+"/config", app.ModifyConfig)
api.POST(p+"/restart", app.restart) api.POST(p+"/restart", app.restart)
if app.config.Section("telegram").Key("enabled").MustBool(false) { if telegramEnabled {
api.GET(p+"/telegram/pin", app.TelegramGetPin) api.GET(p+"/telegram/pin", app.TelegramGetPin)
api.GET(p+"/telegram/verified/:pin", app.TelegramVerified) api.GET(p+"/telegram/verified/:pin", app.TelegramVerified)
api.POST(p+"/users/telegram", app.TelegramAddUser) api.POST(p+"/users/telegram", app.TelegramAddUser)

View File

@ -29,7 +29,7 @@ func (app *appContext) ServeSetup(gc *gin.Context) {
"success_message": app.config.Section("ui").Key("success_message").String(), "success_message": app.config.Section("ui").Key("success_message").String(),
}, },
"email": { "email": {
"message": app.config.Section("email").Key("message").String(), "message": app.config.Section("messages").Key("message").String(),
}, },
} }
msg, err := json.Marshal(messages) msg, err := json.Marshal(messages)

View File

@ -560,10 +560,18 @@ export class settingsList {
document.addEventListener(`settings-${dependant[0]}-${dependant[1]}`, (event: settingsBoolEvent) => { document.addEventListener(`settings-${dependant[0]}-${dependant[1]}`, (event: settingsBoolEvent) => {
if (Boolean(event.detail) !== state) { if (Boolean(event.detail) !== state) {
button.classList.add("unfocused"); button.classList.add("unfocused");
document.dispatchEvent(new CustomEvent(`settings-${name}`, { detail: false }));
} else { } else {
button.classList.remove("unfocused"); button.classList.remove("unfocused");
document.dispatchEvent(new CustomEvent(`settings-${name}`, { detail: true }));
} }
}); });
document.addEventListener(`settings-${dependant[0]}`, (event: settingsBoolEvent) => {
if (Boolean(event.detail) !== state) {
button.classList.add("unfocused");
document.dispatchEvent(new CustomEvent(`settings-${name}`, { detail: false }));
}
});
} }
if (s.meta.advanced) { if (s.meta.advanced) {
document.addEventListener("settings-advancedState", (event: settingsBoolEvent) => { document.addEventListener("settings-advancedState", (event: settingsBoolEvent) => {
@ -669,7 +677,7 @@ export class settingsList {
if (name in this._sections) { if (name in this._sections) {
this._sections[name].update(settings.sections[name]); this._sections[name].update(settings.sections[name]);
} else { } else {
if (name == "email") { if (name == "messages") {
const editButton = document.createElement("div"); const editButton = document.createElement("div");
editButton.classList.add("tooltip", "left"); editButton.classList.add("tooltip", "left");
editButton.innerHTML = ` editButton.innerHTML = `
@ -677,7 +685,7 @@ export class settingsList {
<i class="icon ri-edit-line"></i> <i class="icon ri-edit-line"></i>
</span> </span>
<span class="content sm"> <span class="content sm">
${window.lang.get("strings", "customizeEmails")} ${window.lang.get("strings", "customizeMessages")}
</span> </span>
`; `;
(editButton.querySelector("span.button") as HTMLSpanElement).onclick = this._emailEditor.showList; (editButton.querySelector("span.button") as HTMLSpanElement).onclick = this._emailEditor.showList;

View File

@ -72,8 +72,7 @@ func (app *appContext) checkUsers() {
termPlural = "Deleting" termPlural = "Deleting"
} }
contact := false contact := false
if (emailEnabled && app.config.Section("user_expiry").Key("send_email").MustBool(true)) || if messagesEnabled && app.config.Section("user_expiry").Key("send_email").MustBool(true) {
app.config.Section("telegram").Key("enabled").MustBool(false) {
contact = true contact = true
} }
// Use a map to speed up checking for deleted users later // Use a map to speed up checking for deleted users later

View File

@ -120,7 +120,7 @@ func (app *appContext) AdminPage(gc *gin.Context) {
"cssClass": app.cssClass, "cssClass": app.cssClass,
"contactMessage": "", "contactMessage": "",
"email_enabled": emailEnabled, "email_enabled": emailEnabled,
"telegram_enabled": app.config.Section("telegram").Key("enabled").MustBool(false), "telegram_enabled": telegramEnabled,
"notifications": notificationsEnabled, "notifications": notificationsEnabled,
"version": version, "version": version,
"commit": commit, "commit": commit,
@ -283,7 +283,7 @@ func (app *appContext) InviteProxy(gc *gin.Context) {
"userExpiryMinutes": inv.UserMinutes, "userExpiryMinutes": inv.UserMinutes,
"userExpiryMessage": app.storage.lang.Form[lang].Strings.get("yourAccountIsValidUntil"), "userExpiryMessage": app.storage.lang.Form[lang].Strings.get("yourAccountIsValidUntil"),
"langName": lang, "langName": lang,
"telegramEnabled": app.config.Section("telegram").Key("enabled").MustBool(false), "telegramEnabled": telegramEnabled,
} }
if data["telegramEnabled"].(bool) { if data["telegramEnabled"].(bool) {
data["telegramPIN"] = app.telegram.NewAuthToken() data["telegramPIN"] = app.telegram.NewAuthToken()