diff --git a/twarc/client2.py b/twarc/client2.py index ed9ce21b..afa1a613 100644 --- a/twarc/client2.py +++ b/twarc/client2.py @@ -1228,6 +1228,35 @@ def retweeted_by( f"Retrieved an empty page of results for retweeted_by of {tweet_id}" ) + def quotes( + self, + tweet_id, + expansions=None, + tweet_fields=None, + user_fields=None, + max_results=100, + pagination_token=None, + ): + """ + Retrieve the tweets that quote tweet the given tweet. + + """ + url = f"https://api.twitter.com/2/tweets/{tweet_id}/quote_tweets" + + params = self._prepare_params( + expansions=expansions, + tweet_fields=tweet_fields, + user_fields=user_fields, + max_results=max_results, + pagination_token=pagination_token, + ) + + for page in self.get_paginated(url, params=params): + if "data" in page: + yield page + else: + log.info(f"Retrieved an empty page of results for quotes of {tweet_id}") + @catch_request_exceptions @rate_limit def get(self, *args, **kwargs): diff --git a/twarc/command2.py b/twarc/command2.py index e7534af5..e9e5401c 100644 --- a/twarc/command2.py +++ b/twarc/command2.py @@ -978,6 +978,60 @@ def retweeted_by(T, tweet_id, outfile, limit, max_results, hide_progress): break +@twarc2.command("quotes") +@click.option( + "--limit", + default=0, + help="Maximum number of retweeting users to retrieve. Increments of 100 or --max-results if set.", + type=int, +) +@click.option( + "--max-results", + default=100, + help="Maximum number of users (retweets) per page of results. Default and maximum is 100.", + type=int, +) +@command_line_expansions_shortcuts +@command_line_expansions_options +@command_line_progressbar_option +@click.argument("tweet_id", type=str) +@click.argument("outfile", type=click.File("w"), default="-") +@click.pass_obj +@cli_api_error +def quotes(T, tweet_id, outfile, limit, max_results, hide_progress, **kwargs): + """ + Get the tweets that quote tweet the given tweet. + + Note that the progress bar is approximate. + """ + count = 0 + lookup_total = 0 + kwargs = _process_expansions_shortcuts(kwargs) + # Also remove media poll and place from kwargs, these are not valid for this endpoint: + kwargs.pop("media_fields", None) + kwargs.pop("poll_fields", None) + kwargs.pop("place_fields", None) + + if not re.match("^\d+$", str(tweet_id)): + click.echo(click.style("Please enter a tweet ID", fg="red"), err=True) + + hide_progress = True if (outfile.name == "") else hide_progress + + if not hide_progress: + target_tweet = list(T.tweet_lookup([tweet_id]))[0] + if "data" in target_tweet: + lookup_total = target_tweet["data"][0]["public_metrics"]["quote_count"] + + with tqdm(disable=hide_progress, total=lookup_total) as progress: + for result in T.quotes(tweet_id, max_results=max_results, **kwargs): + _write(result, outfile) + count += len(result.get("data", [])) + progress.update(len(result.get("data", []))) + if limit != 0 and count >= limit: + progress.desc = f"Set --limit of {limit} reached" + break + + @twarc2.command("liked-tweets") @click.option( "--limit",