jdtrat / chimpr

mailchimp R client
https://sckott.github.io/chimpr/
Other
15 stars 3 forks source link

Harcoded Datacenter #1

Closed Btibert3 closed 6 years ago

Btibert3 commented 6 years ago

This issue is to address the hardcoded datacenter found in chmp_base in zzz.R . With the hardcoded datacenter, a call to my account fails.

> options(stringsAsFactors = FALSE)
> library(chimpr)
> ## API Key
> Sys.setenv(MAILCHIMP_KEY = "mykeyhere-us17")
> ## get a list of campaigns
> chmp_ping()
Error: 
  type: http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/
  title: Wrong Datacenter
  status: 403
  detail: The API key provided is linked to a different datacenter
  instance: 9258381c-5176-43d4-bb49-ada6a02f8b47
> devtools::session_info()
Session info ---------------------------------------------------------------------------------------------------
 setting  value                                 
 version  R version 3.4.4 RC (2018-03-08 r74373)
 system   x86_64, darwin15.6.0                  
 ui       RStudio (1.1.423)                     
 language (EN)                                  
 collate  en_US.UTF-8                           
 tz       America/New_York                      
 date     2018-08-15                            

Packages -------------------------------------------------------------------------------------------------------
 package   * version    date       source                        
 base      * 3.4.4      2018-03-09 local                         
 chimpr    * 0.0.4.9100 2018-08-15 Github (sckott/chimpr@99e032b)
 compiler    3.4.4      2018-03-09 local                         
 crul        0.6.0      2018-07-10 cran (@0.6.0)                 
 curl        3.2        2018-03-28 CRAN (R 3.4.4)                
 datasets  * 3.4.4      2018-03-09 local                         
 devtools    1.13.3     2017-08-02 CRAN (R 3.4.1)                
 digest      0.6.15     2018-01-28 cran (@0.6.15)                
 graphics  * 3.4.4      2018-03-09 local                         
 grDevices * 3.4.4      2018-03-09 local                         
 httpcode    0.2.0      2016-11-14 cran (@0.2.0)                 
 jsonlite    1.5        2017-06-01 CRAN (R 3.4.0)                
 memoise     1.1.0      2017-04-21 CRAN (R 3.4.0)                
 methods   * 3.4.4      2018-03-09 local                         
 R6          2.2.2      2017-06-17 CRAN (R 3.4.0)                
 Rcpp        0.12.18    2018-07-23 cran (@0.12.18)               
 stats     * 3.4.4      2018-03-09 local                         
 tools       3.4.4      2018-03-09 local                         
 triebeard   0.3.0      2016-08-04 CRAN (R 3.4.0)                
 urltools    1.7.1      2018-08-03 cran (@1.7.1)                 
 utils     * 3.4.4      2018-03-09 local                         
 withr       2.1.0      2017-11-01 CRAN (R 3.4.2)                
 yaml        2.1.19     2018-05-01 cran (@2.1.19)     
Btibert3 commented 6 years ago

Modified zzz.R and shown below to account for the datacenter and add as a parameter in chmp_GET to pass to chmp_base.

With those tweaks, the following code now works:

options(stringsAsFactors = FALSE)

## load the package
library(chimpr)

## API key
Sys.setenv(MAILCHIMP_KEY = "mykeyhere-us17")

## test
chmp_ping(dc="us17")

The zzz.R file on my local machine:

ct <- function(l) Filter(Negate(is.null), l)

chimpr_ua <- function() {
  versions <- c(
    paste0("r-curl/", utils::packageVersion("curl")),
    paste0("crul/", utils::packageVersion("crul")),
    sprintf("rOpenSci(chimpr/%s)", utils::packageVersion("chimpr"))
  )
  paste0(versions, collapse = " ")
}

chmp_GET <- function(dc = "us7", path, key, query = list(), ...){
  cli <- crul::HttpClient$new(
    url = chmp_base(dc),
    opts = c(list(useragent = chimpr_ua()), ...),
    auth = crul::auth(user = "anystring", pwd = check_key(key))
  )
  temp <- cli$get(
    path = file.path("3.0", path), 
    query = query)
  err_catcher(temp)
  #temp$raise_for_status()
  x <- temp$parse("UTF-8")
  return(x)
}

err_catcher <- function(x) {
  if (x$status_code > 201) {
    if (x$response_headers$`content-type` == 
      "application/problem+json; charset=utf-8") {

      xx <- jsonlite::fromJSON(x$parse("UTF-8"))
      xx <- paste0("\n  ", paste(names(xx), unname(xx), sep = ": ", 
        collapse = "\n  "))
      stop(xx, call. = FALSE)
    } else {
      x$raise_for_status()
    }
  }
}

chmp_parse <- function(x, parse) {
  jsonlite::fromJSON(x, parse)
}

check_key <- function(x){
  tmp <- if (is.null(x)) Sys.getenv("MAILCHIMP_KEY", "") else x
  if (tmp == "") {
    stop("need an API key for the Mailchimp API", call. = FALSE)
  } else {
    tmp
  }
}

chmp_base <- function(x="us7") sprintf("https://%s.api.mailchimp.com", x)

space <- function(x) gsub("\\s", "%20", x)

assert_is <- function(x, y) {
  if (!is.null(x)) {
    if (!class(x) %in% y) {
      stop(deparse(substitute(x)), " must be of class ",
           paste0(y, collapse = ", "), call. = FALSE)
    }
  }
}

assert_n <- function(x, n) {
  if (!is.null(x)) {
    if (!length(x) == n) {
      stop(deparse(substitute(x)), " must be length ", n, call. = FALSE)
    }
  }
}

`%||%` <- function(x, y) {
  if (is.null(x) || length(x) == 0) y else x
}
sckott commented 6 years ago

thanks @Btibert3

a question for you: In a single R session are you going to use the same datacenter the whole time, or do you switch between data centers? Because if the main use case is a single person only interacts with one datacenter, I think it makes more sense to set datacenter as an env var or similar at the beginning of a session instead of as a parameter to each fxn call. thoguhts?

Btibert3 commented 6 years ago

It's a good question. In my current use case it is a singular data center, but if I were managing multiple client accounts, its possible to envision a scenario where changing it on the fly makes sense. I probably could go either way TBH.

sckott commented 6 years ago

thanks. can you install from the rework branch remotes::install_github("sckott/chimpr@rework") and try again? now there's a ChmpClient R6 object to create first, then pass on to all other classes (and root and ping moved inside ChmpClient), now chmp_lists() is only method that's a simple function and not an R6

Btibert3 commented 6 years ago

Looks good!

sckott commented 6 years ago

glad it works, will merge to master now