finished version 1.0
This commit is contained in:
parent
80c09e9afe
commit
3981686040
|
@ -1,21 +1,39 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# TODO:
|
||||||
|
# - save last 5 VODlists and offer replay function to avoid refetching unnecesarily
|
||||||
|
|
||||||
|
|
||||||
# ${1} (optional) username to search VODs of
|
# ${1} (optional) username to search VODs of
|
||||||
|
|
||||||
|
[ "${1}" = "-h" ] || [ "${1}" = "--help" ] && {
|
||||||
|
printf "usage: getvods <username(optional)>\n"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
# ${1} is a string with error reason stated
|
# ${1} is a string with error reason stated
|
||||||
# ${2} is an optional string to report a different error status
|
# ${2} is an optional string to report a different error status
|
||||||
CFG_DIR="${HOME}/.config/getvods"
|
|
||||||
|
|
||||||
on_fail(){
|
on_fail(){
|
||||||
printf "last ran command error status: %s\n" "${2:-${?}}"
|
printf "last ran command error status: %s\n" "${2:-${?}}"
|
||||||
printf "error: %s\n" "${1}"
|
printf "error: %s\n" "${1}"
|
||||||
exit 2
|
exit 2
|
||||||
}
|
}
|
||||||
|
|
||||||
# twitch api credentials
|
CFG_DIR="${HOME}/.config/getvods"
|
||||||
client_id="$(cat "${CFG_DIR}/client_id")"
|
[ ! -d "${CFG_DIR}" ] && {
|
||||||
client_secret="$(cat "${CFG_DIR}/client_secret")"
|
mkdir -p "${CFG_DIR}" || on_fail "${CFG_DIR} doesn't exist and couldn't be made (check write permissions to ${CFG_DIR})"
|
||||||
|
}
|
||||||
|
|
||||||
|
# get twitch api credentials
|
||||||
|
[ ! -f "${CFG_DIR}/client_id" ] && {
|
||||||
|
read -p "enter your twitch API client_id >" client_id
|
||||||
|
[ ! -z "${client_id}" ] && printf "%s" "${client_id}" > "${CFG_DIR}/client_id" || on_fail "couldn't write client_id to ${CFG_DIR}/client_id"
|
||||||
|
} || client_id="$(cat "${CFG_DIR}/client_id")"
|
||||||
|
[ ! -f "${CFG_DIR}/client_secret" ] && {
|
||||||
|
read -p "enter your twitch API client_secret >" client_secret
|
||||||
|
[ ! -z "${client_secret}" ] && printf "%s" "${client_secret}" > "${CFG_DIR}/client_secret" || on_fail "couldn't write client_secret to ${CFG_DIR}/client_secret"
|
||||||
|
} || client_secret="$(cat "${CFG_DIR}/client_secret")"
|
||||||
|
|
||||||
|
# get access token
|
||||||
get_token(){
|
get_token(){
|
||||||
curl -s -X POST https://id.twitch.tv/oauth2/token -d "client_id=${client_id}" -d "client_secret=${client_secret}" -d "grant_type=client_credentials" > "${CFG_DIR}/token.json" || {
|
curl -s -X POST https://id.twitch.tv/oauth2/token -d "client_id=${client_id}" -d "client_secret=${client_secret}" -d "grant_type=client_credentials" > "${CFG_DIR}/token.json" || {
|
||||||
last_err="${?}"
|
last_err="${?}"
|
||||||
|
@ -29,7 +47,6 @@ get_token(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# get access token
|
|
||||||
[ -f "${CFG_DIR}/token.json" ] && [ -f "${CFG_DIR}/expiration.txt" ] && {
|
[ -f "${CFG_DIR}/token.json" ] && [ -f "${CFG_DIR}/expiration.txt" ] && {
|
||||||
[ "$(cat "${CFG_DIR}/expiration.txt")" -le "$(date +%s)" ] && get_token
|
[ "$(cat "${CFG_DIR}/expiration.txt")" -le "$(date +%s)" ] && get_token
|
||||||
} || {
|
} || {
|
||||||
|
@ -43,20 +60,36 @@ access_token="$(grep -o "access_token\":\"[a-zA-Z0-9]\+" "${CFG_DIR}/token.json"
|
||||||
on_fail "couldn't get token (token empty)" "${last_err}"
|
on_fail "couldn't get token (token empty)" "${last_err}"
|
||||||
}
|
}
|
||||||
|
|
||||||
[ ! -z "${1}" ] && login="${1}" || read -p 'type in username >' login
|
# get the username to search for
|
||||||
|
declare -i retries=0
|
||||||
|
[ ! -z "${1}" ] && {
|
||||||
|
[ "${#1}" -ge "4" ] && [ "${#1}" -le "25" ] && grep "[a-zA-Z0-9_]\{4,25\}" <<< "${1}" >/dev/null && {
|
||||||
|
login="${1}"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
printf "username must be between 4 and 25 characters long\n"
|
||||||
|
printf "username may have only characters a-z A-Z 0-9 and _\n"
|
||||||
|
retries+=1
|
||||||
|
}
|
||||||
|
[ -z "${login}"] && {
|
||||||
|
while :; do
|
||||||
|
read -p 'type in username >' login
|
||||||
|
[ "${#login}" -ge "4" ] && [ "${#login}" -le "25" ] && grep "[a-zA-Z0-9_]\{4,25\}" <<< "${login}" >/dev/null && break
|
||||||
|
printf "username must be between 4 and 25 characters long\n"
|
||||||
|
printf "username may have only characters a-z A-Z 0-9 and _\n"
|
||||||
|
retries+=1
|
||||||
|
[ "${retries}" -ge 3 ] && on_fail "exceeded max retries" "1"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
# get user id
|
# get user id
|
||||||
[ ! -f "${CFG_DIR}/userlist.txt" ] || [ "${login}" != "$(grep "${login}" "${CFG_DIR}/userlist.txt" | awk -F ":|," '{print $4}')" ] && {
|
[ ! -f "${CFG_DIR}/userlist.txt" ] || [ "${login}" != "$(grep "${login}" "${CFG_DIR}/userlist.txt" | awk -F ":|," '{print $4}')" ] && {
|
||||||
user_response="$(curl -s -G -X GET "https://api.twitch.tv/helix/users" -d "login=${login}" -H "Authorization: Bearer ${access_token}" -H "client-id: ${client_id}")"
|
user_response="$(curl -s -G -X GET "https://api.twitch.tv/helix/users" -d "login=${login}" -H "Authorization: Bearer ${access_token}" -H "client-id: ${client_id}")"
|
||||||
[ "${?}" -gt 0 ] && {
|
|
||||||
last_err="${?}"
|
last_err="${?}"
|
||||||
on_fail "couldn't get user_id (curl error)" "${last_err}"
|
[ "${last_err}" -gt 0 ] && on_fail "couldn't get user_id (curl error)" "${last_err}"
|
||||||
}
|
parsed_user_response="$(grep -o "id\":\"[0-9]\+\",\"login\":\"[a-zA-Z0-9_]\{4,25\}" <<< "${user_response}")"
|
||||||
parsed_user_response="$(grep -o "id\":\"[0-9]\+\",\"login\":\"[a-zA-Z0-9]\+" <<< "${user_response}")"
|
|
||||||
[ "${?}" -gt 0 ] && {
|
|
||||||
last_err="${?}"
|
last_err="${?}"
|
||||||
on_fail "couldn't get user_id (user_id empty)" "${last_err}"
|
[ "${last_err}" -gt 0 ] && on_fail "couldn't get user_id (user_id empty)" "${last_err}"
|
||||||
}
|
|
||||||
unset user_response
|
unset user_response
|
||||||
sed 's/\"//g' <<< "${parsed_user_response}" >> "${CFG_DIR}/userlist.txt"
|
sed 's/\"//g' <<< "${parsed_user_response}" >> "${CFG_DIR}/userlist.txt"
|
||||||
unset parsed_user_response
|
unset parsed_user_response
|
||||||
|
@ -64,11 +97,67 @@ access_token="$(grep -o "access_token\":\"[a-zA-Z0-9]\+" "${CFG_DIR}/token.json"
|
||||||
user_id="$(grep "${login}" "${CFG_DIR}/userlist.txt" | awk -F ":|," '{print $2}')"
|
user_id="$(grep "${login}" "${CFG_DIR}/userlist.txt" | awk -F ":|," '{print $2}')"
|
||||||
|
|
||||||
# save json with first 20 videos tied to the user id we just got
|
# save json with first 20 videos tied to the user id we just got
|
||||||
curl -s -G -X GET "https://api.twitch.tv/helix/videos" -d "type=archive" -d "user_id=${user_id}" -H "Authorization: Bearer ${access_token}" -H "client-id: ${client_id}"\
|
vodlist="$(curl -s -G -X GET "https://api.twitch.tv/helix/videos" -d "type=archive" -d "user_id=${user_id}" -H "Authorization: Bearer ${access_token}" -H "client-id: ${client_id}")"
|
||||||
> "${CFG_DIR}/streamarchives.json"
|
last_err="${?}"
|
||||||
sed -i 's/^{"data":\[\|}],"pagination":{"cursor":"[a-zA-Z0-9]\+"}}$//g' "${CFG_DIR}/streamarchives.json"
|
unset client_secret client_id
|
||||||
unset client_secret client_id user_id last_err
|
[ "${last_err}" -gt 0 ] && on_fail "couldn't get VOD list (curl error)" "${last_err}"
|
||||||
|
parsed_vodlist="$(sed 's/^{"data":\[\|],"pagination":{\("cursor":"[a-zA-Z0-9]\+"\)\?}}$//g' <<< "${vodlist}")"
|
||||||
|
unset vodlist
|
||||||
|
[ -z "${parsed_vodlist}" ] && on_fail "vodlist empty (no VODs found for ${login})"
|
||||||
|
printf "%s" "${parsed_vodlist}" > "${CFG_DIR}/streamarchives.json"
|
||||||
|
unset parsed_vodlist
|
||||||
|
|
||||||
# TODO:
|
unset user_id last_err vodlist parsed_vodlist
|
||||||
# - read title, duration and url of last 20 VODS and present them to user
|
|
||||||
# - get a choice from user and save the url of that selection to the clipboard
|
utf-16-surrogate-pair-decode() {
|
||||||
|
# shamelessly stolen from stackoverflow
|
||||||
|
local out="$1"
|
||||||
|
local remain=""
|
||||||
|
local regexp='(.*)\\u[dD]([0-9a-fA-F]{3})\\u[dD]([0-9a-fA-F]{3})(.*)'
|
||||||
|
while [[ "${out}" =~ "${regexp}" ]] ; do
|
||||||
|
# match 2 \udxxx hex values, calculate new U, then split and replace
|
||||||
|
local W1="$(( ( 0xd${BASH_REMATCH[2]} & 0x3ff) <<10 ))"
|
||||||
|
local W2="$(( 0xd${BASH_REMATCH[3]} & 0x3ff ))"
|
||||||
|
U="$(( ( W1 | W2 ) + 0x10000 ))"
|
||||||
|
remain="$(printf '\\U%8.8x' "${U}")${BASH_REMATCH[4]}${remain}"
|
||||||
|
out="${BASH_REMATCH[1]}"
|
||||||
|
done
|
||||||
|
printf "%s%s\n" "${out}" "${remain}"
|
||||||
|
}
|
||||||
|
|
||||||
|
printf "VODs of ${login}\n"
|
||||||
|
|
||||||
|
declare -a titles
|
||||||
|
declare -a duration
|
||||||
|
declare -a urls
|
||||||
|
|
||||||
|
declare -i j=0
|
||||||
|
while IFS= read -r i; do
|
||||||
|
titles[${j}]="$(utf-16-surrogate-pair-decode "${i:9:-2}")"
|
||||||
|
j+=1
|
||||||
|
done < <(grep -o '"title":"\(\\"\|[^"]*\)*",' "${CFG_DIR}/streamarchives.json")
|
||||||
|
|
||||||
|
j=0
|
||||||
|
while IFS= read -r i; do
|
||||||
|
duration[${j}]="${i:11:-1}"
|
||||||
|
j+=1
|
||||||
|
done < <(grep -o "\"duration\":\"[a-z0-9]\+\"" "${CFG_DIR}/streamarchives.json")
|
||||||
|
|
||||||
|
j=0
|
||||||
|
while IFS= read -r i; do
|
||||||
|
urls[${j}]="${i:7:-1}"
|
||||||
|
j+=1
|
||||||
|
done < <(grep -o "\"url\":\"https://www\.twitch\.tv/videos/[0-9]\+\"" "${CFG_DIR}/streamarchives.json")
|
||||||
|
unset j
|
||||||
|
|
||||||
|
for i in {0..19}; do
|
||||||
|
printf "%s:\t%s %s\n" "$((${i}+1))" "${titles[${i}]}" "${duration[${i}]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
declare -i retries
|
||||||
|
while :; do
|
||||||
|
read -p "choose a video from the list (type 1-20) >" choice
|
||||||
|
grep "[0-9]\{1,2\}" <<< "${choice}" && [ "${choice}" -ge 0 ] && [ "${choice}" -le 20 ] && break
|
||||||
|
printf "%s is not a number from 1-20\n" "${choice}"
|
||||||
|
done
|
||||||
|
printf "%s\n" "${urls[$((${choice}-1))]}" | xclip -selection clipboard
|
||||||
|
|
Loading…
Reference in New Issue