mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-11-13 22:00:10 +00:00
Compare commits
No commits in common. "ebacfd43be5e292248a5e175afc56aac7e08c17c" and "920161b9208a538a6796b5d7ea3269562db4d374" have entirely different histories.
ebacfd43be
...
920161b920
@ -332,12 +332,18 @@ func (app *appContext) TelegramAddUser(gc *gin.Context) {
|
|||||||
respondBool(400, false, gc)
|
respondBool(400, false, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tgToken, ok := app.telegram.TokenVerified(req.Token)
|
tokenIndex := -1
|
||||||
app.telegram.DeleteVerifiedToken(req.Token)
|
for i, v := range app.telegram.verifiedTokens {
|
||||||
if !ok {
|
if v.Token == req.Token {
|
||||||
|
tokenIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tokenIndex == -1 {
|
||||||
respondBool(500, false, gc)
|
respondBool(500, false, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
tgToken := app.telegram.verifiedTokens[tokenIndex]
|
||||||
tgUser := TelegramUser{
|
tgUser := TelegramUser{
|
||||||
ChatID: tgToken.ChatID,
|
ChatID: tgToken.ChatID,
|
||||||
Username: tgToken.Username,
|
Username: tgToken.Username,
|
||||||
@ -346,7 +352,17 @@ func (app *appContext) TelegramAddUser(gc *gin.Context) {
|
|||||||
if lang, ok := app.telegram.languages[tgToken.ChatID]; ok {
|
if lang, ok := app.telegram.languages[tgToken.ChatID]; ok {
|
||||||
tgUser.Lang = lang
|
tgUser.Lang = lang
|
||||||
}
|
}
|
||||||
|
if app.storage.GetTelegram() == nil {
|
||||||
|
app.storage.telegram = telegramStore{}
|
||||||
|
}
|
||||||
app.storage.SetTelegramKey(req.ID, tgUser)
|
app.storage.SetTelegramKey(req.ID, tgUser)
|
||||||
|
err := app.storage.storeTelegramUsers()
|
||||||
|
if err != nil {
|
||||||
|
app.err.Printf("Failed to store Telegram users: %v", err)
|
||||||
|
} else {
|
||||||
|
app.telegram.verifiedTokens[len(app.telegram.verifiedTokens)-1], app.telegram.verifiedTokens[tokenIndex] = app.telegram.verifiedTokens[tokenIndex], app.telegram.verifiedTokens[len(app.telegram.verifiedTokens)-1]
|
||||||
|
app.telegram.verifiedTokens = app.telegram.verifiedTokens[:len(app.telegram.verifiedTokens)-1]
|
||||||
|
}
|
||||||
linkExistingOmbiDiscordTelegram(app)
|
linkExistingOmbiDiscordTelegram(app)
|
||||||
respondBool(200, true, gc)
|
respondBool(200, true, gc)
|
||||||
}
|
}
|
||||||
@ -446,8 +462,19 @@ func (app *appContext) setContactMethods(req SetContactMethodsDTO, gc *gin.Conte
|
|||||||
// @tags Other
|
// @tags Other
|
||||||
func (app *appContext) TelegramVerified(gc *gin.Context) {
|
func (app *appContext) TelegramVerified(gc *gin.Context) {
|
||||||
pin := gc.Param("pin")
|
pin := gc.Param("pin")
|
||||||
_, ok := app.telegram.TokenVerified(pin)
|
tokenIndex := -1
|
||||||
respondBool(200, ok, gc)
|
for i, v := range app.telegram.verifiedTokens {
|
||||||
|
if v.Token == pin {
|
||||||
|
tokenIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if tokenIndex != -1 {
|
||||||
|
// length := len(app.telegram.verifiedTokens)
|
||||||
|
// app.telegram.verifiedTokens[length-1], app.telegram.verifiedTokens[tokenIndex] = app.telegram.verifiedTokens[tokenIndex], app.telegram.verifiedTokens[length-1]
|
||||||
|
// app.telegram.verifiedTokens = app.telegram.verifiedTokens[:length-1]
|
||||||
|
// }
|
||||||
|
respondBool(200, tokenIndex != -1, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Returns true/false on whether or not a telegram PIN was verified. Requires invite code.
|
// @Summary Returns true/false on whether or not a telegram PIN was verified. Requires invite code.
|
||||||
@ -465,13 +492,27 @@ func (app *appContext) TelegramVerifiedInvite(gc *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
pin := gc.Param("pin")
|
pin := gc.Param("pin")
|
||||||
token, ok := app.telegram.TokenVerified(pin)
|
tokenIndex := -1
|
||||||
if ok && app.config.Section("telegram").Key("require_unique").MustBool(false) && app.telegram.UserExists(token.Username) {
|
for i, v := range app.telegram.verifiedTokens {
|
||||||
app.discord.DeleteVerifiedUser(pin)
|
if v.Token == pin {
|
||||||
respondBool(400, false, gc)
|
tokenIndex = i
|
||||||
return
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
respondBool(200, ok, gc)
|
if app.config.Section("telegram").Key("require_unique").MustBool(false) {
|
||||||
|
for _, u := range app.storage.GetTelegram() {
|
||||||
|
if app.telegram.verifiedTokens[tokenIndex].Username == u.Username {
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if tokenIndex != -1 {
|
||||||
|
// length := len(app.telegram.verifiedTokens)
|
||||||
|
// app.telegram.verifiedTokens[length-1], app.telegram.verifiedTokens[tokenIndex] = app.telegram.verifiedTokens[tokenIndex], app.telegram.verifiedTokens[length-1]
|
||||||
|
// app.telegram.verifiedTokens = app.telegram.verifiedTokens[:length-1]
|
||||||
|
// }
|
||||||
|
respondBool(200, tokenIndex != -1, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Returns true/false on whether or not a discord PIN was verified. Requires invite code.
|
// @Summary Returns true/false on whether or not a discord PIN was verified. Requires invite code.
|
||||||
@ -489,11 +530,15 @@ func (app *appContext) DiscordVerifiedInvite(gc *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
pin := gc.Param("pin")
|
pin := gc.Param("pin")
|
||||||
user, ok := app.discord.UserVerified(pin)
|
_, ok := app.discord.verifiedTokens[pin]
|
||||||
if ok && app.config.Section("discord").Key("require_unique").MustBool(false) && app.discord.UserExists(user.ID) {
|
if app.config.Section("discord").Key("require_unique").MustBool(false) {
|
||||||
delete(app.discord.verifiedTokens, pin)
|
for _, u := range app.storage.GetDiscord() {
|
||||||
respondBool(400, false, gc)
|
if app.discord.verifiedTokens[pin].ID == u.ID {
|
||||||
return
|
delete(app.discord.verifiedTokens, pin)
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
respondBool(200, ok, gc)
|
respondBool(200, ok, gc)
|
||||||
}
|
}
|
||||||
|
@ -301,10 +301,10 @@ func (app *appContext) GetMyPIN(gc *gin.Context) {
|
|||||||
resp := GetMyPINDTO{}
|
resp := GetMyPINDTO{}
|
||||||
switch service {
|
switch service {
|
||||||
case "discord":
|
case "discord":
|
||||||
resp.PIN = app.discord.NewAssignedAuthToken(gc.GetString("jfId"))
|
resp.PIN = app.discord.NewAuthToken()
|
||||||
break
|
break
|
||||||
case "telegram":
|
case "telegram":
|
||||||
resp.PIN = app.telegram.NewAssignedAuthToken(gc.GetString("jfId"))
|
resp.PIN = app.telegram.NewAuthToken()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
respond(400, "invalid service", gc)
|
respond(400, "invalid service", gc)
|
||||||
@ -322,15 +322,19 @@ func (app *appContext) GetMyPIN(gc *gin.Context) {
|
|||||||
// @tags User Page
|
// @tags User Page
|
||||||
func (app *appContext) MyDiscordVerifiedInvite(gc *gin.Context) {
|
func (app *appContext) MyDiscordVerifiedInvite(gc *gin.Context) {
|
||||||
pin := gc.Param("pin")
|
pin := gc.Param("pin")
|
||||||
dcUser, ok := app.discord.AssignedUserVerified(pin, gc.GetString("jfId"))
|
dcUser, ok := app.discord.verifiedTokens[pin]
|
||||||
app.discord.DeleteVerifiedUser(pin)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
respondBool(200, false, gc)
|
respondBool(200, false, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if app.config.Section("discord").Key("require_unique").MustBool(false) && app.discord.UserExists(dcUser.ID) {
|
if app.config.Section("discord").Key("require_unique").MustBool(false) {
|
||||||
respondBool(400, false, gc)
|
for _, u := range app.storage.GetDiscord() {
|
||||||
return
|
if app.discord.verifiedTokens[pin].ID == u.ID {
|
||||||
|
delete(app.discord.verifiedTokens, pin)
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
existingUser, ok := app.storage.GetDiscordKey(gc.GetString("jfId"))
|
existingUser, ok := app.storage.GetDiscordKey(gc.GetString("jfId"))
|
||||||
if ok {
|
if ok {
|
||||||
@ -350,24 +354,30 @@ func (app *appContext) MyDiscordVerifiedInvite(gc *gin.Context) {
|
|||||||
// @tags User Page
|
// @tags User Page
|
||||||
func (app *appContext) MyTelegramVerifiedInvite(gc *gin.Context) {
|
func (app *appContext) MyTelegramVerifiedInvite(gc *gin.Context) {
|
||||||
pin := gc.Param("pin")
|
pin := gc.Param("pin")
|
||||||
token, ok := app.telegram.AssignedTokenVerified(pin, gc.GetString("jfId"))
|
tokenIndex := -1
|
||||||
app.telegram.DeleteVerifiedToken(pin)
|
for i, v := range app.telegram.verifiedTokens {
|
||||||
if !ok {
|
if v.Token == pin {
|
||||||
|
tokenIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tokenIndex == -1 {
|
||||||
respondBool(200, false, gc)
|
respondBool(200, false, gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if app.config.Section("telegram").Key("require_unique").MustBool(false) && app.telegram.UserExists(token.Username) {
|
if app.config.Section("telegram").Key("require_unique").MustBool(false) {
|
||||||
respondBool(400, false, gc)
|
for _, u := range app.storage.GetTelegram() {
|
||||||
return
|
if app.telegram.verifiedTokens[tokenIndex].Username == u.Username {
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tgUser := TelegramUser{
|
tgUser := TelegramUser{
|
||||||
ChatID: token.ChatID,
|
ChatID: app.telegram.verifiedTokens[tokenIndex].ChatID,
|
||||||
Username: token.Username,
|
Username: app.telegram.verifiedTokens[tokenIndex].Username,
|
||||||
Contact: true,
|
Contact: true,
|
||||||
}
|
}
|
||||||
if lang, ok := app.telegram.languages[tgUser.ChatID]; ok {
|
|
||||||
tgUser.Lang = lang
|
|
||||||
}
|
|
||||||
|
|
||||||
existingUser, ok := app.storage.GetTelegramKey(gc.GetString("jfId"))
|
existingUser, ok := app.storage.GetTelegramKey(gc.GetString("jfId"))
|
||||||
if ok {
|
if ok {
|
||||||
|
50
api-users.go
50
api-users.go
@ -121,7 +121,7 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
discordUser, discordVerified = app.discord.UserVerified(req.DiscordPIN)
|
discordUser, discordVerified = app.discord.verifiedTokens[req.DiscordPIN]
|
||||||
if !discordVerified {
|
if !discordVerified {
|
||||||
f = func(gc *gin.Context) {
|
f = func(gc *gin.Context) {
|
||||||
app.debug.Printf("%s: New user failed: Discord PIN was invalid", req.Code)
|
app.debug.Printf("%s: New user failed: Discord PIN was invalid", req.Code)
|
||||||
@ -193,8 +193,7 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var tgToken TelegramVerifiedToken
|
telegramTokenIndex := -1
|
||||||
telegramVerified := false
|
|
||||||
if telegramEnabled {
|
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) {
|
||||||
@ -206,8 +205,13 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tgToken, telegramVerified = app.telegram.TokenVerified(req.TelegramPIN)
|
for i, v := range app.telegram.verifiedTokens {
|
||||||
if !telegramVerified {
|
if v.Token == req.TelegramPIN {
|
||||||
|
telegramTokenIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if telegramTokenIndex == -1 {
|
||||||
f = func(gc *gin.Context) {
|
f = func(gc *gin.Context) {
|
||||||
app.debug.Printf("%s: New user failed: Telegram PIN was invalid", req.Code)
|
app.debug.Printf("%s: New user failed: Telegram PIN was invalid", req.Code)
|
||||||
respond(401, "errorInvalidPIN", gc)
|
respond(401, "errorInvalidPIN", gc)
|
||||||
@ -215,13 +219,17 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
success = false
|
success = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if app.config.Section("telegram").Key("require_unique").MustBool(false) && app.telegram.UserExists(tgToken.Username) {
|
if app.config.Section("telegram").Key("require_unique").MustBool(false) {
|
||||||
f = func(gc *gin.Context) {
|
for _, u := range app.storage.GetTelegram() {
|
||||||
app.debug.Printf("%s: New user failed: Telegram user already linked", req.Code)
|
if app.telegram.verifiedTokens[telegramTokenIndex].Username == u.Username {
|
||||||
respond(400, "errorAccountLinked", gc)
|
f = func(gc *gin.Context) {
|
||||||
|
app.debug.Printf("%s: New user failed: Telegram user already linked", req.Code)
|
||||||
|
respond(400, "errorAccountLinked", gc)
|
||||||
|
}
|
||||||
|
success = false
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
success = false
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -344,7 +352,7 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
app.err.Printf("Failed to store user duration: %v", err)
|
app.err.Printf("Failed to store user duration: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if discordVerified {
|
if discordEnabled && discordVerified {
|
||||||
discordUser.Contact = req.DiscordContact
|
discordUser.Contact = req.DiscordContact
|
||||||
if app.storage.discord == nil {
|
if app.storage.discord == nil {
|
||||||
app.storage.discord = discordStore{}
|
app.storage.discord = discordStore{}
|
||||||
@ -356,7 +364,8 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
delete(app.discord.verifiedTokens, req.DiscordPIN)
|
delete(app.discord.verifiedTokens, req.DiscordPIN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if telegramVerified {
|
if telegramEnabled && telegramTokenIndex != -1 {
|
||||||
|
tgToken := app.telegram.verifiedTokens[telegramTokenIndex]
|
||||||
tgUser := TelegramUser{
|
tgUser := TelegramUser{
|
||||||
ChatID: tgToken.ChatID,
|
ChatID: tgToken.ChatID,
|
||||||
Username: tgToken.Username,
|
Username: tgToken.Username,
|
||||||
@ -368,8 +377,13 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
if app.storage.telegram == nil {
|
if app.storage.telegram == nil {
|
||||||
app.storage.telegram = telegramStore{}
|
app.storage.telegram = telegramStore{}
|
||||||
}
|
}
|
||||||
app.telegram.DeleteVerifiedToken(req.TelegramPIN)
|
|
||||||
app.storage.SetTelegramKey(user.ID, tgUser)
|
app.storage.SetTelegramKey(user.ID, tgUser)
|
||||||
|
if err := app.storage.storeTelegramUsers(); err != nil {
|
||||||
|
app.err.Printf("Failed to store Telegram users: %v", err)
|
||||||
|
} else {
|
||||||
|
app.telegram.verifiedTokens[len(app.telegram.verifiedTokens)-1], app.telegram.verifiedTokens[telegramTokenIndex] = app.telegram.verifiedTokens[telegramTokenIndex], app.telegram.verifiedTokens[len(app.telegram.verifiedTokens)-1]
|
||||||
|
app.telegram.verifiedTokens = app.telegram.verifiedTokens[:len(app.telegram.verifiedTokens)-1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if invite.Profile != "" && app.config.Section("ombi").Key("enabled").MustBool(false) {
|
if invite.Profile != "" && app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||||
if profile.Ombi != nil && len(profile.Ombi) != 0 {
|
if profile.Ombi != nil && len(profile.Ombi) != 0 {
|
||||||
@ -380,17 +394,17 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
|
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
|
||||||
} else {
|
} else {
|
||||||
app.info.Println("Created Ombi user")
|
app.info.Println("Created Ombi user")
|
||||||
if discordVerified || telegramVerified {
|
if (discordEnabled && discordVerified) || (telegramEnabled && telegramTokenIndex != -1) {
|
||||||
ombiUser, status, err := app.getOmbiUser(id)
|
ombiUser, status, err := app.getOmbiUser(id)
|
||||||
if status != 200 || err != nil {
|
if status != 200 || err != nil {
|
||||||
app.err.Printf("Failed to get Ombi user (%d): %v", status, err)
|
app.err.Printf("Failed to get Ombi user (%d): %v", status, err)
|
||||||
} else {
|
} else {
|
||||||
dID := ""
|
dID := ""
|
||||||
tUser := ""
|
tUser := ""
|
||||||
if discordVerified {
|
if discordEnabled && discordVerified {
|
||||||
dID = discordUser.ID
|
dID = discordUser.ID
|
||||||
}
|
}
|
||||||
if telegramVerified {
|
if telegramEnabled && telegramTokenIndex != -1 {
|
||||||
u, _ := app.storage.GetTelegramKey(user.ID)
|
u, _ := app.storage.GetTelegramKey(user.ID)
|
||||||
tUser = u.Username
|
tUser = u.Username
|
||||||
}
|
}
|
||||||
@ -417,7 +431,7 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
app.err.Printf("Failed to store Matrix users: %v", err)
|
app.err.Printf("Failed to store Matrix users: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (emailEnabled && app.config.Section("welcome_email").Key("enabled").MustBool(false) && req.Email != "") || telegramVerified || discordVerified || matrixVerified {
|
if (emailEnabled && app.config.Section("welcome_email").Key("enabled").MustBool(false) && req.Email != "") || telegramTokenIndex != -1 || discordVerified {
|
||||||
name := app.getAddressOrName(user.ID)
|
name := app.getAddressOrName(user.ID)
|
||||||
app.debug.Printf("%s: Sending welcome message to %s", req.Username, name)
|
app.debug.Printf("%s: Sending welcome message to %s", req.Username, name)
|
||||||
msg, err := app.email.constructWelcome(req.Username, expiry, app, false)
|
msg, err := app.email.constructWelcome(req.Username, expiry, app, false)
|
||||||
|
88
discord.go
88
discord.go
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
dg "github.com/bwmarrin/discordgo"
|
dg "github.com/bwmarrin/discordgo"
|
||||||
)
|
)
|
||||||
@ -13,8 +12,8 @@ type DiscordDaemon struct {
|
|||||||
ShutdownChannel chan string
|
ShutdownChannel chan string
|
||||||
bot *dg.Session
|
bot *dg.Session
|
||||||
username string
|
username string
|
||||||
tokens map[string]VerifToken // Map of pins to tokens.
|
tokens []string
|
||||||
verifiedTokens map[string]DiscordUser // Map of token pins to discord users.
|
verifiedTokens map[string]DiscordUser // Map of tokens to discord users.
|
||||||
channelID, channelName, inviteChannelID, inviteChannelName string
|
channelID, channelName, inviteChannelID, inviteChannelName string
|
||||||
guildID string
|
guildID string
|
||||||
serverChannelName, serverName string
|
serverChannelName, serverName string
|
||||||
@ -38,7 +37,7 @@ func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) {
|
|||||||
Stopped: false,
|
Stopped: false,
|
||||||
ShutdownChannel: make(chan string),
|
ShutdownChannel: make(chan string),
|
||||||
bot: bot,
|
bot: bot,
|
||||||
tokens: map[string]VerifToken{},
|
tokens: []string{},
|
||||||
verifiedTokens: map[string]DiscordUser{},
|
verifiedTokens: map[string]DiscordUser{},
|
||||||
users: map[string]DiscordUser{},
|
users: map[string]DiscordUser{},
|
||||||
app: app,
|
app: app,
|
||||||
@ -59,15 +58,7 @@ func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) {
|
|||||||
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
||||||
func (d *DiscordDaemon) NewAuthToken() string {
|
func (d *DiscordDaemon) NewAuthToken() string {
|
||||||
pin := genAuthToken()
|
pin := genAuthToken()
|
||||||
d.tokens[pin] = VerifToken{Expiry: time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second), JellyfinID: ""}
|
d.tokens = append(d.tokens, pin)
|
||||||
return pin
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAssignedAuthToken generates an 8-character pin in the form "A1-2B-CD",
|
|
||||||
// and assigns it for access only with the given Jellyfin ID.
|
|
||||||
func (d *DiscordDaemon) NewAssignedAuthToken(id string) string {
|
|
||||||
pin := genAuthToken()
|
|
||||||
d.tokens[pin] = VerifToken{Expiry: time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second), JellyfinID: id}
|
|
||||||
return pin
|
return pin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,8 +431,14 @@ func (d *DiscordDaemon) cmdStart(s *dg.Session, i *dg.InteractionCreate, lang st
|
|||||||
|
|
||||||
func (d *DiscordDaemon) cmdPIN(s *dg.Session, i *dg.InteractionCreate, lang string) {
|
func (d *DiscordDaemon) cmdPIN(s *dg.Session, i *dg.InteractionCreate, lang string) {
|
||||||
pin := i.ApplicationCommandData().Options[0].StringValue()
|
pin := i.ApplicationCommandData().Options[0].StringValue()
|
||||||
user, ok := d.tokens[pin]
|
tokenIndex := -1
|
||||||
if !ok || time.Now().After(user.Expiry) {
|
for i, token := range d.tokens {
|
||||||
|
if pin == token {
|
||||||
|
tokenIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tokenIndex == -1 {
|
||||||
err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{
|
err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{
|
||||||
// Type: dg.InteractionResponseChannelMessageWithSource,
|
// Type: dg.InteractionResponseChannelMessageWithSource,
|
||||||
Type: dg.InteractionResponseChannelMessageWithSource,
|
Type: dg.InteractionResponseChannelMessageWithSource,
|
||||||
@ -453,7 +450,6 @@ func (d *DiscordDaemon) cmdPIN(s *dg.Session, i *dg.InteractionCreate, lang stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", i.Interaction.Member.User.Username, err)
|
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", i.Interaction.Member.User.Username, err)
|
||||||
}
|
}
|
||||||
delete(d.tokens, pin)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{
|
err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{
|
||||||
@ -467,10 +463,9 @@ func (d *DiscordDaemon) cmdPIN(s *dg.Session, i *dg.InteractionCreate, lang stri
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", i.Interaction.Member.User.Username, err)
|
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", i.Interaction.Member.User.Username, err)
|
||||||
}
|
}
|
||||||
dcUser := d.users[i.Interaction.Member.User.ID]
|
d.verifiedTokens[pin] = d.users[i.Interaction.Member.User.ID]
|
||||||
dcUser.JellyfinID = user.JellyfinID
|
d.tokens[len(d.tokens)-1], d.tokens[tokenIndex] = d.tokens[tokenIndex], d.tokens[len(d.tokens)-1]
|
||||||
d.verifiedTokens[pin] = dcUser
|
d.tokens = d.tokens[:len(d.tokens)-1]
|
||||||
delete(d.tokens, pin)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DiscordDaemon) cmdLang(s *dg.Session, i *dg.InteractionCreate, lang string) {
|
func (d *DiscordDaemon) cmdLang(s *dg.Session, i *dg.InteractionCreate, lang string) {
|
||||||
@ -611,8 +606,14 @@ func (d *DiscordDaemon) msgPIN(s *dg.Session, m *dg.MessageCreate, sects []strin
|
|||||||
d.app.debug.Println("Discord: Ignoring message as user was not found")
|
d.app.debug.Println("Discord: Ignoring message as user was not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, ok := d.tokens[sects[0]]
|
tokenIndex := -1
|
||||||
if !ok || time.Now().After(user.Expiry) {
|
for i, token := range d.tokens {
|
||||||
|
if sects[0] == token {
|
||||||
|
tokenIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tokenIndex == -1 {
|
||||||
_, err := s.ChannelMessageSend(
|
_, err := s.ChannelMessageSend(
|
||||||
m.ChannelID,
|
m.ChannelID,
|
||||||
d.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"),
|
d.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"),
|
||||||
@ -620,7 +621,6 @@ func (d *DiscordDaemon) msgPIN(s *dg.Session, m *dg.MessageCreate, sects []strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
|
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
|
||||||
}
|
}
|
||||||
delete(d.tokens, sects[0])
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err := s.ChannelMessageSend(
|
_, err := s.ChannelMessageSend(
|
||||||
@ -630,10 +630,9 @@ func (d *DiscordDaemon) msgPIN(s *dg.Session, m *dg.MessageCreate, sects []strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
|
d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", m.Author.Username, err)
|
||||||
}
|
}
|
||||||
dcUser := d.users[m.Author.ID]
|
d.verifiedTokens[sects[0]] = d.users[m.Author.ID]
|
||||||
dcUser.JellyfinID = user.JellyfinID
|
d.tokens[len(d.tokens)-1], d.tokens[tokenIndex] = d.tokens[tokenIndex], d.tokens[len(d.tokens)-1]
|
||||||
d.verifiedTokens[sects[0]] = dcUser
|
d.tokens = d.tokens[:len(d.tokens)-1]
|
||||||
delete(d.tokens, sects[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DiscordDaemon) SendDM(message *Message, userID ...string) error {
|
func (d *DiscordDaemon) SendDM(message *Message, userID ...string) error {
|
||||||
@ -687,38 +686,3 @@ func (d *DiscordDaemon) Send(message *Message, channelID ...string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserVerified returns whether or not a token with the given PIN has been verified, and the user itself.
|
|
||||||
func (d *DiscordDaemon) UserVerified(pin string) (user DiscordUser, ok bool) {
|
|
||||||
user, ok = d.verifiedTokens[pin]
|
|
||||||
// delete(d.verifiedTokens, pin)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssignedUserVerified returns whether or not a user with the given PIN has been verified, and the token itself.
|
|
||||||
// Returns false if the given Jellyfin ID does not match the one in the user.
|
|
||||||
func (d *DiscordDaemon) AssignedUserVerified(pin string, jfID string) (user DiscordUser, ok bool) {
|
|
||||||
user, ok = d.verifiedTokens[pin]
|
|
||||||
if ok && user.JellyfinID != jfID {
|
|
||||||
ok = false
|
|
||||||
}
|
|
||||||
// delete(d.verifiedUsers, pin)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserExists returns whether or not a user with the given ID exists.
|
|
||||||
func (d *DiscordDaemon) UserExists(id string) (ok bool) {
|
|
||||||
ok = false
|
|
||||||
for _, u := range d.app.storage.GetDiscord() {
|
|
||||||
if u.ID == id {
|
|
||||||
ok = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteVerifiedUser removes the token with the given PIN.
|
|
||||||
func (d *DiscordDaemon) DeleteVerifiedUser(pin string) {
|
|
||||||
delete(d.verifiedTokens, pin)
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="{{ .cssClass }}">
|
<html lang="en" class="{{ .cssClass }}">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ .urlBase }}/css/{{ .cssVersion }}bundle.css">
|
<link rel="stylesheet" type="text/css" href="css/{{ .cssVersion }}bundle.css">
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
<title>{{ .strings.successHeader }} - jfa-go</title>
|
<title>{{ .strings.successHeader }} - jfa-go</title>
|
||||||
</head>
|
</head>
|
||||||
|
@ -69,11 +69,20 @@
|
|||||||
<span class="button ~warning" alt="{{ .strings.theme }}" id="button-theme"><i class="ri-sun-line"></i></span>
|
<span class="button ~warning" alt="{{ .strings.theme }}" id="button-theme"><i class="ri-sun-line"></i></span>
|
||||||
<span class="button ~critical @low mb-4 unfocused" id="logout-button">{{ .strings.logout }}</span>
|
<span class="button ~critical @low mb-4 unfocused" id="logout-button">{{ .strings.logout }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-container unfocused">
|
<div class="page-container">
|
||||||
<div class="card @low dark:~d_neutral mb-4" id="card-user">
|
<div class="card @low dark:~d_neutral mb-4" id="card-user">
|
||||||
<span class="heading mb-2"></span>
|
<span class="heading mb-2"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
|
<div class="card @low dark:~d_neutral unfocused" id="card-status">
|
||||||
|
<span class="heading mb-2">{{ .strings.expiry }}</span>
|
||||||
|
<aside class="aside ~warning user-expiry my-4"></aside>
|
||||||
|
<div class="user-expiry-countdown"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card @low dark:~d_neutral flex-col" id="card-contact">
|
||||||
|
<span class="heading mb-2">{{ .strings.contactMethods }}</span>
|
||||||
|
<div class="content flex justify-between flex-col h-100"></div>
|
||||||
|
</div>
|
||||||
{{ if index . "PageMessageEnabled" }}
|
{{ if index . "PageMessageEnabled" }}
|
||||||
{{ if .PageMessageEnabled }}
|
{{ if .PageMessageEnabled }}
|
||||||
<div class="card @low dark:~d_neutral content" id="card-message">
|
<div class="card @low dark:~d_neutral content" id="card-message">
|
||||||
@ -81,15 +90,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<div class="card @low dark:~d_neutral flex-col" id="card-contact">
|
|
||||||
<span class="heading mb-2">{{ .strings.contactMethods }}</span>
|
|
||||||
<div class="content flex justify-between flex-col h-100"></div>
|
|
||||||
</div>
|
|
||||||
<div class="card @low dark:~d_neutral unfocused" id="card-status">
|
|
||||||
<span class="heading mb-2">{{ .strings.expiry }}</span>
|
|
||||||
<aside class="aside ~warning user-expiry my-4"></aside>
|
|
||||||
<div class="user-expiry-countdown"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="{{ .urlBase }}/js/user.js" type="module"></script>
|
<script src="{{ .urlBase }}/js/user.js" type="module"></script>
|
||||||
|
@ -236,7 +236,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
user.GET(p+"/discord/verified/:pin", app.MyDiscordVerifiedInvite)
|
user.GET(p+"/discord/verified/:pin", app.MyDiscordVerifiedInvite)
|
||||||
user.GET(p+"/telegram/verified/:pin", app.MyTelegramVerifiedInvite)
|
user.GET(p+"/telegram/verified/:pin", app.MyTelegramVerifiedInvite)
|
||||||
user.POST(p+"/matrix/user", app.MatrixSendMyPIN)
|
user.POST(p+"/matrix/user", app.MatrixSendMyPIN)
|
||||||
user.GET(p+"/matrix/verified/:userID/:pin", app.MatrixCheckMyPIN)
|
user.POST(p+"/matrix/verified/:userID/:pin", app.MatrixCheckMyPIN)
|
||||||
user.DELETE(p+"/discord", app.UnlinkMyDiscord)
|
user.DELETE(p+"/discord", app.UnlinkMyDiscord)
|
||||||
user.DELETE(p+"/telegram", app.UnlinkMyTelegram)
|
user.DELETE(p+"/telegram", app.UnlinkMyTelegram)
|
||||||
user.DELETE(p+"/matrix", app.UnlinkMyMatrix)
|
user.DELETE(p+"/matrix", app.UnlinkMyMatrix)
|
||||||
|
19
storage.go
19
storage.go
@ -70,9 +70,6 @@ func (st *Storage) DeleteEmailsKey(k string) {
|
|||||||
|
|
||||||
// GetDiscord returns a copy of the store.
|
// GetDiscord returns a copy of the store.
|
||||||
func (st *Storage) GetDiscord() discordStore {
|
func (st *Storage) GetDiscord() discordStore {
|
||||||
if st.discord == nil {
|
|
||||||
st.discord = discordStore{}
|
|
||||||
}
|
|
||||||
return st.discord
|
return st.discord
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,9 +82,6 @@ func (st *Storage) GetDiscordKey(k string) (DiscordUser, bool) {
|
|||||||
// SetDiscordKey stores value v in key k.
|
// SetDiscordKey stores value v in key k.
|
||||||
func (st *Storage) SetDiscordKey(k string, v DiscordUser) {
|
func (st *Storage) SetDiscordKey(k string, v DiscordUser) {
|
||||||
st.discordLock.Lock()
|
st.discordLock.Lock()
|
||||||
if st.discord == nil {
|
|
||||||
st.discord = discordStore{}
|
|
||||||
}
|
|
||||||
st.discord[k] = v
|
st.discord[k] = v
|
||||||
st.storeDiscordUsers()
|
st.storeDiscordUsers()
|
||||||
st.discordLock.Unlock()
|
st.discordLock.Unlock()
|
||||||
@ -103,9 +97,6 @@ func (st *Storage) DeleteDiscordKey(k string) {
|
|||||||
|
|
||||||
// GetTelegram returns a copy of the store.
|
// GetTelegram returns a copy of the store.
|
||||||
func (st *Storage) GetTelegram() telegramStore {
|
func (st *Storage) GetTelegram() telegramStore {
|
||||||
if st.telegram == nil {
|
|
||||||
st.telegram = telegramStore{}
|
|
||||||
}
|
|
||||||
return st.telegram
|
return st.telegram
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,9 +109,6 @@ func (st *Storage) GetTelegramKey(k string) (TelegramUser, bool) {
|
|||||||
// SetTelegramKey stores value v in key k.
|
// SetTelegramKey stores value v in key k.
|
||||||
func (st *Storage) SetTelegramKey(k string, v TelegramUser) {
|
func (st *Storage) SetTelegramKey(k string, v TelegramUser) {
|
||||||
st.telegramLock.Lock()
|
st.telegramLock.Lock()
|
||||||
if st.telegram == nil {
|
|
||||||
st.telegram = telegramStore{}
|
|
||||||
}
|
|
||||||
st.telegram[k] = v
|
st.telegram[k] = v
|
||||||
st.storeTelegramUsers()
|
st.storeTelegramUsers()
|
||||||
st.telegramLock.Unlock()
|
st.telegramLock.Unlock()
|
||||||
@ -136,9 +124,6 @@ func (st *Storage) DeleteTelegramKey(k string) {
|
|||||||
|
|
||||||
// GetMatrix returns a copy of the store.
|
// GetMatrix returns a copy of the store.
|
||||||
func (st *Storage) GetMatrix() matrixStore {
|
func (st *Storage) GetMatrix() matrixStore {
|
||||||
if st.matrix == nil {
|
|
||||||
st.matrix = matrixStore{}
|
|
||||||
}
|
|
||||||
return st.matrix
|
return st.matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,9 +136,6 @@ func (st *Storage) GetMatrixKey(k string) (MatrixUser, bool) {
|
|||||||
// SetMatrixKey stores value v in key k.
|
// SetMatrixKey stores value v in key k.
|
||||||
func (st *Storage) SetMatrixKey(k string, v MatrixUser) {
|
func (st *Storage) SetMatrixKey(k string, v MatrixUser) {
|
||||||
st.matrixLock.Lock()
|
st.matrixLock.Lock()
|
||||||
if st.matrix == nil {
|
|
||||||
st.matrix = matrixStore{}
|
|
||||||
}
|
|
||||||
st.matrix[k] = v
|
st.matrix[k] = v
|
||||||
st.storeMatrixUsers()
|
st.storeMatrixUsers()
|
||||||
st.matrixLock.Unlock()
|
st.matrixLock.Unlock()
|
||||||
@ -181,7 +163,6 @@ type DiscordUser struct {
|
|||||||
Discriminator string
|
Discriminator string
|
||||||
Lang string
|
Lang string
|
||||||
Contact bool
|
Contact bool
|
||||||
JellyfinID string `json:"-"` // Used internally in discord.go
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type EmailAddress struct {
|
type EmailAddress struct {
|
||||||
|
95
telegram.go
95
telegram.go
@ -9,20 +9,10 @@ import (
|
|||||||
tg "github.com/go-telegram-bot-api/telegram-bot-api"
|
tg "github.com/go-telegram-bot-api/telegram-bot-api"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
VERIF_TOKEN_EXPIRY_SEC = 10 * 60
|
|
||||||
)
|
|
||||||
|
|
||||||
type TelegramVerifiedToken struct {
|
type TelegramVerifiedToken struct {
|
||||||
ChatID int64
|
Token string
|
||||||
Username string
|
ChatID int64
|
||||||
JellyfinID string // optional, for ensuring a user-requested change is only accessed by them.
|
Username string
|
||||||
}
|
|
||||||
|
|
||||||
// VerifToken stores details about a pending user verification token.
|
|
||||||
type VerifToken struct {
|
|
||||||
Expiry time.Time
|
|
||||||
JellyfinID string // optional, for ensuring a user-requested change is only accessed by them.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TelegramDaemon struct {
|
type TelegramDaemon struct {
|
||||||
@ -30,9 +20,9 @@ type TelegramDaemon struct {
|
|||||||
ShutdownChannel chan string
|
ShutdownChannel chan string
|
||||||
bot *tg.BotAPI
|
bot *tg.BotAPI
|
||||||
username string
|
username string
|
||||||
tokens map[string]VerifToken // Map of pins to tokens.
|
tokens []string
|
||||||
verifiedTokens map[string]TelegramVerifiedToken // Map of token pins to the responsible ChatID+Username.
|
verifiedTokens []TelegramVerifiedToken
|
||||||
languages map[int64]string // Store of languages for chatIDs. Added to on first interaction, and loaded from app.storage.telegram on start.
|
languages map[int64]string // Store of languages for chatIDs. Added to on first interaction, and loaded from app.storage.telegram on start.
|
||||||
link string
|
link string
|
||||||
app *appContext
|
app *appContext
|
||||||
}
|
}
|
||||||
@ -50,8 +40,8 @@ func newTelegramDaemon(app *appContext) (*TelegramDaemon, error) {
|
|||||||
ShutdownChannel: make(chan string),
|
ShutdownChannel: make(chan string),
|
||||||
bot: bot,
|
bot: bot,
|
||||||
username: bot.Self.UserName,
|
username: bot.Self.UserName,
|
||||||
tokens: map[string]VerifToken{},
|
tokens: []string{},
|
||||||
verifiedTokens: map[string]TelegramVerifiedToken{},
|
verifiedTokens: []TelegramVerifiedToken{},
|
||||||
languages: map[int64]string{},
|
languages: map[int64]string{},
|
||||||
link: "https://t.me/" + bot.Self.UserName,
|
link: "https://t.me/" + bot.Self.UserName,
|
||||||
app: app,
|
app: app,
|
||||||
@ -82,15 +72,7 @@ var runes = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
|||||||
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
// NewAuthToken generates an 8-character pin in the form "A1-2B-CD".
|
||||||
func (t *TelegramDaemon) NewAuthToken() string {
|
func (t *TelegramDaemon) NewAuthToken() string {
|
||||||
pin := genAuthToken()
|
pin := genAuthToken()
|
||||||
t.tokens[pin] = VerifToken{Expiry: time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second), JellyfinID: ""}
|
t.tokens = append(t.tokens, pin)
|
||||||
return pin
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAssignedAuthToken generates an 8-character pin in the form "A1-2B-CD",
|
|
||||||
// and assigns it for access only with the given Jellyfin ID.
|
|
||||||
func (t *TelegramDaemon) NewAssignedAuthToken(id string) string {
|
|
||||||
pin := genAuthToken()
|
|
||||||
t.tokens[pin] = VerifToken{Expiry: time.Now().Add(VERIF_TOKEN_EXPIRY_SEC * time.Second), JellyfinID: id}
|
|
||||||
return pin
|
return pin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,58 +212,29 @@ func (t *TelegramDaemon) commandLang(upd *tg.Update, sects []string, lang string
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TelegramDaemon) commandPIN(upd *tg.Update, sects []string, lang string) {
|
func (t *TelegramDaemon) commandPIN(upd *tg.Update, sects []string, lang string) {
|
||||||
token, ok := t.tokens[upd.Message.Text]
|
tokenIndex := -1
|
||||||
if !ok || time.Now().After(token.Expiry) {
|
for i, token := range t.tokens {
|
||||||
|
if upd.Message.Text == token {
|
||||||
|
tokenIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tokenIndex == -1 {
|
||||||
err := t.QuoteReply(upd, t.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"))
|
err := t.QuoteReply(upd, t.app.storage.lang.Telegram[lang].Strings.get("invalidPIN"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.app.err.Printf("Telegram: Failed to send message to \"%s\": %v", upd.Message.From.UserName, err)
|
t.app.err.Printf("Telegram: Failed to send message to \"%s\": %v", upd.Message.From.UserName, err)
|
||||||
}
|
}
|
||||||
delete(t.tokens, upd.Message.Text)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := t.QuoteReply(upd, t.app.storage.lang.Telegram[lang].Strings.get("pinSuccess"))
|
err := t.QuoteReply(upd, t.app.storage.lang.Telegram[lang].Strings.get("pinSuccess"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.app.err.Printf("Telegram: Failed to send message to \"%s\": %v", upd.Message.From.UserName, err)
|
t.app.err.Printf("Telegram: Failed to send message to \"%s\": %v", upd.Message.From.UserName, err)
|
||||||
}
|
}
|
||||||
t.verifiedTokens[upd.Message.Text] = TelegramVerifiedToken{
|
t.verifiedTokens = append(t.verifiedTokens, TelegramVerifiedToken{
|
||||||
ChatID: upd.Message.Chat.ID,
|
Token: upd.Message.Text,
|
||||||
Username: upd.Message.Chat.UserName,
|
ChatID: upd.Message.Chat.ID,
|
||||||
JellyfinID: token.JellyfinID,
|
Username: upd.Message.Chat.UserName,
|
||||||
}
|
})
|
||||||
delete(t.tokens, upd.Message.Text)
|
t.tokens[len(t.tokens)-1], t.tokens[tokenIndex] = t.tokens[tokenIndex], t.tokens[len(t.tokens)-1]
|
||||||
}
|
t.tokens = t.tokens[:len(t.tokens)-1]
|
||||||
|
|
||||||
// TokenVerified returns whether or not a token with the given PIN has been verified, and the token itself.
|
|
||||||
func (t *TelegramDaemon) TokenVerified(pin string) (token TelegramVerifiedToken, ok bool) {
|
|
||||||
token, ok = t.verifiedTokens[pin]
|
|
||||||
// delete(t.verifiedTokens, pin)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssignedTokenVerified returns whether or not a token with the given PIN has been verified, and the token itself.
|
|
||||||
// Returns false if the given Jellyfin ID does not match the one in the token.
|
|
||||||
func (t *TelegramDaemon) AssignedTokenVerified(pin string, jfID string) (token TelegramVerifiedToken, ok bool) {
|
|
||||||
token, ok = t.verifiedTokens[pin]
|
|
||||||
if ok && token.JellyfinID != jfID {
|
|
||||||
ok = false
|
|
||||||
}
|
|
||||||
// delete(t.verifiedTokens, pin)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserExists returns whether or not a user with the given username exists.
|
|
||||||
func (t *TelegramDaemon) UserExists(username string) (ok bool) {
|
|
||||||
ok = false
|
|
||||||
for _, u := range t.app.storage.GetTelegram() {
|
|
||||||
if u.Username == username {
|
|
||||||
ok = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteVerifiedToken removes the token with the given PIN.
|
|
||||||
func (t *TelegramDaemon) DeleteVerifiedToken(pin string) {
|
|
||||||
delete(t.verifiedTokens, pin)
|
|
||||||
}
|
}
|
||||||
|
63
ts/form.ts
63
ts/form.ts
@ -176,31 +176,33 @@ let captchaInput = document.getElementById("captcha-input") as HTMLInputElement;
|
|||||||
const captchaCheckbox = document.getElementById("captcha-success") as HTMLSpanElement;
|
const captchaCheckbox = document.getElementById("captcha-success") as HTMLSpanElement;
|
||||||
let prevCaptcha = "";
|
let prevCaptcha = "";
|
||||||
|
|
||||||
let baseValidator = (oncomplete: (valid: boolean) => void): void => {
|
function baseValidator(oncomplete: (valid: boolean) => void): void {
|
||||||
if (window.captcha && !window.reCAPTCHA && (captchaInput.value != prevCaptcha)) {
|
let captchaChecked = false;
|
||||||
prevCaptcha = captchaInput.value;
|
let captchaChange = false;
|
||||||
_post("/captcha/verify/" + window.code + "/" + captchaID + "/" + captchaInput.value, null, (req: XMLHttpRequest) => {
|
if (window.captcha && !window.reCAPTCHA) {
|
||||||
if (req.readyState == 4) {
|
captchaChange = captchaInput.value != prevCaptcha;
|
||||||
if (req.status == 204) {
|
if (captchaChange) {
|
||||||
captchaCheckbox.innerHTML = `<i class="ri-check-line"></i>`;
|
prevCaptcha = captchaInput.value;
|
||||||
captchaCheckbox.classList.add("~positive");
|
_post("/captcha/verify/" + window.code + "/" + captchaID + "/" + captchaInput.value, null, (req: XMLHttpRequest) => {
|
||||||
captchaCheckbox.classList.remove("~critical");
|
if (req.readyState == 4) {
|
||||||
captchaVerified = true;
|
if (req.status == 204) {
|
||||||
} else {
|
captchaCheckbox.innerHTML = `<i class="ri-check-line"></i>`;
|
||||||
captchaCheckbox.innerHTML = `<i class="ri-close-line"></i>`;
|
captchaCheckbox.classList.add("~positive");
|
||||||
captchaCheckbox.classList.add("~critical");
|
captchaCheckbox.classList.remove("~critical");
|
||||||
captchaCheckbox.classList.remove("~positive");
|
captchaVerified = true;
|
||||||
captchaVerified = false;
|
captchaChecked = true;
|
||||||
|
} else {
|
||||||
|
captchaCheckbox.innerHTML = `<i class="ri-close-line"></i>`;
|
||||||
|
captchaCheckbox.classList.add("~critical");
|
||||||
|
captchaCheckbox.classList.remove("~positive");
|
||||||
|
captchaVerified = false;
|
||||||
|
captchaChecked = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_baseValidator(oncomplete, captchaVerified);
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
} else {
|
|
||||||
_baseValidator(oncomplete, captchaVerified);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function _baseValidator(oncomplete: (valid: boolean) => void, captchaValid: boolean): void {
|
|
||||||
if (window.emailRequired) {
|
if (window.emailRequired) {
|
||||||
if (!emailField.value.includes("@")) {
|
if (!emailField.value.includes("@")) {
|
||||||
oncomplete(false);
|
oncomplete(false);
|
||||||
@ -219,11 +221,18 @@ function _baseValidator(oncomplete: (valid: boolean) => void, captchaValid: bool
|
|||||||
oncomplete(false);
|
oncomplete(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (window.captcha && !window.reCAPTCHA && !captchaValid) {
|
if (window.captcha && !window.reCAPTCHA) {
|
||||||
oncomplete(false);
|
if (!captchaChange) {
|
||||||
return;
|
oncomplete(captchaVerified);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (!captchaChecked) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
oncomplete(captchaVerified);
|
||||||
|
} else {
|
||||||
|
oncomplete(true);
|
||||||
}
|
}
|
||||||
oncomplete(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GreCAPTCHA {
|
interface GreCAPTCHA {
|
||||||
|
@ -59,7 +59,6 @@ export class ServiceLinker {
|
|||||||
protected _waiting: HTMLSpanElement;
|
protected _waiting: HTMLSpanElement;
|
||||||
protected _verified = false;
|
protected _verified = false;
|
||||||
protected _name: string;
|
protected _name: string;
|
||||||
protected _pin: string;
|
|
||||||
|
|
||||||
get verified(): boolean { return this._verified; }
|
get verified(): boolean { return this._verified; }
|
||||||
|
|
||||||
@ -77,7 +76,7 @@ export class ServiceLinker {
|
|||||||
setTimeout(this._checkVerified, 1500);
|
setTimeout(this._checkVerified, 1500);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_get(this._conf.verifiedURL + this._pin, null, (req: XMLHttpRequest) => {
|
_get(this._conf.verifiedURL + this._conf.pin, null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState != 4) return;
|
if (req.readyState != 4) return;
|
||||||
if (req.status == 401) {
|
if (req.status == 401) {
|
||||||
this._conf.modal.close();
|
this._conf.modal.close();
|
||||||
@ -112,16 +111,14 @@ export class ServiceLinker {
|
|||||||
toggleLoader(this._waiting);
|
toggleLoader(this._waiting);
|
||||||
|
|
||||||
this._pinAcquired = false;
|
this._pinAcquired = false;
|
||||||
this._pin = "";
|
|
||||||
if (this._conf.pin) {
|
if (this._conf.pin) {
|
||||||
this._pinAcquired = true;
|
this._pinAcquired = true;
|
||||||
this._pin = this._conf.pin;
|
this._conf.modal.modal.querySelector(".pin").textContent = this._conf.pin;
|
||||||
this._conf.modal.modal.querySelector(".pin").textContent = this._pin;
|
|
||||||
} else if (this._conf.pinURL) {
|
} else if (this._conf.pinURL) {
|
||||||
_get(this._conf.pinURL, null, (req: XMLHttpRequest) => {
|
_get(this._conf.pinURL, null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4 && req.status == 200) {
|
if (req.readyState == 4 && req.status == 200) {
|
||||||
this._pin = req.response["pin"];
|
this._conf.pin = req.response["pin"];
|
||||||
this._conf.modal.modal.querySelector(".pin").textContent = this._pin;
|
this._conf.modal.modal.querySelector(".pin").textContent = this._conf.pin;
|
||||||
this._pinAcquired = true;
|
this._pinAcquired = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -243,7 +240,7 @@ export class Matrix {
|
|||||||
this._input.value = "";
|
this._input.value = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
private _verifyCode = () => _get(this._conf.verifiedURL + this._userID + "/" + this._input.value, null, (req: XMLHttpRequest) => {
|
private _verifyCode = () => _post(this._conf.verifiedURL + this._userID + "/" + this._input.value, null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState != 4) return;
|
if (req.readyState != 4) return;
|
||||||
removeLoader(this._submit);
|
removeLoader(this._submit);
|
||||||
const valid = req.response["success"] as boolean;
|
const valid = req.response["success"] as boolean;
|
||||||
@ -264,6 +261,6 @@ export class Matrix {
|
|||||||
this._submit.classList.remove("~critical");
|
this._submit.classList.remove("~critical");
|
||||||
}, 800);
|
}, 800);
|
||||||
}
|
}
|
||||||
});
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
ts/user.ts
42
ts/user.ts
@ -48,7 +48,6 @@ window.modals = {} as Modals;
|
|||||||
|
|
||||||
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
|
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
|
||||||
|
|
||||||
const grid = document.querySelector(".grid");
|
|
||||||
var rootCard = document.getElementById("card-user");
|
var rootCard = document.getElementById("card-user");
|
||||||
var contactCard = document.getElementById("card-contact");
|
var contactCard = document.getElementById("card-contact");
|
||||||
var statusCard = document.getElementById("card-status");
|
var statusCard = document.getElementById("card-status");
|
||||||
@ -175,7 +174,7 @@ class ContactMethods {
|
|||||||
const deleteButton = row.querySelector(".user-contact-delete") as HTMLButtonElement;
|
const deleteButton = row.querySelector(".user-contact-delete") as HTMLButtonElement;
|
||||||
deleteButton.onclick = () => _delete("/my/" + name, null, (req: XMLHttpRequest) => {
|
deleteButton.onclick = () => _delete("/my/" + name, null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState != 4) return;
|
if (req.readyState != 4) return;
|
||||||
document.dispatchEvent(new CustomEvent("details-reload"));
|
window.location.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +288,7 @@ const addEditEmail = (add: boolean): void => {
|
|||||||
toggleLoader(submit);
|
toggleLoader(submit);
|
||||||
_post("/my/email", {"email": input.value}, (req: XMLHttpRequest) => {
|
_post("/my/email", {"email": input.value}, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4 && (req.status == 303 || req.status == 200)) {
|
if (req.readyState == 4 && (req.status == 303 || req.status == 200)) {
|
||||||
document.dispatchEvent(new CustomEvent("details-reload"));
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}, true, (req: XMLHttpRequest) => {
|
}, true, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4 && req.status == 401) {
|
if (req.readyState == 4 && req.status == 401) {
|
||||||
@ -312,7 +311,7 @@ const discordConf: ServiceConfiguration = {
|
|||||||
accountLinkedError: window.lang.notif("errorAccountLinked"),
|
accountLinkedError: window.lang.notif("errorAccountLinked"),
|
||||||
successError: window.lang.notif("verified"),
|
successError: window.lang.notif("verified"),
|
||||||
successFunc: (modalClosed: boolean) => {
|
successFunc: (modalClosed: boolean) => {
|
||||||
if (modalClosed) document.dispatchEvent(new CustomEvent("details-reload"));
|
if (modalClosed) window.location.reload();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -327,7 +326,7 @@ const telegramConf: ServiceConfiguration = {
|
|||||||
accountLinkedError: window.lang.notif("errorAccountLinked"),
|
accountLinkedError: window.lang.notif("errorAccountLinked"),
|
||||||
successError: window.lang.notif("verified"),
|
successError: window.lang.notif("verified"),
|
||||||
successFunc: (modalClosed: boolean) => {
|
successFunc: (modalClosed: boolean) => {
|
||||||
if (modalClosed) document.dispatchEvent(new CustomEvent("details-reload"));
|
if (modalClosed) window.location.reload();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -342,7 +341,7 @@ const matrixConf: MatrixConfiguration = {
|
|||||||
unknownError: window.lang.notif("errorUnknown"),
|
unknownError: window.lang.notif("errorUnknown"),
|
||||||
successError: window.lang.notif("verified"),
|
successError: window.lang.notif("verified"),
|
||||||
successFunc: () => {
|
successFunc: () => {
|
||||||
setTimeout(() => document.dispatchEvent(new CustomEvent("details-reload")), 1200);
|
setTimeout(() => window.location.reload(), 1200);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -392,13 +391,13 @@ document.addEventListener("details-reload", () => {
|
|||||||
expiryCard.expiry = details.expiry;
|
expiryCard.expiry = details.expiry;
|
||||||
|
|
||||||
|
|
||||||
let messageCard = document.getElementById("card-message");
|
|
||||||
if (details.accounts_admin) {
|
if (details.accounts_admin) {
|
||||||
|
let messageCard = document.getElementById("card-message")
|
||||||
if (typeof(messageCard) == "undefined" || messageCard == null) {
|
if (typeof(messageCard) == "undefined" || messageCard == null) {
|
||||||
messageCard = document.createElement("div");
|
messageCard = document.createElement("div");
|
||||||
messageCard.classList.add("card", "@low", "dark:~d_neutral", "content");
|
messageCard.classList.add("card", "@low", "dark:~d_neutral", "content");
|
||||||
messageCard.id = "card-message";
|
messageCard.id = "card-message";
|
||||||
contactCard.parentElement.insertBefore(messageCard, contactCard);
|
contactCard.parentElement.appendChild(messageCard);
|
||||||
}
|
}
|
||||||
if (!messageCard.textContent) {
|
if (!messageCard.textContent) {
|
||||||
messageCard.innerHTML = `
|
messageCard.innerHTML = `
|
||||||
@ -407,23 +406,6 @@ document.addEventListener("details-reload", () => {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof(messageCard) != "undefined" && messageCard != null) {
|
|
||||||
let largestNonMessageCardHeight = 0;
|
|
||||||
const cards = grid.querySelectorAll(".card") as NodeListOf<HTMLElement>;
|
|
||||||
for (let i = 0; i < cards.length; i++) {
|
|
||||||
if (cards[i].id == "card-message") continue;
|
|
||||||
if (computeRealHeight(cards[i]) > largestNonMessageCardHeight) {
|
|
||||||
largestNonMessageCardHeight = computeRealHeight(cards[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let rowSpan = Math.ceil(computeRealHeight(messageCard) / largestNonMessageCardHeight);
|
|
||||||
|
|
||||||
if (rowSpan > 0)
|
|
||||||
messageCard.style.gridRow = `span ${rowSpan}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -431,18 +413,10 @@ document.addEventListener("details-reload", () => {
|
|||||||
const login = new Login(window.modals.login as Modal, "/my/");
|
const login = new Login(window.modals.login as Modal, "/my/");
|
||||||
login.onLogin = () => {
|
login.onLogin = () => {
|
||||||
console.log("Logged in.");
|
console.log("Logged in.");
|
||||||
document.querySelector(".page-container").classList.remove("unfocused");
|
|
||||||
document.dispatchEvent(new CustomEvent("details-reload"));
|
document.dispatchEvent(new CustomEvent("details-reload"));
|
||||||
};
|
};
|
||||||
|
|
||||||
const computeRealHeight = (el: HTMLElement): number => {
|
|
||||||
let children = el.children as HTMLCollectionOf<HTMLElement>;
|
|
||||||
let total = 0;
|
|
||||||
for (let i = 0; i < children.length; i++) {
|
|
||||||
total += children[i].offsetHeight;
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
login.bindLogout(document.getElementById("logout-button"));
|
login.bindLogout(document.getElementById("logout-button"));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user