Skip to content

Commit

Permalink
Merge pull request #159 from mrkaye97/v3.0.0
Browse files Browse the repository at this point in the history
v3.0.0
  • Loading branch information
mrkaye97 authored Aug 7, 2021
2 parents 6990e6e + 90aa47e commit 56a2a42
Show file tree
Hide file tree
Showing 48 changed files with 502 additions and 621 deletions.
7 changes: 4 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Type: Package
Package: slackr
Title: Send Messages, Images, R Objects and Files to 'Slack'
Channels/Users
Version: 2.4.1
Version: 3.0.0
Author: Bob Rudis [aut, cre], Jay Jacobs [ctb], David Severski [ctb],
Quinn Weber [ctb], Konrad Karczewski [ctb], Shinya Uryu [ctb], Gregory
Jefferis [ctb], Ed Niles [ctb], Rick Saporta [ctb], Jonathan Sidi
Expand Down Expand Up @@ -31,11 +31,12 @@ Imports:
graphics,
grDevices,
httr (>= 1.4.2),
lifecycle,
jsonlite,
magrittr,
memoise (>= 2.0.0),
methods,
purrr,
reprex (>= 2.0.1),
rlang,
tibble,
utils,
Expand All @@ -46,7 +47,7 @@ Suggests:
rmarkdown,
testthat (>= 3.0.0),
texPreview
VignetteBuilder:
VignetteBuilder:
knitr
Config/testthat/edition: 3
Encoding: UTF-8
Expand Down
8 changes: 6 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,15 @@ importFrom(httr,upload_file)
importFrom(httr,verbose)
importFrom(jsonlite,fromJSON)
importFrom(jsonlite,toJSON)
importFrom(lifecycle,deprecate_warn)
importFrom(magrittr,"%>%")
importFrom(memoise,memoise)
importFrom(purrr,discard)
importFrom(purrr,map)
importFrom(purrr,modify_at)
importFrom(purrr,pluck)
importFrom(purrr,quietly)
importFrom(rlang,abort)
importFrom(rlang,as_string)
importFrom(rlang,call2)
importFrom(rlang,inform)
importFrom(rlang,warn)
importFrom(tibble,as_tibble)
Expand Down
17 changes: 15 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# slackr 3.0.0

Lots of breaking changes in this release:
* `bot_user_oauth_token` has been removed entirely in favor of `token`
* `slackr_history` now has `message_count` as it's first argument
* Adding the capability to pass the `thread_ts` parameter to all `slackr_*` functions (i.e. allowing you to reply to a message in a thread)
* Adding `reply_broadcast` capability in `slackr` and `slackr_msg`
* Adding `title` and `initial_comment` parameters for all functions relying on the `files.upload` endpoint (basically everything except for `slackr`, `slackr_bot`, `slackr_msg`, `slackr_history`, and `slackr_delete`)
* `slackr` and `slackr_bot` now use `reprex::prex()` in the background, which means that they no longer throw errors the same way as they did before. `slackr` will try to be helpful in telling you what went wrong if your `prex` output contains an error (instead of posting), but it isn't guaranteed to work all of the time. You can prevent this behavior by setting the `SLACKR_ERRORS` environment variable to `"IGNORE"`.

Other changes:
* Significant improvements to documentation, which now aligns with Slack API descriptions
* Significant internal overhauls of how the functions call the API

# slackr 2.4.1

* Small bug fix for `ggslackr`
Expand Down Expand Up @@ -36,7 +50,7 @@
# slackr 2.1.1

* Changes a few badly-set function default channels to be `Sys.getenv('SLACK_CHANNEL')` instead of `''`
* Adds a more informative error message on `slackr_upload()` when the request returns `not authed` as per #137
* Adds a more informative error message on `slackr_upload()` when the request returns `not authed` as per #137
* Deprecates some arguments in `slackr_bot()` that no longer work (username, channel, icon emoji) that used to work with the old API structure

# slackr 2.1.0
Expand Down Expand Up @@ -81,4 +95,3 @@
* Versions 1.4+ BREAK THINGS.
* Support has been removed for the "old style" incoming web hooks (see "Setup" in the README for the required incoming web hook URL format).
* the incoming webhook "token" is no longer required or used.

