- Telegram integration for customer statistics - MCP server implementation with rate limiting - Cache system for performance optimization - Multi-language support - RESTful API endpoints 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
154 lines
3.4 KiB
Go
154 lines
3.4 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
tgclient "funstatmcp/internal/telegram"
|
|
)
|
|
|
|
type App struct {
|
|
cfg Config
|
|
client *tgclient.Client
|
|
}
|
|
|
|
func New(cfg Config) (*App, error) {
|
|
client, err := tgclient.New(cfg.Telegram)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &App{
|
|
cfg: cfg,
|
|
client: client,
|
|
}, nil
|
|
}
|
|
|
|
func (a *App) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (a *App) SendCommand(ctx context.Context, command string, useCache bool) (string, error) {
|
|
return a.client.SendCommand(ctx, command, useCache)
|
|
}
|
|
|
|
func (a *App) CallTool(ctx context.Context, name string, args map[string]any) (string, error) {
|
|
switch name {
|
|
case "funstat_search":
|
|
query, err := requireString(args, "query")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return a.client.SendCommand(ctx, fmt.Sprintf("/search %s", query), true)
|
|
|
|
case "funstat_topchat":
|
|
category := optionalString(args, "category")
|
|
if category != "" {
|
|
return a.client.SendCommand(ctx, fmt.Sprintf("/topchat %s", category), true)
|
|
}
|
|
return a.client.SendCommand(ctx, "/topchat", true)
|
|
|
|
case "funstat_text":
|
|
text, err := requireString(args, "text")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return a.client.SendCommand(ctx, fmt.Sprintf("/text %s", text), true)
|
|
|
|
case "funstat_human":
|
|
nameArg, err := requireString(args, "name")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return a.client.SendCommand(ctx, fmt.Sprintf("/human %s", nameArg), true)
|
|
|
|
case "funstat_user_info":
|
|
identifier, err := requireString(args, "identifier")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
identifier = strings.TrimSpace(identifier)
|
|
if identifier == "" {
|
|
return "", fmt.Errorf("identifier cannot be empty")
|
|
}
|
|
return a.client.SendCommand(ctx, fmt.Sprintf("/user_info %s", identifier), true)
|
|
|
|
case "funstat_user_messages":
|
|
identifier, err := requireString(args, "identifier")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var maxPagesPtr *int
|
|
if value, ok := args["max_pages"]; ok {
|
|
v, err := toInt(value)
|
|
if err != nil {
|
|
return "", fmt.Errorf("max_pages must be an integer: %w", err)
|
|
}
|
|
maxPagesPtr = &v
|
|
}
|
|
return a.client.FetchUserMessages(ctx, identifier, maxPagesPtr)
|
|
|
|
case "funstat_balance":
|
|
return a.client.SendCommand(ctx, "/balance", true)
|
|
|
|
case "funstat_menu":
|
|
return a.client.SendCommand(ctx, "/menu", true)
|
|
|
|
case "funstat_start":
|
|
return a.client.SendCommand(ctx, "/start", true)
|
|
|
|
default:
|
|
return "", fmt.Errorf("unknown tool: %s", name)
|
|
}
|
|
}
|
|
|
|
func requireString(args map[string]any, key string) (string, error) {
|
|
value, ok := args[key]
|
|
if !ok {
|
|
return "", fmt.Errorf("missing required argument: %s", key)
|
|
}
|
|
str, ok := value.(string)
|
|
if !ok {
|
|
return "", fmt.Errorf("argument %s must be a string", key)
|
|
}
|
|
str = strings.TrimSpace(str)
|
|
if str == "" {
|
|
return "", fmt.Errorf("argument %s cannot be empty", key)
|
|
}
|
|
return str, nil
|
|
}
|
|
|
|
func optionalString(args map[string]any, key string) string {
|
|
if value, ok := args[key]; ok {
|
|
if str, ok := value.(string); ok {
|
|
return strings.TrimSpace(str)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func toInt(value any) (int, error) {
|
|
switch v := value.(type) {
|
|
case float64:
|
|
return int(v), nil
|
|
case float32:
|
|
return int(v), nil
|
|
case int:
|
|
return v, nil
|
|
case int32:
|
|
return int(v), nil
|
|
case int64:
|
|
return int(v), nil
|
|
case string:
|
|
parsed, err := strconv.Atoi(strings.TrimSpace(v))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return parsed, nil
|
|
default:
|
|
return 0, fmt.Errorf("unsupported type %T", value)
|
|
}
|
|
}
|