channel.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package handler
  2. import (
  3. "strconv"
  4. "spider/internal/model"
  5. "spider/internal/store"
  6. "github.com/gin-gonic/gin"
  7. )
  8. // ChannelHandler handles TG channel management.
  9. type ChannelHandler struct {
  10. store *store.Store
  11. }
  12. // List handles GET /channels
  13. func (h *ChannelHandler) List(c *gin.Context) {
  14. page, pageSize, offset := parsePage(c)
  15. query := h.store.DB.Model(&model.Channel{})
  16. if status := c.Query("status"); status != "" {
  17. query = query.Where("status = ?", status)
  18. }
  19. if source := c.Query("source"); source != "" {
  20. query = query.Where("source = ?", source)
  21. }
  22. if search := c.Query("search"); search != "" {
  23. query = query.Where("username LIKE ?", "%"+search+"%")
  24. }
  25. var total int64
  26. query.Count(&total)
  27. var channels []model.Channel
  28. if err := query.Order("created_at DESC").Limit(pageSize).Offset(offset).Find(&channels).Error; err != nil {
  29. Fail(c, 500, err.Error())
  30. return
  31. }
  32. PageOK(c, channels, total, page, pageSize)
  33. }
  34. // UpdateStatus handles PUT /channels/:id/status
  35. func (h *ChannelHandler) UpdateStatus(c *gin.Context) {
  36. id, err := strconv.ParseUint(c.Param("id"), 10, 64)
  37. if err != nil {
  38. Fail(c, 400, "invalid id")
  39. return
  40. }
  41. var body struct {
  42. Status string `json:"status" binding:"required"`
  43. }
  44. if err := c.ShouldBindJSON(&body); err != nil {
  45. Fail(c, 400, err.Error())
  46. return
  47. }
  48. allowed := map[string]bool{"pending": true, "scraped": true, "failed": true, "skipped": true}
  49. if !allowed[body.Status] {
  50. Fail(c, 400, "invalid status")
  51. return
  52. }
  53. var ch model.Channel
  54. if err := h.store.DB.First(&ch, id).Error; err != nil {
  55. Fail(c, 404, "channel not found")
  56. return
  57. }
  58. h.store.DB.Model(&ch).Update("status", body.Status)
  59. OK(c, ch)
  60. }
  61. // Delete handles DELETE /channels/:id
  62. func (h *ChannelHandler) Delete(c *gin.Context) {
  63. id, err := strconv.ParseUint(c.Param("id"), 10, 64)
  64. if err != nil {
  65. Fail(c, 400, "invalid id")
  66. return
  67. }
  68. if err := h.store.DB.Delete(&model.Channel{}, id).Error; err != nil {
  69. Fail(c, 500, err.Error())
  70. return
  71. }
  72. OK(c, gin.H{"message": "已删除"})
  73. }
  74. // Stats handles GET /channels/stats
  75. func (h *ChannelHandler) Stats(c *gin.Context) {
  76. type kv struct {
  77. Key string `gorm:"column:key"`
  78. Count int64 `gorm:"column:count"`
  79. }
  80. var byStatus []kv
  81. h.store.DB.Model(&model.Channel{}).
  82. Select("status as `key`, count(*) as `count`").
  83. Group("status").Find(&byStatus)
  84. var bySource []kv
  85. h.store.DB.Model(&model.Channel{}).
  86. Select("source as `key`, count(*) as `count`").
  87. Group("source").Find(&bySource)
  88. var total int64
  89. h.store.DB.Model(&model.Channel{}).Count(&total)
  90. OK(c, gin.H{
  91. "total": total,
  92. "by_status": byStatus,
  93. "by_source": bySource,
  94. })
  95. }