25 changes: 11 additions & 14 deletions R/call_slack_api.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ POST <- "POST"
#' The function is called for the side effect of warning when the API response
#' has errors, and is a thin wrapper around httr::stop_for_status
#'
#' @param r The response from a call to the Slack API
#' @param r The response from a call to the Slack API.
#'
#' @return NULL
#' @importFrom httr status_code content
Expand Down Expand Up @@ -69,10 +69,10 @@ with_retry <- function(fun) {
#'
#' @inheritParams auth_test
#'
#' @param path The API definition path, e.g. `/api/auth.test`
#' @param ... These arguments must be named and will be added to the API query string
#' @param body If `.method = POST` the `body` gets passed to the API body
#' @param .method Either "GET" or "POST"
#' @param path The API definition path, e.g. `/api/auth.test`.
#' @param ... These arguments must be named and will be added to the API query string.
#' @param body If `.method = POST` the `body` gets passed to the API body.
#' @param .method Either "GET" or "POST".
#' @param .verbose If TRUE, prints `httr` verbose messages. Useful for debugging.
#' @param .next_cursor The value of the next cursor, when using pagination.
#' @importFrom httr add_headers verbose set_config GET POST
Expand Down Expand Up @@ -172,8 +172,8 @@ get_retry_after <- function(x) {
#' This loops over `fun`, extracts the `next_cursor` from the API response, and
#' injects this into the next loop. At the completion of each loop, the function [convert_response_to_tibble()] is run with `extract` as and argument. The results are combined with [dplyr::bind_rows()]
#'
#' @param fun A function that calls the slack API
#' @param extract The name of the element to extract from the API response
#' @param fun A function that calls the slack API.
#' @param extract The name of the element to extract from the API response.
#'
#' @return A `tibble`
#' @seealso call_slack_api
Expand Down Expand Up @@ -218,8 +218,7 @@ with_pagination <- function(fun, extract) {

#' Checks authentication & identity against the Slack API.
#'
#' @param token The Slack bot OAuth token {character vector}
#' @param bot_user_oauth_token Deprecated
#' @param token Authentication token bearing required scopes.
#'
#' @references https://api.slack.com/methods/auth.test
#' @export
Expand All @@ -230,9 +229,7 @@ with_pagination <- function(fun, extract) {
#' if (Sys.getenv("SLACK_TOKEN") != "") {
#' auth_test()
#' }
auth_test <- function(token = Sys.getenv("SLACK_TOKEN"), bot_user_oauth_token = Sys.getenv("SLACK_BOT_USER_OAUTH_TOKEN")) {
if (bot_user_oauth_token != "") warn("The use of `bot_user_oauth_token` is deprecated as of `slackr 2.4.0`. Please use `token` instead.")

auth_test <- function(token = Sys.getenv("SLACK_TOKEN")) {
call_slack_api(
"/api/auth.test",
.method = GET,
Expand All @@ -244,8 +241,8 @@ auth_test <- function(token = Sys.getenv("SLACK_TOKEN"), bot_user_oauth_token =

#' Convert Slack API json response to tibble.
#'
#' @param x The Slack API response object, returned from [call_slack_api]
#' @param element The name of the list element to extract
#' @param x The Slack API response object, returned from [call_slack_api].
#' @param element The name of the list element to extract.
#' @importFrom magrittr %>%
#' @importFrom jsonlite fromJSON
#' @importFrom tibble as_tibble
Expand Down
44 changes: 21 additions & 23 deletions R/call_slack_internals.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#'
#' @inheritParams auth_test
#'
#' @param exclude_archived If TRUE, excludes archived channels
#' @param exclude_archived If TRUE, excludes archived channels.
#'
#' @return tibble of channels
#'
Expand Down Expand Up @@ -54,12 +54,11 @@ list_users <- function(token = Sys.getenv("SLACK_TOKEN"), ...) {
#' @keywords internal
#' @noRd
#'
#' @param txt Passed to `text` parameter of `chat.postMessage` API
#' @param emoji Emoji
#' @param channel Passed to `channel` parameter of `chat.postMessage` API
#' @param username Passed to `username` parameter of `chat.postMessage` API
#' @param as_user Passed to `as_user` parameter of `chat.postMessage` API
#' @param link_names Passed to `link_names` parameter of `chat.postMessage` API
#' @param txt Passed to `text` parameter of `chat.postMessage` API.
#' @param channel Channel, private group, or IM channel to send message to. Can be an encoded ID, or a name.
#' @param emoji Emoji to use as the icon for this message. Overrides icon_url. Must be used in conjunction with as_user (hard coded in `slackr`) set to false, otherwise ignored.
#' @param username Set your bot's user name. Must be used in conjunction with as_user set to false, otherwise ignored.
#' @param token A Slack API token.
#'
#' @references https://api.slack.com/methods/chat.postMessage
post_message <- function(txt,
Expand All @@ -68,7 +67,7 @@ post_message <- function(txt,
username = Sys.getenv("SLACK_USERNAME"),
token = Sys.getenv("SLACK_TOKEN"),
...) {
z <-
r <-
call_slack_api(
"/api/chat.postMessage",
.method = POST,
Expand All @@ -83,7 +82,7 @@ post_message <- function(txt,
)
)

invisible(content(z))
invisible(content(r))
}


Expand All @@ -94,43 +93,42 @@ post_message <- function(txt,
#'
#' This needs the scope `files:write:user`
#'
#' @inheritParams auth_test
#' @inheritParams post_message
#'
#' @param file Name of file to upload
#' @param file Name of file to upload.
#' @param channels Comma-separated list of channel names or IDs where the file will be shared.
#' @param initial_comment The message text introducing the file in specified channels.
#' @param token Authentication token bearing required scopes.
#' @param ... Additional arguments to be passed in the POST body to the `files.upload` endpoint. See the \href{https://api.slack.com/methods/files.upload}{files.upload endpoint documentation} for details.
#' @importFrom httr upload_file
#' @keywords internal
#' @noRd
#'
#'
#' @references https://api.slack.com/methods/files.upload
files_upload <- function(file,
channel,
txt = "",
username = Sys.getenv("SLACK_USERNAME"),
channels,
initial_comment = NULL,
token = Sys.getenv("SLACK_TOKEN"),
...) {
z <- call_slack_api(
r <- call_slack_api(
"/api/files.upload",
.method = POST,
token = token,
body = list(
file = upload_file(file),
initial_comment = txt,
channels = channel,
username = username,
initial_comment = initial_comment,
channels = paste(channels, collapse = ","),
...
)
)
invisible(content(z))
invisible(content(r))
}


list_scopes <- function(token = Sys.getenv("SLACK_TOKEN")) {
z <- call_slack_api(
r <- call_slack_api(
"/api/apps.permissions.scopes.list",
.method = GET,
token = token
)
invisible(content(z))
invisible(content(r))
}
38 changes: 21 additions & 17 deletions R/gg_slackr.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@
#' Unlike the [slackr_dev()] function, this one takes a `ggplot` object,
#' eliminating the need to have a graphics device (think use in scripts).
#'
#' @param plot ggplot object to save, defaults to last plot displayed
#' @param channels list of channels to post image to
#' @param scale scaling factor
#' @param width width (defaults to the width of current plotting window)
#' @param height height (defaults to the height of current plotting window)
#' @param plot ggplot object to save, defaults to last plot displayed.
#' @param channels Comma-separated list of channel names or IDs where the file will be shared.
#' @param scale scaling factor.
#' @param width width (defaults to the width of current plotting window).
#' @param height height (defaults to the height of current plotting window).
#' @param units units for width and height when either one is explicitly specified
#' (in, cm, or mm)
#' @param dpi dpi to use for raster graphics
#' (in, cm, or mm).
#' @param dpi dpi to use for raster graphics.
#' @param limitsize when TRUE (the default), ggsave will not save images larger
#' than 50x50 inches, to prevent the common error of specifying dimensions in pixels.
#' @param token A Slack token (either a user token or a bot user token)
#' @param bot_user_oauth_token Deprecated. A Slack bot user OAuth token
#' @param file prefix for filenames (defaults to `ggplot`)
#' @param ... other arguments passed to graphics device
#' @param token Authentication token bearing required scopes.
#' @param file Prefix for filenames (defaults to `ggplot`).
#' @param initial_comment The message text introducing the file in specified channels.
#' @param thread_ts Provide another message's ts value to upload this file as a reply. Never use a reply's ts value; use its parent instead.
#' @param title Title of file.
#' @param ... other arguments passed to graphics device.
#' @importFrom ggplot2 ggsave last_plot ggplot aes geom_point
#' @importFrom graphics par
#' @return `httr` response object (invisibly)
Expand All @@ -36,11 +38,10 @@ ggslackr <- function(plot = last_plot(),
limitsize = TRUE,
token = Sys.getenv("SLACK_TOKEN"),
file = "ggplot",
bot_user_oauth_token = Sys.getenv("SLACK_BOT_USER_OAUTH_TOKEN"),
initial_comment = NULL,
thread_ts = NULL,
title = NULL,
...) {

token <- check_tokens(token, bot_user_oauth_token)

ftmp <- tempfile(file, fileext = ".png")
ggsave(
filename = ftmp,
Expand All @@ -57,8 +58,11 @@ ggslackr <- function(plot = last_plot(),
res <-
files_upload(
file = ftmp,
channel = channels,
token = token
channels = channels,
token = token,
initial_comment = initial_comment,
thread_ts = thread_ts,
title = title
)

invisible(res)
Expand Down
2 changes: 2 additions & 0 deletions R/globals.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
prex_r <- utils::getFromNamespace("prex_r", "reprex")
quiet_prex <- purrr::quietly(prex_r)
40 changes: 2 additions & 38 deletions R/internals.R
Original file line number Diff line number Diff line change
@@ -1,43 +1,7 @@
#' Check for token issues
#'
#' @param token a token
#' @param bot_user_oauth_token another token
#' @importFrom lifecycle deprecate_warn
#' @importFrom rlang as_string
#' @return A token
check_tokens <- function(token, bot_user_oauth_token) {
calling_fun <- tryCatch(
{
as_string(as.list(sys.call(-1))[[1]])
},
error = function(e) "an unknown function"
)
dep_arg1 <- sprintf("%s(bot_user_oauth_token)", calling_fun)
dep_arg2 <- sprintf("%s(token)", calling_fun)

if (token == "" & bot_user_oauth_token == "") {
abort("No token found. Did you forget to call `slackr_setup()`?")
}

if (token != "" & bot_user_oauth_token != "" & token != bot_user_oauth_token) {
abort(
"You specified both a `token` and a `bot_user_oauth_token`, and the two were not the same. Please only specify a `token`."
)
}

if (bot_user_oauth_token != "") {
deprecate_warn("2.4.0", dep_arg1, dep_arg2)

return(bot_user_oauth_token)
}

return(token)
}

#' Check for token-parameter mismatches
#'
#' @param token a token
#' @param ... Additiional arguments passed to the function called
#' @param token Authentication token bearing required scopes.
#' @param ... Additiional arguments passed to the function called.
#' @return No return value. Called for side effects
warn_for_args <- function(token, ...) {
if (substr(token, 1L, 4L) == "xoxp") {
Expand Down
18 changes: 7 additions & 11 deletions R/register_onexit.R
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
#' @title Append slackr_msg as on.exit to functions.
#' @description Appends to the body of a function an on.exit call to run at the end of the call.
#' @param f function or character
#' @param ... expressions to be sent to Slack
#' @param header_msg boolean, message to append to start of Slack output, Default: NULL
#' @param f function or character.
#' @param ... expressions to be sent to Slack.
#' @param header_msg boolean, message to append to start of Slack output, Default: NULL.
#' @param use_device boolean, passes current image in the graphics device to Slack as part of f,
#' Default: FALSE
#' Default: FALSE.
#' @param env environment to assign appended function to with relation to the function environment,
#' Default: parent.frame(2) (global environment)
#' @param token A Slack token (either a user token or a bot user token)
#' @param bot_user_oauth_token Deprecated. A Slack bot user OAuth token
#' Default: parent.frame(2) (global environment).
#' @param token Authentication token bearing required scopes.
#' @inherit slackr
#' @return function
#' @details If a character is passed to f then it will evaluate internally to a function.
Expand Down Expand Up @@ -64,10 +63,7 @@ register_onexit <- function(f,
channel = Sys.getenv("SLACK_CHANNEL"),
username = Sys.getenv("SLACK_USERNAME"),
icon_emoji = Sys.getenv("SLACK_ICON_EMOJI"),
token = Sys.getenv("SLACK_TOKEN"),
bot_user_oauth_token = Sys.getenv("SLACK_BOT_USER_OAUTH_TOKEN")) {
token <- check_tokens(token, bot_user_oauth_token)

token = Sys.getenv("SLACK_TOKEN")) {
warn_for_args(
token,
username = username,
Expand Down
Loading

0 comments on commit 56a2a42

Please sign in to comment.