R/get_ly_committees.R

Defines functions get_ly_committee_meets

Documented in get_ly_committee_meets

#' @encoding UTF-8
#' @title Fetch Legislative Yuan Committee Meetings 取得立法院委員會會議資料
#'
#' @description
#' Retrieves and processes committee meeting information from the Legislative Yuan API.
#' This function allows you to fetch detailed information about committee meetings
#' including attendance, bills discussed, and meeting details.
#'
#' @param committee_id integer. Required. The ID of the committee. Available values:
#'   \itemize{
#'     \item 15: 內政委員會 (Interior Committee)
#'     \item 16: 外交及僑務委員會 (Foreign and Overseas Chinese Affairs Committee)
#'     \item 17: 科技及資訊委員會 (Science and Technology Committee)
#'     \item 18: 國防委員會 (Defense Committee)
#'     \item 19: 經濟委員會 (Economics Committee)
#'     \item 20: 財政委員會 (Finance Committee)
#'     \item 21: 預算及決算委員會 (Budget Committee)
#'     \item 22: 教育及文化委員會 (Education and Culture Committee)
#'     \item 23: 交通委員會 (Transportation Committee)
#'     \item 24: 司法委員會 (Judiciary Committee)
#'     \item 25: 法制委員會 (Legal Affairs Committee)
#'     \item 26: 社會福利及衛生環境委員會 (Social Welfare and Environmental Hygiene Committee)
#'     \item 27: 程序委員會 (Procedure Committee)
#'     \item 28: 紀律委員會 (Discipline Committee)
#'     \item 29: 修憲委員會 (Constitutional Amendment Committee)
#'     \item 30: 經費稽核委員會 (Expenditure Review Committee)
#'     \item 35: 外交及國防委員會 (Foreign Affairs and Defense Committee)
#'     \item 36: 司法及法制委員會 (Judiciary and Legal Affairs Committee)
#'   }
#' @param page integer. Page number for pagination (default: 1)
#' @param per_page integer. Number of items per page (default: 20)
#' @param term integer. Legislative term number
#' @param session integer. Session number
#' @param meeting_code string. Meeting code
#' @param meeting_type string. Type of meeting
#' @param attending_member string. Name of attending member
#' @param date string. Meeting date in YYYY-MM-DD format
#' @param meeting_number string. Meeting number
#' @param bill_id string. Bill ID
#' @param show_progress logical. Whether to display progress bar (default: TRUE)
#'
#' @return A list containing two elements:
#'   \itemize{
#'     \item metadata: List containing pagination information and request status
#'     \item data: Data frame containing meeting information with columns including
#'           meeting date, type, attending members, and discussed bills
#'   }
#'
#' @examples
#' \dontrun{
#' # Fetch meetings from the Interior Committee
#' meetings <- get_ly_committee_meets(committee_id = 15)
#'
#' # Fetch meetings with specific filters
#' meetings <- get_ly_committee_meets(
#'   committee_id = 16,
#'   term = 10,
#'   session = 1,
#'   date = "2024-01-01"
#' )
#' }
#'
#' @importFrom httr GET content status_code
#' @importFrom jsonlite fromJSON
#' @importFrom dplyr bind_rows
#' @importFrom utils txtProgressBar setTxtProgressBar
#' @encoding UTF-8
#' @export
get_ly_committee_meets <- function(
    committee_id,
    page = 1,
    per_page = 20,
    term = NULL,
    session = NULL,
    meeting_code = NULL,
    meeting_type = NULL,
    attending_member = NULL,
    date = NULL,
    meeting_number = NULL,
    bill_id = NULL,
    show_progress = TRUE
) {
  # Input validation
  if (missing(committee_id)) stop("committee_id is required")
  if (!is.numeric(committee_id)) stop("committee_id must be numeric")

  # Initialize progress
  if(show_progress) {
    cat(sprintf("\nFetching meetings data for committee ID %d...\n", committee_id))
    pb <- txtProgressBar(min = 0, max = 100, style = 3)
    setTxtProgressBar(pb, 20)
  }

  # API request
  base_url <- sprintf("https://v2.ly.govapi.tw/committees/%d/meets", committee_id)

  query_params <- list(
    page = page,
    per_page = per_page,= term,
    會期 = session,
    會議代碼 = meeting_code,
    會議種類 = meeting_type,
    "會議資料.出席委員" = attending_member,
    日期 = date,
    "會議資料.會議編號" = meeting_number,
    "議事網資料.關係文書.議案.議案編號" = bill_id
  )
  query_params <- query_params[!sapply(query_params, is.null)]

  # Update progress - API call
  if(show_progress) {
    setTxtProgressBar(pb, 40)
  }

  # Make API request with error handling
  response <- tryCatch({
    httr::GET(base_url, query = query_params, httr::timeout(60))
  }, error = function(e) {
    if(show_progress) close(pb)
    stop(sprintf("API request failed: %s", e$message))
  })

  if (httr::status_code(response) != 200) {
    if(show_progress) close(pb)
    stop(sprintf("API request failed with status code: %d", httr::status_code(response)))
  }

  # Update progress - parsing
  if(show_progress) {
    setTxtProgressBar(pb, 60)
  }

  content <- httr::content(response, "text", encoding = "UTF-8")
  data <- jsonlite::fromJSON(content, simplifyVector = FALSE)

  # Process meetings
  if (length(data$meets) > 0) {
    # Update progress - data processing
    if(show_progress) {
      setTxtProgressBar(pb, 80)
    }

    meetings_list <- lapply(data$meets, function(meet) {
      # Extract and process meeting participants
      legislators <- character(0)


      # From 發言紀錄
      if (!is.null(meet$發言紀錄)) {
        legislators <- c(legislators, unique(unlist(
          lapply(meet$發言紀錄, function(x) x$legislatorNameList)
        )))
      }

      # From 議事錄
      if (!is.null(meet$議事錄) && !is.null(meet$議事錄$出席委員)) {
        legislators <- c(legislators, meet$議事錄$出席委員)
      }

      legislators <- unique(legislators[!is.na(legislators)])
      attending_str <- if(length(legislators) > 0) paste(legislators, collapse = ", ") else NA_character_

      # Extract meeting content
      content <- NA_character_
      if (!is.null(meet$發言紀錄) && length(meet$發言紀錄) > 0 && !is.null(meet$發言紀錄[[1]]$meetingContent)) {
        content <- meet$發言紀錄[[1]]$meetingContent
      } else if (!is.null(meet$會議資料) && length(meet$會議資料) > 0 && !is.null(meet$會議資料[[1]]$會議事由)) {
        content <- meet$會議資料[[1]]$會議事由
      }

      # Create data frame row
      data.frame(
        會議名稱 = if (!is.null(meet$name)) meet$name else NA_character_,
        會議代碼 = if (!is.null(meet$會議代碼)) meet$會議代碼 else NA_character_,
        會議種類 = if (!is.null(meet$會議種類)) meet$會議種類 else NA_character_,
        屆期 = as.integer(if (!is.null(meet$)) meet$else NA),
        會期 = as.integer(if (!is.null(meet$會期)) meet$會期 else NA),
        會次 = as.integer(if (!is.null(meet$會次)) meet$會次 else NA),
        地點 = if (!is.null(meet$會議資料) && length(meet$會議資料) > 0)
          meet$會議資料[[1]]$會議地點 else NA_character_,
        召委 = if (!is.null(meet$會議資料) && length(meet$會議資料) > 0)
          meet$會議資料[[1]]$委員會召集委員 else NA_character_,
        出席委員 = attending_str,
        會議日期 = if (length(meet$日期) > 0) paste(meet$日期, collapse = ", ") else NA_character_,
        會議內容 = content,
        stringsAsFactors = FALSE
      )
    })

    meetings_df <- dplyr::bind_rows(meetings_list)

  } else {
    meetings_df <- data.frame(
      會議名稱 = character(),
      會議代碼 = character(),
      會議種類 = character(),
      屆期 = integer(),
      會期 = integer(),
      會次 = integer(),
      地點 = character(),
      召委 = character(),
      出席委員 = character(),
      會議日期 = character(),
      會議內容 = character(),
      stringsAsFactors = FALSE
    )
  }

  # Process metadata
  metadata <- list(
    total = data$total,
    total_page = data$total_page,
    current_page = data$page,
    per_page = data$limit,
    filters = data$filter,
    timestamp = Sys.time()
  )

  # Update progress - complete
  if(show_progress) {
    setTxtProgressBar(pb, 100)
    close(pb)

    # Print summary
    cat("\n\n")
    cat("====== Retrieved Information ======\n")
    cat("-----------------------------------\n")
    cat(sprintf("Total Meetings: %d\n", metadata$total))
    cat(sprintf("Page: %d of %d\n", metadata$current_page, metadata$total_page))
    cat(sprintf("Records per page: %d\n", metadata$per_page))

    if(nrow(meetings_df) > 0) {
      # Add meeting type distribution
      type_counts <- table(meetings_df$會議種類)
      cat("\nMeeting Type Distribution:\n")
      for(type_name in names(type_counts)) {
        if(!is.na(type_name)) {
          cat(sprintf(" %s: %d\n", type_name, type_counts[type_name]))
        }
      }

      # Add session distribution
      if(any(!is.na(meetings_df$會期))) {
        session_counts <- table(meetings_df$會期)
        cat("\nSession Distribution:\n")
        for(session in sort(as.numeric(names(session_counts)))) {
          cat(sprintf(" Session %d: %d\n", session, session_counts[as.character(session)]))
        }
      }

      # Add location distribution if available
      if(any(!is.na(meetings_df$地點))) {
        location_counts <- table(meetings_df$地點)
        cat("\nLocation Distribution:\n")
        for(location in names(location_counts)) {
          if(!is.na(location)) {
            cat(sprintf(" %s: %d\n", location, location_counts[location]))
          }
        }
      }
    }
    cat("===================================\n")
  }

  return(list(
    metadata = metadata,
    meetings = meetings_df
  ))
}
yl17124/legisTaiwan documentation built on June 15, 2025, 12:59 a.m.