Add scraper function to get user by ID
This commit is contained in:
parent
210328bcc9
commit
4ea15f10af
@ -163,6 +163,12 @@ func main() {
|
||||
login(target, password)
|
||||
case "fetch_user":
|
||||
fetch_user(scraper.UserHandle(target))
|
||||
case "fetch_user_by_id":
|
||||
id, err := strconv.Atoi(target)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fetch_user_by_id(scraper.UserID(id))
|
||||
case "download_user_content":
|
||||
download_user_content(scraper.UserHandle(target))
|
||||
case "fetch_tweet_only":
|
||||
@ -310,6 +316,26 @@ func fetch_user(handle scraper.UserHandle) {
|
||||
happy_exit("Saved the user", nil)
|
||||
}
|
||||
|
||||
func fetch_user_by_id(id scraper.UserID) {
|
||||
session, err := scraper.NewGuestSession() // This endpoint works better if you're not logged in
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
user, err := session.GetUserByID(id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Debug(user)
|
||||
|
||||
err = profile.SaveUser(&user)
|
||||
if err != nil {
|
||||
die(fmt.Sprintf("Error saving user: %s", err.Error()), false, 4)
|
||||
}
|
||||
|
||||
download_user_content(user.Handle)
|
||||
happy_exit("Saved the user", nil)
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrape a single tweet and save it in the database.
|
||||
*
|
||||
|
@ -139,6 +139,8 @@ func (app *Application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
http.StripPrefix("/messages", http.HandlerFunc(app.Messages)).ServeHTTP(w, r)
|
||||
case "nav-sidebar-poll-updates":
|
||||
app.NavSidebarPollUpdates(w, r)
|
||||
case "communities":
|
||||
panic("not implemented")
|
||||
default:
|
||||
app.UserFeed(w, r)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@
|
||||
<label class="nav-sidebar__button-label">Bookmarks</label>
|
||||
</li>
|
||||
</a>
|
||||
<a href="#">
|
||||
<a hx-get="/communities">
|
||||
<li class="button labelled-icon">
|
||||
<img class="svg-icon" src="/static/icons/communities.svg" width="24" height="24" />
|
||||
<label class="nav-sidebar__button-label">Communities</label>
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
var (
|
||||
END_OF_FEED = errors.New("End of feed")
|
||||
ErrDoesntExist = errors.New("Doesn't exist")
|
||||
ErrUserIsBanned = errors.New("user is banned")
|
||||
EXTERNAL_API_ERROR = errors.New("Unexpected result from external API")
|
||||
ErrorIsTombstone = errors.New("tweet is a tombstone")
|
||||
ErrRateLimited = errors.New("rate limited")
|
||||
|
@ -63,6 +63,7 @@ type GraphqlFeatures struct {
|
||||
ResponsiveWebTextConversationsEnabled bool `json:"responsive_web_text_conversations_enabled"`
|
||||
ResponsiveWebTwitterArticleTweetConsumptionEnabled bool `json:"responsive_web_twitter_article_tweet_consumption_enabled"`
|
||||
ResponsiveWebMediaDownloadVideoEnabled bool `json:"responsive_web_media_download_video_enabled"`
|
||||
ResponsiveWebTwitterArticleNotesTabEnabled bool `json:"responsive_web_twitter_article_notes_tab_enabled"`
|
||||
SubscriptionsVerificationInfoVerifiedSinceEnabled bool `json:"subscriptions_verification_info_verified_since_enabled"`
|
||||
HiddenProfileLikesEnabled bool `json:"hidden_profile_likes_enabled"`
|
||||
HiddenProfileSubscriptionsEnabled bool `json:"hidden_profile_subscriptions_enabled"`
|
||||
@ -81,6 +82,7 @@ type GraphqlFeatures struct {
|
||||
ArticlesPreviewEnabled bool `json:"articles_preview_enabled,omitempty"`
|
||||
GraphqlTimelineV2BookmarkTimeline bool `json:"graphql_timeline_v2_bookmark_timeline,omitempty"`
|
||||
CreatorSubscriptionsQuoteTweetPreviewEnabled bool `json:"creator_subscriptions_quote_tweet_preview_enabled"`
|
||||
SubscriptionsFeatureCanGiftPremium bool `json:"subscriptions_feature_can_gift_premium,omitempty"`
|
||||
}
|
||||
|
||||
type GraphqlURL struct {
|
||||
|
@ -1384,6 +1384,48 @@ func (api API) GetUser(handle UserHandle) (User, error) {
|
||||
return ParseSingleUser(apiUser)
|
||||
}
|
||||
|
||||
func (api API) GetUserByID(u_id UserID) (User, error) {
|
||||
url, err := url.Parse(GraphqlURL{
|
||||
BaseUrl: "https://x.com/i/api/graphql/Qw77dDjp9xCpUY-AXwt-yQ/UserByRestId",
|
||||
Variables: GraphqlVariables{
|
||||
UserID: u_id,
|
||||
},
|
||||
Features: GraphqlFeatures{
|
||||
RWebTipjarConsumptionEnabled: true,
|
||||
ResponsiveWebGraphqlExcludeDirectiveEnabled: true,
|
||||
VerifiedPhoneLabelEnabled: false,
|
||||
ResponsiveWebGraphqlSkipUserProfileImageExtensionsEnabled: false,
|
||||
ResponsiveWebGraphqlTimelineNavigationEnabled: true,
|
||||
SubscriptionsFeatureCanGiftPremium: true,
|
||||
ResponsiveWebTwitterArticleNotesTabEnabled: true,
|
||||
},
|
||||
}.String())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var response UserResponse
|
||||
err = api.do_http(url.String(), "", &response)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
apiUser, err := response.ConvertToAPIUser()
|
||||
if errors.Is(err, ErrDoesntExist) {
|
||||
return User{}, err
|
||||
}
|
||||
if apiUser.ScreenName == "" {
|
||||
if apiUser.IsBanned {
|
||||
return User{}, ErrUserIsBanned
|
||||
} else {
|
||||
return User{}, ErrDoesntExist
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return User{}, fmt.Errorf("Error fetching user ID %d:\n %w", u_id, err)
|
||||
}
|
||||
return ParseSingleUser(apiUser)
|
||||
}
|
||||
|
||||
// Paginated Search
|
||||
// ----------------
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user