From 4fdc64c03bbf83c4b24792b106150839a6cb7312 Mon Sep 17 00:00:00 2001 From: Neur0toxine Date: Mon, 13 May 2024 21:46:05 +0300 Subject: [PATCH] change fsm behavior, unknown command state --- internal/handler/fsmwizard/init.go | 26 +++++++++++++-- internal/handler/fsmwizard/register_state.go | 7 ++++ .../fsmwizard/unknown_command_state.go | 32 +++++++++++++++++++ internal/handler/new_message_handler.go | 4 --- internal/handler/util/command.go | 7 ++++ pkg/fsm/machine.go | 12 ++++--- 6 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 internal/handler/fsmwizard/unknown_command_state.go diff --git a/internal/handler/fsmwizard/init.go b/internal/handler/fsmwizard/init.go index 5f28edb..2f640af 100644 --- a/internal/handler/fsmwizard/init.go +++ b/internal/handler/fsmwizard/init.go @@ -1,10 +1,12 @@ package fsmwizard import ( + "time" + "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/maypok86/otter" - "time" ) var ( @@ -36,7 +38,7 @@ func Get(userID int64) fsm.IMachine[Wizard] { } func newWizard() fsm.IMachine[Wizard] { - return fsm.New[Wizard](states[0].ID(), Wizard{}, states, errorState) + return fsm.New[Wizard](states[0].ID(), Wizard{}, wizardPreHandle, states, errorState) } // PopulateStates will init all state handlers for future use. @@ -48,6 +50,26 @@ func PopulateStates(app iface.App) { NewKeyboardChooserState(app), NewRemoveChatMemberState(app), NewHelpState(app), + NewUnknownCommandState(app), } errorState = NewErrorState(app.Log()) } + +func wizardPreHandle(w *Wizard, mc fsm.MachineControls[*Wizard]) { + if w.Data.Message != nil { + switch { + case util.MatchCommand("start", w.Data.Message): + mc.Move(RegisterStateID, w) + case util.MatchCommand("help", w.Data.Message): + mc.Move(HelpStateID, w) + case util.HasCommand(w.Data.Message): + mc.Move(UnknownCommandStateID, w) + default: + return + } + } + + if w.Data.MyChatMember != nil { + mc.Move(WaitingForMemberWebhookStateID, w) + } +} diff --git a/internal/handler/fsmwizard/register_state.go b/internal/handler/fsmwizard/register_state.go index e36a58e..16b31f3 100644 --- a/internal/handler/fsmwizard/register_state.go +++ b/internal/handler/fsmwizard/register_state.go @@ -18,6 +18,13 @@ func NewRegisterState(app iface.App) fsm.IState[Wizard] { return &RegisterState{newBase(app)} } +func (s *RegisterState) Enter(pl *Wizard, _ fsm.MachineControls[*Wizard]) error { + if pl.Data.Message != nil && pl.Data.Message.Chat.Type != telego.ChatTypePrivate { + return fsm.ErrPreventTransition + } + return nil +} + func (s *RegisterState) Handle(pl *Wizard, mc fsm.MachineControls[*Wizard]) { loc := s.Localizer(pl.Data.Message.From.LanguageCode) userRepo := s.App.DB().ForUser() diff --git a/internal/handler/fsmwizard/unknown_command_state.go b/internal/handler/fsmwizard/unknown_command_state.go new file mode 100644 index 0000000..62b1c04 --- /dev/null +++ b/internal/handler/fsmwizard/unknown_command_state.go @@ -0,0 +1,32 @@ +package fsmwizard + +import ( + "gitea.neur0tx.site/Neur0toxine/vegapokerbot/internal/handler/iface" + "gitea.neur0tx.site/Neur0toxine/vegapokerbot/pkg/fsm" + "github.com/mymmrac/telego" + tu "github.com/mymmrac/telego/telegoutil" +) + +const UnknownCommandStateID fsm.StateID = "unknown_command" + +type UnknownCommandState struct { + State +} + +func NewUnknownCommandState(app iface.App) fsm.IState[Wizard] { + return &UnknownCommandState{newBase(app)} +} + +func (s *UnknownCommandState) Enter(pl *Wizard, _ fsm.MachineControls[*Wizard]) error { + _, err := s.App.TG().SendMessage(&telego.SendMessageParams{ + ChatID: tu.ID(s.Payload.Data.Message.Chat.ID), + Text: s.Localizer(s.Payload.Data.Message.From.LanguageCode).Message("unknown_command"), + ParseMode: telego.ModeMarkdown, + }) + s.LogError(err) + return fsm.ErrPreventTransition +} + +func (s *UnknownCommandState) ID() fsm.StateID { + return UnknownCommandStateID +} diff --git a/internal/handler/new_message_handler.go b/internal/handler/new_message_handler.go index 5fdd167..3d3a670 100644 --- a/internal/handler/new_message_handler.go +++ b/internal/handler/new_message_handler.go @@ -30,10 +30,6 @@ func (h *MessageHandler) Handle(wh telego.Update) error { return group.NewPoll(h.App, wh.Message.From.ID, wh.Message.Chat.ID).Handle(wh) } - if util.MatchCommand("start", wh.Message) { - return wizard.NewRegister(h.App, wh.Message.From.ID, wh.Message.Chat.ID).Handle(wh) - } - setup, found := store.RedmineSetups.Get(wh.Message.Chat.ID) if found { return wizard.NewRedmineSetup(h.App, wh.Message.From.ID, wh.Message.Chat.ID, setup).Handle(wh) diff --git a/internal/handler/util/command.go b/internal/handler/util/command.go index a98c293..47e8055 100644 --- a/internal/handler/util/command.go +++ b/internal/handler/util/command.go @@ -8,3 +8,10 @@ import ( func MatchCommand(command string, msg *telego.Message) bool { return th.CommandEqual(command)(telego.Update{Message: msg}) } + +func HasCommand(msg *telego.Message) bool { + if msg == nil { + return false + } + return th.CommandRegexp.MatchString(msg.Text) +} diff --git a/pkg/fsm/machine.go b/pkg/fsm/machine.go index 22dda56..afdab9b 100644 --- a/pkg/fsm/machine.go +++ b/pkg/fsm/machine.go @@ -26,7 +26,7 @@ type MachineHandleInput[T any] func(*T, MachineControls[*T]) type IMachine[T any] interface { MachineControls[*T] // Handle the state input. Handle func will accept the current payload and modify it based on user input. - Handle(MachineHandleInput[T]) error + Handle() error // Reset the machine to its initial state. Reset() } @@ -35,6 +35,7 @@ type IMachine[T any] interface { type Machine[T any] struct { lock sync.Mutex payload *T + preHandle MachineHandleInput[T] state StateID initialState StateID initialPayload T @@ -43,7 +44,7 @@ type Machine[T any] struct { } // New machine. -func New[T any](initialState StateID, initialPayload T, states []IState[T], errHandler ErrorState[T]) IMachine[T] { +func New[T any](initialState StateID, initialPayload T, preHandle MachineHandleInput[T], states []IState[T], errHandler ErrorState[T]) IMachine[T] { stateMap := make(map[StateID]IState[T], len(states)) for _, state := range states { stateMap[state.ID()] = state @@ -52,6 +53,7 @@ func New[T any](initialState StateID, initialPayload T, states []IState[T], errH return &Machine[T]{ state: initialState, payload: &pl, + preHandle: preHandle, initialState: initialState, initialPayload: initialPayload, states: stateMap, @@ -91,10 +93,12 @@ func (m *Machine[T]) Move(id StateID, payload *T) error { } // Handle the input. -func (m *Machine[T]) Handle(inputFunc MachineHandleInput[T]) error { +func (m *Machine[T]) Handle() error { defer m.lock.Unlock() m.lock.Lock() - inputFunc(m.payload, m) + if m.preHandle != nil { + m.preHandle(m.payload, m) + } st, err := m.loadState(m.state, m.payload) if st == nil || err != nil { return err