Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 195 additions & 19 deletions src/wtwitch
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env bash
#
# Description: Browse and watch Twitch without being tracked.
# Homepage: https://github.com/krathalan/wtwitch
#
Expand Down Expand Up @@ -464,12 +463,6 @@ TRANSLATIONS="$(cat <<EOF
"de": "No more streamers",
"es": "No more streamers",
"fr": "No more streamers"
},
"install_fzf_first": {
"en": "You need to install fzf to use this feature.",
"de": "You need to install fzf to use this feature.",
"es": "You need to install fzf to use this feature.",
"fr": "You need to install fzf to use this feature."
}
}
EOF
Expand Down Expand Up @@ -924,37 +917,220 @@ cache_online_subscription_json()
# Make request URL with all streamers followed by &, so the request URL looks something like:
# /streams?user_login=streamerone&user_login=streamertwo&user_login=streamerthree
local requestURL
requestURL="${TWITCH_API_URL}/streams?user_login=$(jq -r ".subscriptions[].streamer" "${CONFIG_FILE}" | awk 1 ORS="&user_login=")"
# Remove trailing &user_login=
requestURL="${requestURL%&user_login=}"
printf "" > "${CACHE_CHECK_JSON_TEXT_FILE}.tmp"
jq -r ".subscriptions[].streamer" "${CONFIG_FILE}" | xargs -n 99 | while read -r page
do
requestURL="${TWITCH_API_URL}/streams?user_login=$(echo "$page"| tr '\n' ' ' | sed 's/ /\&user_login=/g')"

# Get data of all online streamers (sans game names)
local -r allStreamerJson="$(download_file "${requestURL}")"
# Remove trailing &user_login=
requestURL="${requestURL%&user_login=}"

printf "%s" "${allStreamerJson}" > "${CACHE_CHECK_JSON_TEXT_FILE}"
# Get data of all online streamers (sans game names)
printf "%s" "$(download_file "${requestURL}")" >> "${CACHE_CHECK_JSON_TEXT_FILE}.tmp"
done

# merge all data arrays into one
sed 's/\],"pagination".*{"data":\[\]/]/g' < "${CACHE_CHECK_JSON_TEXT_FILE}.tmp" | sed 's/\],"pagination".*{"data":\[/,/g' > "${CACHE_CHECK_JSON_TEXT_FILE}"
# Print usernames to cache file for easy mapfile-ing for tab completion
jq -r ".data[].user_login" <<< "${allStreamerJson}" > "${CACHE_ONLINE_SUBS_TEXT_FILE}"
jq -r ".data[].user_login" < "${CACHE_CHECK_JSON_TEXT_FILE}" > "${CACHE_ONLINE_SUBS_TEXT_FILE}"

# Update lastSubscriptionUpdate time
write_setting ".lastSubscriptionUpdate" "${CURRENT_TIME_UNIX}" &
fi
}

#######################################
# Select and open online streams with FZF.
# Select and open online streams (uses FZF if available)
# Arguments:
# none
# Returns:
# none
#######################################

remove_ansi_escape_codes() {
sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g"
}



fsh() {
# https://github.com/yazgoo/fuzzysh/

setup_theme() {
selector_color=${FSH_SELECTOR_COLOR:=40}
grep_colors=${FSH_GREP_COLORS:='ms=01;92'}
frame_color=${FSH_FRAME_COLOR:=30}
prompt_color=${FSH_PROMPT_COLOR:=34}
select_color=${FSH_SELECT_COLOR:=31}
}

remove_ansi_escape_codes() {
sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2};?)?)?[mGK]//g"
}

get_new_choices() {
echo "$choices" | GREP_COLORS="$grep_colors" grep -i --color=always "$filter"
}

read_key() {
# not POSIX
IFS= read -rsn1 "$1" </dev/tty >&2
}

handle_key() {
read_key key
case "$key" in
' ') filter="$filter " ;;
$'\x1b')
read_key key3
# arrows
read_key key2
case "$key2" in
'A') [ "$item_n" -lt "$((n_choices - 1))" ] && item_n=$((item_n + 1)) ;;
'B') [ "$item_n" -gt 0 ] && item_n=$((item_n - 1)) ;;
*) ;;
esac
# flush stdin
read -rsn5 -t 0.1
;;
'')
result=$(echo "$new_choices" | head "-$((item_n + 1))" | tail -1 | remove_ansi_escape_codes)
running=false
;;
# not POSIX
$'\x7f') filter="${filter%?}" ;;
*) filter="${filter}${key}" ;;
esac
}

