ultisuite-backend/internal/ai/chat_sync.go
R3D347HR4Y 0466a1c169
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run
wow
2026-06-11 01:22:52 +02:00

102 lines
2.7 KiB
Go

package ai
import (
"context"
"encoding/json"
"fmt"
"io"
"path"
"strings"
"time"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/ultisuite/ulti-backend/internal/nextcloud"
)
type ChatStore struct {
nc *nextcloud.Client
db *pgxpool.Pool
}
func NewChatStore(nc *nextcloud.Client, db *pgxpool.Pool) *ChatStore {
return &ChatStore{nc: nc, db: db}
}
func (s *ChatStore) Sync(ctx context.Context, userEmail string, record ChatRecord) error {
if s == nil || s.nc == nil {
return fmt.Errorf("nextcloud unavailable")
}
policy, _ := LoadAssistantPolicy(ctx, s.db)
basePath := policy.ChatNCPath
if strings.TrimSpace(basePath) == "" {
basePath = nextcloud.DefaultChatNCBasePath
}
if strings.TrimSpace(record.ID) == "" {
return fmt.Errorf("chat id required")
}
if record.UpdatedAt.IsZero() {
record.UpdatedAt = time.Now().UTC()
}
if record.CreatedAt.IsZero() {
record.CreatedAt = record.UpdatedAt
}
if strings.TrimSpace(record.Source) == "" {
record.Source = "openwebui"
}
userID := nextcloud.UserIDFromClaims(userEmail, "")
sidecarPath := nextcloud.ChatSidecarPath(basePath, record.ID)
dir := path.Dir(sidecarPath)
if dir != "/" && dir != "." {
_ = s.nc.CreateFolder(ctx, userID, dir)
}
payload, err := json.MarshalIndent(record, "", " ")
if err != nil {
return err
}
return s.nc.Upload(ctx, userID, sidecarPath, strings.NewReader(string(payload)), "application/json")
}
func (s *ChatStore) Get(ctx context.Context, userEmail, chatID string) (ChatRecord, error) {
if s == nil || s.nc == nil {
return ChatRecord{}, fmt.Errorf("nextcloud unavailable")
}
policy, _ := LoadAssistantPolicy(ctx, s.db)
basePath := policy.ChatNCPath
if strings.TrimSpace(basePath) == "" {
basePath = nextcloud.DefaultChatNCBasePath
}
userID := nextcloud.UserIDFromClaims(userEmail, "")
sidecarPath := nextcloud.ChatSidecarPath(basePath, chatID)
body, _, err := s.nc.Download(ctx, userID, sidecarPath)
if err != nil {
return ChatRecord{}, err
}
defer body.Close()
raw, err := io.ReadAll(io.LimitReader(body, 8<<20))
if err != nil {
return ChatRecord{}, err
}
var record ChatRecord
if err := json.Unmarshal(raw, &record); err != nil {
return ChatRecord{}, err
}
return record, nil
}
func (s *ChatStore) Delete(ctx context.Context, userEmail, chatID string) error {
if s == nil || s.nc == nil {
return fmt.Errorf("nextcloud unavailable")
}
policy, _ := LoadAssistantPolicy(ctx, s.db)
basePath := policy.ChatNCPath
if strings.TrimSpace(basePath) == "" {
basePath = nextcloud.DefaultChatNCBasePath
}
userID := nextcloud.UserIDFromClaims(userEmail, "")
sidecarPath := nextcloud.ChatSidecarPath(basePath, chatID)
return s.nc.Delete(ctx, userID, sidecarPath)
}