diff --git a/access.go b/access.go index 23bb2e4..0b33c50 100644 --- a/access.go +++ b/access.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "net/url" ) type accessToken struct { @@ -13,7 +14,18 @@ type accessToken struct { } func getAcessToken(c *http.Client, username string) (*accessToken, error) { - req, err := http.NewRequest("GET", fmt.Sprintf(accessURL, username), nil) + aURL, err := url.Parse(fmt.Sprintf(accessURL, username)) + if err != nil { + return nil, err + } + + query := aURL.Query() + + query.Set("player_type", "embed") + + aURL.RawQuery = query.Encode() + + req, err := http.NewRequest("GET", aURL.String(), nil) if err != nil { return nil, err } diff --git a/access_test.go b/access_test.go index e10a58a..f16279e 100644 --- a/access_test.go +++ b/access_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io/ioutil" "net/http" + "net/url" "testing" ) @@ -17,7 +18,14 @@ func TestGetAccessToken(t *testing.T) { } client := NewTestClient(func(req *http.Request) *http.Response { - equals(t, fmt.Sprintf(accessURL, testUsername), req.URL.String()) + aURL, err := url.Parse(fmt.Sprintf(accessURL, testUsername)) + ok(t, err) + + query := aURL.Query() + query.Set("player_type", "embed") + aURL.RawQuery = query.Encode() + + equals(t, aURL.String(), req.URL.String()) equals(t, clientID, req.Header.Get("Client-ID")) var jsonBuf bytes.Buffer ok(t, json.NewEncoder(&jsonBuf).Encode(token)) diff --git a/main.go b/main.go index e75b545..eeafd28 100644 --- a/main.go +++ b/main.go @@ -157,6 +157,8 @@ func main() { os.Exit(1) } + username = strings.ToLower(username) + if terminal.IsTerminal(int(os.Stdout.Fd())) && !forceOutput && !externalCommand && !groupList { stdErr.Println("[WARNING] You have not piped the output anywhere.") stdErr.Println(" Outputting binary data to a terminal can be dangerous.") diff --git a/tools/record.sh b/tools/record.sh index 2288f7d..c0388cb 100644 --- a/tools/record.sh +++ b/tools/record.sh @@ -2,17 +2,31 @@ DEPS=("websocat" "curl" "jq" "cut" "twitchpipe") -API_URL="https://api.twitch.tv/kraken/channels/" +API_URL="https://gql.twitch.tv/gql" WEBSOCKET_URL="wss://pubsub-edge.twitch.tv/v1" -CLIENT_ID="jzkbprff40iqj646a697cyrvl0zt2m6" +CLIENT_ID="kimne78kx3ncx6brgo4mv6wki5h1ko" PRINT_FILENAME=0 +<<<<<<< HEAD GROUP="chunked" +======= +FILENAME_TITLE=0 +FILENAME_DATE=0 +>>>>>>> bc71d4092b66110c59c3a0e13b444a664dca2d61 errf(){ >&2 printf "$@"; } -get_id () { - curl --silent --fail -H "Client-ID: $CLIENT_ID" "$API_URL$1" | jq -r ._id +get_ids () { + USERNAMES="$(printf "%s\n" "${@}")" + USERNAMES_ARRAY="$(jq -R . <<< "${USERNAMES}" | jq -s -c .)" + QUERY_STRING="$(printf "{users(logins:%s){id}}" "${USERNAMES_ARRAY}")" + DATA="$(jq -c -R '{"query":.}' <<< "${QUERY_STRING}")" + IDS="$(curl --silent --fail -H "Client-ID: ${CLIENT_ID}" "${API_URL}" --data-raw "${DATA}" | jq -r ".data.users[].id | .//-1")" + echo -n "${IDS}" +} + +get_stream_title () { + curl --silent --fail -H "Client-ID: $CLIENT_ID" "$API_URL$1" | jq -r .status } print_usage() { @@ -43,7 +57,11 @@ invalid_input() { check_deps +<<<<<<< HEAD while getopts ":phg:" opt +======= +while getopts "d:pht" opt +>>>>>>> bc71d4092b66110c59c3a0e13b444a664dca2d61 do case "$opt" in p ) @@ -53,8 +71,18 @@ do print_usage exit 0 ;; +<<<<<<< HEAD g ) GROUP="$OPTARG" +======= + t ) + FILENAME_TITLE=1 + ;; + d ) + FILENAME_DATE=1 + DFORMAT="+""$OPTARG" + #OPTIND=`echo $OPTIND + 1 | bc` +>>>>>>> bc71d4092b66110c59c3a0e13b444a664dca2d61 ;; \? ) invalid_input "$(printf $'unknown option \'-%s\'' "$OPTARG")" @@ -64,23 +92,28 @@ done shift $((OPTIND -1)) -if [ "$#" -lt 1 ]; then - invalid_input 'no username(s) supplied' +USERNAMES=("${@,,}") + +if [ "${#USERNAMES[@]}" -lt 1 ]; then + invalid_input 'no username(s) supplied' fi errf 'fetching user IDs...\n' +IDS="$(get_ids "${USERNAMES[@]}" | tr -d '\r')" declare -A id_username -for username in "$@" +i=0 +while read -r ID do - id=$(get_id $username) - if [ "$id" == "" ]; + USERNAME="${USERNAMES[${i}]}" + if [[ "${ID}" -eq "-1" ]] then - errf $'ERROR! could not get ID for \'%s\'' "$username" + errf 'ERROR! could not get ID for "%s"' "$USERNAME" exit 1 fi - id_username[$id]=$username -done + id_username["${ID}"]="${USERNAME}" + ((i++)) +done <<< "${IDS}" ( trap exit SIGINT SIGTERM @@ -118,11 +151,27 @@ done then ( username=${id_username[$id]} + errf '[%s] stream started\a\n' "$username" while : do mkdir -p "$username" - filename=$(printf "%s/%s.ts" $username "$(date -u '+%Y_%m_%d_%H_%M_%S_(%Z)')") + + filename="$username/" + + if [ "$FILENAME_TITLE" == "1" ]; + then + title=$(get_stream_title $username) + filename+="${title}_" + fi + if [ "$FILENAME_DATE" == "1" ]; + then + filename+=$(date $DFORMAT) + else + filename+=$(date -u '+%Y-%m-%d-%H-%M-%S-(%Z)') + fi + filename+=".ts" + errf '[%s] recording to %s\n' "$username" "$filename" (twitchpipe --archive --group "$GROUP" "$username" >> "$filename") 2>&1 | ( while read -r line; @@ -154,4 +203,4 @@ done ;; esac done -) \ No newline at end of file +) diff --git a/urls.go b/urls.go index f297b6b..8c6f08a 100644 --- a/urls.go +++ b/urls.go @@ -21,6 +21,8 @@ func getURLs(c *http.Client, playlist string) ([]string, error) { return nil, err } + req.Header.Set("Origin", "https://player.twitch.tv") + res, err := c.Do(req) if err != nil { return nil, err