package ibd import ( "context" "encoding/json" "fmt" "io" "log/slog" "net/http" ) const ( userInfoUrl = "https://myibd.investors.com/services/userprofile.aspx?format=json" ) func (c *Client) UserInfo(ctx context.Context, cookie *http.Cookie) (*UserProfile, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, userInfoUrl, nil) if err != nil { return nil, err } req.AddCookie(cookie) resp, err := c.Do(req) if err != nil { return nil, err } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) content, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response body: %w", err) } if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf( "unexpected status code %d: %s", resp.StatusCode, string(content), ) } up := new(UserProfile) if err = up.UnmarshalJSON(content); err != nil { return nil, err } return up, nil } type UserStatus string const ( UserStatusUnknown UserStatus = "" UserStatusVisitor UserStatus = "Visitor" UserStatusSubscriber UserStatus = "Subscriber" ) type UserProfile struct { DisplayName string Email string FirstName string LastName string Status UserStatus } func (u *UserProfile) UnmarshalJSON(bytes []byte) error { var resp userProfileResponse if err := json.Unmarshal(bytes, &resp); err != nil { return err } u.DisplayName = resp.UserProfile.UserDisplayName u.Email = resp.UserProfile.UserEmailAddress u.FirstName = resp.UserProfile.UserFirstName u.LastName = resp.UserProfile.UserLastName switch resp.UserProfile.UserTrialStatus { case "Visitor": u.Status = UserStatusVisitor case "Subscriber": u.Status = UserStatusSubscriber default: slog.Warn("Unknown user status", "status", resp.UserProfile.UserTrialStatus) u.Status = UserStatusUnknown } return nil } type userProfileResponse struct { UserProfile userProfile `json:"userProfile"` } type userProfile struct { UserSubType string `json:"userSubType"` UserId string `json:"userId"` UserDisplayName string `json:"userDisplayName"` Countrycode string `json:"countrycode"` IsEUCountry string `json:"isEUCountry"` Log string `json:"log"` AgeGroup string `json:"ageGroup"` Gender string `json:"gender"` InvestingExperience string `json:"investingExperience"` NumberOfTrades string `json:"numberOfTrades"` Occupation string `json:"occupation"` TypeOfInvestments string `json:"typeOfInvestments"` UserEmailAddress string `json:"userEmailAddress"` UserEmailAddressSHA1 string `json:"userEmailAddressSHA1"` UserEmailAddressSHA256 string `json:"userEmailAddressSHA256"` UserEmailAddressMD5 string `json:"userEmailAddressMD5"` UserFirstName string `json:"userFirstName"` UserLastName string `json:"userLastName"` UserZip string `json:"userZip"` UserTrialStatus string `json:"userTrialStatus"` UserProductsOnTrial string `json:"userProductsOnTrial"` UserProductsOwned string `json:"userProductsOwned"` UserAdTrade string `json:"userAdTrade"` UserAdTime string `json:"userAdTime"` UserAdHold string `json:"userAdHold"` UserAdJob string `json:"userAdJob"` UserAdAge string `json:"userAdAge"` UserAdOutSell string `json:"userAdOutSell"` UserVisitCount string `json:"userVisitCount"` RoleLeaderboard bool `json:"role_leaderboard"` RoleOws bool `json:"role_ows"` RoleIbdlive bool `json:"role_ibdlive"` RoleFounderclub bool `json:"role_founderclub"` RoleEibd bool `json:"role_eibd"` RoleIcom bool `json:"role_icom"` RoleEtables bool `json:"role_etables"` RoleTru10 bool `json:"role_tru10"` RoleMarketsurge bool `json:"role_marketsurge"` RoleSwingtrader bool `json:"role_swingtrader"` RoleAdfree bool `json:"role_adfree"` RoleMarketdiem bool `json:"role_marketdiem"` RoleWsjPlus bool `json:"role_wsj_plus"` RoleWsj bool `json:"role_wsj"` RoleBarrons bool `json:"role_barrons"` RoleMarketwatch bool `json:"role_marketwatch"` UserAdRoles string `json:"userAdRoles"` TrialDailyPrintNeg bool `json:"trial_daily_print_neg"` TrialDailyPrintNon bool `json:"trial_daily_print_non"` TrialWeeklyPrintNeg bool `json:"trial_weekly_print_neg"` TrialWeeklyPrintNon bool `json:"trial_weekly_print_non"` TrialDailyComboNeg bool `json:"trial_daily_combo_neg"` TrialDailyComboNon bool `json:"trial_daily_combo_non"` TrialWeeklyComboNeg bool `json:"trial_weekly_combo_neg"` TrialWeeklyComboNon bool `json:"trial_weekly_combo_non"` TrialEibdNeg bool `json:"trial_eibd_neg"` TrialEibdNon bool `json:"trial_eibd_non"` UserVideoPreference string `json:"userVideoPreference"` UserProfessionalStatus bool `json:"userProfessionalStatus"` }