Files
xiaohongshu-mcp/handlers_api.go
zy cd28e4064e feat: 添加小红书Feed评论功能 (#50)
实现通过HTTP GIN API和MCP API发表评论到小红书Feed的功能:
- 新增POST /api/v1/feeds/comment端点
- 新增post_comment_to_feed MCP工具
- 添加PostCommentRequest和PostCommentResponse类型
- 实现PostCommentToFeed服务方法
- 新增CommentFeedAction用于浏览器自动化操作

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-09 23:13:05 +08:00

157 lines
4.2 KiB
Go

package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
)
// respondError 返回错误响应
func respondError(c *gin.Context, statusCode int, code, message string, details any) {
response := ErrorResponse{
Error: message,
Code: code,
Details: details,
}
logrus.Errorf("%s %s %s %d", c.Request.Method, c.Request.URL.Path,
c.GetString("account"), statusCode)
c.JSON(statusCode, response)
}
// respondSuccess 返回成功响应
func respondSuccess(c *gin.Context, data any, message string) {
response := SuccessResponse{
Success: true,
Data: data,
Message: message,
}
logrus.Infof("%s %s %s %d", c.Request.Method, c.Request.URL.Path,
c.GetString("account"), http.StatusOK)
c.JSON(http.StatusOK, response)
}
// checkLoginStatusHandler 检查登录状态
func (s *AppServer) checkLoginStatusHandler(c *gin.Context) {
status, err := s.xiaohongshuService.CheckLoginStatus(c.Request.Context())
if err != nil {
respondError(c, http.StatusInternalServerError, "STATUS_CHECK_FAILED",
"检查登录状态失败", err.Error())
return
}
c.Set("account", "ai-report")
respondSuccess(c, status, "检查登录状态成功")
}
// publishHandler 发布内容
func (s *AppServer) publishHandler(c *gin.Context) {
var req PublishRequest
if err := c.ShouldBindJSON(&req); err != nil {
respondError(c, http.StatusBadRequest, "INVALID_REQUEST",
"请求参数错误", err.Error())
return
}
// 执行发布
result, err := s.xiaohongshuService.PublishContent(c.Request.Context(), &req)
if err != nil {
respondError(c, http.StatusInternalServerError, "PUBLISH_FAILED",
"发布失败", err.Error())
return
}
respondSuccess(c, result, "发布成功")
}
// listFeedsHandler 获取Feeds列表
func (s *AppServer) listFeedsHandler(c *gin.Context) {
// 获取 Feeds 列表
result, err := s.xiaohongshuService.ListFeeds(c.Request.Context())
if err != nil {
respondError(c, http.StatusInternalServerError, "LIST_FEEDS_FAILED",
"获取Feeds列表失败", err.Error())
return
}
c.Set("account", "ai-report")
respondSuccess(c, result, "获取Feeds列表成功")
}
// searchFeedsHandler 搜索Feeds
func (s *AppServer) searchFeedsHandler(c *gin.Context) {
keyword := c.Query("keyword")
if keyword == "" {
respondError(c, http.StatusBadRequest, "MISSING_KEYWORD",
"缺少关键词参数", "keyword parameter is required")
return
}
// 搜索 Feeds
result, err := s.xiaohongshuService.SearchFeeds(c.Request.Context(), keyword)
if err != nil {
respondError(c, http.StatusInternalServerError, "SEARCH_FEEDS_FAILED",
"搜索Feeds失败", err.Error())
return
}
c.Set("account", "ai-report")
respondSuccess(c, result, "搜索Feeds成功")
}
// getFeedDetailHandler 获取Feed详情
func (s *AppServer) getFeedDetailHandler(c *gin.Context) {
var req FeedDetailRequest
if err := c.ShouldBindJSON(&req); err != nil {
respondError(c, http.StatusBadRequest, "INVALID_REQUEST",
"请求参数错误", err.Error())
return
}
// 获取 Feed 详情
result, err := s.xiaohongshuService.GetFeedDetail(c.Request.Context(), req.FeedID, req.XsecToken)
if err != nil {
respondError(c, http.StatusInternalServerError, "GET_FEED_DETAIL_FAILED",
"获取Feed详情失败", err.Error())
return
}
c.Set("account", "ai-report")
respondSuccess(c, result, "获取Feed详情成功")
}
// postCommentHandler 发表评论到Feed
func (s *AppServer) postCommentHandler(c *gin.Context) {
var req PostCommentRequest
if err := c.ShouldBindJSON(&req); err != nil {
respondError(c, http.StatusBadRequest, "INVALID_REQUEST",
"请求参数错误", err.Error())
return
}
// 发表评论
result, err := s.xiaohongshuService.PostCommentToFeed(c.Request.Context(), req.FeedID, req.XsecToken, req.Content)
if err != nil {
respondError(c, http.StatusInternalServerError, "POST_COMMENT_FAILED",
"发表评论失败", err.Error())
return
}
c.Set("account", "ai-report")
respondSuccess(c, result, result.Message)
}
// healthHandler 健康检查
func healthHandler(c *gin.Context) {
respondSuccess(c, map[string]any{
"status": "healthy",
"service": "xiaohongshu-mcp",
"account": "ai-report",
"timestamp": "now",
}, "服务正常")
}