From 825efc692d32c1122630b0a86ca7a3dd77528456 Mon Sep 17 00:00:00 2001 From: Astra Date: Thu, 29 Jan 2026 11:40:13 +0000 Subject: [PATCH] change wording, add way to give declined reason --- main.go | 132 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 90 insertions(+), 42 deletions(-) diff --git a/main.go b/main.go index 6418a6e..2b8970a 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "strconv" "strings" "time" @@ -10,9 +11,9 @@ import ( ) const ( - AdminJoinRequestMsg = "New join #request from _%s_\n\nJoin reason: %s" - AdminApprovedMsg = "✅ Join #request approved for _%s_\n\nJoin reason: %s\nApproved by: %s\nApproved at: %s" - AdminRejectedMsg = "❌ Join #request rejected for _%s_\n\nJoin reason: %s\nRejected by: %s\nRejected at: %s" + AdminJoinRequestMsg = "New join #request from %s [%d]\n\nJoin reason: %s" + AdminApprovedMsg = "✅ Join #request approved for %s [%d]\n\nJoin reason: %s\nApproved by: %s\nApproved at: %s" + AdminDeclinedMsg = "❌ Join #request declined for %s [%d]\n\nJoin reason: %s\nDeclined by: %s\nDeclined at: %s\nDeclined reason: %s" ) type ExtendedChatJoinRequest struct { @@ -51,7 +52,9 @@ func main() { for update := range updatesChannel { if update.ChatJoinRequest != nil { - b.handleJoinRequest(update.ChatJoinRequest) + if update.ChatJoinRequest.Chat.ID == b.Config.TargetChatId { + b.handleJoinRequest(update.ChatJoinRequest) + } continue } @@ -69,12 +72,33 @@ func main() { b.handleJoinRequestResponse(user, update.Message) } } + + if update.Message.Chat.ID == b.Config.AdminChatId && update.Message.ReplyToMessage != nil { + // handle admin declineion reason + repliedMsg := update.Message.ReplyToMessage + if strings.Contains(repliedMsg.Text, "(no reason provided, reply to this to send one)") { + // now we need to make sure the one that declined it is the one replying + lines := strings.Split(repliedMsg.Text, "\n") + if strings.TrimPrefix(lines[3], "Declined by: ") == update.Message.From.String() { + + edit := api.NewEditMessageText(b.Config.AdminChatId, repliedMsg.MessageID, + strings.Replace(repliedMsg.Text, "(no reason provided, reply to this to send one)", + escapeHTML(update.Message.Text), 1)) + edit.ParseMode = api.ModeHTML + b.API.Send(edit) + userID := GetUserIDFromMessage(repliedMsg.Text) + m := api.NewMessage(userID, fmt.Sprintf("Your join request was declined for the following reason:\n\n%s", + update.Message.Text)) + b.API.Send(m) + } + } + } } } func (bot *Bot) handleJoinRequestResponse(user *ExtendedChatJoinRequest, update *api.Message) { if user.JoinReason == "" { - user.JoinReason = escapeMarkdown(update.Text) + user.JoinReason = escapeHTML(update.Text) userString := "" if user.From.UserName != "" { @@ -84,10 +108,10 @@ func (bot *Bot) handleJoinRequestResponse(user *ExtendedChatJoinRequest, update } edit := api.NewEditMessageText(bot.Config.AdminChatId, user.JoinRequestMessageID, fmt.Sprintf(AdminJoinRequestMsg, - userString, user.JoinReason)) + userString, user.From.ID, user.JoinReason)) keyboard := newApprovalKeyboard(user.From.ID) edit.ReplyMarkup = &keyboard - edit.ParseMode = api.ModeMarkdown + edit.ParseMode = api.ModeHTML bot.API.Send(edit) ack := api.NewMessage(update.From.ID, "Thank you! Your request has been sent to the admins for review.") @@ -99,31 +123,29 @@ func (bot *Bot) handleJoinRequestResponse(user *ExtendedChatJoinRequest, update } func (bot *Bot) handleJoinRequest(request *api.ChatJoinRequest) { - if bot.Config.TargetChatId == request.Chat.ID { - bot.WaitingForApproval[request.From.ID] = &ExtendedChatJoinRequest{ - ChatJoinRequest: request, - JoinReason: "", - } - m := api.NewMessage(request.From.ID, bot.Config.EntryMessage) - m.ParseMode = api.ModeMarkdown - bot.API.Send(m) - - userString := "" - if request.From.UserName != "" { - userString = "@" + request.From.UserName - } else { - userString = fmt.Sprintf("%s %s (no username)", request.From.FirstName, request.From.LastName) - } - m = api.NewMessage(bot.Config.AdminChatId, - fmt.Sprintf(AdminJoinRequestMsg, userString, "(awaiting user response)")) - m.ReplyMarkup = newApprovalKeyboard(request.From.ID) - m.ParseMode = api.ModeMarkdown - if bot.Config.AdminChatTopicId != 0 { - m.MessageThreadID = bot.Config.AdminChatTopicId - } - r, _ := bot.API.Send(m) - bot.WaitingForApproval[request.From.ID].JoinRequestMessageID = r.MessageID + bot.WaitingForApproval[request.From.ID] = &ExtendedChatJoinRequest{ + ChatJoinRequest: request, + JoinReason: "", } + m := api.NewMessage(request.From.ID, bot.Config.EntryMessage) + m.ParseMode = api.ModeHTML + bot.API.Send(m) + + userString := "" + if request.From.UserName != "" { + userString = "@" + request.From.UserName + } else { + userString = fmt.Sprintf("%s %s (no username)", request.From.FirstName, request.From.LastName) + } + m = api.NewMessage(bot.Config.AdminChatId, + fmt.Sprintf(AdminJoinRequestMsg, userString, request.From.ID, "(awaiting user response)")) + m.ReplyMarkup = newApprovalKeyboard(request.From.ID) + m.ParseMode = api.ModeHTML + if bot.Config.AdminChatTopicId != 0 { + m.MessageThreadID = bot.Config.AdminChatTopicId + } + r, _ := bot.API.Send(m) + bot.WaitingForApproval[request.From.ID].JoinRequestMessageID = r.MessageID } func (bot *Bot) handleCallbackQuery(query *api.CallbackQuery) { @@ -162,17 +184,20 @@ func (bot *Bot) handleCallbackQuery(query *api.CallbackQuery) { } edit := api.NewEditMessageText(bot.Config.AdminChatId, user.JoinRequestMessageID, fmt.Sprintf(AdminApprovedMsg, - userString, user.JoinReason, query.From.String(), time.Now().Format("2006-01-02 15:04:05"))) - edit.ParseMode = api.ModeMarkdown + userString, user.From.ID, user.JoinReason, query.From.String(), time.Now().Format("2006-01-02 15:04:05"))) + edit.ParseMode = api.ModeHTML bot.API.Send(edit) if bot.Config.ApprovalMessage != "" { m := api.NewMessage(user.From.ID, bot.Config.ApprovalMessage) - m.ParseMode = api.ModeMarkdown + m.ParseMode = api.ModeHTML bot.API.Send(m) } - case "reject": + callback := api.NewCallback(query.ID, "Join request approved.") + bot.API.Request(callback) + + case "decline": r := api.DeclineChatJoinRequest{ ChatConfig: api.ChatConfig{ ChatID: user.ChatJoinRequest.Chat.ID, @@ -188,10 +213,13 @@ func (bot *Bot) handleCallbackQuery(query *api.CallbackQuery) { userString = fmt.Sprintf("%s %s (no username)", user.From.FirstName, user.From.LastName) } edit := api.NewEditMessageText(bot.Config.AdminChatId, user.JoinRequestMessageID, - fmt.Sprintf(AdminRejectedMsg, - userString, user.JoinReason, query.From.String(), time.Now().Format("2006-01-02 15:04:05"))) - edit.ParseMode = api.ModeMarkdown + fmt.Sprintf(AdminDeclinedMsg, + userString, user.From.ID, user.JoinReason, query.From.String(), time.Now().Format("2006-01-02 15:04:05"), "(no reason provided, reply to this to send one)")) + edit.ParseMode = api.ModeHTML bot.API.Send(edit) + + callback := api.NewCallback(query.ID, "Join request declined.") + bot.API.Request(callback) } delete(bot.WaitingForApproval, userId) @@ -210,8 +238,28 @@ func escapeMarkdown(s string) string { return replacer.Replace(s) } -func newApprovalKeyboard(userID int64) api.InlineKeyboardMarkup { - approveBtn := api.NewInlineKeyboardButtonData("✅ Approve", fmt.Sprintf("approve_%d", userID)) - rejectBtn := api.NewInlineKeyboardButtonData("❌ Reject", fmt.Sprintf("reject_%d", userID)) - return api.NewInlineKeyboardMarkup([]api.InlineKeyboardButton{approveBtn, rejectBtn}) +func escapeHTML(s string) string { + toEscape := []string{"&", "<", ">", "\"", "'"} + + replacements := make([]string, 0, len(toEscape)*2) + replacements = append(replacements, "&", "&") + replacements = append(replacements, "<", "<") + replacements = append(replacements, ">", ">") + replacements = append(replacements, "\"", """) + + replacer := strings.NewReplacer(replacements...) + return replacer.Replace(s) +} + +func newApprovalKeyboard(userID int64) api.InlineKeyboardMarkup { + approveBtn := api.NewInlineKeyboardButtonData("Approve", fmt.Sprintf("approve_%d", userID)) + declineBtn := api.NewInlineKeyboardButtonData("Decline", fmt.Sprintf("decline_%d", userID)) + return api.NewInlineKeyboardMarkup([]api.InlineKeyboardButton{approveBtn, declineBtn}) +} + +func GetUserIDFromMessage(msg string) int64 { + start := strings.Index(msg, "[") + end := strings.Index(msg, "]") + num, _ := strconv.Atoi(msg[start+1 : end]) + return int64(num) }