mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-29 12:30:11 +00:00
Compare commits
18 Commits
19f466c1b7
...
d60d347458
Author | SHA1 | Date | |
---|---|---|---|
|
d60d347458 | ||
9c771e193e | |||
|
f37451021f | ||
|
4aa095d466 | ||
|
638be18ea8 | ||
|
42264f0547 | ||
|
07d738006f | ||
|
4bc51570c2 | ||
cf94fdb2f0 | |||
4864c6c53c | |||
5702e8012c | |||
523902f951 | |||
543f23c8ef | |||
f6fdd41b35 | |||
4f78b7c33b | |||
9956bbd974 | |||
ff1ea8549a | |||
5a2d3d2ee2 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -24,3 +24,4 @@ matacc.txt
|
||||
scripts/langmover/lang
|
||||
scripts/langmover/lang2
|
||||
scripts/langmover/out
|
||||
tinyproxy.conf
|
||||
|
42
api-ombi.go
42
api-ombi.go
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/hrfee/mediabrowser"
|
||||
)
|
||||
|
||||
func (app *appContext) getOmbiUser(jfID string) (map[string]interface{}, int, error) {
|
||||
@ -29,7 +30,31 @@ func (app *appContext) getOmbiUser(jfID string) (map[string]interface{}, int, er
|
||||
return ombiUser, code, err
|
||||
}
|
||||
}
|
||||
return nil, 400, fmt.Errorf("Couldn't find user")
|
||||
return nil, 400, fmt.Errorf("couldn't find user")
|
||||
}
|
||||
|
||||
// Returns a user with the given name who has been imported from Jellyfin/Emby by Ombi
|
||||
func (app *appContext) getOmbiImportedUser(name string) (map[string]interface{}, int, error) {
|
||||
// Ombi User Types: 3/4 = Emby, 5 = Jellyfin
|
||||
ombiUsers, code, err := app.ombi.GetUsers()
|
||||
if err != nil || code != 200 {
|
||||
return nil, code, err
|
||||
}
|
||||
for _, ombiUser := range ombiUsers {
|
||||
if ombiUser["userName"].(string) == name {
|
||||
uType, ok := ombiUser["userType"].(int)
|
||||
if !ok { // Don't know if Ombi somehow allows duplicate usernames
|
||||
continue
|
||||
}
|
||||
if serverType == mediabrowser.JellyfinServer && uType != 5 { // Jellyfin
|
||||
continue
|
||||
} else if uType != 3 && uType != 4 { // Emby
|
||||
continue
|
||||
}
|
||||
return ombiUser, code, err
|
||||
}
|
||||
}
|
||||
return nil, 400, fmt.Errorf("couldn't find user")
|
||||
}
|
||||
|
||||
// @Summary Get a list of Ombi users.
|
||||
@ -107,3 +132,18 @@ func (app *appContext) DeleteOmbiProfile(gc *gin.Context) {
|
||||
app.storage.SetProfileKey(profileName, profile)
|
||||
respondBool(204, true, gc)
|
||||
}
|
||||
|
||||
func (app *appContext) applyOmbiProfile(user map[string]interface{}, profile map[string]interface{}) (status int, err error) {
|
||||
for k, v := range profile {
|
||||
switch v.(type) {
|
||||
case map[string]interface{}, []interface{}:
|
||||
user[k] = v
|
||||
default:
|
||||
if v != user[k] {
|
||||
user[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
status, err = app.ombi.ModifyUser(user)
|
||||
return
|
||||
}
|
||||
|
73
api-users.go
73
api-users.go
@ -377,30 +377,47 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
||||
if profile.Ombi != nil && len(profile.Ombi) != 0 {
|
||||
template := profile.Ombi
|
||||
errors, code, err := app.ombi.NewUser(req.Username, req.Password, req.Email, template)
|
||||
accountExists := false
|
||||
var ombiUser map[string]interface{}
|
||||
if err != nil || code != 200 {
|
||||
app.info.Printf("Failed to create Ombi user (%d): %s", code, err)
|
||||
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
|
||||
} else {
|
||||
app.info.Println("Created Ombi user")
|
||||
if discordVerified || telegramVerified {
|
||||
ombiUser, status, err := app.getOmbiUser(id)
|
||||
// Check if on the off chance, Ombi's user importer has already added the account.
|
||||
ombiUser, status, err = app.getOmbiImportedUser(req.Username)
|
||||
if status == 200 && err == nil {
|
||||
app.info.Println("Found existing Ombi user, applying changes")
|
||||
accountExists = true
|
||||
template["password"] = req.Password
|
||||
status, err = app.applyOmbiProfile(ombiUser, template)
|
||||
if status != 200 || err != nil {
|
||||
app.err.Printf("Failed to get Ombi user (%d): %v", status, err)
|
||||
} else {
|
||||
dID := ""
|
||||
tUser := ""
|
||||
if discordVerified {
|
||||
dID = discordUser.ID
|
||||
}
|
||||
if telegramVerified {
|
||||
u, _ := app.storage.GetTelegramKey(user.ID)
|
||||
tUser = u.Username
|
||||
}
|
||||
resp, status, err := app.ombi.SetNotificationPrefs(ombiUser, dID, tUser)
|
||||
if !(status == 200 || status == 204) || err != nil {
|
||||
app.err.Printf("Failed to link Telegram/Discord to Ombi (%d): %v", status, err)
|
||||
app.debug.Printf("Response: %v", resp)
|
||||
}
|
||||
app.err.Printf("Failed to modify existing Ombi user (%d): %v\n", status, err)
|
||||
}
|
||||
} else {
|
||||
app.info.Printf("Failed to create Ombi user (%d): %s", code, err)
|
||||
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
|
||||
}
|
||||
} else {
|
||||
ombiUser, status, err = app.getOmbiUser(id)
|
||||
if status != 200 || err != nil {
|
||||
app.err.Printf("Failed to get Ombi user (%d): %v", status, err)
|
||||
} else {
|
||||
app.info.Println("Created Ombi user")
|
||||
accountExists = true
|
||||
}
|
||||
}
|
||||
if accountExists {
|
||||
if discordVerified || telegramVerified {
|
||||
dID := ""
|
||||
tUser := ""
|
||||
if discordVerified {
|
||||
dID = discordUser.ID
|
||||
}
|
||||
if telegramVerified {
|
||||
u, _ := app.storage.GetTelegramKey(user.ID)
|
||||
tUser = u.Username
|
||||
}
|
||||
resp, status, err := app.ombi.SetNotificationPrefs(ombiUser, dID, tUser)
|
||||
if !(status == 200 || status == 204) || err != nil {
|
||||
app.err.Printf("Failed to link Telegram/Discord to Ombi (%d): %v", status, err)
|
||||
app.debug.Printf("Response: %v", resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1214,17 +1231,7 @@ func (app *appContext) ApplySettings(gc *gin.Context) {
|
||||
// newUser["userName"] = user["userName"]
|
||||
// newUser["alias"] = user["alias"]
|
||||
// newUser["emailAddress"] = user["emailAddress"]
|
||||
for k, v := range ombi {
|
||||
switch v.(type) {
|
||||
case map[string]interface{}, []interface{}:
|
||||
user[k] = v
|
||||
default:
|
||||
if v != user[k] {
|
||||
user[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
status, err = app.ombi.ModifyUser(user)
|
||||
status, err = app.applyOmbiProfile(user, ombi)
|
||||
if status != 200 || err != nil {
|
||||
errorString += fmt.Sprintf("Apply %d: %v ", status, err)
|
||||
}
|
||||
|
2
api.go
2
api.go
@ -182,7 +182,7 @@ func (app *appContext) ResetSetPassword(gc *gin.Context) {
|
||||
}
|
||||
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||
// Silently fail for changing ombi passwords
|
||||
if status != 200 || err != nil {
|
||||
if (status != 200 && status != 204) || err != nil {
|
||||
app.err.Printf("Failed to get user \"%s\" from jellyfin/emby (%d): %v", username, status, err)
|
||||
respondBool(200, true, gc)
|
||||
return
|
||||
|
20
config.go
20
config.go
@ -8,6 +8,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hrfee/jfa-go/easyproxy"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
@ -135,6 +136,22 @@ func (app *appContext) loadConfig() error {
|
||||
messagesEnabled = false
|
||||
}
|
||||
|
||||
if app.proxyEnabled = app.config.Section("advanced").Key("proxy").MustBool(false); app.proxyEnabled {
|
||||
app.proxyConfig = easyproxy.ProxyConfig{}
|
||||
app.proxyConfig.Protocol = easyproxy.HTTP
|
||||
if strings.Contains(app.config.Section("advanced").Key("proxy_protocol").MustString("http"), "socks") {
|
||||
app.proxyConfig.Protocol = easyproxy.SOCKS5
|
||||
}
|
||||
app.proxyConfig.Addr = app.config.Section("advanced").Key("proxy_address").MustString("")
|
||||
app.proxyConfig.User = app.config.Section("advanced").Key("proxy_user").MustString("")
|
||||
app.proxyConfig.Password = app.config.Section("advanced").Key("proxy_password").MustString("")
|
||||
app.proxyTransport, err = easyproxy.NewTransport(app.proxyConfig)
|
||||
if err != nil {
|
||||
app.err.Printf("Failed to initialize Proxy: %v\n", err)
|
||||
}
|
||||
app.proxyEnabled = true
|
||||
}
|
||||
|
||||
app.MustSetValue("updates", "enabled", "true")
|
||||
releaseChannel := app.config.Section("updates").Key("channel").String()
|
||||
if app.config.Section("updates").Key("enabled").MustBool(false) {
|
||||
@ -147,6 +164,9 @@ func (app *appContext) loadConfig() error {
|
||||
v = "git"
|
||||
}
|
||||
app.updater = newUpdater(baseURL, namespace, repo, v, commit, updater)
|
||||
if app.proxyEnabled {
|
||||
app.updater.SetTransport(app.proxyTransport)
|
||||
}
|
||||
}
|
||||
if releaseChannel == "" {
|
||||
if version == "git" {
|
||||
|
@ -274,6 +274,18 @@
|
||||
"value": false,
|
||||
"advanced": true,
|
||||
"description": "Navigate directly to the above URL instead of needing the user to click \"Continue\"."
|
||||
},
|
||||
"login_appearance": {
|
||||
"name": "Login screen appearance",
|
||||
"required": false,
|
||||
"requires_restart": false,
|
||||
"type": "select",
|
||||
"options": [
|
||||
["clear", "Transparent"],
|
||||
["opaque", "Opaque"]
|
||||
],
|
||||
"value": "clear",
|
||||
"description": "Appearance of the Admin login screen."
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -281,7 +293,8 @@
|
||||
"order": [],
|
||||
"meta": {
|
||||
"name": "Advanced",
|
||||
"description": "Advanced settings."
|
||||
"description": "Advanced settings.",
|
||||
"advanced": true
|
||||
},
|
||||
"settings": {
|
||||
"tls": {
|
||||
@ -318,6 +331,70 @@
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"description": "Path to .key file. See jfa-go wiki for more info."
|
||||
},
|
||||
"auth_retry_count": {
|
||||
"name": "Initial auth retry count",
|
||||
"required": false,
|
||||
"requires_restart": true,
|
||||
"type": "number",
|
||||
"value": 6,
|
||||
"description": "Number of times to retry initial connection to Jellyfin before failing."
|
||||
},
|
||||
"auth_retry_gap": {
|
||||
"name": "Initial auth retry gap (seconds)",
|
||||
"required": false,
|
||||
"requires_restart": true,
|
||||
"type": "number",
|
||||
"value": 10,
|
||||
"description": "Duration in seconds to wait between connection retries."
|
||||
},
|
||||
"proxy": {
|
||||
"name": "Use Proxy",
|
||||
"required": false,
|
||||
"requires_restart": true,
|
||||
"type": "bool",
|
||||
"value": false,
|
||||
"description": "Whether or not to use a HTTP/SOCKS5 Proxy."
|
||||
},
|
||||
"proxy_protocol": {
|
||||
"name": "Proxy Protocol",
|
||||
"depends_true": "proxy",
|
||||
"required": false,
|
||||
"requires_restart": true,
|
||||
"type": "select",
|
||||
"options": [
|
||||
["http", "HTTP"],
|
||||
["socks", "SOCKS5"]
|
||||
],
|
||||
"value": "http",
|
||||
"description": "Protocol to use for proxy connection."
|
||||
},
|
||||
"proxy_address": {
|
||||
"name": "Proxy Address",
|
||||
"depends_true": "proxy",
|
||||
"required": false,
|
||||
"requires_restart": true,
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"description": "Proxy address, including port."
|
||||
},
|
||||
"proxy_user": {
|
||||
"name": "Proxy Username",
|
||||
"depends_true": "proxy",
|
||||
"required": false,
|
||||
"requires_restart": true,
|
||||
"type": "text",
|
||||
"value": "",
|
||||
"description": "Leave blank for no Authentication."
|
||||
},
|
||||
"proxy_password": {
|
||||
"name": "Proxy Password",
|
||||
"depends_true": "proxy",
|
||||
"required": false,
|
||||
"requires_restart": true,
|
||||
"type": "password",
|
||||
"value": "",
|
||||
"description": "Leave blank for no Authentication."
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -406,6 +483,14 @@
|
||||
"required": "false",
|
||||
"description": "Click the edit icon next to the \"User Page\" Setting to add custom Markdown messages that will be shown to the user. Note message cards are not private, little effort is required for anyone to view them."
|
||||
},
|
||||
"show_link": {
|
||||
"name": "Show Link on Admin Login page",
|
||||
"required": false,
|
||||
"requires_restart": false,
|
||||
"type": "bool",
|
||||
"value": true,
|
||||
"description": "Whether or not to show a link to the \"My Account\" page on the admin login screen, to direct lost users."
|
||||
},
|
||||
"referrals": {
|
||||
"name": "User Referrals",
|
||||
"required": false,
|
||||
|
@ -15,6 +15,9 @@
|
||||
--border-width-4: 5px;
|
||||
--border-width-8: 8px;
|
||||
font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
|
||||
--bg-light: #fff;
|
||||
--bg-dark: #101010;
|
||||
}
|
||||
|
||||
.light {
|
||||
@ -26,11 +29,11 @@
|
||||
}
|
||||
|
||||
.dark body {
|
||||
background-color: #101010;
|
||||
background-color: var(--bg-dark);
|
||||
}
|
||||
|
||||
html:not(.dark) body {
|
||||
background-color: #fff;
|
||||
background-color: var(--bg-light);
|
||||
}
|
||||
|
||||
.dark select, .dark option, .dark input {
|
||||
|
@ -10,6 +10,24 @@
|
||||
background-color: rgba(0,0,0,40%);
|
||||
}
|
||||
|
||||
.wall {
|
||||
position: fixed;
|
||||
z-index: 11;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
html.dark .wall {
|
||||
background-color: var(--bg-dark);
|
||||
}
|
||||
|
||||
html:not(.dark) .wall {
|
||||
background-color: var(--bg-light);
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
float: right;
|
||||
color: #aaa;
|
||||
|
83
easyproxy/easyproxy.go
Normal file
83
easyproxy/easyproxy.go
Normal file
@ -0,0 +1,83 @@
|
||||
// Package easyproxy provides a method to quickly create a http.Transport or net.Conn using given proxy details (SOCKS5 or HTTP).
|
||||
package easyproxy
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/magisterquis/connectproxy"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
type Protocol int
|
||||
|
||||
const (
|
||||
SOCKS5 Protocol = iota // SOCKS5
|
||||
HTTP // HTTP
|
||||
)
|
||||
|
||||
type ProxyConfig struct {
|
||||
Protocol Protocol
|
||||
Addr string
|
||||
User string
|
||||
Password string
|
||||
}
|
||||
|
||||
// NewTransport returns a http.Transport using the given proxy details. Leave user/pass blank if not needed.
|
||||
func NewTransport(c ProxyConfig) (*http.Transport, error) {
|
||||
t := &http.Transport{}
|
||||
if c.Protocol == HTTP {
|
||||
u := &url.URL{
|
||||
Scheme: "http",
|
||||
Host: c.Addr,
|
||||
}
|
||||
if c.User != "" && c.Password != "" {
|
||||
u.User = url.UserPassword(c.User, c.Password)
|
||||
}
|
||||
t.Proxy = http.ProxyURL(u)
|
||||
return t, nil
|
||||
}
|
||||
var auth *proxy.Auth = nil
|
||||
if c.User != "" && c.Password != "" {
|
||||
auth = &proxy.Auth{User: c.User, Password: c.Password}
|
||||
}
|
||||
dialer, err := proxy.SOCKS5("tcp", c.Addr, auth, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.Dial = dialer.Dial
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// NewConn returns a tls.Conn to "addr" using the given proxy details. Leave user/pass blank if not needed.
|
||||
func NewConn(c ProxyConfig, addr string, tlsConf *tls.Config) (*tls.Conn, error) {
|
||||
var proxyDialer proxy.Dialer
|
||||
var err error
|
||||
if c.Protocol == SOCKS5 {
|
||||
var auth *proxy.Auth = nil
|
||||
if c.User != "" && c.Password != "" {
|
||||
auth = &proxy.Auth{User: c.User, Password: c.Password}
|
||||
}
|
||||
proxyDialer, err = proxy.SOCKS5("tcp", c.Addr, auth, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
u := &url.URL{
|
||||
Scheme: "http",
|
||||
Host: c.Addr,
|
||||
}
|
||||
if c.User != "" && c.Password != "" {
|
||||
u.User = url.UserPassword(c.User, c.Password)
|
||||
}
|
||||
proxyDialer, err = connectproxy.New(u, proxy.Direct)
|
||||
}
|
||||
|
||||
dialer, err := proxyDialer.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn := tls.Client(dialer, tlsConf)
|
||||
return conn, nil
|
||||
}
|
7
easyproxy/go.mod
Normal file
7
easyproxy/go.mod
Normal file
@ -0,0 +1,7 @@
|
||||
module github.com/hrfee/jfa-go/easyproxy
|
||||
|
||||
go 1.20
|
||||
|
||||
require golang.org/x/net v0.15.0
|
||||
|
||||
require github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b // indirect
|
4
easyproxy/go.sum
Normal file
4
easyproxy/go.sum
Normal file
@ -0,0 +1,4 @@
|
||||
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b h1:xZ59n7Frzh8CwyfAapUZLSg+gXH5m63YEaFCMpDHhpI=
|
||||
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b/go.mod h1:uDd4sYVYsqcxAB8j+Q7uhL6IJCs/r1kxib1HV4bgOMg=
|
||||
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
16
email.go
16
email.go
@ -19,6 +19,7 @@ import (
|
||||
|
||||
"github.com/gomarkdown/markdown"
|
||||
"github.com/gomarkdown/markdown/html"
|
||||
"github.com/hrfee/jfa-go/easyproxy"
|
||||
"github.com/hrfee/mediabrowser"
|
||||
"github.com/itchyny/timefmt-go"
|
||||
"github.com/mailgun/mailgun-go/v4"
|
||||
@ -87,7 +88,11 @@ func NewEmailer(app *appContext) *Emailer {
|
||||
if username == "" && password != "" {
|
||||
username = emailer.fromAddr
|
||||
}
|
||||
err := emailer.NewSMTP(app.config.Section("smtp").Key("server").String(), app.config.Section("smtp").Key("port").MustInt(465), username, password, sslTLS, app.config.Section("smtp").Key("ssl_cert").MustString(""), app.config.Section("smtp").Key("hello_hostname").String(), app.config.Section("smtp").Key("cert_validation").MustBool(true))
|
||||
var proxyConf *easyproxy.ProxyConfig = nil
|
||||
if app.proxyEnabled {
|
||||
proxyConf = &app.proxyConfig
|
||||
}
|
||||
err := emailer.NewSMTP(app.config.Section("smtp").Key("server").String(), app.config.Section("smtp").Key("port").MustInt(465), username, password, sslTLS, app.config.Section("smtp").Key("ssl_cert").MustString(""), app.config.Section("smtp").Key("hello_hostname").String(), app.config.Section("smtp").Key("cert_validation").MustBool(true), proxyConf)
|
||||
if err != nil {
|
||||
app.err.Printf("Error while initiating SMTP mailer: %v", err)
|
||||
}
|
||||
@ -113,7 +118,7 @@ type SMTP struct {
|
||||
}
|
||||
|
||||
// NewSMTP returns an SMTP emailClient.
|
||||
func (emailer *Emailer) NewSMTP(server string, port int, username, password string, sslTLS bool, certPath string, helloHostname string, validateCertificate bool) (err error) {
|
||||
func (emailer *Emailer) NewSMTP(server string, port int, username, password string, sslTLS bool, certPath string, helloHostname string, validateCertificate bool, proxy *easyproxy.ProxyConfig) (err error) {
|
||||
sender := &SMTP{}
|
||||
sender.Client = sMail.NewSMTPClient()
|
||||
if sslTLS {
|
||||
@ -131,12 +136,16 @@ func (emailer *Emailer) NewSMTP(server string, port int, username, password stri
|
||||
sender.Client.Host = server
|
||||
sender.Client.Port = port
|
||||
sender.Client.KeepAlive = false
|
||||
|
||||
// x509.SystemCertPool is unavailable on windows
|
||||
if PLATFORM == "windows" {
|
||||
sender.Client.TLSConfig = &tls.Config{
|
||||
InsecureSkipVerify: !validateCertificate,
|
||||
ServerName: server,
|
||||
}
|
||||
if proxy != nil {
|
||||
sender.Client.CustomConn, err = easyproxy.NewConn(*proxy, fmt.Sprintf("%s:%d", server, port), sender.Client.TLSConfig)
|
||||
}
|
||||
emailer.sender = sender
|
||||
return
|
||||
}
|
||||
@ -156,6 +165,9 @@ func (emailer *Emailer) NewSMTP(server string, port int, username, password stri
|
||||
ServerName: server,
|
||||
RootCAs: rootCAs,
|
||||
}
|
||||
if proxy != nil {
|
||||
sender.Client.CustomConn, err = easyproxy.NewConn(*proxy, fmt.Sprintf("%s:%d", server, port), sender.Client.TLSConfig)
|
||||
}
|
||||
emailer.sender = sender
|
||||
return
|
||||
}
|
||||
|
16
go.mod
16
go.mod
@ -14,6 +14,8 @@ replace github.com/hrfee/jfa-go/linecache => ./linecache
|
||||
|
||||
replace github.com/hrfee/jfa-go/api => ./api
|
||||
|
||||
replace github.com/hrfee/jfa-go/easyproxy => ./easyproxy
|
||||
|
||||
require (
|
||||
github.com/bwmarrin/discordgo v0.27.1
|
||||
github.com/emersion/go-autostart v0.0.0-20210130080809-00ed301c8e9a
|
||||
@ -31,7 +33,7 @@ require (
|
||||
github.com/hrfee/jfa-go/linecache v0.0.0-20230626224816-f72960635dc3
|
||||
github.com/hrfee/jfa-go/logger v0.0.0-20230626224816-f72960635dc3
|
||||
github.com/hrfee/jfa-go/ombi v0.0.0-20230626224816-f72960635dc3
|
||||
github.com/hrfee/mediabrowser v0.3.10
|
||||
github.com/hrfee/mediabrowser v0.3.12
|
||||
github.com/itchyny/timefmt-go v0.1.5
|
||||
github.com/lithammer/shortuuid/v3 v3.0.7
|
||||
github.com/mailgun/mailgun-go/v4 v4.9.1
|
||||
@ -41,7 +43,7 @@ require (
|
||||
github.com/swaggo/gin-swagger v1.6.0
|
||||
github.com/timshannon/badgerhold/v4 v4.0.2
|
||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
||||
github.com/xhit/go-simple-mail/v2 v2.13.0
|
||||
github.com/xhit/go-simple-mail/v2 v2.16.0
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
maunium.net/go/mautrix v0.15.3
|
||||
)
|
||||
@ -85,11 +87,13 @@ require (
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/hrfee/jfa-go/easyproxy v0.0.0-00010101000000-000000000000 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.16.6 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
@ -116,12 +120,12 @@ require (
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.10.0 // indirect
|
||||
golang.org/x/crypto v0.13.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
|
||||
golang.org/x/image v0.8.0 // indirect
|
||||
golang.org/x/net v0.11.0 // indirect
|
||||
golang.org/x/sys v0.9.0 // indirect
|
||||
golang.org/x/text v0.10.0 // indirect
|
||||
golang.org/x/net v0.15.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.10.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
58
go.sum
58
go.sum
@ -3,6 +3,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
@ -14,14 +15,11 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx
|
||||
github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY=
|
||||
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/bytedance/sonic v1.9.2 h1:GDaNjuWSGu09guE9Oql0MSTNhNCLlWwO8y/xM5BzcbM=
|
||||
github.com/bytedance/sonic v1.9.2/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@ -40,16 +38,14 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgraph-io/badger/v3 v3.2103.1 h1:zaX53IRg7ycxVlkd5pYdCeFp1FynD6qBGQoQql3R3Hk=
|
||||
github.com/dgraph-io/badger/v3 v3.2103.1/go.mod h1:dULbq6ehJ5K0cGW/1TQ9iSfUk0gbSiToDWmWmTsJ53E=
|
||||
github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg=
|
||||
github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw=
|
||||
github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI=
|
||||
github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug=
|
||||
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
|
||||
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
@ -174,7 +170,6 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v0.0.0-20210429001901-424d2337a529 h1:2voWjNECnrZRbfwXxHB1/j8wa6xdKn85B5NzgVL/pTU=
|
||||
github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.1 h1:jxpi2eWoU84wbX9iIEyAeeoac3FLuifZpY9tcNUD9kw=
|
||||
github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
|
||||
@ -195,7 +190,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
@ -206,7 +200,6 @@ github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a h1:AWZzzFrqyjY
|
||||
github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
|
||||
github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v2.0.0+incompatible h1:dicJ2oXwypfwUGnB2/TYWYEKiuk9eYQlQO/AnOHl5mI=
|
||||
github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg=
|
||||
github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
@ -231,12 +224,8 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hrfee/mediabrowser v0.3.8 h1:y0iBCb6jE3QKcsiCJSYva2fFPHRn4UA+sGRzoPuJ/Dk=
|
||||
github.com/hrfee/mediabrowser v0.3.8/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
||||
github.com/hrfee/mediabrowser v0.3.9 h1:ecBUd7LMjQrh+9SFRen2T2DzQqI7W8J7vV2lGExD0YU=
|
||||
github.com/hrfee/mediabrowser v0.3.9/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
||||
github.com/hrfee/mediabrowser v0.3.10 h1:MUrgZQVY3mk76Bhn7PsZ4LFRhtGitkZA4FP+1qg1HFo=
|
||||
github.com/hrfee/mediabrowser v0.3.10/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
||||
github.com/hrfee/mediabrowser v0.3.12 h1:fqDxt1be3e+ZNjAtlKc8MTqg7peo6fuGCrk2wOXo20k=
|
||||
github.com/hrfee/mediabrowser v0.3.12/go.mod h1:PnHZbdxmbv1wCVdAQyM7nwPwpVj9fdKx2EcET7sAk+U=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
||||
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
||||
@ -251,7 +240,6 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.1 h1:wXr2uRxZTJXHLly6qhJabee5JqIhTRoLBhDOA74hDEQ=
|
||||
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
|
||||
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
@ -276,8 +264,8 @@ github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaK
|
||||
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailgun/mailgun-go/v4 v4.9.0 h1:wRbxvVQ5QObFewLxc1uVvipA16D8gxeiO+cBOca51Iw=
|
||||
github.com/mailgun/mailgun-go/v4 v4.9.0/go.mod h1:FJlF9rI5cQT+mrwujtJjPMbIVy3Ebor9bKTVsJ0QU40=
|
||||
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b h1:xZ59n7Frzh8CwyfAapUZLSg+gXH5m63YEaFCMpDHhpI=
|
||||
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b/go.mod h1:uDd4sYVYsqcxAB8j+Q7uhL6IJCs/r1kxib1HV4bgOMg=
|
||||
github.com/mailgun/mailgun-go/v4 v4.9.1 h1:D/jhJXYod4RqRsNOOSrjrtAcMEnz8mPYJmeA5cueHKY=
|
||||
github.com/mailgun/mailgun-go/v4 v4.9.1/go.mod h1:FJlF9rI5cQT+mrwujtJjPMbIVy3Ebor9bKTVsJ0QU40=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@ -298,7 +286,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
@ -337,6 +324,7 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
@ -359,7 +347,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
|
||||
@ -384,6 +371,7 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
github.com/timshannon/badgerhold/v3 v3.0.0-20210909134927-2b6764d68c1e h1:zWSVsQaifg0cVH9VvR+cMguV7exK6U+SoW8YD1cZpR4=
|
||||
github.com/timshannon/badgerhold/v3 v3.0.0-20210909134927-2b6764d68c1e/go.mod h1:/Seq5xGNo8jLhSbDX3jdbeZrp4yFIpQ6/7n4TjziEWs=
|
||||
github.com/timshannon/badgerhold/v4 v4.0.2 h1:83OLY/NFnEaMnHEPd84bYtkLipVkjTsMbzQRYbk47g4=
|
||||
github.com/timshannon/badgerhold/v4 v4.0.2/go.mod h1:rh6RyXLQFsvrvcKondPQQFZnNovpRzu+gS0FlLxYuHY=
|
||||
@ -408,13 +396,14 @@ github.com/writeas/go-strip-markdown v2.0.1+incompatible h1:IIqxTM5Jr7RzhigcL6Fk
|
||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible/go.mod h1:Rsyu10ZhbEK9pXdk8V6MVnZmTzRG0alMNLMwa0J01fE=
|
||||
github.com/xhit/go-simple-mail/v2 v2.13.0 h1:OANWU9jHZrVfBkNkvLf8Ww0fexwpQVF/v/5f96fFTLI=
|
||||
github.com/xhit/go-simple-mail/v2 v2.13.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98=
|
||||
github.com/xhit/go-simple-mail/v2 v2.16.0 h1:ouGy/Ww4kuaqu2E2UrDw7SvLaziWTB60ICLkIkNVccA=
|
||||
github.com/xhit/go-simple-mail/v2 v2.16.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
@ -448,18 +437,14 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
|
||||
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw=
|
||||
golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg=
|
||||
golang.org/x/image v0.8.0 h1:agUcRXV/+w6L9ryntYYsF2x9fQTMd4T8fiiYXAVW6Jg=
|
||||
golang.org/x/image v0.8.0/go.mod h1:PwLxp3opCYg4WR2WO9P0L6ESnsD6bLTWcw8zanLMVFM=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -471,7 +456,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -494,10 +478,10 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -539,10 +523,10 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@ -552,10 +536,10 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@ -570,8 +554,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
|
||||
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -603,8 +585,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E=
|
||||
@ -633,8 +613,6 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8=
|
||||
maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho=
|
||||
maunium.net/go/mautrix v0.15.2 h1:fUiVajeoOR92uJoSShHbCvh7uG6lDY4ZO4Mvt90LbjU=
|
||||
maunium.net/go/mautrix v0.15.2/go.mod h1:h4NwfKqE4YxGTLSgn/gawKzXAb2sF4qx8agL6QEFtGg=
|
||||
maunium.net/go/mautrix v0.15.3 h1:C9BHSUM0gYbuZmAtopuLjIcH5XHLb/ZjTEz7nN+0jN0=
|
||||
maunium.net/go/mautrix v0.15.3/go.mod h1:zLrQqdxJlLkurRCozTc9CL6FySkgZlO/kpCYxBILSLE=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
@ -18,6 +18,7 @@
|
||||
window.jfAdminOnly = {{ .jfAdminOnly }};
|
||||
window.jfAllowAll = {{ .jfAllowAll }};
|
||||
window.referralsEnabled = {{ .referralsEnabled }};
|
||||
window.loginAppearance = "{{ .loginAppearance }}";
|
||||
</script>
|
||||
<title>Admin - jfa-go</title>
|
||||
{{ template "header.html" . }}
|
||||
@ -465,7 +466,7 @@
|
||||
</div>
|
||||
{{ if .userPageEnabled }}
|
||||
<div class="top-4 right-4 absolute">
|
||||
<a class="button ~info" href="/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
|
||||
<a class="button ~info" href="{{ .urlBase }}/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="page-container">
|
||||
|
@ -7,6 +7,14 @@
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if index . "userPageEnabled" }}
|
||||
{{ if and .userPageEnabled .showUserPageLink }}
|
||||
<div class="card mx-2 flex-initial w-[100%] xl:w-[35%] mb-4 xl:mb-0 dark:~d_neutral @low content">
|
||||
<span class="heading row">{{ .strings.loginNotAdmin }}</span>
|
||||
<a class="button ~info h-12 w-100" href="{{ .urlBase }}/my/account"><i class="ri-account-circle-fill mr-2"></i>{{ .strings.myAccount }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<form class="card mx-2 flex-auto form-login w-[100%] xl:w-[55%] mb-0" href="">
|
||||
<span class="heading">{{ .strings.login }}</span>
|
||||
<input type="text" class="field input ~neutral @high mt-4 mb-2" placeholder="{{ .strings.username }}" id="login-user">
|
||||
|
@ -123,7 +123,8 @@
|
||||
"userPageLogin": "User Page: Login",
|
||||
"userPagePage": "User Page: Page",
|
||||
"buildTime": "Build Time",
|
||||
"builtBy": "Built By"
|
||||
"builtBy": "Built By",
|
||||
"loginNotAdmin": "Not an Admin?"
|
||||
},
|
||||
"notifications": {
|
||||
"changedEmailAddress": "Changed email address of {n}.",
|
||||
|
@ -118,7 +118,14 @@
|
||||
"userPagePage": "Page utilisateur : Page",
|
||||
"after": "Après",
|
||||
"before": "Avant",
|
||||
"unlink": "Délier le compte"
|
||||
"unlink": "Délier le compte",
|
||||
"enableReferrals": "Activer Parrainage",
|
||||
"enableReferralsDescription": "Offrez aux utilisateurs un lien de parrainage personnel semblable à une invitation, à envoyer à vos amis/famille. Peut provenir modèle de profil ou d’une invitation existante.",
|
||||
"invite": "Inviter",
|
||||
"userLabel": "Étiquette",
|
||||
"userLabelDescription": "Étiquette à appliquer aux utilisateurs créés avec cette invitation.",
|
||||
"disableReferrals": "Désactiver Parrainage",
|
||||
"enableReferralsProfileDescription": "Donnez aux utilisateurs créés avec ce profil un lien de parrainage personnel semblable à une invitation, à envoyer à vos amis/famille. Créez une invitation avec les paramètres souhaités, puis sélectionnez-la ici. Chaque référence sera alors basée sur cette invitation. Vous pouvez supprimer l'invitation une fois terminée."
|
||||
},
|
||||
"notifications": {
|
||||
"changedEmailAddress": "Adresse e-mail modifiée de {n}.",
|
||||
@ -156,7 +163,9 @@
|
||||
"accountConnected": "Compte connecté.",
|
||||
"savedAnnouncement": "Annonce enregistrée.",
|
||||
"setOmbiProfile": "Profil ombi enregistré.",
|
||||
"errorSetOmbiProfile": "Echec de la sauvegarde du profil ombi."
|
||||
"errorSetOmbiProfile": "Echec de la sauvegarde du profil ombi.",
|
||||
"errorNoReferralTemplate": "Le profil ne contient pas de modèle de référence, ajoutez-en un dans les paramètres.",
|
||||
"referralsEnabled": "Parrainage activer."
|
||||
},
|
||||
"quantityStrings": {
|
||||
"modifySettingsFor": {
|
||||
@ -214,6 +223,10 @@
|
||||
"setExpiry": {
|
||||
"singular": "Définir l'expiration pour {n} utilisateur",
|
||||
"plural": "Définir l'expiration pour {n} utilisateurs"
|
||||
},
|
||||
"enableReferralsFor": {
|
||||
"singular": "Activer les parrainages pour {n} utilisateur",
|
||||
"plural": "Activer les parrainages pour {n} utilisateur"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
"strings": {
|
||||
"username": "Nom d'utilisateur",
|
||||
"password": "Mot de passe",
|
||||
"emailAddress": "Adresse courriel",
|
||||
"emailAddress": "Adresse Email",
|
||||
"name": "Nom",
|
||||
"submit": "Soumettre",
|
||||
"send": "Envoyer",
|
||||
@ -29,7 +29,7 @@
|
||||
"logout": "Se déconnecter",
|
||||
"admin": "Administrateur",
|
||||
"enabled": "Activé",
|
||||
"disabled": "Désactivé",
|
||||
"disabled": "Désactiver",
|
||||
"reEnable": "Ré-activé",
|
||||
"disable": "Désactivé",
|
||||
"expiry": "Expiration",
|
||||
@ -40,7 +40,8 @@
|
||||
"accountStatus": "Statut du compte",
|
||||
"notSet": "Non défini",
|
||||
"myAccount": "Mon compte",
|
||||
"contactMethods": "Moyens de contact"
|
||||
"contactMethods": "Moyens de contact",
|
||||
"referrals": "Programme de parrainage"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "Le nom d'utilisateur et/ou le mot de passe sont vides.",
|
||||
@ -51,16 +52,16 @@
|
||||
},
|
||||
"quantityStrings": {
|
||||
"year": {
|
||||
"plural": "{n] années",
|
||||
"singular": "{n] année"
|
||||
"plural": "{n} années",
|
||||
"singular": "{n} année"
|
||||
},
|
||||
"day": {
|
||||
"singular": "{n] jour",
|
||||
"plural": "{n] jours"
|
||||
"singular": "{n} jour",
|
||||
"plural": "{n} jours"
|
||||
},
|
||||
"month": {
|
||||
"singular": "{n] mois",
|
||||
"plural": "{n] mois"
|
||||
"singular": "{n} mois",
|
||||
"plural": "{n} mois"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,22 @@
|
||||
"expiry": "Löper ut",
|
||||
"edit": "Redigera",
|
||||
"delete": "Radera",
|
||||
"inviteRemainingUses": "Återstående användningar"
|
||||
"inviteRemainingUses": "Återstående användningar",
|
||||
"send": "Skicka",
|
||||
"linkDiscord": "Länka Discord",
|
||||
"copied": "Kopierat",
|
||||
"linkTelegram": "Länka Telegram",
|
||||
"contactEmail": "Kontakta via e-post",
|
||||
"contactTelegram": "Kontakta via Telegram",
|
||||
"refresh": "Uppdatera",
|
||||
"required": "Obligatoriskt",
|
||||
"contactDiscord": "Kontakt via Discord",
|
||||
"linkMatrix": "Länka Matrix",
|
||||
"reEnable": "Återaktivera",
|
||||
"disable": "Inaktivera",
|
||||
"contactMethods": "Kontaktmetoder",
|
||||
"accountStatus": "Kontostatus",
|
||||
"notSet": "Inte inställt"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "Användarnamnet och/eller lösenordet lämnades tomt.",
|
||||
@ -31,6 +46,5 @@
|
||||
"errorUnknown": "Okänt fel.",
|
||||
"error401Unauthorized": "Obehörig. Prova att uppdatera sidan.",
|
||||
"errorSaveSettings": "Det gick inte att spara inställningarna."
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,11 @@
|
||||
"pageTitle": "Créer un compte Jellyfin",
|
||||
"createAccountHeader": "Création du compte",
|
||||
"accountDetails": "Détails",
|
||||
"emailAddress": "Courriel",
|
||||
"emailAddress": "Email",
|
||||
"username": "Nom d'utilisateur",
|
||||
"password": "Mot de passe",
|
||||
"reEnterPassword": "Confirmez mot de passe",
|
||||
"reEnterPasswordInvalid": "Les mots de passe ne correspondent pas.",
|
||||
"reEnterPasswordInvalid": "Les mots de passe ne sont pas pareils.",
|
||||
"createAccountButton": "Créer le compte",
|
||||
"passwordRequirementsHeader": "Mot de passe requis",
|
||||
"successHeader": "Succès !",
|
||||
@ -35,7 +35,10 @@
|
||||
"editContactMethod": "Modifier le moyen de contact",
|
||||
"joinTheServer": "Rejoindre le serveur :",
|
||||
"customMessagePlaceholderHeader": "Personnaliser cette carte",
|
||||
"resetPassword": "Réinitialisation de mot de passe"
|
||||
"resetPassword": "Réinitialisation mot de passe",
|
||||
"referralsDescription": "Invitez vos amis et votre famille à Jellyfin avec ce lien. Revenez ici pour en obtenir un nouveau s'il expire.",
|
||||
"copyReferral": "Copier le lien",
|
||||
"invitedBy": "Vous avez été invité par l'utilisateur {user}."
|
||||
},
|
||||
"validationStrings": {
|
||||
"length": {
|
||||
|
@ -8,7 +8,7 @@
|
||||
"back": "Retour",
|
||||
"optional": "Optionnel",
|
||||
"serverType": "Type de serveur",
|
||||
"disabled": "Désactivé",
|
||||
"disabled": "Désactiver",
|
||||
"enabled": "Activé",
|
||||
"port": "Port",
|
||||
"message": "Message",
|
||||
|
16
main.go
16
main.go
@ -24,6 +24,7 @@ import (
|
||||
"github.com/fatih/color"
|
||||
"github.com/hrfee/jfa-go/common"
|
||||
_ "github.com/hrfee/jfa-go/docs"
|
||||
"github.com/hrfee/jfa-go/easyproxy"
|
||||
"github.com/hrfee/jfa-go/logger"
|
||||
"github.com/hrfee/jfa-go/ombi"
|
||||
"github.com/hrfee/mediabrowser"
|
||||
@ -113,6 +114,9 @@ type appContext struct {
|
||||
newUpdate bool // Whether whatever's in update is new.
|
||||
tag Tag
|
||||
update Update
|
||||
proxyEnabled bool
|
||||
proxyTransport *http.Transport
|
||||
proxyConfig easyproxy.ProxyConfig
|
||||
internalPWRs map[string]InternalPWR
|
||||
ConfirmationKeys map[string]map[string]newUserDTO // Map of invite code to jwt to request
|
||||
confirmationKeysLock sync.Mutex
|
||||
@ -390,8 +394,18 @@ func start(asDaemon, firstCall bool) {
|
||||
if debugMode {
|
||||
app.jf.Verbose = true
|
||||
}
|
||||
|
||||
if app.proxyEnabled {
|
||||
app.jf.SetTransport(app.proxyTransport)
|
||||
}
|
||||
|
||||
var status int
|
||||
_, status, err = app.jf.Authenticate(app.config.Section("jellyfin").Key("username").String(), app.config.Section("jellyfin").Key("password").String())
|
||||
retryOpts := mediabrowser.MustAuthenticateOptions{
|
||||
RetryCount: app.config.Section("advanced").Key("auth_retry_count").MustInt(6),
|
||||
RetryGap: time.Duration(app.config.Section("advanced").Key("auth_retry_gap").MustInt(10)) * time.Second,
|
||||
LogFailures: true,
|
||||
}
|
||||
_, status, err = app.jf.MustAuthenticate(app.config.Section("jellyfin").Key("username").String(), app.config.Section("jellyfin").Key("password").String(), retryOpts)
|
||||
if status != 200 || err != nil {
|
||||
app.err.Fatalf("Failed to authenticate with Jellyfin @ \"%s\" (%d): %v", server, status, err)
|
||||
}
|
||||
|
@ -239,9 +239,9 @@ type NotificationPref struct {
|
||||
func (ombi *Ombi) SetNotificationPrefs(user map[string]interface{}, discordID, telegramUser string) (result string, code int, err error) {
|
||||
id := user["id"].(string)
|
||||
url := fmt.Sprintf("%s/api/v1/Identity/NotificationPreferences", ombi.server)
|
||||
var data []NotificationPref
|
||||
data := []NotificationPref{}
|
||||
if discordID != "" {
|
||||
data = []NotificationPref{NotificationPref{NotifAgentDiscord, id, discordID, true}}
|
||||
data = append(data, NotificationPref{NotifAgentDiscord, id, discordID, true})
|
||||
}
|
||||
if telegramUser != "" {
|
||||
data = append(data, NotificationPref{NotifAgentTelegram, id, telegramUser, true})
|
||||
|
39
router.go
39
router.go
@ -160,12 +160,11 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
||||
|
||||
api := router.Group("/", app.webAuth())
|
||||
|
||||
var user *gin.RouterGroup
|
||||
if userPageEnabled {
|
||||
user = router.Group("/my", app.userAuth())
|
||||
}
|
||||
|
||||
for _, p := range routePrefixes {
|
||||
var user *gin.RouterGroup
|
||||
if userPageEnabled {
|
||||
user = router.Group(p+"/my", app.userAuth())
|
||||
}
|
||||
router.POST(p+"/logout", app.Logout)
|
||||
api.DELETE(p+"/users", app.DeleteUsers)
|
||||
api.GET(p+"/users", app.GetUsers)
|
||||
@ -234,22 +233,22 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
||||
}
|
||||
|
||||
if userPageEnabled {
|
||||
user.GET(p+"/details", app.MyDetails)
|
||||
user.POST(p+"/contact", app.SetMyContactMethods)
|
||||
user.POST(p+"/logout", app.LogoutUser)
|
||||
user.POST(p+"/email", app.ModifyMyEmail)
|
||||
user.GET(p+"/discord/invite", app.MyDiscordServerInvite)
|
||||
user.GET(p+"/pin/:service", app.GetMyPIN)
|
||||
user.GET(p+"/discord/verified/:pin", app.MyDiscordVerifiedInvite)
|
||||
user.GET(p+"/telegram/verified/:pin", app.MyTelegramVerifiedInvite)
|
||||
user.POST(p+"/matrix/user", app.MatrixSendMyPIN)
|
||||
user.GET(p+"/matrix/verified/:userID/:pin", app.MatrixCheckMyPIN)
|
||||
user.DELETE(p+"/discord", app.UnlinkMyDiscord)
|
||||
user.DELETE(p+"/telegram", app.UnlinkMyTelegram)
|
||||
user.DELETE(p+"/matrix", app.UnlinkMyMatrix)
|
||||
user.POST(p+"/password", app.ChangeMyPassword)
|
||||
user.GET("/details", app.MyDetails)
|
||||
user.POST("/contact", app.SetMyContactMethods)
|
||||
user.POST("/logout", app.LogoutUser)
|
||||
user.POST("/email", app.ModifyMyEmail)
|
||||
user.GET("/discord/invite", app.MyDiscordServerInvite)
|
||||
user.GET("/pin/:service", app.GetMyPIN)
|
||||
user.GET("/discord/verified/:pin", app.MyDiscordVerifiedInvite)
|
||||
user.GET("/telegram/verified/:pin", app.MyTelegramVerifiedInvite)
|
||||
user.POST("/matrix/user", app.MatrixSendMyPIN)
|
||||
user.GET("/matrix/verified/:userID/:pin", app.MatrixCheckMyPIN)
|
||||
user.DELETE("/discord", app.UnlinkMyDiscord)
|
||||
user.DELETE("/telegram", app.UnlinkMyTelegram)
|
||||
user.DELETE("/matrix", app.UnlinkMyMatrix)
|
||||
user.POST("/password", app.ChangeMyPassword)
|
||||
if app.config.Section("user_page").Key("referrals").MustBool(false) {
|
||||
user.GET(p+"/referral", app.GetMyReferral)
|
||||
user.GET("/referral", app.GetMyReferral)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ window.onpopstate = (event: PopStateEvent) => {
|
||||
window.tabs.switch(event.state);
|
||||
}
|
||||
|
||||
const login = new Login(window.modals.login as Modal, "/");
|
||||
const login = new Login(window.modals.login as Modal, "/", window.loginAppearance);
|
||||
login.onLogin = () => {
|
||||
console.log("Logged in.");
|
||||
window.updater = new Updater();
|
||||
|
@ -8,13 +8,21 @@ export class Login {
|
||||
private _endpoint: string;
|
||||
private _onLogin: (username: string, password: string) => void;
|
||||
private _logoutButton: HTMLElement = null;
|
||||
private _wall: HTMLElement;
|
||||
private _hasOpacityWall: boolean = false;
|
||||
|
||||
constructor(modal: Modal, endpoint: string) {
|
||||
constructor(modal: Modal, endpoint: string, appearance: string) {
|
||||
this._endpoint = endpoint;
|
||||
this._url = window.URLBase + endpoint;
|
||||
if (this._url[this._url.length-1] != '/') this._url += "/";
|
||||
|
||||
this._modal = modal;
|
||||
if (appearance == "opaque") {
|
||||
this._hasOpacityWall = true;
|
||||
this._wall = document.createElement("div");
|
||||
this._wall.classList.add("wall");
|
||||
this._modal.asElement().parentElement.appendChild(this._wall);
|
||||
}
|
||||
this._form = this._modal.asElement().querySelector(".form-login") as HTMLFormElement;
|
||||
this._form.onsubmit = (event: SubmitEvent) => {
|
||||
event.preventDefault();
|
||||
@ -86,6 +94,7 @@ export class Login {
|
||||
if (this._onLogin) {
|
||||
this._onLogin(username, password);
|
||||
}
|
||||
if (this._hasOpacityWall) this._wall.remove();
|
||||
this._modal.close();
|
||||
if (this._logoutButton != null)
|
||||
this._logoutButton.classList.remove("unfocused");
|
||||
|
@ -41,6 +41,7 @@ declare interface Window {
|
||||
jfAdminOnly: boolean;
|
||||
jfAllowAll: boolean;
|
||||
referralsEnabled: boolean;
|
||||
loginAppearance: string;
|
||||
}
|
||||
|
||||
declare interface Update {
|
||||
|
@ -556,7 +556,6 @@ changePasswordButton.addEventListener("click", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
// FIXME: Submit & Validate
|
||||
|
||||
document.addEventListener("details-reload", () => {
|
||||
_get("/my/details", null, (req: XMLHttpRequest) => {
|
||||
@ -645,7 +644,7 @@ document.addEventListener("details-reload", () => {
|
||||
});
|
||||
});
|
||||
|
||||
const login = new Login(window.modals.login as Modal, "/my/");
|
||||
const login = new Login(window.modals.login as Modal, "/my/", "opaque");
|
||||
login.onLogin = () => {
|
||||
console.log("Logged in.");
|
||||
document.querySelector(".page-container").classList.remove("unfocused");
|
||||
|
@ -185,6 +185,11 @@ type BuildDTO struct {
|
||||
Tags map[string]Tag
|
||||
}
|
||||
|
||||
// SetTransport sets the http.Transport to use for requests. Can be used to set a proxy.
|
||||
func (ud *Updater) SetTransport(t *http.Transport) {
|
||||
ud.httpClient.Transport = t
|
||||
}
|
||||
|
||||
func (ud *Updater) GetTag() (Tag, int, error) {
|
||||
if ud.buildType == off {
|
||||
return Tag{}, -1, nil
|
||||
|
12
user-auth.go
12
user-auth.go
@ -1,6 +1,10 @@
|
||||
package main
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func (app *appContext) userAuth() gin.HandlerFunc {
|
||||
return app.userAuthenticate
|
||||
@ -60,7 +64,11 @@ func (app *appContext) getUserTokenLogin(gc *gin.Context) {
|
||||
}
|
||||
|
||||
app.debug.Printf("Token generated for non-admin user \"%s\"", username)
|
||||
gc.SetCookie("user-refresh", refresh, REFRESH_TOKEN_VALIDITY_SEC, "/my", gc.Request.URL.Hostname(), true, true)
|
||||
uri := "/my"
|
||||
if strings.HasPrefix(gc.Request.RequestURI, app.URLBase) {
|
||||
uri = "/accounts/my"
|
||||
}
|
||||
gc.SetCookie("user-refresh", refresh, REFRESH_TOKEN_VALIDITY_SEC, uri, gc.Request.URL.Hostname(), true, true)
|
||||
gc.JSON(200, getTokenDTO{token})
|
||||
}
|
||||
|
||||
|
2
views.go
2
views.go
@ -175,7 +175,9 @@ func (app *appContext) AdminPage(gc *gin.Context) {
|
||||
"jfAdminOnly": jfAdminOnly,
|
||||
"jfAllowAll": jfAllowAll,
|
||||
"userPageEnabled": app.config.Section("user_page").Key("enabled").MustBool(false),
|
||||
"showUserPageLink": app.config.Section("user_page").Key("show_link").MustBool(true),
|
||||
"referralsEnabled": app.config.Section("user_page").Key("enabled").MustBool(false) && app.config.Section("user_page").Key("referrals").MustBool(false),
|
||||
"loginAppearance": app.config.Section("ui").Key("login_appearance").MustString("clear"),
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user