Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ Imports:
openxlsx,
tidyr,
rvest,
readr
readr,
cli
Suggests:
gargle,
gitcreds,
Expand Down
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ export(ga_query_explorer)
export(get_core_project_info)
export(get_ga_basic)
export(get_ga_meta_by_id)
export(get_ga_summary)
export(get_github_by_topic)
export(get_github_by_topic_graphql)
export(icite)
import(dplyr)
import(httr2)
import(jsonlite)
importFrom(cli,cli_progress_bar)
importFrom(cli,cli_progress_done)
importFrom(cli,cli_progress_update)
importFrom(dplyr,arrange)
importFrom(dplyr,as_tibble)
importFrom(dplyr,bind_rows)
Expand All @@ -28,6 +32,7 @@ importFrom(glue,glue)
importFrom(glue,glue_collapse)
importFrom(googleAnalyticsR,ga_account_list)
importFrom(googleAnalyticsR,ga_auth)
importFrom(googleAnalyticsR,ga_data)
importFrom(httr2,req_auth_bearer_token)
importFrom(httr2,req_body_json)
importFrom(httr2,req_error)
Expand All @@ -36,6 +41,7 @@ importFrom(httr2,req_method)
importFrom(httr2,req_perform)
importFrom(httr2,req_perform_parallel)
importFrom(httr2,req_retry)
importFrom(httr2,req_throttle)
importFrom(httr2,req_url_query)
importFrom(httr2,request)
importFrom(httr2,resp_body_json)
Expand Down
31 changes: 31 additions & 0 deletions R/ga_summary.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#' Get summary metrics from Google Analytics
#'
#' This function retrieves summary metrics from Google Analytics,
#' including total users, new users, engaged sessions, engagement rate,
#' event count, and screen page views.
#'
#' @param propertyId The Google Analytics property ID
#' @param start_date The start date for the data retrieval (e.g., "30daysAgo")
#' @param end_date The end date for the data retrieval (e.g., "yesterday")
#'
#' @importFrom googleAnalyticsR ga_data
#' @importFrom dplyr mutate
#'
#' @return A tibble containing the summary metrics
#' @export
get_ga_summary <- function(propertyId, start_date = "30daysAgo", end_date = "yesterday") {
ga_data(
propertyId,
metrics = c(
"totalUsers",
"newUsers",
"engagedSessions",
"engagementRate",
"eventCount",
"screenPageViews"
),
dimensions = "date",
date_range = c(start_date, end_date)
) |>
mutate(propertyId = propertyId)
}
102 changes: 72 additions & 30 deletions R/get_github_by_topic.R
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
# REST API Helper Functions
#' Get the number of contributors for a GitHub repository
#'
#' @param owner The owner of the GitHub repository
#' @param repo The name of the GitHub repository
#' @param token A GitHub personal access token (optional)
#'
#' @importFrom httr2 req_throttle
#'
#' @return The number of contributors to the repository
get_contributor_count <- function(owner, repo, token = NULL) {
base_url <- glue("https://api.github.com/repos/{owner}/{repo}/contributors")
req <- request(base_url) |>
req_url_query(per_page = 1, anon = "false") |> # anon=TRUE counts contributors without accounts
req_headers("User-Agent" = "httr2")
if (!is.null(token)) {
req <- req |>
req_auth_bearer_token(token) |>
req_throttle(capacity = 5000, fill_time_s = 3600, realm = "github_authenticated")
} else {
req <- req |>
req_throttle(capacity = 60, fill_time_s = 3600, realm = "github_anonymous")
}

resp <- tryCatch(req_perform(req), error = function(e) NULL)
if (is.null(resp) || resp_status(resp) != 200) return(NA_real_)

link <- resp_headers(resp)[["link"]]
if (!is.null(link) && grepl("rel=\"last\"", link)) {
matches <- regmatches(link, regexpr("page=\\d+>; rel=\\\"last\\\"", link))
count <- as.numeric(sub("page=", "", sub(">; rel=\"last\"", "", matches)))
return(count)
} else {
body <- resp_body_json(resp)
return(length(body)) # if only a few contributors
}
}

