mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
Telegram: Change user's contact method in accounts
By clicking the cog next to the telegram username, one can select whether to contact through telegram or email.
This commit is contained in:
parent
0efd7c5718
commit
71554e0c85
37
api.go
37
api.go
@ -1176,6 +1176,7 @@ func (app *appContext) GetUsers(gc *gin.Context) {
|
|||||||
}
|
}
|
||||||
if tgUser, ok := app.storage.telegram[jfUser.ID]; ok {
|
if tgUser, ok := app.storage.telegram[jfUser.ID]; ok {
|
||||||
user.Telegram = tgUser.Username
|
user.Telegram = tgUser.Username
|
||||||
|
user.NotifyThroughTelegram = tgUser.Contact
|
||||||
}
|
}
|
||||||
resp.UserList[i] = user
|
resp.UserList[i] = user
|
||||||
i++
|
i++
|
||||||
@ -1991,6 +1992,42 @@ func (app *appContext) TelegramAddUser(gc *gin.Context) {
|
|||||||
respondBool(200, true, gc)
|
respondBool(200, true, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Summary Sets whether to notify a user through telegram or not.
|
||||||
|
// @Produce json
|
||||||
|
// @Param telegramNotifyDTO body telegramNotifyDTO true "User's Jellyfin ID and whether or not to notify then through Telegram."
|
||||||
|
// @Success 200 {object} boolResponse
|
||||||
|
// @Success 400 {object} boolResponse
|
||||||
|
// @Success 500 {object} boolResponse
|
||||||
|
// @Router /users/telegram/notify [post]
|
||||||
|
// @Security Bearer
|
||||||
|
// @tags Other
|
||||||
|
func (app *appContext) TelegramSetNotify(gc *gin.Context) {
|
||||||
|
var req telegramNotifyDTO
|
||||||
|
gc.BindJSON(&req)
|
||||||
|
if req.ID == "" {
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if tgUser, ok := app.storage.telegram[req.ID]; ok {
|
||||||
|
tgUser.Contact = req.Enabled
|
||||||
|
app.storage.telegram[req.ID] = tgUser
|
||||||
|
if err := app.storage.storeTelegramUsers(); err != nil {
|
||||||
|
respondBool(500, false, gc)
|
||||||
|
app.err.Printf("Telegram: Failed to store users: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respondBool(200, true, gc)
|
||||||
|
msg := ""
|
||||||
|
if !req.Enabled {
|
||||||
|
msg = "not"
|
||||||
|
}
|
||||||
|
app.debug.Printf("Telegram: User \"%s\" will %s be notified through Telegram.", tgUser.Username, msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
app.err.Printf("Telegram: User \"%s\" does not have a telegram account registered.", req.ID)
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
}
|
||||||
|
|
||||||
// @Summary Returns true/false on whether or not a telegram PIN was verified. Requires bearer auth.
|
// @Summary Returns true/false on whether or not a telegram PIN was verified. Requires bearer auth.
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Success 200 {object} boolResponse
|
// @Success 200 {object} boolResponse
|
||||||
|
@ -171,6 +171,12 @@ div.card:contains(section.banner.footer) {
|
|||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.sm,
|
||||||
|
span.sm {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.col.sm {
|
.col.sm {
|
||||||
margin: .25rem;
|
margin: .25rem;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"donate": "Donate",
|
"donate": "Donate",
|
||||||
|
"contactThrough": "Contact through:",
|
||||||
"extendExpiry": "Extend expiry",
|
"extendExpiry": "Extend expiry",
|
||||||
"customizeMessages": "Customize Messages",
|
"customizeMessages": "Customize Messages",
|
||||||
"customizeMessagesDescription": "If you don't want to use jfa-go's message templates, you can create your own using Markdown.",
|
"customizeMessagesDescription": "If you don't want to use jfa-go's message templates, you can create your own using Markdown.",
|
||||||
|
@ -130,6 +130,7 @@ type respUser struct {
|
|||||||
Expiry int64 `json:"expiry" example:"1617737207510"` // Expiry time of user as Epoch/Unix time.
|
Expiry int64 `json:"expiry" example:"1617737207510"` // Expiry time of user as Epoch/Unix time.
|
||||||
Disabled bool `json:"disabled"` // Whether or not the user is disabled.
|
Disabled bool `json:"disabled"` // Whether or not the user is disabled.
|
||||||
Telegram string `json:"telegram"` // Telegram username (if known)
|
Telegram string `json:"telegram"` // Telegram username (if known)
|
||||||
|
NotifyThroughTelegram bool `json:"notify_telegram"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type getUsersDTO struct {
|
type getUsersDTO struct {
|
||||||
@ -247,3 +248,8 @@ type telegramSetDTO struct {
|
|||||||
Token string `json:"token" example:"A1-B2-3C"`
|
Token string `json:"token" example:"A1-B2-3C"`
|
||||||
ID string `json:"id"` // Jellyfin ID of user.
|
ID string `json:"id"` // Jellyfin ID of user.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type telegramNotifyDTO struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
}
|
||||||
|
@ -162,6 +162,7 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
api.GET(p+"/telegram/pin", app.TelegramGetPin)
|
api.GET(p+"/telegram/pin", app.TelegramGetPin)
|
||||||
api.GET(p+"/telegram/verified/:pin", app.TelegramVerified)
|
api.GET(p+"/telegram/verified/:pin", app.TelegramVerified)
|
||||||
api.POST(p+"/users/telegram", app.TelegramAddUser)
|
api.POST(p+"/users/telegram", app.TelegramAddUser)
|
||||||
|
api.POST(p+"/users/telegram/notify", app.TelegramSetNotify)
|
||||||
}
|
}
|
||||||
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||||
api.GET(p+"/ombi/users", app.OmbiUsers)
|
api.GET(p+"/ombi/users", app.OmbiUsers)
|
||||||
|
@ -12,6 +12,7 @@ interface User {
|
|||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
expiry: number;
|
expiry: number;
|
||||||
telegram: string;
|
telegram: string;
|
||||||
|
notify_telegram: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface getPinResponse {
|
interface getPinResponse {
|
||||||
@ -30,6 +31,7 @@ class user implements User {
|
|||||||
private _emailEditButton: HTMLElement;
|
private _emailEditButton: HTMLElement;
|
||||||
private _telegram: HTMLTableDataCellElement;
|
private _telegram: HTMLTableDataCellElement;
|
||||||
private _telegramUsername: string;
|
private _telegramUsername: string;
|
||||||
|
private _notifyTelegram: boolean;
|
||||||
private _expiry: HTMLTableDataCellElement;
|
private _expiry: HTMLTableDataCellElement;
|
||||||
private _expiryUnix: number;
|
private _expiryUnix: number;
|
||||||
private _lastActive: HTMLTableDataCellElement;
|
private _lastActive: HTMLTableDataCellElement;
|
||||||
@ -88,10 +90,80 @@ class user implements User {
|
|||||||
this._telegram.innerHTML = `<span class="chip btn !low">Add</span>`;
|
this._telegram.innerHTML = `<span class="chip btn !low">Add</span>`;
|
||||||
(this._telegram.querySelector("span") as HTMLSpanElement).onclick = this._addTelegram;
|
(this._telegram.querySelector("span") as HTMLSpanElement).onclick = this._addTelegram;
|
||||||
} else {
|
} else {
|
||||||
this._telegram.innerHTML = `<a href="https://t.me/${u}" target="_blank">@${u}</a>`;
|
this._telegram.innerHTML = `
|
||||||
|
<a href="https://t.me/${u}" target="_blank">@${u}</a>
|
||||||
|
<i class="icon ri-settings-2-line ml-half dropdown-button"></i>
|
||||||
|
<div class="dropdown manual">
|
||||||
|
<div class="dropdown-display">
|
||||||
|
<div class="card ~neutral !low">
|
||||||
|
<span class="supra sm">${window.lang.strings("contactThrough")}</span>
|
||||||
|
<label class="switch pb-1 mt-half">
|
||||||
|
<input type="radio" name="accounts-contact-${this.id}" class="accounts-contact-email">
|
||||||
|
<span>Email</span>
|
||||||
|
</label>
|
||||||
|
<label class="switch pb-1">
|
||||||
|
<input type="radio" name="accounts-contact-${this.id}">
|
||||||
|
<span>Telegram</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
// 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 radios = this._telegram.querySelectorAll("input") as NodeListOf<HTMLInputElement>;
|
||||||
|
for (let i = 0; i < radios.length; i++) {
|
||||||
|
radios[i].onclick = this._setTelegramNotify;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get notify_telegram(): boolean { return this._notifyTelegram; }
|
||||||
|
set notify_telegram(s: boolean) {
|
||||||
|
if (!window.telegramEnabled || !this._telegramUsername) return;
|
||||||
|
this._notifyTelegram = s;
|
||||||
|
const radios = this._telegram.querySelectorAll("input") as NodeListOf<HTMLInputElement>;
|
||||||
|
radios[0].checked = !s;
|
||||||
|
radios[1].checked = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setTelegramNotify = () => {
|
||||||
|
const radios = this._telegram.querySelectorAll("input") as NodeListOf<HTMLInputElement>;
|
||||||
|
let send = {
|
||||||
|
id: this.id,
|
||||||
|
enabled: radios[1].checked
|
||||||
|
};
|
||||||
|
_post("/users/telegram/notify", send, (req: XMLHttpRequest) => {
|
||||||
|
if (req.readyState == 4) {
|
||||||
|
if (req.status != 200) {
|
||||||
|
window.notifications.customError("errorSetTelegramNotify", window.lang.notif("errorSaveSettings"));
|
||||||
|
radios[0].checked, radios[1].checked= radios[1].checked, radios[0].checked;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, false, (req: XMLHttpRequest) => {
|
||||||
|
if (req.status == 0) {
|
||||||
|
window.notifications.connectionError();
|
||||||
|
radios[0].checked, radios[1].checked= radios[1].checked, radios[0].checked;
|
||||||
|
return;
|
||||||
|
} else if (req.status == 401) {
|
||||||
|
radios[0].checked, radios[1].checked= radios[1].checked, radios[0].checked;
|
||||||
|
window.notifications.customError("401Error", window.lang.notif("error401Unauthorized"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
get expiry(): number { return this._expiryUnix; }
|
get expiry(): number { return this._expiryUnix; }
|
||||||
set expiry(unix: number) {
|
set expiry(unix: number) {
|
||||||
@ -252,6 +324,7 @@ class user implements User {
|
|||||||
this.admin = user.admin;
|
this.admin = user.admin;
|
||||||
this.disabled = user.disabled;
|
this.disabled = user.disabled;
|
||||||
this.expiry = user.expiry;
|
this.expiry = user.expiry;
|
||||||
|
this.notify_telegram = user.notify_telegram;
|
||||||
}
|
}
|
||||||
|
|
||||||
asElement = (): HTMLTableRowElement => { return this._row; }
|
asElement = (): HTMLTableRowElement => { return this._row; }
|
||||||
|
Loading…
Reference in New Issue
Block a user