Complete implementation of xiaohongshu (Little Red Book) automation system: ### Core Features: - **QR Code Login**: Automated login with cookie persistence - **Content Publishing**: Post text, images with AI-powered descriptions - **Browser Management**: Headless Chrome automation via go-rod - **Cookie Persistence**: Session management for login state - **MCP Server**: Model Context Protocol integration for Claude ### Technical Components: - go-rod browser automation with stealth mode - MCP server for Claude Code integration - Cookie-based session management - Robust error handling and logging - Cross-platform compatibility ### API Endpoints: - Login status checking and QR code authentication - Content publishing with image upload support - Navigation and page interaction utilities This provides a complete foundation for xiaohongshu automation with proper session management and MCP integration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
128 lines
3.2 KiB
Go
128 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// LoginWaitRequest 等待登录请求
|
|
type LoginWaitRequest struct {
|
|
Timeout int `json:"timeout"`
|
|
}
|
|
|
|
// ErrorResponse 错误响应
|
|
type ErrorResponse struct {
|
|
Error string `json:"error"`
|
|
Code string `json:"code"`
|
|
Details any `json:"details,omitempty"`
|
|
}
|
|
|
|
// SuccessResponse 成功响应
|
|
type SuccessResponse struct {
|
|
Success bool `json:"success"`
|
|
Data any `json:"data"`
|
|
Message string `json:"message,omitempty"`
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
|
|
// XiaohongshuService 全局服务实例
|
|
var xiaohongshuService = NewXiaohongshuService()
|
|
|
|
// checkLoginStatusHandler 检查登录状态
|
|
func checkLoginStatusHandler(c *gin.Context) {
|
|
status, err := 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 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 := xiaohongshuService.PublishContent(c.Request.Context(), &req)
|
|
if err != nil {
|
|
respondError(c, http.StatusInternalServerError, "PUBLISH_FAILED",
|
|
"发布失败", err.Error())
|
|
return
|
|
}
|
|
|
|
respondSuccess(c, result, "发布成功")
|
|
}
|
|
|
|
// healthHandler 健康检查
|
|
func healthHandler(c *gin.Context) {
|
|
respondSuccess(c, map[string]any{
|
|
"status": "healthy",
|
|
"service": "xiaohongshu-mcp",
|
|
"account": "ai-report",
|
|
"timestamp": "now",
|
|
}, "服务正常")
|
|
}
|
|
|
|
// corsMiddleware CORS 中间件
|
|
func corsMiddleware() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
c.Header("Access-Control-Allow-Origin", "*")
|
|
c.Header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
|
c.Header("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
|
|
|
if c.Request.Method == "OPTIONS" {
|
|
c.AbortWithStatus(http.StatusNoContent)
|
|
return
|
|
}
|
|
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// errorHandlingMiddleware 错误处理中间件
|
|
func errorHandlingMiddleware() gin.HandlerFunc {
|
|
return gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
|
|
logrus.Errorf("服务器内部错误: %v, path: %s", recovered, c.Request.URL.Path)
|
|
|
|
respondError(c, http.StatusInternalServerError, "INTERNAL_ERROR",
|
|
"服务器内部错误", recovered)
|
|
})
|
|
}
|