R/reddit_functions.R

Defines functions get_posts get_users search_reddit

Documented in get_posts get_users search_reddit

#' Generate an access token for the Reddit API
#'
#' @param scope The scope of what you want to access. Must be one of these:
#' identity, read, history, wikiread
#' @param useragent The useragent for the device accessing the API
#' @param username Username for the Reddit profile accessing the API. If left
#' empty, it will attempt to read from the environment. Can be set with
#' \code{Sys.setenv(REDDIT_API_USERNAME = "")}
#' @param password Password for the Reddit profile accessing the API. If left
#' empty, it will attempt to read from the environment. Can be set with
#' \code{Sys.setenv(REDDIT_API_PASSWORD = "")}
#' @param client_id The id of the app through which the API is accessed.If left
#' empty, it will attempt to read from the environment. Can be set with
#' \code{Sys.setenv(REDDIT_API_CLIENT_ID = "")}
#' @param client_secret The client secret of the app through which the API is
#' accessed. If left empty, it will attempt to read from the environment. Can be
#' set with \code{Sys.setenv(REDDIT_API_SECRET = "")}
#' @return A list containing the access token, the time until it expires, the
#' scope, the time it was generated and the useragent
#' @details Access tokens are recquired to acccess any of the endpoints of the
#' API. Access tokens are only valid for an hour.
#' It is recquired to define an App through which the API is being accessed.
#' Apps can be defined in the settings at this page
#' \url{https://www.reddit.com/prefs/apps/}. Client ID and Client Secret must be
#' taken from this page.
#' More info about accessing the API at \url{https://www.reddit.com/dev/api/}
#' @return A list containing the access token, its scope, the acces time and
#' the useragent.
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = useragent,
#'                         username = username,
#'                         password = password,
#'                         client_id = client_id,
#'                         client_secret = client_secret)
#' }
#' @export

get_token <- function (scope = c("identity", "read", "history", "wikiread"),
                       useragent,
                       username = NULL,
                       password = NULL,
                       client_id = NULL,
                       client_secret = NULL) {
  
  assertthat::assert_that(assertthat::is.string(scope),
                          assertthat::not_empty(scope),
                          nchar(scope) > 0,
                          scope %in% c("identity", "read", "history", "wikiread"),
                          msg = "Invalid scope")
  
  assertthat::assert_that(assertthat::is.string(useragent),
                          assertthat::not_empty(useragent),
                          nchar(useragent) > 0,
                          msg = "Please supply a useragent")
  
  if(is.null(username)) {username <- Sys.getenv("REDDIT_API_USERNAME")}
  if(is.null(password)){password <- Sys.getenv("REDDIT_API_PASSWORD")}
  if(is.null(client_id)){client_id <- Sys.getenv("REDDIT_API_CLIENT_ID")}
  if(is.null(client_secret)){client_secret <- Sys.getenv("REDDIT_API_CLIENT_SECRET")}
  
  check_credentials(username)
  check_credentials(password)
  check_credentials(client_id)
  check_credentials(client_secret)
  
  token <- httr::POST(url = "https://www.reddit.com/api/v1/access_token",
                      body = list(
                        grant_type = "password",
                        username = username,
                        password = password,
                        scope = scope),
                      encode = "form",
                      httr::authenticate(client_id, client_secret),
                      httr::user_agent(useragent)
  )
  
  httr::stop_for_status(token)
  
  acc_token <- httr::content(token)
  
  access_time <- Sys.time()
  
  acc_token <- c(acc_token,
                 access_time = access_time,
                 useragent = useragent)
  
  return (acc_token)
}

