-
Notifications
You must be signed in to change notification settings - Fork 0
/
BiocSlack.qmd
150 lines (132 loc) · 5.31 KB
/
BiocSlack.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
---
title: "Slack channels"
subtitle: "Explore [Bioconductor](bioconductor.org) Slack channels at [https://slack.bioconductor.org/](https://slack.bioconductor.org/) and join conversations that spark your interest. Our table lists all public channels, updated daily. It displays the date and time of the last activity - whether it's a message or a thread reply - alongside a notation indicating how recent this activity was at the time of the last update. Open to everyone interested in Bioconductor, these channels are a great place to participate and collaborate."
date: now
date-format: "DD MMMM YYYY, HH:mm[Z]"
format:
html:
template-partials:
- title-block.html
grid:
sidebar-width: 0px
body-width: 2000px
margin-width: 0px
gutter-width: 1.5rem
editor: visual
execute:
message: false
warning: false
echo: false
cache: true
css: styles.css
---
```{r setup, include=FALSE}
library(slackr)
library(dplyr)
library(tidyr)
library(lubridate)
library(purrr)
library(reactable)
# Safe wrapper for slackr_channels call with error handling
safe_slackr_channels <- function(token) {
tryCatch({
slackr_channels(token = token, exclude_archived = TRUE)
}, error = function(e) {
message("Error fetching Slack channels: ", e$message)
return(NULL) # Return NULL on failure
})
}
# Safe wrapper for slackr_history call with error handling
safe_slackr_history <- function(channel_id, token) {
tryCatch({
slackr_history(channel = channel_id, token = token, message_count = 100)
}, error = function(e) {
message("Error fetching history for channel ID ", channel_id, ": ", e$message)
return(tibble()) # Return an empty tibble on failure
})
}
# Capture the current date and time in UTC
last_update <- with_tz(Sys.time(), "UTC")
```
```{r}
# Retrieve a list of all public Bioconductor Slack channels using the safe wrapper function
sc <- safe_slackr_channels(token = Sys.getenv("SLACK_TOKEN")) |>
filter(!is_private) |>
unnest(cols = c(topic, purpose), names_sep = "_") |>
mutate(created = as_date(as_datetime(created))) |> # Convert creation timestamp to readable date
select(id, name, topic_value, purpose_value, created, num_members)
```
```{r}
# Fetch message history for each public channel using the safe wrapper function
sm <-
map_dfr(
.x = set_names(na.omit(sc$id)),
.f = ~ safe_slackr_history(.x, Sys.getenv("SLACK_TOKEN")),
.id = "id"
)
```
```{r}
# Process message data to find the latest activity for each channel
# Compare latest message and thread reply to determine the most recent
sm_latest <- sm |>
filter(is.na(subtype) | subtype %in% c("thread_broadcast", "bot_message")) |>
separate(ts, c("ts_formatted", NA)) |>
mutate(
latest = as_datetime(as.integer(ts_formatted), tz = "UTC"), # Latest message timestamp
latest_reply = as_datetime(as.integer(root$latest_reply), tz = "UTC"), # Latest reply in a thread
final_latest = pmax(latest, latest_reply, na.rm = TRUE), # Determine the most recent activity
TimeDiff = difftime(last_update, final_latest, units = "mins"),
# Calculate time difference and format for display
`Last Activity` = format(final_latest, "%Y-%m-%d %H:%M %Z"), # Timestamp of last activity
`Time Since Last Activity` = case_when(
TimeDiff < 60 ~ paste0(round(TimeDiff), " mins ago"),
TimeDiff < 1440 ~ paste0(round(TimeDiff / 60), " hours ago"),
TimeDiff < 43200 ~ paste0(round(TimeDiff / 1440), " days ago"),
TimeDiff < 525600 ~ paste0(round(TimeDiff / 43200), " months ago"),
TRUE ~ paste0(round(TimeDiff / 525600), " years ago")
)
) |>
group_by(id) |>
slice_max(final_latest, with_ties = FALSE) |>
ungroup()
```
```{r}
# Combine channel information with the latest activity data
# Prepare final dataset for table visualisation
all <- left_join(sc, sm_latest, by = "id") |>
select(name.x, topic_value, purpose_value, num_members, created, `Last Activity`, `Time Since Last Activity`) |>
rename(Name = name.x, Topic = topic_value, Description = purpose_value, `Number of Members` = num_members, `Created` = created)
```
[**Last Update:** `r format(last_update, "%Y-%m-%d %H:%M %Z")` - The "Last Activity" and "Time Since Last Activity" data points are calculated relative to this timestamp. This provides a snapshot of channel activities up to this moment.]{style="font-size: smaller; font-style: italic;"}
```{r}
# Determine the appropriate page size options
page_sizes <- c(10, 25, 50, 100)
max_rows <- nrow(all)
if (max_rows > max(page_sizes)) {
# Round up the maximum number of rows to the nearest multiple of 50
max_rows_rounded <- ceiling(max_rows / 50) * 50
page_sizes <- c(page_sizes, max_rows_rounded)
}
# Create a searchable and sortable table using Reactable
# Configures visual aspects of the table for better readability
all |>
reactable(
columns = list(
Name = colDef(minWidth = 150),
Topic = colDef(minWidth = 300),
Description = colDef(minWidth = 300)
),
defaultSorted = "Last Activity", defaultSortOrder = "desc",
style = list(fontSize = "0.875rem"),
resizable = TRUE,
searchable = TRUE,
highlight = TRUE,
compact = TRUE,
showPageSizeOptions = TRUE,
defaultPageSize = page_sizes[1],
pageSizeOptions = page_sizes
)
```
::: {#footer}
[![](https://github.githubassets.com/favicon.ico)](https://github.com/mblue9/BiocSlack)
:::