1+ get_gist_pages <- function (user ) {
12
2- get_gist_pages <- function ( user ){
3+ req_user <- httr :: GET( glue :: glue( " https://api.github.com/users/{ user} " ))
34
4- req_user <- httr :: GET(
5- glue :: glue(" https://api.github.com/users/{user}" )
6- )
5+ # Check HTTP response first
6+ if (httr :: status_code(req_user ) != 200 ) {
7+ warning(" Failed to fetch GitHub user info for '\" , user,\" ' (status " , httr :: status_code(req_user ), " ). Returning 0 pages." )
8+ return (0L )
9+ }
710
8- num_gists <- httr :: content(req_user )$ public_gists
11+ body <- httr :: content(req_user )
12+ num_gists <- body $ public_gists
913
10- # Number of pages to do (assuming 100 per page)
11- num_pages <- num_gists %/% 100
12- remainder <- num_gists %% 100
13- if ( remainder > 0 ) num_pages <- num_pages + 1
14+ # Defensive handling: ensure we have a single non-negative integer
15+ if (is.null( num_gists ) || length( num_gists ) == 0 ) return ( 0L )
16+ num_gists <- as.integer( num_gists )
17+ if (is.na( num_gists ) || num_gists < = 0L ) return ( 0L )
1418
19+ # Compute pages using ceiling to avoid remainder logic problems
20+ num_pages <- ceiling(num_gists / 100 )
1521 num_pages
1622}
1723
18- get_gist_content <- function (user ){
24+ get_gist_content <- function (user ) {
1925
2026 num_pages <- get_gist_pages(user )
2127
28+ # If there are no pages, return an empty list
29+ if (num_pages == 0L ) return (list ())
30+
2231 # gists themselves
2332 req_content <- vector(" list" , num_pages )
2433
25- for (i in seq_len(num_pages )){
34+ for (i in seq_len(num_pages )) {
35+
36+ req <- httr :: GET(
37+ glue :: glue(" https://api.github.com/users/{user}/gists" ),
38+ query = list (per_page = 100 , page = i )
39+ )
2640
27- req <- httr :: GET(glue :: glue(" https://api.github.com/users/{user}/gists" ),
28- query = list (per_page = 100 ,
29- page = i ))
41+ if (httr :: status_code(req ) != 200 ) {
42+ warning(" Failed to fetch gists for page " , i , " (status " , httr :: status_code(req ), " ). Skipping page." )
43+ req_content [[i ]] <- list ()
44+ next
45+ }
3046
3147 req_content [[i ]] <- httr :: content(req )
3248 }
3349
3450 purrr :: flatten(req_content )
35-
3651}
3752
38- # ' List Github Gists of User
39- # '
40- # ' Given a username, return a dataframe with paths to all the gists by that user.
41- # '
42- # ' @param user Character string of username whose github gists you want to pull.
43- # ' @param pattern Regex pattern to keep only matching files. Default is
44- # ' `stringr::regex("(r|rmd|rmarkdown|qmd)$", ignore_case = TRUE)` which will
45- # ' keep only R, Rmarkdown and Quarto documents. If you have a lot of .md gists
46- # ' that can be converted to .R files you may want to edit this argument. To
47- # ' keep all files use `"."`.
48- # '
49- # ' @return Dataframe with `relative_paths` and `absolute_paths` of file paths.
50- # ' Because gists do not exist in a folder structure `relative_paths` will
51- # ' generally just be a file name. `absolute_paths` a url to the raw file. See
52- # ' `unnest_results()` for helper to put into an easier to read format.
53- # '
54- # ' @seealso [list_files_github_repo()], [list_files_wd()]
55- # ' @export
56- # '
57- # ' @examples
58- # ' \donttest{
59- # ' library(dplyr)
60- # ' library(funspotr)
61- # '
62- # ' # pulling and analyzing my R file github gists
63- # ' gists_urls <- list_files_github_gists("brshallo", pattern = ".")
64- # '
65- # ' # Will just parse the first 2 files/gists
66- # ' # Note that is easy to hit the API limit if have lots of gists
67- # ' contents <- filter(gists_urls, str_detect_r_docs(absolute_paths)) %>%
68- # ' slice(1:2) %>%
69- # ' spot_funs_files()
70- # '
71- # '
72- # ' contents %>%
73- # ' unnest_results()
74- # ' }
7553list_files_github_gists <- function (user ,
76- pattern = stringr :: regex(" (r|rmd|rmarkdown|qmd)$" , ignore_case = TRUE )){
54+ pattern = stringr :: regex(" (r|rmd|rmarkdown|qmd)$" , ignore_case = TRUE )) {
7755
7856 content <- get_gist_content(user )
7957
58+ # If nothing returned, return an empty tibble with the same columns
59+ if (length(content ) == 0 ) {
60+ return (tibble :: tibble(relative_paths = character (), absolute_paths = character ()))
61+ }
62+
8063 raw_urls <- content %> %
8164 map(" files" ) %> %
8265 map(1 ) %> %
@@ -85,13 +68,4 @@ list_files_github_gists <- function(user,
8568 output <- tibble(relative_paths = fs :: path_file(raw_urls ), absolute_paths = raw_urls )
8669
8770 filter(output , str_detect_r_docs(.data $ relative_paths , pattern = pattern , rmv_index = FALSE ))
88- }
89-
90-
91- # ' #' `r lifecycle::badge("deprecated")`
92- # ' #'
93- # ' #' This function was deprecated with updates to the API that improved
94- # ' #' consistency of naming conventions.
95- # ' github_gists <- function(user, drop_non_r = TRUE){
96- # ' list_files_github_gists(user, drop_non_r)
97- # ' }
71+ }
0 commit comments