#' Start a compliance check
#'
#' @return twCompliance ID of the compliance job. Save this to check the jobs status and download the results.
#'
#' @param data A dataframe generated by `combine_status()`.
#'
#' @importFrom usethis ui_info ui_line
#' @export
start_compliance_check <- function(data) {
return_list <- list("tweets"=NULL, "users"=NULL, "data"=data, "checked_at"=lubridate::now())
var_list <- names(data)
if (!all(var_list %in% c("status_id", "user_id", "created_at", "account_created_at"))) {
usethis::ui_oops("Data must only contain any/all of {usethis::ui_field('status_id')}, {usethis::ui_field('user_id')}, {usethis::ui_field('created_at')}, {usethis::ui_field('account_created_at')}")
stop("Wrong format")
}
if (!any(c("status_id", "user_id") %in% var_list)) {
stop("Data has the wrong format, status_id and/or user_id are required")
}
if (all(c("created_at", "account_created_at") %in% var_list)) {
if (!lubridate::is.POSIXct(data$created_at) &
!lubridate::is.POSIXct(data$account_created_at)) {
usethis::ui_oops("The variables {usethis::ui_field('created_at')} and {usethis::ui_field('account_created_at')} must both be of type POSIXct.")
usethis::ui_info("Only {usethis::ui_field('status_id')} and {usethis::ui_field('user_id')} will be used.")
}
} else if ("created_at" %in% var_list) {
if (!lubridate::is.POSIXct(data$created_at)) {
usethis::ui_oops("The variable {usethis::ui_field('created_at')} must be of type POSIXct.")
usethis::ui_info("Only {usethis::ui_field('status_id')} and {usethis::ui_field('user_id')} will be used.")
}
} else if ("account_created_at" %in% var_list) {
if (!lubridate::is.POSIXct(data$account_created_at)) {
usethis::ui_oops("The variable {usethis::ui_field('account_created_at')} must be of type POSIXct.")
usethis::ui_info("Only {usethis::ui_field('status_id')} and {usethis::ui_field('user_id')} will be used.")
}
}
usethis::ui_info("Starting compliance check and uploading data (this might take a while)")
if ("status_id" %in% var_list) {
r <- httr::GET(
sprintf("https://api.twitter.com/2/compliance/jobs?type=%s", "tweets"),
httr::add_headers(
"Authorization" = paste0("Bearer ", get_bearer())
)
)
if ("in_progress" %in% (unlist(lapply(httr::content(r)$data, function(x){x[["status"]]})))) {
usethis::ui_oops("Cannot start a new job with type 'tweets', as there is an ongoing job with that type")
#list_compliance_jobs(type = "tweets")
stop("Check in progress")
}
return_list$tweets <- start_job(data$status_id, type = "tweets", verbose = FALSE)
}
if ("user_id" %in% var_list) {
r <- httr::GET(
sprintf("https://api.twitter.com/2/compliance/jobs?type=%s", "users"),
httr::add_headers(
"Authorization" = paste0("Bearer ", get_bearer())
)
)
if ("in_progress" %in% (unlist(lapply(httr::content(r)$data, function(x){x[["status"]]})))) {
usethis::ui_oops("Cannot start a new job with type 'users', as there is an ongoing job with that type")
#list_compliance_jobs(type = "users")
stop("Check in progress")
}
return_list$users <- start_job(data$user_id, type = "users", verbose = FALSE)
}
return_list$print_string <- gen_print(return_list)
success_msg <- c("Compliance check started successfully:")
if ("status_id" %in% names(return_list$data)) {
n_tweets <- format(length(unique(return_list$data$status_id)), big.mark = ",")
success_msg <- c(success_msg, "\n\t{usethis::ui_field('Tweets')}: {usethis::ui_value(n_tweets)}")
}
if ("user_id" %in% names(return_list$data)) {
n_users <- format(length(unique(return_list$data$user_id)), big.mark = ",")
success_msg <- c(success_msg, "\n\t{usethis::ui_field('Users')}: {usethis::ui_value(n_users)}")
}
usethis::ui_done(paste0(success_msg, collapse = ""))
return(structure(return_list, class = "twCompliance"))
}
#' Download a compliacnce check
#'
#' This function downloads a compliance check
#'
#' @return data.frame The downloaded and combinded compliance check
#'
#' @param job_id The object generated by `start_compliance_check()`.
#' @param return_raw bool Should a combinded output be returned or the raw API response?
#'
#' @importFrom usethis ui_info ui_line
#' @export
download_compliance_check <- function(
job_id,
return_raw = FALSE
) {
downloaded_jobs <- check_job(job_id, verbose = FALSE)
if (is.character(downloaded_jobs$tweets) & is.character(downloaded_jobs$users)) {
usethis::ui_info("Downloading jobs")
downloaded_jobs$users <- download_job(job_id$users)
downloaded_jobs$tweets <- download_job(job_id$tweets)
if (return_raw) {
return(downloaded_jobs)
}
combinded_data <- combine_jobs(job_id$data, downloaded_jobs$tweets, downloaded_jobs$users)
combinded_data$checked_at <- job_id$checked_at
return(combinded_data)
} else if (is.character(downloaded_jobs$tweets) & is.null(job_id$users)) {
usethis::ui_info("Downloading jobs")
downloaded_jobs$users <- NULL
downloaded_jobs$tweets <- download_job(job_id$tweets)
if (return_raw) {
return(downloaded_jobs)
}
combinded_data <- combine_jobs(job_id$data, downloaded_jobs$tweets, downloaded_jobs$users)
combinded_data$checked_at <- job_id$checked_at
return(combinded_data)
} else if (is.character(downloaded_jobs$users) & is.null(job_id$tweets)) {
usethis::ui_info("Downloading jobs")
downloaded_jobs$users <- download_job(job_id$users)
downloaded_jobs$tweets <- NULL
if (return_raw) {
return(downloaded_jobs)
}
combinded_data <- combine_jobs(job_id$data, downloaded_jobs$tweets, downloaded_jobs$users)
combinded_data$checked_at <- job_id$checked_at
return(combinded_data)
} else {
usethis::ui_info("Jobs are not ready yet\n\n")
if (!is.null(job_id$tweets)) {check_job(job_id$tweets)}
if (!is.null(job_id$users)) {check_job(job_id$users)}
}
}
#' Report deleted content
#'
#' This function generates a report of deleted content
#'
#' @return string ID of the compliance job. Save this to check the jobs status and download the results.
#'
#' @param df A dataframe generated by `combine_status()`.
#' @param plot If `TRUE` plot a report as well.
#' @param combine_plots If `TRUE` plots will be combined with `patchwork`, if `FALSE` a named list of plots will be returned.
#'
#' @importFrom usethis ui_info ui_line
#' @export
report_compliance <- function(df, plot = FALSE, combine_plots = TRUE) {
if ("status_id" %in% names(df)) {
cat(report_text(df, type = "tweets"))
if (plot == TRUE) {
if ("created_at" %in% names(df)) {
report_plot(df, type = "tweets", combine_plots = combine_plots)
} else {
usethis::ui_oops("Plots require {usethis::ui_field('created_at')} in data")
}
}
} else if ("user_id" %in% names(df)) {
cat(report_text(df, type = "users"))
if (plot == TRUE) {
if ("account_created_at" %in% names(df)) {
report_plot(df, type = "users", combine_plots = combine_plots)
} else {
usethis::ui_oops("Plots require {usethis::ui_field('account_created_at')} in data")
}
}
} else if (!all(c("status_id", "user_id") %in% names(df))) {
usethis::ui_oops("Wrong format ({usethis::ui_field('status_id')} or {usethis::ui_field('user_id')} are required)")
}
}
#' List all compliance jobs
#'
#' This function prints a list of all compliance jobs.
#'
#' @param bearer_token API bearer token.
#' @param type Type of the job. Either 'all' (default), 'tweets', or 'users'.
#' @param status The status of the job. Either 'all' (default), 'in_progress', or 'complete'.
#'
#' @export
list_compliance_jobs <- function(type = "all",
status = "all",
bearer_token = get_bearer()) {
if (!type %in% c("users", "tweets", "all")) {
stop("Wrong type")
}
if (!status %in% c("in_progress", "complete", "all")) {
stop("Wrong status")
}
if (type == "all") {
type <- c("tweets", "users")
}
for (ct in type) {
r <- httr::GET(
sprintf(
"https://api.twitter.com/2/compliance/jobs?type=%s",
ct
),
httr::add_headers("Authorization" = paste0("Bearer ", bearer_token))
)
jobs <- httr::content(r)$data
if (status != "all") {
jobs <- jobs[unlist(lapply(jobs, `[`, "status")) == status]
}
if (httr::status_code(r) == 200) {
usethis::ui_info(
"{length(jobs)} jobs(s) of type {usethis::ui_value(ct)} and status {usethis::ui_value(status)} found"
)
for (job in jobs) {
print_job(job)
}
}
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.