feat: xiaji-go v1.0.0 - 智能记账机器人

- Telegram Bot + QQ Bot (WebSocket) 双平台支持
- 150+ 预设分类关键词,jieba 智能分词
- Web 管理后台(记录查看/删除/CSV导出)
- 金额精确存储(分/int64)
- 版本信息嵌入(编译时注入)
- Docker 支持
- 优雅关闭(context + signal)
This commit is contained in:
2026-02-15 06:40:04 +08:00
commit 0c1a4f06f7
18 changed files with 1719 additions and 0 deletions

102
cmd/main.go Normal file
View File

@@ -0,0 +1,102 @@
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"time"
"xiaji-go/config"
"xiaji-go/internal/bot"
"xiaji-go/internal/qq"
"xiaji-go/internal/service"
"xiaji-go/internal/web"
"xiaji-go/models"
"xiaji-go/version"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
func main() {
// 版本信息
if len(os.Args) > 1 && (os.Args[1] == "-v" || os.Args[1] == "--version" || os.Args[1] == "version") {
fmt.Println(version.Info())
return
}
log.Printf("🦞 %s", version.Info())
// 1. 加载配置
cfgPath := "config.yaml"
if len(os.Args) > 1 {
cfgPath = os.Args[1]
}
cfg, err := config.LoadConfig(cfgPath)
if err != nil {
log.Fatalf("无法加载配置: %v", err)
}
// 2. 初始化数据库
db, err := gorm.Open(sqlite.Open(cfg.Database.Path), &gorm.Config{})
if err != nil {
log.Fatalf("无法连接数据库: %v", err)
}
// 3. 自动迁移表结构
if err := models.Migrate(db); err != nil {
log.Fatalf("数据库迁移失败: %v", err)
}
// 4. 初始化核心服务
finance := service.NewFinanceService(db)
defer finance.Close()
// 全局 context用于优雅退出
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 5. 启动 Telegram Bot
if cfg.Telegram.Enabled {
tgBot, err := bot.NewTGBot(cfg.Telegram.Token, finance)
if err != nil {
log.Printf("⚠️ TG Bot 启动失败: %v", err)
} else {
go tgBot.Start(ctx)
}
}
// 6. 启动 QQ Bot
if cfg.QQBot.Enabled {
qqBot := qq.NewQQBot(cfg.QQBot.AppID, cfg.QQBot.Secret, finance)
go qqBot.Start(ctx)
}
// 7. 启动 Web 后台
webServer := web.NewWebServer(db, cfg.Server.Port, cfg.Admin.Username, cfg.Admin.Password)
go webServer.Start()
// 8. 优雅关闭
log.Println("🦞 Xiaji-Go 已全面启动")
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
log.Println("⏳ 正在关闭服务...")
cancel() // 通知所有 goroutine 停止
// 等待一点时间让 goroutine 退出
time.Sleep(2 * time.Second)
// 关闭数据库连接
sqlDB, err := db.DB()
if err == nil {
sqlDB.Close()
}
log.Println("👋 Xiaji-Go 已关闭")
}