myProfileHandler (#239)
Co-authored-by: Buf Generate <buf-generate@bondee.com>
This commit is contained in:
@@ -227,3 +227,17 @@ func healthHandler(c *gin.Context) {
|
|||||||
"timestamp": "now",
|
"timestamp": "now",
|
||||||
}, "服务正常")
|
}, "服务正常")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// myProfileHandler 我的信息
|
||||||
|
func (s *AppServer) myProfileHandler(c *gin.Context) {
|
||||||
|
// 获取当前登录用户信息
|
||||||
|
result, err := s.xiaohongshuService.GetMyProfile(c.Request.Context())
|
||||||
|
if err != nil {
|
||||||
|
respondError(c, http.StatusInternalServerError, "GET_MY_PROFILE_FAILED",
|
||||||
|
"获取我的主页失败", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set("account", "ai-report")
|
||||||
|
respondSuccess(c, map[string]any{"data": result}, "获取我的主页成功")
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ func setupRoutes(appServer *AppServer) *gin.Engine {
|
|||||||
api.POST("/feeds/detail", appServer.getFeedDetailHandler)
|
api.POST("/feeds/detail", appServer.getFeedDetailHandler)
|
||||||
api.POST("/user/profile", appServer.userProfileHandler)
|
api.POST("/user/profile", appServer.userProfileHandler)
|
||||||
api.POST("/feeds/comment", appServer.postCommentHandler)
|
api.POST("/feeds/comment", appServer.postCommentHandler)
|
||||||
|
api.GET("/user/me", appServer.myProfileHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
return router
|
return router
|
||||||
|
|||||||
35
service.go
35
service.go
@@ -461,3 +461,38 @@ func saveCookies(page *rod.Page) error {
|
|||||||
cookieLoader := cookies.NewLoadCookie(cookies.GetCookiesFilePath())
|
cookieLoader := cookies.NewLoadCookie(cookies.GetCookiesFilePath())
|
||||||
return cookieLoader.SaveCookies(data)
|
return cookieLoader.SaveCookies(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// withBrowserPage 执行需要浏览器页面的操作的通用函数
|
||||||
|
func withBrowserPage(fn func(*rod.Page) error) error {
|
||||||
|
b := newBrowser()
|
||||||
|
defer b.Close()
|
||||||
|
|
||||||
|
page := b.NewPage()
|
||||||
|
defer page.Close()
|
||||||
|
|
||||||
|
return fn(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyProfile 获取当前登录用户的个人信息
|
||||||
|
func (s *XiaohongshuService) GetMyProfile(ctx context.Context) (*UserProfileResponse, error) {
|
||||||
|
var result *xiaohongshu.UserProfileResponse
|
||||||
|
var err error
|
||||||
|
|
||||||
|
err = withBrowserPage(func(page *rod.Page) error {
|
||||||
|
action := xiaohongshu.NewUserProfileAction(page)
|
||||||
|
result, err = action.GetMyProfileViaSidebar(ctx)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &UserProfileResponse{
|
||||||
|
UserBasicInfo: result.UserBasicInfo,
|
||||||
|
Interactions: result.Interactions,
|
||||||
|
Feeds: result.Feeds,
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,3 +23,23 @@ func (n *NavigateAction) ToExplorePage(ctx context.Context) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NavigateAction) ToProfilePage(ctx context.Context) error {
|
||||||
|
page := n.page.Context(ctx)
|
||||||
|
|
||||||
|
// First navigate to explore page
|
||||||
|
if err := n.ToExplorePage(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
page.MustWaitStable()
|
||||||
|
|
||||||
|
// Find and click the "我" channel link in sidebar
|
||||||
|
profileLink := page.MustElement(`div.main-container li.user.side-bar-component a.link-wrapper span.channel`)
|
||||||
|
profileLink.MustClick()
|
||||||
|
|
||||||
|
// Wait for navigation to complete
|
||||||
|
page.MustWaitLoad()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ func (u *UserProfileAction) UserProfile(ctx context.Context, userID, xsecToken s
|
|||||||
page.MustNavigate(searchURL)
|
page.MustNavigate(searchURL)
|
||||||
page.MustWaitStable()
|
page.MustWaitStable()
|
||||||
|
|
||||||
|
return u.extractUserProfileData(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractUserProfileData 从页面中提取用户资料数据的通用方法
|
||||||
|
func (u *UserProfileAction) extractUserProfileData(page *rod.Page) (*UserProfileResponse, error) {
|
||||||
page.MustWait(`() => window.__INITIAL_STATE__ !== undefined`)
|
page.MustWait(`() => window.__INITIAL_STATE__ !== undefined`)
|
||||||
|
|
||||||
// 获取 window.__INITIAL_STATE__ 并转换为 JSON 字符串
|
// 获取 window.__INITIAL_STATE__ 并转换为 JSON 字符串
|
||||||
@@ -69,3 +74,20 @@ func (u *UserProfileAction) UserProfile(ctx context.Context, userID, xsecToken s
|
|||||||
func makeUserProfileURL(userID, xsecToken string) string {
|
func makeUserProfileURL(userID, xsecToken string) string {
|
||||||
return fmt.Sprintf("https://www.xiaohongshu.com/user/profile/%s?xsec_token=%s&xsec_source=pc_note", userID, xsecToken)
|
return fmt.Sprintf("https://www.xiaohongshu.com/user/profile/%s?xsec_token=%s&xsec_source=pc_note", userID, xsecToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *UserProfileAction) GetMyProfileViaSidebar(ctx context.Context) (*UserProfileResponse, error) {
|
||||||
|
page := u.page.Context(ctx)
|
||||||
|
|
||||||
|
// 创建导航动作
|
||||||
|
navigate := NewNavigate(page)
|
||||||
|
|
||||||
|
// 通过侧边栏导航到个人主页
|
||||||
|
if err := navigate.ToProfilePage(ctx); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to navigate to profile page via sidebar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待页面加载完成并获取 __INITIAL_STATE__
|
||||||
|
page.MustWaitStable()
|
||||||
|
|
||||||
|
return u.extractUserProfileData(page)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user