mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-29 12:30:11 +00:00
Compare commits
3 Commits
765a749959
...
fcedea110d
Author | SHA1 | Date | |
---|---|---|---|
fcedea110d | |||
68aedf07ae | |||
094f7cea94 |
@ -26,11 +26,11 @@ before:
|
|||||||
- cp -r ts tempts
|
- cp -r ts tempts
|
||||||
- scripts/dark-variant.sh tempts
|
- scripts/dark-variant.sh tempts
|
||||||
- scripts/dark-variant.sh tempts/modules
|
- scripts/dark-variant.sh tempts/modules
|
||||||
- npx esbuild --bundle tempts/admin.ts --outfile=./data/web/js/admin.js --minify
|
- npx esbuild --target=es6 --format=esm --bundle tempts/admin.ts --outfile=./data/web/js/admin.js --minify
|
||||||
- npx esbuild --bundle tempts/pwr.ts --outfile=./data/web/js/pwr.js --minify
|
- npx esbuild --target=es6 --format=esm --bundle tempts/pwr.ts --outfile=./data/web/js/pwr.js --minify
|
||||||
- npx esbuild --bundle tempts/form.ts --outfile=./data/web/js/form.js --minify
|
- npx esbuild --target=es6 --format=esm --bundle tempts/form.ts --outfile=./data/web/js/form.js --minify
|
||||||
- npx esbuild --bundle tempts/setup.ts --outfile=./data/web/js/setup.js --minify
|
- npx esbuild --target=es6 --format=esm --bundle tempts/setup.ts --outfile=./data/web/js/setup.js --minify
|
||||||
- npx esbuild --bundle tempts/crash.ts --outfile=./data/crash.js --minify
|
- npx esbuild --target=es6 --format=esm --bundle tempts/crash.ts --outfile=./data/crash.js --minify
|
||||||
- rm -r tempts
|
- rm -r tempts
|
||||||
- npx esbuild --bundle css/base.css --outfile=./data/web/css/bundle.css --external:remixicon.css --minify
|
- npx esbuild --bundle css/base.css --outfile=./data/web/css/bundle.css --external:remixicon.css --minify
|
||||||
- cp html/crash.html data/
|
- cp html/crash.html data/
|
||||||
|
@ -329,8 +329,58 @@ func (app *appContext) MyDiscordVerifiedInvite(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dc := app.storage.discord
|
dc := app.storage.discord
|
||||||
|
existingUser, ok := app.storage.discord[gc.GetString("jfId")]
|
||||||
|
if ok {
|
||||||
|
dcUser.Lang = existingUser.Lang
|
||||||
|
dcUser.Contact = existingUser.Contact
|
||||||
|
}
|
||||||
dc[gc.GetString("jfId")] = dcUser
|
dc[gc.GetString("jfId")] = dcUser
|
||||||
app.storage.discord = dc
|
app.storage.discord = dc
|
||||||
app.storage.storeDiscordUsers()
|
app.storage.storeDiscordUsers()
|
||||||
respondBool(200, true, gc)
|
respondBool(200, true, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary Returns true/false on whether or not your telegram PIN was verified, and assigns the telegram user to you.
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} boolResponse
|
||||||
|
// @Failure 401 {object} boolResponse
|
||||||
|
// @Param pin path string true "PIN code to check"
|
||||||
|
// @Router /my/telegram/verified/{pin} [get]
|
||||||
|
// @tags User Page
|
||||||
|
func (app *appContext) MyTelegramVerifiedInvite(gc *gin.Context) {
|
||||||
|
pin := gc.Param("pin")
|
||||||
|
tokenIndex := -1
|
||||||
|
for i, v := range app.telegram.verifiedTokens {
|
||||||
|
if v.Token == pin {
|
||||||
|
tokenIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tokenIndex == -1 {
|
||||||
|
respondBool(200, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if app.config.Section("telegram").Key("require_unique").MustBool(false) {
|
||||||
|
for _, u := range app.storage.telegram {
|
||||||
|
if app.telegram.verifiedTokens[tokenIndex].Username == u.Username {
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tgUser := TelegramUser{
|
||||||
|
ChatID: app.telegram.verifiedTokens[tokenIndex].ChatID,
|
||||||
|
Username: app.telegram.verifiedTokens[tokenIndex].Username,
|
||||||
|
Contact: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
tg := app.storage.telegram
|
||||||
|
existingUser, ok := app.storage.telegram[gc.GetString("jfId")]
|
||||||
|
if ok {
|
||||||
|
tgUser.Lang = existingUser.Lang
|
||||||
|
tgUser.Contact = existingUser.Contact
|
||||||
|
}
|
||||||
|
tg[gc.GetString("jfId")] = tgUser
|
||||||
|
app.storage.storeTelegramUsers()
|
||||||
|
respondBool(200, true, gc)
|
||||||
|
}
|
||||||
|
@ -210,7 +210,9 @@ func (d *DiscordDaemon) NewTempInvite(ageSeconds, maxUses int) (inviteURL, iconU
|
|||||||
d.app.err.Printf("Discord: Failed to get guild: %v", err)
|
d.app.err.Printf("Discord: Failed to get guild: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// FIXME: Fix CSS, and handle no icon
|
||||||
iconURL = guild.IconURL("256")
|
iconURL = guild.IconURL("256")
|
||||||
|
fmt.Println("GOT ICON", iconURL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
52
html/account-linking.html
Normal file
52
html/account-linking.html
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{{ if .discordEnabled }}
|
||||||
|
<div id="modal-discord" class="modal">
|
||||||
|
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
||||||
|
<span class="heading mb-4">{{ .strings.linkDiscord }}</span>
|
||||||
|
<p class="content mb-4"> {{ .discordSendPINMessage }}</p>
|
||||||
|
<h1 class="text-center text-2xl mb-2 pin"></h1>
|
||||||
|
<div class="row center">
|
||||||
|
<a class="my-5 hover:underline">
|
||||||
|
<span class="mr-2">{{ .strings.joinTheServer }}</span>
|
||||||
|
<span id="discord-invite"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<span class="button ~info @low full-width center mt-4" id="discord-waiting">{{ .strings.success }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .telegramEnabled }}
|
||||||
|
<div id="modal-telegram" class="modal">
|
||||||
|
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
||||||
|
<span class="heading mb-4">{{ .strings.linkTelegram }}</span>
|
||||||
|
<p class="content mb-4">{{ .strings.sendPIN }}</p>
|
||||||
|
<p class="text-center text-2xl mb-2 pin"></p>
|
||||||
|
<a class="subheading link-center" href="{{ .telegramURL }}" target="_blank">
|
||||||
|
<span class="shield ~info mr-4">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="ri-telegram-line"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
@{{ .telegramUsername }}
|
||||||
|
</a>
|
||||||
|
<span class="button ~info @low full-width center mt-4" id="telegram-waiting">{{ .strings.success }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .matrixEnabled }}
|
||||||
|
<div id="modal-matrix" class="modal">
|
||||||
|
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
||||||
|
<span class="heading mb-4">{{ .strings.linkMatrix }}</span>
|
||||||
|
<p class="content mb-4"> {{ .strings.matrixEnterUser }}</p>
|
||||||
|
<input type="text" class="input ~neutral @high" placeholder="@user:riot.im" id="matrix-userid">
|
||||||
|
<div class="subheading link-center mt-4">
|
||||||
|
<span class="shield ~info mr-4">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="ri-chat-3-line"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
{{ .matrixUser }}
|
||||||
|
</div>
|
||||||
|
<span class="button ~info @low full-width center mt-4" id="matrix-send">{{ .strings.submit }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
@ -26,53 +26,7 @@
|
|||||||
<p class="content mb-4">{{ .strings.confirmationRequiredMessage }}</p>
|
<p class="content mb-4">{{ .strings.confirmationRequiredMessage }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ if .telegramEnabled }}
|
{{ template "account-linking.html" . }}
|
||||||
<div id="modal-telegram" class="modal">
|
|
||||||
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
|
||||||
<span class="heading mb-4">{{ .strings.linkTelegram }}</span>
|
|
||||||
<p class="content mb-4">{{ .strings.sendPIN }}</p>
|
|
||||||
<p class="text-center text-2xl mb-2">{{ .telegramPIN }}</p>
|
|
||||||
<a class="subheading link-center" href="{{ .telegramURL }}" target="_blank">
|
|
||||||
<span class="shield ~info mr-4">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="ri-telegram-line"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
@{{ .telegramUsername }}
|
|
||||||
</a>
|
|
||||||
<span class="button ~info @low full-width center mt-4" id="telegram-waiting">{{ .strings.success }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .discordEnabled }}
|
|
||||||
<div id="modal-discord" class="modal">
|
|
||||||
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
|
||||||
<span class="heading mb-4">{{ .strings.linkDiscord }}</span>
|
|
||||||
<p class="content mb-4"> {{ .discordSendPINMessage }}</p>
|
|
||||||
<h1 class="text-center text-2xl mb-2">{{ .discordPIN }}</h1>
|
|
||||||
<a id="discord-invite"></a>
|
|
||||||
<span class="button ~info @low full-width center mt-4" id="discord-waiting">{{ .strings.success }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
{{ if .matrixEnabled }}
|
|
||||||
<div id="modal-matrix" class="modal">
|
|
||||||
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
|
||||||
<span class="heading mb-4">{{ .strings.linkMatrix }}</span>
|
|
||||||
<p class="content mb-4"> {{ .strings.matrixEnterUser }}</p>
|
|
||||||
<input type="text" class="input ~neutral @high" placeholder="@user:riot.im" id="matrix-userid">
|
|
||||||
<div class="subheading link-center mt-4">
|
|
||||||
<span class="shield ~info mr-4">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="ri-chat-3-line"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
{{ .matrixUser }}
|
|
||||||
</div>
|
|
||||||
<span class="button ~info @low full-width center mt-4" id="matrix-send">{{ .strings.submit }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
<div class="top-4 left-4 absolute">
|
<div class="top-4 left-4 absolute">
|
||||||
<span class="dropdown" tabindex="0" id="lang-dropdown">
|
<span class="dropdown" tabindex="0" id="lang-dropdown">
|
||||||
<span class="button ~urge dropdown-button">
|
<span class="button ~urge dropdown-button">
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
window.language = "{{ .langName }}";
|
window.language = "{{ .langName }}";
|
||||||
window.telegramEnabled = {{ .telegramEnabled }};
|
window.telegramEnabled = {{ .telegramEnabled }};
|
||||||
window.telegramRequired = {{ .telegramRequired }};
|
window.telegramRequired = {{ .telegramRequired }};
|
||||||
|
window.telegramUsername = {{ .telegramUsername }};
|
||||||
|
window.telegramURL = {{ .telegramURL }};
|
||||||
window.emailEnabled = {{ .emailEnabled }};
|
window.emailEnabled = {{ .emailEnabled }};
|
||||||
window.emailRequired = {{ .emailRequired }};
|
window.emailRequired = {{ .emailRequired }};
|
||||||
window.discordEnabled = {{ .discordEnabled }};
|
window.discordEnabled = {{ .discordEnabled }};
|
||||||
@ -41,47 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="modal-discord" class="modal">
|
{{ template "account-linking.html" . }}
|
||||||
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
|
||||||
<span class="heading mb-4">{{ .strings.linkDiscord }}</span>
|
|
||||||
<p class="content mb-4"> {{ .discordSendPINMessage }}</p>
|
|
||||||
<h1 class="text-center text-2xl mb-2 pin"></h1>
|
|
||||||
<a id="discord-invite"></a>
|
|
||||||
<span class="button ~info @low full-width center mt-4" id="discord-waiting">{{ .strings.success }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="modal-telegram" class="modal">
|
|
||||||
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
|
||||||
<span class="heading mb-4">{{ .strings.linkTelegram }}</span>
|
|
||||||
<p class="content mb-4">{{ .strings.sendPIN }}</p>
|
|
||||||
<p class="text-center text-2xl mb-2">{{ .telegramPIN }}</p>
|
|
||||||
<a class="subheading link-center" href="{{ .telegramURL }}" target="_blank">
|
|
||||||
<span class="shield ~info mr-4">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="ri-telegram-line"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
@{{ .telegramUsername }}
|
|
||||||
</a>
|
|
||||||
<span class="button ~info @low full-width center mt-4" id="telegram-waiting">{{ .strings.success }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="modal-matrix" class="modal">
|
|
||||||
<div class="card relative mx-auto my-[10%] w-4/5 lg:w-1/3">
|
|
||||||
<span class="heading mb-4">{{ .strings.linkMatrix }}</span>
|
|
||||||
<p class="content mb-4"> {{ .strings.matrixEnterUser }}</p>
|
|
||||||
<input type="text" class="input ~neutral @high" placeholder="@user:riot.im" id="matrix-userid">
|
|
||||||
<div class="subheading link-center mt-4">
|
|
||||||
<span class="shield ~info mr-4">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="ri-chat-3-line"></i>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
{{ .matrixUser }}
|
|
||||||
</div>
|
|
||||||
<span class="button ~info @low full-width center mt-4" id="matrix-send">{{ .strings.submit }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="notification-box"></div>
|
<div id="notification-box"></div>
|
||||||
<div class="top-4 left-4 absolute">
|
<div class="top-4 left-4 absolute">
|
||||||
<span class="dropdown" tabindex="0" id="lang-dropdown">
|
<span class="dropdown" tabindex="0" id="lang-dropdown">
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
"sendPIN": "Send the PIN below to the bot, then come back here to link your account.",
|
"sendPIN": "Send the PIN below to the bot, then come back here to link your account.",
|
||||||
"sendPINDiscord": "Type {command} in {server_channel} on Discord, then send the PIN below.",
|
"sendPINDiscord": "Type {command} in {server_channel} on Discord, then send the PIN below.",
|
||||||
"matrixEnterUser": "Enter your User ID, press submit, and a PIN will be sent to you. Enter it here to continue.",
|
"matrixEnterUser": "Enter your User ID, press submit, and a PIN will be sent to you. Enter it here to continue.",
|
||||||
"welcomeUser": "Welcome, {user}!"
|
"welcomeUser": "Welcome, {user}!",
|
||||||
|
"joinTheServer": "Join the server:"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"errorUserExists": "User already exists.",
|
"errorUserExists": "User already exists.",
|
||||||
|
@ -234,6 +234,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
user.GET(p+"/discord/invite", app.MyDiscordServerInvite)
|
user.GET(p+"/discord/invite", app.MyDiscordServerInvite)
|
||||||
user.GET(p+"/pin/:service", app.GetMyPIN)
|
user.GET(p+"/pin/:service", app.GetMyPIN)
|
||||||
user.GET(p+"/discord/verified/:pin", app.MyDiscordVerifiedInvite)
|
user.GET(p+"/discord/verified/:pin", app.MyDiscordVerifiedInvite)
|
||||||
|
user.GET(p+"/telegram/verified/:pin", app.MyTelegramVerifiedInvite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,8 @@ module.exports = {
|
|||||||
d_urge: dark.d_urge,
|
d_urge: dark.d_urge,
|
||||||
d_warning: dark.d_warning,
|
d_warning: dark.d_warning,
|
||||||
d_info: dark.d_info,
|
d_info: dark.d_info,
|
||||||
d_critical: dark.d_critical
|
d_critical: dark.d_critical,
|
||||||
|
discord: "#5865F2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
85
ts/form.ts
85
ts/form.ts
@ -3,7 +3,7 @@ import { notificationBox, whichAnimationEvent } from "./modules/common.js";
|
|||||||
import { _get, _post, toggleLoader, addLoader, removeLoader, toDateString } from "./modules/common.js";
|
import { _get, _post, toggleLoader, addLoader, removeLoader, toDateString } from "./modules/common.js";
|
||||||
import { loadLangSelector } from "./modules/lang.js";
|
import { loadLangSelector } from "./modules/lang.js";
|
||||||
import { initValidator } from "./modules/validator.js";
|
import { initValidator } from "./modules/validator.js";
|
||||||
import { Discord, DiscordConfiguration } from "./modules/account-linking.js";
|
import { Discord, Telegram, ServiceConfiguration } from "./modules/account-linking.js";
|
||||||
|
|
||||||
interface formWindow extends Window {
|
interface formWindow extends Window {
|
||||||
invalidPassword: string;
|
invalidPassword: string;
|
||||||
@ -50,46 +50,31 @@ var telegramVerified = false;
|
|||||||
if (window.telegramEnabled) {
|
if (window.telegramEnabled) {
|
||||||
window.telegramModal = new Modal(document.getElementById("modal-telegram"), window.telegramRequired);
|
window.telegramModal = new Modal(document.getElementById("modal-telegram"), window.telegramRequired);
|
||||||
const telegramButton = document.getElementById("link-telegram") as HTMLSpanElement;
|
const telegramButton = document.getElementById("link-telegram") as HTMLSpanElement;
|
||||||
telegramButton.onclick = () => {
|
|
||||||
const waiting = document.getElementById("telegram-waiting") as HTMLSpanElement;
|
const telegramConf: ServiceConfiguration = {
|
||||||
toggleLoader(waiting);
|
modal: window.telegramModal as Modal,
|
||||||
window.telegramModal.show();
|
pin: window.telegramPIN,
|
||||||
let modalClosed = false;
|
pinURL: "",
|
||||||
window.telegramModal.onclose = () => {
|
verifiedURL: "/invite/" + window.code + "/telegram/verified/",
|
||||||
modalClosed = true;
|
invalidCodeError: window.messages["errorInvalidCode"],
|
||||||
toggleLoader(waiting);
|
accountLinkedError: window.messages["errorAccountLinked"],
|
||||||
|
successError: window.messages["verified"],
|
||||||
|
successFunc: (modalClosed: boolean) => {
|
||||||
|
if (modalClosed) return;
|
||||||
|
telegramVerified = true;
|
||||||
|
telegramButton.classList.add("unfocused");
|
||||||
|
document.getElementById("contact-via").classList.remove("unfocused");
|
||||||
|
document.getElementById("contact-via-email").parentElement.classList.remove("unfocused");
|
||||||
|
const radio = document.getElementById("contact-via-telegram") as HTMLInputElement;
|
||||||
|
radio.parentElement.classList.remove("unfocused");
|
||||||
|
radio.checked = true;
|
||||||
|
validatorFunc();
|
||||||
}
|
}
|
||||||
const checkVerified = () => _get("/invite/" + window.code + "/telegram/verified/" + window.telegramPIN, null, (req: XMLHttpRequest) => {
|
|
||||||
if (req.readyState == 4) {
|
|
||||||
if (req.status == 401) {
|
|
||||||
window.telegramModal.close();
|
|
||||||
window.notifications.customError("invalidCodeError", window.messages["errorInvalidCode"]);
|
|
||||||
return;
|
|
||||||
} else if (req.status == 400) {
|
|
||||||
window.telegramModal.close();
|
|
||||||
window.notifications.customError("accountLinkedError", window.messages["errorAccountLinked"]);
|
|
||||||
} else if (req.status == 200) {
|
|
||||||
if (req.response["success"] as boolean) {
|
|
||||||
telegramVerified = true;
|
|
||||||
waiting.classList.add("~positive");
|
|
||||||
waiting.classList.remove("~info");
|
|
||||||
window.notifications.customPositive("telegramVerified", "", window.messages["verified"]);
|
|
||||||
setTimeout(window.telegramModal.close, 2000);
|
|
||||||
telegramButton.classList.add("unfocused");
|
|
||||||
document.getElementById("contact-via").classList.remove("unfocused");
|
|
||||||
document.getElementById("contact-via-email").parentElement.classList.remove("unfocused");
|
|
||||||
const radio = document.getElementById("contact-via-telegram") as HTMLInputElement;
|
|
||||||
radio.parentElement.classList.remove("unfocused");
|
|
||||||
radio.checked = true;
|
|
||||||
validatorFunc();
|
|
||||||
} else if (!modalClosed) {
|
|
||||||
setTimeout(checkVerified, 1500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
checkVerified();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const telegram = new Telegram(telegramConf);
|
||||||
|
|
||||||
|
telegramButton.onclick = () => { telegram.onclick(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
var discordVerified = false;
|
var discordVerified = false;
|
||||||
@ -97,7 +82,7 @@ if (window.discordEnabled) {
|
|||||||
window.discordModal = new Modal(document.getElementById("modal-discord"), window.discordRequired);
|
window.discordModal = new Modal(document.getElementById("modal-discord"), window.discordRequired);
|
||||||
const discordButton = document.getElementById("link-discord") as HTMLSpanElement;
|
const discordButton = document.getElementById("link-discord") as HTMLSpanElement;
|
||||||
|
|
||||||
const discordConf: DiscordConfiguration = {
|
const discordConf: ServiceConfiguration = {
|
||||||
modal: window.discordModal as Modal,
|
modal: window.discordModal as Modal,
|
||||||
pin: window.discordPIN,
|
pin: window.discordPIN,
|
||||||
inviteURL: window.discordInviteLink ? ("/invite/" + window.code + "/discord/invite") : "",
|
inviteURL: window.discordInviteLink ? ("/invite/" + window.code + "/discord/invite") : "",
|
||||||
@ -107,21 +92,21 @@ if (window.discordEnabled) {
|
|||||||
accountLinkedError: window.messages["errorAccountLinked"],
|
accountLinkedError: window.messages["errorAccountLinked"],
|
||||||
successError: window.messages["verified"],
|
successError: window.messages["verified"],
|
||||||
successFunc: (modalClosed: boolean) => {
|
successFunc: (modalClosed: boolean) => {
|
||||||
if (!modalClosed) {
|
if (modalClosed) return;
|
||||||
discordButton.classList.add("unfocused");
|
discordVerified = true;
|
||||||
document.getElementById("contact-via").classList.remove("unfocused");
|
discordButton.classList.add("unfocused");
|
||||||
document.getElementById("contact-via-email").parentElement.classList.remove("unfocused");
|
document.getElementById("contact-via").classList.remove("unfocused");
|
||||||
const radio = document.getElementById("contact-via-discord") as HTMLInputElement;
|
document.getElementById("contact-via-email").parentElement.classList.remove("unfocused");
|
||||||
radio.parentElement.classList.remove("unfocused")
|
const radio = document.getElementById("contact-via-discord") as HTMLInputElement;
|
||||||
radio.checked = true;
|
radio.parentElement.classList.remove("unfocused")
|
||||||
validatorFunc();
|
radio.checked = true;
|
||||||
}
|
validatorFunc();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const discord = new Discord(discordConf);
|
const discord = new Discord(discordConf);
|
||||||
|
|
||||||
discordButton.onclick = discord.onclick;
|
discordButton.onclick = () => { discord.onclick(); };
|
||||||
}
|
}
|
||||||
|
|
||||||
var matrixVerified = false;
|
var matrixVerified = false;
|
||||||
|
@ -35,10 +35,10 @@ interface formWindow extends Window {
|
|||||||
|
|
||||||
declare var window: formWindow;
|
declare var window: formWindow;
|
||||||
|
|
||||||
export interface DiscordConfiguration {
|
export interface ServiceConfiguration {
|
||||||
modal: Modal;
|
modal: Modal;
|
||||||
pin: string;
|
pin: string;
|
||||||
inviteURL: string;
|
inviteURL?: string;
|
||||||
pinURL: string;
|
pinURL: string;
|
||||||
verifiedURL: string;
|
verifiedURL: string;
|
||||||
invalidCodeError: string;
|
invalidCodeError: string;
|
||||||
@ -52,16 +52,17 @@ export interface DiscordInvite {
|
|||||||
icon: string;
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Discord {
|
export class ServiceLinker {
|
||||||
private _conf: DiscordConfiguration;
|
protected _conf: ServiceConfiguration;
|
||||||
private _pinAcquired = false;
|
protected _pinAcquired = false;
|
||||||
private _modalClosed = false;
|
protected _modalClosed = false;
|
||||||
private _waiting = document.getElementById("discord-waiting") as HTMLSpanElement;
|
protected _waiting: HTMLSpanElement;
|
||||||
private _verified = false;
|
protected _verified = false;
|
||||||
|
protected _name: string;
|
||||||
|
|
||||||
get verified(): boolean { return this._verified; }
|
get verified(): boolean { return this._verified; }
|
||||||
|
|
||||||
constructor(conf: DiscordConfiguration) {
|
constructor(conf: ServiceConfiguration) {
|
||||||
this._conf = conf;
|
this._conf = conf;
|
||||||
this._conf.modal.onclose = () => {
|
this._conf.modal.onclose = () => {
|
||||||
this._modalClosed = true;
|
this._modalClosed = true;
|
||||||
@ -69,16 +70,7 @@ export class Discord {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getInviteURL = () => _get(this._conf.inviteURL, null, (req: XMLHttpRequest) => {
|
protected _checkVerified = () => {
|
||||||
if (req.readyState != 4) return;
|
|
||||||
const inv = req.response as DiscordInvite;
|
|
||||||
const link = document.getElementById("discord-invite") as HTMLAnchorElement;
|
|
||||||
link.href = inv.invite;
|
|
||||||
link.target = "_blank";
|
|
||||||
link.innerHTML = `<span class="img-circle lg mr-4"><img class="img-circle" src="${inv.icon}" width="64" height="64"></span>${window.discordServerName}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
private _checkVerified = () => {
|
|
||||||
if (this._modalClosed) return;
|
if (this._modalClosed) return;
|
||||||
if (!this._pinAcquired) {
|
if (!this._pinAcquired) {
|
||||||
setTimeout(this._checkVerified, 1500);
|
setTimeout(this._checkVerified, 1500);
|
||||||
@ -97,7 +89,7 @@ export class Discord {
|
|||||||
this._verified = true;
|
this._verified = true;
|
||||||
this._waiting.classList.add("~positive");
|
this._waiting.classList.add("~positive");
|
||||||
this._waiting.classList.remove("~info");
|
this._waiting.classList.remove("~info");
|
||||||
window.notifications.customPositive("discordVerified", "", this._conf.successError);
|
window.notifications.customPositive(this._name + "Verified", "", this._conf.successError);
|
||||||
if (this._conf.successFunc) {
|
if (this._conf.successFunc) {
|
||||||
this._conf.successFunc(false);
|
this._conf.successFunc(false);
|
||||||
}
|
}
|
||||||
@ -115,18 +107,14 @@ export class Discord {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onclick = () => {
|
onclick() {
|
||||||
if (this._conf.inviteURL != "") {
|
|
||||||
this._getInviteURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleLoader(this._waiting);
|
toggleLoader(this._waiting);
|
||||||
|
|
||||||
this._pinAcquired = false;
|
this._pinAcquired = false;
|
||||||
if (this._conf.pin) {
|
if (this._conf.pin) {
|
||||||
this._pinAcquired = true;
|
this._pinAcquired = true;
|
||||||
this._conf.modal.modal.querySelector(".pin").textContent = this._conf.pin;
|
this._conf.modal.modal.querySelector(".pin").textContent = this._conf.pin;
|
||||||
} else {
|
} 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._conf.pin = req.response["pin"];
|
this._conf.pin = req.response["pin"];
|
||||||
@ -142,3 +130,45 @@ export class Discord {
|
|||||||
this._checkVerified();
|
this._checkVerified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class Discord extends ServiceLinker {
|
||||||
|
|
||||||
|
constructor(conf: ServiceConfiguration) {
|
||||||
|
super(conf);
|
||||||
|
this._name = "discord";
|
||||||
|
this._waiting = document.getElementById("discord-waiting") as HTMLSpanElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getInviteURL = () => _get(this._conf.inviteURL, null, (req: XMLHttpRequest) => {
|
||||||
|
if (req.readyState != 4) return;
|
||||||
|
const inv = req.response as DiscordInvite;
|
||||||
|
const link = document.getElementById("discord-invite") as HTMLSpanElement;
|
||||||
|
(link.parentElement as HTMLAnchorElement).href = inv.invite;
|
||||||
|
(link.parentElement as HTMLAnchorElement).target = "_blank";
|
||||||
|
let innerHTML = ``;
|
||||||
|
if (inv.icon != "") {
|
||||||
|
innerHTML += `<span class="img-circle lg mr-4"><img class="img-circle" src="${inv.icon}" width="64" height="64"></span>${window.discordServerName}`;
|
||||||
|
} else {
|
||||||
|
innerHTML += `
|
||||||
|
<span class="shield mr-4 bg-discord"><i class="ri-discord-fill ri-xl text-white"></i></span>${window.discordServerName}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
link.innerHTML = innerHTML;
|
||||||
|
});
|
||||||
|
|
||||||
|
onclick() {
|
||||||
|
if (this._conf.inviteURL != "") {
|
||||||
|
this._getInviteURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onclick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Telegram extends ServiceLinker {
|
||||||
|
constructor(conf: ServiceConfiguration) {
|
||||||
|
super(conf);
|
||||||
|
this._name = "telegram";
|
||||||
|
this._waiting = document.getElementById("telegram-waiting") as HTMLSpanElement;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../js",
|
"outDir": "../js",
|
||||||
"target": "es6",
|
"target": "es2017",
|
||||||
"lib": ["dom", "es2017"],
|
"lib": ["dom", "es2017"],
|
||||||
"typeRoots": ["./typings", "../node_modules/@types"],
|
"typeRoots": ["./typings", "../node_modules/@types"],
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "nodenext",
|
||||||
"esModuleInterop": true
|
"esModuleInterop": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
ts/user.ts
38
ts/user.ts
@ -3,7 +3,7 @@ import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
|
|||||||
import { Modal } from "./modules/modal.js";
|
import { Modal } from "./modules/modal.js";
|
||||||
import { _get, _post, notificationBox, whichAnimationEvent, toDateString, toggleLoader } from "./modules/common.js";
|
import { _get, _post, notificationBox, whichAnimationEvent, toDateString, toggleLoader } from "./modules/common.js";
|
||||||
import { Login } from "./modules/login.js";
|
import { Login } from "./modules/login.js";
|
||||||
import { Discord, DiscordConfiguration } from "./modules/account-linking.js";
|
import { Discord, Telegram, ServiceConfiguration } from "./modules/account-linking.js";
|
||||||
|
|
||||||
interface userWindow extends Window {
|
interface userWindow extends Window {
|
||||||
jellyfinID: string;
|
jellyfinID: string;
|
||||||
@ -35,9 +35,15 @@ window.modals = {} as Modals;
|
|||||||
(() => {
|
(() => {
|
||||||
window.modals.login = new Modal(document.getElementById("modal-login"), true);
|
window.modals.login = new Modal(document.getElementById("modal-login"), true);
|
||||||
window.modals.email = new Modal(document.getElementById("modal-email"), false);
|
window.modals.email = new Modal(document.getElementById("modal-email"), false);
|
||||||
window.modals.discord = new Modal(document.getElementById("modal-discord"), false);
|
if (window.discordEnabled) {
|
||||||
window.modals.telegram = new Modal(document.getElementById("modal-telegram"), false);
|
window.modals.discord = new Modal(document.getElementById("modal-discord"), false);
|
||||||
window.modals.matrix = new Modal(document.getElementById("modal-matrix"), false);
|
}
|
||||||
|
if (window.telegramEnabled) {
|
||||||
|
window.modals.telegram = new Modal(document.getElementById("modal-telegram"), false);
|
||||||
|
}
|
||||||
|
if (window.matrixEnabled) {
|
||||||
|
window.modals.matrix = new Modal(document.getElementById("modal-matrix"), false);
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
|
window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5);
|
||||||
@ -279,7 +285,7 @@ const addEditEmail = (add: boolean): void => {
|
|||||||
window.modals.email.show();
|
window.modals.email.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
const discordConf: DiscordConfiguration = {
|
const discordConf: ServiceConfiguration = {
|
||||||
modal: window.modals.discord as Modal,
|
modal: window.modals.discord as Modal,
|
||||||
pin: "",
|
pin: "",
|
||||||
inviteURL: window.discordInviteLink ? "/my/discord/invite" : "",
|
inviteURL: window.discordInviteLink ? "/my/discord/invite" : "",
|
||||||
@ -295,6 +301,21 @@ const discordConf: DiscordConfiguration = {
|
|||||||
|
|
||||||
let discord = new Discord(discordConf);
|
let discord = new Discord(discordConf);
|
||||||
|
|
||||||
|
const telegramConf: ServiceConfiguration = {
|
||||||
|
modal: window.modals.telegram as Modal,
|
||||||
|
pin: "",
|
||||||
|
pinURL: "/my/pin/telegram",
|
||||||
|
verifiedURL: "/my/telegram/verified/",
|
||||||
|
invalidCodeError: window.lang.notif("errorInvalidCode"),
|
||||||
|
accountLinkedError: window.lang.notif("errorAccountLinked"),
|
||||||
|
successError: window.lang.notif("verified"),
|
||||||
|
successFunc: (modalClosed: boolean) => {
|
||||||
|
if (modalClosed) window.location.reload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let telegram = new Telegram(telegramConf);
|
||||||
|
|
||||||
document.addEventListener("details-reload", () => {
|
document.addEventListener("details-reload", () => {
|
||||||
_get("/my/details", null, (req: XMLHttpRequest) => {
|
_get("/my/details", null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
@ -319,10 +340,13 @@ document.addEventListener("details-reload", () => {
|
|||||||
|
|
||||||
contactMethodList.clear();
|
contactMethodList.clear();
|
||||||
|
|
||||||
|
// Note the weird format of the functions for discord/telegram:
|
||||||
|
// "this" was being redefined within the onclick() method, so
|
||||||
|
// they had to be wrapped in an anonymous function.
|
||||||
const contactMethods: { name: string, icon: string, f: (add: boolean) => void }[] = [
|
const contactMethods: { name: string, icon: string, f: (add: boolean) => void }[] = [
|
||||||
{name: "email", icon: `<i class="ri-mail-fill ri-lg"></i>`, f: addEditEmail},
|
{name: "email", icon: `<i class="ri-mail-fill ri-lg"></i>`, f: addEditEmail},
|
||||||
{name: "discord", icon: `<i class="ri-discord-fill ri-lg"></i>`, f: discord.onclick},
|
{name: "discord", icon: `<i class="ri-discord-fill ri-lg"></i>`, f: (add: boolean) => { discord.onclick(); }},
|
||||||
{name: "telegram", icon: `<i class="ri-telegram-fill ri-lg"></i>`, f: null},
|
{name: "telegram", icon: `<i class="ri-telegram-fill ri-lg"></i>`, f: (add: boolean) => { telegram.onclick() }},
|
||||||
{name: "matrix", icon: `<span class="font-bold">[m]</span>`, f: null}
|
{name: "matrix", icon: `<span class="font-bold">[m]</span>`, f: null}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
2
views.go
2
views.go
@ -185,7 +185,7 @@ func (app *appContext) MyUserPage(gc *gin.Context) {
|
|||||||
"langName": lang,
|
"langName": lang,
|
||||||
}
|
}
|
||||||
if telegramEnabled {
|
if telegramEnabled {
|
||||||
data["telegramUser"] = app.telegram.username
|
data["telegramUsername"] = app.telegram.username
|
||||||
data["telegramURL"] = app.telegram.link
|
data["telegramURL"] = app.telegram.link
|
||||||
data["telegramRequired"] = app.config.Section("telegram").Key("required").MustBool(false)
|
data["telegramRequired"] = app.config.Section("telegram").Key("required").MustBool(false)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user