#' VOSON Dashboard youtubeServer
#'
#' Collects Youtube video comments and creates an actor network using the vosonSML package.
#'
#### values ---------------------------------------------------------------------------------------------------------- #
yt_rv <- reactiveValues(
yt_data = NULL,
yt_network = NULL,
yt_graphml = NULL,
yt_wt_graphml = NULL,
data_cols = NULL
)
youtube_api_key <- NULL # youtube api key
youtube_video_id_list <- c() # list of youtube video ids to collect on
youtube_max_comments <- 200
#### events ---------------------------------------------------------------------------------------------------------- #
# update youtube api key when field input changes
observeEvent(input$youtube_api_key_input, {
setYoutubeAPIKey()
})
# when the youtube add video id button is pushed update the list and input fields
observeEvent(input$youtube_add_video_id_button, {
updateTextInput(session, "youtube_video_id_input", value = "")
videoListAdd()
updateSelectInput(session, "youtube_video_id_list_output",
choices = youtube_video_id_list)
})
# when the youtube remove video id button is pushed update the list and input fields
observeEvent(input$youtube_remove_video_id_button, {
videoListRemove()
updateSelectInput(session, "youtube_video_id_list_output",
choices = youtube_video_id_list)
})
# set count parameter and reset if not numeric or less than one
observeEvent(input$youtube_max_comments_input, {
if (!is.na(input$youtube_max_comments_input)) {
if (!is.numeric(input$youtube_max_comments_input) ||input$youtube_max_comments_input < 1) {
updateNumericInput(session, "youtube_max_comments_input", value = gbl_def_youtube_count)
}
}
youtube_max_comments <<- input$youtube_max_comments_input
})
# youtube collection button pushed
observeEvent(input$youtube_collect_button, {
# disable button so it is not pushed again
shinyjs::disable("youtube_collect_button")
withProgress(message = 'Collecting comments', value = 0.5, {
withConsoleRedirect("youtube_console", {
youtube_video_id_list <- sapply(youtube_video_id_list,
function(x) gsub("^v=", "", x, ignore.case = TRUE, perl = TRUE))
# collect youtube data and print any output to console
tryCatch({
yt_rv$yt_data <- collectYoutubeData(youtube_api_key, youtube_video_id_list, youtube_max_comments)
yt_rv$data_cols <- names(yt_rv$yt_data)
}, error = function(err) {
incProgress(1, detail = "Error")
cat(paste('youtube collection error:', err))
return(NULL)
})
incProgress(1, detail = "Finished")
updateTabItems(session, "youtube_control_tabset", selected = "Create Network")
}) # withConsoleRedirect
}) # withProgress
# enable button
youtubeArgumentsOutput()
delay(gbl_scroll_delay, js$scroll_console("youtube_console"))
})
observeEvent(yt_rv$yt_data, {
if (!is.null(yt_rv$yt_data) && nrow(yt_rv$yt_data)) {
shinyjs::enable("youtube_create_button")
} else {
shinyjs::disable("youtube_create_button")
}
})
observeEvent(input$youtube_create_button, {
net_type <- input$youtube_network_type_select
add_text <- input$youtube_network_text
network <- NULL
shinyjs::disable("youtube_create_button")
withProgress(message = 'Creating network', value = 0.5, {
withConsoleRedirect("youtube_console", {
if (net_type == "activity") {
network <- vosonSML::Create(isolate(yt_rv$yt_data), "activity", verbose = TRUE)
if (add_text) {
network <- vosonSML::AddText(network, isolate(yt_rv$yt_data))
}
} else if (net_type == "actor") {
network <- vosonSML::Create(isolate(yt_rv$yt_data), "actor", verbose = TRUE)
if (add_text) {
if (is2910) {
# vosonSML changed param name
network <- vosonSML::AddText(network, isolate(yt_rv$yt_data),
repliesFromText = input$youtube_network_replies_from_text)
} else {
network <- vosonSML::AddText(network, isolate(yt_rv$yt_data),
replies_from_text = input$youtube_network_replies_from_text)
}
}
if (input$youtube_network_video_data) {
creds <- vosonSML::Authenticate("youtube", apiKey = youtube_api_key)
network <- vosonSML::AddVideoData(network, youtubeAuth = creds,
actorSubOnly = input$youtube_network_video_subs)
}
}
if (!is.null(network)) {
yt_rv$yt_network <- network
yt_rv$yt_graphml <- vosonSML::Graph(network)
}
}) # withConsoleRedirect
incProgress(1, detail = "Finished")
}) # withProgress
shinyjs::enable("youtube_create_button")
delay(gbl_scroll_delay, js$scroll_console("youtube_console"))
})
# download and view actions
callModule(collectDataButtons, "youtube", data = reactive({ yt_rv$yt_data }), file_prefix = "youtube")
callModule(collectNetworkButtons, "youtube", network = reactive({ yt_rv$yt_network }), file_prefix = "youtube")
callModule(collectGraphButtons_, "youtube", graph_data = reactive({ yt_rv$yt_graphml }), file_prefix = "youtube")
youtube_view_rvalues <- callModule(collectViewGraphButtons, "youtube", graph_data = reactive({ yt_rv$yt_graphml }))
observeEvent(youtube_view_rvalues$data, {
setGraphView(data = isolate(youtube_view_rvalues$data),
desc = paste0("Youtube network for videos: ", paste0(youtube_video_id_list, collapse = ', '),
sep = ""),
type = "youtube",
name = "",
seed = sample(gbl_rng_range[1]:gbl_rng_range[2], 1))
updateCheckboxInput(session, "expand_demo_data_check", value = FALSE)
}, ignoreInit = TRUE)
observeEvent(input$clear_youtube_console, {
resetConsole("youtube_console")
})
#### output ---------------------------------------------------------------------------------------------------------- #
# render youtube collection arguments
output$youtube_arguments_output <- renderText({
input$youtube_api_key_input
input$youtube_add_video_id_button
input$youtube_remove_video_id_button
input$youtube_max_comments_input
# do not update arguments text on input field or list changes
isolate({ input$youtube_video_id_input
input$youtube_video_id_list_output })
# get youtube collection arguments output
youtubeArgumentsOutput()
})
# render youtube data table
output$dt_youtube_data <- DT::renderDataTable({
datatableYoutubeData()
})
observeEvent(input$select_all_youtube_dt_columns, {
updateCheckboxGroupInput(session, "show_youtube_cols", label = NULL,
choices = isolate(yt_rv$data_cols),
selected = isolate(yt_rv$data_cols),
inline = TRUE)
})
observeEvent(input$clear_all_youtube_dt_columns, {
updateCheckboxGroupInput(session, "show_youtube_cols", label = NULL,
choices = isolate(yt_rv$data_cols),
selected = character(0),
inline = TRUE)
})
dt_yt_cols <- function() {
return(c("Comment", "AuthorDisplayName", "VideoID", "PublishedAt"))
}
observeEvent(input$reset_youtube_dt_columns, {
updateCheckboxGroupInput(session, "show_youtube_cols", label = NULL,
choices = isolate(yt_rv$data_cols),
selected = dt_yt_cols(),
inline = TRUE)
})
output$youtube_data_cols_ui <- renderUI({
data <- yt_rv$data_cols
if (is.null(data)) { return(NULL) }
conditionalPanel(condition = 'input.expand_show_youtube_cols',
div(actionButton("select_all_youtube_dt_columns", "Select all"),
actionButton("clear_all_youtube_dt_columns", "Clear all"),
actionButton("reset_youtube_dt_columns", "Reset")),
checkboxGroupInput("show_youtube_cols", label = NULL,
choices = yt_rv$data_cols,
selected = dt_yt_cols(),
inline = TRUE, width = '98%'))
})
#### reactives ------------------------------------------------------------------------------------------------------- #
setYoutubeAPIKey <- reactive({
youtube_api_key <<- trimws(input$youtube_api_key_input)
return(youtube_api_key)
})
# add to the list of youtube video ids to collect on
videoListAdd <- reactive({
if (is.null(input$youtube_video_id_input) || trimws(input$youtube_video_id_input) == "") {
return(NULL)
}
video_id <- getYoutubeVideoId(input$youtube_video_id_input)
if (is.null(video_id)) { return(NULL) }
# only add if not already in list
if (!(trimws(video_id) %in% youtube_video_id_list)) {
youtube_video_id_list <<- append(youtube_video_id_list, trimws(video_id))
}
return(youtube_video_id_list)
})
# remove from the list of youtube video ids to collect on
videoListRemove <- reactive({
if (is.null(input$youtube_video_id_list_output) || trimws(input$youtube_video_id_list_output) == "") {
return(NULL)
}
youtube_video_id_list <<- youtube_video_id_list[!(youtube_video_id_list %in% input$youtube_video_id_list_output)]
return(youtube_video_id_list)
})
datatableYoutubeData <- reactive({
data <- yt_rv$yt_data
if (is.null(data)) { return(NULL) }
cls_lst <- class(data)
class(data) <- cls_lst[!cls_lst %in% c("datasource", "youtube")]
if (!is.null(input$show_youtube_cols)) {
if (length(input$show_youtube_cols) > 0) {
# data <- dplyr::select(yt_rv$yt_data, input$show_youtube_cols)
data <- dplyr::select(data, input$show_youtube_cols)
} else { return(NULL) }
} else { return(NULL) }
if (nrow(data) < 1) { return(NULL) }
col_classes <- sapply(data, class)
for (i in seq(1, length(col_classes))) {
if ("list" %in% col_classes[i]) {
var <- names(col_classes)[i]
data[var] <- lapply(data[var], function(x) sapply(x, paste, collapse = ", ", character(1L)))
}
}
if (!is.null(yt_rv$yt_data)) {
col_defs <- NULL
if (input$dt_youtube_truncate_text_check == TRUE) {
col_defs <- gbl_dt_col_defs
col_defs[[1]]$targets = "_all"
}
DT::datatable(data, extensions = 'Buttons', filter = "top",
options = list(lengthMenu = gbl_dt_menu_len, pageLength = gbl_dt_page_len, scrollX = TRUE,
columnDefs = col_defs, dom = 'lBfrtip',
buttons = c('copy', 'csv', 'excel', 'print')),
class = 'cell-border stripe compact hover')
}
})
#### functions ------------------------------------------------------------------------------------------------------- #
# format youtube collection arguments output
youtubeArgumentsOutput <- function() {
output <- c()
key_flag <- video_id_flag <- count_flag <- FALSE
if (!is.null(youtube_api_key) && nchar(youtube_api_key) > 1) {
key_flag <- TRUE
output <- append(output, trimws(paste0("api key: ", strtrim(youtube_api_key, 6), "...", sep = "")))
}
if (!is.null(youtube_video_id_list) && length(youtube_video_id_list) > 0) {
video_id_flag <- TRUE
output <- append(output, paste0("videos: ", trimws(paste0(youtube_video_id_list, collapse = ', '))))
}
if (!VOSONDash::isNullOrEmpty(youtube_max_comments) && is.numeric(youtube_max_comments)) {
count_flag <- TRUE
output <- append(output, paste0("max comments: ", youtube_max_comments))
}
if (key_flag && video_id_flag && count_flag) {
shinyjs::enable("youtube_collect_button")
} else {
shinyjs::disable("youtube_collect_button")
}
paste0(output, collapse = '\n')
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.