Skip to content

Instantly share code, notes, and snippets.

@maguay
Created July 14, 2025 08:46
Show Gist options
  • Select an option

  • Save maguay/9d83d1ef714cb6f828c29b3e255a5e15 to your computer and use it in GitHub Desktop.

Select an option

Save maguay/9d83d1ef714cb6f828c29b3e255a5e15 to your computer and use it in GitHub Desktop.
Buttondown | Slack Top Threads to Email script
# A Bash script to pull the three most popular Slack threads from the last week and merge them with an email template.
# Copy everything from line 7 on, add in your Slack token, channel ID, workspace URL, and Buttondown API key, then run in Terminal.
# See https://buttondown.com/blog/api-powered-email-newsletter for more details.
-----
#!/bin/bash
SLACK_TOKEN="your-Slack-bot-token"
CHANNEL_ID="your_channel_ID"
WORKSPACE_URL="https://yourworkspace.slack.com"
EMAIL_TEMPLATE="email_template.txt"
BUTTONDOWN_API_TOKEN="buttondown_API_key"
seven_days_ago=$(date -v-7d +%s)
thread_data=$(curl -s -H "Authorization: Bearer $SLACK_TOKEN" \
"https://slack.com/api/conversations.history?channel=$CHANNEL_ID&limit=200" \
| jq -r --arg seven_days_ago "$seven_days_ago" '.messages[] | select(.thread_ts != null and .thread_ts == .ts and (.ts | tonumber) >= ($seven_days_ago | tonumber)) | "\(.ts)|\(.user)|\(.text)|\(.reply_count // 0)"' \
| sort -t'|' -k4,4nr \
| head -3)
thread_num=0
while IFS='|' read -r thread_ts user_id text reply_count; do
thread_num=$((thread_num + 1))
user_info=$(curl -s -H "Authorization: Bearer $SLACK_TOKEN" \
"https://slack.com/api/users.info?user=$user_id")
username=$(echo "$user_info" | jq -r '.user.name')
real_name=$(echo "$user_info" | jq -r '.user.real_name')
timestamp=$(echo "$thread_ts" | cut -d'.' -f1)
formatted_date=$(date -r "$timestamp" "+%A, %B %d, %l:%M%p" | sed 's/ / /g' | sed 's/AM/am/g' | sed 's/PM/pm/g')
links=$(echo "$text" | grep -oE 'https?://[^>|[:space:]]+' | tr '\n' ' ')
thread_link="$WORKSPACE_URL/archives/$CHANNEL_ID/p$(echo "$thread_ts" | tr -d '.')"
reply_data=$(curl -s -H "Authorization: Bearer $SLACK_TOKEN" \
"https://slack.com/api/conversations.replies?channel=$CHANNEL_ID&ts=$thread_ts" \
| jq -r '.messages[1:] | map(. + {reaction_count: ((.reactions // []) | map(.count) | add // 0)}) | sort_by(.reaction_count) | reverse | .[0:3] | .[] | "\(.user)|\(.text)"')
reply_count=1
while IFS='|' read -r reply_user reply_text; do
if [[ -n "$reply_user" && -n "$reply_text" ]]; then
reply_user_info=$(curl -s -H "Authorization: Bearer $SLACK_TOKEN" \
"https://slack.com/api/users.info?user=$reply_user")
reply_username=$(echo "$reply_user_info" | jq -r '.user.name')
eval "THREAD_${thread_num}_TOP_REPLY_${reply_count}=\"@$reply_username: $reply_text\""
((reply_count++))
fi
done <<< "$reply_data"
while [[ $reply_count -le 3 ]]; do
eval "THREAD_${thread_num}_TOP_REPLY_${reply_count}=\"\""
((reply_count++))
done
eval "THREAD_${thread_num}_USERNAME=\"$username\""
eval "THREAD_${thread_num}_REAL_NAME=\"$real_name\""
eval "THREAD_${thread_num}_DATE_TIME=\"$formatted_date\""
eval "THREAD_${thread_num}_TEXT=\"$text\""
eval "THREAD_${thread_num}_LINKS=\"$links\""
eval "THREAD_${thread_num}_LINK=\"$thread_link\""
done <<< "$thread_data"
for i in 1 2 3; do
if eval "[[ -n \"\$THREAD_${i}_USERNAME\" ]]"; then
eval "export THREAD_${i}_USERNAME=\"\$THREAD_${i}_USERNAME\""
eval "export THREAD_${i}_REAL_NAME=\"\$THREAD_${i}_REAL_NAME\""
eval "export THREAD_${i}_DATE_TIME=\"\$THREAD_${i}_DATE_TIME\""
eval "export THREAD_${i}_TEXT=\"\$THREAD_${i}_TEXT\""
eval "export THREAD_${i}_LINKS=\"\$THREAD_${i}_LINKS\""
eval "export THREAD_${i}_LINK=\"\$THREAD_${i}_LINK\""
eval "export THREAD_${i}_TOP_REPLY_1=\"\$THREAD_${i}_TOP_REPLY_1\""
eval "export THREAD_${i}_TOP_REPLY_2=\"\$THREAD_${i}_TOP_REPLY_2\""
eval "export THREAD_${i}_TOP_REPLY_3=\"\$THREAD_${i}_TOP_REPLY_3\""
else
eval "export THREAD_${i}_USERNAME=\"\""
eval "export THREAD_${i}_REAL_NAME=\"\""
eval "export THREAD_${i}_DATE_TIME=\"\""
eval "export THREAD_${i}_TEXT=\"\""
eval "export THREAD_${i}_LINKS=\"\""
eval "export THREAD_${i}_LINK=\"\""
eval "export THREAD_${i}_TOP_REPLY_1=\"\""
eval "export THREAD_${i}_TOP_REPLY_2=\"\""
eval "export THREAD_${i}_TOP_REPLY_3=\"\""
fi
done
if [[ -f "$EMAIL_TEMPLATE" ]]; then
content=$(cat "$EMAIL_TEMPLATE")
content=$(echo "$content" | envsubst)
subject=$(echo "$content" | grep -m 1 '^# ' | sed 's/^# //')
body=$(echo "$content" | sed -n '/^# /,$p' | tail -n +2)
curl -X POST \
"https://api.buttondown.com/v1/emails" \
-H "Authorization: Token $BUTTONDOWN_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg subject "$subject" --arg body "$body" '{subject: $subject, body: $body, status: "draft"}')"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment