R/civicfeed.R

Defines functions .add_key_header .get_key .get_content .build_url .build_endpoint .force_row_tibble .force_tibble get_legislator get_legislators get_bill_details get_bills get_meta_state get_meta set_civicfeed_key

Documented in get_bill_details get_bills get_legislator get_legislators get_meta get_meta_state set_civicfeed_key

#' Setup CivicFeed
#' 
#' Setup your CivicFeed session, all subsequent calls will use this API key.
#'
#' @param key Your API key from your CivicFeed dashboard: \url{https://developers.civicfeed.com}.
#'
#' @note You can set the \code{CIVICFEED_API_KEY} in your \code{.Renviron} instead.
#'
#' @examples
#' \dontrun{set_civicfeed_key("XxXXxXXxxxXx")}
#' 
#' @export
set_civicfeed_key <- function(key) {
  if(missing(key))
    stop("Missing key", call. = FALSE)
  Sys.setenv("CIVICFEED_API_KEY" = key)
}

#' Metadata
#' 
#' Returns metadata on legislation by state.
#' 
#' @param state Two letter abbreviation of the state.
#' 
#' @section Functions:
#' \itemize{
#'  \item{\code{get_meta} This function returns a list of all states with data available and basic metadata about their status.} 
#'  \item{\code{get_meta_state} This function returns detailed metadata for a particular state.} 
#' }
#' 
#' @examples
#' \dontrun{
#' (states <- get_meta())
#' get_meta_state("dc")  
#' }
#' 
#' @name civicfeed-metadata
#' @export
get_meta <- function(){
  url <- .build_url("metadata")
  content <- .get_content(url)
  .force_tibble(content)
}

#' @rdname civicfeed-metadata
#' @export
get_meta_state <- function(state){
  if(missing(state))
    stop("Missing `state`", call. = FALSE)
  url <- .build_url(c("metadata", state))
  content <- .get_content(url)
  .force_row_tibble(content)
}

#' Bills
#' 
#' Returns information and details on bills.
#' 
#' @param state Returns bills matching the given state abbreviation.
#' @param session Return bills matching session.
#' @param chamber Returns bills matching the given state abbreviation, valid values are 
#' \code{upper}, or \code{lower}.
#' @param bill_id Returns bills with the given \code{bill_id}.
#' @param q Return bills match the full text query.
#' @param search_window Time window to be searched through, valid values are 
#' \code{all}, \code{term}, \code{session}, \code{sessionYear} (a specific year).
#' @param updated_since Returns bills updated since this date.
#' @param sort Sort order of results, \code{first}, \code{last}, \code{updated_at}, \code{created_at}.
#' 
#' @section Functions:
#' \itemize{
#'  \item{\code{get_bills} This function allows you to search bills by (almost) any of their attributes, or full text.} 
#'  \item{\code{get_bill_details} This function returns the full detail for bill, including any actions, votes, etc.} 
#' }
#' 
#' @examples
#' \dontrun{
#' bills <- get_bills(state = "dc") 
#' details <- get_bill_details(bills$state[1], bills$session[1], bills$bill_id[1])
#' }
#' 
#' @name civicfeed-bills
#' @export
get_bills <- function(state = NULL, chamber = NULL, bill_id = NULL, q = NULL, 
  search_window = NULL, updated_since = NULL, sort = NULL, pages = 1){

  results <- tibble::tibble()
  p <- 1
  while(p <= pages){
    url <- .build_url("bills", 
      state = state, chamber = chamber, 
      bill_id = bill_id, q = q, search_window = search_window, updated_since = updated_since, 
      sort = sort, page = p)
    content <- .get_content(url)
    content_df <- .force_tibble(content)
    results <- dplyr::bind_rows(results, content_df)
    p <- p + 1
  }
  return(results)
}

#' @name civicfeed-bills
#' @export
get_bill_details <- function(state, session, bill_id){
  if(missing(state) || missing(session) || missing(bill_id))
    stop("Missing `state`, `session`, or `bill_id`", call. = FALSE)
  url <- .build_url(c("bills", state, session, bill_id))
  content <- .get_content(url)
  .force_row_tibble(content)
}

#' Legislators
#' 
#' Returns data on legislators.
#' 
#' @param state Returns bills matching the given state abbreviation.
#' @param district Returns legislators from the given district.
#' @param chamber Returns bills matching the given state abbreviation, valid values are 
#' \code{upper}, or \code{lower}.
#' @param legislator_id A legislator id, as returned by \code{\link{get_legislators}}.
#' 
#' @section Functions:
#' \itemize{
#'  \item{\code{get_legislators} This function returns a list of legislators.} 
#'  \item{\code{get_legislator} This function returns details for a legislator, including all roles.} 
#' }
#' 
#' @examples
#' \dontrun{
#' (legislators <- get_legislators())
#' get_legislator(legislators$legislator_id[1])  
#' }
#' 
#' @name civicfeed-legislators
#' @export
get_legislators <- function(state = NULL, chamber = NULL, district = NULL){
  url <- .build_url("legislators", state = state, chamber = chamber, district = district)
  content <- .get_content(url)
  .force_tibble(content)
}

#' @rdname civicfeed-legislators
#' @export
get_legislator <- function(legislator_id){
  if(missing(legislator_id))
    stop("Missing `legislator_id`", call. = FALSE)
  url <- .build_url(c("legislators", legislator_id))
  content <- .get_content(url)
  .force_row_tibble(content)
}

CIVICFEED_BASE_URL <- "https://api-beta.civicfeed.com/"
CIVICFEED_BASE_PATH <- "legislation"

.force_tibble <- function(content){
  content %>% 
    purrr::map_dfr(function(item){
      .force_row_tibble(item)
    })
}

.force_row_tibble <- function(item){
  item <- purrr::map(item, function(row){
    if(length(row) > 1) row <- list(row)
    if(length(row) == 0) row <- NA
    return(row)
  })
  tibble::as_tibble(item)
}

.build_endpoint <- function(path){
  c(CIVICFEED_BASE_PATH, path)
}

.build_url <- function(path, ...){
  url <- httr::parse_url(CIVICFEED_BASE_URL)
  url$path <- .build_endpoint(path)
  url$query <- list(...)
  httr::build_url(url)
}

.get_content <- function(url){
  response <- httr::GET(url, .add_key_header())
  httr::stop_for_status(response)
  httr::content(response)
}

.get_key <- function(){
  key <- Sys.getenv("CIVICFEED_API_KEY")
  if(nchar(key) == "")
    stop(missing(key))
  return(key)
}

.add_key_header <- function(){
  httr::add_headers(`x-api-key` = .get_key())
}
abresler/govtrackR documentation built on July 11, 2020, 12:30 a.m.