#' Get posts from a specified subreddit
#'
#' A maximum of 100 posts can be requested from a specified subreddit. The
#' timeframe and the sorting of the posts can be specified.
#'
#' @param subreddit The name of the subreddit from which posts are requested.
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"read"}.
#' @param sort The order in which the posts in the subreddit should be ordered
#' when accessing them. Possible values are:
#' \itemize{
#'   \item \code{new}: Sorts posts by the time when they were created
#'   \item \code{hot}: Sorts posts by posts currently on the frontpage of the 
#'   subreddit
#'   \item \code{controversial}: Posts with a higher number of up- and downvotes
#'   simultaneously.
#'   \item \code{random}:
#'   \item \code{rising}:
#'   \item \code{top}: Most upvoted posts in a certain timeframe. Timeframe can
#'   be specified with \code{time}.
#' }
#' @param limit The maximum number of posts to return. Must be a number between
#' 1 and 100.
#' @param time The timeframe for the \code{sort} order \code{controversial} and
#' \code{top}. Possible values are:
#' \itemize{
#'   \item \code{hour}
#'   \item \code{day}
#'   \item \code{week}
#'   \item \code{month}
#'   \item \code{year}
#'   \item \code{all} for posts from all time. The default value if 
#'   time is not specified.
#' }
#' @param before The fullname of a post serving as anchor in the request.
#' Posts before this post in the listing are returned.
#' @param after The fullname of a post serving as anchor in the request.
#' Posts after this post in the listing are returned.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#' @return The requested posts as a dataframe, json object or a list 
#' containing both.
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'                         
#' # 10 "hot" posts from the subreddit askreddit
#' posts <- get_posts(subreddit = "askreddit",
#'                    accesstoken = read_token,
#'                    sort = "hot", limit = 10)
#'
#' # The next set of posts can be retrieved with the argument "after"
#' posts_after <- get_posts(subreddit = "soccer",
#'                          accesstoken = read_token,
#'                          sort = "hot",
#'                          limit = 10,
#'                          after = after)
#' }
#' @export

