Skip to content

Commit 717688b

Browse files
authored
New segment github_notifications (#432)
* add new util function "is_tmp_valid" to make handling of temp files based on last update reusable * add new segment * add jq requirement to README.md fixes #431
1 parent 269d359 commit 717688b

File tree

3 files changed

+195
-0
lines changed

3 files changed

+195
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ Some segments have their own requirements. If you enable them in your theme, mak
106106
* `tmux_mem_cpu_load.sh`: [tmux-mem-cpu-load](https://github.com/thewtex/tmux-mem-cpu-load)
107107
* `rainbarf.sh`: [rainbarf](https://github.com/creaktive/rainbarf)
108108
* `weather.sh`: GNU `grep` with Perl regular expression enabled (FreeBSD specific), `jq` for yrno weather API.
109+
* `github_notifications.sh`: `jq` for GitHub API.
109110

110111
## FreeBSD specific requirements
111112
Preinstalled `grep` in FreeBSD doesn't support Perl regular expressions. Solution is rather simple -- you need to use `textproc/gnugrep` port instead. You also need to make sure, that it has support for PCRE and is compiled with `--enable-perl-regexp` flag.

lib/util.sh

+30
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,33 @@ is_flag_enabled() {
1212
;;
1313
esac
1414
}
15+
16+
is_tmp_valid() {
17+
local tmp_file="$1"
18+
local tmp_validity="$2"
19+
20+
if [ -f "$tmp_file" ]; then
21+
if shell_is_osx || shell_is_bsd; then
22+
stat >/dev/null 2>&1 && is_gnu_stat=false || is_gnu_stat=true
23+
if [ "$is_gnu_stat" == "true" ]; then
24+
last_update=$(stat -c "%Y" "${tmp_file}")
25+
else
26+
last_update=$(stat -f "%m" "${tmp_file}")
27+
fi
28+
elif shell_is_linux || [ -z "$is_gnu_stat" ]; then
29+
last_update=$(stat -c "%Y" "${tmp_file}")
30+
fi
31+
32+
time_now=$(date +%s)
33+
valid=$(echo "(${time_now}-${last_update}) < ${tmp_validity}" | bc)
34+
35+
if [ "$valid" -eq 1 ]; then
36+
return 0
37+
else
38+
return 1
39+
fi
40+
else
41+
return 1
42+
fi
43+
44+
}

segments/github_notifications.sh

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# shellcheck shell=bash
2+
3+
# shellcheck source=lib/util.sh
4+
source "${TMUX_POWERLINE_DIR_LIB}/util.sh"
5+
6+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE:-$(date +%Y-%m-%dT00:00:00Z)}"
7+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE_ENABLE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE_ENABLE:-no}"
8+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_PER_PAGE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_PER_PAGE:-50}"
9+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_MAX_PAGES="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_MAX_PAGES:-10}"
10+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_UPDATE_INTERVAL="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_UPDATE_INTERVAL:-60}"
11+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SUMMARIZE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SUMMARIZE:-no}"
12+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SYMBOL_MODE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SYMBOL_MODE:-yes}"
13+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_HIDE_NO_NOTIFICATIONS="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_HIDE_NO_NOTIFICATIONS:-yes}"
14+
TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TEST_MODE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TEST_MODE:-no}"
15+
16+
_GITHUB_NOTIFICATIONS_TEST_RESPONSE='
17+
[
18+
{"reason": "approval_requested"},
19+
{"reason": "assign"},
20+
{"reason": "author"},
21+
{"reason": "comment"},
22+
{"reason": "ci_activity"},
23+
{"reason": "invitation"},
24+
{"reason": "manual"},
25+
{"reason": "mention"},
26+
{"reason": "review_requested"},
27+
{"reason": "security_alert"},
28+
{"reason": "state_change"},
29+
{"reason": "subscribed"},
30+
{"reason": "team_mention"}
31+
]
32+
'
33+
34+
generate_segmentrc() {
35+
read -r -d '' rccontents <<EORC
36+
# Github token (https://github.com/settings/tokens) with at least "notifications" scope
37+
export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TOKEN=""
38+
# Include available notification reasons (https://docs.github.com/en/rest/activity/notifications?apiVersion=2022-11-28#about-notification-reasons),
39+
# in the format "REASON:SEPARATOR"
40+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS="approval_requested:-󰴄 |assign:-󰎔 |author:-󰔗 |comment:- |ci_activity:-󰙨 |invitation:- |manual:-󱥃 |mention:- |review_requested:- |security_alert:-󰒃 |state_change:-󱇯 |subscribed:- |team_mention:- "
41+
# Or if you don't like so many symbols, try the abbreviation variant
42+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS="approval_requested:areq|assign:as|author:au|comment:co|ci_activity:ci|invitation:in|manual:ma|mention:me|review_requested:rreq|security_alert:sec|state_change:st|subscribed:sub|team_mention:team"
43+
# Use symbol mode (ignored if you set TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS yourself)
44+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SYMBOL_MODE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SYMBOL_MODE}"
45+
# Summarize all notifications
46+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SUMMARIZE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SUMMARIZE}"
47+
# Hide if no notifications
48+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_HIDE_NO_NOTIFICATIONS="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_HIDE_NO_NOTIFICATIONS}"
49+
# Only show new notifications since date (default: today) (takes up to UPDATE_INTERVAL time to take effect)
50+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE="\$(date +%Y-%m-%dT00:00:00Z)"
51+
# Enable show only notifications since date (takes up to UPDATE_INTERVAL time to take effect)
52+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE_ENABLE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE_ENABLE}"
53+
# Maximum notifications to retreive per page (upstream github default per_page, 50)
54+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_PER_PAGE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_PER_PAGE}"
55+
# Maximum pages to retreive
56+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_MAX_PAGES="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_MAX_PAGES}"
57+
# Update interval to pull latest state from github api
58+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_UPDATE_INTERVAL="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_UPDATE_INTERVAL}"
59+
# Enable Test Mode (to test how the segment will look like when you have notifications for all types/reasons)
60+
# export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TEST_MODE="${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TEST_MODE}"
61+
EORC
62+
echo "$rccontents"
63+
}
64+
65+
run_segment() {
66+
__process_settings
67+
if ! type curl >/dev/null 2>&1; then
68+
return 0
69+
fi
70+
71+
if [ -z "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TOKEN" ] && ! is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TEST_MODE"; then
72+
return 0
73+
fi
74+
75+
local tmp_file
76+
local api_url
77+
local api_query
78+
local auth_header
79+
80+
tmp_file="${TMUX_POWERLINE_DIR_TEMPORARY}/github_notifications.stat"
81+
tmp_headers_file="$TMUX_POWERLINE_DIR_TEMPORARY/github_notifications.headers"
82+
83+
api_url="https://api.github.com/notifications"
84+
85+
if is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE_ENABLE"; then
86+
api_query="since=${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SINCE}&"
87+
fi
88+
api_query="${api_query}per_page=${TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_PER_PAGE}"
89+
90+
auth_header="Authorization: Bearer $TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TOKEN"
91+
92+
if ! is_tmp_valid "$tmp_file" "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_UPDATE_INTERVAL"; then
93+
if is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_TEST_MODE"; then
94+
notifications=$_GITHUB_NOTIFICATIONS_TEST_RESPONSE
95+
else
96+
read -r -d '' notifications < <(curl -s --url "${api_url}?${api_query}" -D "$tmp_headers_file" --header "$auth_header")
97+
# Handle paging (we only get "link" header when there are more pages)
98+
# For more information see: https://docs.github.com/en/rest/using-the-rest-api/using-pagination-in-the-rest-api?apiVersion=2022-11-28#using-link-headers
99+
if link=$(grep '^link: ' "$tmp_headers_file"); then
100+
# Get last page number
101+
last_page=$(echo "$link" | sed -r 's/.*page=([0-9]+)>; rel="last".*/\1/' | tr -d '\r\n')
102+
# We already got the first page, so we start now with page 2
103+
page=2
104+
# Get pages until we got the last page or up until configured max pages
105+
until [ "$page" -gt "$last_page" ] || [ "$page" -gt "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_MAX_PAGES" ]; do
106+
read -r -d '' _tmp_notifications < <(curl -s --url "${api_url}?${api_query}&page=$page" --header "$auth_header")
107+
notifications=$(jq -s 'add' <(echo "$notifications") <(echo "$_tmp_notifications"))
108+
((page++))
109+
done
110+
fi
111+
fi
112+
113+
all_count=0
114+
result=""
115+
116+
IFS=$'|' read -r -a reasons_list <<<"$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS"
117+
118+
for reason_entry in "${reasons_list[@]}"; do
119+
count=0
120+
IFS=$':' read -r reason separator <<<"$reason_entry"
121+
count="$(echo "$notifications" | jq -c '.[] | select( .reason == "'"$reason"'" )' | jq -s 'length')"
122+
123+
if [ "$count" -eq 0 ] && is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_HIDE_NO_NOTIFICATIONS"; then
124+
continue
125+
fi
126+
127+
if is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SUMMARIZE"; then
128+
all_count="$((all_count + count))"
129+
else
130+
if ! [[ "$separator" =~ ^-.*$ ]]; then
131+
result="$result $separator:$count"
132+
else
133+
result="$result ${separator:1}$count"
134+
fi
135+
fi
136+
done
137+
138+
if is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SUMMARIZE"; then
139+
if [ "$all_count" -gt 0 ] || ! is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_HIDE_NO_NOTIFICATIONS"; then
140+
echo "$all_count" >"$tmp_file"
141+
else
142+
echo -n >"$tmp_file"
143+
fi
144+
else
145+
if [ -n "$result" ] || ! is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_HIDE_NO_NOTIFICATIONS"; then
146+
echo "$result" >"$tmp_file"
147+
else
148+
echo -n >"$tmp_file"
149+
fi
150+
fi
151+
fi
152+
153+
cat "$tmp_file"
154+
}
155+
156+
__process_settings() {
157+
if [ -z "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS" ]; then
158+
if is_flag_enabled "$TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_SYMBOL_MODE"; then
159+
export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS="approval_requested:-󰴄 |assign:-󰎔 |author:-󰔗 |comment:- |ci_activity:-󰙨 |invitation:- |manual:-󱥃 |mention:- |review_requested:- |security_alert:-󰒃 |state_change:-󱇯 |subscribed:- |team_mention:- "
160+
else
161+
export TMUX_POWERLINE_SEG_GITHUB_NOTIFICATIONS_REASONS="approval_requested:areq|assign:as|author:au|comment:co|ci_activity:ci|invitation:in|manual:ma|mention:me|review_requested:rreq|security_alert:sec|state_change:st|subscribed:sub|team_mention:team"
162+
fi
163+
fi
164+
}

0 commit comments

Comments
 (0)