From 0b51cdc4b8d316a6684045c67849d2a39c4f10a4 Mon Sep 17 00:00:00 2001 From: laijasmine Date: Wed, 12 May 2021 14:01:48 -0700 Subject: [PATCH 1/6] add instructions for Slack OAUTH token --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c663a5..dde914d 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Every 24 hours the bot queries NSF's award [API](https://www.research.gov/common DATABASE_PATH # Path to the database of awards and correspondences LASTRUN_PATH=LASTRUN # Determines where the bot stores its state SLACK_WEBHOOK_URL="{URL}" # Your Slack webhook URL + SLACK_OAUTH_TOKEN="TOKEN" # Slack OAUTH token (see your bot admin for access) RT_URL="https://example.com/rt" # The URL of your RT install RT_USER="your_rt_user" # Your RT username RT_PASS="your_rt_password" # Your RT password @@ -58,12 +59,13 @@ Please follow this closely so no emails are sent to researchers by mistake while 1. Add the following lines to the `.Renviron` (can be accessed by `usethis::edit_r_environ()`) ``` SLACK_WEBHOOK_URL="{URL}" # Your Slack webhook URL + SLACK_OAUTH_TOKEN="TOKEN" RT_URL="https://example.com/rt" # The URL of your RT install RT_USER="your_rt_user" # Your RT username RT_PASS="your_rt_password" # Your RT password ``` -2. Set up slackbot: `slackr::slackr_setup(channel = "#awardbot",incoming_webhook_url = Sys.getenv("SLACK_WEBHOOK_URL"), cacheChannels = F)` +2. Set up slackbot: `slackr::slackr_setup(channel = "#awardbot", username = 'awardbot', incoming_webhook_url = Sys.getenv("SLACK_WEBHOOK_URL"), bot_user_oauth_token = Sys.getenv("SLACK_OAUTH_TOKEN"))` 3. Login to RT: `rt::rt_login()` From 7ff8ce37b3aa3459f5985bc0d806e6fa618d0e43 Mon Sep 17 00:00:00 2001 From: laijasmine Date: Wed, 12 May 2021 16:08:28 -0700 Subject: [PATCH 2/6] add csvs to gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a9b46f2..2cc27ba 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,5 @@ .Rhistory .RData .Ruserdata - +*.csv *.DS_Store \ No newline at end of file From c1c2133ffd3654d5c80ce489661e2bd0684fd330 Mon Sep 17 00:00:00 2001 From: laijasmine Date: Wed, 12 May 2021 16:09:56 -0700 Subject: [PATCH 3/6] modify RT functions to save every time --- R/RT_functions.R | 52 ++++++++++++++++++------------ R/main.R | 3 +- tests/testthat/test_RT_functions.R | 17 +++++----- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/R/RT_functions.R b/R/RT_functions.R index 4b72637..fc9c1e1 100644 --- a/R/RT_functions.R +++ b/R/RT_functions.R @@ -7,14 +7,14 @@ #' @param awards_db (data.frame) awards database #' #' @importFrom magrittr '%>%' -send_correspondences <- function(awards_db) { +send_correspondences <- function(awards_db, database_path) { indices <- which(awards_db$active_award_flag == 'yes') db <- awards_db[indices,] - db <- create_ticket_and_send_initial_correspondence(db) %>% - send_annual_report_correspondence() %>% - send_aon_correspondence() %>% - send_one_month_remaining_correspondence() + db <- create_ticket_and_send_initial_correspondence(db, database_path) %>% + send_annual_report_correspondence(., database_path) %>% + send_aon_correspondence(., database_path) %>% + send_one_month_remaining_correspondence(., database_path) awards_db[indices,] <- db @@ -57,7 +57,7 @@ create_ticket <- function(award, requestor) { #' @param awards_db (data.frame) database of NSF awards pulled from NSF-API #' #' @return awards_db (data.frame) The initial database with updated RT ticket numbers -create_ticket_and_send_initial_correspondence <- function(awards_db) { +create_ticket_and_send_initial_correspondence <- function(awards_db, database_path) { # Get awards without an initial correspondence indices <- which(is.na(awards_db$contact_initial)) # save indices to re-merge db <- awards_db[indices,] @@ -65,6 +65,7 @@ create_ticket_and_send_initial_correspondence <- function(awards_db) { for (i in seq_len(nrow(db))) { # Create RT ticket db$rt_ticket[i] <- create_ticket(db$id[i], db$pi_email[i]) + if (db$rt_ticket[i] == 'rt_ticket_create_error') { next } @@ -78,16 +79,18 @@ create_ticket_and_send_initial_correspondence <- function(awards_db) { reply <- check_rt_reply(db$rt_ticket[i], email_text) db$contact_initial[i] <- as.character(Sys.Date()) + + # re-merge temporary database into permanent + awards_db[i,] <- db[i,] + #save the result inbetween + utils::write.csv(db, file = database_path, row.names = FALSE) } - # re-merge temporary database into permanent - awards_db[indices,] <- db - return(awards_db) } -send_annual_report_correspondence <- function(awards_db) { +send_annual_report_correspondence <- function(awards_db, database_path) { # Get awards to send annual report correspondence current_date <- as.character(Sys.Date()) indices <- which(awards_db$contact_annual_report_next == current_date) # save indices to re-merge @@ -103,19 +106,22 @@ send_annual_report_correspondence <- function(awards_db) { # Update last contact date db$contact_annual_report_previous[i] <- db$contact_annual_report_next[i] + + # re-merge temporary database into permanent + awards_db[i,] <- db[i, ] + #save the result inbetween + utils::write.csv(db, file = database_path, row.names = FALSE) } - # re-merge temporary database into permanent - awards_db[indices,] <- db - ## TODO # add function that updates annual report correspondence times + return(awards_db) } -send_aon_correspondence <- function(awards_db){ +send_aon_correspondence <- function(awards_db, database_path){ current_date <- as.character(Sys.Date()) indices <- which(awards_db$contact_aon_next == current_date) db <- awards_db[indices,] @@ -130,16 +136,18 @@ send_aon_correspondence <- function(awards_db){ # Update last contact date db$contact_aon_previous[i] <- db$contact_aon_next[i] + + # re-merge temporary database into permanent + awards_db[i,] <- db[i, ] + #save the result inbetween + utils::write.csv(db, file = database_path, row.names = FALSE) } - # re-merge temporary database into permanent - awards_db[indices,] <- db - return(awards_db) } -send_one_month_remaining_correspondence <- function(awards_db) { +send_one_month_remaining_correspondence <- function(awards_db, database_path) { indices <- which(awards_db$contact_1mo == as.character(Sys.Date())) db <- awards_db[indices,] @@ -155,10 +163,12 @@ send_one_month_remaining_correspondence <- function(awards_db) { # Update last contact date db$contact_1mo[i] <- as.character(Sys.Date()) + + # re-merge temporary database into permanent + awards_db[i,] <- db[i, ] + #save the result inbetween + utils::write.csv(db, file = database_path, row.names = FALSE) } - - # re-merge temporary database into permanent - awards_db[indices,] <- db return(awards_db) } diff --git a/R/main.R b/R/main.R index b3478bb..15f3c40 100644 --- a/R/main.R +++ b/R/main.R @@ -33,11 +33,10 @@ main <- function(database_path = Sys.getenv('DATABASE_PATH'), db <- update_contact_dates(db, annual_report_time, initial_aon_offset, aon_recurring_interval) ## Send correspondences - db <- send_correspondences(db) + send_correspondences(db, database_path) ## Save lastrun and database save_lastrun(current_date, lastrun_path) - utils::write.csv(db, file = database_path, row.names = FALSE) return(invisible()) } diff --git a/tests/testthat/test_RT_functions.R b/tests/testthat/test_RT_functions.R index 6b7e43b..6c11e3f 100644 --- a/tests/testthat/test_RT_functions.R +++ b/tests/testthat/test_RT_functions.R @@ -24,7 +24,8 @@ test_that('we can send an initial correspondence', { } db <- create_dummy_database() - db <- create_ticket_and_send_initial_correspondence(db) + + db <- create_ticket_and_send_initial_correspondence(db, database_path = "inst/test_db.csv") ticket <- rt::rt_ticket_properties(db$rt_ticket) expect_equal(ticket$Requestors, 'jasminelai@nceas.ucsb.edu') @@ -36,9 +37,9 @@ test_that('we can send an annual report correspondence', { } db <- create_dummy_database() - db <- create_ticket_and_send_initial_correspondence(db) + db <- create_ticket_and_send_initial_correspondence(db, database_path = "inst/test_db.csv") db$contact_annual_report_next <- as.character(Sys.Date()) - db <- send_annual_report_correspondence(db) + db <- send_annual_report_correspondence(db, database_path = "inst/test_db.csv") expect_equal(db$contact_annual_report_next, db$contact_annual_report_previous) }) @@ -49,10 +50,10 @@ test_that('we can send a one month remaining correspondence',{ } db <- create_dummy_database() - db <- create_ticket_and_send_initial_correspondence(db) + db <- create_ticket_and_send_initial_correspondence(db, database_path = "inst/test_db.csv") # Set expiration date to one month from now db$contact_1mo <- as.character(Sys.Date()) - db <- send_one_month_remaining_correspondence(db) + db <- send_one_month_remaining_correspondence(db, database_path = "inst/test_db.csv") expect_equal(db$contact_1mo, as.character(Sys.Date())) }) @@ -63,9 +64,9 @@ test_that('we can send an aon correspondence', { } db <- create_dummy_database() - db <- create_ticket_and_send_initial_correspondence(db) + db <- create_ticket_and_send_initial_correspondence(db, database_path = "inst/test_db.csv") db$contact_aon_next <- as.character(Sys.Date()) - db <- send_aon_correspondence(db) + db <- send_aon_correspondence(db, database_path = "inst/test_db.csv") expect_equal(db$contact_aon_previous, db$contact_aon_next) }) @@ -80,7 +81,7 @@ test_that('check_rt_reply catches both potential errors', { } db <- create_dummy_database() - db <- create_ticket_and_send_initial_correspondence(db) + db <- create_ticket_and_send_initial_correspondence(db, database_path = "inst/test_db.csv") template <- read_initial_template(db$fund_program_name[1]) email_text <- sprintf(template, From 27a8d1eb0e9d7848b0542991b55398e572648be5 Mon Sep 17 00:00:00 2001 From: laijasmine Date: Thu, 13 May 2021 15:59:07 -0700 Subject: [PATCH 4/6] add database_path to documentation --- R/RT_functions.R | 2 ++ man/create_ticket_and_send_initial_correspondence.Rd | 4 +++- man/send_correspondences.Rd | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/R/RT_functions.R b/R/RT_functions.R index fc9c1e1..ed9b45d 100644 --- a/R/RT_functions.R +++ b/R/RT_functions.R @@ -5,6 +5,7 @@ #' 'send_one_month_remaining_correspondence' #' #' @param awards_db (data.frame) awards database +#' @param database_path (character) the path to save the database to #' #' @importFrom magrittr '%>%' send_correspondences <- function(awards_db, database_path) { @@ -55,6 +56,7 @@ create_ticket <- function(award, requestor) { #' pi_email, pi_first_name, id (NSF award #), title (NSF award title). #' #' @param awards_db (data.frame) database of NSF awards pulled from NSF-API +#' @param database_path (character) the path to save the database to #' #' @return awards_db (data.frame) The initial database with updated RT ticket numbers create_ticket_and_send_initial_correspondence <- function(awards_db, database_path) { diff --git a/man/create_ticket_and_send_initial_correspondence.Rd b/man/create_ticket_and_send_initial_correspondence.Rd index a7e86e2..226af39 100644 --- a/man/create_ticket_and_send_initial_correspondence.Rd +++ b/man/create_ticket_and_send_initial_correspondence.Rd @@ -4,10 +4,12 @@ \alias{create_ticket_and_send_initial_correspondence} \title{Create New Tickets and send initial correspondences} \usage{ -create_ticket_and_send_initial_correspondence(awards_db) +create_ticket_and_send_initial_correspondence(awards_db, database_path) } \arguments{ \item{awards_db}{(data.frame) database of NSF awards pulled from NSF-API} + +\item{database_path}{(character) the path to save the database to} } \value{ awards_db (data.frame) The initial database with updated RT ticket numbers diff --git a/man/send_correspondences.Rd b/man/send_correspondences.Rd index 59f3f51..0437949 100644 --- a/man/send_correspondences.Rd +++ b/man/send_correspondences.Rd @@ -4,10 +4,12 @@ \alias{send_correspondences} \title{Wrapper function that sends all correspondences} \usage{ -send_correspondences(awards_db) +send_correspondences(awards_db, database_path) } \arguments{ \item{awards_db}{(data.frame) awards database} + +\item{database_path}{(character) the path to save the database to} } \description{ Wrapper function for 'create_ticket_and_send_initial_correspondence', From 7ea3e6b54c4be299eb7bff0cacffa3b9f5bd8a01 Mon Sep 17 00:00:00 2001 From: laijasmine Date: Thu, 13 May 2021 16:01:17 -0700 Subject: [PATCH 5/6] update slackr_setup in cron script to include the bot_user_oauth_token argument --- inst/main_cron_script.R | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/inst/main_cron_script.R b/inst/main_cron_script.R index 8668d88..61995ff 100644 --- a/inst/main_cron_script.R +++ b/inst/main_cron_script.R @@ -8,18 +8,20 @@ library(slackr) library(stringr) library(XML) -## Set up environment variables -readRenviron(file.path(getwd(), '.Renviron')) +## Set up environment variables +readRenviron(file.path(getwd(), ".Renviron")) ## Source the bot -remotes::install_github('NCEAS/awards-bot') +remotes::install_github("NCEAS/awards-bot") library(awardsBot) -# Log in to RT/SLACK -rt::rt_login(Sys.getenv('RT_USER'), Sys.getenv('RT_PASS'), Sys.getenv('RT_URL')) +# Log in to RT/SLACK +rt::rt_login(Sys.getenv("RT_USER"), Sys.getenv("RT_PASS"), Sys.getenv("RT_URL")) -slackr::slackr_setup(channel = "#awardbot", username = 'awardbot', - incoming_webhook_url = Sys.getenv("SLACK_WEBHOOK_URL"), - cacheChannels = F) +slackr::slackr_setup( + channel = "#awardbot", username = "awardbot", + incoming_webhook_url = Sys.getenv("SLACK_WEBHOOK_URL"), + bot_user_oauth_token = Sys.getenv("SLACK_OAUTH_TOKEN") +) -awardsBot::main() \ No newline at end of file +awardsBot::main() From 0dd713c62d5e4f7cef8f5ddb3ff9a6f6aeb9530d Mon Sep 17 00:00:00 2001 From: laijasmine Date: Fri, 14 May 2021 15:43:51 -0700 Subject: [PATCH 6/6] add to a slack bot message after every complete run to report back the number of tickets sent that time --- R/RT_functions.R | 6 ++++++ R/main.R | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/R/RT_functions.R b/R/RT_functions.R index ed9b45d..74d568a 100644 --- a/R/RT_functions.R +++ b/R/RT_functions.R @@ -19,6 +19,12 @@ send_correspondences <- function(awards_db, database_path) { awards_db[indices,] <- db + #send summary of tickets sent + if(nrow(awards_db[indices,]) > 0) { + out <- sprintf('I sent %s tickets today', nrow(awards_db[indices,])) + slackr::slackr_bot(out) + } + return(awards_db) } diff --git a/R/main.R b/R/main.R index 15f3c40..03a7b34 100644 --- a/R/main.R +++ b/R/main.R @@ -1,4 +1,3 @@ -## TODO add a slack message that details every email sent per day? #' main function #' #' @param database_path (character) Path to the database of awards and correspondences