refactor: remove legacy finance module
This commit is contained in:
+14
-146
@@ -7,31 +7,28 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
xchart "ops-assistant/internal/chart"
|
||||
"ops-assistant/internal/core/ops"
|
||||
"ops-assistant/internal/service"
|
||||
"ops-assistant/models"
|
||||
|
||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// DefaultUserID 统一用户ID,使所有平台共享同一份账本
|
||||
// DefaultUserID 统一用户ID
|
||||
const DefaultUserID int64 = 1
|
||||
|
||||
type TGBot struct {
|
||||
api *tgbotapi.BotAPI
|
||||
finance *service.FinanceService
|
||||
db *gorm.DB
|
||||
opsSvc *ops.Service
|
||||
api *tgbotapi.BotAPI
|
||||
db *gorm.DB
|
||||
opsSvc *ops.Service
|
||||
}
|
||||
|
||||
func NewTGBot(db *gorm.DB, token string, finance *service.FinanceService, opsSvc *ops.Service) (*TGBot, error) {
|
||||
func NewTGBot(db *gorm.DB, token string, opsSvc *ops.Service) (*TGBot, error) {
|
||||
bot, err := tgbotapi.NewBotAPI(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &TGBot{api: bot, finance: finance, db: db, opsSvc: opsSvc}, nil
|
||||
return &TGBot{api: bot, db: db, opsSvc: opsSvc}, nil
|
||||
}
|
||||
|
||||
func (b *TGBot) Start(ctx context.Context) {
|
||||
@@ -91,147 +88,18 @@ func (b *TGBot) handleMessage(msg *tgbotapi.Message) {
|
||||
}
|
||||
}
|
||||
|
||||
var reply string
|
||||
|
||||
switch {
|
||||
case text == "/start":
|
||||
reply = "🛠️ 欢迎使用 Ops-Assistant!\n\n直接发送消费描述即可记账,例如:\n• 午饭 25元\n• 打车 ¥30\n• 买咖啡15块\n\n命令:\n/list - 查看最近记录\n/today - 今日汇总\n/chart - 本月图表\n/help - 帮助"
|
||||
|
||||
case text == "/help":
|
||||
reply = "📖 使用说明:\n\n直接发送带金额的文本即可自动记账。\n系统会自动识别金额和消费分类。\n\n支持格式:\n• 午饭 25元\n• ¥30 打车\n• 买水果15块\n\n命令:\n/list - 最近10条记录\n/today - 今日汇总\n/chart - 本月消费图表\n/week - 近7天每日趋势\n/start - 欢迎信息"
|
||||
|
||||
case text == "/today":
|
||||
today := time.Now().Format("2006-01-02")
|
||||
items, err := b.finance.GetTransactionsByDate(DefaultUserID, today)
|
||||
if err != nil {
|
||||
reply = "❌ 查询失败"
|
||||
} else if len(items) == 0 {
|
||||
reply = fmt.Sprintf("📭 %s 暂无消费记录", today)
|
||||
} else {
|
||||
var sb strings.Builder
|
||||
var total int64
|
||||
sb.WriteString(fmt.Sprintf("📊 今日(%s)消费:\n\n", today))
|
||||
for _, item := range items {
|
||||
sb.WriteString(fmt.Sprintf("• %s:%.2f元\n", item.Category, item.AmountYuan()))
|
||||
total += item.Amount
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("\n💰 共 %d 笔,合计 %.2f 元", len(items), float64(total)/100.0))
|
||||
reply = sb.String()
|
||||
}
|
||||
|
||||
case text == "/chart":
|
||||
b.sendMonthlyChart(chatID)
|
||||
return
|
||||
|
||||
case text == "/week":
|
||||
b.sendWeeklyChart(chatID)
|
||||
return
|
||||
|
||||
case text == "/list":
|
||||
items, err := b.finance.GetTransactions(DefaultUserID, 10)
|
||||
if err != nil {
|
||||
reply = "❌ 查询失败"
|
||||
} else if len(items) == 0 {
|
||||
reply = "📭 暂无记录"
|
||||
} else {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("📋 最近记录:\n\n")
|
||||
for _, item := range items {
|
||||
sb.WriteString(fmt.Sprintf("• [%s] %s:%.2f元\n", item.Date, item.Category, item.AmountYuan()))
|
||||
}
|
||||
reply = sb.String()
|
||||
}
|
||||
|
||||
case strings.HasPrefix(text, "/"):
|
||||
reply = "❓ 未知命令,输入 /help 查看帮助"
|
||||
|
||||
reply := ""
|
||||
switch text {
|
||||
case "/start":
|
||||
reply = "🛠️ 欢迎使用 Ops-Assistant!\n\n模块化运维命令助手,支持:\n• /cpa - CPA 管理\n• /cf - Cloudflare 管理\n• /cfdav - cfdav 管理\n• /sub - 订阅管理\n• /mail - 邮箱管理\n\n/help - 使用说明"
|
||||
case "/help":
|
||||
reply = "📖 使用说明:\n\n直接发送 OPS 命令即可,例如:\n• /cpa status\n• /cf zones\n• /cf dns list <zone_id>\n• /cfdav users\n• /sub list\n\n模块入口默认关闭,可在 Web 后台「模块设置」中启用。"
|
||||
default:
|
||||
amount, category, err := b.finance.AddTransaction(DefaultUserID, text)
|
||||
if err != nil {
|
||||
reply = "❌ 记账失败,请稍后重试"
|
||||
log.Printf("记账失败: %v", err)
|
||||
} else if amount == 0 {
|
||||
reply = "📍 没看到金额,这笔花了多少钱?"
|
||||
} else {
|
||||
amountYuan := float64(amount) / 100.0
|
||||
reply = fmt.Sprintf("✅ 已记入【%s】:%.2f元\n📝 备注:%s", category, amountYuan, text)
|
||||
}
|
||||
reply = "❓ 无法识别,输入 /help 查看支持的命令"
|
||||
}
|
||||
|
||||
m := tgbotapi.NewMessage(chatID, reply)
|
||||
if _, err := b.api.Send(m); err != nil {
|
||||
log.Printf("发送消息失败 chat=%d: %v", chatID, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *TGBot) sendMonthlyChart(chatID int64) {
|
||||
now := time.Now()
|
||||
dateFrom := now.Format("2006-01") + "-01"
|
||||
dateTo := now.Format("2006-01-02")
|
||||
title := fmt.Sprintf("%d年%d月消费分类", now.Year(), now.Month())
|
||||
|
||||
stats, err := b.finance.GetCategoryStats(DefaultUserID, dateFrom, dateTo)
|
||||
if err != nil || len(stats) == 0 {
|
||||
m := tgbotapi.NewMessage(chatID, "📭 本月暂无消费数据")
|
||||
b.api.Send(m)
|
||||
return
|
||||
}
|
||||
|
||||
imgData, err := xchart.GeneratePieChart(stats, title)
|
||||
if err != nil {
|
||||
log.Printf("生成饼图失败: %v", err)
|
||||
m := tgbotapi.NewMessage(chatID, "❌ 图表生成失败")
|
||||
b.api.Send(m)
|
||||
return
|
||||
}
|
||||
|
||||
var total int64
|
||||
var totalCount int
|
||||
for _, s := range stats {
|
||||
total += s.Total
|
||||
totalCount += s.Count
|
||||
}
|
||||
caption := fmt.Sprintf("📊 %s\n💰 共 %d 笔,合计 %.2f 元", title, totalCount, float64(total)/100.0)
|
||||
|
||||
photo := tgbotapi.NewPhoto(chatID, tgbotapi.FileBytes{Name: "chart.png", Bytes: imgData})
|
||||
photo.Caption = caption
|
||||
if _, err := b.api.Send(photo); err != nil {
|
||||
log.Printf("发送图表失败 chat=%d: %v", chatID, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *TGBot) sendWeeklyChart(chatID int64) {
|
||||
now := time.Now()
|
||||
dateFrom := now.AddDate(0, 0, -6).Format("2006-01-02")
|
||||
dateTo := now.Format("2006-01-02")
|
||||
title := fmt.Sprintf("近7天消费趋势 (%s ~ %s)", dateFrom[5:], dateTo[5:])
|
||||
|
||||
stats, err := b.finance.GetDailyStats(DefaultUserID, dateFrom, dateTo)
|
||||
if err != nil || len(stats) == 0 {
|
||||
m := tgbotapi.NewMessage(chatID, "📭 近7天暂无消费数据")
|
||||
b.api.Send(m)
|
||||
return
|
||||
}
|
||||
|
||||
imgData, err := xchart.GenerateBarChart(stats, title)
|
||||
if err != nil {
|
||||
log.Printf("生成柱状图失败: %v", err)
|
||||
m := tgbotapi.NewMessage(chatID, "❌ 图表生成失败")
|
||||
b.api.Send(m)
|
||||
return
|
||||
}
|
||||
|
||||
var total int64
|
||||
var totalCount int
|
||||
for _, s := range stats {
|
||||
total += s.Total
|
||||
totalCount += s.Count
|
||||
}
|
||||
caption := fmt.Sprintf("📈 %s\n💰 共 %d 笔,合计 %.2f 元", title, totalCount, float64(total)/100.0)
|
||||
|
||||
photo := tgbotapi.NewPhoto(chatID, tgbotapi.FileBytes{Name: "chart.png", Bytes: imgData})
|
||||
photo.Caption = caption
|
||||
if _, err := b.api.Send(photo); err != nil {
|
||||
log.Printf("发送图表失败 chat=%d: %v", chatID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user