smcup() {
stty -echo
printf "\e[?1049h"
printf "\e[?25l"
}

rmcup() {
printf "\e[?1049l"
printf "\e[?25h"
stty echo
}

move_cursor_to() {
printf "\e[%d;%dH" "$1" "$2"
}

start_color() {
printf "\e[1;%dm" "$1"
}

end_color() {
printf "\e[0m"
}

draw_frame() {
move_cursor_to 0 0
start_color "$frame_color"
printf "┌%s┐" "$(printf '─%.0s' $(seq 1 $((columns - 2))))"
for i in $(seq 2 $((lines - 1)))
do
move_cursor_to "$i" 0
printf "│"
move_cursor_to "$i" $columns
printf "│"
done
move_cursor_to $lines 0
printf "└%s┘" "$(printf '─%.0s' $(seq 1 $((columns - 2))))"
end_color
}

print_text() {
(
i="$((n_choices - 1))"
echo "$new_choices" | tac | while read -r choice
do
cursor=" "$(end_color)
[ $i -eq $item_n ] && cursor=$(printf "%s>%s%s" "$(start_color "$select_color")" "$(end_color)" "$(start_color "$selector_color")")
printf "\n%s%s %s %s%s" "$(start_color "$selector_color")" "$cursor" "$choice" "$(end_color)" "$(printf " %.0s" $(seq 1 $((columns - 5 - ${#choice}))))"
i=$((i - 1))
done
display_n_choice="$n_choices"
[ "$new_choices" = "" ] && display_n_choice=0
choices_quota=$(printf "%d/%d" "$display_n_choice" "$total_n_choices")
printf "\n%s%s%s%s %s%s%s" "$(start_color "$frame_color")" "$choices_quota" "$(end_color)" "$header" $(start_color "$frame_color") "$(printf "─%.0s" $(seq 1 $((columns - 5 - ${#header} - ${#choices_quota}))))" "$(end_color)"
printf "\n%s>%s %s %s" "$(start_color "$prompt_color")" "$(end_color)" "$filter" "$(printf " %.0s" $(seq 1 $((columns - 5 - ${#filter}))))"
) | sed 's/^/ /'
}

draw_frame_content() {
new_choices=$(get_new_choices)
n_choices=$(echo "$new_choices" | wc -l)
start_line=$(( lines - n_choices - 4))
for i in $(seq 1 $((start_line + 1)))
do
move_cursor_to "$i" 0
printf " %0.s" $(seq 1 $((columns - 5)))
done
s=$(print_text)
printf "%s" "$s"
}

init() {
setup_theme
header=""
[ "$#" -gt 1 ] && header=" $1"
if read -t 0; then
choices=$(cat)
else
choices=$(find . -not -path '*/.*' | sed 's,^./,,')
fi
total_n_choices=$(echo "$choices" | wc -l)
filter=""
result=""
running=true
item_n=0
lines=$(tput lines)
columns=$(tput cols)
}

draw() {
draw_frame_content
draw_frame
}

run() {
clear >&2
while $running
do
draw >&2
handle_key >/dev/null 2>&1
done
}

main() {
init "$@"
smcup
run
rmcup
if [ -n "$result" ]; then
echo "$result"
else
false
fi
}

main "$@"
}

open_selected_stream()
{
if ! command -v "fzf" &> /dev/null; then
exit_script_on_failure "$(get_translation install_fzf_first)"
fi
local selector
selector=fsh

streams=$(check_twitch_streams --online-only)
stream="$(echo "$streams" | $selector | cut -d: -f1 | remove_ansi_escape_codes | sed -E "s/.* +//")"

stream="$(check_twitch_streams --online-only | fzf --ansi | cut -d: -f1 | sed 's/ *//')"
clear
echo "opening stream: $stream"

if [ -n "$stream" ]; then
watch_stream "$stream"
Expand Down