Files
Memoh/internal/conversation/flow/email_gateway.go

94 lines
2.3 KiB
Go

package flow
import (
"context"
"errors"
"fmt"
"log/slog"
"strings"
"time"
"github.com/memohai/memoh/internal/auth"
"github.com/memohai/memoh/internal/conversation"
"github.com/memohai/memoh/internal/db"
"github.com/memohai/memoh/internal/db/sqlc"
)
const emailTriggerTokenTTL = 10 * time.Minute
// EmailChatGateway implements email.ChatTriggerer by delegating to the Resolver.
type EmailChatGateway struct {
resolver *Resolver
queries *sqlc.Queries
jwtSecret string
logger *slog.Logger
}
func NewEmailChatGateway(resolver *Resolver, queries *sqlc.Queries, jwtSecret string, logger *slog.Logger) *EmailChatGateway {
return &EmailChatGateway{
resolver: resolver,
queries: queries,
jwtSecret: jwtSecret,
logger: logger,
}
}
func (g *EmailChatGateway) TriggerBotChat(ctx context.Context, botID, content string) error {
if g == nil || g.resolver == nil {
return errors.New("chat resolver not configured")
}
ownerUserID, err := g.resolveBotOwner(ctx, botID)
if err != nil {
return fmt.Errorf("resolve bot owner: %w", err)
}
token, err := g.generateToken(ownerUserID)
if err != nil {
return fmt.Errorf("generate trigger token: %w", err)
}
_, err = g.resolver.Chat(ctx, conversation.ChatRequest{
BotID: botID,
ChatID: botID,
Query: content,
UserID: ownerUserID,
Token: token,
CurrentChannel: "email",
})
if err != nil {
return fmt.Errorf("trigger chat: %w", err)
}
g.logger.Info("email trigger chat completed",
slog.String("bot_id", botID))
return nil
}
func (g *EmailChatGateway) resolveBotOwner(ctx context.Context, botID string) (string, error) {
pgBotID, err := db.ParseUUID(botID)
if err != nil {
return "", err
}
bot, err := g.queries.GetBotByID(ctx, pgBotID)
if err != nil {
return "", fmt.Errorf("get bot: %w", err)
}
ownerID := bot.OwnerUserID.String()
if ownerID == "" {
return "", errors.New("bot owner not found")
}
return ownerID, nil
}
func (g *EmailChatGateway) generateToken(userID string) (string, error) {
if strings.TrimSpace(g.jwtSecret) == "" {
return "", errors.New("jwt secret not configured")
}
signed, _, err := auth.GenerateToken(userID, g.jwtSecret, emailTriggerTokenTTL)
if err != nil {
return "", err
}
return "Bearer " + signed, nil
}