n0madic / twitter-scraper

Scrape the Twitter frontend API without authentication with Golang.
MIT License
886 stars 180 forks source link

Get tweet by ID #145

Open aero89 opened 11 months ago

aero89 commented 11 months ago
func (s *Scraper) GetTweetByID(id string) (*Tweet, error) {
    req, err := s.newRequest("GET", "https://twitter.com/i/api/graphql/mbnjGF4gOwo5gyp9pe5s4A/TweetResultByRestId")
    if err != nil {
        return nil, err
    }

    variables := map[string]interface{}{
        "tweetId":                id,
        "withCommunity":          false,
        "includePromotedContent": false,
        "withVoice":              false,
        "withV2Timeline":         true,
    }

    features := map[string]interface{}{
        "creator_subscriptions_tweet_preview_api_enabled":                         true,
        "tweetypie_unmention_optimization_enabled":                                true,
        "responsive_web_edit_tweet_api_enabled":                                   true,
        "graphql_is_translatable_rweb_tweet_is_translatable_enabled":              true,
        "view_counts_everywhere_api_enabled":                                      true,
        "longform_notetweets_consumption_enabled":                                 true,
        "responsive_web_twitter_article_tweet_consumption_enabled":                false,
        "tweet_awards_web_tipping_enabled":                                        false,
        "responsive_web_home_pinned_timelines_enabled":                            false,
        "freedom_of_speech_not_reach_fetch_enabled":                               true,
        "standardized_nudges_misinfo":                                             true,
        "tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled": true,
        "longform_notetweets_rich_text_read_enabled":                              true,
        "longform_notetweets_inline_media_enabled":                                true,
        "responsive_web_graphql_exclude_directive_enabled":                        true,
        "verified_phone_label_enabled":                                            false,
        "responsive_web_media_download_video_enabled":                             false,
        "responsive_web_graphql_skip_user_profile_image_extensions_enabled":       false,
        "responsive_web_graphql_timeline_navigation_enabled":                      true,
        "responsive_web_enhance_cards_enabled":                                    false,
    }

    query := url.Values{}
    query.Set("variables", mapToJSONString(variables))
    query.Set("features", mapToJSONString(features))
    req.URL.RawQuery = query.Encode()

    var (
        res struct {
                        Data struct {
                      TweetResult struct {
                               Result result `json:"result"`
                       } `json:"tweetResult"`
                     } `json:"data"`
                }
    )

    curBearerToken := s.bearerToken
    if curBearerToken != bearerToken2 {
        s.setBearerToken(bearerToken2)
    }

    err = s.RequestAPI(req, &res)

    if curBearerToken != bearerToken2 {
        s.setBearerToken(curBearerToken)
    }

    if err != nil {
        return nil, err
    }

    tweet := res.Data.TweetResult.Result.parse()
    if tweet != nil && tweet.ID == id {
        return tweet, nil
    }
    return nil, fmt.Errorf("tweet with ID %s not found", id)
}