From 0361ad63cbd080bff1d9841b2577997ade1cd1ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 17:26:53 +0000 Subject: [PATCH 1/4] Initial plan From 54820a168ab959b6576216c21131e9b89abbfeb9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 17:32:32 +0000 Subject: [PATCH 2/4] Implement list_user_activity_stream function Co-authored-by: tin900 <113692500+tin900@users.noreply.github.com> --- R/list_user_activity_stream.R | 54 +++++++++++++++++++++++++++++++++++ TODO.md | 4 +-- _pkgdown.yml | 5 ++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 R/list_user_activity_stream.R diff --git a/R/list_user_activity_stream.R b/R/list_user_activity_stream.R new file mode 100644 index 0000000..87ea91c --- /dev/null +++ b/R/list_user_activity_stream.R @@ -0,0 +1,54 @@ +#' List User Activity Stream +#' +#' Retrieves the activity stream (recent activities/stories) for a specified user from the Canvas LMS API. +#' The activity stream contains recent activities such as assignments, discussions, announcements, and other course interactions. +#' +#' @param canvas A list containing the 'api_key' and 'base_url' for authentication. +#' @param user_id The ID of the user whose activity stream to retrieve. Defaults to "self" for the authenticated user. +#' @param per_page Number of activity items to retrieve per page. Default is 100. +#' @param ... Additional parameters to pass to the API request. +#' +#' @return A list of activity stream objects retrieved from the Canvas LMS API. Each object represents a story/activity. +#' +#' @details +#' The activity stream returns Canvas "stories" which are activity objects that represent recent user activities. +#' These may include course activities, announcements, assignment submissions, discussion posts, and other interactions. +#' +#' The API endpoint used is: \code{GET /api/v1/users/:user_id/activity_stream} +#' +#' @examples +#' \dontrun{ +#' # Get activity stream for the authenticated user +#' canvas <- canvas_authenticate() +#' activities <- list_user_activity_stream(canvas) +#' +#' # Get activity stream for a specific user +#' activities <- list_user_activity_stream(canvas, user_id = "12345") +#' +#' # Get activity stream with custom pagination +#' activities <- list_user_activity_stream(canvas, per_page = 50) +#' } +#' +#' @seealso +#' \url{https://canvas.instructure.com/doc/api/users.html#method.users.activity_stream} +#' +#' @export +list_user_activity_stream <- function(canvas, user_id = "self", per_page = 100, ...) { + # Construct the API endpoint URL + url <- paste0(canvas$base_url, "/api/v1/users/", user_id, "/activity_stream?per_page=", per_page) + + # Make the API request + response <- httr::GET(url, httr::add_headers(Authorization = paste("Bearer", canvas$api_key))) + + # Check the response status code + if (httr::status_code(response) != 200) { + stop("Failed to retrieve user activity stream. Please check your authentication and API endpoint.") + } + + # Parse the response as JSON + activity_stream <- httr::content(response, "text", encoding = "UTF-8") %>% + jsonlite::fromJSON(flatten = TRUE) + + # Return the activity stream + return(activity_stream) +} \ No newline at end of file diff --git a/TODO.md b/TODO.md index 2d33507..7a0a14d 100644 --- a/TODO.md +++ b/TODO.md @@ -2632,10 +2632,10 @@ - [ ] List users in account UsersController#api_index ; GET /api/v1/accounts/:account_id/users -- [ ] List the activity stream UsersController#activity_stream ; +- [x] List the activity stream UsersController#activity_stream ; GET /api/v1/users/self/activity_stream -- [ ] List the activity stream UsersController#activity_stream ; +- [x] List the activity stream UsersController#activity_stream ; GET /api/v1/users/activity_stream - [ ] Activity stream summary UsersController#activity_stream_summary ; diff --git a/_pkgdown.yml b/_pkgdown.yml index 51aa6eb..066ceaf 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -1304,6 +1304,11 @@ reference: # - get_document_annotations_read_state # - mark_document_annotations_as_read # - submission_summary +- title: Users + desc: > + Manage users and user activities. + contents: + - list_user_activity_stream # title: Custom Data # desc: > # Manage custom data. From 1f3539ae495c33357b0b0704a4bd36b1f64253a4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 19 Jul 2025 17:34:11 +0000 Subject: [PATCH 3/4] Enhanced parameter handling for list_user_activity_stream Co-authored-by: tin900 <113692500+tin900@users.noreply.github.com> --- R/list_user_activity_stream.R | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/R/list_user_activity_stream.R b/R/list_user_activity_stream.R index 87ea91c..63d4973 100644 --- a/R/list_user_activity_stream.R +++ b/R/list_user_activity_stream.R @@ -34,11 +34,14 @@ #' #' @export list_user_activity_stream <- function(canvas, user_id = "self", per_page = 100, ...) { - # Construct the API endpoint URL - url <- paste0(canvas$base_url, "/api/v1/users/", user_id, "/activity_stream?per_page=", per_page) + # Construct the base API endpoint URL + url <- paste0(canvas$base_url, "/api/v1/users/", user_id, "/activity_stream") + + # Build query parameters + query_params <- list(per_page = per_page, ...) # Make the API request - response <- httr::GET(url, httr::add_headers(Authorization = paste("Bearer", canvas$api_key))) + response <- httr::GET(url, query = query_params, httr::add_headers(Authorization = paste("Bearer", canvas$api_key))) # Check the response status code if (httr::status_code(response) != 200) { From 1e58ba3f3c69e7dde98cad28eb1ab3b8e63e1726 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 23 Jul 2025 13:53:14 +0000 Subject: [PATCH 4/4] Update list_user_activity_stream to use paginate function Co-authored-by: tin900 <113692500+tin900@users.noreply.github.com> --- R/list_user_activity_stream.R | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/R/list_user_activity_stream.R b/R/list_user_activity_stream.R index 63d4973..4f74c8f 100644 --- a/R/list_user_activity_stream.R +++ b/R/list_user_activity_stream.R @@ -8,12 +8,14 @@ #' @param per_page Number of activity items to retrieve per page. Default is 100. #' @param ... Additional parameters to pass to the API request. #' -#' @return A list of activity stream objects retrieved from the Canvas LMS API. Each object represents a story/activity. +#' @return A data frame of activity stream objects retrieved from the Canvas LMS API. Each row represents a story/activity. Uses pagination to retrieve all available results. #' #' @details #' The activity stream returns Canvas "stories" which are activity objects that represent recent user activities. #' These may include course activities, announcements, assignment submissions, discussion posts, and other interactions. #' +#' This function uses pagination to automatically retrieve all available activity stream items across multiple pages. +#' #' The API endpoint used is: \code{GET /api/v1/users/:user_id/activity_stream} #' #' @examples @@ -43,14 +45,16 @@ list_user_activity_stream <- function(canvas, user_id = "self", per_page = 100, # Make the API request response <- httr::GET(url, query = query_params, httr::add_headers(Authorization = paste("Bearer", canvas$api_key))) - # Check the response status code - if (httr::status_code(response) != 200) { - stop("Failed to retrieve user activity stream. Please check your authentication and API endpoint.") - } + # Use pagination helper to get all pages + responses <- paginate(response, canvas$api_key) - # Parse the response as JSON - activity_stream <- httr::content(response, "text", encoding = "UTF-8") %>% - jsonlite::fromJSON(flatten = TRUE) + # Parse and combine all results + activity_list <- lapply(responses, function(resp) { + httr::content(resp, "text", encoding = "UTF-8") %>% + jsonlite::fromJSON(flatten = TRUE) %>% + as.data.frame() + }) + activity_stream <- dplyr::bind_rows(activity_list) # Return the activity stream return(activity_stream)