Skip to content

Commit

Permalink
feat: type Router interface
Browse files Browse the repository at this point in the history
  • Loading branch information
trakhimenok committed Feb 3, 2025
1 parent beaf45b commit 7097c36
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 26 deletions.
8 changes: 4 additions & 4 deletions botsfw/bot_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

type BotProfile interface {
ID() string
Router() *WebhooksRouter
Router() Router
DefaultLocale() i18n.Locale
SupportedLocales() []i18n.Locale
NewBotChatData() botsfwmodels.BotChatData
Expand All @@ -26,14 +26,14 @@ type botProfile struct {
newBotUserData func() botsfwmodels.PlatformUserData
newAppUserData func() botsfwmodels.AppUserData
getAppUserByID AppUserGetter
router *WebhooksRouter
router Router
}

func (v *botProfile) ID() string {
return v.id
}

func (v *botProfile) Router() *WebhooksRouter {
func (v *botProfile) Router() Router {
return v.router
}

Expand All @@ -59,7 +59,7 @@ func (v *botProfile) NewAppUserData() botsfwmodels.AppUserData {

func NewBotProfile(
id string,
router *WebhooksRouter,
router Router,
newBotChatData func() botsfwmodels.BotChatData,
newBotUserData func() botsfwmodels.PlatformUserData,
newAppUserData func() botsfwmodels.AppUserData,
Expand Down
75 changes: 54 additions & 21 deletions botsfw/router.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package botsfw

import (
"context"
"errors"
"fmt"
"github.com/bots-go-framework/bots-fw-store/botsfwmodels"
Expand Down Expand Up @@ -36,24 +37,51 @@ func (v *TypeCommands) addCommand(command Command, commandType botinput.WebhookI
}
}

// WebhooksRouter maps routes to commands
type WebhooksRouter struct {
// Router dispatches requests to commands by input type, command code or a matching function
type Router interface {
RegisterCommands(commands ...Command)
RegisterCommandsForInputType(inputType botinput.WebhookInputType, commands ...Command)

// Dispatch requests to commands by input type, command code or a matching function
Dispatch(webhookHandler WebhookHandler, responder WebhookResponder, whc WebhookContext) error

// RegisteredCommands returns all registered commands
RegisteredCommands() map[botinput.WebhookInputType]map[CommandCode]Command
}

var _ Router = (*webhooksRouter)(nil)

type ErrorFooterArgs struct {
BotProfileID string
BotCode string
}
type ErrorFooterTextFunc func(ctx context.Context, botContext ErrorFooterArgs) string

// webhooksRouter maps routes to commands
type webhooksRouter struct {
commandsByType map[botinput.WebhookInputType]*TypeCommands
errorFooterText func() string
errorFooterText func(ctx context.Context, botContext ErrorFooterArgs) string
}

func (whRouter *webhooksRouter) RegisteredCommands() map[botinput.WebhookInputType]map[CommandCode]Command {
var commandsByType = make(map[botinput.WebhookInputType]map[CommandCode]Command)
for inputType, typeCommands := range whRouter.commandsByType {
commandsByType[inputType] = typeCommands.byCode
}
return commandsByType
}

// NewWebhookRouter creates new router
//
//goland:noinspection GoUnusedExportedFunction
func NewWebhookRouter(errorFooterText func() string) WebhooksRouter {
r := WebhooksRouter{
func NewWebhookRouter(errorFooterText func(ctx context.Context, botContext ErrorFooterArgs) string) *webhooksRouter {
return &webhooksRouter{
commandsByType: make(map[botinput.WebhookInputType]*TypeCommands),
errorFooterText: errorFooterText,
}
return r
}

func (whRouter *WebhooksRouter) CommandsCount() int {
func (whRouter *webhooksRouter) CommandsCount() int {
var count int
for _, v := range whRouter.commandsByType {
count += len(v.all)
Expand All @@ -63,20 +91,20 @@ func (whRouter *WebhooksRouter) CommandsCount() int {

// AddCommandsGroupedByType adds commands grouped by input type
// Deprecated: Use RegisterCommands() instead
func (whRouter *WebhooksRouter) AddCommandsGroupedByType(commandsByType map[botinput.WebhookInputType][]Command) {
func (whRouter *webhooksRouter) AddCommandsGroupedByType(commandsByType map[botinput.WebhookInputType][]Command) {
for inputType, commands := range commandsByType {
whRouter.RegisterCommandsForInputType(inputType, commands...)
}
}

// AddCommands adds commands to router. It should be called just once with the current implementation of RegisterCommandsForInputType()
// Deprecated: Use RegisterCommands() instead
func (whRouter *WebhooksRouter) AddCommands(commands ...Command) {
func (whRouter *webhooksRouter) AddCommands(commands ...Command) {
whRouter.RegisterCommands(commands...)
}

// RegisterCommandsForInputType adds commands for the given input type
func (whRouter *WebhooksRouter) RegisterCommandsForInputType(inputType botinput.WebhookInputType, commands ...Command) {
func (whRouter *webhooksRouter) RegisterCommandsForInputType(inputType botinput.WebhookInputType, commands ...Command) {
typeCommands, ok := whRouter.commandsByType[inputType]
if !ok {
typeCommands = newTypeCommands(len(commands))
Expand All @@ -99,14 +127,14 @@ type CommandsRegisterer interface {
RegisterCommands(commands ...Command)
}

var _ CommandsRegisterer = (*WebhooksRouter)(nil)
var _ CommandsRegisterer = (*webhooksRouter)(nil)

type RegisterCommandsFunc func(commands ...Command)
type RegisterCommandsForInputTypeFunc func(inputType botinput.WebhookInputType, commands ...Command)

// RegisterCommands is registering commands with router
// TODO: Either leave this one or AddCommands()
func (whRouter *WebhooksRouter) RegisterCommands(commands ...Command) {
func (whRouter *webhooksRouter) RegisterCommands(commands ...Command) {
addCommand := func(t botinput.WebhookInputType, command Command) {
typeCommands, ok := whRouter.commandsByType[t]
if !ok {
Expand Down Expand Up @@ -169,7 +197,7 @@ func matchCallbackCommands(whc WebhookContext, input botinput.WebhookCallbackQue
return nil, callbackURL, err
}

func (whRouter *WebhooksRouter) matchMessageCommands(whc WebhookContext, input botinput.WebhookMessage, isCommandText bool, messageText, parentPath string, commands []Command) (matchedCommand *Command) {
func (whRouter *webhooksRouter) matchMessageCommands(whc WebhookContext, input botinput.WebhookMessage, isCommandText bool, messageText, parentPath string, commands []Command) (matchedCommand *Command) {
c := whc.Context()

var awaitingReplyCommand Command
Expand Down Expand Up @@ -270,7 +298,7 @@ func (whRouter *WebhooksRouter) matchMessageCommands(whc WebhookContext, input b
}

// DispatchInlineQuery dispatches inlines query
func (whRouter *WebhooksRouter) DispatchInlineQuery(responder WebhookResponder) {
func (whRouter *webhooksRouter) DispatchInlineQuery(responder WebhookResponder) {
panic(fmt.Errorf("not implemented, responder: %+v", responder))
}

Expand Down Expand Up @@ -323,12 +351,12 @@ func changeLocaleIfLangPassed(whc WebhookContext, callbackUrl *url.URL) (m Messa
return
}

// Dispatch query to commands
func (whRouter *WebhooksRouter) Dispatch(webhookHandler WebhookHandler, responder WebhookResponder, whc WebhookContext) (err error) {
// Dispatch a query to commands
func (whRouter *webhooksRouter) Dispatch(webhookHandler WebhookHandler, responder WebhookResponder, whc WebhookContext) (err error) {
c := whc.Context()
// defer func() {
// if err := recover(); err != nil {
// log.Criticalf(c, "*WebhooksRouter.Dispatch() => PANIC: %v", err)
// log.Criticalf(c, "*webhooksRouter.Dispatch() => PANIC: %v", err)
// }
// }()

Expand Down Expand Up @@ -461,7 +489,7 @@ func logInputDetails(whc WebhookContext, isKnownType bool) {
inputType := whc.Input().InputType()
input := whc.Input()
inputTypeIdName := botinput.GetWebhookInputTypeIdNameString(inputType)
logMessage := fmt.Sprintf("WebhooksRouter.Dispatch() => WebhookIputType=%s, %T", inputTypeIdName, input)
logMessage := fmt.Sprintf("webhooksRouter.Dispatch() => WebhookIputType=%s, %T", inputTypeIdName, input)
switch inputType {
case botinput.WebhookInputText:
textMessage := input.(botinput.WebhookTextMessage)
Expand Down Expand Up @@ -506,7 +534,7 @@ func logInputDetails(whc WebhookContext, isKnownType bool) {
}
}

func (whRouter *WebhooksRouter) processCommandResponse(matchedCommand *Command, responder WebhookResponder, whc WebhookContext, m MessageFromBot, err error) {
func (whRouter *webhooksRouter) processCommandResponse(matchedCommand *Command, responder WebhookResponder, whc WebhookContext, m MessageFromBot, err error) {
if err != nil {
whRouter.processCommandResponseError(whc, matchedCommand, responder, err)
return
Expand Down Expand Up @@ -574,7 +602,7 @@ func (whRouter *WebhooksRouter) processCommandResponse(matchedCommand *Command,
}
}

func (whRouter *WebhooksRouter) processCommandResponseError(whc WebhookContext, matchedCommand *Command, responder WebhookResponder, err error) {
func (whRouter *webhooksRouter) processCommandResponseError(whc WebhookContext, matchedCommand *Command, responder WebhookResponder, err error) {
c := whc.Context()
log.Errorf(c, err.Error())
env := whc.GetBotSettings().Env
Expand Down Expand Up @@ -602,7 +630,12 @@ func (whRouter *WebhooksRouter) processCommandResponseError(whc WebhookContext,
)

if whRouter.errorFooterText != nil {
if footer := whRouter.errorFooterText(); footer != "" {
ctx := whc.Context()
args := ErrorFooterArgs{
BotCode: whc.GetBotCode(),
BotProfileID: "", // TODO(help-wanted): implement!
}
if footer := whRouter.errorFooterText(ctx, args); footer != "" {
m.Text += "\n\n" + footer
}
}
Expand Down
2 changes: 1 addition & 1 deletion botsfw/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

func dummyBotProfile() BotProfile {
router := &WebhooksRouter{}
router := &webhooksRouter{}
newBotChatDate := func() botsfwmodels.BotChatData {
return nil
}
Expand Down

0 comments on commit 7097c36

Please sign in to comment.