mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
discord: modularize user-facing code
will be done for others too, code for discord account linking in form and userpage is now in ts/modules/account-linking.ts as a configurable class.
This commit is contained in:
parent
cf7983ca11
commit
765a749959
78
ts/form.ts
78
ts/form.ts
@ -1,8 +1,9 @@
|
|||||||
import { Modal } from "./modules/modal.js";
|
import { Modal } from "./modules/modal.js";
|
||||||
import { notificationBox, whichAnimationEvent } from "./modules/common.js";
|
import { notificationBox, whichAnimationEvent } from "./modules/common.js";
|
||||||
import { _get, _post, toggleLoader, addLoader, removeLoader, toDateString, DiscordInvite } 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";
|
||||||
|
|
||||||
interface formWindow extends Window {
|
interface formWindow extends Window {
|
||||||
invalidPassword: string;
|
invalidPassword: string;
|
||||||
@ -95,61 +96,32 @@ var discordVerified = false;
|
|||||||
if (window.discordEnabled) {
|
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;
|
||||||
if (window.discordInviteLink) {
|
|
||||||
_get("/invite/" + window.code + "/discord/invite", null, (req: XMLHttpRequest) => {
|
const discordConf: DiscordConfiguration = {
|
||||||
if (req.readyState == 4) {
|
modal: window.discordModal as Modal,
|
||||||
if (req.status != 200) {
|
pin: window.discordPIN,
|
||||||
return;
|
inviteURL: window.discordInviteLink ? ("/invite/" + window.code + "/discord/invite") : "",
|
||||||
}
|
pinURL: "",
|
||||||
const inv = req.response as DiscordInvite;
|
verifiedURL: "/invite/" + window.code + "/discord/verified/",
|
||||||
const link = document.getElementById("discord-invite") as HTMLAnchorElement;
|
invalidCodeError: window.messages["errorInvalidCode"],
|
||||||
link.classList.add("subheading", "link-center");
|
accountLinkedError: window.messages["errorAccountLinked"],
|
||||||
link.href = inv.invite;
|
successError: window.messages["verified"],
|
||||||
link.target = "_blank";
|
successFunc: (modalClosed: boolean) => {
|
||||||
link.innerHTML = `<span class="img-circle lg mr-4"><img class="img-circle" src="${inv.icon}" width="64" height="64"></span>${window.discordServerName}`;
|
if (!modalClosed) {
|
||||||
|
discordButton.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-discord") as HTMLInputElement;
|
||||||
|
radio.parentElement.classList.remove("unfocused")
|
||||||
|
radio.checked = true;
|
||||||
|
validatorFunc();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
discordButton.onclick = () => {
|
|
||||||
const waiting = document.getElementById("discord-waiting") as HTMLSpanElement;
|
|
||||||
toggleLoader(waiting);
|
|
||||||
window.discordModal.show();
|
|
||||||
let modalClosed = false;
|
|
||||||
window.discordModal.onclose = () => {
|
|
||||||
modalClosed = true;
|
|
||||||
toggleLoader(waiting);
|
|
||||||
}
|
}
|
||||||
const checkVerified = () => _get("/invite/" + window.code + "/discord/verified/" + window.discordPIN, null, (req: XMLHttpRequest) => {
|
|
||||||
if (req.readyState == 4) {
|
|
||||||
if (req.status == 401) {
|
|
||||||
window.discordModal.close();
|
|
||||||
window.notifications.customError("invalidCodeError", window.messages["errorInvalidCode"]);
|
|
||||||
return;
|
|
||||||
} else if (req.status == 400) {
|
|
||||||
window.discordModal.close();
|
|
||||||
window.notifications.customError("accountLinkedError", window.messages["errorAccountLinked"]);
|
|
||||||
} else if (req.status == 200) {
|
|
||||||
if (req.response["success"] as boolean) {
|
|
||||||
discordVerified = true;
|
|
||||||
waiting.classList.add("~positive");
|
|
||||||
waiting.classList.remove("~info");
|
|
||||||
window.notifications.customPositive("discordVerified", "", window.messages["verified"]);
|
|
||||||
setTimeout(window.discordModal.close, 2000);
|
|
||||||
discordButton.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-discord") as HTMLInputElement;
|
|
||||||
radio.parentElement.classList.remove("unfocused")
|
|
||||||
radio.checked = true;
|
|
||||||
validatorFunc();
|
|
||||||
} else if (!modalClosed) {
|
|
||||||
setTimeout(checkVerified, 1500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
checkVerified();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const discord = new Discord(discordConf);
|
||||||
|
|
||||||
|
discordButton.onclick = discord.onclick;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matrixVerified = false;
|
var matrixVerified = false;
|
||||||
|
144
ts/modules/account-linking.ts
Normal file
144
ts/modules/account-linking.ts
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import { Modal } from "../modules/modal.js";
|
||||||
|
import { _get, _post, toggleLoader } from "../modules/common.js";
|
||||||
|
|
||||||
|
interface formWindow extends Window {
|
||||||
|
invalidPassword: string;
|
||||||
|
successModal: Modal;
|
||||||
|
telegramModal: Modal;
|
||||||
|
discordModal: Modal;
|
||||||
|
matrixModal: Modal;
|
||||||
|
confirmationModal: Modal;
|
||||||
|
redirectToJellyfin: boolean;
|
||||||
|
code: string;
|
||||||
|
messages: { [key: string]: string };
|
||||||
|
confirmation: boolean;
|
||||||
|
telegramRequired: boolean;
|
||||||
|
telegramPIN: string;
|
||||||
|
discordRequired: boolean;
|
||||||
|
discordPIN: string;
|
||||||
|
discordStartCommand: string;
|
||||||
|
discordInviteLink: boolean;
|
||||||
|
discordServerName: string;
|
||||||
|
matrixRequired: boolean;
|
||||||
|
matrixUserID: string;
|
||||||
|
userExpiryEnabled: boolean;
|
||||||
|
userExpiryMonths: number;
|
||||||
|
userExpiryDays: number;
|
||||||
|
userExpiryHours: number;
|
||||||
|
userExpiryMinutes: number;
|
||||||
|
userExpiryMessage: string;
|
||||||
|
emailRequired: boolean;
|
||||||
|
captcha: boolean;
|
||||||
|
reCAPTCHA: boolean;
|
||||||
|
reCAPTCHASiteKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare var window: formWindow;
|
||||||
|
|
||||||
|
export interface DiscordConfiguration {
|
||||||
|
modal: Modal;
|
||||||
|
pin: string;
|
||||||
|
inviteURL: string;
|
||||||
|
pinURL: string;
|
||||||
|
verifiedURL: string;
|
||||||
|
invalidCodeError: string;
|
||||||
|
accountLinkedError: string;
|
||||||
|
successError: string;
|
||||||
|
successFunc: (modalClosed: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface DiscordInvite {
|
||||||
|
invite: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Discord {
|
||||||
|
private _conf: DiscordConfiguration;
|
||||||
|
private _pinAcquired = false;
|
||||||
|
private _modalClosed = false;
|
||||||
|
private _waiting = document.getElementById("discord-waiting") as HTMLSpanElement;
|
||||||
|
private _verified = false;
|
||||||
|
|
||||||
|
get verified(): boolean { return this._verified; }
|
||||||
|
|
||||||
|
constructor(conf: DiscordConfiguration) {
|
||||||
|
this._conf = conf;
|
||||||
|
this._conf.modal.onclose = () => {
|
||||||
|
this._modalClosed = true;
|
||||||
|
toggleLoader(this._waiting);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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._pinAcquired) {
|
||||||
|
setTimeout(this._checkVerified, 1500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_get(this._conf.verifiedURL + this._conf.pin, null, (req: XMLHttpRequest) => {
|
||||||
|
if (req.readyState != 4) return;
|
||||||
|
if (req.status == 401) {
|
||||||
|
this._conf.modal.close();
|
||||||
|
window.notifications.customError("invalidCodeError", this._conf.invalidCodeError);
|
||||||
|
} else if (req.status == 400) {
|
||||||
|
this._conf.modal.close();
|
||||||
|
window.notifications.customError("accountLinkedError", this._conf.accountLinkedError);
|
||||||
|
} else if (req.status == 200) {
|
||||||
|
if (req.response["success"] as boolean) {
|
||||||
|
this._verified = true;
|
||||||
|
this._waiting.classList.add("~positive");
|
||||||
|
this._waiting.classList.remove("~info");
|
||||||
|
window.notifications.customPositive("discordVerified", "", this._conf.successError);
|
||||||
|
if (this._conf.successFunc) {
|
||||||
|
this._conf.successFunc(false);
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
this._conf.modal.close();
|
||||||
|
if (this._conf.successFunc) {
|
||||||
|
this._conf.successFunc(true);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
} else if (!this._modalClosed) {
|
||||||
|
setTimeout(this._checkVerified, 1500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onclick = () => {
|
||||||
|
if (this._conf.inviteURL != "") {
|
||||||
|
this._getInviteURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleLoader(this._waiting);
|
||||||
|
|
||||||
|
this._pinAcquired = false;
|
||||||
|
if (this._conf.pin) {
|
||||||
|
this._pinAcquired = true;
|
||||||
|
this._conf.modal.modal.querySelector(".pin").textContent = this._conf.pin;
|
||||||
|
} else {
|
||||||
|
_get(this._conf.pinURL, null, (req: XMLHttpRequest) => {
|
||||||
|
if (req.readyState == 4 && req.status == 200) {
|
||||||
|
this._conf.pin = req.response["pin"];
|
||||||
|
this._conf.modal.modal.querySelector(".pin").textContent = this._conf.pin;
|
||||||
|
this._pinAcquired = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this._modalClosed = false;
|
||||||
|
this._conf.modal.show();
|
||||||
|
|
||||||
|
this._checkVerified();
|
||||||
|
}
|
||||||
|
}
|
@ -221,8 +221,3 @@ export function insertText(textarea: HTMLTextAreaElement, text: string) {
|
|||||||
textarea.focus();
|
textarea.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DiscordInvite {
|
|
||||||
invite: string;
|
|
||||||
icon: string;
|
|
||||||
}
|
|
||||||
|
79
ts/user.ts
79
ts/user.ts
@ -1,8 +1,9 @@
|
|||||||
import { ThemeManager } from "./modules/theme.js";
|
import { ThemeManager } from "./modules/theme.js";
|
||||||
import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
|
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, DiscordInvite } 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";
|
||||||
|
|
||||||
interface userWindow extends Window {
|
interface userWindow extends Window {
|
||||||
jellyfinID: string;
|
jellyfinID: string;
|
||||||
@ -278,70 +279,22 @@ const addEditEmail = (add: boolean): void => {
|
|||||||
window.modals.email.show();
|
window.modals.email.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
let discordModalClosed = false;
|
const discordConf: DiscordConfiguration = {
|
||||||
let discordPIN = "";
|
modal: window.modals.discord as Modal,
|
||||||
const addEditDiscord = (add: boolean): void => {
|
pin: "",
|
||||||
if (window.discordInviteLink) {
|
inviteURL: window.discordInviteLink ? "/my/discord/invite" : "",
|
||||||
_get("/my/discord/invite", null, (req: XMLHttpRequest) => {
|
pinURL: "/my/pin/discord",
|
||||||
if (req.readyState == 4) {
|
verifiedURL: "/my/discord/verified/",
|
||||||
if (req.status != 200) return;
|
invalidCodeError: window.lang.notif("errorInvalidCode"),
|
||||||
const inv = req.response as DiscordInvite;
|
accountLinkedError: window.lang.notif("errorAccountLinked"),
|
||||||
const link = document.getElementById("discord-invite") as HTMLAnchorElement;
|
successError: window.lang.notif("verified"),
|
||||||
link.href = inv.invite;
|
successFunc: (modalClosed: boolean) => {
|
||||||
link.target = "_blank";
|
if (modalClosed) window.location.reload();
|
||||||
link.innerHTML = `<span class="img-circle lg mr-4"><img class="img-circle" src="${inv.icon}" width="64" height="64"></span>${window.discordServerName}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_get("/my/pin/discord", null, (req: XMLHttpRequest) => {
|
|
||||||
if (req.readyState == 4 && req.status == 200) {
|
|
||||||
discordPIN = req.response["pin"];
|
|
||||||
window.modals.discord.modal.querySelector(".pin").textContent = discordPIN;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const waiting = document.getElementById("discord-waiting") as HTMLSpanElement;
|
|
||||||
toggleLoader(waiting);
|
|
||||||
window.modals.discord.show();
|
|
||||||
discordModalClosed = false;
|
|
||||||
window.modals.discord.onclose = () => {
|
|
||||||
discordModalClosed = true;
|
|
||||||
toggleLoader(waiting);
|
|
||||||
}
|
|
||||||
const checkVerified = () => {
|
|
||||||
if (discordPIN == "") {
|
|
||||||
setTimeout(checkVerified, 1500);
|
|
||||||
}
|
|
||||||
if (discordModalClosed) return;
|
|
||||||
_get("/my/discord/verified/" + discordPIN, null, (req: XMLHttpRequest) => {
|
|
||||||
if (req.readyState != 4) return;
|
|
||||||
if (req.status == 401) {
|
|
||||||
window.modals.discord.close();
|
|
||||||
window.notifications.customError("invalidCodeError", window.lang.notif("errorInvalidCode"));
|
|
||||||
return;
|
|
||||||
} else if (req.status == 400) {
|
|
||||||
window.modals.discord.close();
|
|
||||||
window.notifications.customError("accountLinkedError", window.lang.notif("errorAccountLinked"));
|
|
||||||
} else if (req.status == 200) {
|
|
||||||
if (req.response["success"] as boolean) {
|
|
||||||
waiting.classList.add("~positive");
|
|
||||||
waiting.classList.remove("~info");
|
|
||||||
window.notifications.customPositive("discordVerified", "", window.lang.notif("verified"));
|
|
||||||
setTimeout(() => {
|
|
||||||
window.modals.discord.close;
|
|
||||||
window.location.reload();
|
|
||||||
}, 2000);
|
|
||||||
} else if (!discordModalClosed) {
|
|
||||||
setTimeout(checkVerified, 1500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
checkVerified();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let discord = new Discord(discordConf);
|
||||||
|
|
||||||
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) {
|
||||||
@ -368,7 +321,7 @@ document.addEventListener("details-reload", () => {
|
|||||||
|
|
||||||
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: addEditDiscord},
|
{name: "discord", icon: `<i class="ri-discord-fill ri-lg"></i>`, f: 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: null},
|
||||||
{name: "matrix", icon: `<span class="font-bold">[m]</span>`, f: null}
|
{name: "matrix", icon: `<span class="font-bold">[m]</span>`, f: null}
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user