top of page

CancelBot: Twitter Profanity Finder

  • toldham2
  • Jan 20, 2022
  • 1 min read

Updated: May 13, 2023

This R Shiny App collects tweets from any Twitter user and displays all of their tweets containing vulgarity.


NOTE: STILL WORKS AS OF 5/14/23 DESPITE TWITTER CLAIMING TO HAVE REMOVED FREE API ACCESS


This Shiny App collects all tweets (3,200 max) from any Twitter username and displays all of their tweets containing vulgarity. Try it on yourself to make sure your social media is clean for a job application, or cause a little bit of trouble and try it on someone else.



Code

library(shiny)


# Define UI for application that draws a histogram

ui <- fluidPage(

tags$head(

tags$script(async = NA,

src = "https://platform.twitter.com/widgets.js")

),

titlePanel("CancelBot"),

sidebarLayout(

sidebarPanel(

helpText(

"See a Twitter user's explicit and/or offensive tweets.\nWARNING: App will crash if username invalid or if user has no vulgar tweets."

),

br(),

textInput(

"username",

label = h5("Enter a Twitter handle"),

placeholder = "Enter handle..."

),

checkboxInput("checkStrict", "Strict Lexicon", value = FALSE),

checkboxInput("checkReplies", "Include Replies", value = FALSE),

checkboxInput("checkRts", "Include Retweets", value = FALSE),

actionButton("actionConfirm", "Get Tweets")

), # sidebarPanel

mainPanel(lapply(1:3200, function(i) {

uiOutput(paste0('tweet', i))

})) # mainPanel

) # sidebarLayout

) # fluidPage


# Define server logic required to draw a histogram

server <- function(input, output) {

# ---- Libraries ----

library(academictwitteR)

library(tidytext)

library(stringr)

library(dplyr)

# ---- run App ----

observeEvent(input$actionConfirm, {

withProgress(message = 'Getting Tweets', value = 0, {

# ---- Get Parameters ----

incProgress(1 / 5, detail = "Setting parameters...")

username <- input$username

strict = input$checkStrict

replies = input$checkReplies

retweets = input$checkRts

incProgress(1 / 5, detail = "Getting user ID...")

if (str_detect(username, "@")) {

username <- str_replace(username, "@", "")

}

bearer <- "AAAAAAAAAAAAAAAAAAAAAKBjWwEAAAAAdzslRclhVPpPk%2BpLmsag%2FaMP1Lc%3DOFW3srfgJ4yNluxIgjEsFwJ5oHsDuuinHJcf13NYFY1reCAHyk"

user_id <- get_user_id(username, bearer)

# ---- Get Tweets ----

incProgress(1 / 5, detail = "Getting all tweets...")

tweets <- get_user_timeline(

user_id,

start_tweets = "2010-11-06T00:00:00Z",

end_tweets = paste0(Sys.Date(), "T00:00:00Z"),

bearer_token = bearer,

n = 3200,

bind_tweets = TRUE,

verbose = FALSE

)

# ---- Format Tweet Data ----

incProgress(1 / 5, detail = "Filtering tweets...")

if (!retweets) {

tweets <- tweets[!grepl("RT @", tweets$text),]

}

if (!replies) {

tweets <- tweets[!grepl("@", tweets$text),]

}

tweets_unnested <- tweets %>%

unnest_tokens(word, text, drop = FALSE)

# ---- Get Bad Tweets ----

idlist <- list()

if (strict) {

badwords <-

read.csv(

"data/LDNOOBW-Strict/strictwords.csv"

)

varList <- names(badwords)

for (i in 1:nrow(tweets_unnested)) {

lang <- tweets_unnested[i, "lang"]

if (lang %in% varList) {

for (badword in badwords[, lang]) {

if ((badword == tweets_unnested[i, "word"]) && (badword != "")) {

idlist <- append(idlist, tweets_unnested[i, "id"])

}

}

}

}

} else {

badwords <-

read.csv(

"data/LDNOOBW-Lax/laxwords.csv"

)

varList <- names(badwords)

for (i in 1:nrow(tweets_unnested)) {

lang <- tweets_unnested[i, "lang"]

if (lang %in% varList) {

for (badword in badwords[, lang]) {

if ((badword == tweets_unnested[i, "word"]) && (badword != "")) {

idlist <- append(idlist, tweets_unnested[i, "id"])

}

}

}

}

}

id_df <- do.call(rbind.data.frame, idlist)

colnames(id_df) <- c("id")

id_df <- id_df %>% distinct()

incProgress(1 / 5, detail = "Printing tweets...")

lapply(1:nrow(id_df), function(i) {

outputID <- paste0("tweet", i)

outputLink <- paste0("https://twitter.com/", username, "/status/", id_df[i, "id"])

outputScript <- paste0("twttr.widgets.load(document.getElementById('",

outputID,

"'));")

output[[outputID]] <- renderUI({

tagList(

tags$blockquote(class = "twitter-tweet",

tags$a(href = outputLink)),

tags$script(outputScript)

)

}) # renderUI

}) # loop

}) # withProgress

}) # observeEvent actionConfirm

} # function


# Run the application

shinyApp(ui = ui, server = server)


Comments


bottom of page