thread-master/apps/backend/internal/module/appnotif/usecase/service.go

124 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package usecase
import (
"context"
"fmt"
"strings"
"apps/backend/internal/module/appnotif/domain"
"github.com/google/uuid"
)
type Service struct {
Repo domain.Repository
}
func New(repo domain.Repository) *Service {
return &Service{Repo: repo}
}
func (s *Service) List(ctx context.Context, ownerUID int64) ([]*domain.Notification, error) {
return s.Repo.ListByOwner(ctx, ownerUID)
}
func (s *Service) UnreadCount(ctx context.Context, ownerUID int64) (int64, error) {
return s.Repo.UnreadCount(ctx, ownerUID)
}
func (s *Service) MarkRead(ctx context.Context, ownerUID int64, id string) error {
return s.Repo.MarkRead(ctx, ownerUID, id)
}
func (s *Service) MarkAllRead(ctx context.Context, ownerUID int64) error {
return s.Repo.MarkAllRead(ctx, ownerUID)
}
// NotifyJobTerminal — 相容舊介面;改走 NotifyJobStateupsert 同一 job 一則)
func (s *Service) NotifyJobTerminal(ctx context.Context, ownerUID int64, jobID, status, summary string) error {
return s.NotifyJobState(ctx, ownerUID, jobID, "", status, summary, 100)
}
// NotifyJobState — 同一 job 只保留一則通知,進度更新時改寫 title/body鈴鐺即時有進度
func (s *Service) NotifyJobState(ctx context.Context, ownerUID int64, jobID, templateType, status, summary string, percent int) error {
if ownerUID <= 0 || jobID == "" {
return nil
}
title := jobNotifyTitle(templateType, status, percent)
body := strings.TrimSpace(summary)
if body == "" {
body = fmt.Sprintf("%s · %s", title, jobID)
}
// 進度摘要裡若已含 % 就不再重複;否則附上 percent
if percent > 0 && percent < 100 && !strings.Contains(body, "%") {
body = fmt.Sprintf("%s · %d%%", body, percent)
}
existing, err := s.Repo.FindLatestByJobRef(ctx, ownerUID, jobID)
now := domain.NowNano()
if err == nil && existing != nil {
existing.Title = title
existing.Body = body
existing.Kind = domain.KindJob
existing.RefType = domain.RefJob
existing.RefID = jobID
// 每次有進度/終態都標未讀,鈴鐺才會跳
existing.ReadAt = 0
// 用 created_at 排序時把最新活動頂到前面
existing.CreatedAt = now
return s.Repo.Replace(ctx, existing)
}
n := &domain.Notification{
ID: uuid.NewString(), OwnerUID: ownerUID,
Title: title, Body: body, Kind: domain.KindJob,
RefType: domain.RefJob, RefID: jobID,
CreatedAt: now,
}
return s.Repo.Insert(ctx, n)
}
func jobNotifyTitle(templateType, status string, percent int) string {
name := templateLabelZH(templateType)
switch status {
case "succeeded":
return name + " · 已完成"
case "failed":
return name + " · 失敗"
case "cancelled":
return name + " · 已取消"
case "running":
if percent > 0 {
return fmt.Sprintf("%s · 進行中 %d%%", name, percent)
}
return name + " · 進行中"
case "queued", "pending":
return name + " · 已排程"
default:
if percent > 0 {
return fmt.Sprintf("%s · %d%%", name, percent)
}
return name + " · 更新"
}
}
func templateLabelZH(templateType string) string {
switch templateType {
case "persona_analyze_account":
return "人設分析(爬公開貼文)"
case "persona_analyze_text":
return "人設分析(文字)"
case "compose_mimic":
return "仿寫貼文"
case "threads_token_renew":
return "Threads Token 延長"
case "demo":
return "Demo 測試任務"
default:
if strings.TrimSpace(templateType) == "" {
return "背景任務"
}
return "背景任務"
}
}