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)
|
login(target, password)
|
||||||
case "fetch_user":
|
case "fetch_user":
|
||||||
fetch_user(scraper.UserHandle(target))
|
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":
|
case "download_user_content":
|
||||||
download_user_content(scraper.UserHandle(target))
|
download_user_content(scraper.UserHandle(target))
|
||||||
case "fetch_tweet_only":
|
case "fetch_tweet_only":
|
||||||
@ -310,6 +316,26 @@ func fetch_user(handle scraper.UserHandle) {
|
|||||||
happy_exit("Saved the user", nil)
|
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.
|
* 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)
|
http.StripPrefix("/messages", http.HandlerFunc(app.Messages)).ServeHTTP(w, r)
|
||||||
case "nav-sidebar-poll-updates":
|
case "nav-sidebar-poll-updates":
|
||||||
app.NavSidebarPollUpdates(w, r)
|
app.NavSidebarPollUpdates(w, r)
|
||||||
|
case "communities":
|
||||||
|
panic("not implemented")
|
||||||
default:
|
default:
|
||||||
app.UserFeed(w, r)
|
app.UserFeed(w, r)
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
<label class="nav-sidebar__button-label">Bookmarks</label>
|
<label class="nav-sidebar__button-label">Bookmarks</label>
|
||||||
</li>
|
</li>
|
||||||
</a>
|
</a>
|
||||||
<a href="#">
|
<a hx-get="/communities">
|
||||||
<li class="button labelled-icon">
|
<li class="button labelled-icon">
|
||||||
<img class="svg-icon" src="/static/icons/communities.svg" width="24" height="24" />
|
<img class="svg-icon" src="/static/icons/communities.svg" width="24" height="24" />
|
||||||
<label class="nav-sidebar__button-label">Communities</label>
|
<label class="nav-sidebar__button-label">Communities</label>
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
END_OF_FEED = errors.New("End of feed")
|
END_OF_FEED = errors.New("End of feed")
|
||||||
ErrDoesntExist = errors.New("Doesn't exist")
|
ErrDoesntExist = errors.New("Doesn't exist")
|
||||||
|
ErrUserIsBanned = errors.New("user is banned")
|
||||||
EXTERNAL_API_ERROR = errors.New("Unexpected result from external API")
|
EXTERNAL_API_ERROR = errors.New("Unexpected result from external API")
|
||||||
ErrorIsTombstone = errors.New("tweet is a tombstone")
|
ErrorIsTombstone = errors.New("tweet is a tombstone")
|
||||||
ErrRateLimited = errors.New("rate limited")
|
ErrRateLimited = errors.New("rate limited")
|
||||||
|
@ -63,6 +63,7 @@ type GraphqlFeatures struct {
|
|||||||
ResponsiveWebTextConversationsEnabled bool `json:"responsive_web_text_conversations_enabled"`
|
ResponsiveWebTextConversationsEnabled bool `json:"responsive_web_text_conversations_enabled"`
|
||||||
ResponsiveWebTwitterArticleTweetConsumptionEnabled bool `json:"responsive_web_twitter_article_tweet_consumption_enabled"`
|
ResponsiveWebTwitterArticleTweetConsumptionEnabled bool `json:"responsive_web_twitter_article_tweet_consumption_enabled"`
|
||||||
ResponsiveWebMediaDownloadVideoEnabled bool `json:"responsive_web_media_download_video_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"`
|
SubscriptionsVerificationInfoVerifiedSinceEnabled bool `json:"subscriptions_verification_info_verified_since_enabled"`
|
||||||
HiddenProfileLikesEnabled bool `json:"hidden_profile_likes_enabled"`
|
HiddenProfileLikesEnabled bool `json:"hidden_profile_likes_enabled"`
|
||||||
HiddenProfileSubscriptionsEnabled bool `json:"hidden_profile_subscriptions_enabled"`
|
HiddenProfileSubscriptionsEnabled bool `json:"hidden_profile_subscriptions_enabled"`
|
||||||
@ -81,6 +82,7 @@ type GraphqlFeatures struct {
|
|||||||
ArticlesPreviewEnabled bool `json:"articles_preview_enabled,omitempty"`
|
ArticlesPreviewEnabled bool `json:"articles_preview_enabled,omitempty"`
|
||||||
GraphqlTimelineV2BookmarkTimeline bool `json:"graphql_timeline_v2_bookmark_timeline,omitempty"`
|
GraphqlTimelineV2BookmarkTimeline bool `json:"graphql_timeline_v2_bookmark_timeline,omitempty"`
|
||||||
CreatorSubscriptionsQuoteTweetPreviewEnabled bool `json:"creator_subscriptions_quote_tweet_preview_enabled"`
|
CreatorSubscriptionsQuoteTweetPreviewEnabled bool `json:"creator_subscriptions_quote_tweet_preview_enabled"`
|
||||||
|
SubscriptionsFeatureCanGiftPremium bool `json:"subscriptions_feature_can_gift_premium,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GraphqlURL struct {
|
type GraphqlURL struct {
|
||||||
|
@ -1384,6 +1384,48 @@ func (api API) GetUser(handle UserHandle) (User, error) {
|
|||||||
return ParseSingleUser(apiUser)
|
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
|
// Paginated Search
|
||||||
// ----------------
|
// ----------------
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user