feat: add delete cookies functionality for login reset (#275)

This commit is contained in:
Ctrlz
2025-11-02 19:01:48 +08:00
committed by GitHub
parent 7cf35fc4ae
commit 11a937b84f
6 changed files with 88 additions and 11 deletions

View File

@@ -10,6 +10,7 @@ import (
type Cookier interface { type Cookier interface {
LoadCookies() ([]byte, error) LoadCookies() ([]byte, error)
SaveCookies(data []byte) error SaveCookies(data []byte) error
DeleteCookies() error
} }
type localCookie struct { type localCookie struct {
@@ -42,6 +43,15 @@ func (c *localCookie) SaveCookies(data []byte) error {
return os.WriteFile(c.path, data, 0644) return os.WriteFile(c.path, data, 0644)
} }
// DeleteCookies 删除 cookies 文件。
func (c *localCookie) DeleteCookies() error {
if _, err := os.Stat(c.path); os.IsNotExist(err) {
// 文件不存在,返回 nil认为已经删除
return nil
}
return os.Remove(c.path)
}
// GetCookiesFilePath 获取 cookies 文件路径。 // GetCookiesFilePath 获取 cookies 文件路径。
// 为了向后兼容,如果旧路径 /tmp/cookies.json 存在,则继续使用; // 为了向后兼容,如果旧路径 /tmp/cookies.json 存在,则继续使用;
// 否则使用当前目录下的 cookies.json // 否则使用当前目录下的 cookies.json

View File

@@ -3,6 +3,7 @@ package main
import ( import (
"net/http" "net/http"
"github.com/xpzouying/xiaohongshu-mcp/cookies"
"github.com/xpzouying/xiaohongshu-mcp/xiaohongshu" "github.com/xpzouying/xiaohongshu-mcp/xiaohongshu"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -63,6 +64,22 @@ func (s *AppServer) getLoginQrcodeHandler(c *gin.Context) {
respondSuccess(c, result, "获取登录二维码成功") respondSuccess(c, result, "获取登录二维码成功")
} }
// deleteCookiesHandler 删除 cookies重置登录状态
func (s *AppServer) deleteCookiesHandler(c *gin.Context) {
err := s.xiaohongshuService.DeleteCookies(c.Request.Context())
if err != nil {
respondError(c, http.StatusInternalServerError, "DELETE_COOKIES_FAILED",
"删除 cookies 失败", err.Error())
return
}
cookiePath := cookies.GetCookiesFilePath()
respondSuccess(c, map[string]interface{}{
"cookie_path": cookiePath,
"message": "Cookies 已成功删除,登录状态已重置。下次操作时需要重新登录。",
}, "删除 cookies 成功")
}
// publishHandler 发布内容 // publishHandler 发布内容
func (s *AppServer) publishHandler(c *gin.Context) { func (s *AppServer) publishHandler(c *gin.Context) {
var req PublishRequest var req PublishRequest

View File

@@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/xpzouying/xiaohongshu-mcp/cookies"
"github.com/xpzouying/xiaohongshu-mcp/xiaohongshu" "github.com/xpzouying/xiaohongshu-mcp/xiaohongshu"
"strings" "strings"
"time" "time"
@@ -27,7 +28,14 @@ func (s *AppServer) handleCheckLoginStatus(ctx context.Context) *MCPToolResult {
} }
} }
resultText := fmt.Sprintf("登录状态检查成功: %+v", status) // 根据 IsLoggedIn 判断并返回友好的提示
var resultText string
if status.IsLoggedIn {
resultText = fmt.Sprintf("✅ 已登录\n用户名: %s\n\n你可以使用其他功能了。", status.Username)
} else {
resultText = fmt.Sprintf("❌ 未登录\n\n请使用 get_login_qrcode 工具获取二维码进行登录。")
}
return &MCPToolResult{ return &MCPToolResult{
Content: []MCPContent{{ Content: []MCPContent{{
Type: "text", Type: "text",
@@ -76,6 +84,28 @@ func (s *AppServer) handleGetLoginQrcode(ctx context.Context) *MCPToolResult {
return &MCPToolResult{Content: contents} return &MCPToolResult{Content: contents}
} }
// handleDeleteCookies 处理删除 cookies 请求,用于登录重置
func (s *AppServer) handleDeleteCookies(ctx context.Context) *MCPToolResult {
logrus.Info("MCP: 删除 cookies重置登录状态")
err := s.xiaohongshuService.DeleteCookies(ctx)
if err != nil {
return &MCPToolResult{
Content: []MCPContent{{Type: "text", Text: "删除 cookies 失败: " + err.Error()}},
IsError: true,
}
}
cookiePath := cookies.GetCookiesFilePath()
resultText := fmt.Sprintf("Cookies 已成功删除,登录状态已重置。\n\n删除的文件路径: %s\n\n下次操作时需要重新登录。", cookiePath)
return &MCPToolResult{
Content: []MCPContent{{
Type: "text",
Text: resultText,
}},
}
}
// handlePublishContent 处理发布内容 // handlePublishContent 处理发布内容
func (s *AppServer) handlePublishContent(ctx context.Context, args map[string]interface{}) *MCPToolResult { func (s *AppServer) handlePublishContent(ctx context.Context, args map[string]interface{}) *MCPToolResult {
logrus.Info("MCP: 发布内容") logrus.Info("MCP: 发布内容")

View File

@@ -153,7 +153,19 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 3: 发布内容 // 工具 3: 删除 cookies登录重置
mcp.AddTool(server,
&mcp.Tool{
Name: "delete_cookies",
Description: "删除 cookies 文件,重置登录状态。删除后需要重新登录。",
},
withPanicRecovery("delete_cookies", func(ctx context.Context, req *mcp.CallToolRequest, _ any) (*mcp.CallToolResult, any, error) {
result := appServer.handleDeleteCookies(ctx)
return convertToMCPResult(result), nil, nil
}),
)
// 工具 4: 发布内容
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "publish_content", Name: "publish_content",
@@ -172,7 +184,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 4: 获取Feed列表 // 工具 5: 获取Feed列表
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "list_feeds", Name: "list_feeds",
@@ -184,7 +196,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 5: 搜索内容 // 工具 6: 搜索内容
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "search_feeds", Name: "search_feeds",
@@ -196,7 +208,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 6: 获取Feed详情 // 工具 7: 获取Feed详情
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "get_feed_detail", Name: "get_feed_detail",
@@ -212,7 +224,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 7: 获取用户主页 // 工具 8: 获取用户主页
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "user_profile", Name: "user_profile",
@@ -228,7 +240,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 8: 发表评论 // 工具 9: 发表评论
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "post_comment_to_feed", Name: "post_comment_to_feed",
@@ -245,7 +257,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 9: 发布视频(仅本地文件) // 工具 10: 发布视频(仅本地文件)
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "publish_with_video", Name: "publish_with_video",
@@ -263,7 +275,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 10: 点赞笔记 // 工具 11: 点赞笔记
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "like_feed", Name: "like_feed",
@@ -280,7 +292,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
// 工具 11: 收藏笔记 // 工具 12: 收藏笔记
mcp.AddTool(server, mcp.AddTool(server,
&mcp.Tool{ &mcp.Tool{
Name: "favorite_feed", Name: "favorite_feed",
@@ -297,7 +309,7 @@ func registerTools(server *mcp.Server, appServer *AppServer) {
}), }),
) )
logrus.Infof("Registered %d MCP tools", 11) logrus.Infof("Registered %d MCP tools", 12)
} }
// convertToMCPResult 将自定义的 MCPToolResult 转换为官方 SDK 的格式 // convertToMCPResult 将自定义的 MCPToolResult 转换为官方 SDK 的格式

View File

@@ -40,6 +40,7 @@ func setupRoutes(appServer *AppServer) *gin.Engine {
{ {
api.GET("/login/status", appServer.checkLoginStatusHandler) api.GET("/login/status", appServer.checkLoginStatusHandler)
api.GET("/login/qrcode", appServer.getLoginQrcodeHandler) api.GET("/login/qrcode", appServer.getLoginQrcodeHandler)
api.DELETE("/login/cookies", appServer.deleteCookiesHandler)
api.POST("/publish", appServer.publishHandler) api.POST("/publish", appServer.publishHandler)
api.POST("/publish_video", appServer.publishVideoHandler) api.POST("/publish_video", appServer.publishVideoHandler)
api.GET("/feeds/list", appServer.listFeedsHandler) api.GET("/feeds/list", appServer.listFeedsHandler)

View File

@@ -86,6 +86,13 @@ type UserProfileResponse struct {
Feeds []xiaohongshu.Feed `json:"feeds"` Feeds []xiaohongshu.Feed `json:"feeds"`
} }
// DeleteCookies 删除 cookies 文件,用于登录重置
func (s *XiaohongshuService) DeleteCookies(ctx context.Context) error {
cookiePath := cookies.GetCookiesFilePath()
cookieLoader := cookies.NewLoadCookie(cookiePath)
return cookieLoader.DeleteCookies()
}
// CheckLoginStatus 检查登录状态 // CheckLoginStatus 检查登录状态
func (s *XiaohongshuService) CheckLoginStatus(ctx context.Context) (*LoginStatusResponse, error) { func (s *XiaohongshuService) CheckLoginStatus(ctx context.Context) (*LoginStatusResponse, error) {
b := newBrowser() b := newBrowser()