Title: | Wrapper for the 'AT' Protocol Behind 'Bluesky' |
---|---|
Description: | Wraps the 'AT' Protocol (Authenticated Transfer Protocol) behind 'Bluesky' <https://bsky.social>. Functions can be used for, among others, retrieving posts and followers from the network or posting content. |
Authors: | Johannes B. Gruber [aut, cre] , Benjamin Guinaudeau [aut, ctb] , Fabio Votta [aut, ctb] |
Maintainer: | Johannes B. Gruber <[email protected]> |
License: | MIT + file LICENSE |
Version: | 0.0.4.9000 |
Built: | 2024-11-24 12:47:28 UTC |
Source: | https://github.com/jbgruber/atrrr |
Run authentication for a network using the AT protocol (e.g., 'Blue Sky') and save the token permanently.
auth( user, password, domain = "https://bsky.app/", verbose = TRUE, overwrite = FALSE, token = NULL )
auth( user, password, domain = "https://bsky.app/", verbose = TRUE, overwrite = FALSE, token = NULL )
user |
Your user handle (e.g, benguinaudeau.bsky.social). |
password |
Your app password (usually created on https://bsky.app/settings/app-passwords). |
domain |
For now https://bsky.app/, but could change in the future. |
verbose |
Whether to print status messages to the Console
( |
overwrite |
If TRUE, overwrites old token without asking for confirmation. |
token |
(Stale) token object. Usually you don't need to use this. But if you manage your own tokens and they get stale, you can use this parameter and request a fresh token. |
After requesting the token, it is saved in the location returned by
file.path(tools::R_user_dir("atrrr", "cache"), Sys.getenv("BSKY_TOKEN", unset = "token.rds"))
. If you have multiple tokens, you can use
Sys.setenv(BSKY_TOKEN = "filename.rds")
to save/load the token with a
different name.
An authentication token (invisible)
## Not run: # request a token auth() # this will guide you through all steps # the token is stored in the location returned by this command file.path(tools::R_user_dir("atrrr", "cache"), Sys.getenv("BSKY_TOKEN", unset = "token.rds")) # to use a different than the default file name for the token, set BSKY_TOKEN Sys.setenv(BSKY_TOKEN = "identity-2.rds") # now either rename your token file or request a new token auth() # the cache now contains two tokens list.files(tools::R_user_dir("atrrr", "cache")) # functions that interact with the API also take a .token argument with the # path. For example: tok_path <- file.path(tools::R_user_dir("atrrr", "cache"), "identity-2.rds") get_skeets_authored_by(actor = "benguinaudeau.bsky.social", parse = TRUE, .token = tok_path) ## End(Not run)
## Not run: # request a token auth() # this will guide you through all steps # the token is stored in the location returned by this command file.path(tools::R_user_dir("atrrr", "cache"), Sys.getenv("BSKY_TOKEN", unset = "token.rds")) # to use a different than the default file name for the token, set BSKY_TOKEN Sys.setenv(BSKY_TOKEN = "identity-2.rds") # now either rename your token file or request a new token auth() # the cache now contains two tokens list.files(tools::R_user_dir("atrrr", "cache")) # functions that interact with the API also take a .token argument with the # path. For example: tok_path <- file.path(tools::R_user_dir("atrrr", "cache"), "identity-2.rds") get_skeets_authored_by(actor = "benguinaudeau.bsky.social", parse = TRUE, .token = tok_path) ## End(Not run)
Converts betweet http URL and AT URI
convert_http_to_at(link, .token = NULL) convert_at_to_http(link)
convert_http_to_at(link, .token = NULL) convert_at_to_http(link)
link |
either an AT or HTTP link. |
.token |
If you manage your own tokens, you can supply it here. Usually
|
The AT protocol uses a different scheme to link to posts, useser, feeds etc. Instead of the common https:// link format, internally a links starting with at:// are used (see https://atproto.com/specs/at-uri-scheme for details). The functions convert links from the HTTP to the AT format, or the other way around. This is useful if you want to use a link in a browser.
either an AT or HTTP link
## Not run: convert_http_to_at("https://bsky.app/profile/benguinaudeau.bsky.social/post/3kbi5v7oncq25") convert_at_to_http("at://did:plc:vuvsifrusnjsys7mhkpk662u/app.bsky.feed.post/3kbi5v7oncq25") ## End(Not run)
## Not run: convert_http_to_at("https://bsky.app/profile/benguinaudeau.bsky.social/post/3kbi5v7oncq25") convert_at_to_http("at://did:plc:vuvsifrusnjsys7mhkpk662u/app.bsky.feed.post/3kbi5v7oncq25") ## End(Not run)
Un/Follow an account
follow(actor, verbose = NULL, .token = NULL) unfollow(actor, verbose = NULL, .token = NULL)
follow(actor, verbose = NULL, .token = NULL) unfollow(actor, verbose = NULL, .token = NULL)
actor |
User handle to follow or unfollow |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
You can only unfollow accounts which you also followed through the API/the package.
list with URI and CID of the record (invisible).
## Not run: # follow our test account follow("atpr.bsky.social") # unfollow our test account unfollow("atpr.bsky.social") ## End(Not run)
## Not run: # follow our test account follow("atpr.bsky.social") # unfollow our test account unfollow("atpr.bsky.social") ## End(Not run)
Get likes of a user
get_actor_likes( actor, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
get_actor_likes( actor, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
actor |
user handle to retrieve likes for. |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of likes/reposts
## Not run: get_actor_likes("jbgruber.bsky.social") ## End(Not run)
## Not run: get_actor_likes("jbgruber.bsky.social") ## End(Not run)
Get the skeets that would be shown when you open the given feed
get_feed( feed_url, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
get_feed( feed_url, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
feed_url |
The url of the requested feed |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of posts
## Not run: # use the URL of a feed get_feed("https://bsky.app/profile/did:plc:2zcfjzyocp6kapg6jc4eacok/feed/aaaeckvqc3gzg") # or search for a feed by name res <- search_feed("#rstats") get_feed(res$uri[1]) ## End(Not run)
## Not run: # use the URL of a feed get_feed("https://bsky.app/profile/did:plc:2zcfjzyocp6kapg6jc4eacok/feed/aaaeckvqc3gzg") # or search for a feed by name res <- search_feed("#rstats") get_feed(res$uri[1]) ## End(Not run)
Get likes of a feed
get_feed_likes( feed_url, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
get_feed_likes( feed_url, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
feed_url |
the URL of a feed for which to retrieve who liked it. |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of likes/reposts
## Not run: # use the URL of a feed get_feed_likes("https://bsky.app/profile/did:plc:2zcfjzyocp6kapg6jc4eacok/feed/aaaeckvqc3gzg") # or search for a feed by name res <- search_feed("#rstats") get_feed_likes(res$uri[1]) ## End(Not run)
## Not run: # use the URL of a feed get_feed_likes("https://bsky.app/profile/did:plc:2zcfjzyocp6kapg6jc4eacok/feed/aaaeckvqc3gzg") # or search for a feed by name res <- search_feed("#rstats") get_feed_likes(res$uri[1]) ## End(Not run)
A view of the feed created by an actor.
get_feeds_created_by( actor, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
get_feeds_created_by( actor, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
actor |
user handle to retrieve feed from |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of feeds
## Not run: feed <- get_feeds_created_by("andrew.heiss.phd") ## End(Not run)
## Not run: feed <- get_feeds_created_by("andrew.heiss.phd") ## End(Not run)
Get followers and follows of an actor
get_followers( actor, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL ) get_follows( actor, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
get_followers( actor, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL ) get_follows( actor, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
actor |
user handle to look up followers for. |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of found actors.
## Not run: get_followers("benguinaudeau.bsky.social") # get first page of results follows_df <- get_follows("favstats.eu", limit = 25L) # continue same search, starting from the next match follows_df2 <- get_follows("favstats.eu", limit = 25L, cursor = attr(follows_df, "last_cursor")) ## End(Not run)
## Not run: get_followers("benguinaudeau.bsky.social") # get first page of results follows_df <- get_follows("favstats.eu", limit = 25L) # continue same search, starting from the next match follows_df2 <- get_follows("favstats.eu", limit = 25L, cursor = attr(follows_df, "last_cursor")) ## End(Not run)
Get likes/reposts of a skeet
get_likes( post_url, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL ) get_reposts( post_url, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
get_likes( post_url, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL ) get_reposts( post_url, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
post_url |
the URL of a skeet for which to retrieve who liked/reposted it. |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of likes/reposts
## Not run: get_likes("https://bsky.app/profile/jbgruber.bsky.social/post/3kbi55xm6u62v") get_reposts("https://bsky.app/profile/jbgruber.bsky.social/post/3kbi55xm6u62v") ## End(Not run)
## Not run: get_likes("https://bsky.app/profile/jbgruber.bsky.social/post/3kbi55xm6u62v") get_reposts("https://bsky.app/profile/jbgruber.bsky.social/post/3kbi55xm6u62v") ## End(Not run)
Get the posts that would be shown when you open the Bluesky app or website.
get_own_timeline( algorithm = NULL, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
get_own_timeline( algorithm = NULL, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
algorithm |
algorithm used to sort the posts |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of posts
## Not run: get_own_timeline() get_own_timeline(algorithm = "reverse-chronological") ## End(Not run)
## Not run: get_own_timeline() get_own_timeline(algorithm = "reverse-chronological") ## End(Not run)
Get all replies and replies on replies of a skeet.
get_replies(post_url, .token = NULL)
get_replies(post_url, .token = NULL)
post_url |
the URL of a skeet. |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame of skeets
## Not run: get_replies("https://bsky.app/profile/jbgruber.bsky.social/post/3kbi57u4sys2l") ## End(Not run)
## Not run: get_replies("https://bsky.app/profile/jbgruber.bsky.social/post/3kbi57u4sys2l") ## End(Not run)
A view of an actor's skeets.
get_skeets_authored_by( actor, limit = 25L, filter = NULL, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
get_skeets_authored_by( actor, limit = 25L, filter = NULL, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
actor |
user handle to retrieve feed for. |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
filter |
get only certain post/repost types. Possible values "posts_with_replies", "posts_no_replies", "posts_with_media", and "posts_and_author_threads". |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of posts
## Not run: feed <- get_skeets_authored_by("andrew.heiss.phd") ## End(Not run)
## Not run: feed <- get_skeets_authored_by("andrew.heiss.phd") ## End(Not run)
Retrieve all skeets in a thread (all replies to an original skeet by any
author). It does not matter if you use the original skeet or any reply as
post_url
.
get_thread(post_url, .token = NULL)
get_thread(post_url, .token = NULL)
post_url |
the URL of any skeet in a thread. |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame of skeets
## Not run: get_thread("https://bsky.app/profile/jbgruber.bsky.social/post/3kbi57u4sys2l") ## End(Not run)
## Not run: get_thread("https://bsky.app/profile/jbgruber.bsky.social/post/3kbi57u4sys2l") ## End(Not run)
Query profile of an actor
get_user_info(actor, parse = TRUE, .token = NULL)
get_user_info(actor, parse = TRUE, .token = NULL)
actor |
user handle(s) to get information for. |
parse |
Parse the results or return the original nested object sent by the server. |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of found actors.
## Not run: rstats_user <- search_user("rstats", limit = 2L) get_user_info(rstats_user$handle) ## End(Not run)
## Not run: rstats_user <- search_user("rstats", limit = 2L) get_user_info(rstats_user$handle) ## End(Not run)
Available lexicons for the AT Protocol (Authenticated Transfer Protocol)
list_lexicons
list_lexicons
list_lexicons
A list with all lexicons available for the AT protocols.
Name of the lexicon
path relative to https://github.com/bluesky-social/atproto/tree/main/lexicons
https://github.com/bluesky-social/atproto
Post a skeet
post( text, in_reply_to = NULL, quote = NULL, image = NULL, image_alt = NULL, created_at = Sys.time(), labels = NULL, langs = NULL, tags = NULL, preview_card = TRUE, verbose = NULL, .token = NULL ) post_skeet( text, in_reply_to = NULL, quote = NULL, image = NULL, image_alt = NULL, created_at = Sys.time(), labels = NULL, langs = NULL, tags = NULL, preview_card = TRUE, verbose = NULL, .token = NULL ) delete_skeet(post_url, verbose = NULL, .token = NULL) delete_post(post_url, verbose = NULL, .token = NULL)
post( text, in_reply_to = NULL, quote = NULL, image = NULL, image_alt = NULL, created_at = Sys.time(), labels = NULL, langs = NULL, tags = NULL, preview_card = TRUE, verbose = NULL, .token = NULL ) post_skeet( text, in_reply_to = NULL, quote = NULL, image = NULL, image_alt = NULL, created_at = Sys.time(), labels = NULL, langs = NULL, tags = NULL, preview_card = TRUE, verbose = NULL, .token = NULL ) delete_skeet(post_url, verbose = NULL, .token = NULL) delete_post(post_url, verbose = NULL, .token = NULL)
text |
Text to post |
in_reply_to |
URL or URI of a skeet this should reply to. |
quote |
URL or URI of a skeet this should quote. |
image |
path to an image to post. |
image_alt |
alt text for the image. |
created_at |
time stamp of the post. |
labels |
can be used to label a post, for example "!no-unauthenticated", "porn", "sexual", "nudity", or "graphic-media". |
langs |
indicates human language(s) (up to 3) of post's primary text content. |
tags |
additional hashtags, in addition to any included in post text and facets. |
preview_card |
display a preview card for links included in the text
(only if image is |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
post_url |
URL or URI of post to delete. |
list of the URI and CID of the post (invisible)
## Not run: post("Hello from #rstats with {atrrr}") ## End(Not run)
## Not run: post("Hello from #rstats with {atrrr}") ## End(Not run)
Post a thread
post_thread( texts, images = NULL, image_alts = NULL, thread_df = NULL, verbose = NULL, .token = NULL )
post_thread( texts, images = NULL, image_alts = NULL, thread_df = NULL, verbose = NULL, .token = NULL )
texts |
a vector of skeet (post) texts |
images |
paths to images to be included in each post |
image_alts |
alt texts for the images to be included in each post |
thread_df |
instead of defining texts, images and image_alts, you can also create a data frame with the information in columns of the same names. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
list of the URIs and CIDs of the posts (invisible)
## Not run: # post three messages in a thread thread <- post_thread(c("Post 1", "Post 2", "Post 3")) # delete the thread delete_post(thread$uri) ## End(Not run)
## Not run: # post three messages in a thread thread <- post_thread(c("Post 1", "Post 2", "Post 3")) # delete the thread delete_post(thread$uri) ## End(Not run)
Print a AT token
## S3 method for class 'bsky_token' print(x, ...)
## S3 method for class 'bsky_token' print(x, ...)
x |
An object of class |
... |
not used. |
No return value, called to print the token to screen
Search the feed named after a given query
search_feed( query, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
search_feed( query, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
query |
The term to be searched |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of posts
## Not run: search_feed("rstats") ## End(Not run)
## Not run: search_feed("rstats") ## End(Not run)
Search Posts
search_post(q, limit = 100L, parse = TRUE, verbose = NULL, .token = NULL) search_skeet(q, limit = 100L, parse = TRUE, verbose = NULL, .token = NULL)
search_post(q, limit = 100L, parse = TRUE, verbose = NULL, .token = NULL) search_skeet(q, limit = 100L, parse = TRUE, verbose = NULL, .token = NULL)
q |
search query. See Details. |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
The API docs claim that Lucene query syntax is supported (Boolean operators and brackets for complex queries). But only a small subset is actually implemented:
Whitespace is treated as implicit AND, so all words in a query must occur, but the word order and proximity are ignored.
Double quotes indicate exact phrases.
from:<handle>
will filter to results from that account.
-
excludes terms (does not seem to be working at the moment).
Note that matches can occur anywhere in the skeet, not just the text. For example, a term can be in the link preview, or alt text of an image.
a data frame (or nested list) of posts
## Not run: search_post("rstats") # finds post with the hashtag rstats AND the word Bluesky somewhere in the # skeet (ignoring capitalisaion) search_post("#rstats Bluesky") # search for the exact phrase "new #rstats package" search_post("\"new #rstats package\"") # Use single quotes so you do not need to escape double quotes search_post('"new #rstats package"') # only search for skeets from one user search_post("from:jbgruber.bsky.social #rstats") ## End(Not run)
## Not run: search_post("rstats") # finds post with the hashtag rstats AND the word Bluesky somewhere in the # skeet (ignoring capitalisaion) search_post("#rstats Bluesky") # search for the exact phrase "new #rstats package" search_post("\"new #rstats package\"") # Use single quotes so you do not need to escape double quotes search_post('"new #rstats package"') # only search for skeets from one user search_post("from:jbgruber.bsky.social #rstats") ## End(Not run)
Find users (profiles) matching search criteria.
search_user( query, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
search_user( query, limit = 25L, cursor = NULL, parse = TRUE, verbose = NULL, .token = NULL )
query |
The search query. Searches in user names and descriptions or exact matches in user handles (including the .bsky.social part). |
limit |
Maximum number of records to return. For queries with more than 100 results, pagination is used automatically (one request per 100 results). The function stops when the limit is reached, but you will usually get a few items more than requested. |
cursor |
Cursor for pagination (to pick up an old search). |
parse |
Parse the results or return the original nested object sent by the server. |
verbose |
Whether to print status messages to the Console
( |
.token |
If you manage your own tokens, you can supply it here. Usually
|
a data frame (or nested list) of found actors.
## Not run: search_user("benguinaudeau.bsky.social") search_user("Blog: favstats.eu") search_user("JBGruber") search_user("@UvA_ASCoR") search_user("rstats", limit = 1000L) ## End(Not run)
## Not run: search_user("benguinaudeau.bsky.social") search_user("Blog: favstats.eu") search_user("JBGruber") search_user("@UvA_ASCoR") search_user("rstats", limit = 1000L) ## End(Not run)
Take high quality screenshots of skeets
skeet_shot(x, file = NULL, ...)
skeet_shot(x, file = NULL, ...)
x |
a vector of URLs or URIs. |
file |
output file name. Defaults to the skeet id. |
... |
passed on to webshot. |
path to file
## Not run: df <- atrrr::search_post("rstats") skeet_shot(df$uri[1:2]) ## End(Not run)
## Not run: df <- atrrr::search_post("rstats") skeet_shot(df$uri[1:2]) ## End(Not run)