Skip to content

Commit

Permalink
feat: improved user acceptance flow (#59)
Browse files Browse the repository at this point in the history
* feat: improved user acceptance flow

* fix: linter errors

---------

Co-authored-by: hrvadl <[email protected]>
  • Loading branch information
hrvadl and hrvadl authored Jun 10, 2024
1 parent c60bfb4 commit f0b6faa
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 43 deletions.
12 changes: 0 additions & 12 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,6 @@ linters:
- wrapcheck # Checks that errors returned from external packages are wrapped
- wsl # Whitespace Linter - Forces you to use empty lines!

# Disabled because deprecated
- deadcode # Finds unused code
- exhaustivestruct # Checks if all struct's fields are initialized
- golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
- ifshort # Checks that your code uses short syntax for if-statements whenever possible
- interfacer # Linter that suggests narrower interface types
- maligned # Tool to detect Go structs that would take less memory if their fields were sorted
- nosnakecase # nosnakecase is a linter that detects snake case of variable naming and function name.
- scopelint # Scopelint checks for unpinned variables in go programs
- structcheck # Finds unused struct fields
- varcheck # Finds unused global variables and constants

# To see a list of enabled/disabled by current configuration linters:
# golangci-lint linters

Expand Down
8 changes: 4 additions & 4 deletions internal/handler/callback/callbackdata/decisions.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ const (
DeclineDecision = "decline"
)

func NewAgreeWithGroupID(groupdID int64) string {
return fmt.Sprintf("%s_%v", AgreeDecision, groupdID)
func NewAgreeWithGroupID(groupdID int64, msgID int) string {
return fmt.Sprintf("%s_%d_%d", AgreeDecision, groupdID, msgID)
}

func NewDeclineWithGroupID(groupdID int64) string {
return fmt.Sprintf("%s_%v", DeclineDecision, groupdID)
func NewDeclineWithGroupID(groupdID int64, msgID int) string {
return fmt.Sprintf("%s_%d_%d", DeclineDecision, groupdID, msgID)
}
32 changes: 25 additions & 7 deletions internal/handler/callback/callbackdata/parser.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,49 @@
package callbackdata

import (
"errors"
"fmt"
"strconv"
"strings"
)

type Payload struct {
Decision string
GroupID int64
Decision string
GroupID int64
MessageID int
}

var (
ErrInvalidCallbackData = errors.New("invalid callback query data token")
ErrInvalidGroupID = errors.New("invalid groupID in callback query data")
ErrInvalidMessageID = errors.New("invalid messageID in callback query data")
ErrInvalidDecision = errors.New("invalid terms of use decision")
)

func Parse(data string) (*Payload, error) {
splits := strings.Split(data, "_")
if len(splits) != 2 { //nolint:gomnd,mnd
return nil, fmt.Errorf("invalid callback query data token: %v", splits)
if len(splits) != 3 { //nolint:gomnd,mnd
return nil, fmt.Errorf("%w: %v", ErrInvalidCallbackData, splits)
}

groupID, err := strconv.ParseInt(splits[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid groupID in callback query data: %s", splits[1])
return nil, fmt.Errorf("%w: %s", ErrInvalidGroupID, splits[1])
}

messageID, err := strconv.Atoi(splits[2])
if err != nil {
return nil, fmt.Errorf("%w: %s", ErrInvalidMessageID, splits[1])
}

decision := splits[0]
if decision != AgreeDecision && decision != DeclineDecision {
return nil, fmt.Errorf("invalid callback data for terms of use decision: %v", decision)
return nil, fmt.Errorf("%w: %v", ErrInvalidDecision, decision)
}

return &Payload{decision, groupID}, nil
return &Payload{
Decision: decision,
GroupID: groupID,
MessageID: messageID,
}, nil
}
8 changes: 4 additions & 4 deletions internal/handler/callback/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ func (h *handler) callbackQuery(ctx context.Context, bot *telego.Bot, query tele
msg = fmt.Sprintf(messages.Decline, viper.GetString("admin-username"))
}

_, err = bot.SendMessage(&telego.SendMessageParams{
ChatID: tu.ID(query.From.ID),
Text: msg,
ReplyMarkup: tu.ReplyKeyboardRemove(),
_, err = bot.EditMessageText(&telego.EditMessageTextParams{
MessageID: data.MessageID,
ChatID: tu.ID(query.From.ID),
Text: msg,
})
if err != nil {
log.Error("Sending decision message failed", slog.Any("error", err))
Expand Down
34 changes: 22 additions & 12 deletions internal/handler/join/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,40 @@ func (h *handler) chatJoinRequest(ctx context.Context, bot *telego.Bot, request
return
}

_, err := bot.SendMessage(&telego.SendMessageParams{
ChatID: tu.ID(request.From.ID),
ParseMode: telego.ModeHTML,
Text: messages.JoinHeader + messages.Rules,
})
if err != nil {
log.Error("Sending TermsOfUse and Rules message failed", slog.Any("error", err))
}

msg := tu.Message(tu.ID(request.From.ID), messages.JoinFooter)
toEdit, err := bot.SendMessage(msg)
if err != nil {
log.Error("Sending terms of use failed", slog.Any("error", err))
}

k := tu.InlineKeyboard(
tu.InlineKeyboardRow(
telego.InlineKeyboardButton{
Text: AgreeText,
CallbackData: callbackdata.NewAgreeWithGroupID(request.Chat.ID),
CallbackData: callbackdata.NewAgreeWithGroupID(request.Chat.ID, toEdit.MessageID),
},
telego.InlineKeyboardButton{
Text: DontAgreeText,
CallbackData: callbackdata.NewDeclineWithGroupID(request.Chat.ID),
CallbackData: callbackdata.NewDeclineWithGroupID(request.Chat.ID, toEdit.MessageID),
},
),
)

_, err := bot.SendMessage(&telego.SendMessageParams{
ChatID: tu.ID(request.From.ID),
ParseMode: telego.ModeHTML,
Text: messages.JoinHeader + messages.Rules,
_, err = bot.EditMessageReplyMarkup(&telego.EditMessageReplyMarkupParams{
ReplyMarkup: k,
ChatID: tu.ID(request.From.ID),
MessageID: toEdit.MessageID,
})
if err != nil {
log.Error("Sending TermsOfUse and Rules message failed", slog.Any("error", err))
}

msg := tu.Message(tu.ID(request.From.ID), messages.JoinFooter).WithReplyMarkup(k).WithProtectContent()
if _, err := bot.SendMessage(msg); err != nil {
log.Error("Sending terms of use failed", slog.Any("error", err))
log.Error("Editing callback query failed", slog.Any("error", err))
}
}
3 changes: 0 additions & 3 deletions internal/messages/terms.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ const JoinHeader = `
Вітаємо! Ви подали запит на вступ до групи <b>GolangUA</b>.
`

//nolint:lll
const JoinFooter = `
Перед тим як прийняти рішення, будь ласка, привітайтесь з ботом, написавши довільне повідомлення. Після цього ви зможете натиснути на потрібну кнопну та отримати результат вашого запиту.
Приймаючи запрошення в цю групу ви автоматично:
1. Засуджуєте війну рф проти України.
2. Не визнаєте тимчасовано окупованії українські території субʼєктом рф.
Expand Down
5 changes: 4 additions & 1 deletion internal/module/gcp/secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package secrets
import (
"context"
"encoding/base64"
"errors"
"fmt"

"google.golang.org/api/secretmanager/v1"
Expand All @@ -14,6 +15,8 @@ type Client struct {
*secretmanager.Service
}

var ErrSecretAccessRequest = errors.New("secret access request failed")

func NewClient(ctx context.Context) (*Client, error) {
client, err := secretmanager.NewService(ctx)
if err != nil {
Expand All @@ -31,7 +34,7 @@ func (c Client) GetSecretValue(ctx context.Context, name string) (string, error)
return "", fmt.Errorf("secret access request: %w", err)
}
if resp.HTTPStatusCode != 200 { //nolint:gomnd,mnd
return "", fmt.Errorf("secret access request: code=%d, data=%v", resp.HTTPStatusCode, resp.Payload.Data)
return "", fmt.Errorf("%w: code=%d, data=%v", ErrSecretAccessRequest, resp.HTTPStatusCode, resp.Payload.Data)
}

decoded, err := base64.StdEncoding.DecodeString(resp.Payload.Data)
Expand Down

0 comments on commit f0b6faa

Please sign in to comment.