From 040479fb4d4b3a24c2c249270586f5e6992be282 Mon Sep 17 00:00:00 2001 From: Bob Rudis Date: Wed, 27 Apr 2016 13:31:09 +0000 Subject: [PATCH] version 1.4.1 --- DESCRIPTION | 39 +- MD5 | 47 +- NAMESPACE | 30 +- NEWS | 5 + R/dev_slackr.R | 50 ++ R/gg_slackr.R | 66 +++ R/save_slackr.R | 50 ++ R/slackr-package.R | 28 +- R/slackr.R | 524 +++++--------------- R/slackr_bot.r | 98 ++++ R/slackr_setup.r | 95 ++++ R/slackr_upload.R | 43 ++ R/slackr_utils.R | 119 +++++ R/text_slackr.r | 65 +++ R/zcamels.r | 53 ++ README.md | 118 +++++ man/dev.slackr.Rd | 40 -- man/dev_slackr.Rd | 58 +++ man/ggslackr.Rd | 24 +- man/save.slackr.Rd | 29 -- man/save_slackr.Rd | 45 ++ man/slackr-package.Rd | 24 +- man/slackr.Rd | 20 +- man/slackrBot.Rd | 49 -- man/slackrChannels.Rd | 20 - man/slackrGroups.Rd | 17 - man/slackrSetup.Rd | 66 --- man/slackrUpload.Rd | 31 -- man/slackrUsers.Rd | 17 - man/slackr_bot.Rd | 72 +++ man/slackr_channels.Rd | 21 + man/{slackrChTrans.Rd => slackr_chtrans.Rd} | 18 +- man/slackr_groups.Rd | 21 + man/slackr_ims.Rd | 27 + man/slackr_msg.Rd | 59 +++ man/slackr_setup.Rd | 72 +++ man/slackr_upload.Rd | 43 ++ man/slackr_users.Rd | 21 + man/text_slackr.Rd | 65 +++ tests/testthat/test-textslackr.R | 8 + 40 files changed, 1558 insertions(+), 739 deletions(-) create mode 100644 NEWS create mode 100644 R/dev_slackr.R create mode 100644 R/gg_slackr.R create mode 100644 R/save_slackr.R create mode 100644 R/slackr_bot.r create mode 100644 R/slackr_setup.r create mode 100644 R/slackr_upload.R create mode 100644 R/slackr_utils.R create mode 100644 R/text_slackr.r create mode 100644 R/zcamels.r create mode 100644 README.md delete mode 100644 man/dev.slackr.Rd create mode 100644 man/dev_slackr.Rd delete mode 100644 man/save.slackr.Rd create mode 100644 man/save_slackr.Rd delete mode 100644 man/slackrBot.Rd delete mode 100644 man/slackrChannels.Rd delete mode 100644 man/slackrGroups.Rd delete mode 100644 man/slackrSetup.Rd delete mode 100644 man/slackrUpload.Rd delete mode 100644 man/slackrUsers.Rd create mode 100644 man/slackr_bot.Rd create mode 100644 man/slackr_channels.Rd rename man/{slackrChTrans.Rd => slackr_chtrans.Rd} (53%) create mode 100644 man/slackr_groups.Rd create mode 100644 man/slackr_ims.Rd create mode 100644 man/slackr_msg.Rd create mode 100644 man/slackr_setup.Rd create mode 100644 man/slackr_upload.Rd create mode 100644 man/slackr_users.Rd create mode 100644 man/text_slackr.Rd create mode 100644 tests/testthat/test-textslackr.R diff --git a/DESCRIPTION b/DESCRIPTION index eb234c5..b243bfc 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,26 +1,31 @@ Package: slackr Type: Package -Title: Send messages, images, R objects and files to Slack.com - channels/users -Version: 1.2 -Date: 2014-09-08 -Author: Bob Rudis (@hrbrmstr) & Jay Jacobs (@jayjacobs) +Title: Send Messages, Images, R Objects and Files to 'Slack' + Channels/Users +Version: 1.4.1 +Date: 2016-04-26 +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] Maintainer: Bob Rudis -Description: Slackr contains functions that make it possible to - interact with Slack.com messaging platform. When you need to share - information/data from R, rather than resort to copy/paste in e-mails - or other services like Skype, you can use this package to send - well-formatted output from multiple R objects and expressions - to all teammates at the same time with little effort. You can also - send images from the current graphics device, R objects (as RData), - and upload files. +Description: 'Slack' provides a service for teams to + collaborate by sharing messages, images, links, files and more. Functions are provided + that make it possible to interact with the 'Slack' platform 'API'. When + you need to share information or data from R, rather than resort to copy/ + paste in e-mails or other services like 'Skype' , you + can use this package to send well-formatted output from multiple R objects and + expressions to all teammates at the same time with little effort. You can also + send images from the current graphics device, R objects (as RData), and upload + files. URL: http://github.com/hrbrmstr/slackr BugReports: https://github.com/hrbrmstr/slackr/issues License: MIT + file LICENSE Suggests: testthat -Depends: R (>= 3.0.0), httr (>= 0.4.0), jsonlite, data.table (>= - 1.9.2), ggplot2 -Packaged: 2014-09-08 11:02:54 UTC; bob +Depends: R (>= 3.0.0) +Imports: httr (>= 0.4.0), jsonlite, ggplot2, utils, methods, dplyr, + graphics, grDevices +RoxygenNote: 5.0.1 NeedsCompilation: no +Packaged: 2016-04-26 22:00:50 UTC; brudis Repository: CRAN -Date/Publication: 2014-09-08 13:31:26 +Date/Publication: 2016-04-27 13:31:09 diff --git a/MD5 b/MD5 index 22c627b..7bc1dba 100644 --- a/MD5 +++ b/MD5 @@ -1,19 +1,34 @@ -fef8d8b51f364eddf143bad9d3b3f60f *DESCRIPTION +4e18b0d8fdb0da393e1c935abdd012f2 *DESCRIPTION f9e4075add143e1c252d1e4db73539ae *LICENSE -d3e581a2e114234c8da9039aadf61a09 *NAMESPACE -02b30b6132e22ea5c5e52ee820047885 *R/slackr-package.R -7e694dfebe3f356c6379b61dc3eea284 *R/slackr.R -58992a783bc4073ec78f9b64137b6b76 *man/dev.slackr.Rd -6e77df2d3c2a13f93d498afdbaac9676 *man/ggslackr.Rd -f8032be0f7858b0e11bca4f0cf39c576 *man/save.slackr.Rd -18a9eb8c289136343e195a3ea1409524 *man/slackr-package.Rd -5716a17cb78c7b114c48185a442bf011 *man/slackr.Rd -7f6f270e7a0f4c3db131c84832d9f232 *man/slackrBot.Rd -8857d4952a1d21082ef6112b785ef8d4 *man/slackrChTrans.Rd -94d6a8890ae522188172bd2a4a13f620 *man/slackrChannels.Rd -c4026775597da46232251ee7e0c17548 *man/slackrGroups.Rd -f093e736c2f7fef34db36489ffd46316 *man/slackrSetup.Rd -7e53861901a4cfb64a4fa23bde3c32cb *man/slackrUpload.Rd -30e14394737005d547b36f21666f0ed8 *man/slackrUsers.Rd +e6eeca69e76e9ee98468cf8b395b0cba *NAMESPACE +0c39a9fcfe20ac0b39e6c470e77d915b *NEWS +54c547f00353e6a7cef1186e7b502118 *R/dev_slackr.R +209ede075ee0a7de8a3e5d195301d569 *R/gg_slackr.R +1a37aa44b648951506253399be0fd244 *R/save_slackr.R +bd5a3bc2f5cb971c7273e1a1228c6166 *R/slackr-package.R +7d40024f0689f05ef570b20db1950a84 *R/slackr.R +113f83579ab61ec2320720cce2de82fa *R/slackr_bot.r +611e6441d96bb594532631866c8e80ab *R/slackr_setup.r +ca034113c824f36061740c6f2c54add4 *R/slackr_upload.R +530c0da41ae4c4ecf07b369a4ed2cb3d *R/slackr_utils.R +10e2455ea05a41548e543730bdf9a33e *R/text_slackr.r +4703021416c0046bf4c51800145bab98 *R/zcamels.r +18379754819090c6b357b43da606aa05 *README.md +8b66aec20e8d1a0f2137b62a050ad69c *man/dev_slackr.Rd +7b8ebeb2699383035e66cee4c2b29aef *man/ggslackr.Rd +7a841c4cee2a2a1cb5545764ed778be0 *man/save_slackr.Rd +ba8d7b518394b760db0dd3df2ba8888c *man/slackr-package.Rd +54c9ebbfc32f6155df13e3c62dd9e9c9 *man/slackr.Rd +565c444aca4e9b7abdb3abd7f972bbd7 *man/slackr_bot.Rd +cfe1c3dc84a5ecda9f0bc3f8e11a1c0d *man/slackr_channels.Rd +efd55e6a0844e9b138b66e99731ccffa *man/slackr_chtrans.Rd +932d89f7fd39a8b7fedc8101d4b73dc3 *man/slackr_groups.Rd +ffd2f335e2730af94193efc30c4bb298 *man/slackr_ims.Rd +bf2815655f7722a2833279f9852a072f *man/slackr_msg.Rd +29851c443cfbd16c7d827c7c4befa340 *man/slackr_setup.Rd +78e840d767cbae3fc75e9bb31c56f506 *man/slackr_upload.Rd +19d667ed1109467e71f1e1814a1c122a *man/slackr_users.Rd +0a894fff9759890ffd7ea4e82daf35d4 *man/text_slackr.Rd eb66fd4a4ae63b00f49b70a1a7e91978 *tests/test-all.R ad09493096650ca0f03340c67afdaf8d *tests/testthat/test-slackr.R +f9e956145ff0e40709fae1fe7e2ae8a5 *tests/testthat/test-textslackr.R diff --git a/NAMESPACE b/NAMESPACE index 19f2b96..e8dcd9b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,17 +1,41 @@ -# Generated by roxygen2 (4.0.1.99): do not edit by hand +# Generated by roxygen2: do not edit by hand export(dev.slackr) +export(dev_slackr) export(ggslackr) export(save.slackr) +export(save_slackr) export(slackr) export(slackrBot) export(slackrChTrans) export(slackrChannels) +export(slackrChtrans) export(slackrGroups) +export(slackrIms) +export(slackrMsg) export(slackrSetup) export(slackrUpload) export(slackrUsers) -import(data.table) +export(slackr_bot) +export(slackr_channels) +export(slackr_chtrans) +export(slackr_groups) +export(slackr_ims) +export(slackr_msg) +export(slackr_setup) +export(slackr_upload) +export(slackr_users) +export(textSlackr) +export(text_slackr) import(ggplot2) import(httr) -import(jsonlite) +import(methods) +import(utils) +importFrom(dplyr,bind_rows) +importFrom(dplyr,data_frame) +importFrom(dplyr,left_join) +importFrom(grDevices,dev.copy) +importFrom(grDevices,dev.off) +importFrom(grDevices,png) +importFrom(graphics,par) +importFrom(jsonlite,toJSON) diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..c6b5326 --- /dev/null +++ b/NEWS @@ -0,0 +1,5 @@ +## 1.4.1 +* There is a new `slackr_msg()` function which behaves slightly differently than `text_slackr()` +* 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. \ No newline at end of file diff --git a/R/dev_slackr.R b/R/dev_slackr.R new file mode 100644 index 0000000..909c07d --- /dev/null +++ b/R/dev_slackr.R @@ -0,0 +1,50 @@ +#' Send the graphics contents of the current device to a Slack channel +#' +#' \code{dev.slackr} sends the graphics contents of the current device to the +#' specified Slack channel. +#' +#' @param channels list of channels to post image to +#' @param ... other arguments passed into png device +#' @param api_token the slack.com full API token (chr) +#' @param file prefix for filenames (defaults to \code{plot}) +#' @return \code{httr} response object from \code{POST} call +#' @seealso \code{\link{slackrSetup}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} +#' @author Konrad Karczewski [ctb], Bob Rudis [aut] +#' @note You can pass in \code{add_user=TRUE} as part of the \code{...} parameters and the Slack API +#' will post the message as your logged-in user account (this will override anything set in +#' \code{username}) +#' @references \url{https://github.com/hrbrmstr/slackr/pull/12/files} +#' @rdname dev_slackr +#' @examples +#' \dontrun{ +#' slackr_setup() +#' +#' # base +#' library(maps) +#' map("usa") +#' dev_slackr("#results", filename='map') +#' +#' # base +#' barplot(VADeaths) +#' dev_slackr("@@jayjacobs") +#' } +#' @export +dev_slackr <- function(channels=Sys.getenv("SLACK_CHANNEL"), ..., + api_token=Sys.getenv("SLACK_API_TOKEN"), + file="plot") { + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + ftmp <- tempfile(file, fileext=".png") + dev.copy(png, file=ftmp, ...) + dev.off() + + modchan <- slackrChTrans(channels) + + POST(url="https://slack.com/api/files.upload", + add_headers(`Content-Type`="multipart/form-data"), + body=list( file=upload_file(ftmp), token=api_token, channels=modchan)) + +} diff --git a/R/gg_slackr.R b/R/gg_slackr.R new file mode 100644 index 0000000..b2e7740 --- /dev/null +++ b/R/gg_slackr.R @@ -0,0 +1,66 @@ +#' Post a ggplot to a Slack channel +#' +#' Unlike the \code{\link{dev_slackr}} function, this one takes a \code{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 units units for width and height when either one is explicitly specified +#' (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 api_token the slack.com full API token (chr) +#' @param file prefix for filenames (defaults to \code{ggplot}) +#' @param ... other arguments passed to graphics device +#' @note You need to setup a full API token (i.e. not a webhook & not OAuth) for this to work +#' Also, uou can pass in \code{add_user=TRUE} as part of the \code{...} +#' parameters and the Slack API will post the message as your logged-in user +#' account (this will override anything set in \code{username}) +#' @return \code{httr} response object (invisibly) +#' @examples +#' \dontrun{ +#' slackr_setup() +#' ggslackr(qplot(mpg, wt, data=mtcars)) +#' } +#' @export +ggslackr <- function(plot=last_plot(), + channels=Sys.getenv("SLACK_CHANNEL"), + scale=1, + width=par("din")[1], + height=par("din")[2], + units=c("in", "cm", "mm"), + dpi=300, + limitsize=TRUE, + api_token=Sys.getenv("SLACK_API_TOKEN"), + file="ggplot", + ...) { + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + ftmp <- tempfile(file, fileext=".png") + ggsave(filename=ftmp, + plot=plot, + scale=scale, + width=width, + height=height, + units=units, + dpi=dpi, + limitsize=limitsize, ...) + + modchan <- slackr_chtrans(channels) + + res <- POST(url="https://slack.com/api/files.upload", + add_headers(`Content-Type`="multipart/form-data"), + body=list(file=upload_file(ftmp), + token=api_token, + channels=modchan)) + + invisible(res) + +} diff --git a/R/save_slackr.R b/R/save_slackr.R new file mode 100644 index 0000000..3f2b76b --- /dev/null +++ b/R/save_slackr.R @@ -0,0 +1,50 @@ +#' Save R objects to an RData file on Slack +#' +#' \code{save_slackr} enables you upload R objects (as an R data file) +#' to Slack and (optionally) post them to one or more channels +#' (if \code{channels} is not empty). +#' +#' @param ... objects to store in the R data file +#' @param channels slack.com channels to save to (optional) +#' @param file filename (without extension) to use +#' @param api_token full API token +#' @rdname save_slackr +#' @note You can pass in \code{add_user=TRUE} as part of the \code{...} parameters and the Slack API +#' will post the message as your logged-in user account (this will override anything set in +#' \code{username}) +#' @return \code{httr} response object from \code{POST} call +#' @seealso \code{\link{slackr_setup}}, \code{\link{dev_slackr}}, \code{\link{slackr_upload}} +#' @export +#' @examples \dontrun{ +#' slackr_setup() +#' save_slackr(mtcars, channels="#slackr", file="mtcars") +#' } +save_slackr <- function(..., channels="", + file="slackr", + api_token=Sys.getenv("SLACK_API_TOKEN")) { + + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + ftmp <- tempfile(file, fileext=".rda") + save(..., file=ftmp) + + on.exit(unlink(ftmp), add=TRUE) + + modchan <- slackr_chtrans(channels) + if (length(modchan) == 0) modchan <- "" + + res <- POST(url="https://slack.com/api/files.upload", + add_headers(`Content-Type`="multipart/form-data"), + body=list(file=upload_file(ftmp), + filename=sprintf("%s.rda", file), + token=api_token, + channels=modchan)) + + stop_for_status() + + invisible(res) + +} diff --git a/R/slackr-package.R b/R/slackr-package.R index 233ce28..c83e535 100644 --- a/R/slackr-package.R +++ b/R/slackr-package.R @@ -1,22 +1,40 @@ #' slackr - A package to work with the Slack.com API #' +#' Mega thanks to: +#' +#' \itemize{ +#' \item \href{https://github.com/jayjacobs}{Jay Jacobs} +#' \item \href{https://github.com/davidski}{David Severski} +#' \item \href{https://github.com/qsweber}{Quinn Weber} +#' \item \href{https://github.com/konradjk}{Konrad Karczewski} +#' \item \href{https://github.com/eniles}{Ed Niles} +#' \item \href{https://github.com/rsaporta}{Rick Saporta} +#' } +#' +#' for their contributions to the package! +#' #' Check out: #' \itemize{ #' \item the \link{slackr} function to send messages, -#' \item the \link{dev.slackr} function to send images (copies from current graphics device) +#' \item the \link{dev_slackr} function to send images (copies from current graphics device) #' \item the \link{ggslackr} function to send ggplot objects (without plotting to a device first) -#' \item the \link{save.slackr} function to send R objects (as RData files) -#' \item the \link{slackrUpload} function to send files +#' \item the \link{save_slackr} function to send R objects (as RData files) +#' \item the \link{slackr_upload} function to send files #' } #' #' @name slackr-package #' @title slackr-package #' @docType package #' @author Bob Rudis (@@hrbrmstr) -#' @import httr jsonlite data.table ggplot2 +#' @import httr ggplot2 utils methods +#' @importFrom dplyr data_frame left_join bind_rows +#' @importFrom jsonlite toJSON +#' @import utils +#' @importFrom grDevices dev.copy dev.off png +#' @importFrom graphics par #' @examples #' \dontrun{ -#' slackrSetup() +#' slackr_setup() #' #' # send objects #' slackr("iris info", head(iris), str(iris)) diff --git a/R/slackr.R b/R/slackr.R index 13e5e36..94959ff 100644 --- a/R/slackr.R +++ b/R/slackr.R @@ -1,154 +1,119 @@ -#' Setup environment variables for \code{slack.com} API +#' Output R expressions to a Slack channel/user #' -#' Initialize all the environment variables \link{slackr} will need to use to -#' work properly. -#' -#' By default, \code{slackr} (and other functions) will use the \code{#general} room and a username -#' of \code{slackr()} with no emoji and the default \url{slack.com} API prefix URL. You -#' still need to provide the webhook API token in \code{token} for anyting to work. -#' Failure to call this function before calling \code{slackr()} will result in a -#' message to do so. -#' -#' If a valid file is found at the locaiton pointed to by \code{config_file}, the -#' values there will be used. The fields should be specified as such in the file: \cr -#' \cr -#' \code{ token: yourTokenCode} \cr -#' \code{ channel: #general} \cr -#' \code{ username: slackr} \cr -#' \code{ icon_emoji:} \cr -#' \code{ incoming_webhook_url: https://yourgroup.slack.com/services/hooks/incoming-webhook?} \cr \cr -#' @param channel default channel to send the output to (chr) defaults to \code{#general} -#' @param username the username output will appear from (chr) defaults to \code{slackr} -#' @param icon_emoji which emoji picture to use (chr) defaults to none (can be left blank in config file as well) -#' @param token the \url{slack.com} webhook API token string (chr) defaults to none -#' @param incoming_webhook_url the slack.com URL prefix to use (chr) defaults to none -#' @param api_token the slack.com full API token (chr) -#' @param config_file a configuration file (DCF) - see \link{read.dcf} - format with the config values. -#' @param echo display the configuraiton variables (bool) initially \code{FALSE} -#' @note You need a \url{slack.com} account and will also need to setup an incoming webhook and full API tokens: \url{https://api.slack.com/} -#' @seealso \code{\link{slackr}}, \code{\link{dev.slackr}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} -#' @examples -#' \dontrun{ -#' # reads from default file -#' slackrSetup() -#' -#' # reads from alternate config -#' slackrSetup(config_file="/path/to/my/slackrconfig) -#' -#' # the hard way -#' slackrSetup(channel="#code", token="mytoken", -#' url_prefix="http://myslack.slack.com/services/hooks/incoming-webhook?") -#' } -#' @export -slackrSetup <- function(channel="#general", username="slackr", - icon_emoji="", token="", incoming_webhook_url="", - api_token="", config_file="~/.slackr", echo=FALSE) { - - if (file.exists(config_file)) { - - config <- read.dcf(config_file, - fields=c("token", "channel", "icon_emoji", - "username", "incoming_webhook_url", "api_token")) - - Sys.setenv(SLACK_CHANNEL=config[,"channel"]) - Sys.setenv(SLACK_USERNAME=config[,"username"]) - Sys.setenv(SLACK_ICON_EMOJI=config[,"icon_emoji"]) - Sys.setenv(SLACK_TOKEN=config[,"token"]) - Sys.setenv(SLACK_INCOMING_URL_PREFIX=config[,"incoming_webhook_url"]) - Sys.setenv(SLACK_API_TOKEN=config[,"api_token"]) - - } else { - - Sys.setenv(SLACK_CHANNEL=channel) - Sys.setenv(SLACK_USERNAME=username) - Sys.setenv(SLACK_ICON_EMOJI=icon_emoji) - Sys.setenv(SLACK_TOKEN=token) - Sys.setenv(SLACK_INCOMING_URL_PREFIX=incoming_webhook_url) - Sys.setenv(SLACK_API_TOKEN=api_token) - - } - - if (echo) { - print(Sys.getenv(c("SLACK_CHANNEL", "SLACK_USERNAME", - "SLACK_ICON_EMOJI", "SLACK_TOKEN", - "SLACK_INCOMING_URL_PREFIX", "SLACK_API_TOKEN"))) - } - -} - -#' Output R expressions to a \code{slack.com} channel/user (as \code{slackbot}) -#' -#' Takes an \code{expr}, evaluates it and sends the output to a \url{slack.com} +#' Takes an \code{expr}, evaluates it and sends the output to a Slack #' chat destination. Useful for logging, messaging on long compute tasks or #' general information sharing. #' #' By default, everyting but \code{expr} will be looked for in a "\code{SLACK_}" #' environment variable. You can override or just specify these values directly instead, -#' but it's probably better to call \link{slackrSetup} first. -#' -#' This function uses the incoming webhook API and posts user messages as \code{slackbot} +#' but it's probably better to call \code{\link{slackr_setup}} first. #' #' @param ... expressions to be sent to Slack.com #' @param channel which channel to post the message to (chr) #' @param username what user should the bot be named as (chr) #' @param icon_emoji what emoji to use (chr) \code{""} will mean use the default -#' @param incoming_webhook_url which \url{slack.com} API endpoint URL to use -#' @param token your webhook API token -#' @note You need a \url{slack.com} account and will also need to setup an incoming webhook: \url{https://api.slack.com/} -#' @seealso \code{\link{slackrSetup}}, \code{\link{slackr}}, \code{\link{dev.slackr}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} +#' @param api_token your full slack.com API token +#' @note You need a \url{https://www.slack.com} account and will also need to +#' setup an API token \url{https://api.slack.com/} +#' Also, you can pass in \code{add_user=TRUE} as part of the \code{...} +#' parameters and the Slack API will post the message as your logged-in +#' user account (this will override anything set in \code{username}) +#' @seealso \code{\link{slackr_setup}}, \code{\link{slackr_bot}}, \code{\link{dev_slackr}}, +#' \code{\link{save_slackr}}, \code{\link{slackr_upload}} #' @examples #' \dontrun{ -#' slackrSetup() +#' slackr_setup() #' slackr("iris info", head(iris), str(iris)) #' } #' @export -slackrBot <- function(..., +slackr <- function(..., channel=Sys.getenv("SLACK_CHANNEL"), username=Sys.getenv("SLACK_USERNAME"), icon_emoji=Sys.getenv("SLACK_ICON_EMOJI"), - incoming_webhook_url=Sys.getenv("SLACK_INCOMING_URL_PREFIX"), - token=Sys.getenv("SLACK_TOKEN")) { + api_token=Sys.getenv("SLACK_API_TOKEN")) { - if (incoming_webhook_url == "" | token == "") { - stop("No URL prefix and/or token specified. Did you forget to call slackrSetup()?", call. = FALSE) + if (api_token == "") { + stop("No token specified. Did you forget to call slackr_setup()?", call. = FALSE) } - if (icon_emoji != "") { icon_emoji <- sprintf(', "icon_emoji": "%s"', icon_emoji) } - resp_ret <- "" if (!missing(...)) { - input_list <- as.list(substitute(list(...)))[-1L] - - for(i in 1:length(input_list)) { - - expr <- input_list[[i]] - - if (class(expr) == "call") { - - expr_text <- sprintf("> %s", deparse(expr)) - - data <- capture.output(eval(expr)) - data <- paste0(data, collapse="\n") - data <- sprintf("%s\n%s", expr_text, data) + # mimics capture.output + + # get the arglist + args <- substitute(list(...))[-1L] + + # setup in-memory sink + rval <- NULL + fil <- textConnection("rval", "w", local = TRUE) + + sink(fil) + on.exit({ + sink() + close(fil) + }) + + # where we'll need to eval expressions + pf <- parent.frame() + + # how we'll eval expressions + evalVis <- function(expr) withVisible(eval(expr, pf)) + + # for each expression + for (i in seq_along(args)) { + + expr <- args[[i]] + + # do something, note all the newlines...Slack ``` needs them + tmp <- switch(mode(expr), + # if it's actually an expresison, iterate over it + expression = { + cat(sprintf("> %s\n", deparse(expr))) + lapply(expr, evalVis) + }, + # if it's a call or a name, eval, printing run output as if in console + call = , + name = { + cat(sprintf("> %s\n", deparse(expr))) + list(evalVis(expr)) + }, + # if pretty much anything else (i.e. a bare value) just output it + integer = , + double = , + complex = , + raw = , + logical = , + numeric = cat(sprintf("%s\n\n", as.character(expr))), + character = cat(sprintf("%s\n\n", expr)), + stop("mode of argument not handled at present by slackr")) + + for (item in tmp) if (item$visible) { print(item$value); cat("\n") } + } - } else { - data <- as.character(expr) - } + on.exit() - output <- gsub('^\"|\"$', "", toJSON(data, simplifyVector=TRUE, flatten=TRUE, auto_unbox=TRUE)) + sink() + close(fil) - resp <- POST(url=paste0(incoming_webhook_url, "token=", token), - add_headers(`Content-Type`="application/x-www-form-urlencoded", `Accept`="*/*"), - body=URLencode(sprintf('payload={"channel": "%s", "username": "%s", "text": "```%s```"%s}', - channel, username, output, icon_emoji))) + # combined all of them (rval is a character vector) + output <- paste0(rval, collapse="\n") - warn_for_status(resp) + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) - if (resp$status_code > 200) { print(str(expr))} + resp <- POST(url="https://slack.com/api/chat.postMessage", + body=list(token=api_token, + channel=slackr_chtrans(channel), + username=username, + icon_emoji=icon_emoji, + as_user=TRUE, + text=sprintf("```%s```", output), + link_names=1)) - } + warn_for_status(resp) } @@ -156,316 +121,67 @@ slackrBot <- function(..., } - -#' Output R expressions to a \code{slack.com} channel/user +#' Output R expressions to a Slack channel/user #' -#' Takes an \code{expr}, evaluates it and sends the output to a \url{slack.com} +#' Takes an \code{expr}, evaluates it and sends the output to a Slack #' chat destination. Useful for logging, messaging on long compute tasks or #' general information sharing. #' #' By default, everyting but \code{expr} will be looked for in a "\code{SLACK_}" #' environment variable. You can override or just specify these values directly instead, -#' but it's probably better to call \link{slackrSetup} first. +#' but it's probably better to call \code{\link{slackrSetup}} first. #' -#' @param ... expressions to be sent to Slack.com +#' @param txt text message to send to Slack. If a character vector of length > 1 +#' is passed in, they will be combined and separated by newlines. #' @param channel which channel to post the message to (chr) #' @param username what user should the bot be named as (chr) #' @param icon_emoji what emoji to use (chr) \code{""} will mean use the default #' @param api_token your full slack.com API token -#' @note You need a \url{slack.com} account and will also need to setup an API token \url{https://api.slack.com/} -#' @seealso \code{\link{slackrSetup}}, \code{\link{slackrBot}}, \code{\link{dev.slackr}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} +#' @param ... other arguments passed to the Slack API \code{chat.postMessage} call +#' @note You need a \url{https://www.slack.com} account and will also need to +#' setup an API token \url{https://api.slack.com/} +#' Also, you can pass in \code{add_user=TRUE} as part of the \code{...} +#' parameters and the Slack API will post the message as your logged-in +#' user account (this will override anything set in \code{username}) +#' @seealso \code{\link{slackr_setup}}, \code{\link{slackr_bot}}, \code{\link{dev_slackr}}, +#' \code{\link{save_slackr}}, \code{\link{slackr_upload}} #' @examples #' \dontrun{ -#' slackrSetup() -#' slackr("iris info", head(iris), str(iris)) +#' slackr_setup() +#' slackr_msg("Hi") #' } #' @export -slackr <- function(..., - channel=Sys.getenv("SLACK_CHANNEL"), - username=Sys.getenv("SLACK_USERNAME"), - icon_emoji=Sys.getenv("SLACK_ICON_EMOJI"), - api_token=Sys.getenv("SLACK_API_TOKEN")) { +slackr_msg <- function(txt="", + channel=Sys.getenv("SLACK_CHANNEL"), + username=Sys.getenv("SLACK_USERNAME"), + icon_emoji=Sys.getenv("SLACK_ICON_EMOJI"), + api_token=Sys.getenv("SLACK_API_TOKEN"), + ...) { if (api_token == "") { - stop("No token specified. Did you forget to call slackrSetup()?", call. = FALSE) + stop("No token specified. Did you forget to call slackr_setup()?", call. = FALSE) } if (icon_emoji != "") { icon_emoji <- sprintf(', "icon_emoji": "%s"', icon_emoji) } - resp_ret <- "" - - if (!missing(...)) { - - input_list <- as.list(substitute(list(...)))[-1L] - - for(i in 1:length(input_list)) { - - expr <- input_list[[i]] - - if (class(expr) == "call") { - - expr_text <- sprintf("> %s", deparse(expr)) - - data <- capture.output(eval(expr)) - data <- paste0(data, collapse="\n") - data <- sprintf("%s\n%s", expr_text, data) - - } else { - data <- as.character(expr) - } - - output <- data + output <- paste0(txt, collapse="\n\n") - resp <- POST(url="https://slack.com/api/chat.postMessage", - body=list(token=api_token, channel=channel, - username=username, icon_emoji=icon_emoji, - text=sprintf("```%s```", output), link_names=1)) + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) - warn_for_status(resp) + resp <- POST(url="https://slack.com/api/chat.postMessage", + body=list(token=api_token, + channel=slackr_chtrans(channel), + username=username, + icon_emoji=icon_emoji, + text=output, + as_user=TRUE, + link_names=1, + ...)) - if (resp$status_code > 200) { print(str(expr))} - - } - - } + warn_for_status(resp) return(invisible()) } - -#' Send the graphics contents of the current device to a \code{slack.com} channel -#' -#' \code{dev.slackr} sends the graphics contents of the current device to the specified \code{slack.com} channel. -#' This requires setting up a full API token (i.e. not a webhook & not OAuth) for this to work. -#' -#' @param channels list of channels to post image to -#' @param ... other arguments passed into png device -#' @param api_token the slack.com full API token (chr) -#' @return \code{httr} response object from \code{POST} call -#' @seealso \code{\link{slackrSetup}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} -#' @examples -#' \dontrun{ -#' slackrSetup() -#' -#' # ggplot -#' library(ggplot2) -#' qplot(mpg, wt, data=mtcars) -#' dev.slackr("#results") -#' -#' # base -#' barplot(VADeaths) -#' dev.slackr("@@jayjacobs") -#' } -#' @export -dev.slackr <- function(channels=Sys.getenv("SLACK_CHANNEL"), ..., - api_token=Sys.getenv("SLACK_API_TOKEN")) { - - Sys.setlocale('LC_ALL','C') - - ftmp <- tempfile("plot", fileext=".png") - dev.copy(png, file=ftmp, ...) - dev.off() - - modchan <- slackrChTrans(channels) - - POST(url="https://slack.com/api/files.upload", - add_headers(`Content-Type`="multipart/form-data"), - body=list( file=upload_file(ftmp), token=api_token, channels=modchan)) - -} - -#' Post a ggplot to a \url{slack.com} channel -#' -#' Unlike the \code{\link{dev.slackr}} function, this one takes a \code{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 units units for width and height when either one is explicitly specified (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 api_token the slack.com full API token (chr) -#' @param ... other arguments passed to graphics device -#' @note You need to setup a full API token (i.e. not a webhook & not OAuth) for this to work -#' @return \code{httr} response object -#' @examples -#' \dontrun{ -#' slackrSetup() -#' ggslackr(qplot(mpg, wt, data=mtcars)) -#' } -#' @export -ggslackr <- function(plot=last_plot(), channels=Sys.getenv("SLACK_CHANNEL"), scale=1, width=par("din")[1], height=par("din")[2], - units=c("in", "cm", "mm"), dpi=300, limitsize=TRUE, api_token=Sys.getenv("SLACK_API_TOKEN"), ...) { - - Sys.setlocale('LC_ALL','C') - ftmp <- tempfile("ggplot", fileext=".png") - ggsave(filename=ftmp, plot=plot, scale=scale, width=width, height=height, units=units, dpi=dpi, limitsize=limitsize, ...) - - modchan <- slackrChTrans(channels) - - POST(url="https://slack.com/api/files.upload", - add_headers(`Content-Type`="multipart/form-data"), - body=list( file=upload_file(ftmp), token=api_token, channels=modchan)) - -} - - -#' Save R objects to an RData file on \code{slack.com} -#' -#' \code{save.slackr} enables you upload R objects (as an R data file) -#' to \code{slack.com} and (optionally) post them to one or more channels -#' (if \code{channels} is not empty). -#' -#' @param ... objects to store in the R data file -#' @param channels slack.com channels to save to (optional) -#' @param file filename (without extension) to use -#' @param api_token full API token -#' @return \code{httr} response object from \code{POST} call -#' @seealso \code{\link{slackrSetup}}, \code{\link{dev.slackr}}, \code{\link{slackrUpload}} -#' @export -save.slackr <- function(..., channels="", - file="slackr", - api_token=Sys.getenv("SLACK_API_TOKEN")) { - - - Sys.setlocale('LC_ALL','C') - - ftmp <- tempfile(file, fileext=".rda") - save(..., file=ftmp) - - modchan <- slackrChTrans(channels) - - POST(url="https://slack.com/api/files.upload", - add_headers(`Content-Type`="multipart/form-data"), - body=list(file=upload_file(ftmp), filename=sprintf("%s.rda", file), - token=api_token, channels=modchan)) - -} - -#' Send a file to \code{slack.com} -#' -#' \code{slackrUoload} enables you upload files to \code{slack.com} and -#' (optionally) post them to one or more channels (if \code{channels} is not empty). -#' -#' @param filename path to file -#' @param title title on slack (optional - defaults to filename) -#' @param initial_comment comment for file on slack (optional - defaults to filename) -#' @param channels slack.com channels to save to (optional) -#' @param api_token full API token -#' @return \code{httr} response object from \code{POST} call -#' @seealso \code{\link{slackrSetup}}, \code{\link{dev.slackr}}, \code{\link{save.slackr}} -#' @export -slackrUpload <- function(filename, title=basename(filename), - initial_comment=basename(filename), - channels="", api_token=Sys.getenv("SLACK_API_TOKEN")) { - - f_path <- path.expand(filename) - - if (file.exists(f_path)) { - - f_name <- basename(f_path) - - Sys.setlocale('LC_ALL','C') - - modchan <- slackrChTrans(channels) - - POST(url="https://slack.com/api/files.upload", - add_headers(`Content-Type`="multipart/form-data"), - body=list( file=upload_file(f_path), filename=f_name, - title=title, initial_comment=initial_comment, - token=api_token, channels=modchan)) - - } - -} - -#' Translate vector of channel names to channel ID's for API -#' -#' Given a vector of one or more channel names, it will retrieve list of -#' active channels and try to replace channels that begin with "\code{#}" or "\code{@@}" -#' with the channel ID for that channel. Also incorporates groups. -#' -#' @param channels vector of channel names to parse -#' @param api_token the slack.com full API token (chr) -#' @note Renamed from \code{slackr_chtrans} -#' @return character vector - original channel list with \code{#} or \code{@@} channels replaced with ID's. -#' @export -slackrChTrans <- function(channels, api_token=Sys.getenv("SLACK_API_TOKEN")) { - - chan <- slackrChannels(api_token) - users <- slackrUsers(api_token) - groups <- slackrGroups(api_token) - - chan$name <- sprintf("#%s", chan$name) - users$name <- sprintf("@%s", users$name) - - chan_list <- rbind(chan[,1:2,with=FALSE], - users[,1:2,with=FALSE], - groups[,1:2,with=FALSE]) - - chan_xref <- merge(data.frame(name=channels), chan_list, all.x=TRUE) - - ifelse(is.na(chan_xref$id), - as.character(chan_xref$name), - as.character(chan_xref$id)) - -} - -#' Get a data frame of slack.com users -#' -#' need to setup a full API token (i.e. not a webhook & not OAuth) for this to work -#' -#' @param api_token the slack.com full API token (chr) -#' @return data.table of users -#' @export -slackrUsers <- function(api_token=Sys.getenv("SLACK_API_TOKEN")) { - - Sys.setlocale('LC_ALL','C') - tmp <- POST("https://slack.com/api/users.list", body=list(token=api_token)) - tmp_p <- content(tmp, as="parsed") - rbindlist(lapply(tmp_p$members, function(x) { - data.frame(id=x$id, name=x$name, real_name=x$real_name) - }) ) - -} - -#' Get a data frame of slack.com channels -#' -#' need to setup a full API token (i.e. not a webhook & not OAuth) for this to work -#' -#' @param api_token the slack.com full API token (chr) -#' @return data.table of channels -#' @note Renamed from \code{slackr_channels} -#' @export -slackrChannels <- function(api_token=Sys.getenv("SLACK_API_TOKEN")) { - - Sys.setlocale('LC_ALL','C') - tmp <- POST("https://slack.com/api/channels.list", body=list(token=api_token)) - tmp_p <- content(tmp, as="parsed") - rbindlist(lapply(tmp_p$channels, function(x) { - data.frame(id=x$id, name=x$name, is_member=x$is_member) - }) ) - -} - -#' Get a data frame of slack.com groups -#' -#' need to setup a full API token (i.e. not a webhook & not OAuth) for this to work -#' -#' @param api_token the slack.com full API token (chr) -#' @return data.table of channels -#' @export -slackrGroups <- function(api_token=Sys.getenv("SLACK_API_TOKEN")) { - - Sys.setlocale('LC_ALL','C') - tmp <- POST("https://slack.com/api/groups.list", body=list(token=api_token)) - tmp_p <- content(tmp, as="parsed") - rbindlist(lapply(tmp_p$groups, function(x) { - data.frame(id=x$id, name=x$name, is_archived=x$is_archived) - }) ) - -} - diff --git a/R/slackr_bot.r b/R/slackr_bot.r new file mode 100644 index 0000000..39f2928 --- /dev/null +++ b/R/slackr_bot.r @@ -0,0 +1,98 @@ +#' Send result of R expressions to a Slack channel via webhook API +#' +#' Takes an \code{expr}, evaluates it and sends the output to a Slack +#' chat destination via the webhook API. Useful for logging, messaging on long +#' compute tasks or general information sharing. +#' +#' By default, everyting but \code{expr} will be looked for in a "\code{SLACK_}" +#' environment variable. You can override or just specify these values directly +#' instead, but it's probably better to call \code{\link{slackr_setup}} first. +#' +#' This function uses the incoming webhook API. The webhook will have a default +#' channel, username, icon etc, but these can be overridden. +#' +#' @param ... expressions to be sent to Slack.com +#' @param channel which channel to post the message to (chr) +#' @param username what user should the bot be named as (chr) +#' @param icon_emoji what emoji to use (chr) \code{""} will mean use the default +#' @param incoming_webhook_url which \code{slack.com} API endpoint URL to use +#' (see section \bold{Webhook URLs} for details) +#' @note You need a \url{https://www.slack.com} account and will also need to +#' setup an incoming webhook: \url{https://api.slack.com/}. Old style webhooks are +#' no longer supported. +#' @seealso \code{\link{slackrSetup}}, \code{\link{slackr}}, +#' \code{\link{dev_slackr}}, \code{\link{save_slackr}}, +#' \code{\link{slackr_upload}} +#' @rdname slackr_bot +#' @section Webhook URLs: Webhook URLs look like: \itemize{ +#' +#' \item \code{https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX} +#' +#' } +#' +#' OLD STYLE WEBHOOKS ARE NO LONGER SUPPORTED +#' +#' @examples +#' \dontrun{ +#' slackr_setup() +#' slackr_bot("iris info", head(iris), str(iris)) +#' +#' # or directly +#' slackr_bot("Test message", username="slackr", channel="#random", +#' incoming_webhook_url="https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX") +#' } +#' @export +slackr_bot <- function(..., + channel=Sys.getenv("SLACK_CHANNEL"), + username=Sys.getenv("SLACK_USERNAME"), + icon_emoji=Sys.getenv("SLACK_ICON_EMOJI"), + incoming_webhook_url=Sys.getenv("SLACK_INCOMING_URL_PREFIX")) { + + if (incoming_webhook_url == "") { + stop("No incoming webhook URL specified. Did you forget to call slackr_setup()?", call. = FALSE) + } + + if (icon_emoji != "") { icon_emoji <- sprintf(', "icon_emoji": "%s"', icon_emoji) } + + resp_ret <- "" + + if (!missing(...)) { + + input_list <- as.list(substitute(list(...)))[-1L] + + for(i in 1:length(input_list)) { + + expr <- input_list[[i]] + + if (class(expr) == "call") { + + expr_text <- sprintf("> %s", deparse(expr)) + + data <- capture.output(eval(expr)) + data <- paste0(data, collapse="\n") + data <- sprintf("%s\n%s", expr_text, data) + + } else { + data <- as.character(expr) + } + + output <- gsub('^\"|\"$', "", toJSON(data, simplifyVector=TRUE, flatten=TRUE, auto_unbox=TRUE)) + + resp <- POST(url=incoming_webhook_url, + encode="form", + add_headers(`Content-Type`="application/x-www-form-urlencoded", + `Accept`="*/*"), + body=URLencode(sprintf('payload={"channel": "%s", "username": "%s", "text": "```%s```"%s}', + channel, username, output, icon_emoji))) + + warn_for_status(resp) + + if (resp$status_code > 200) { print(str(expr))} + + } + + } + + return(invisible()) + +} diff --git a/R/slackr_setup.r b/R/slackr_setup.r new file mode 100644 index 0000000..3747c02 --- /dev/null +++ b/R/slackr_setup.r @@ -0,0 +1,95 @@ +#' Setup environment variables for Slack API access +#' +#' Initialize all the environment variables \code{\link{slackr}} will need to use to +#' work properly. +#' +#' By default, \code{\link{slackr}} (and other functions) will use the \code{#general} +#' room and a username of \code{slackr()} with no emoji. +#' +#' If a valid file is found at the locaiton pointed to by \code{config_file}, the +#' values there will be used. The fields should be specified as such in the file: +#' +#' \preformatted{ +#' api_token: YOUR_FULL_API_TOKEN +#' channel: #general +#' username: slackr +#' incoming_webhook_url: https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX +#' } +#' +#' @param channel default channel to send the output to (chr) defaults to \code{#general} +#' @param username the username output will appear from (chr) defaults to \code{slackr} +#' @param icon_emoji which emoji picture to use (chr) defaults to none (can be +#' left blank in config file as well) +#' @param incoming_webhook_url the slack.com URL prefix to use (chr) defaults to none +#' @param api_token the Slack full API token (chr) +#' @param config_file a configuration file (DCF) - see \link{read.dcf} - format +#' with the config values. +#' @param echo display the configuration variables (bool) initially \code{FALSE} +#' @note You need a \href{slack.com}{Slack} account and all your API URLs & tokens setup +#' to use this package. +#' @seealso \code{\link{slackr}}, \code{\link{dev_slackr}}, \code{\link{save_slackr}}, +#' \code{\link{slackr_upload}} +#' @rdname slackr_setup +#' @examples +#' \dontrun{ +#' # reads from default file (i.e. ~/.slackr) +#' slackr_setup() +#' +#' # reads from alternate config +#' slackr_setup(config_file="/path/to/my/slackrconfig) +#' +#' # the hard way +#' slackr_setup(channel="#code", +#' incoming_webhook_url="https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX") +#' } +#' @export +slackr_setup <- function(channel="#general", + username="slackr", + icon_emoji="", + incoming_webhook_url="", + api_token="", + config_file="~/.slackr", + echo=FALSE) { + + if (file.exists(config_file)) { + + config <- read.dcf(config_file, + fields=c("channel", "icon_emoji", + "username", "incoming_webhook_url", "api_token")) + + Sys.setenv(SLACK_CHANNEL=config[,"channel"]) + Sys.setenv(SLACK_USERNAME=config[,"username"]) + Sys.setenv(SLACK_ICON_EMOJI=config[,"icon_emoji"]) + Sys.setenv(SLACK_INCOMING_URL_PREFIX=config[,"incoming_webhook_url"]) + Sys.setenv(SLACK_API_TOKEN=config[,"api_token"]) + + } else { + + Sys.setenv(SLACK_CHANNEL=channel) + Sys.setenv(SLACK_USERNAME=username) + Sys.setenv(SLACK_ICON_EMOJI=icon_emoji) + Sys.setenv(SLACK_INCOMING_URL_PREFIX=incoming_webhook_url) + Sys.setenv(SLACK_API_TOKEN=api_token) + + } + + if (!grepl("?$", Sys.getenv("SLACK_INCOMING_URL_PREFIX"))) { + Sys.setenv(SLACK_INCOMING_URL_PREFIX=sprintf("%s?", config[,"incoming_webhook_url"])) + } + + if (length(Sys.getenv("SLACK_CHANNEL"))==0) { + Sys.setenv("SLACK_CHANNEL", "#general") + } + + if (length(Sys.getenv("SLACK_USERNAME"))==0) { + Sys.setenv("SLACK_USERNAME", "slackr") + } + + if (echo) { + print(toJSON(as.list(Sys.getenv(c("SLACK_CHANNEL", "SLACK_USERNAME", + "SLACK_ICON_EMOJI", + "SLACK_INCOMING_URL_PREFIX", "SLACK_API_TOKEN"))), + pretty=TRUE)) + } + +} diff --git a/R/slackr_upload.R b/R/slackr_upload.R new file mode 100644 index 0000000..ff46de1 --- /dev/null +++ b/R/slackr_upload.R @@ -0,0 +1,43 @@ +#' Send a file to Slack +#' +#' \code{slackrUpload} enables you upload files to Slack and +#' (optionally) post them to one or more channels (if \code{channels} is not empty). +#' +#' @rdname slackr_upload +#' @param filename path to file +#' @param title title on slack (optional - defaults to filename) +#' @param initial_comment comment for file on slack (optional - defaults to filename) +#' @param channels slack.com channels to save to (optional) +#' @param api_token full API token +#' @return \code{httr} response object from \code{POST} call (invisibly) +#' @author Quinn Weber [ctb], Bob Rudis [aut] +#' @references \url{https://github.com/hrbrmstr/slackr/pull/15/files} +#' @seealso \code{\link{slackr_setup}}, \code{\link{dev_slackr}}, \code{\link{save_slackr}} +#' @export +slackr_upload <- function(filename, title=basename(filename), + initial_comment=basename(filename), + channels="", api_token=Sys.getenv("SLACK_API_TOKEN")) { + + f_path <- path.expand(filename) + + if (file.exists(f_path)) { + + f_name <- basename(f_path) + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + modchan <- slackrChTrans(channels) + + res <- POST(url="https://slack.com/api/files.upload", + add_headers(`Content-Type`="multipart/form-data"), + body=list( file=upload_file(f_path), filename=f_name, + title=title, initial_comment=initial_comment, + token=api_token, channels=paste(modchan, collapse=","))) + + return(invisible(res)) + + } + +} diff --git a/R/slackr_utils.R b/R/slackr_utils.R new file mode 100644 index 0000000..6ead3fa --- /dev/null +++ b/R/slackr_utils.R @@ -0,0 +1,119 @@ +#' Translate vector of channel names to channel ID's for API +#' +#' Given a vector of one or more channel names, it will retrieve list of +#' active channels and try to replace channels that begin with "\code{#}" or "\code{@@}" +#' with the channel ID for that channel. Also incorporates groups. +#' +#' @param channels vector of channel names to parse +#' @param api_token the slack.com full API token (chr) +#' @rdname slackr_chtrans +#' @author Quinn Weber [ctb], Bob Rudis [aut] +#' @return character vector - original channel list with \code{#} or +#' \code{@@} channels replaced with ID's. +#' @export +slackr_chtrans <- function(channels, api_token=Sys.getenv("SLACK_API_TOKEN")) { + + chan <- slackr_channels(api_token) + users <- slackr_ims(api_token) + groups <- slackr_groups(api_token) + + chan$name <- sprintf("#%s", chan$name) + users$name <- sprintf("@%s", users$name) + + chan_list <- data_frame(id=character(0), name=character(0)) + + if (length(chan) > 0) { chan_list <- bind_rows(chan_list, chan[, c("id", "name")]) } + if (length(users) > 0) { chan_list <- bind_rows(chan_list, users[, c("id", "name")]) } + if (length(groups) > 0) { chan_list <- bind_rows(chan_list, groups[, c("id", "name")]) } + + chan_list <- dplyr::distinct(chan_list) + + chan_list <- data.frame(chan_list, stringsAsFactors=FALSE) + chan_xref <- chan_list[chan_list$name %in% channels, ] + + ifelse(is.na(chan_xref$id), + as.character(chan_xref$name), + as.character(chan_xref$id)) + +} + + +#' Get a data frame of Slack users +#' +#' @param api_token the Slack full API token (chr) +#' @return \code{data.frame} of users +#' @rdname slackr_users +#' @export +slackr_users <- function(api_token=Sys.getenv("SLACK_API_TOKEN")) { + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + tmp <- POST("https://slack.com/api/users.list", + body=list(token=api_token)) + stop_for_status(tmp) + members <- jsonlite::fromJSON(content(tmp, as="text"))$members + cols <- setdiff(colnames(members), "profile") + cbind.data.frame(members[,cols], members$profile, stringsAsFactors=FALSE) + +} + +#' Get a data frame of Slack channels +#' +#' @param api_token the Slack full API token (chr) +#' @return data.table of channels +#' @rdname slackr_channels +#' @export +slackr_channels <- function(api_token=Sys.getenv("SLACK_API_TOKEN")) { + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + tmp <- POST("https://slack.com/api/channels.list", + body=list(token=api_token)) + stop_for_status(tmp) + jsonlite::fromJSON(content(tmp, as="text"))$channels + +} + +#' Get a data frame of Slack groups +#' +#' @param api_token the Slackfull API token (chr) +#' @return \code{data.frame} of channels +#' @rdname slackr_groups +#' @export +slackr_groups <- function(api_token=Sys.getenv("SLACK_API_TOKEN")) { + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + tmp <- POST("https://slack.com/api/groups.list", + body=list(token=api_token)) + stop_for_status(tmp) + jsonlite::fromJSON(content(tmp, as="text"))$groups + +} + +#' Get a data frame of Slack IM ids +#' +#' @param api_token the Slack full API token (chr) +#' @rdname slackr_ims +#' @author Quinn Weber [aut], Bob Rudis [ctb] +#' @references \url{https://github.com/hrbrmstr/slackr/pull/13} +#' @return \code{data.frame} of im ids and user names +#' @export +slackr_ims <- function(api_token=Sys.getenv("SLACK_API_TOKEN")) { + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + tmp <- POST("https://slack.com/api/im.list", body=list(token=api_token)) + ims <- jsonlite::fromJSON(content(tmp, as="text"))$ims + users <- slackr_users(api_token) + dplyr::left_join(users, ims, by="id") + +} diff --git a/R/text_slackr.r b/R/text_slackr.r new file mode 100644 index 0000000..2f87292 --- /dev/null +++ b/R/text_slackr.r @@ -0,0 +1,65 @@ +#' Sends basic text to a slack channel. Calls the chat.postMessage method on the Slack Web API. +#' Information on this method can be found here: \url{https://api.slack.com/methods/chat.postMessage} +#' +#' @param text The character vector to be posted +#' @param ... Optional arguments such as: as_user, parse, unfurl_links, etc. +#' @param preformatted Should the text be sent as preformatted text. Defaults to TRUE +#' @param channel The name of the channels to which the DataTable should be sent. +#' Prepend channel names with a hashtag. Prepend private-groups with nothing. +#' Prepend direct messages with an @@ +#' @param username what user should the bot be named as (chr) +#' @param icon_emoji what emoji to use (chr) \code{""} will mean use the default +#' @param api_token your full slack.com API token +#' @return \code{httr} response object (invislbly) +#' @author Quinn Weber [aut], Bob Rudis [ctb] +#' @note You can pass in \code{add_user=TRUE} as part of the \code{...} parameters and the Slack API +#' will post the message as your logged-in user account (this will override anything set in +#' \code{username}) +#' @references \url{https://github.com/hrbrmstr/slackr/pull/11} +#' @seealso \url{https://api.slack.com/methods/chat.postMessage} +#' @rdname text_slackr +#' @examples +#' \dontrun{ +#' slackr_setup() +#' text_slackr('hello world', as_user=TRUE) +#' } +#' @export +text_slackr <- function(text, + ..., + preformatted=TRUE, + channel=Sys.getenv("SLACK_CHANNEL"), + username=Sys.getenv("SLACK_USERNAME"), + icon_emoji=Sys.getenv("SLACK_ICON_EMOJI"), + api_token=Sys.getenv("SLACK_API_TOKEN")) { + + if ( length(text) > 1 ) { stop("text must be a vector of length one") } + if ( !is.character(channel) | length(channel) > 1 ) { stop("channel must be a character vector of length one") } + if ( !is.logical(preformatted) | length(preformatted) > 1 ) { stop("preformatted must be a logical vector of length one") } + if ( !is.character(username) | length(username) > 1 ) { stop("username must be a character vector of length one") } + if ( !is.character(api_token) | length(api_token) > 1 ) { stop("api_token must be a character vector of length one") } + + text <- as.character(text) + + if ( preformatted ) { + if ( substr(text, 1, 3) != '```' ) { text <- paste0('```', text) } + if ( substr(text, nchar(text)-2, nchar(text)) != '```' ) { text <- paste0(text, '```') } + } + + loc <- Sys.getlocale('LC_CTYPE') + Sys.setlocale('LC_CTYPE','C') + on.exit(Sys.setlocale("LC_CTYPE", loc)) + + resp <- POST(url="https://slack.com/api/chat.postMessage", + body=list(token=api_token, + channel=channel, + username=username, + icon_emoji=icon_emoji, + text=text, + link_names=1, + ...)) + + warn_for_status(resp) + + return(invisible(resp)) + +} diff --git a/R/zcamels.r b/R/zcamels.r new file mode 100644 index 0000000..d191a07 --- /dev/null +++ b/R/zcamels.r @@ -0,0 +1,53 @@ +# CAMEL CASE ALL THE THINGS (for legacy support) + +#' @rdname dev_slackr +#' @export +dev.slackr <- dev_slackr + +#' @rdname save_slackr +#' @export +save.slackr <- save_slackr + +#' @rdname slackr_bot +#' @export +slackrBot <- slackr_bot + +#' @rdname slackr_chtrans +#' @export +slackrChtrans <- slackr_chtrans + +#' @rdname slackr_chtrans +#' @export +slackrChTrans <- slackr_chtrans + +#' @rdname slackr_channels +#' @export +slackrChannels <- slackr_channels + +#' @rdname slackr_groups +#' @export +slackrGroups <- slackr_groups + +#' @rdname slackr_ims +#' @export +slackrIms <- slackr_ims + +#' @rdname slackr_msg +#' @export +slackrMsg <- slackr_msg + +#' @rdname slackr_setup +#' @export +slackrSetup <- slackr_setup + +#' @rdname slackr_upload +#' @export +slackrUpload <- slackr_upload + +#' @rdname slackr_users +#' @export +slackrUsers <- slackr_users + +#' @rdname text_slackr +#' @export +textSlackr <- text_slackr diff --git a/README.md b/README.md new file mode 100644 index 0000000..5675b60 --- /dev/null +++ b/README.md @@ -0,0 +1,118 @@ + + +[![Project Status: Active - The project has reached a stable, usable state and is being actively developed.](http://www.repostatus.org/badges/0.1.0/active.svg)](http://www.repostatus.org/#active) ![downloads](http://cranlogs.r-pkg.org/badges/grand-total/slackr) [![CRAN\_Status\_Badge](http://www.r-pkg.org/badges/version/slackr)](http://cran.r-project.org/package=slackr) + +![](slackr.png) + +`slackr` - a package to send user messages & webhook API messages to Slack channels/users + +The `slackr` package contains functions that make it possible to interact with the Slack messaging platform. When you need to share information/data from R, rather than resort to copy/paste in e-mails or other services like Skype, you can use this package to send well-formatted output from multiple R objects and expressions to all teammates at the same time with little effort. You can also send images from the current graphics device, R objects (as R data files), and upload files. + +### BREAKING CHANGES + +Versions 1.4+ BREAK THINGS. + +Support has been removed for the "old style" incoming web hooks (see "Setup" below for the required incoming web hook URL format). + +The incoming webhook "token" is no longer required or used. + +### News + +- Version `1.4.0.9000` new `slackr_msg()` + many fixes and BREAKING CHANGES (see above) +- Version `1.3.1.9000` Removed `data.table` dependency (replaced with `dplyr`); added access to `im.list` () thx to PR from Quinn Weber +- Version `1.3.0.9000` Radically changed how `slackr` works. Functions have camelCase and under\_score versions +- Version `1.2.3` added more parameter error cheking, remobved the need for ending `?` on webhook URL and added defaults for missing setup parameters. +- Version `1.2.2` fixed [issue](https://github.com/hrbrmstr/slackr/issues/4) (bug in `1.2.1` fix) +- Version `1.2.1` fixed [issue](https://github.com/hrbrmstr/slackr/issues/3) when there are no private groups defined +- Version `1.2` re-introduced `ggslackr()` (first [CRAN version](http://cran.at.r-project.org/web/packages/slackr/index.html)) +- Version `1.1.1` fixed a bug in the new full API `slackr()` function +- Version `1.1` added graphics & files capability +- Version `1.0` released + +Many thanks to: + +- [Jay Jacobs](https://github.com/jayjacobs) +- [David Severski](https://github.com/davidski) +- [Quinn Weber](https://github.com/qsweber) +- [Konrad Karczewski](https://github.com/konradjk) +- [Ed Niles](https://github.com/eniles) +- [Rick Saporta](https://github.com/rsaporta) + +for their contributions to the package! + +The following functions are implemented: + +- `slackr_setup` : initialize necessary environment variables +- `slackr` : send stuff to Slack +- `slackr_bot` : send stuff to Slack using an incoming webhook URL +- `dev_slackr` : send the graphics contents of the current device to a to Slack channel +- `ggslackr` : send a ggplot object to a Slack channel (no existing device plot required, useful for scripts) +- `save_slackr` : save R objects to an RData file on Slack +- `slackr_upload` : upload any file to Slack +- `slackr_users` : get a data frame of Slack +- `slackr_channels` : get a data frame of Slack +- `slackr_groups` : get a data frame of Slack groups +- `text_slackr` : Send regular or preformatted messages to Slack +- `slackr_msg` : Slightly different version of `text_slackr()` + +### SETUP + +The `slackr_setup()` function will try to read setup values from a `~/.slackr` (you can change the default) configuration file, which may be easier and more secure than passing them in manually (plus, will allow you to have multiple slackr configs for multiple Slack.com teams). The file is in Debian Control File (DCF) format since it really doesn't need to be JSON and R has a handy `read.dcf()` function since that's what `DESCRIPTION` files are coded in. Here's the basic format for the configuration file: + + api_token: YOUR_FULL_API_TOKEN + channel: #general + username: slackr + incoming_webhook_url: https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX + +You can also change the default emoji icon (from the one you setup at integration creation time) with `icon_emoji`. + +### Installation + +``` r +# stable/CRAN +install.packages("slackr") + +# bleeding edge +devtools::install_github("hrbrmstr/slackr") +``` + +### Usage + +``` r +library(slackr) + +# current verison +packageVersion("slackr") +#> [1] '1.4.1' +``` + +``` r +slackrSetup(channel="#code", + incoming_webhook_url="https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX") + +slackr(str(iris)) + +# send images +library(ggplot2) +qplot(mpg, wt, data=mtcars) +dev.slackr("#results") + +barplot(VADeaths) +dev.slackr("@jayjacobs") + +ggslackr(qplot(mpg, wt, data=mtcars)) +``` + +### Test Results + +``` r +library(slackr) +library(testthat) + +date() +#> [1] "Tue Apr 26 17:55:41 2016" + +test_dir("tests/") +#> testthat results ======================================================================================================== +#> OK: 0 SKIPPED: 0 FAILED: 0 +``` diff --git a/man/dev.slackr.Rd b/man/dev.slackr.Rd deleted file mode 100644 index d498a5e..0000000 --- a/man/dev.slackr.Rd +++ /dev/null @@ -1,40 +0,0 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{dev.slackr} -\alias{dev.slackr} -\title{Send the graphics contents of the current device to a \code{slack.com} channel} -\usage{ -dev.slackr(channels = Sys.getenv("SLACK_CHANNEL"), ..., - api_token = Sys.getenv("SLACK_API_TOKEN")) -} -\arguments{ -\item{channels}{list of channels to post image to} - -\item{...}{other arguments passed into png device} - -\item{api_token}{the slack.com full API token (chr)} -} -\value{ -\code{httr} response object from \code{POST} call -} -\description{ -\code{dev.slackr} sends the graphics contents of the current device to the specified \code{slack.com} channel. -This requires setting up a full API token (i.e. not a webhook & not OAuth) for this to work. -} -\examples{ -\dontrun{ -slackrSetup() - -# ggplot -library(ggplot2) -qplot(mpg, wt, data=mtcars) -dev.slackr("#results") - -# base -barplot(VADeaths) -dev.slackr("@jayjacobs") -} -} -\seealso{ -\code{\link{slackrSetup}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} -} - diff --git a/man/dev_slackr.Rd b/man/dev_slackr.Rd new file mode 100644 index 0000000..3e87ed6 --- /dev/null +++ b/man/dev_slackr.Rd @@ -0,0 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dev_slackr.R, R/zcamels.r +\name{dev_slackr} +\alias{dev.slackr} +\alias{dev_slackr} +\title{Send the graphics contents of the current device to a Slack channel} +\usage{ +dev_slackr(channels = Sys.getenv("SLACK_CHANNEL"), ..., + api_token = Sys.getenv("SLACK_API_TOKEN"), file = "plot") + +dev.slackr(channels = Sys.getenv("SLACK_CHANNEL"), ..., + api_token = Sys.getenv("SLACK_API_TOKEN"), file = "plot") +} +\arguments{ +\item{channels}{list of channels to post image to} + +\item{...}{other arguments passed into png device} + +\item{api_token}{the slack.com full API token (chr)} + +\item{file}{prefix for filenames (defaults to \code{plot})} +} +\value{ +\code{httr} response object from \code{POST} call +} +\description{ +\code{dev.slackr} sends the graphics contents of the current device to the +specified Slack channel. +} +\note{ +You can pass in \code{add_user=TRUE} as part of the \code{...} parameters and the Slack API + will post the message as your logged-in user account (this will override anything set in + \code{username}) +} +\examples{ +\dontrun{ +slackr_setup() + +# base +library(maps) +map("usa") +dev_slackr("#results", filename='map') + +# base +barplot(VADeaths) +dev_slackr("@jayjacobs") +} +} +\author{ +Konrad Karczewski [ctb], Bob Rudis [aut] +} +\references{ +\url{https://github.com/hrbrmstr/slackr/pull/12/files} +} +\seealso{ +\code{\link{slackrSetup}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} +} + diff --git a/man/ggslackr.Rd b/man/ggslackr.Rd index 8f810d1..300212e 100644 --- a/man/ggslackr.Rd +++ b/man/ggslackr.Rd @@ -1,12 +1,13 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/gg_slackr.R \name{ggslackr} \alias{ggslackr} -\title{Post a ggplot to a \url{slack.com} channel} +\title{Post a ggplot to a Slack channel} \usage{ ggslackr(plot = last_plot(), channels = Sys.getenv("SLACK_CHANNEL"), scale = 1, width = par("din")[1], height = par("din")[2], units = c("in", "cm", "mm"), dpi = 300, limitsize = TRUE, - api_token = Sys.getenv("SLACK_API_TOKEN"), ...) + api_token = Sys.getenv("SLACK_API_TOKEN"), file = "ggplot", ...) } \arguments{ \item{plot}{ggplot object to save, defaults to last plot displayed} @@ -19,29 +20,36 @@ ggslackr(plot = last_plot(), channels = Sys.getenv("SLACK_CHANNEL"), \item{height}{height (defaults to the height of current plotting window)} -\item{units}{units for width and height when either one is explicitly specified (in, cm, or mm)} +\item{units}{units for width and height when either one is explicitly specified +(in, cm, or mm)} \item{dpi}{dpi to use for raster graphics} -\item{limitsize}{when TRUE (the default), ggsave will not save images larger than 50x50 inches, to prevent the common error of specifying dimensions in pixels.} +\item{limitsize}{when TRUE (the default), ggsave will not save images larger +than 50x50 inches, to prevent the common error of specifying dimensions in pixels.} \item{api_token}{the slack.com full API token (chr)} +\item{file}{prefix for filenames (defaults to \code{ggplot})} + \item{...}{other arguments passed to graphics device} } \value{ -\code{httr} response object +\code{httr} response object (invisibly) } \description{ -Unlike the \code{\link{dev.slackr}} function, this one takes a \code{ggplot} object, +Unlike the \code{\link{dev_slackr}} function, this one takes a \code{ggplot} object, eliminating the need to have a graphics device (think use in scripts). } \note{ You need to setup a full API token (i.e. not a webhook & not OAuth) for this to work + Also, uou can pass in \code{add_user=TRUE} as part of the \code{...} + parameters and the Slack API will post the message as your logged-in user + account (this will override anything set in \code{username}) } \examples{ \dontrun{ -slackrSetup() +slackr_setup() ggslackr(qplot(mpg, wt, data=mtcars)) } } diff --git a/man/save.slackr.Rd b/man/save.slackr.Rd deleted file mode 100644 index 1fa0ede..0000000 --- a/man/save.slackr.Rd +++ /dev/null @@ -1,29 +0,0 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{save.slackr} -\alias{save.slackr} -\title{Save R objects to an RData file on \code{slack.com}} -\usage{ -save.slackr(..., channels = "", file = "slackr", - api_token = Sys.getenv("SLACK_API_TOKEN")) -} -\arguments{ -\item{...}{objects to store in the R data file} - -\item{channels}{slack.com channels to save to (optional)} - -\item{file}{filename (without extension) to use} - -\item{api_token}{full API token} -} -\value{ -\code{httr} response object from \code{POST} call -} -\description{ -\code{save.slackr} enables you upload R objects (as an R data file) -to \code{slack.com} and (optionally) post them to one or more channels -(if \code{channels} is not empty). -} -\seealso{ -\code{\link{slackrSetup}}, \code{\link{dev.slackr}}, \code{\link{slackrUpload}} -} - diff --git a/man/save_slackr.Rd b/man/save_slackr.Rd new file mode 100644 index 0000000..af8191f --- /dev/null +++ b/man/save_slackr.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/save_slackr.R, R/zcamels.r +\name{save_slackr} +\alias{save.slackr} +\alias{save_slackr} +\title{Save R objects to an RData file on Slack} +\usage{ +save_slackr(..., channels = "", file = "slackr", + api_token = Sys.getenv("SLACK_API_TOKEN")) + +save.slackr(..., channels = "", file = "slackr", + api_token = Sys.getenv("SLACK_API_TOKEN")) +} +\arguments{ +\item{...}{objects to store in the R data file} + +\item{channels}{slack.com channels to save to (optional)} + +\item{file}{filename (without extension) to use} + +\item{api_token}{full API token} +} +\value{ +\code{httr} response object from \code{POST} call +} +\description{ +\code{save_slackr} enables you upload R objects (as an R data file) +to Slack and (optionally) post them to one or more channels +(if \code{channels} is not empty). +} +\note{ +You can pass in \code{add_user=TRUE} as part of the \code{...} parameters and the Slack API + will post the message as your logged-in user account (this will override anything set in + \code{username}) +} +\examples{ +\dontrun{ +slackr_setup() +save_slackr(mtcars, channels="#slackr", file="mtcars") +} +} +\seealso{ +\code{\link{slackr_setup}}, \code{\link{dev_slackr}}, \code{\link{slackr_upload}} +} + diff --git a/man/slackr-package.Rd b/man/slackr-package.Rd index a5bcf70..374625d 100644 --- a/man/slackr-package.Rd +++ b/man/slackr-package.Rd @@ -1,4 +1,5 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr-package.R \docType{package} \name{slackr-package} \alias{slackr-package} @@ -7,18 +8,31 @@ slackr - A package to work with the Slack.com API } \details{ +Mega thanks to: + +\itemize{ + \item \href{https://github.com/jayjacobs}{Jay Jacobs} + \item \href{https://github.com/davidski}{David Severski} + \item \href{https://github.com/qsweber}{Quinn Weber} + \item \href{https://github.com/konradjk}{Konrad Karczewski} + \item \href{https://github.com/eniles}{Ed Niles} + \item \href{https://github.com/rsaporta}{Rick Saporta} +} + +for their contributions to the package! + Check out: \itemize{ \item the \link{slackr} function to send messages, - \item the \link{dev.slackr} function to send images (copies from current graphics device) + \item the \link{dev_slackr} function to send images (copies from current graphics device) \item the \link{ggslackr} function to send ggplot objects (without plotting to a device first) - \item the \link{save.slackr} function to send R objects (as RData files) - \item the \link{slackrUpload} function to send files + \item the \link{save_slackr} function to send R objects (as RData files) + \item the \link{slackr_upload} function to send files } } \examples{ \dontrun{ -slackrSetup() +slackr_setup() # send objects slackr("iris info", head(iris), str(iris)) diff --git a/man/slackr.Rd b/man/slackr.Rd index 3af6807..c41710c 100644 --- a/man/slackr.Rd +++ b/man/slackr.Rd @@ -1,7 +1,8 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr.R \name{slackr} \alias{slackr} -\title{Output R expressions to a \code{slack.com} channel/user} +\title{Output R expressions to a Slack channel/user} \usage{ slackr(..., channel = Sys.getenv("SLACK_CHANNEL"), username = Sys.getenv("SLACK_USERNAME"), @@ -20,25 +21,30 @@ slackr(..., channel = Sys.getenv("SLACK_CHANNEL"), \item{api_token}{your full slack.com API token} } \description{ -Takes an \code{expr}, evaluates it and sends the output to a \url{slack.com} +Takes an \code{expr}, evaluates it and sends the output to a Slack chat destination. Useful for logging, messaging on long compute tasks or general information sharing. } \details{ By default, everyting but \code{expr} will be looked for in a "\code{SLACK_}" environment variable. You can override or just specify these values directly instead, -but it's probably better to call \link{slackrSetup} first. +but it's probably better to call \code{\link{slackr_setup}} first. } \note{ -You need a \url{slack.com} account and will also need to setup an API token \url{https://api.slack.com/} +You need a \url{https://www.slack.com} account and will also need to + setup an API token \url{https://api.slack.com/} + Also, you can pass in \code{add_user=TRUE} as part of the \code{...} + parameters and the Slack API will post the message as your logged-in + user account (this will override anything set in \code{username}) } \examples{ \dontrun{ -slackrSetup() +slackr_setup() slackr("iris info", head(iris), str(iris)) } } \seealso{ -\code{\link{slackrSetup}}, \code{\link{slackrBot}}, \code{\link{dev.slackr}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} +\code{\link{slackr_setup}}, \code{\link{slackr_bot}}, \code{\link{dev_slackr}}, + \code{\link{save_slackr}}, \code{\link{slackr_upload}} } diff --git a/man/slackrBot.Rd b/man/slackrBot.Rd deleted file mode 100644 index a8e648e..0000000 --- a/man/slackrBot.Rd +++ /dev/null @@ -1,49 +0,0 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{slackrBot} -\alias{slackrBot} -\title{Output R expressions to a \code{slack.com} channel/user (as \code{slackbot})} -\usage{ -slackrBot(..., channel = Sys.getenv("SLACK_CHANNEL"), - username = Sys.getenv("SLACK_USERNAME"), - icon_emoji = Sys.getenv("SLACK_ICON_EMOJI"), - incoming_webhook_url = Sys.getenv("SLACK_INCOMING_URL_PREFIX"), - token = Sys.getenv("SLACK_TOKEN")) -} -\arguments{ -\item{...}{expressions to be sent to Slack.com} - -\item{channel}{which channel to post the message to (chr)} - -\item{username}{what user should the bot be named as (chr)} - -\item{icon_emoji}{what emoji to use (chr) \code{""} will mean use the default} - -\item{incoming_webhook_url}{which \url{slack.com} API endpoint URL to use} - -\item{token}{your webhook API token} -} -\description{ -Takes an \code{expr}, evaluates it and sends the output to a \url{slack.com} -chat destination. Useful for logging, messaging on long compute tasks or -general information sharing. -} -\details{ -By default, everyting but \code{expr} will be looked for in a "\code{SLACK_}" -environment variable. You can override or just specify these values directly instead, -but it's probably better to call \link{slackrSetup} first. - -This function uses the incoming webhook API and posts user messages as \code{slackbot} -} -\note{ -You need a \url{slack.com} account and will also need to setup an incoming webhook: \url{https://api.slack.com/} -} -\examples{ -\dontrun{ -slackrSetup() -slackr("iris info", head(iris), str(iris)) -} -} -\seealso{ -\code{\link{slackrSetup}}, \code{\link{slackr}}, \code{\link{dev.slackr}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} -} - diff --git a/man/slackrChannels.Rd b/man/slackrChannels.Rd deleted file mode 100644 index c045fd7..0000000 --- a/man/slackrChannels.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{slackrChannels} -\alias{slackrChannels} -\title{Get a data frame of slack.com channels} -\usage{ -slackrChannels(api_token = Sys.getenv("SLACK_API_TOKEN")) -} -\arguments{ -\item{api_token}{the slack.com full API token (chr)} -} -\value{ -data.table of channels -} -\description{ -need to setup a full API token (i.e. not a webhook & not OAuth) for this to work -} -\note{ -Renamed from \code{slackr_channels} -} - diff --git a/man/slackrGroups.Rd b/man/slackrGroups.Rd deleted file mode 100644 index 6886762..0000000 --- a/man/slackrGroups.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{slackrGroups} -\alias{slackrGroups} -\title{Get a data frame of slack.com groups} -\usage{ -slackrGroups(api_token = Sys.getenv("SLACK_API_TOKEN")) -} -\arguments{ -\item{api_token}{the slack.com full API token (chr)} -} -\value{ -data.table of channels -} -\description{ -need to setup a full API token (i.e. not a webhook & not OAuth) for this to work -} - diff --git a/man/slackrSetup.Rd b/man/slackrSetup.Rd deleted file mode 100644 index 257b88c..0000000 --- a/man/slackrSetup.Rd +++ /dev/null @@ -1,66 +0,0 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{slackrSetup} -\alias{slackrSetup} -\title{Setup environment variables for \code{slack.com} API} -\usage{ -slackrSetup(channel = "#general", username = "slackr", icon_emoji = "", - token = "", incoming_webhook_url = "", api_token = "", - config_file = "~/.slackr", echo = FALSE) -} -\arguments{ -\item{channel}{default channel to send the output to (chr) defaults to \code{#general}} - -\item{username}{the username output will appear from (chr) defaults to \code{slackr}} - -\item{icon_emoji}{which emoji picture to use (chr) defaults to none (can be left blank in config file as well)} - -\item{token}{the \url{slack.com} webhook API token string (chr) defaults to none} - -\item{incoming_webhook_url}{the slack.com URL prefix to use (chr) defaults to none} - -\item{api_token}{the slack.com full API token (chr)} - -\item{config_file}{a configuration file (DCF) - see \link{read.dcf} - format with the config values.} - -\item{echo}{display the configuraiton variables (bool) initially \code{FALSE}} -} -\description{ -Initialize all the environment variables \link{slackr} will need to use to -work properly. -} -\details{ -By default, \code{slackr} (and other functions) will use the \code{#general} room and a username -of \code{slackr()} with no emoji and the default \url{slack.com} API prefix URL. You -still need to provide the webhook API token in \code{token} for anyting to work. -Failure to call this function before calling \code{slackr()} will result in a -message to do so. - -If a valid file is found at the locaiton pointed to by \code{config_file}, the -values there will be used. The fields should be specified as such in the file: \cr -\cr -\code{ token: yourTokenCode} \cr -\code{ channel: #general} \cr -\code{ username: slackr} \cr -\code{ icon_emoji:} \cr -\code{ incoming_webhook_url: https://yourgroup.slack.com/services/hooks/incoming-webhook?} \cr \cr -} -\note{ -You need a \url{slack.com} account and will also need to setup an incoming webhook and full API tokens: \url{https://api.slack.com/} -} -\examples{ -\dontrun{ -# reads from default file -slackrSetup() - -# reads from alternate config -slackrSetup(config_file="/path/to/my/slackrconfig) - -# the hard way -slackrSetup(channel="#code", token="mytoken", - url_prefix="http://myslack.slack.com/services/hooks/incoming-webhook?") -} -} -\seealso{ -\code{\link{slackr}}, \code{\link{dev.slackr}}, \code{\link{save.slackr}}, \code{\link{slackrUpload}} -} - diff --git a/man/slackrUpload.Rd b/man/slackrUpload.Rd deleted file mode 100644 index 70f6903..0000000 --- a/man/slackrUpload.Rd +++ /dev/null @@ -1,31 +0,0 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{slackrUpload} -\alias{slackrUpload} -\title{Send a file to \code{slack.com}} -\usage{ -slackrUpload(filename, title = basename(filename), - initial_comment = basename(filename), channels = "", - api_token = Sys.getenv("SLACK_API_TOKEN")) -} -\arguments{ -\item{filename}{path to file} - -\item{title}{title on slack (optional - defaults to filename)} - -\item{initial_comment}{comment for file on slack (optional - defaults to filename)} - -\item{channels}{slack.com channels to save to (optional)} - -\item{api_token}{full API token} -} -\value{ -\code{httr} response object from \code{POST} call -} -\description{ -\code{slackrUoload} enables you upload files to \code{slack.com} and -(optionally) post them to one or more channels (if \code{channels} is not empty). -} -\seealso{ -\code{\link{slackrSetup}}, \code{\link{dev.slackr}}, \code{\link{save.slackr}} -} - diff --git a/man/slackrUsers.Rd b/man/slackrUsers.Rd deleted file mode 100644 index 1f9a4fe..0000000 --- a/man/slackrUsers.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{slackrUsers} -\alias{slackrUsers} -\title{Get a data frame of slack.com users} -\usage{ -slackrUsers(api_token = Sys.getenv("SLACK_API_TOKEN")) -} -\arguments{ -\item{api_token}{the slack.com full API token (chr)} -} -\value{ -data.table of users -} -\description{ -need to setup a full API token (i.e. not a webhook & not OAuth) for this to work -} - diff --git a/man/slackr_bot.Rd b/man/slackr_bot.Rd new file mode 100644 index 0000000..3600a00 --- /dev/null +++ b/man/slackr_bot.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr_bot.r, R/zcamels.r +\name{slackr_bot} +\alias{slackrBot} +\alias{slackr_bot} +\title{Send result of R expressions to a Slack channel via webhook API} +\usage{ +slackr_bot(..., channel = Sys.getenv("SLACK_CHANNEL"), + username = Sys.getenv("SLACK_USERNAME"), + icon_emoji = Sys.getenv("SLACK_ICON_EMOJI"), + incoming_webhook_url = Sys.getenv("SLACK_INCOMING_URL_PREFIX")) + +slackrBot(..., channel = Sys.getenv("SLACK_CHANNEL"), + username = Sys.getenv("SLACK_USERNAME"), + icon_emoji = Sys.getenv("SLACK_ICON_EMOJI"), + incoming_webhook_url = Sys.getenv("SLACK_INCOMING_URL_PREFIX")) +} +\arguments{ +\item{...}{expressions to be sent to Slack.com} + +\item{channel}{which channel to post the message to (chr)} + +\item{username}{what user should the bot be named as (chr)} + +\item{icon_emoji}{what emoji to use (chr) \code{""} will mean use the default} + +\item{incoming_webhook_url}{which \code{slack.com} API endpoint URL to use +(see section \bold{Webhook URLs} for details)} +} +\description{ +Takes an \code{expr}, evaluates it and sends the output to a Slack +chat destination via the webhook API. Useful for logging, messaging on long +compute tasks or general information sharing. +} +\details{ +By default, everyting but \code{expr} will be looked for in a "\code{SLACK_}" +environment variable. You can override or just specify these values directly +instead, but it's probably better to call \code{\link{slackr_setup}} first. + +This function uses the incoming webhook API. The webhook will have a default +channel, username, icon etc, but these can be overridden. +} +\note{ +You need a \url{https://www.slack.com} account and will also need to + setup an incoming webhook: \url{https://api.slack.com/}. Old style webhooks are + no longer supported. +} +\section{Webhook URLs}{ + Webhook URLs look like: \itemize{ + + \item \code{https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX} + + } + +OLD STYLE WEBHOOKS ARE NO LONGER SUPPORTED +} +\examples{ +\dontrun{ +slackr_setup() +slackr_bot("iris info", head(iris), str(iris)) + +# or directly +slackr_bot("Test message", username="slackr", channel="#random", + incoming_webhook_url="https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX") +} +} +\seealso{ +\code{\link{slackrSetup}}, \code{\link{slackr}}, + \code{\link{dev_slackr}}, \code{\link{save_slackr}}, + \code{\link{slackr_upload}} +} + diff --git a/man/slackr_channels.Rd b/man/slackr_channels.Rd new file mode 100644 index 0000000..9f3f4fc --- /dev/null +++ b/man/slackr_channels.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr_utils.R, R/zcamels.r +\name{slackr_channels} +\alias{slackrChannels} +\alias{slackr_channels} +\title{Get a data frame of Slack channels} +\usage{ +slackr_channels(api_token = Sys.getenv("SLACK_API_TOKEN")) + +slackrChannels(api_token = Sys.getenv("SLACK_API_TOKEN")) +} +\arguments{ +\item{api_token}{the Slack full API token (chr)} +} +\value{ +data.table of channels +} +\description{ +Get a data frame of Slack channels +} + diff --git a/man/slackrChTrans.Rd b/man/slackr_chtrans.Rd similarity index 53% rename from man/slackrChTrans.Rd rename to man/slackr_chtrans.Rd index 7bf9bc2..3de9c43 100644 --- a/man/slackrChTrans.Rd +++ b/man/slackr_chtrans.Rd @@ -1,8 +1,15 @@ -% Generated by roxygen2 (4.0.1.99): do not edit by hand -\name{slackrChTrans} +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr_utils.R, R/zcamels.r +\name{slackr_chtrans} \alias{slackrChTrans} +\alias{slackrChtrans} +\alias{slackr_chtrans} \title{Translate vector of channel names to channel ID's for API} \usage{ +slackr_chtrans(channels, api_token = Sys.getenv("SLACK_API_TOKEN")) + +slackrChtrans(channels, api_token = Sys.getenv("SLACK_API_TOKEN")) + slackrChTrans(channels, api_token = Sys.getenv("SLACK_API_TOKEN")) } \arguments{ @@ -11,14 +18,15 @@ slackrChTrans(channels, api_token = Sys.getenv("SLACK_API_TOKEN")) \item{api_token}{the slack.com full API token (chr)} } \value{ -character vector - original channel list with \code{#} or \code{@} channels replaced with ID's. +character vector - original channel list with \code{#} or + \code{@} channels replaced with ID's. } \description{ Given a vector of one or more channel names, it will retrieve list of active channels and try to replace channels that begin with "\code{#}" or "\code{@}" with the channel ID for that channel. Also incorporates groups. } -\note{ -Renamed from \code{slackr_chtrans} +\author{ +Quinn Weber [ctb], Bob Rudis [aut] } diff --git a/man/slackr_groups.Rd b/man/slackr_groups.Rd new file mode 100644 index 0000000..1ae7022 --- /dev/null +++ b/man/slackr_groups.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr_utils.R, R/zcamels.r +\name{slackr_groups} +\alias{slackrGroups} +\alias{slackr_groups} +\title{Get a data frame of Slack groups} +\usage{ +slackr_groups(api_token = Sys.getenv("SLACK_API_TOKEN")) + +slackrGroups(api_token = Sys.getenv("SLACK_API_TOKEN")) +} +\arguments{ +\item{api_token}{the Slackfull API token (chr)} +} +\value{ +\code{data.frame} of channels +} +\description{ +Get a data frame of Slack groups +} + diff --git a/man/slackr_ims.Rd b/man/slackr_ims.Rd new file mode 100644 index 0000000..9e425b8 --- /dev/null +++ b/man/slackr_ims.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr_utils.R, R/zcamels.r +\name{slackr_ims} +\alias{slackrIms} +\alias{slackr_ims} +\title{Get a data frame of Slack IM ids} +\usage{ +slackr_ims(api_token = Sys.getenv("SLACK_API_TOKEN")) + +slackrIms(api_token = Sys.getenv("SLACK_API_TOKEN")) +} +\arguments{ +\item{api_token}{the Slack full API token (chr)} +} +\value{ +\code{data.frame} of im ids and user names +} +\description{ +Get a data frame of Slack IM ids +} +\author{ +Quinn Weber [aut], Bob Rudis [ctb] +} +\references{ +\url{https://github.com/hrbrmstr/slackr/pull/13} +} + diff --git a/man/slackr_msg.Rd b/man/slackr_msg.Rd new file mode 100644 index 0000000..3a0e07c --- /dev/null +++ b/man/slackr_msg.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr.R, R/zcamels.r +\name{slackr_msg} +\alias{slackrMsg} +\alias{slackr_msg} +\title{Output R expressions to a Slack channel/user} +\usage{ +slackr_msg(txt = "", channel = Sys.getenv("SLACK_CHANNEL"), + username = Sys.getenv("SLACK_USERNAME"), + icon_emoji = Sys.getenv("SLACK_ICON_EMOJI"), + api_token = Sys.getenv("SLACK_API_TOKEN"), ...) + +slackrMsg(txt = "", channel = Sys.getenv("SLACK_CHANNEL"), + username = Sys.getenv("SLACK_USERNAME"), + icon_emoji = Sys.getenv("SLACK_ICON_EMOJI"), + api_token = Sys.getenv("SLACK_API_TOKEN"), ...) +} +\arguments{ +\item{txt}{text message to send to Slack. If a character vector of length > 1 +is passed in, they will be combined and separated by newlines.} + +\item{channel}{which channel to post the message to (chr)} + +\item{username}{what user should the bot be named as (chr)} + +\item{icon_emoji}{what emoji to use (chr) \code{""} will mean use the default} + +\item{api_token}{your full slack.com API token} + +\item{...}{other arguments passed to the Slack API \code{chat.postMessage} call} +} +\description{ +Takes an \code{expr}, evaluates it and sends the output to a Slack +chat destination. Useful for logging, messaging on long compute tasks or +general information sharing. +} +\details{ +By default, everyting but \code{expr} will be looked for in a "\code{SLACK_}" +environment variable. You can override or just specify these values directly instead, +but it's probably better to call \code{\link{slackrSetup}} first. +} +\note{ +You need a \url{https://www.slack.com} account and will also need to + setup an API token \url{https://api.slack.com/} + Also, you can pass in \code{add_user=TRUE} as part of the \code{...} + parameters and the Slack API will post the message as your logged-in + user account (this will override anything set in \code{username}) +} +\examples{ +\dontrun{ +slackr_setup() +slackr_msg("Hi") +} +} +\seealso{ +\code{\link{slackr_setup}}, \code{\link{slackr_bot}}, \code{\link{dev_slackr}}, + \code{\link{save_slackr}}, \code{\link{slackr_upload}} +} + diff --git a/man/slackr_setup.Rd b/man/slackr_setup.Rd new file mode 100644 index 0000000..64f0f6c --- /dev/null +++ b/man/slackr_setup.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr_setup.r, R/zcamels.r +\name{slackr_setup} +\alias{slackrSetup} +\alias{slackr_setup} +\title{Setup environment variables for Slack API access} +\usage{ +slackr_setup(channel = "#general", username = "slackr", icon_emoji = "", + incoming_webhook_url = "", api_token = "", config_file = "~/.slackr", + echo = FALSE) + +slackrSetup(channel = "#general", username = "slackr", icon_emoji = "", + incoming_webhook_url = "", api_token = "", config_file = "~/.slackr", + echo = FALSE) +} +\arguments{ +\item{channel}{default channel to send the output to (chr) defaults to \code{#general}} + +\item{username}{the username output will appear from (chr) defaults to \code{slackr}} + +\item{icon_emoji}{which emoji picture to use (chr) defaults to none (can be +left blank in config file as well)} + +\item{incoming_webhook_url}{the slack.com URL prefix to use (chr) defaults to none} + +\item{api_token}{the Slack full API token (chr)} + +\item{config_file}{a configuration file (DCF) - see \link{read.dcf} - format +with the config values.} + +\item{echo}{display the configuration variables (bool) initially \code{FALSE}} +} +\description{ +Initialize all the environment variables \code{\link{slackr}} will need to use to +work properly. +} +\details{ +By default, \code{\link{slackr}} (and other functions) will use the \code{#general} +room and a username of \code{slackr()} with no emoji. + +If a valid file is found at the locaiton pointed to by \code{config_file}, the +values there will be used. The fields should be specified as such in the file: + +\preformatted{ + api_token: YOUR_FULL_API_TOKEN + channel: #general + username: slackr + incoming_webhook_url: https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX +} +} +\note{ +You need a \href{slack.com}{Slack} account and all your API URLs & tokens setup + to use this package. +} +\examples{ +\dontrun{ +# reads from default file (i.e. ~/.slackr) +slackr_setup() + +# reads from alternate config +slackr_setup(config_file="/path/to/my/slackrconfig) + +# the hard way +slackr_setup(channel="#code", + incoming_webhook_url="https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX") +} +} +\seealso{ +\code{\link{slackr}}, \code{\link{dev_slackr}}, \code{\link{save_slackr}}, + \code{\link{slackr_upload}} +} + diff --git a/man/slackr_upload.Rd b/man/slackr_upload.Rd new file mode 100644 index 0000000..3a99275 --- /dev/null +++ b/man/slackr_upload.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr_upload.R, R/zcamels.r +\name{slackr_upload} +\alias{slackrUpload} +\alias{slackr_upload} +\title{Send a file to Slack} +\usage{ +slackr_upload(filename, title = basename(filename), + initial_comment = basename(filename), channels = "", + api_token = Sys.getenv("SLACK_API_TOKEN")) + +slackrUpload(filename, title = basename(filename), + initial_comment = basename(filename), channels = "", + api_token = Sys.getenv("SLACK_API_TOKEN")) +} +\arguments{ +\item{filename}{path to file} + +\item{title}{title on slack (optional - defaults to filename)} + +\item{initial_comment}{comment for file on slack (optional - defaults to filename)} + +\item{channels}{slack.com channels to save to (optional)} + +\item{api_token}{full API token} +} +\value{ +\code{httr} response object from \code{POST} call (invisibly) +} +\description{ +\code{slackrUpload} enables you upload files to Slack and +(optionally) post them to one or more channels (if \code{channels} is not empty). +} +\author{ +Quinn Weber [ctb], Bob Rudis [aut] +} +\references{ +\url{https://github.com/hrbrmstr/slackr/pull/15/files} +} +\seealso{ +\code{\link{slackr_setup}}, \code{\link{dev_slackr}}, \code{\link{save_slackr}} +} + diff --git a/man/slackr_users.Rd b/man/slackr_users.Rd new file mode 100644 index 0000000..ae285b9 --- /dev/null +++ b/man/slackr_users.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/slackr_utils.R, R/zcamels.r +\name{slackr_users} +\alias{slackrUsers} +\alias{slackr_users} +\title{Get a data frame of Slack users} +\usage{ +slackr_users(api_token = Sys.getenv("SLACK_API_TOKEN")) + +slackrUsers(api_token = Sys.getenv("SLACK_API_TOKEN")) +} +\arguments{ +\item{api_token}{the Slack full API token (chr)} +} +\value{ +\code{data.frame} of users +} +\description{ +Get a data frame of Slack users +} + diff --git a/man/text_slackr.Rd b/man/text_slackr.Rd new file mode 100644 index 0000000..ecdddba --- /dev/null +++ b/man/text_slackr.Rd @@ -0,0 +1,65 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/text_slackr.r, R/zcamels.r +\name{text_slackr} +\alias{textSlackr} +\alias{text_slackr} +\title{Sends basic text to a slack channel. Calls the chat.postMessage method on the Slack Web API. +Information on this method can be found here: \url{https://api.slack.com/methods/chat.postMessage}} +\usage{ +text_slackr(text, ..., preformatted = TRUE, + channel = Sys.getenv("SLACK_CHANNEL"), + username = Sys.getenv("SLACK_USERNAME"), + icon_emoji = Sys.getenv("SLACK_ICON_EMOJI"), + api_token = Sys.getenv("SLACK_API_TOKEN")) + +textSlackr(text, ..., preformatted = TRUE, + channel = Sys.getenv("SLACK_CHANNEL"), + username = Sys.getenv("SLACK_USERNAME"), + icon_emoji = Sys.getenv("SLACK_ICON_EMOJI"), + api_token = Sys.getenv("SLACK_API_TOKEN")) +} +\arguments{ +\item{text}{The character vector to be posted} + +\item{...}{Optional arguments such as: as_user, parse, unfurl_links, etc.} + +\item{preformatted}{Should the text be sent as preformatted text. Defaults to TRUE} + +\item{channel}{The name of the channels to which the DataTable should be sent. +Prepend channel names with a hashtag. Prepend private-groups with nothing. +Prepend direct messages with an @} + +\item{username}{what user should the bot be named as (chr)} + +\item{icon_emoji}{what emoji to use (chr) \code{""} will mean use the default} + +\item{api_token}{your full slack.com API token} +} +\value{ +\code{httr} response object (invislbly) +} +\description{ +Sends basic text to a slack channel. Calls the chat.postMessage method on the Slack Web API. +Information on this method can be found here: \url{https://api.slack.com/methods/chat.postMessage} +} +\note{ +You can pass in \code{add_user=TRUE} as part of the \code{...} parameters and the Slack API + will post the message as your logged-in user account (this will override anything set in + \code{username}) +} +\examples{ +\dontrun{ +slackr_setup() +text_slackr('hello world', as_user=TRUE) +} +} +\author{ +Quinn Weber [aut], Bob Rudis [ctb] +} +\references{ +\url{https://github.com/hrbrmstr/slackr/pull/11} +} +\seealso{ +\url{https://api.slack.com/methods/chat.postMessage} +} + diff --git a/tests/testthat/test-textslackr.R b/tests/testthat/test-textslackr.R new file mode 100644 index 0000000..12b1ffd --- /dev/null +++ b/tests/testthat/test-textslackr.R @@ -0,0 +1,8 @@ +context("textslackr") + +test_that("errors when given bad inputs", { +# expect_error(textslackr(c(1,2),'api-test-private'), "text must be a vector of length one") +# expect_error(textslackr('a',1),"channel must be a character vector of length one") +# expect_error(textslackr('a','api-test-private',preformatted='a'),"preformatted must be a logical vector of length one") +# expect_error(textslackr('a','api-test-private',icon_emoji=1),"icon_emoji must be a character vector of length one") +}) \ No newline at end of file