scrapebadger 0.2.0

Async Rust SDK and CLI for the ScrapeBadger web-scraping API (Amazon, Google, Twitter/X, Reddit, Vinted, Web Scraping).
Documentation
//! Pagination convenience adapters for Twitter.
//!
//! Most Twitter listing endpoints page with an opaque `cursor` query parameter
//! and return the next page's cursor in `next_cursor`. The generated methods
//! expose one page at a time; the `*_stream` adapters here wrap them with
//! [`cursor_stream`](crate::core::pagination::cursor_stream) so you can iterate
//! every item across pages as a single flat [`Stream`].
//!
//! This file is hand-written (not regenerated by `xtask gen`), so it is safe to
//! extend alongside the generated endpoint methods.
//!
//! ```no_run
//! # async fn demo(twitter: scrapebadger::Twitter) -> scrapebadger::Result<()> {
//! use futures_util::StreamExt;
//! let stream = twitter.advanced_search_tweets_stream(
//!     scrapebadger::twitter::AdvancedSearchTweetsParams {
//!         query: Some("rust lang".into()),
//!         ..Default::default()
//!     },
//! );
//! futures_util::pin_mut!(stream);
//! while let Some(tweet) = stream.next().await {
//!     let _tweet = tweet?;
//! }
//! # Ok(()) }
//! ```

use futures_core::Stream;

use crate::core::pagination::cursor_stream;
use crate::core::Result;

use super::generated::*;
use super::Twitter;

/// Generate a `*_stream` adapter for a cursor-paginated endpoint that takes no
/// path argument (only a `Params` value).
macro_rules! cursor_stream_no_path {
    ($(#[$meta:meta])* $stream_fn:ident => $call_fn:ident, $params:ty, $item:ty) => {
        $(#[$meta])*
        pub fn $stream_fn(&self, params: $params) -> impl Stream<Item = Result<$item>> {
            let this = self.clone();
            cursor_stream(None::<String>, move |cursor| {
                let this = this.clone();
                let mut params = params.clone();
                async move {
                    params.cursor = cursor;
                    let page = this.$call_fn(params).await?;
                    Ok((page.data.unwrap_or_default(), page.next_cursor))
                }
            })
        }
    };
}

/// Generate a `*_stream` adapter for a cursor-paginated endpoint that takes one
/// path argument (e.g. a user id, tweet id, or list id) plus a `Params` value.
macro_rules! cursor_stream_path {
    ($(#[$meta:meta])* $stream_fn:ident => $call_fn:ident, $arg:ident, $params:ty, $item:ty) => {
        $(#[$meta])*
        pub fn $stream_fn(
            &self,
            $arg: impl AsRef<str>,
            params: $params,
        ) -> impl Stream<Item = Result<$item>> {
            let this = self.clone();
            let arg = $arg.as_ref().to_string();
            cursor_stream(None::<String>, move |cursor| {
                let this = this.clone();
                let arg = arg.clone();
                let mut params = params.clone();
                async move {
                    params.cursor = cursor;
                    let page = this.$call_fn(&arg, params).await?;
                    Ok((page.data.unwrap_or_default(), page.next_cursor))
                }
            })
        }
    };
}

impl Twitter {
    cursor_stream_no_path! {
        /// Stream every tweet matching an advanced search, following pagination
        /// cursors automatically. Any `cursor` set on `params` is ignored.
        advanced_search_tweets_stream => advanced_search_tweets, AdvancedSearchTweetsParams, TweetData
    }

    cursor_stream_no_path! {
        /// Stream every user matching a user search, across all pages.
        search_users_stream => search_users, SearchUsersParams, UserData
    }

    cursor_stream_path! {
        /// Stream a user's latest tweets across all pages.
        get_user_latest_tweets_stream => get_user_latest_tweets, username, GetUserLatestTweetsParams, TweetData
    }

    cursor_stream_path! {
        /// Stream the tweets mentioning a user across all pages.
        get_user_mentions_stream => get_user_mentions, username, GetUserMentionsParams, TweetData
    }

    cursor_stream_path! {
        /// Stream every follower of a user across all pages.
        get_user_followers_stream => get_user_followers, username, GetUserFollowersParams, UserData
    }

    cursor_stream_path! {
        /// Stream every account a user follows across all pages.
        get_user_followings_stream => get_user_followings, username, GetUserFollowingsParams, UserData
    }

    cursor_stream_path! {
        /// Stream a user's subscriptions across all pages.
        get_user_subscriptions_stream => get_user_subscriptions, user_id, GetUserSubscriptionsParams, UserData
    }

    cursor_stream_path! {
        /// Stream a user's articles across all pages.
        get_user_articles_stream => get_user_articles, user_id, GetUserArticlesParams, ArticleData
    }

    cursor_stream_path! {
        /// Stream every reply to a tweet across all pages.
        get_tweet_replies_stream => get_tweet_replies, tweet_id, GetTweetRepliesParams, TweetData
    }

    cursor_stream_path! {
        /// Stream every quote tweet of a tweet across all pages.
        get_tweet_quotes_stream => get_tweet_quotes, tweet_id, GetTweetQuotesParams, TweetData
    }

    cursor_stream_path! {
        /// Stream every account that retweeted a tweet across all pages.
        get_tweet_retweeters_stream => get_tweet_retweeters, tweet_id, GetTweetRetweetersParams, UserData
    }

    cursor_stream_path! {
        /// Stream every account that liked a tweet across all pages.
        get_tweet_favoriters_stream => get_tweet_favoriters, tweet_id, GetTweetFavoritersParams, UserData
    }

    cursor_stream_path! {
        /// Stream every tweet in a community across all pages.
        get_community_tweets_stream => get_community_tweets, community_id, GetCommunityTweetsParams, TweetData
    }

    cursor_stream_path! {
        /// Stream every tweet in a list across all pages.
        get_list_tweets_stream => get_list_tweets, list_id, GetListTweetsParams, TweetData
    }

    cursor_stream_path! {
        /// Stream every tweet matching a within-list search across all pages.
        search_list_tweets_stream => search_list_tweets, list_id, SearchListTweetsParams, TweetData
    }
}