R/build.R

Defines functions import_posts build_student_pages build_lates_posts build_all_posts

Documented in build_all_posts build_lates_posts build_student_pages import_posts

#' Builds all blog posts
#'
#' Builds all drafted blog posts for a DACSS course site.
#' The index page listing posts will be updated once
#' the Distill blog is built. Assumes a DACSS blog R project
#' is being used.
#'
#' @export
build_all_posts <- function() {
  correct_env()

  all_post_files <- list.files('_posts', '*.Rmd', recursive = TRUE)

  # No post files found
  if (identical(all_post_files, character(0))) stop('No posts found!')

  # Goes through each post
  for (post in all_post_files) {
    post <- paste('_posts/', post, sep = '')
    # Un-drafts a Rmd file
    change_yaml_matter(post, draft = FALSE, output_file = post)
    # Renders Rmd file into Distill article
    rmarkdown::render(post, quiet = TRUE)
    message(paste(post, 'rendered.'))
    # Drafts Rmd file again
    change_yaml_matter(post, draft = TRUE, output_file = post)
  }

  preview_site('Success! Posts rendered successfully.')
}


#' Build latest blog posts
#'
#' Render the posts added or modified in the most recent git pull.
#' Recommended use is only after git pull. In other cases and for a foolproof rendering of posts, consider using build_all_posts().
#'
#' @export
build_lates_posts <- function() {
  correct_env()

  file_names <- list.files('_posts', '*.Rmd', recursive = TRUE, full.names=TRUE) # Find file paths/names
  df <- file.info(file_names)   # Get info for the file paths - we want mtime from this ie. last modified
  max_date <- max(df$mtime)     # We find the last modified post and take it as the standard timestamp for the latest posts

  for (row in 1:nrow(df)) {     # Loop through the dataframe

    # message(paste(file_names[row], difftime(max_date, df[[row, 'mtime']])))

    if (difftime(max_date, df[[row, 'mtime']]) < 1) {     # Even the latest modified files have a difference of 0.0001 seconds at least so we take all the files which have time stamps less than 1 second away from the latest modified file's timestamp
      # similar to build_all_posts() - renders all posts whose file paths we provide
      post <- file_names[row]
      change_yaml_matter(post, draft = FALSE, output_file = post)
      rmarkdown::render(post, quiet = TRUE)
      message(paste(post, 'rendered.'))
      change_yaml_matter(post, draft = TRUE, output_file = post)
    }
  }
  preview_site('Success! Posts rendered successfully.')
}


#' Builds all student pages
#'
#' Builds all student pages for a DACSS course site.
#' Assumes the working directory is the GitHub repo
#' project file.
#' @export
build_student_pages <- function() {
  correct_env()

  # Get path for all users
  all_pages <- list.files('users', '*.Rmd', recursive = TRUE)
  # Get users without path
  users <- sub('users/', '', all_pages)

  # No pages found
  if (identical(all_pages, character(0))) stop('No pages found!')

  # Iterates through each page
  for (user in users) {
    # Move files to root
    move_files(source_path = './users', source_file = user)
  }

  message('Building files... Please wait...')
  # Rename students (ignores)
  move_files(source_file = 'students.Rmd', dest_file = '_students.Rmd')
  # Builds entire site (except for students)
  rmarkdown::render_site(quiet = TRUE)
  # Rename students back
  move_files(source_file = '_students.Rmd', dest_file = 'students.Rmd')

  # Moves files back to user folder
  for (user in users) {
    move_files(source_file = user, dest_path = './users')
  }

  # Render students page
  rmarkdown::render_site(input = 'students.Rmd', quiet = TRUE)

  preview_site('Success! Student pages rendered successfully.')
}



#' Import student posts from their blogs
#'
#' Import student posts from their blogs.
#' @export
import_posts <- function() {
  # "https://docs.google.com/spreadsheets/d/1BzpTglVbQ331UUJXlh3K3fOVGN0aaHh7s2CHfGwzTfw/edit?resourcekey#gid=311435407"

  tryCatch(
    expr = {
      sheets_link = readLines("local.txt")
      posts = googlesheets4::read_sheet(sheets_link, sheet="Form Responses 1")
    },
    error = function(e){
      message('Invalid or no google sheets link provided! Please use update_sheets_link() to provide a valid google sheets URL and run import_posts() again.')
    },
    warning = function(w){
      message('Invalid or no google sheets link provided! Please use update_sheets_link() to provide a valid google sheets URL and run import_posts() again.')
    }
  )

  for (i in seq_along(posts$`Email Address`)) {
    tryCatch(
      expr = {
        row <- posts[i, ]

        if(is.na(row$`Email Address`)) {
          next
        }

        email <- row$`Email Address`
        url <- row$URL

        distill::import_post(url, slug = url, overwrite = TRUE, check_license = FALSE)

        send_email(email, url)
      },
      error = function(e){
        # Ideally email the students that their post failed as well.
        message(paste0('Error with post link ', row$URL, ' by ', row$`Email Address`))
        print(e)
      },
      warning = function(w){
        message(paste0('A warning occured for post link ', row$URL, ' by ', row$`Email Address`))
        print(w)
      }
    )
  }

  posts = posts[0, ]
  googlesheets4::write_sheet(posts, sheets_link, sheet = 'Form Responses 1')
}
DACSS/dacss.websites documentation built on Aug. 1, 2022, 8:26 p.m.