# REST Functions
#' Get GitHub Repositories by Topic
#'
#' @param topics A vector of GitHub topics to search for.
Expand Down Expand Up @@ -45,7 +84,12 @@ get_github_by_topic <- function(topics, token = NULL, limit = 30) {
req_url_query(q = q_topic, per_page = limit)

if (!is.null(token)) {
req_topic <- req_topic |> req_auth_bearer_token(token)
req_topic <- req_topic |>
req_auth_bearer_token(token) |>
req_throttle(capacity = 30, fill_time_s = 60, realm = "github_search_authenticated")
} else {
req_topic <- req_topic |>
req_throttle(capacity = 10, fill_time_s = 60, realm = "github_search_anonymous")
}

resp_topic <- req_perform(req_topic)
Expand All @@ -64,7 +108,14 @@ get_github_by_topic <- function(topics, token = NULL, limit = 30) {
req <- httr2::request(url) |>
httr2::req_headers("User-Agent" = "httr2",
"X-GitHub-Api-Version" = "2022-11-28")
if (!is.null(token)) req <- req |> httr2::req_auth_bearer_token(token)
if (!is.null(token)) {
req <- req |>
httr2::req_auth_bearer_token(token) |>
req_throttle(capacity = 5000, fill_time_s = 3600, realm = "github_authenticated")
} else {
req <- req |>
req_throttle(capacity = 60, fill_time_s = 3600, realm = "github_anonymous")
}

resp <- tryCatch(httr2::req_perform(req), error = function(e) NULL)
if (is.null(resp) || httr2::resp_status(resp) != 200) return(NA_real_)
Expand Down Expand Up @@ -97,7 +148,12 @@ get_github_by_topic <- function(topics, token = NULL, limit = 30) {
req_url_query(state = state, per_page = 1) |>
req_headers("User-Agent" = "httr2")
if (!is.null(token)) {
req <- req |> req_auth_bearer_token(token)
req <- req |>
req_auth_bearer_token(token) |>
req_throttle(capacity = 5000, fill_time_s = 3600, realm = "github_authenticated")
} else {
req <- req |>
req_throttle(capacity = 60, fill_time_s = 3600, realm = "github_anonymous")
}

resp <- tryCatch(req_perform(req), error = function(e) NULL)
Expand All @@ -121,8 +177,13 @@ get_github_by_topic <- function(topics, token = NULL, limit = 30) {
req_url_query(q = q, per_page = 1) |>
req_headers("User-Agent" = "httr2")
if (!is.null(token)) {
req <- req |> req_auth_bearer_token(token)
}
req <- req |>
req_auth_bearer_token(token) |>
req_throttle(capacity = 30, fill_time_s = 60, realm = "github_search_authenticated")
} else {
req <- req |>
req_throttle(capacity = 10, fill_time_s = 60, realm = "github_search_anonymous")
}
resp <- tryCatch(req_perform(req), error = function(e) NULL)
if (!is.null(resp) && resp_status(resp) == 200) {
return(resp_body_json(resp)$total_count)
Expand All @@ -148,7 +209,12 @@ get_github_by_topic <- function(topics, token = NULL, limit = 30) {
req_url_query(sha = branch, per_page = 1) |>
req_headers("User-Agent" = "httr2")
if (!is.null(token)) {
req <- req |> req_auth_bearer_token(token)
req <- req |>
req_auth_bearer_token(token) |>
req_throttle(capacity = 5000, fill_time_s = 3600, realm = "github_authenticated")
} else {
req <- req |>
req_throttle(capacity = 60, fill_time_s = 3600, realm = "github_anonymous")
}

resp <- tryCatch(req_perform(req), error = function(e) NULL)
Expand All @@ -168,30 +234,6 @@ get_github_by_topic <- function(topics, token = NULL, limit = 30) {
commit_counts <- map2_dbl(df$owner, df$name, ~ get_commit_count(.x, .y, token = token))
df$commits <- commit_counts

# Helper to count contributors
get_contributor_count <- function(owner, repo, token = NULL) {
base_url <- glue("https://api.github.com/repos/{owner}/{repo}/contributors")
req <- request(base_url) |>
req_url_query(per_page = 1, anon = "false") |> # anon=TRUE counts contributors without accounts
req_headers("User-Agent" = "httr2")
if (!is.null(token)) {
req <- req |> req_auth_bearer_token(token)
}

resp <- tryCatch(req_perform(req), error = function(e) NULL)
if (is.null(resp) || resp_status(resp) != 200) return(NA_real_)

link <- resp_headers(resp)[["link"]]
if (!is.null(link) && grepl("rel=\"last\"", link)) {
matches <- regmatches(link, regexpr("page=\\d+>; rel=\\\"last\\\"", link))
count <- as.numeric(sub("page=", "", sub(">; rel=\"last\"", "", matches)))
return(count)
} else {
body <- resp_body_json(resp)
return(length(body)) # if only a few contributors
}
}

contributor_counts <- map2_dbl(df$owner, df$name, ~ get_contributor_count(.x, .y, token = token))
df$contributors <- contributor_counts

Expand Down
Loading