#' VOSON Dashboard twitterServer
#'
#' Collects tweets and creates an actor network using the vosonSML package.
#'
#### values ---------------------------------------------------------------------------------------------------------- #
tw_rv <- reactiveValues(
tw_data = NULL, # dataframe returned by vosonSML collection
tw_network = NULL,
tw_graphml = NULL # igraph graph object returned from collection
)
tw_data <- NULL
tw_rv$data_cols <- NULL
# twitter api keys
tw_api_keyring <- list(
twitter_app_name = "",
twitter_api_key = "",
twitter_api_secret = "",
twitter_access_token = "",
twitter_access_token_secret = ""
)
# twitter search parameters
twitter_search_term <- NULL
twitter_search_type <- NULL
twitter_retweets <- NULL
twitter_retry <- NULL
twitter_tweet_count <- NULL
twitter_language <- NULL
twitter_date_until <- NULL
twitter_since_id <- NULL
twitter_max_id <- NULL
twitter_filter_from <- NULL
twitter_filter_to <- NULL
twitter_filter_safe <- NULL
twitter_filter_media <- NULL
twitter_filter_url <- NULL
twitter_filter_negative <- NULL
twitter_filter_positive <- NULL
#### events ---------------------------------------------------------------------------------------------------------- #
# set twitter parameters on input
observeEvent({
input$twitter_search_term_input
input$twitter_retweets_check
input$twitter_retry_check
input$twitter_search_type_select
input$twitter_date_until_input
input$twitter_since_id_input
input$twitter_max_id_input
input$twitter_filter_from
input$twitter_filter_to
input$twitter_filter_safe
input$twitter_filter_media
input$twitter_filter_url
input$twitter_filter_negative
input$twitter_filter_positive
}, {
setTwitterParams()
})
# set twitter language parameter and reset if greater than two alpha characters
observeEvent(input$twitter_language_input, {
if (!is.na(input$twitter_language_input)) {
alpha_check <- grep("^[[:alpha:]]+$", input$twitter_language_input, value = FALSE)
if (nchar(input$twitter_language_input) > 2 || identical(alpha_check, integer(0))) {
updateTextInput(session, "twitter_language_input", value = "")
}
}
setTwitterParams()
})
# set tweet count parameter and reset if not numeric or less than one
observeEvent(input$twitter_tweet_count_input, {
if (!is.na(input$twitter_tweet_count_input)) {
if (!is.numeric(input$twitter_tweet_count_input) || input$twitter_tweet_count_input < 1) {
updateNumericInput(session, "twitter_tweet_count_input", value = gbl_def_tweet_count)
}
}
setTwitterParams()
})
observeEvent(input$clear_twitter_console, {
resetConsole("twitter_console")
})
# twitter collection button pushed
observeEvent(input$twitter_collect_button, {
# disable button so it is not pushed again
shinyjs::disable("twitter_collect_button")
withProgress(message = 'Collecting tweets', value = 0.5, {
withConsoleRedirect("twitter_console", {
# collect twitter data and print any output to console
withCallingHandlers(
tryCatch({
search_term <- twitter_search_term
search_type <- twitter_search_type
twitter_search_options <- c()
if (nchar(twitter_filter_from) > 2) {
twitter_search_options <- append(twitter_search_options, paste0("from:", twitter_filter_from))
}
if (nchar(twitter_filter_to) > 2) {
twitter_search_options <- append(twitter_search_options, paste0("to:", twitter_filter_to))
}
# "-filter:nativeretweets" = !twitter_retweets,
opts <- list("filter:safe" = !twitter_filter_safe,
"filter:media" = !twitter_filter_media,
"filter:links" = !twitter_filter_url,
":)" = !twitter_filter_positive,
":(" = !twitter_filter_negative)
sapply(names(opts), function(x) {
if (!VOSONDash::isNullOrEmpty(opts[x])) {
if (opts[x] == FALSE) { twitter_search_options <<- append(twitter_search_options, x) }
}
})
if (length(twitter_search_options) > 0) {
search_term <- ifelse(nchar(trimws(search_term)) > 0, paste0(search_term, " "), "")
search_term <- paste0(search_term, paste0(twitter_search_options, collapse = " "))
}
# tw_api_keyring, search_term, search_type, tweet_count,
# include_retweets, retry_on_rate_limit, language, date_until, since_id, max_id
tw_data <- suppressWarnings({
VOSONDash::collectTwitterData(cred = creds_rv$use_token, search_term, search_type,
twitter_tweet_count, twitter_retweets, twitter_retry,
twitter_language, twitter_date_until,
twitter_since_id, twitter_max_id) })
tw_rv$tw_data <- tw_data
tw_rv$data_cols <- names(tw_rv$tw_data)
}, error = function(err) {
incProgress(1, detail = "Error")
cat(paste("twitter collection error: ", err))
NULL
}, warning = function(w) {
incProgress(1, detail = "Warning")
cat(paste("twitter collection warning: ", w))
})
) # withCallingHandlers
incProgress(1, detail = "Finished")
updateTabItems(session, "twitter_control_tabset", selected = "Create Network")
}) # withConsoleRedirect
}) # withProgress
# enable button
twitterArgumentsOutput()
delay(gbl_scroll_delay, js$scroll_console("twitter_console"))
})
observeEvent(tw_rv$tw_data, {
if (!is.null(tw_rv$tw_data) && nrow(tw_rv$tw_data)) {
shinyjs::enable("twitter_create_button")
} else {
shinyjs::disable("twitter_create_button")
}
})
observeEvent(input$twitter_create_button, {
net_type <- input$twitter_network_type_select
add_text <- input$twitter_network_text
add_user_data <- input$twitter_network_user_data
network <- NULL
parse_rem_terms <- function(rem_terms) {
rem_terms <- unlist(strsplit(rem_terms, ","), use.names = FALSE)
rem_terms <- sapply(rem_terms, function(x) {
term <- trimws(x)
if (term == "") { return(NA) }
term
}, USE.NAMES = FALSE)
rem_terms <- na.omit(rem_terms)
}
shinyjs::disable("twitter_create_button")
withProgress(message = "Creating network", value = 0.5, {
withConsoleRedirect("twitter_console", {
if (net_type == "activity") {
network <- vosonSML::Create(isolate(tw_rv$tw_data), "activity", verbose = TRUE)
if (add_text) { network <- vosonSML::AddText(network, isolate(tw_rv$tw_data)) }
} else if (net_type == "actor") {
network <- vosonSML::Create(isolate(tw_rv$tw_data), "actor", verbose = TRUE)
if (add_text) { network <- vosonSML::AddText(network, isolate(tw_rv$tw_data)) }
if (add_user_data) {
network <- vosonSML::AddUserData(network, isolate(tw_rv$tw_data), twitterAuth = creds_rv$use_token)
}
} else if (net_type == "twomode") {
rem_terms <- parse_rem_terms(input$twitter_twomode_remove)
network <- NULL
tryCatch({
network <- vosonSML::Create(isolate(tw_rv$tw_data), "twomode",
removeTermsOrHashtags = rem_terms,
verbose = TRUE)
}, error = function(e) { cat(e$message) })
} else if (net_type == "semantic") {
rem_terms <- parse_rem_terms(input$twitter_semantic_remove)
network <- NULL
tryCatch({
if (is2910) {
network <- vosonSML::Create(isolate(tw_rv$tw_data), "semantic",
removeTermsOrHashtags = rem_terms,
stopwords = input$twitter_semantic_stopwords, # >= v0.29.10
termFreq = input$twitter_term_freq,
hashtagFreq = input$twitter_hashtag_freq,
assoc = ifelse(input$twitter_semantic_assoc, "limited", "full"), # >= v0.29.10
verbose = TRUE)
} else {
network <- vosonSML::Create(isolate(tw_rv$tw_data), "semantic",
removeTermsOrHashtags = rem_terms,
stopwordsEnglish = input$twitter_semantic_stopwords, # < v0.29.10
termFreq = input$twitter_term_freq,
hashtagFreq = input$twitter_hashtag_freq,
verbose = TRUE)
}
}, error = function(e) { cat(e$message) })
}
if (!is.null(network)) {
tw_rv$tw_network <- network
tw_rv$tw_graphml <- vosonSML::Graph(network)
}
})
incProgress(1, detail = "Finished")
})
shinyjs::enable("twitter_create_button")
delay(gbl_scroll_delay, js$scroll_console("twitter_console"))
})
# download and view actions
callModule(collectDataButtons, "twitter", data = reactive({ tw_rv$tw_data }), file_prefix = "twitter")
callModule(collectNetworkButtons, "twitter", network = reactive({ tw_rv$tw_network }), file_prefix = "twitter")
callModule(collectGraphButtons_, "twitter", graph_data = reactive({ tw_rv$tw_graphml }), file_prefix = "twitter")
twitter_view_rvalues <- callModule(collectViewGraphButtons, "twitter", graph_data = reactive({ tw_rv$tw_graphml }))
observeEvent(twitter_view_rvalues$data, {
setGraphView(data = isolate(twitter_view_rvalues$data),
desc = paste0("Twitter network for search term: ", twitter_search_term, sep = ""),
type = "twitter",
name = "",
seed = sample(gbl_rng_range[1]:gbl_rng_range[2], 1))
updateCheckboxInput(session, "expand_demo_data_check", value = FALSE)
}, ignoreInit = TRUE)
#### output ---------------------------------------------------------------------------------------------------------- #
output$twitter_collect_token_output <- renderText({
if (!is.null(creds_rv$use_token)) {
createTokenId(creds_rv$use_token)
} else {
"No token set"
}
})
# render twitter collection arguments
output$twitter_arguments_output <- renderText({
# dependencies
input$twitter_app_name_input
input$twitter_api_key_input
input$twitter_api_secret_input
input$twitter_access_token_input
input$twitter_access_token_secret_input
input$twitter_search_term_input
input$twitter_search_type_select
input$twitter_retweets_check
input$twitter_retry_check
input$twitter_tweet_count_input
input$twitter_language_input
input$twitter_date_until_input
input$twitter_since_id_input
input$twitter_max_id_input
input$twitter_filter_from
input$twitter_filter_to
input$twitter_filter_safe
input$twitter_filter_media
input$twitter_filter_url
input$twitter_filter_negative
input$twitter_filter_positive
# get twitter collection arguments output
twitterArgumentsOutput()
})
# render twitter data table
output$dt_twitter_data <- DT::renderDataTable({
datatableTwitterData()
})
observeEvent(input$select_all_twitter_dt_columns, {
updateCheckboxGroupInput(session, "show_twitter_cols", label = NULL,
choices = isolate(tw_rv$data_cols),
selected = isolate(tw_rv$data_cols),
inline = TRUE)
})
observeEvent(input$clear_all_twitter_dt_columns, {
updateCheckboxGroupInput(session, "show_twitter_cols", label = NULL,
choices = isolate(tw_rv$data_cols),
selected = character(0),
inline = TRUE)
})
observeEvent(input$reset_twitter_dt_columns, {
updateCheckboxGroupInput(session, "show_twitter_cols", label = NULL,
choices = isolate(tw_rv$data_cols),
selected = c("user_id", "status_id", "created_at", "screen_name", "text",
"is_retweet"),
inline = TRUE)
})
output$twitter_data_cols_ui <- renderUI({
data <- tw_rv$data_cols
if (is.null(data)) { return(NULL) }
conditionalPanel(condition = 'input.expand_show_twitter_cols',
div(actionButton("select_all_twitter_dt_columns", "Select all"),
actionButton("clear_all_twitter_dt_columns", "Clear all"),
actionButton("reset_twitter_dt_columns", "Reset")),
checkboxGroupInput("show_twitter_cols", label = NULL,
choices = tw_rv$data_cols,
selected = c("user_id", "status_id", "created_at", "screen_name", "text",
"is_retweet"),
inline = TRUE, width = '98%')
)
})
#### reactives ------------------------------------------------------------------------------------------------------- #
setTwitterAPIKeys <- reactive({
tw_api_keyring$twitter_app_name <<- input$twitter_app_name_input
tw_api_keyring$twitter_api_key <<- trimws(input$twitter_api_key_input)
tw_api_keyring$twitter_api_secret <<- trimws(input$twitter_api_secret_input)
tw_api_keyring$twitter_access_token <<- trimws(input$twitter_access_token_input)
tw_api_keyring$twitter_access_token_secret <<- trimws(input$twitter_access_token_secret_input)
})
setTwitterParams <- reactive({
twitter_search_term <<- trimws(input$twitter_search_term_input)
twitter_search_term <<- gsub("\n{1, }", " ", twitter_search_term)
twitter_search_type <<- input$twitter_search_type_select
twitter_retweets <<- input$twitter_retweets_check
twitter_retry <<- input$twitter_retry_check
twitter_tweet_count <<- input$twitter_tweet_count_input
twitter_language <<- input$twitter_language_input
twitter_date_until <<- trimws(input$twitter_date_until_input)
twitter_since_id <<- trimws(input$twitter_since_id_input)
twitter_max_id <<- trimws(input$twitter_max_id_input)
twitter_filter_from <<- trimws(input$twitter_filter_from)
twitter_filter_from <<- gsub("^@", "", twitter_filter_from)
twitter_filter_to <<- trimws(input$twitter_filter_to)
twitter_filter_to <<- gsub("^@", "", twitter_filter_to)
twitter_filter_safe <<- input$twitter_filter_safe
twitter_filter_media <<- input$twitter_filter_media
twitter_filter_url <<- input$twitter_filter_url
twitter_filter_negative <<- input$twitter_filter_negative
twitter_filter_positive <<- input$twitter_filter_positive
})
# create data table from collected twitter data
datatableTwitterData <- reactive({
data <- tw_rv$tw_data
if (is.null(data)) { return(NULL) }
cls_lst <- class(data)
class(data) <- cls_lst[!cls_lst %in% c("datasource", "twitter")]
if (!is.null(input$show_twitter_cols)) {
if (length(input$show_twitter_cols) > 0) {
# data <- dplyr::select(tw_rv$tw_data, input$show_twitter_cols)
data <- dplyr::select(data, input$show_twitter_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(tw_rv$tw_data)) {
col_defs <- NULL
if (input$dt_twitter_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 twitter collection arguments output
twitterArgumentsOutput <- function() {
output <- c()
check_keys <- sapply(tw_api_keyring, VOSONDash::isNullOrEmpty)
search_term_flag <- FALSE
if (!VOSONDash::isNullOrEmpty(twitter_search_term)) {
temp_search_term <- twitter_search_term
output <- append(output, paste0("search term: ", trimws(temp_search_term)))
search_term_flag <- TRUE
}
output <- append(output, paste0("include retweets: ", ifelse(twitter_retweets, "yes", "no")))
output <- append(output, paste0("retry on rate limit: ", ifelse(twitter_retry, "yes", "no")))
output <- append(output, paste0("results type: ", trimws(twitter_search_type)))
twitter_search_options <- c()
if (nchar(twitter_filter_from) > 2) {
twitter_search_options <- append(twitter_search_options, paste0("from:", twitter_filter_from))
search_term_flag <- TRUE
}
if (nchar(twitter_filter_to) > 2) {
twitter_search_options <- append(twitter_search_options, paste0("to:", twitter_filter_to))
search_term_flag <- TRUE
}
opts <- list("filter:safe" = !twitter_filter_safe,
"filter:media" = !twitter_filter_media,
"filter:links" = !twitter_filter_url,
":)" = !twitter_filter_positive,
":(" = !twitter_filter_negative)
sapply(names(opts), function(x) {
if (!VOSONDash::isNullOrEmpty(opts[x])) {
if (opts[x] == FALSE) { twitter_search_options <<- append(twitter_search_options, x) }
}
})
if (!VOSONDash::isNullOrEmpty(twitter_tweet_count) && is.numeric(twitter_tweet_count)) {
output <- append(output, paste0("number of tweets: ", twitter_tweet_count))
}
if (!VOSONDash::isNullOrEmpty(twitter_language)) {
output <- append(output, paste0("language: ", twitter_language))
}
if (!VOSONDash::isNullOrEmpty(twitter_date_until)) {
output <- append(output, paste0("until date: ", twitter_date_until, sep = ""))
}
if (!VOSONDash::isNullOrEmpty(twitter_since_id)) {
output <- append(output, paste0("since ID: ", twitter_since_id, sep = ""))
}
if (!VOSONDash::isNullOrEmpty(twitter_max_id)) {
output <- append(output, paste0("max ID: ", twitter_max_id, sep = ""))
}
if (length(twitter_search_options) > 0) {
output <- append(output, paste0("filters: ", paste0(twitter_search_options, collapse = " ")))
}
# if api key and video ids have been inputed enable collect button
if (!is.null(creds_rv$use_token) && search_term_flag) {
shinyjs::enable("twitter_collect_button")
} else {
shinyjs::disable("twitter_collect_button")
}
paste0(output, collapse = '\n')
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.