library(tidyverse)
library(httr)
library(jsonlite)
library(scales)
library(ggthemes)
library(ggrepel)
# data source
<- "https://instances.mastodon.xyz/"
url
<- GET(paste0(url, "instances.json")) %>%
mastodon content(as = "text") %>%
fromJSON() %>%
select(-info) %>%
filter(!str_detect(name, "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")) %>% # remove IP
mutate(statuses = as.integer(statuses),
name_clean = str_remove(str_to_lower(name), "/$|\\.$|:\\d*$"), # remove trailing dots, slashes and port number
tld = str_replace_all(name_clean, "(.*?)(\\.[a-z0-9]*)$", "\\2")) %>% # extract TLD
filter(! tld %in% c("0")) # remove special cases
<- format(Sys.time(), tz = "UTC", usetz = TRUE)
download_time
# saveRDS(mastodon, paste0("data/mastodon_", download_time, ".rds"))
<- nrow(mastodon)
nbi <- sum(mastodon$users, na.rm = TRUE)
nbu
# cleaning and
# plot the TLDs (top level domains) of Mastondon instances -----------------------
%>%
mastodon filter(! str_detect(tld, "xn--")) %>%
group_by(tld) %>%
summarise(nb = n(),
users = sum(users, na.rm = TRUE),
statuses = sum(statuses, na.rm = TRUE)) %>%
filter(nb > 0 & users > 0 & statuses > 0) %>% {
ggplot(., aes(users, statuses, label = tld, size = nb, color = nb)) +
geom_text_repel(segment.size = 0, force = 0.5) +
#geom_point(alpha = 0.4) +
labs(title = "Mastodon Top Level Domains",
subtitle = paste(nrow(.), "TLDs for", nbi, "instances having", nbu, "users -", download_time),
x = "users",
y = "statuses",
caption = paste("r.iresmi.net\ndata from", url, "\nIDN removed ; positions adapted for clarity")) +
scale_x_log10(labels = comma) +
scale_y_log10(labels = comma) +
scale_color_viridis_c(trans = "log", name = "# of\ninstances", labels = function(x) round(x, 0)) +
scale_size(range = c(3, 10), guide = FALSE) +
theme(plot.caption = element_text(size = 7)) }
<- paste0("img/mastodon_tld_", download_time, ".png")) %>%
(plot_file ggsave(width = 15, height = 10, units = "cm", dpi = 100, scale = 2)
Mastodon is a decentralized microblogging platform.
We can analyse some data and directly post our findings to a Mastodon instance.
For example we can plot the different TLDs used by the Mastodon Fediverse and publish it on mastodon.cloud.
NB: the API has changed and it doesn’t work anymore. See other implementations now, like {mastodon} or {rtoot}.
Before posting we have to create an authorization token once.
# Registration
# run this part once and write down client_id and client_secret,
# you can then comment this part
<- POST(paste0(instance , "api/v1/apps"),
r body = list(client_name = "my_application_name",
redirect_uris = "urn:ietf:wg:oauth:2.0:oob",
scopes = "write"))
stop_for_status(r)
<- content(r)
apps
paste("client_id :", apps[["client_id"]])
paste("client_secret", apps[["client_secret"]])
# end of registration ; set your client id/secret below
Login:
# Your instance, login and password
<- "https://mastodon.cloud/"
instance <- "*******"
user <- "*******"
pass
<- "********************"
client_id <- "******************"
client_secret
# Login -------------------------------------------------------------------
<- POST(paste0(instance , "oauth/token"),
r body = list(client_id = client_id,
client_secret = client_secret,
grant_type = "password",
username = user,
password = pass,
scope = "write"))
stop_for_status(r)
<- content(r) token
We can then post the created image and its accompanying status.
# post image
<- POST(paste0(instance , "api/v1/media"),
r add_headers(Authorization = paste("Bearer", token[["access_token"]])),
body = list(file = upload_file(plot_file)))
stop_for_status(r)
<- content(r)
media
# post status
<- POST(paste0(instance , "/api/v1/statuses"),
r add_headers(Authorization = paste("Bearer", token[["access_token"]])),
body = list(status = paste0("#Mastodon Top Level Domains\n#Rstats\n", media[["text_url"]]),
"media_ids[]" = media[["id"]]))
stop_for_status(r)
<- content(r) statuses