package fsmwizard import ( "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/db/model" "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/handler/iface" "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/handler/util" "gitea.neur0tx.site/Neur0toxine/vegapokerbot/pkg/fsm" "github.com/mymmrac/telego" tu "github.com/mymmrac/telego/telegoutil" "golang.org/x/text/language" ) const MaxChatMembers = 32 const AddChatMemberStateID fsm.StateID = "add_chat_member" type AddChatMemberState struct { State } func NewAddChatMemberState(app iface.App) fsm.IState[Wizard] { return &AddChatMemberState{newBase(app)} } func (s *AddChatMemberState) Enter(pl *Wizard, mc fsm.MachineControls[*Wizard]) error { if pl.Data.MyChatMember == nil { s.Move(mc, WaitingForMemberWebhookStateID, pl) } return nil } func (s *AddChatMemberState) Handle(pl *Wizard, mc fsm.MachineControls[*Wizard]) { next := WaitingForMemberWebhookStateID defer func() { s.Move(mc, next, pl) }() cr := s.App.DB().ForChat() tgChat := pl.Data.MyChatMember.Chat user, chat := s.getUserAndChat(tgChat) if user == nil || chat == nil { return } s.Payload.Loc = s.Localizer(user.Language) if s.handleTooManyMembers(tgChat.ID) { return } if chat.ID == 0 { chat = &model.Chat{ TelegramID: tgChat.ID, UserID: user.ID, } err := cr.Save(chat) if err != nil { s.curseAndLeave(tgChat.ID, err) return } } else { chat.UserID = user.ID err := s.App.DB().ForIntegration().DeleteForChat(chat.ID) if err != nil { s.curseAndLeave(tgChat.ID, err) return } err = cr.Save(chat) if err != nil { s.curseAndLeave(tgChat.ID, err) return } } _, err := s.App.TG().SendMessage(&telego.SendMessageParams{ ChatID: tu.ID(user.ChatID), Text: s.Payload.Loc.Template("bot_was_added", map[string]interface{}{"Name": tgChat.Title}), ParseMode: telego.ModeMarkdown, }) s.LogError(err) pl.User = user pl.TGChat = tgChat next = KeyboardChooserStateID } func (s *AddChatMemberState) handleTooManyMembers(chatID int64) bool { totalMembers, err := s.App.TG().GetChatMemberCount(&telego.GetChatMemberCountParams{ ChatID: tu.ID(chatID), }) if err != nil { s.curseAndLeave(chatID, err) return true } if *totalMembers > MaxChatMembers { _, err = s.App.TG().SendMessage(&telego.SendMessageParams{ ChatID: tu.ID(chatID), Text: s.Payload.Loc.Template( "too_many_members_in_the_group", map[string]interface{}{"Limit": MaxChatMembers}), ParseMode: telego.ModeMarkdown, }) s.leaveChat(chatID) s.LogError(err) return true } return false } func (s *AddChatMemberState) getUserAndChat(tgChat telego.Chat) (*model.User, *model.Chat) { cr := s.App.DB().ForChat() chat, err := cr.ByTelegramID(tgChat.ID) if err != nil { s.curseAndLeave(tgChat.ID, err) return nil, nil } user, err := s.getRegisteredAdmin(tgChat.ID) if err != nil { s.curseAndLeave(tgChat.ID, err) return nil, nil } if user == nil || user.ID == 0 { _, err = s.App.TG().SendMessage(&telego.SendMessageParams{ ChatID: tu.ID(tgChat.ID), Text: s.Localizer(language.English.String()). Template("you_should_register_first", map[string]interface{}{"Name": s.App.TGProfile().Username}), ParseMode: telego.ModeMarkdown, }) s.leaveChat(tgChat.ID) s.LogError(err) return nil, nil } return user, chat } func (s *AddChatMemberState) curseAndLeave(chatID int64, err error) { s.LogError(util.SendInternalError(s.App.TG(), chatID, s.Localizer())) s.leaveChat(chatID) s.LogError(err) } func (s *AddChatMemberState) getRegisteredAdmin(chatID int64) (*model.User, error) { admins, err := s.App.TG().GetChatAdministrators(&telego.GetChatAdministratorsParams{ ChatID: tu.ID(chatID), }) if err != nil { return nil, err } adminIDs := make([]int64, len(admins)) for i, admin := range admins { adminIDs[i] = admin.MemberUser().ID } dbAdmins, err := s.App.DB().ForUser().ByTelegramIDs(adminIDs) if err != nil { return nil, err } if len(dbAdmins) > 0 { return &dbAdmins[0], nil } return nil, nil } func (s *AddChatMemberState) leaveChat(chatID int64) { s.LogError(s.App.TG().LeaveChat(&telego.LeaveChatParams{ ChatID: tu.ID(chatID), })) } func (s *AddChatMemberState) ID() fsm.StateID { return AddChatMemberStateID }