From 6d94bc243ccd0060f619c0cc2be5c2c5628cd864 Mon Sep 17 00:00:00 2001 From: your name Date: Thu, 13 Jun 2024 10:22:54 -0400 Subject: [PATCH 01/18] Add list_activities, list_versions, and list_permissions methods list_activities added to both ms_drive_item objects and ms_drive objects --- R/ms_drive.R | 6 ++++++ R/ms_drive_item.R | 21 +++++++++++++++++++++ man/ms_drive.Rd | 2 ++ man/ms_drive_item.Rd | 6 ++++++ 4 files changed, 35 insertions(+) diff --git a/R/ms_drive.R b/R/ms_drive.R index 41409c0..854d755 100644 --- a/R/ms_drive.R +++ b/R/ms_drive.R @@ -62,6 +62,8 @@ #' #' `list_files` is a synonym for `list_items`. #' +#' `list_activities` returns a list of activities for a drive. +#' #' `download_file` and `upload_file` transfer files between the local machine and the drive. For `download_file`, the default destination folder is the current (working) directory of your R session. For `upload_file`, there is no default destination folder; make sure you specify the destination explicitly. #' #' `download_folder` and `upload_folder` transfer all the files in a folder. If `recursive` is TRUE, all subfolders will also be transferred recursively. The `parallel` argument can have the following values: @@ -174,6 +176,10 @@ public=list( private$get_root()$list_items(path, ...) }, + list_activites=function() { + self$do_operation("activities") + }, + upload_file=function(src, dest, blocksize=32768000) { private$get_root()$upload(src, dest, blocksize) diff --git a/R/ms_drive_item.R b/R/ms_drive_item.R index 518e958..943bee9 100644 --- a/R/ms_drive_item.R +++ b/R/ms_drive_item.R @@ -50,6 +50,12 @@ #' #' `list_files` is a synonym for `list_items`. #' +#' `list_permissions` returns a list of permissions for a drive item. +#' +#' `list_versions` returns a list of drive item versions. +#' +#' `list_activities` returns a list of activities for a drive item. +#' #' `download` downloads the item to the local machine. If this is a file, it is downloaded; in this case, the `dest` argument can be the path to the destination file, or NULL to return the downloaded content in a raw vector. If the item is a folder, all its files are downloaded, including subfolders if the `recursive` argument is TRUE. #' #' `upload` uploads a file or folder from the local machine into the folder item. The `src` argument can be the path to the source file, a [rawConnection] or a [textConnection] object. If `src` is a folder, all its files are uploaded, including subfolders if the `recursive` argument iS TRUE. An `ms_drive_item` object is returned invisibly. @@ -211,6 +217,21 @@ public=list( httr::BROWSE(self$properties$webUrl) }, + # https://learn.microsoft.com/en-us/graph/api/driveitem-list-permissions + list_permissions=function() { + self$do_operation("permissions") + }, + + # https://learn.microsoft.com/en-us/graph/api/driveitem-list-versions + list_versions=function() { + self$do_operation("versions") + }, + + # https://learn.microsoft.com/en-us/graph/api/activities-list + list_activities=function() { + self$do_operation("activities") + }, + create_share_link=function(type=c("view", "edit", "embed"), expiry="7 days", password=NULL, scope=NULL) { type <- match.arg(type) diff --git a/man/ms_drive.Rd b/man/ms_drive.Rd index 3c94911..7d8d0b1 100644 --- a/man/ms_drive.Rd +++ b/man/ms_drive.Rd @@ -82,6 +82,8 @@ For copying and moving, the destination folder must exist beforehand. When copyi \code{list_files} is a synonym for \code{list_items}. +\code{list_activities} returns a list of activities for a drive. + \code{download_file} and \code{upload_file} transfer files between the local machine and the drive. For \code{download_file}, the default destination folder is the current (working) directory of your R session. For \code{upload_file}, there is no default destination folder; make sure you specify the destination explicitly. \code{download_folder} and \code{upload_folder} transfer all the files in a folder. If \code{recursive} is TRUE, all subfolders will also be transferred recursively. The \code{parallel} argument can have the following values: diff --git a/man/ms_drive_item.Rd b/man/ms_drive_item.Rd index 18764db..288196d 100644 --- a/man/ms_drive_item.Rd +++ b/man/ms_drive_item.Rd @@ -71,6 +71,12 @@ This class exposes methods for carrying out common operations on files and folde \code{list_files} is a synonym for \code{list_items}. +\code{list_permissions} returns a list of permissions for a drive item. + +\code{list_versions} returns a list of drive item versions. + +\code{list_activities} returns a list of activities for a drive item. + \code{download} downloads the item to the local machine. If this is a file, it is downloaded; in this case, the \code{dest} argument can be the path to the destination file, or NULL to return the downloaded content in a raw vector. If the item is a folder, all its files are downloaded, including subfolders if the \code{recursive} argument is TRUE. \code{upload} uploads a file or folder from the local machine into the folder item. The \code{src} argument can be the path to the source file, a \link{rawConnection} or a \link{textConnection} object. If \code{src} is a folder, all its files are uploaded, including subfolders if the \code{recursive} argument iS TRUE. An \code{ms_drive_item} object is returned invisibly. From d7ebca00a41ce7180dc65ee7ce6b08b644573073 Mon Sep 17 00:00:00 2001 From: your name Date: Thu, 13 Jun 2024 10:24:35 -0400 Subject: [PATCH 02/18] Add create_link method to ms_list_item --- R/ms_list_item.R | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/R/ms_list_item.R b/R/ms_list_item.R index c75a791..ec6d90c 100644 --- a/R/ms_list_item.R +++ b/R/ms_list_item.R @@ -14,6 +14,7 @@ #' - `update(...)`: Update the item's properties (metadata) in Microsoft Graph. To update the list _data_, update the `fields` property. See the examples below. #' - `do_operation(...)`: Carry out an arbitrary operation on the item. #' - `sync_fields()`: Synchronise the R object with the item data and metadata in Microsoft Graph. +#' - `create_link()`: Create a shared link to a list item. #' #' @section Initialization: #' Creating new objects of this class should be done via the `get_item` method of the [`ms_list`] class. Calling the `new()` method for this class only constructs the R object; it does not call the Microsoft Graph API to retrieve or create the actual item. @@ -62,6 +63,15 @@ public=list( super$initialize(token, tenant, properties) }, + # https://learn.microsoft.com/en-us/graph/api/listitem-createlink + create_link = function() { + self$do_operation("createLink", http_verb = "POST") + }, + + # delete = function() { + # self$do_operation(http_verb = "DELETE") + # }, + print=function(...) { cat("\n", sep="") From 4b994464be2c147b65682f1bdabc7ddef7615f65 Mon Sep 17 00:00:00 2001 From: your name Date: Thu, 13 Jun 2024 10:25:53 -0400 Subject: [PATCH 03/18] Add get_analytics, list_columns, list_permission, and list_content_types Add get_analytics, list_columns, list_permission, and list_content_types methods to ms_site objects --- R/ms_site.R | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/R/ms_site.R b/R/ms_site.R index c43e267..0a5f4b8 100644 --- a/R/ms_site.R +++ b/R/ms_site.R @@ -109,6 +109,31 @@ public=list( az_group$new(self$token, self$tenant, res[[1]]) }, + get_analytics=function() + { + self$do_operation("analytics") + }, + + # https://learn.microsoft.com/en-us/graph/api/site-list-columns + # FIXME: Add support for OData parameters + list_columns=function() + { + self$do_operation("columns") + }, + + # https://learn.microsoft.com/en-us/graph/api/site-list-permissions?view=graph-rest-beta&tabs=http + # FIXME: Add support for OData parameters + list_permissions=function() + { + self$do_operation("permissions") + }, + + # https://learn.microsoft.com/en-us/graph/api/site-list-contenttypes?view=graph-rest-beta&tabs=http + list_content_types=function() + { + self$do_operation("contentTypes") + }, + print=function(...) { cat("\n", sep="") From d01dc5295216426a7ee00d30a4147eda688d500b Mon Sep 17 00:00:00 2001 From: your name Date: Mon, 17 Jun 2024 23:23:14 -0400 Subject: [PATCH 04/18] Add create_column method Also expose simplify parameter for get_column_info method --- R/ms_list.R | 14 +++++++++++--- man/ms_list.Rd | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/R/ms_list.R b/R/ms_list.R index 54b261d..c2ee2f2 100644 --- a/R/ms_list.R +++ b/R/ms_list.R @@ -15,7 +15,8 @@ #' - `do_operation(...)`: Carry out an arbitrary operation on the list. #' - `sync_fields()`: Synchronise the R object with the list metadata in Microsoft Graph. #' - `list_items(filter, select, all_metadata, as_data_frame, pagesize)`: Queries the list and returns items as a data frame. See 'List querying' below. -#' - `get_column_info()`: Return a data frame containing metadata on the columns (fields) in the list. +#' - `get_column_info(simplify)`: Return a list or data frame containing metadata on the columns (fields) in the list. +#' - `create_column(definition)`: Create a new column in the list. #' - `get_item(id)`: Get an individual list item. #' - `create_item(...)`: Create a new list item, using the named arguments as fields. #' - `update_item(id, ...)`: Update the _data_ fields in the given item, using the named arguments. To update the item's metadata, use `get_item()` to retrieve the item object, then call its `update()` method. @@ -134,12 +135,19 @@ public=list( invisible(lapply(seq_len(nrow(data)), function(i) do.call(self$create_item, data[i, , drop=FALSE]))) }, - get_column_info=function() + get_column_info=function(simplify=TRUE) { - res <- self$do_operation(options=list(expand="columns"), simplify=TRUE) + res <- self$do_operation(options=list(expand="columns"), simplify=simplify) res$columns }, + create_column=function(definition) + { + stopifnot(is.list(definition)) + res <- self$do_operation(options=list(expand="columns"), encode="json", body=definition, http_verb="POST") + res + }, + print=function(...) { cat("\n", sep="") diff --git a/man/ms_list.Rd b/man/ms_list.Rd index 6e2470a..76b858d 100644 --- a/man/ms_list.Rd +++ b/man/ms_list.Rd @@ -29,7 +29,8 @@ Class representing a list in a SharePoint site. \item \code{do_operation(...)}: Carry out an arbitrary operation on the list. \item \code{sync_fields()}: Synchronise the R object with the list metadata in Microsoft Graph. \item \code{list_items(filter, select, all_metadata, as_data_frame, pagesize)}: Queries the list and returns items as a data frame. See 'List querying' below. -\item \code{get_column_info()}: Return a data frame containing metadata on the columns (fields) in the list. +\item \code{get_column_info(simplify)}: Return a data frame containing metadata on the columns (fields) in the list. +\item \code{create_column()} \item \code{get_item(id)}: Get an individual list item. \item \code{create_item(...)}: Create a new list item, using the named arguments as fields. \item \code{update_item(id, ...)}: Update the \emph{data} fields in the given item, using the named arguments. To update the item's metadata, use \code{get_item()} to retrieve the item object, then call its \code{update()} method. From 28547f43d02af02e45619f0e07cda72dadc806a9 Mon Sep 17 00:00:00 2001 From: your name Date: Mon, 17 Jun 2024 23:23:22 -0400 Subject: [PATCH 05/18] Update docs for ms_list_item --- man/ms_list_item.Rd | 1 + 1 file changed, 1 insertion(+) diff --git a/man/ms_list_item.Rd b/man/ms_list_item.Rd index 1de1ffb..313984c 100644 --- a/man/ms_list_item.Rd +++ b/man/ms_list_item.Rd @@ -28,6 +28,7 @@ Class representing an item in a SharePoint list. \item \code{update(...)}: Update the item's properties (metadata) in Microsoft Graph. To update the list \emph{data}, update the \code{fields} property. See the examples below. \item \code{do_operation(...)}: Carry out an arbitrary operation on the item. \item \code{sync_fields()}: Synchronise the R object with the item data and metadata in Microsoft Graph. +\item \code{create_link()}: Create a shared link to a list item. } } From 801b99fee86eb776cf01a55379238f752389174e Mon Sep 17 00:00:00 2001 From: your name Date: Mon, 17 Jun 2024 23:29:20 -0400 Subject: [PATCH 06/18] Tidy DESCRIPTION Add missing Encoding: UTF-8 --- DESCRIPTION | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 13c71d5..07b9d2b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -3,38 +3,48 @@ Title: Interface to the 'Microsoft 365' Suite of Cloud Services Version: 2.4.0.9000 Authors@R: c( person("Hong", "Ooi", , "hongooi73@gmail.com", role = c("aut", "cre")), - person("Roman", "Zenka", role="ctb"), - person("Robert", "Ashton", role="ctb"), - person("Philip", "Zheng", role="ctb"), - person("Microsoft", role="cph") - ) -Description: An interface to the 'Microsoft 365' (formerly known as 'Office 365') suite of cloud services, building on the framework supplied by the 'AzureGraph' package. Enables access from R to data stored in 'Teams', 'SharePoint Online' and 'OneDrive', including the ability to list drive folder contents, upload and download files, send messages, and retrieve data lists. Also provides a full-featured 'Outlook' email client, with the ability to send emails and manage emails and mail folders. -URL: https://github.com/Azure/Microsoft365R https://github.com/Azure/AzureR -BugReports: https://github.com/Azure/Microsoft365R/issues + person("Roman", "Zenka", role = "ctb"), + person("Robert", "Ashton", role = "ctb"), + person("Philip", "Zheng", role = "ctb"), + person("Microsoft", role = "cph") + ) +Description: An interface to the 'Microsoft 365' (formerly known as + 'Office 365') suite of cloud services, building on the framework + supplied by the 'AzureGraph' package. Enables access from R to data + stored in 'Teams', 'SharePoint Online' and 'OneDrive', including the + ability to list drive folder contents, upload and download files, send + messages, and retrieve data lists. Also provides a full-featured + 'Outlook' email client, with the ability to send emails and manage + emails and mail folders. License: MIT + file LICENSE -VignetteBuilder: knitr +URL: https://github.com/Azure/Microsoft365R + https://github.com/Azure/AzureR +BugReports: https://github.com/Azure/Microsoft365R/issues Depends: R (>= 3.3) Imports: AzureAuth, AzureGraph (>= 1.3.1), - utils, - parallel, - tools, curl, httr, jsonlite, + mime, + parallel, R6, - vctrs, - mime + tools, + utils, + vctrs Suggests: - openssl, - knitr, - rmarkdown, - testthat, blastula, emayili, + knitr, + openssl, readr, - readxl + readxl, + rmarkdown, + testthat +VignetteBuilder: + knitr +Encoding: UTF-8 Roxygen: list(markdown=TRUE, r6=FALSE) RoxygenNote: 7.2.1 From bb93f0079e90d24cb1e869db3707a0039c992384 Mon Sep 17 00:00:00 2001 From: your name Date: Mon, 17 Jun 2024 23:32:41 -0400 Subject: [PATCH 07/18] Update ms_list docs --- R/ms_list.R | 2 +- man/ms_list.Rd | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/R/ms_list.R b/R/ms_list.R index c2ee2f2..2392dfa 100644 --- a/R/ms_list.R +++ b/R/ms_list.R @@ -15,7 +15,7 @@ #' - `do_operation(...)`: Carry out an arbitrary operation on the list. #' - `sync_fields()`: Synchronise the R object with the list metadata in Microsoft Graph. #' - `list_items(filter, select, all_metadata, as_data_frame, pagesize)`: Queries the list and returns items as a data frame. See 'List querying' below. -#' - `get_column_info(simplify)`: Return a list or data frame containing metadata on the columns (fields) in the list. +#' - `get_column_info(simplify=TRUE)`: Return a list or data frame containing metadata on the columns (fields) in the list. #' - `create_column(definition)`: Create a new column in the list. #' - `get_item(id)`: Get an individual list item. #' - `create_item(...)`: Create a new list item, using the named arguments as fields. diff --git a/man/ms_list.Rd b/man/ms_list.Rd index 76b858d..42c5b9a 100644 --- a/man/ms_list.Rd +++ b/man/ms_list.Rd @@ -29,8 +29,8 @@ Class representing a list in a SharePoint site. \item \code{do_operation(...)}: Carry out an arbitrary operation on the list. \item \code{sync_fields()}: Synchronise the R object with the list metadata in Microsoft Graph. \item \code{list_items(filter, select, all_metadata, as_data_frame, pagesize)}: Queries the list and returns items as a data frame. See 'List querying' below. -\item \code{get_column_info(simplify)}: Return a data frame containing metadata on the columns (fields) in the list. -\item \code{create_column()} +\item \code{get_column_info(simplify)}: Return a list or data frame containing metadata on the columns (fields) in the list. +\item \code{create_column(definition)}: Create a new column in the list. \item \code{get_item(id)}: Get an individual list item. \item \code{create_item(...)}: Create a new list item, using the named arguments as fields. \item \code{update_item(id, ...)}: Update the \emph{data} fields in the given item, using the named arguments. To update the item's metadata, use \code{get_item()} to retrieve the item object, then call its \code{update()} method. From 217fe6499d32f88b465b51034cd6c5f2ac5cbff0 Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:29:54 -0400 Subject: [PATCH 08/18] Add missing imports --- R/Microsoft365R.R | 4 ++++ R/ms_drive.R | 1 + R/ms_drive_item.R | 2 ++ R/ms_site.R | 1 + 4 files changed, 8 insertions(+) diff --git a/R/Microsoft365R.R b/R/Microsoft365R.R index 002520e..d3512ec 100644 --- a/R/Microsoft365R.R +++ b/R/Microsoft365R.R @@ -110,3 +110,7 @@ get_confirmation <- get("get_confirmation", getNamespace("AzureGraph")) # to combine paged results into a single data frame: individual pages can have # different structures, which will break base::rbind vctrs::vec_rbind + + +#' @importFrom R6 R6Class + diff --git a/R/ms_drive.R b/R/ms_drive.R index 854d755..c05ed12 100644 --- a/R/ms_drive.R +++ b/R/ms_drive.R @@ -160,6 +160,7 @@ #' } #' @format An R6 object of class `ms_drive`, inheriting from `ms_object`. #' @export +#' @importFrom curl curl_escape ms_drive <- R6::R6Class("ms_drive", inherit=ms_object, public=list( diff --git a/R/ms_drive_item.R b/R/ms_drive_item.R index 943bee9..3c3a4fa 100644 --- a/R/ms_drive_item.R +++ b/R/ms_drive_item.R @@ -158,6 +158,8 @@ #' } #' @format An R6 object of class `ms_drive_item`, inheriting from `ms_object`. #' @export +#' @importFrom parallel makeCluster stopCluster parLapply +#' @importFrom tools file_ext ms_drive_item <- R6::R6Class("ms_drive_item", inherit=ms_object, public=list( diff --git a/R/ms_site.R b/R/ms_site.R index 0a5f4b8..873b303 100644 --- a/R/ms_site.R +++ b/R/ms_site.R @@ -44,6 +44,7 @@ #' } #' @format An R6 object of class `ms_site`, inheriting from `ms_object`. #' @export +#' @importFrom curl curl_escape ms_site <- R6::R6Class("ms_site", inherit=ms_object, public=list( From 0953a06b13f7755b24f1472f8bf4169c8a58fd85 Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:32:23 -0400 Subject: [PATCH 09/18] Export methods to avoid warning w/ document --- R/build_chatmessage_body.R | 11 ++++++----- R/build_email_request.R | 8 +++++--- R/make_email_attachments.R | 8 +++++--- R/ms_outlook_email.R | 7 +++++-- R/normalize_src.R | 8 +++++--- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/R/build_chatmessage_body.R b/R/build_chatmessage_body.R index 17d4dcb..87b4077 100644 --- a/R/build_chatmessage_body.R +++ b/R/build_chatmessage_body.R @@ -72,13 +72,14 @@ build_chatmessage_body <- function(channel, body, content_type, attachments, inl call_body } - +#' @export +#' @keywords internal make_mention <- function(object, i) { UseMethod("make_mention") } - +#' @exportS3Method make_mention.az_user <- function(object, i) { name <- if(!is.null(object$properties$displayName)) @@ -99,7 +100,7 @@ make_mention.az_user <- function(object, i) ) } - +#' @exportS3Method make_mention.ms_team <- function(object, i) { list( @@ -115,7 +116,7 @@ make_mention.ms_team <- function(object, i) ) } - +#' @exportS3Method make_mention.ms_channel <- function(object, i) { list( @@ -131,7 +132,7 @@ make_mention.ms_channel <- function(object, i) ) } - +#' @exportS3Method make_mention.ms_team_member <- function(object, i) { make_mention(object$get_aaduser(), i) diff --git a/R/build_email_request.R b/R/build_email_request.R index f9012bd..6a064a2 100644 --- a/R/build_email_request.R +++ b/R/build_email_request.R @@ -1,11 +1,13 @@ # methods for different email formats: default, blastula, emayili +#' @export +#' @keywords internal build_email_request <- function(body, ...) { UseMethod("build_email_request") } - +#' @exportS3Method build_email_request.character <- function(body, content_type, subject=NULL, to=NA, cc=NA, bcc=NA, reply_to=NA, token=NULL, user_id=NULL, ...) { @@ -21,7 +23,7 @@ build_email_request.character <- function(body, content_type, utils::modifyList(req, build_email_recipients(to, cc, bcc, reply_to)) } - +#' @exportS3Method build_email_request.blastula_message <- function(body, content_type, subject=NULL, to=NA, cc=NA, bcc=NA, reply_to=NA, token=NULL, user_id=NULL, ...) { @@ -37,7 +39,7 @@ build_email_request.blastula_message <- function(body, content_type, utils::modifyList(req, build_email_recipients(to, cc, bcc, reply_to)) } - +#' @exportS3Method build_email_request.envelope <- function(body, token=NULL, user_id=NULL, ...) { require_emayili_0.6() diff --git a/R/make_email_attachments.R b/R/make_email_attachments.R index 17baa46..462c552 100644 --- a/R/make_email_attachments.R +++ b/R/make_email_attachments.R @@ -1,9 +1,11 @@ +#' @export +#' @keywords internal add_external_attachments <- function(object, email) { UseMethod("add_external_attachments") } - +#' @exportS3Method add_external_attachments.blastula_message <- function(object, email) { for(a in object$attachments) @@ -28,7 +30,7 @@ add_external_attachments.blastula_message <- function(object, email) } } - +#' @exportS3Method add_external_attachments.envelope <- function(object, email) { require_emayili_0.6() @@ -60,7 +62,7 @@ add_external_attachments.envelope <- function(object, email) } } - +#' @exportS3Method add_external_attachments.default <- function(object, email) { # do nothing if message object is not a recognised class (from blastula or emayili) diff --git a/R/ms_outlook_email.R b/R/ms_outlook_email.R index 2006bca..f64d9eb 100644 --- a/R/ms_outlook_email.R +++ b/R/ms_outlook_email.R @@ -527,24 +527,27 @@ format_email_date <- function(datestr) } +#' @export +#' @keywords internal make_reply_comment <- function(comment) { UseMethod("make_reply_comment") } +#' @exportS3Method make_reply_comment.default <- function(comment) { as.character(comment) } - +#' @exportS3Method make_reply_comment.blastula_message <- function(comment) { comment$html_str } - +#' @exportS3Method make_reply_comment.envelope <- function(comment) { parts <- comment$parts diff --git a/R/normalize_src.R b/R/normalize_src.R index ba0e12f..d55d91a 100644 --- a/R/normalize_src.R +++ b/R/normalize_src.R @@ -1,9 +1,11 @@ +#' @keywords internal +#' @export normalize_src <- function(src) { UseMethod("normalize_src") } - +#' @exportS3Method normalize_src.character <- function(src) { con <- file(src, open="rb") @@ -11,7 +13,7 @@ normalize_src.character <- function(src) list(con=con, size=size) } - +#' @exportS3Method normalize_src.textConnection <- function(src) { # convert to raw connection @@ -21,7 +23,7 @@ normalize_src.textConnection <- function(src) list(con=con, size=size) } - +#' @exportS3Method normalize_src.rawConnection <- function(src) { # need to read the data to get object size (!) From 10fa4a48a635afb6ffea59737da259e5ed47235b Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:38:19 -0400 Subject: [PATCH 10/18] Add get_pages method to ms_site --- R/ms_site.R | 13 +++++++++++++ man/ms_site.Rd | 1 + 2 files changed, 14 insertions(+) diff --git a/R/ms_site.R b/R/ms_site.R index 873b303..474f406 100644 --- a/R/ms_site.R +++ b/R/ms_site.R @@ -17,6 +17,7 @@ #' - `list_drives(filter=NULL, n=Inf)`: List the drives (shared document libraries) associated with this site. #' - `get_drive(drive_name, drive_id)`: Retrieve a shared document library for this site. If the name and ID are not specified, this returns the default document library. #' - `list_subsites(filter=NULL, n=Inf)`: List the subsites of this site. +#' - `get_pages(type = c("sitePage", "page"))`: Returns SharePoint pages for this site. #' - `get_lists(filter=NULL, n=Inf)`: Returns the lists that are part of this site. #' - `get_list(list_name, list_id)`: Returns a specific list, either by name or ID. #' - `get_group()`: Retrieve the Microsoft 365 group associated with the site, if it exists. A site that backs a private Teams channel will not have a group associated with it. @@ -115,6 +116,18 @@ public=list( self$do_operation("analytics") }, + get_pages=function(type = c("sitePage", "page")) + { + type <- match.arg(type) + + op <- switch (type, + page = "pages", + sitePage = "pages/microsoft.graph.sitePage" + ) + + self$do_operation(op) + }, + # https://learn.microsoft.com/en-us/graph/api/site-list-columns # FIXME: Add support for OData parameters list_columns=function() diff --git a/man/ms_site.Rd b/man/ms_site.Rd index 03ed4ac..3259eae 100644 --- a/man/ms_site.Rd +++ b/man/ms_site.Rd @@ -31,6 +31,7 @@ Class representing a SharePoint site. \item \code{list_drives(filter=NULL, n=Inf)}: List the drives (shared document libraries) associated with this site. \item \code{get_drive(drive_name, drive_id)}: Retrieve a shared document library for this site. If the name and ID are not specified, this returns the default document library. \item \code{list_subsites(filter=NULL, n=Inf)}: List the subsites of this site. +\item \code{get_pages(type = c("sitePage", "page"))}: Returns SharePoint pages for this site. \item \code{get_lists(filter=NULL, n=Inf)}: Returns the lists that are part of this site. \item \code{get_list(list_name, list_id)}: Returns a specific list, either by name or ID. \item \code{get_group()}: Retrieve the Microsoft 365 group associated with the site, if it exists. A site that backs a private Teams channel will not have a group associated with it. From 697ae77c55ff1e73d8c957f34c7d39da47883aa8 Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:40:58 -0400 Subject: [PATCH 11/18] Don't export methods just use noRd --- R/build_chatmessage_body.R | 11 +++++------ R/build_email_request.R | 9 ++++----- R/ms_outlook_email.R | 9 ++++----- R/normalize_src.R | 9 ++++----- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/R/build_chatmessage_body.R b/R/build_chatmessage_body.R index 87b4077..ebe551c 100644 --- a/R/build_chatmessage_body.R +++ b/R/build_chatmessage_body.R @@ -72,14 +72,13 @@ build_chatmessage_body <- function(channel, body, content_type, attachments, inl call_body } -#' @export -#' @keywords internal +#' @noRd make_mention <- function(object, i) { UseMethod("make_mention") } -#' @exportS3Method +#' @noRd make_mention.az_user <- function(object, i) { name <- if(!is.null(object$properties$displayName)) @@ -100,7 +99,7 @@ make_mention.az_user <- function(object, i) ) } -#' @exportS3Method +#' @noRd make_mention.ms_team <- function(object, i) { list( @@ -116,7 +115,7 @@ make_mention.ms_team <- function(object, i) ) } -#' @exportS3Method +#' @noRd make_mention.ms_channel <- function(object, i) { list( @@ -132,7 +131,7 @@ make_mention.ms_channel <- function(object, i) ) } -#' @exportS3Method +#' @noRd make_mention.ms_team_member <- function(object, i) { make_mention(object$get_aaduser(), i) diff --git a/R/build_email_request.R b/R/build_email_request.R index 6a064a2..4d173b6 100644 --- a/R/build_email_request.R +++ b/R/build_email_request.R @@ -1,13 +1,12 @@ # methods for different email formats: default, blastula, emayili -#' @export -#' @keywords internal +#' @noRd build_email_request <- function(body, ...) { UseMethod("build_email_request") } -#' @exportS3Method +#' @noRd build_email_request.character <- function(body, content_type, subject=NULL, to=NA, cc=NA, bcc=NA, reply_to=NA, token=NULL, user_id=NULL, ...) { @@ -23,7 +22,7 @@ build_email_request.character <- function(body, content_type, utils::modifyList(req, build_email_recipients(to, cc, bcc, reply_to)) } -#' @exportS3Method +#' @noRd build_email_request.blastula_message <- function(body, content_type, subject=NULL, to=NA, cc=NA, bcc=NA, reply_to=NA, token=NULL, user_id=NULL, ...) { @@ -39,7 +38,7 @@ build_email_request.blastula_message <- function(body, content_type, utils::modifyList(req, build_email_recipients(to, cc, bcc, reply_to)) } -#' @exportS3Method +#' @noRd build_email_request.envelope <- function(body, token=NULL, user_id=NULL, ...) { require_emayili_0.6() diff --git a/R/ms_outlook_email.R b/R/ms_outlook_email.R index f64d9eb..52f288a 100644 --- a/R/ms_outlook_email.R +++ b/R/ms_outlook_email.R @@ -527,27 +527,26 @@ format_email_date <- function(datestr) } -#' @export -#' @keywords internal +#' @noRd make_reply_comment <- function(comment) { UseMethod("make_reply_comment") } -#' @exportS3Method +#' @noRd make_reply_comment.default <- function(comment) { as.character(comment) } -#' @exportS3Method +#' @noRd make_reply_comment.blastula_message <- function(comment) { comment$html_str } -#' @exportS3Method +#' @noRd make_reply_comment.envelope <- function(comment) { parts <- comment$parts diff --git a/R/normalize_src.R b/R/normalize_src.R index d55d91a..2d53403 100644 --- a/R/normalize_src.R +++ b/R/normalize_src.R @@ -1,11 +1,10 @@ -#' @keywords internal -#' @export +#' @noRd normalize_src <- function(src) { UseMethod("normalize_src") } -#' @exportS3Method +#' @noRd normalize_src.character <- function(src) { con <- file(src, open="rb") @@ -13,7 +12,7 @@ normalize_src.character <- function(src) list(con=con, size=size) } -#' @exportS3Method +#' @noRd normalize_src.textConnection <- function(src) { # convert to raw connection @@ -23,7 +22,7 @@ normalize_src.textConnection <- function(src) list(con=con, size=size) } -#' @exportS3Method +#' @noRd normalize_src.rawConnection <- function(src) { # need to read the data to get object size (!) From d6f3259b4cac8f04f941d1fd13526ec11e27cfcc Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:41:38 -0400 Subject: [PATCH 12/18] use noRd not exportS3Method --- R/make_email_attachments.R | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/R/make_email_attachments.R b/R/make_email_attachments.R index 462c552..220fd87 100644 --- a/R/make_email_attachments.R +++ b/R/make_email_attachments.R @@ -1,11 +1,10 @@ -#' @export -#' @keywords internal +#' @noRd add_external_attachments <- function(object, email) { UseMethod("add_external_attachments") } -#' @exportS3Method +#' @noRd add_external_attachments.blastula_message <- function(object, email) { for(a in object$attachments) @@ -30,7 +29,7 @@ add_external_attachments.blastula_message <- function(object, email) } } -#' @exportS3Method +#' @noRd add_external_attachments.envelope <- function(object, email) { require_emayili_0.6() @@ -62,7 +61,7 @@ add_external_attachments.envelope <- function(object, email) } } -#' @exportS3Method +#' @noRd add_external_attachments.default <- function(object, email) { # do nothing if message object is not a recognised class (from blastula or emayili) From 1c85216289fed878122d114ab603987a7a3822f9 Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:41:51 -0400 Subject: [PATCH 13/18] Update NAMESPACE --- NAMESPACE | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index 6c48147..1ba6a82 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -31,3 +31,8 @@ export(ms_team_member) export(personal_onedrive) export(sharepoint_site) import(AzureGraph) +importFrom(curl,curl_escape) +importFrom(parallel,makeCluster) +importFrom(parallel,parLapply) +importFrom(parallel,stopCluster) +importFrom(tools,file_ext) From 7a9bbdad436ecb97735c096849146bac614ff29f Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:41:59 -0400 Subject: [PATCH 14/18] Update ms_list docs --- man/ms_list.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/ms_list.Rd b/man/ms_list.Rd index 42c5b9a..b7356d6 100644 --- a/man/ms_list.Rd +++ b/man/ms_list.Rd @@ -29,7 +29,7 @@ Class representing a list in a SharePoint site. \item \code{do_operation(...)}: Carry out an arbitrary operation on the list. \item \code{sync_fields()}: Synchronise the R object with the list metadata in Microsoft Graph. \item \code{list_items(filter, select, all_metadata, as_data_frame, pagesize)}: Queries the list and returns items as a data frame. See 'List querying' below. -\item \code{get_column_info(simplify)}: Return a list or data frame containing metadata on the columns (fields) in the list. +\item \code{get_column_info(simplify=TRUE)}: Return a list or data frame containing metadata on the columns (fields) in the list. \item \code{create_column(definition)}: Create a new column in the list. \item \code{get_item(id)}: Get an individual list item. \item \code{create_item(...)}: Create a new list item, using the named arguments as fields. From 97bc86b1456b6935c8b0fc28322d637aa7036cf1 Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:42:12 -0400 Subject: [PATCH 15/18] Add Eli Pousson as contributor --- DESCRIPTION | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 07b9d2b..9d9b958 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -6,6 +6,8 @@ Authors@R: c( person("Roman", "Zenka", role = "ctb"), person("Robert", "Ashton", role = "ctb"), person("Philip", "Zheng", role = "ctb"), + person("Eli", "Pousson", , "eli.pousson@gmail.com", role = "ctb", + comment = c(ORCID = "0000-0001-8280-1706")), person("Microsoft", role = "cph") ) Description: An interface to the 'Microsoft 365' (formerly known as @@ -47,4 +49,4 @@ VignetteBuilder: knitr Encoding: UTF-8 Roxygen: list(markdown=TRUE, r6=FALSE) -RoxygenNote: 7.2.1 +RoxygenNote: 7.3.2 From d9cb70200497c6628eca7774459ba2d49f2d5ce3 Mon Sep 17 00:00:00 2001 From: your name Date: Tue, 20 Aug 2024 12:51:44 -0400 Subject: [PATCH 16/18] Update NEWS w/ additional methods --- NEWS.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/NEWS.md b/NEWS.md index 5aab98b..3d154cc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,11 +5,21 @@ - In the `ms_drive_item$load_dataframe()` method, pass the `...` argument to `read_delim`. - Add the ability to load Excel files (with extension .xls or .xlsx) to the `ms_drive_item$load_dataframe()` method. This requires the readxl package to be installed. - Fix a bug in downloading shared files in business SharePoint/OneDrive (#189) +- Expose `simplify` argument for `ms_list$get_column_info()` method. +- Add `ms_list$create_link()` method for creating a shared link to a list item. +- Add `ms_list$create_column()` method. +- Add `ms_site$get_pages()` method (#190) +- Add `ms_site$get_analytics()`, `ms_site$list_permissions()`, and `ms_site$list_content_types()` methods. (#209) +- Add `ms_drive$list_activities()` (#209) ## Planner - Fix a bug in the `ms_plan$get_details()` method. +## Other + +- Add Eli Pousson to contributors. + # Microsoft365R 2.4.0 ## OneDrive/SharePoint From cc9b205e5649bfb662114f2c32120cd2149ca70a Mon Sep 17 00:00:00 2001 From: Eli Pousson Date: Thu, 24 Oct 2024 21:19:05 -0400 Subject: [PATCH 17/18] Add select argument to list_items method --- R/ms_drive_item.R | 12 ++++++++---- man/ms_drive_item.Rd | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/R/ms_drive_item.R b/R/ms_drive_item.R index 3c3a4fa..625ba0d 100644 --- a/R/ms_drive_item.R +++ b/R/ms_drive_item.R @@ -41,11 +41,11 @@ #' #' `open` opens this file or folder in your browser. If the file has an unrecognised type, most browsers will attempt to download it. #' -#' `list_items(path, info, full_names, filter, n, pagesize)` lists the items under the specified path. It is the analogue of base R's `dir`/`list.files`. Its arguments are +#' `list_items(path, info, full_names, filter, select, n, pagesize)` lists the items under the specified path. It is the analogue of base R's `dir`/`list.files`. Its arguments are #' - `path`: The path. -#' - `info`: The information to return: either "partial", "name" or "all". If "partial", a data frame is returned containing the name, size, ID and whether the item is a file or folder. If "name", a vector of file/folder names is returned. If "all", a data frame is returned containing _all_ the properties for each item (this can be large). +#' - `info`: The information to return: either "partial", "name" or "all". If "partial", a data frame is returned containing the name, size, ID and whether the item is a file or folder. If "name", a vector of file/folder names is returned (and any value passed to `select` is ignored). If "all", a data frame is returned containing _all_ the properties for each item (this can be large). Supply `select` (if info is "partial" pr "all") to specify which columns to include in the returned data frame. #' - `full_names`: Whether to prefix the folder path to the names of the items. -#' - `filter, n`: See 'List methods' below. +#' - `filter, select, n`: See 'List methods' below. #' - `pagesize`: The number of results to return for each call to the REST endpoint. You can try reducing this argument below the default of 1000 if you are experiencing timeouts. #' #' `list_files` is a synonym for `list_items`. @@ -256,7 +256,7 @@ public=list( else res$link$webUrl }, - list_items=function(path="", info=c("partial", "name", "all"), full_names=FALSE, filter=NULL, n=Inf, pagesize=1000) + list_items=function(path="", info=c("partial", "name", "all"), full_names=FALSE, filter=NULL, select=NULL, n=Inf, pagesize=1000) { private$assert_is_folder() if(path == "/") @@ -267,6 +267,10 @@ public=list( name=list(`$select`="name", `$top`=pagesize), list(`$top`=pagesize) ) + + if (!is.null(select) && info != "name") + opts$`$select` <- paste0(select, collapse = ",") + if(!is.null(filter)) opts$`filter` <- filter diff --git a/man/ms_drive_item.Rd b/man/ms_drive_item.Rd index 288196d..6eb0b79 100644 --- a/man/ms_drive_item.Rd +++ b/man/ms_drive_item.Rd @@ -60,12 +60,12 @@ This class exposes methods for carrying out common operations on files and folde \code{open} opens this file or folder in your browser. If the file has an unrecognised type, most browsers will attempt to download it. -\code{list_items(path, info, full_names, filter, n, pagesize)} lists the items under the specified path. It is the analogue of base R's \code{dir}/\code{list.files}. Its arguments are +\code{list_items(path, info, full_names, filter, select, n, pagesize)} lists the items under the specified path. It is the analogue of base R's \code{dir}/\code{list.files}. Its arguments are \itemize{ \item \code{path}: The path. -\item \code{info}: The information to return: either "partial", "name" or "all". If "partial", a data frame is returned containing the name, size, ID and whether the item is a file or folder. If "name", a vector of file/folder names is returned. If "all", a data frame is returned containing \emph{all} the properties for each item (this can be large). +\item \code{info}: The information to return: either "partial", "name" or "all". If "partial", a data frame is returned containing the name, size, ID and whether the item is a file or folder. If "name", a vector of file/folder names is returned (and any value passed to \code{select} is ignored). If "all", a data frame is returned containing \emph{all} the properties for each item (this can be large). Supply \code{select} (if info is "partial" pr "all") to specify which columns to include in the returned data frame. \item \code{full_names}: Whether to prefix the folder path to the names of the items. -\item \verb{filter, n}: See 'List methods' below. +\item \verb{filter, select, n}: See 'List methods' below. \item \code{pagesize}: The number of results to return for each call to the REST endpoint. You can try reducing this argument below the default of 1000 if you are experiencing timeouts. } From 1d9d130327fce3c379d3c33d02ae0b8c31e3acbd Mon Sep 17 00:00:00 2001 From: Eli Pousson Date: Thu, 24 Oct 2024 21:21:53 -0400 Subject: [PATCH 18/18] Update NEWS w/ info re: list_items method change --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 3d154cc..1bdb4f9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,7 @@ - In the `ms_drive_item$load_dataframe()` method, pass the `...` argument to `read_delim`. - Add the ability to load Excel files (with extension .xls or .xlsx) to the `ms_drive_item$load_dataframe()` method. This requires the readxl package to be installed. - Fix a bug in downloading shared files in business SharePoint/OneDrive (#189) +- Expose `select` argument for `ms_drive$list_items()` method (ignored when `info="name"`). - Expose `simplify` argument for `ms_list$get_column_info()` method. - Add `ms_list$create_link()` method for creating a shared link to a list item. - Add `ms_list$create_column()` method.