get_posts <- function(subreddit,
                      accesstoken,
                      sort ="new",
                      limit=100,
                      time = c("all","hour", "day", "week", "month", "year"),
                      after = NULL,
                      before = NULL,
                      output = c("df","json", "all"),
                      verbose = FALSE,
                      retry = FALSE) {
  
  check_token(accesstoken, scope = "read")
  
  check_args(default_arg = "subreddit")
  
  output <- match.arg(output)

  time <- match.arg(time)
  
  link <- build_link(path_elements = paste0("r/", subreddit, "/", sort),
                     query_elements = paste0("limit=", limit, "&t=", time),
                     before, after)
  
  if(verbose == TRUE) print(paste("Getting posts from:",link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  posts <- parse_request(req, verbose, output, after_before = TRUE)
  
  return(posts)
}


#' Get submissions for a specified user
#'
#' Submissions are posts made by one user. Submissions can be requested for a
#' specific timeframe or sort order.
#'
#' @param user The username of the user for which submissions are requested.
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"history"}.
#' @param sort The order in which the submissions of the user should be ordered
#' when accessing them. Possible values are:
#' \itemize{
#'   \item \code{new}: Sorts posts by the time when they were created
#'   \item \code{hot}: Sorts posts by posts currently trending
#'   \item \code{controversial}: Sorts posts by number of upvotes and downvotes
#'   \item \code{top}: Most upvoted posts in a certain timeframe. Timeframe can
#'   be specified with \code{time}.
#' }
#' @param time The timeframe for the \code{sort} order \code{controversial} and
#' \code{top}. Possible values are:
#' \itemize{
#'   \item \code{hour}
#'   \item \code{day}
#'   \item \code{week}
#'   \item \code{month}
#'   \item \code{year}
#'   \item \code{all} for posts from all time. The default value if 
#'   time is not specified.
#' }
#' @param limit The maximum number of submissions to return. Must be a number
#' between 1 and 100.
#' @param before The fullname of a post serving as anchor in the request.
#' Posts before this post in the listing are returned.
#' @param after The fullname of a post serving as anchor in the request.
#' Posts after this post in the listing are returned.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#' @return Posts for a specified user as a dataframe, json object or a list 
#' containing both.
#' @export
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @seealso \code{\link{get_user}}
#' @examples
#' \dontrun{
#' history_token <- get_token(scope = "history",
#'                            useragent = useragent,
#'                            username = username,
#'                            password = password,
#'                            client_id = client_id,
#'                            client_secret = client_secret)
#'
#'submissions <- get_submissions(user = "_KeanuReeves",
#'                               accesstoken = history_token,
#'                               sort = "top", time = "all",
#'                               limit = 10)
#' }


get_submissions <- function (user,
                             accesstoken,
                             sort = c("new", "hot", "controversial", "top"),
                             time = c("all","hour", "day", "week", "month", "year"),
                             limit = 100,
                             before = NULL,
                             after = NULL,
                             output = c("df","json", "all"),
                             verbose = FALSE,
                             retry = FALSE) {
  
  check_token(accesstoken, scope = "history")
  
  check_args(default_arg = "user")
  
  output <- match.arg(output)
  
  time <- match.arg(time)
  
  sort <- match.arg(sort)
  
  link <- build_link(path_elements = paste0("user/", user, "/submitted"),
                     query_elements = paste0("limit=", limit,
                                             "&sort=", sort,
                                             "&t=", time),
                     before = before, after = after)
  
  if(verbose == TRUE) print(paste("Getting submissions from:", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  submissions <- parse_request(req,  verbose, output, after_before = TRUE)
  
  return(submissions)
}



#' Get comments from a specified subreddit
#'
#' @param subreddit The name of the subreddit from which comments are requested
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"read"}.
#' @param limit The maximum number of comments to return. Must be a number
#' between 1 and 100.
#' @param before The fullname of a comment serving as anchor in the request.
#' Comments before this comment in the listing are returned.
#' @param after The fullname of a comment serving as anchor in the request.
#' Comments after this comment in the listing are returned.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#' @return New comments from a specified subreddit as a dataframe, json 
#' object or a list containing both.
#' @export
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'                         
#' #10 new comments from subreddit askreddit
#' comms <- get_comments(subreddit = "askreddit",
#'                       accesstoken = read_token,
#'                       limit = 10)
#' }

get_comments <- function (subreddit,
                          accesstoken,
                          limit=100,
                          before=NULL,
                          after=NULL,
                          output = c("df","json", "all"),
                          verbose = FALSE,
                          retry = FALSE) {
  
  check_token(accesstoken, scope = "read")
  
  check_args(default_arg = "subreddit")
  
  output <- match.arg(output)
  
  link <- build_link(path_elements = paste0("r/", subreddit, "/comments"),
                     query_elements = paste0("limit=", limit),
                     before = before, after = after)
  
  if(verbose == TRUE) print(paste("Getting comments from:",link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  comments <- parse_request(req, verbose, output, after_before = TRUE)
  
  return(comments)
}


#' Get comments from a specified user
#'
#' This returns comments made by one user. Comments can be requested for a
#' specific timeframe or sort order.
#'
#' @param user The username of the user for which comments are requested.
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"history"}.
#' @param sort The order in which the submissions of the user should be ordered
#' when accessing them. Possible values are:
#' \itemize{
#'   \item \code{new}: Returns newest comments
#'   \item \code{hot}: Returns highly upvoted comments currently
#'   \item \code{controversial}: Returns comments that received a lot of upvotes
#'   and downvotes
#'   \item \code{top}: Returns most upvoted comments in a certain timeframe.
#'   Timeframe can be specified with \code{time}.
#' }
#' @param time The timeframe for the \code{sort} order \code{controversial} and
#' \code{top}. Possible values are:
#' \itemize{
#'   \item \code{hour}
#'   \item \code{day}
#'   \item \code{week}
#'   \item \code{month}
#'   \item \code{year}
#'   \item \code{all time}
#' }
#' @param limit The maximum number of user comments to return. Must be a number
#' between 1 and 100.
#' @param before The fullname of a comment serving as anchor in the request.
#' Comments before this comment in the listing are returned.
#' @param after The fullname of a comment serving as anchor in the request.
#' Comments after this comment in the listing are returned.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#' @return Comments for the specified user as a dataframe, json  object or a 
#' list containing both.
#' @export
#' @seealso \code{\link{get_user}}
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @examples
#' \dontrun{
#' history_token <- get_token(scope = "history",
#'                            useragent = my_useragent,
#'                            username = my_username,
#'                            password = my_password,
#'                            client_id = my_client_id,
#'                            client_secret = my_client_secret)
#'
#' #Get 10 comments made by Keanu Reeves
#' keanu_comments <- get_user_comments(user = "_KeanuReeves",
#'                                     accesstoken = history_token,
#'                                     sort = "top", time = "all",
#'                                     limit = 10)
#' }


get_user_comments <- function (user,
                               accesstoken,
                               sort = c("new", "hot", "controversial", "top"),
                               time = c("all","hour", "day", "week", "month", "year"),
                               limit = 100,
                               after=NULL,
                               before=NULL,
                               output = c("df","json", "all"),
                               verbose = FALSE,
                               retry = FALSE) {
  
  check_token(accesstoken, scope = "history")
  
  check_args(default_arg = "user")
  
  output <- match.arg(output)
  
  time <- match.arg(time)
  
  sort <- match.arg(sort)
  
  link <- build_link(path_elements = paste0("user/", user,"/comments"),
                     query_elements = paste0("limit=",limit,
                                             "&sort=", sort,
                                             "&t=", time),
                     before, after)
  
  if(verbose == TRUE) print(paste("Getting comments from:", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  user_comments <- parse_request(req, verbose, output, after_before = TRUE)
  
  return(user_comments)
}


#' Get posts and comments from a specified user
#'
#' This function returns posts and/or comments made by one user. They can be
#' requested for a specific timeframe or sort order.
#'
#' @param user The username of the user for which posts and comments are
#' requested.
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"history"}.
#' @param type The type of content that is requested for the user. Possible
#' valuesare:
#' \itemize{
#'   \item \code{overview} Contains posts and comments.
#'   \item \code{comments} Only comments.
#'   \item \code{submitted} Only posts.
#'   \item \code{gilded} Posts and comments that have received awards.
#'   }
#' @param sort The order in which the posts or comments of the user should be
#' ordered when accessing them. Possible values are:
#' \itemize{
#'   \item \code{new}: Returns newest comments or posts
#'   \item \code{hot}: Returns highly upvoted comments or posts currently
#'   \item \code{controversial}: Returns comments or posts that received a lot
#'   of upvotes and downvotes in a certain imeframe.Timeframe can be specified
#'   with \code{time}.
#'   \item \code{top}: Returns most upvoted comments posts in a certain
#'   timeframe.Timeframe can be specified with \code{time}.
#' }
#' @param time The timeframe for the \code{sort} order \code{"controversial"}
#' and \code{"top"}. Possible values are:
#' \itemize{
#'   \item \code{hour}
#'   \item \code{day}
#'   \item \code{week}
#'   \item \code{month}
#'   \item \code{year}
#'   \item \code{all} for posts or comments from all time. The default value if 
#'   time is not specified.
#' }
#' @param limit The maximum number of items to return. Must be a number between
#' 1 and 100.
#' @param before The fullname of an item serving as anchor in the
#' request. Items before this item in the listing are returned.
#' @param after The fullname of an item serving as anchor in the request.
#' Items after this item in the listing are returned.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#' @return Posts, comments or both for the specified user as a dataframe, json 
#' object or a list containing both.
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @seealso \code{\link{get_user_comments}} and \code{\link{get_submissions}}
#' @export
#' @examples
#' \dontrun{
#' history_token <- get_token(scope = "history",
#'                            useragent = my_useragent,
#'                            username = my_username,
#'                            password = my_password,
#'                            client_id = my_client_id,
#'                            client_secret = my_client_secret)
#'
#' # overview returns posts and comments
#' overview <- get_user(user = "_KeanuReeves",
#'                      type = "overview",
#'                      accesstoken = history_token,
#'                      sort = "top", time = "all",
#'                      limit = 10)
#'
#' # type = "comments" returns only comments
#' user_comments <- get_user(user = "_KeanuReeves",
#'                           type = "comments",
#'                           accesstoken = history_token,
#'                           sort = "top", time = "all",
#'                           limit = 10)
#'
#' # type = "submitted" returns only posts
#' user_comments <- get_user(user = "_KeanuReeves",
#'                           type = "submitted",
#'                           accesstoken = history_token,
#'                           sort = "top", time = "all",
#'                           limit = 10)
#'
#'#
#'gilded <- get_user(user = "_KeanuReeves",
#'                   type = "gilded",
#'                   accesstoken = history_token,
#'                   sort = "hot",
#'                   time = "all",
#'                   limit = 10)
#' }


get_user <- function (user,
                      accesstoken,
                      type = c("overview", "comments", "submitted", "gilded"),
                      sort = c("new", "hot", "controversial", "top"),
                      time = c("all","hour", "day", "week", "month", "year"),
                      limit = 100,
                      before=NULL,
                      after=NULL,
                      output = c("df","json", "all"),
                      verbose = FALSE,
                      retry = FALSE) {
  
  check_token(accesstoken, scope = "history")
  
  check_args(default_arg = "user")
  
  output <- match.arg(output)
  type <- match.arg(type)
  time <- match.arg(time)
  sort <- match.arg(sort)
  
  link <- build_link(path_elements = paste0("user/", user,"/", type),
                     query_elements = paste0("limit=", limit, 
                                             "&sort=", sort,
                                             "&t=", time),
                     before, after)
  
  if(verbose == TRUE) print(paste("Getting user data from:", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  user <- parse_request(req, verbose, output, after_before = TRUE)
  
  return(user)
}


#' Get basic information about the account of a specified user
#'
#' @param user Username of the Reddit user that is requested.
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"read"}.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#' @return Information about a specified user as a dataframe, json object or a 
#' list containing both.
#' @export
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'                         
#' user_info <- get_user_info(user = "_KeanuReeves",
#'                            accesstoken = read_token)
#' }


get_user_info <- function (user,
                           accesstoken,
                           output = c("df","json", "all"),
                           verbose = FALSE,
                           retry = FALSE) {
  
  check_token(accesstoken, scope = "read")
  
  check_args(default_arg = "user")
  
  output <- match.arg(output)
  
  link <- build_link(path_elements = paste0("user/", user, "/about"))
  
  if(verbose == TRUE) print(paste("Getting user info from: ", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  user_info <- parse_request(req,
                             verbose, 
                             output, 
                             after_before = FALSE)
  
  return(user_info)
}



#' Get basic information for a specified subreddit.
#'
#' @param subreddit Name of the subreddit for which info is requested.
#' @param type Which info is requested. Possible values are \code{info} for
#' information about the subreddit from the sidebar, \code{moderators} for
#' the moderators of the subreddit and \code{rules} for the rules of the
#' subreddit.
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"read"}.
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#'
#' @return Basic information about a subreddit from the
#' sidebar or the moderators or the rules of the subreddit as a dataframe, json 
#' object or a list containing both.
#' @export
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'
#'#Get sidebar for subreddit "soccer"
#' sub_info <- get_subreddit_info(subreddit = "soccer",
#'                                type = "info",
#'                                accesstoken = read_token)
#'
#'#Get moderators for subreddit "soccer"
#'moderators <- get_subreddit_info(subreddit = "soccer",
#'                                 type = "moderators",
#'                                 accesstoken = read_token)
#'}

get_subreddit_info <- function (subreddit,
                                type = c("info", "moderators", "rules"),
                                accesstoken,
                                output = c("df","json", "all"),
                                verbose = FALSE,
                                retry = FALSE) {
  
  check_token(accesstoken, scope = "read")
  
  check_args(default_arg = "subreddit")
  
  output <- match.arg(output)
  
  if(type == "info") {
    
    link <- build_link(path_elements = paste0("r/", subreddit, "/about"))
    
  } else if(type == "moderators"|type == "rules"){
    
    link <- build_link(path_elements = paste0("r/", subreddit, "/about/", type))
    
  } else stop("Result has to be 'info', 'moderators' or 'rules'.")
  
  if(verbose == TRUE) print(paste("Getting subreddit info from:", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  sub_info <- parse_request(req,
                            verbose,
                            output,
                            after_before = FALSE)
  return(sub_info)
}


#' Get wiki pages for a specified subreddit.
#'
#' @param subreddit Name of the subreddit for which wiki pages are requested.
#' @param page Name of the requested page. If \code{"page"} is \code{"all"},
#' all wiki pages for the subreddit are returned.
#' @param accesstoken The access token required to access the endpoint. Scope of
#' the access token must be \code{"wikiread"}.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#'
#' @return The text of the wiki page and all revisions as a dataframe, json 
#' object or a list containing both.
#' If  \code{"page"} is \code{"all"}, the names of all wiki pages as a dataframe, 
#' json object or a list containing both.
#' @export
#'
#' @seealso \code{\link{get_subreddit_info}}
#' @details More info at \url{https://www.reddit.com/dev/api/} and 
#' \url{https://www.reddit.com/wiki/wiki}
#' @examples
#' \dontrun{
#' wiki_token <- get_token(scope = "wikiread",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'
#'#All wiki pages of a subreddit
#'soccer_wiki <- get_wiki(subreddit = "soccer",
#'                        page = "all",
#'                        accesstoken = wiki_token)
#'
#'#Access a specific wiki page
#'soccer_wiki_page <- get_wiki(subreddit = "soccer",
#'                             page = soccer_wiki[1,1],
#'                             accesstoken = wiki_token)
#'}

get_wiki <- function (subreddit,
                      page = "all",
                      accesstoken,
                      output = c("df","json", "all"),
                      verbose = FALSE,
                      retry = FALSE) {
  
  check_token(accesstoken, scope = "wikiread")
  
  check_args(default_arg = "subreddit")
  
  output <- match.arg(output)
  
  if(page == "all"){
    link <- build_link(path_elements = paste0("r/", subreddit, "/wiki/pages"),
                       query_elements = NULL, before = NULL, after = NULL)
  } else{
    link <- build_link(path_elements = paste0("r/", subreddit, "/wiki/", page),
                       query_elements = NULL, before = NULL, after = NULL)
  }
  
  if(verbose == TRUE) print(paste("Getting wiki from", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  wiki <- parse_request(req,
                        verbose,
                        output, 
                        after_before = FALSE)
  
  return(wiki)
}



#' Get trophies for a specified user
#'
#' @param user The username of the user
#' @param accesstoken The access token required to access the endpoint. Scope of
#' the acces token must be \code{"read"}.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#'
#' @return All trophies a specified user has received as a dataframe, json 
#' object or a list containing both.
#' @export
#' @seealso \code{\link{get_user_info}}
#' @details More info at \url{https://www.reddit.com/dev/api/} and 
#' \url{https://www.reddit.com/wiki/trophies}
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'                         
#' trophies <- get_trophies(user = "_KeanuReeves",accesstoken = read_token)
#' }

get_trophies <- function (user,
                          accesstoken,
                          output = c("df","json", "all"),
                          verbose = FALSE,
                          retry = FALSE) {
  
  check_token(accesstoken, scope = "read")
  
  check_args(default_arg = "user")
  
  output <- match.arg(output)
  
  link <- build_link(path_elements = paste0("api/v1/user/", user,
                                            "/trophies"), 
                     query_elements = NULL, before = NULL, after = NULL)
  
  if(verbose == TRUE) print(paste("Getting trophies from:", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  trophies <- parse_request(req,
                            verbose,
                            output, 
                            after_before = FALSE)
  
  return(trophies)
}



#' Get a dataframe of subreddits
#'
#' Subreddits can be sorted by creation date or popularity. Also
#' allows searching for subreddits with search queries.
#'
#' @param type The type of list that is requested. Possible values are:
#' \itemize{
#'   \item \code{popular} Subreddits that are popular right now
#'   \item \code{new} Newly created subreddits
#'   \item \code{default} Default subreddits that users are subscribed to when
#'   they sign up for reddit.
#'    \item \code{search} Search for subreddits with a query.
#'   }
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"read"}.
#' @param query Search terms for type \code{search}. Must be less than 512
#' characters.
#' @param sort The order in which results from type \code{search} should be
#' sorted. Possible values are \code{"relevance"} and \code{"activity"}.
#' @param limit The maximum number of subreddits to return. Must be a number
#' between 1 and 100.
#' @param before The fullname of an item serving as anchor in the
#' request. Items before this item in the listing are returned.
#' @param after The fullname of an item serving as anchor in the request.
#' Items after this item in the listing are returned.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#' @return  New or popular subreddits as a dataframe, json object or a list 
#' containing both.
#' @export
#' @details More info at \url{https://www.reddit.com/dev/api/}
#'@examples
#'\dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'                         
#'#type = "popular" will show subreddits that are popular right now
#'popular_subs <- get_subreddits(type = "popular",
#'                               limit = 10,
#'                               accesstoken = read_token)
#'
#'#Searches for subreddits can be performed with type "search"
#'search_subs <- get_subreddits(type = "search",
#'                              accesstoken = read_token,
#'                              limit = 10,
#'                              query = "soccer",
#'                              sort = "activity")
#'}

get_subreddits <- function (type = c("popular", "new", "default", "search"),
                            accesstoken,
                            query = NULL,
                            sort = c("relevance", "activity"),
                            limit = 100,
                            after = NULL,
                            before = NULL,
                            output = c("df","json", "all"),
                            verbose = FALSE,
                            retry = FALSE) {
  
  check_token(accesstoken, scope = "read")
  
  check_args(default_arg = NULL)
  
  output <- match.arg(output)
  
  if(!type %in% c("popular", "new", "default", "search"))
    stop("type has to be one of these: popular, new, default", "search")
  
  if(type == "search") assertthat::assert_that(!is.null(query),
                                               msg = "No query specified for type search")
  
  link <- build_link(path_elements = paste0("subreddits/", type),
                     query_elements = paste0("limit=",limit,  "&q=", query,
                                             "&sort=", sort),
                     before = before, after = after)
  
  if(verbose == TRUE) print(paste("Getting subreddits from:", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  subreddits <- parse_request(req,
                              verbose,
                              output,
                              after_before = TRUE)
  
  return(subreddits)
}




#' Get user accounts
#'
#' Searches for popular or new users and returns them as a dataframe.
#'
#' @param type The type of users that is requested. Possible values are:
#' \itemize{
#'   \item \code{popular} User accounts that are popular right now
#'   \item \code{new} Newly created user accounts
#'   }
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"read"}.
#' @param limit The maximum number of users to return. Must be a number
#' between 1 and 100.
#' @param before The fullname of an item serving as anchor in the
#' request. Items before this item in the listing are returned.
#' @param after The fullname of an item serving as anchor in the request.
#' Items after this item in the listing are returned.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#' @return New or popular users as a dataframe, json object or a list 
#' containing both.
#' @export
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'                         
#' #Find popular users
#' popular_users <- get_users(type = "popular",
#'                            accesstoken = read_token,
#'                            limit = 10)
#'#Find new user accounts
#'new_users <- get_users(type = "new",
#'                       accesstoken = read_token,
#'                       limit = 100)
#'}

get_users <- function(type = c("popular", "new"),
                      accesstoken,
                      limit = 100,
                      after = NULL,
                      before = NULL,
                      output = c("df","json", "all"),
                      verbose = FALSE,
                      retry = FALSE) {
  
  check_token(accesstoken, scope = "read")
  
  check_args()
  
  output <- match.arg(output)
  
  if(!type %in% c("popular", "new"))
    stop("type has to be one of these: popular, new")
  
  link <- build_link(path_elements = paste0("users/", type),
                     query_elements = paste0("limit=",limit),
                     before, after)
  
  if(verbose == TRUE) print(paste("Getting users from: ", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  users <- parse_request(req,
                         verbose,
                         output,
                         after_before = TRUE)
  
  return(users)
}



#' Search for items based on a query
#'
#' Searches can be confined to one subreddit or conducted in all of reddit.
#'
#' @param query The search query. Maximum length of the query is 512 characters.
#' @param subreddit The name of the subreddit in which the search should be
#' conducted. If it is NULL, the search will be conducted in all subreddits.
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"read"}.
#' @param sort The order in which the search results should be ordered
#' when accessing them. Possible values are:
#' \itemize{
#'   \item \code{new}: Sorts search results by the time when they were created
#'   \item \code{hot}: Sorts search results currently trending
#'   \item \code{relevance}:
#'   \item \code{comments}:
#'   \item \code{top}: Most upvoted search results in a certain timeframe.
#'   Timeframe can be specified with \code{time}.
#' }
#' @param limit The maximum number of search results to return. Must be a number
#' between 1 and 100.
#' @param time The timeframe in which the search results were created. Possible
#' values are:
#' \itemize{
#'   \item \code{hour}
#'   \item \code{day}
#'   \item \code{week}
#'   \item \code{month}
#'   \item \code{year}
#'   \item \code{all} for search results from all time. The default value if 
#'   time is not specified.
#' }
#' @param type The type of item to return. Must be \code{"link"} for posts, 
#' \code{"user"} for "users or \code{"sr"} for subreddits. If it is NULL, it 
#' will return posts.
#' @param before The fullname of a search result serving as anchor in the
#' request. Search results before this post in the listing are returned.
#' @param after The fullname of a search result serving as anchor in the
#' request. Search results after this post in the listing are returned.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#'
#' @return Posts matching the search query as a dataframe, json object or a list
#' containing both.
#'
#' @details A '+' has to be put between multiple search terms in the query.
#' Information on how to build advanced search queries can be found at
#' this link: \url{https://www.reddit.com/wiki/search}
#' @export
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'                         
#' #Search for posts in a single subreddit
#' search_results_movies <- search_reddit(subreddit = "movies",
#'                                 accesstoken = read_token,
#'                                 query = "Keanu+Reeves",
#'                                 sort = "relevance",
#'                                 limit = 10,
#'                                 time = "year")
#'
#'# Search for posts in all of reddit
#'search_results_reddit <- search_reddit(subreddit = NULL,
#'                                       accesstoken = read_token,
#'                                       query = "Keanu+Reeves",
#'                                       sort = "relevance",
#'                                       limit = 10)
#' }

search_reddit <- function(query,
                          accesstoken,
                          subreddit=NULL,
                          sort ="new",
                          limit=100,
                          time = c("all","hour", "day", "week", "month", "year"),
                          type = c("link", "user", "sr"),
                          after=NULL,
                          before=NULL,
                          output = c("df","json", "all"),
                          verbose = FALSE,
                          retry = FALSE) {
  
  check_token(accesstoken, scope = "read")
  
  check_args(default_arg = "query")
  
  output <- match.arg(output)
  
  time <- match.arg(time)
  
  if(!is.null(subreddit)){search_path <- paste0("r/", subreddit, "/search")}
  else{search_path <- paste0("search")}
  
  link <- build_link(path_elements = search_path,
                     query_elements = paste0("q=",query, "&sort=", sort,
                                             "&limit=", limit, "&t=", time,
                                             "&type=", type,
                                             "&restrict_sr=on"),
                     before, after)
  
  if(verbose == TRUE) print(paste("Getting search results from: ", link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  search_results <- parse_request(req,
                                  verbose,
                                  output,
                                  after_before = TRUE)
  
  return(search_results)
}

#' Get a comment or post based on its unique id
#'
#' @param subreddit The subreddit of the thing
#' @param id The unique id of the requested thing. Reddit IDs are in base 36.
#' @param type What type of thing the id is. Must be \code{comment} or 
#' \code{post}.
#' @param accesstoken The accesstoken required to access the endpoint. Scope
#' must be \code{"read"}.
#' @param output What the function should return. Choose \code{json} for an 
#' unparsed json object, \code{df} for a parsed object in form of a dataframe, 
#' and \code{all} for a list containg the json object, a dataframe, and the 
#' before and after anchors (if those exist for the endpoint).
#' @param verbose A logical flag whether information about the data extraction
#' should be printed to the console.
#' @param retry A logical flag whether a failed api request should be retried.
#' Requests will be tried up to three times with varying time intervals between
#' requests.
#'
#' @return The requested thing as a dataframe, json object or a list containing 
#' both.
#' @export
#' @details More info at \url{https://www.reddit.com/dev/api/}
#' @examples
#' \dontrun{
#' read_token <- get_token(scope = "read",
#'                         useragent = my_useragent,
#'                         username = my_username,
#'                         password = my_password,
#'                         client_id = my_client_id,
#'                         client_secret = my_client_secret)
#'                         
#' 
#' comm <- get_comments(subreddit = "askreddit",
#'                       accesstoken = read_token,
#'                       output = "df",
#'                       limit = 1)
#'
#' #Look up the post this comment was made to
#' parent_post <- get_thing(subreddit = "askreddit",
#'                          id = comm$parent_id,
#'                          item_type = "post",
#'                          accesstoken = read_token)
#' }

get_thing <- function (subreddit,
                      id,
                      type = c("comment", "post"),
                      accesstoken = NULL,
                      output = c("df","json", "all"),
                      verbose = FALSE,
                      retry = FALSE) {
  
  
  check_token(accesstoken, scope = "read")
  
  check_args(default_arg = "id")
  
  output <- match.arg(output)
  
  type <- match.arg(type)
  
  if(grepl("^t[1-9]{1}_", id)){
    fullname <- id
  }else{
    fullname <- ifelse(type == "comment", paste0("t1_", id),
                       paste0("t3_", id)) 
  }
  
  link <- build_link(path_elements = paste0("r/", subreddit, "/api/info"),
                     query_elements = paste0("id=", fullname))
  
  if(verbose == TRUE) print(paste("Getting items from:",link))
  
  req <- get_reddit(accesstoken, link, verbose, retry)
  
  item <- parse_request(req, verbose, output, after_before = FALSE)
  
  return(item)
}
jfeldhege/redditoR documentation built on April 2, 2020, 9:42 p.m.