package handler import ( "strconv" "spider/internal/model" "spider/internal/store" "github.com/gin-gonic/gin" ) // ChannelHandler handles TG channel management. type ChannelHandler struct { store *store.Store } // List handles GET /channels func (h *ChannelHandler) List(c *gin.Context) { page, pageSize, offset := parsePage(c) query := h.store.DB.Model(&model.Channel{}) if status := c.Query("status"); status != "" { query = query.Where("status = ?", status) } if source := c.Query("source"); source != "" { query = query.Where("source = ?", source) } if search := c.Query("search"); search != "" { query = query.Where("username LIKE ?", "%"+search+"%") } var total int64 query.Count(&total) var channels []model.Channel if err := query.Order("created_at DESC").Limit(pageSize).Offset(offset).Find(&channels).Error; err != nil { Fail(c, 500, err.Error()) return } PageOK(c, channels, total, page, pageSize) } // UpdateStatus handles PUT /channels/:id/status func (h *ChannelHandler) UpdateStatus(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { Fail(c, 400, "invalid id") return } var body struct { Status string `json:"status" binding:"required"` } if err := c.ShouldBindJSON(&body); err != nil { Fail(c, 400, err.Error()) return } allowed := map[string]bool{"pending": true, "scraped": true, "failed": true, "skipped": true} if !allowed[body.Status] { Fail(c, 400, "invalid status") return } var ch model.Channel if err := h.store.DB.First(&ch, id).Error; err != nil { Fail(c, 404, "channel not found") return } h.store.DB.Model(&ch).Update("status", body.Status) OK(c, ch) } // Delete handles DELETE /channels/:id func (h *ChannelHandler) Delete(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { Fail(c, 400, "invalid id") return } if err := h.store.DB.Delete(&model.Channel{}, id).Error; err != nil { Fail(c, 500, err.Error()) return } OK(c, gin.H{"message": "已删除"}) } // Stats handles GET /channels/stats func (h *ChannelHandler) Stats(c *gin.Context) { type kv struct { Key string `gorm:"column:key"` Count int64 `gorm:"column:count"` } var byStatus []kv h.store.DB.Model(&model.Channel{}). Select("status as `key`, count(*) as `count`"). Group("status").Find(&byStatus) var bySource []kv h.store.DB.Model(&model.Channel{}). Select("source as `key`, count(*) as `count`"). Group("source").Find(&bySource) var total int64 h.store.DB.Model(&model.Channel{}).Count(&total) OK(c, gin.H{ "total": total, "by_status": byStatus, "by_source": bySource, }) }