| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package handlers
- import (
- "errors"
- "net/http"
- "time"
- "github.com/celestia-trace/backend/models"
- "github.com/gin-gonic/gin"
- "gorm.io/gorm"
- )
- type SyncHandler struct {
- DB *gorm.DB
- }
- func defaultSyncSetting(userID string) models.SyncSetting {
- return models.SyncSetting{
- UserID: userID,
- AutoSyncWiFi: true,
- SyncPhotos: true,
- SyncAudio: true,
- AudioQuality: "HD",
- CloudStorageMaxMB: 5120,
- CloudStorageUsedMB: 0,
- }
- }
- // GetSyncSettings returns the user sync settings and storage status
- func (h *SyncHandler) GetSyncSettings(c *gin.Context) {
- userID := c.GetString("userID")
- var setting models.SyncSetting
- err := h.DB.First(&setting, "user_id = ?", userID).Error
- if errors.Is(err, gorm.ErrRecordNotFound) {
- setting = defaultSyncSetting(userID)
- h.DB.Create(&setting)
- }
- var totalBytes int64
- h.DB.Model(&models.MediaAsset{}).Where("user_id = ?", userID).Select("COALESCE(SUM(size_bytes), 0)").Scan(&totalBytes)
- setting.CloudStorageUsedMB = (totalBytes + 1024*1024 - 1) / (1024 * 1024)
- respondSuccess(c, setting)
- }
- // UpdateSyncSettings updates sync settings
- func (h *SyncHandler) UpdateSyncSettings(c *gin.Context) {
- userID := c.GetString("userID")
- var req models.UpdateSyncSettingRequest
- if err := c.ShouldBindJSON(&req); err != nil {
- respondError(c, http.StatusBadRequest, 400, "invalid parameters")
- return
- }
- var setting models.SyncSetting
- if err := h.DB.First(&setting, "user_id = ?", userID).Error; err != nil {
- setting = defaultSyncSetting(userID)
- }
- if req.AutoSyncWiFi != nil {
- setting.AutoSyncWiFi = *req.AutoSyncWiFi
- }
- if req.SyncPhotos != nil {
- setting.SyncPhotos = *req.SyncPhotos
- }
- if req.SyncAudio != nil {
- setting.SyncAudio = *req.SyncAudio
- }
- if req.AudioQuality != nil {
- setting.AudioQuality = *req.AudioQuality
- }
- now := time.Now()
- setting.LastSyncedAt = &now
- if err := h.DB.Save(&setting).Error; err != nil {
- respondError(c, http.StatusInternalServerError, 500, "failed to update sync settings")
- return
- }
- respondSuccess(c, setting)
- }
- // GetSyncSummary returns aggregated stats (devices, sessions, total duration, storage)
- func (h *SyncHandler) GetSyncSummary(c *gin.Context) {
- userID := c.GetString("userID")
- var deviceCount int64
- h.DB.Model(&models.BoundDevice{}).Where("user_id = ?", userID).Count(&deviceCount)
- var sessionCount int64
- h.DB.Model(&models.CelestiaSession{}).Where("user_id = ? AND deleted_at IS NULL", userID).Count(&sessionCount)
- var totalDurationMs int64
- h.DB.Model(&models.CelestiaSession{}).Where("user_id = ? AND deleted_at IS NULL", userID).Select("COALESCE(SUM(duration_ms), 0)").Scan(&totalDurationMs)
- var setting models.SyncSetting
- if err := h.DB.First(&setting, "user_id = ?", userID).Error; err != nil {
- setting = defaultSyncSetting(userID)
- h.DB.Create(&setting)
- }
- var totalBytes int64
- h.DB.Model(&models.MediaAsset{}).Where("user_id = ?", userID).Select("COALESCE(SUM(size_bytes), 0)").Scan(&totalBytes)
- setting.CloudStorageUsedMB = (totalBytes + 1024*1024 - 1) / (1024 * 1024)
- summary := models.SyncSummary{
- DeviceCount: deviceCount,
- SessionCount: sessionCount,
- TotalDurationMs: totalDurationMs,
- Storage: setting,
- }
- respondSuccess(c, summary)
- }
- // TriggerManualSync records a completed client checkpoint. It does not claim
- // that local files were uploaded; the client only calls this after all uploads.
- func (h *SyncHandler) TriggerManualSync(c *gin.Context) {
- userID := c.GetString("userID")
- now := time.Now()
- var setting models.SyncSetting
- if err := h.DB.First(&setting, "user_id = ?", userID).Error; err == nil {
- setting.LastSyncedAt = &now
- h.DB.Save(&setting)
- }
- respondSuccess(c, gin.H{
- "syncedAt": now,
- "message": "Client sync checkpoint recorded",
- })
- }
- // GetStorageQuota returns the user's storage quota and current usage in bytes.
- // The iOS client calls GET /storage/quota before uploading large files.
- func (h *SyncHandler) GetStorageQuota(c *gin.Context) {
- userID := c.GetString("userID")
- var setting models.SyncSetting
- if err := h.DB.First(&setting, "user_id = ?", userID).Error; err != nil {
- setting = defaultSyncSetting(userID)
- h.DB.Create(&setting)
- }
- var usedBytes int64
- h.DB.Model(&models.MediaAsset{}).Where("user_id = ?", userID).
- Select("COALESCE(SUM(size_bytes), 0)").Scan(&usedBytes)
- totalBytes := setting.CloudStorageMaxMB * 1024 * 1024
- remainingBytes := totalBytes - usedBytes
- if remainingBytes < 0 {
- remainingBytes = 0
- }
- respondSuccess(c, gin.H{
- "totalBytes": totalBytes,
- "usedBytes": usedBytes,
- "remainingBytes": remainingBytes,
- })
- }
|