diff --git a/api.go b/api.go
index 6dd10c7..5dfbdcb 100644
--- a/api.go
+++ b/api.go
@@ -1277,10 +1277,14 @@ func (app *appContext) GetUsers(gc *gin.Context) {
user.Telegram = tgUser.Username
user.NotifyThroughTelegram = tgUser.Contact
}
- if dc, ok := app.storage.discord[jfUser.ID]; ok {
- user.Discord = dc.Username + "#" + dc.Discriminator
- user.DiscordID = dc.ID
- user.NotifyThroughDiscord = dc.Contact
+ if mxUser, ok := app.storage.matrix[jfUser.ID]; ok {
+ user.Matrix = mxUser.UserID
+ user.NotifyThroughMatrix = mxUser.Contact
+ }
+ if dcUser, ok := app.storage.discord[jfUser.ID]; ok {
+ user.Discord = dcUser.Username + "#" + dcUser.Discriminator
+ user.DiscordID = dcUser.ID
+ user.NotifyThroughDiscord = dcUser.Contact
}
resp.UserList[i] = user
i++
@@ -2127,6 +2131,7 @@ func (app *appContext) SetContactMethods(gc *gin.Context) {
return
}
if tgUser, ok := app.storage.telegram[req.ID]; ok {
+ change := tgUser.Contact != req.Telegram
tgUser.Contact = req.Telegram
app.storage.telegram[req.ID] = tgUser
if err := app.storage.storeTelegramUsers(); err != nil {
@@ -2134,13 +2139,16 @@ func (app *appContext) SetContactMethods(gc *gin.Context) {
app.err.Printf("Telegram: Failed to store users: %v", err)
return
}
- msg := ""
- if !req.Telegram {
- msg = " not"
+ if change {
+ msg := ""
+ if !req.Telegram {
+ msg = " not"
+ }
+ app.debug.Printf("Telegram: User \"%s\" will%s be notified through Telegram.", tgUser.Username, msg)
}
- app.debug.Printf("Telegram: User \"%s\" will%s be notified through Telegram.", tgUser.Username, msg)
}
if dcUser, ok := app.storage.discord[req.ID]; ok {
+ change := dcUser.Contact != req.Discord
dcUser.Contact = req.Discord
app.storage.discord[req.ID] = dcUser
if err := app.storage.storeDiscordUsers(); err != nil {
@@ -2148,13 +2156,33 @@ func (app *appContext) SetContactMethods(gc *gin.Context) {
app.err.Printf("Discord: Failed to store users: %v", err)
return
}
- msg := ""
- if !req.Discord {
- msg = " not"
+ if change {
+ msg := ""
+ if !req.Discord {
+ msg = " not"
+ }
+ app.debug.Printf("Discord: User \"%s\" will%s be notified through Discord.", dcUser.Username, msg)
+ }
+ }
+ if mxUser, ok := app.storage.matrix[req.ID]; ok {
+ change := mxUser.Contact != req.Matrix
+ mxUser.Contact = req.Matrix
+ app.storage.matrix[req.ID] = mxUser
+ if err := app.storage.storeMatrixUsers(); err != nil {
+ respondBool(500, false, gc)
+ app.err.Printf("Matrix: Failed to store users: %v", err)
+ return
+ }
+ if change {
+ msg := ""
+ if !req.Matrix {
+ msg = " not"
+ }
+ app.debug.Printf("Matrix: User \"%s\" will%s be notified through Matrix.", mxUser.UserID, msg)
}
- app.debug.Printf("Discord: User \"%s\" will%s be notified through Discord.", dcUser.Username, msg)
}
if email, ok := app.storage.emails[req.ID]; ok {
+ change := email.Contact != req.Email
email.Contact = req.Email
app.storage.emails[req.ID] = email
if err := app.storage.storeEmails(); err != nil {
@@ -2162,11 +2190,13 @@ func (app *appContext) SetContactMethods(gc *gin.Context) {
app.err.Printf("Failed to store emails: %v", err)
return
}
- msg := ""
- if !req.Email {
- msg = " not"
+ if change {
+ msg := ""
+ if !req.Email {
+ msg = " not"
+ }
+ app.debug.Printf("\"%s\" will%s be notified via Email.", email.Addr, msg)
}
- app.debug.Printf("\"%s\" will%s be notified via Email.", email.Addr, msg)
}
respondBool(200, true, gc)
}
diff --git a/html/admin.html b/html/admin.html
index 31db2b2..7591ed4 100644
--- a/html/admin.html
+++ b/html/admin.html
@@ -8,6 +8,7 @@
window.emailEnabled = {{ .email_enabled }};
window.telegramEnabled = {{ .telegram_enabled }};
window.discordEnabled = {{ .discord_enabled }};
+ window.matrixEnabled = {{ .matrix_enabled }};
window.ombiEnabled = {{ .ombiEnabled }};
window.usernameEnabled = {{ .username }};
window.langFile = JSON.parse({{ .language }});
@@ -545,6 +546,9 @@
{{ if .telegram_enabled }}
Telegram |
{{ end }}
+ {{ if .matrix_enabled }}
+ Matrix |
+ {{ end }}
{{ if .discord_enabled }}
Discord |
{{ end }}
diff --git a/models.go b/models.go
index 950ccaa..f75eefb 100644
--- a/models.go
+++ b/models.go
@@ -139,6 +139,8 @@ type respUser struct {
Discord string `json:"discord"` // Discord username (if known)
DiscordID string `json:"discord_id"` // Discord user ID for creating links.
NotifyThroughDiscord bool `json:"notify_discord"`
+ Matrix string `json:"matrix"` // Matrix ID (if known)
+ NotifyThroughMatrix bool `json:"notify_matrix"`
}
type getUsersDTO struct {
@@ -262,6 +264,7 @@ type SetContactMethodsDTO struct {
Email bool `json:"email"`
Discord bool `json:"discord"`
Telegram bool `json:"telegram"`
+ Matrix bool `json:"matrix"`
}
type DiscordUserDTO struct {
diff --git a/ts/modules/accounts.ts b/ts/modules/accounts.ts
index b00ef97..33a1b14 100644
--- a/ts/modules/accounts.ts
+++ b/ts/modules/accounts.ts
@@ -18,6 +18,8 @@ interface User {
discord: string;
notify_discord: boolean;
discord_id: string;
+ matrix: string;
+ notify_matrix: boolean;
}
interface getPinResponse {
@@ -44,13 +46,27 @@ class user implements User {
private _discordUsername: string;
private _discordID: string;
private _notifyDiscord: boolean;
+ private _matrix: HTMLTableDataCellElement;
+ private _matrixID: string;
+ private _notifyMatrix: boolean;
private _expiry: HTMLTableDataCellElement;
private _expiryUnix: number;
private _lastActive: HTMLTableDataCellElement;
private _lastActiveUnix: number;
+ private _notifyDropdown: HTMLDivElement;
id = "";
private _selected: boolean;
+ private _lastNotifyMethod = (): string => {
+ // Telegram, Matrix, Discord
+ const telegram = this._telegramUsername && this._telegramUsername != "";
+ const discord = this._discordUsername && this._discordUsername != "";
+ const matrix = this._matrixID && this._matrixID != "";
+ if (discord) return "discord";
+ if (matrix) return "matrix";
+ if (telegram) return "telegram";
+ }
+
get selected(): boolean { return this._selected; }
set selected(state: boolean) {
this._selected = state;
@@ -96,105 +112,146 @@ class user implements User {
get notify_email(): boolean { return this._notifyEmail; }
set notify_email(s: boolean) {
- this._notifyEmail = s;
- if (window.telegramEnabled && this._telegramUsername != "") {
- const email = this._telegram.getElementsByClassName("accounts-contact-email")[0] as HTMLInputElement;
- if (email) {
- email.checked = s;
+ if (this._notifyDropdown) {
+ (this._notifyDropdown.querySelector(".accounts-contact-email") as HTMLInputElement).checked = s;
+ }
+ }
+
+ private _constructDropdown = (): HTMLDivElement => {
+ const el = document.createElement("div") as HTMLDivElement;
+ const telegram = this._telegramUsername != "";
+ const discord = this._discordUsername != "";
+ const matrix = this._matrixID != "";
+ if (!telegram && !discord && !matrix) return;
+ let innerHTML = `
+
+
+ `;
+ el.innerHTML = innerHTML;
+ const button = el.querySelector("i");
+ const dropdown = el.querySelector("div.dropdown") as HTMLDivElement;
+ const checks = el.querySelectorAll("input") as NodeListOf;
+ for (let i = 0; i < checks.length; i++) {
+ checks[i].onclick = () => this._setNotifyMethod();
+ }
+
+ button.onclick = () => {
+ dropdown.classList.add("selected");
+ document.addEventListener("click", outerClickListener);
+ };
+ const outerClickListener = (event: Event) => {
+ if (!(event.target instanceof HTMLElement && (el.contains(event.target) || button.contains(event.target)))) {
+ dropdown.classList.remove("selected");
+ document.removeEventListener("click", outerClickListener);
+ }
+ };
+ return el;
+ }
+
+ get matrix(): string { return this._matrixID; }
+ set matrix(u: string) {
+ if (!window.matrixEnabled) {
+ this._notifyDropdown.querySelector(".accounts-area-matrix").classList.add("unfocused");
+ return;
+ }
+ const lastNotifyMethod = this._lastNotifyMethod() == "matrix";
+ this._matrixID = u;
+ if (!u) {
+ this._notifyDropdown.querySelector(".accounts-area-matrix").classList.add("unfocused");
+ this._matrix.innerHTML = `${window.lang.strings("add")}`;
+ // (this._matrix.querySelector("span") as HTMLSpanElement).onclick = this._addMatrix;
+ } else {
+ this._notifyDropdown.querySelector(".accounts-area-matrix").classList.remove("unfocused");
+ this._matrix.innerHTML = `
+
+ ${u}
+
+ `;
+ if (lastNotifyMethod) {
+ (this._matrix.querySelector(".table-inline") as HTMLDivElement).appendChild(this._notifyDropdown);
}
}
- if (window.discordEnabled && this._discordUsername) {
- const email = this._discord.getElementsByClassName("accounts-contact-email")[0] as HTMLInputElement;
- email.checked = s;
+ }
+
+ get notify_matrix(): boolean { return this._notifyMatrix; }
+ set notify_matrix(s: boolean) {
+ if (this._notifyDropdown) {
+ (this._notifyDropdown.querySelector(".accounts-contact-matrix") as HTMLInputElement).checked = s;
}
}
get telegram(): string { return this._telegramUsername; }
set telegram(u: string) {
- if (!window.telegramEnabled) return;
+ if (!window.telegramEnabled) {
+ this._notifyDropdown.querySelector(".accounts-area-telegram").classList.add("unfocused");
+ return;
+ }
+ const lastNotifyMethod = this._lastNotifyMethod() == "telegram";
this._telegramUsername = u;
- if (u == "") {
- this._telegram.innerHTML = `Add`;
+ if (!u) {
+ this._notifyDropdown.querySelector(".accounts-area-telegram").classList.add("unfocused");
+ this._telegram.innerHTML = `${window.lang.strings("add")}`;
(this._telegram.querySelector("span") as HTMLSpanElement).onclick = this._addTelegram;
} else {
- let innerHTML = `
+ this._notifyDropdown.querySelector(".accounts-area-telegram").classList.remove("unfocused");
+ this._telegram.innerHTML = `
`;
- if (!window.discordEnabled || !this._discordUsername) {
- innerHTML += `
-
-
- `;
- }
- innerHTML += "";
- this._telegram.innerHTML = innerHTML;
- if (!window.discordEnabled || !this._discordUsername) {
- // Javascript is necessary as including the button inside the dropdown would make it too wide to display next to the username.
- const button = this._telegram.querySelector("i");
- const dropdown = this._telegram.querySelector("div.dropdown") as HTMLDivElement;
- const checks = this._telegram.querySelectorAll("input") as NodeListOf;
- for (let i = 0; i < checks.length; i++) {
- checks[i].onclick = () => this._setNotifyMethod("telegram");
- }
-
- button.onclick = () => {
- dropdown.classList.add("selected");
- document.addEventListener("click", outerClickListener);
- };
- const outerClickListener = (event: Event) => {
- if (!(event.target instanceof HTMLElement && (this._telegram.contains(event.target) || button.contains(event.target)))) {
- dropdown.classList.remove("selected");
- document.removeEventListener("click", outerClickListener);
- }
- };
+ if (lastNotifyMethod) {
+ (this._telegram.querySelector(".table-inline") as HTMLDivElement).appendChild(this._notifyDropdown);
}
}
}
get notify_telegram(): boolean { return this._notifyTelegram; }
set notify_telegram(s: boolean) {
- if (!window.telegramEnabled || !this._telegramUsername) return;
- this._notifyTelegram = s;
- const telegram = this._telegram.getElementsByClassName("accounts-contact-telegram")[0] as HTMLInputElement;
- if (telegram) {
- telegram.checked = s;
- }
- if (window.discordEnabled && this._discordUsername) {
- const telegram = this._discord.getElementsByClassName("accounts-contact-telegram")[0] as HTMLInputElement;
- telegram.checked = s;
+ if (this._notifyDropdown) {
+ (this._notifyDropdown.querySelector(".accounts-contact-telegram") as HTMLInputElement).checked = s;
}
}
- private _setNotifyMethod = (mode: string = "telegram") => {
- let el: HTMLElement;
- if (mode == "telegram") { el = this._telegram }
- else if (mode == "discord") { el = this._discord }
- const email = el.getElementsByClassName("accounts-contact-email")[0] as HTMLInputElement;
+ private _setNotifyMethod = () => {
+ const email = this._notifyDropdown.getElementsByClassName("accounts-contact-email")[0] as HTMLInputElement;
let send = {
id: this.id,
email: email.checked
}
if (window.telegramEnabled && this._telegramUsername) {
- const telegram = el.getElementsByClassName("accounts-contact-telegram")[0] as HTMLInputElement;
+ const telegram = this._notifyDropdown.getElementsByClassName("accounts-contact-telegram")[0] as HTMLInputElement;
send["telegram"] = telegram.checked;
}
if (window.discordEnabled && this._discordUsername) {
- const discord = el.getElementsByClassName("accounts-contact-discord")[0] as HTMLInputElement;
+ const discord = this._notifyDropdown.getElementsByClassName("accounts-contact-discord")[0] as HTMLInputElement;
send["discord"] = discord.checked;
}
_post("/users/contact", send, (req: XMLHttpRequest) => {
@@ -219,62 +276,26 @@ class user implements User {
get discord(): string { return this._discordUsername; }
set discord(u: string) {
- if (!window.discordEnabled) return;
+ if (!window.discordEnabled) {
+ this._notifyDropdown.querySelector(".accounts-area-discord").classList.add("unfocused");
+ return;
+ }
+ const lastNotifyMethod = this._lastNotifyMethod() == "discord";
this._discordUsername = u;
- if (u == "") {
+ if (!u) {
this._discord.innerHTML = `Add`;
(this._discord.querySelector("span") as HTMLSpanElement).onclick = () => addDiscord(this.id);
+ this._notifyDropdown.querySelector(".accounts-area-discord").classList.add("unfocused");
} else {
- let innerHTML = `
+ this._notifyDropdown.querySelector(".accounts-area-discord").classList.remove("unfocused");
+ this._discord.innerHTML = `
`;
- this._discord.innerHTML = innerHTML;
- // Javascript is necessary as including the button inside the dropdown would make it too wide to display next to the username.
- const button = this._discord.querySelector("i");
- const dropdown = this._discord.querySelector("div.dropdown") as HTMLDivElement;
- const checks = this._discord.querySelectorAll("input") as NodeListOf;
- for (let i = 0; i < checks.length; i++) {
- checks[i].onclick = () => this._setNotifyMethod("discord");
+ if (lastNotifyMethod) {
+ (this._discord.querySelector(".table-inline") as HTMLDivElement).appendChild(this._notifyDropdown);
}
-
- button.onclick = () => {
- dropdown.classList.add("selected");
- document.addEventListener("click", outerClickListener);
- };
- const outerClickListener = (event: Event) => {
- if (!(event.target instanceof HTMLElement && (this._discord.contains(event.target) || button.contains(event.target)))) {
- dropdown.classList.remove("selected");
- document.removeEventListener("click", outerClickListener);
- }
- };
}
}
@@ -288,13 +309,8 @@ class user implements User {
get notify_discord(): boolean { return this._notifyDiscord; }
set notify_discord(s: boolean) {
- if (!window.discordEnabled || !this._discordUsername) return;
- this._notifyDiscord = s;
- const discord = this._discord.getElementsByClassName("accounts-contact-discord")[0] as HTMLInputElement;
- discord.checked = s;
- if (window.telegramEnabled && this._telegramUsername != "") {
- const discord = this._discord.getElementsByClassName("accounts-contact-discord")[0] as HTMLInputElement;
- discord.checked = s;
+ if (this._notifyDropdown) {
+ (this._notifyDropdown.querySelector(".accounts-contact-discord") as HTMLInputElement).checked = s;
}
}
@@ -333,6 +349,11 @@ class user implements User {
|
`;
}
+ if (window.matrixEnabled) {
+ innerHTML += `
+ |
+ `;
+ }
if (window.discordEnabled) {
innerHTML += `
|
@@ -352,10 +373,13 @@ class user implements User {
this._emailEditButton = this._row.querySelector(".accounts-email-edit") as HTMLElement;
this._telegram = this._row.querySelector(".accounts-telegram") as HTMLTableDataCellElement;
this._discord = this._row.querySelector(".accounts-discord") as HTMLTableDataCellElement;
+ this._matrix = this._row.querySelector(".accounts-matrix") as HTMLTableDataCellElement;
this._expiry = this._row.querySelector(".accounts-expiry") as HTMLTableDataCellElement;
this._lastActive = this._row.querySelector(".accounts-last-active") as HTMLTableDataCellElement;
this._check.onchange = () => { this.selected = this._check.checked; }
+ this._notifyDropdown = this._constructDropdown();
+
const toggleStealthInput = () => {
if (this._emailEditButton.classList.contains("ri-edit-line")) {
this._email.innerHTML = emailEditor;
@@ -458,14 +482,20 @@ class user implements User {
this.id = user.id;
this.name = user.name;
this.email = user.email || "";
+ // Little hack to get settings cogs to appear on first load
+ this._discordUsername = user.discord;
+ this._telegramUsername = user.telegram;
+ this._matrixID = user.matrix;
this.discord = user.discord;
this.telegram = user.telegram;
+ this.matrix = user.matrix;
this.last_active = user.last_active;
this.admin = user.admin;
this.disabled = user.disabled;
this.expiry = user.expiry;
this.notify_discord = user.notify_discord;
this.notify_telegram = user.notify_telegram;
+ this.notify_matrix = user.notify_matrix;
this.notify_email = user.notify_email;
this.discord_id = user.discord_id;
}
diff --git a/views.go b/views.go
index f463fd9..044e744 100644
--- a/views.go
+++ b/views.go
@@ -123,6 +123,7 @@ func (app *appContext) AdminPage(gc *gin.Context) {
"email_enabled": emailEnabled,
"telegram_enabled": telegramEnabled,
"discord_enabled": discordEnabled,
+ "matrix_enabled": matrixEnabled,
"notifications": notificationsEnabled,
"version": version,
"commit": commit,