mirror of
https://github.com/thorsten-gehrig/alexa-remote-control.git
synced 2024-12-11 18:05:32 +01:00
Fixed TuneIn support
This commit is contained in:
parent
a7b2ff3755
commit
d267c30fef
@ -22,9 +22,7 @@ DEVICEVOLNAME - a list of device names with specific volume settings (space se
|
|||||||
DEVICEVOLSPEAK - a list of speak volume levels - matching the devices above
|
DEVICEVOLSPEAK - a list of speak volume levels - matching the devices above
|
||||||
DEVICEVOLNORMAL - a list of normal volume levels- matching the devices above
|
DEVICEVOLNORMAL - a list of normal volume levels- matching the devices above
|
||||||
(current playing volume takes precedence for normal volume)
|
(current playing volume takes precedence for normal volume)
|
||||||
USE_ANNOUNCEMENT_FOR_SPEAK - Announcements can be made to multiple devices, while
|
|
||||||
regular SPEAK cannot but the announcement feature has
|
|
||||||
to be turned on for those devices. Also supports SSML!
|
|
||||||
```
|
```
|
||||||
You will very likely want to set the language to:
|
You will very likely want to set the language to:
|
||||||
```
|
```
|
||||||
@ -41,9 +39,11 @@ alexa-remote-control [-d <device>|ALL] -e <pause|play|next|prev|fwd|rwd|shuffle|
|
|||||||
-e : run command, additional SEQUENCECMDs:
|
-e : run command, additional SEQUENCECMDs:
|
||||||
weather,traffic,flashbriefing,goodmorning,singasong,tellstory,
|
weather,traffic,flashbriefing,goodmorning,singasong,tellstory,
|
||||||
speak:'<text/ssml>',automation:'<routine name>',sound:<soundeffect_name>,
|
speak:'<text/ssml>',automation:'<routine name>',sound:<soundeffect_name>,
|
||||||
textcommand:'<anything you would otherwise say to Alexa>'
|
textcommand:'<anything you would otherwise say to Alexa>',
|
||||||
|
playmusic:<channel e.g. TUNEIN, AMAZON_MUSIC>:'<music name>'
|
||||||
|
|
||||||
-b : connect/disconnect/list bluetooth device
|
-b : connect/disconnect/list bluetooth device
|
||||||
|
-c : list 'playmusic' channels
|
||||||
-q : query queue
|
-q : query queue
|
||||||
-n : query notifications
|
-n : query notifications
|
||||||
-r : play tunein radio
|
-r : play tunein radio
|
||||||
|
@ -67,6 +67,9 @@
|
|||||||
# (thanks to Ingo Fischer)
|
# (thanks to Ingo Fischer)
|
||||||
# 2021-05-27: v0.18 complete rework of sequence commands especially for TTS
|
# 2021-05-27: v0.18 complete rework of sequence commands especially for TTS
|
||||||
# Announcement feature is no longer required due to inconsistent SSML handling
|
# Announcement feature is no longer required due to inconsistent SSML handling
|
||||||
|
# 2021-09-02: v0.19 Playing TuneIn works again using new entertainment API endpoint
|
||||||
|
# Added playmusic (Alexa.Music.PlaySearchPhrase) as command, for available channels use "-c"
|
||||||
|
# Note: playmusic is not multi-room capable, doing so might lead to unexpected results
|
||||||
#
|
#
|
||||||
###
|
###
|
||||||
#
|
#
|
||||||
@ -74,6 +77,7 @@
|
|||||||
# - requires cURL for web communication
|
# - requires cURL for web communication
|
||||||
# - (GNU) sed and awk for extraction
|
# - (GNU) sed and awk for extraction
|
||||||
# - jq as command line JSON parser (optional for the fancy bits)
|
# - jq as command line JSON parser (optional for the fancy bits)
|
||||||
|
# - base64 for B64 encoding (make sure "-w 0" option is available on your platform)
|
||||||
# - oathtool as OATH one-time password tool (optional for two-factor authentication)
|
# - oathtool as OATH one-time password tool (optional for two-factor authentication)
|
||||||
#
|
#
|
||||||
##########################################
|
##########################################
|
||||||
@ -167,7 +171,10 @@ TTS=""
|
|||||||
UTTERANCE=""
|
UTTERANCE=""
|
||||||
SEQUENCECMD=""
|
SEQUENCECMD=""
|
||||||
SEQUENCEVAL=""
|
SEQUENCEVAL=""
|
||||||
|
SEARCHPHRASE=""
|
||||||
|
PROVIDERID=""
|
||||||
STATIONID=""
|
STATIONID=""
|
||||||
|
CHANNEL=""
|
||||||
QUEUE=""
|
QUEUE=""
|
||||||
SONG=""
|
SONG=""
|
||||||
ALBUM=""
|
ALBUM=""
|
||||||
@ -188,15 +195,17 @@ NOTIFICATIONS=""
|
|||||||
usage()
|
usage()
|
||||||
{
|
{
|
||||||
echo "$0 [-d <device>|ALL] -e <pause|play|next|prev|fwd|rwd|shuffle|repeat|vol:<0-100>> |"
|
echo "$0 [-d <device>|ALL] -e <pause|play|next|prev|fwd|rwd|shuffle|repeat|vol:<0-100>> |"
|
||||||
echo " -b [list|<\"AA:BB:CC:DD:EE:FF\">] | -q | -n | -r <\"station name\"|stationid> |"
|
echo " -b [list|<\"AA:BB:CC:DD:EE:FF\">] | -q | -n | -r <\"station name\"|stationId> |"
|
||||||
echo " -s <trackID|'Artist' 'Album'> | -t <ASIN> | -u <seedID> | -v <queueID> | -w <playlistId> |"
|
echo " -s <trackID|'Artist' 'Album'> | -t <ASIN> | -u <seedID> | -v <queueID> | -w <playlistId> |"
|
||||||
echo " -i | -p | -P | -S | -a | -m <multiroom_device> [device_1 .. device_X] | -lastalexa | -lastcommand | -z | -l | -h"
|
echo " -i | -p | -P | -S | -a | -m <multiroom_device> [device_1 .. device_X] | -lastalexa | -lastcommand | -z | -l | -h"
|
||||||
echo
|
echo
|
||||||
echo " -e : run command, additional SEQUENCECMDs:"
|
echo " -e : run command, additional SEQUENCECMDs:"
|
||||||
echo " weather,traffic,flashbriefing,goodmorning,singasong,tellstory,"
|
echo " weather,traffic,flashbriefing,goodmorning,singasong,tellstory,"
|
||||||
echo " speak:'<text/ssml>',automation:'<routine name>',sound:<soundeffect_name>,"
|
echo " speak:'<text/ssml>',automation:'<routine name>',sound:<soundeffect_name>,"
|
||||||
echo " textcommand:'<anything you would otherwise say to Alexa>'"
|
echo " textcommand:'<anything you would otherwise say to Alexa>',"
|
||||||
|
echo " playmusic:<channel e.g. TUNEIN, AMAZON_MUSIC>:'<music name>'"
|
||||||
echo " -b : connect/disconnect/list bluetooth device"
|
echo " -b : connect/disconnect/list bluetooth device"
|
||||||
|
echo " -c : list 'playmusic' channels"
|
||||||
echo " -q : query queue"
|
echo " -q : query queue"
|
||||||
echo " -n : query notifications"
|
echo " -n : query notifications"
|
||||||
echo " -r : play tunein radio"
|
echo " -r : play tunein radio"
|
||||||
@ -222,7 +231,7 @@ usage()
|
|||||||
while [ "$#" -gt 0 ] ; do
|
while [ "$#" -gt 0 ] ; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--version)
|
--version)
|
||||||
echo "v0.18"
|
echo "v0.19"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
-d)
|
-d)
|
||||||
@ -341,6 +350,9 @@ while [ "$#" -gt 0 ] ; do
|
|||||||
-a)
|
-a)
|
||||||
LIST="true"
|
LIST="true"
|
||||||
;;
|
;;
|
||||||
|
-c)
|
||||||
|
CHANNEL="true"
|
||||||
|
;;
|
||||||
-i)
|
-i)
|
||||||
TYPE="IMPORTED"
|
TYPE="IMPORTED"
|
||||||
;;
|
;;
|
||||||
@ -455,6 +467,13 @@ case "$COMMAND" in
|
|||||||
tellstory)
|
tellstory)
|
||||||
SEQUENCECMD='Alexa.TellStory.Play'
|
SEQUENCECMD='Alexa.TellStory.Play'
|
||||||
;;
|
;;
|
||||||
|
playmusic:*)
|
||||||
|
SEQUENCECMD='Alexa.Music.PlaySearchPhrase'
|
||||||
|
PROVIDERID=${COMMAND#*:}
|
||||||
|
PROVIDERID=${PROVIDERID%:*}
|
||||||
|
SEQUENCEVAL=',\"musicProviderId\":\"'${PROVIDERID}'\",'
|
||||||
|
SEARCHPHRASE=$(echo ${COMMAND##*:} | sed s/\"/\'/g)
|
||||||
|
;;
|
||||||
"")
|
"")
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@ -626,6 +645,26 @@ list_devices()
|
|||||||
jq -r '.devices[].accountName' ${DEVLIST}
|
jq -r '.devices[].accountName' ${DEVLIST}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# sanitize search phrase
|
||||||
|
# ARG1 - sequence command (e.g. Alexa.Music.PlaySearchPhrase)
|
||||||
|
# ARG2 - musicProviderID ( TUNEIN, AMASON_MUSIC, CLOUDPLAYER, SPOTIFY, APPLE_MUSIC, DEEZER, I_HEART_RADIO )
|
||||||
|
# ARG3 - search phrase
|
||||||
|
#
|
||||||
|
sanitize_search()
|
||||||
|
{
|
||||||
|
if [ -n "$1" -a -n "$2" -a -n "$3" ] ; then
|
||||||
|
JSON='{"type":"'${1}'","operationPayload":"{\"locale\":\"'${TTS_LOCALE}'\",\"musicProviderId\":\"'${2}'\",\"searchPhrase\":\"'${3}'\"}"}'
|
||||||
|
else
|
||||||
|
JSON='{"type":"'${SEQUENCECMD}'","operationPayload":"{\"locale\":\"'${TTS_LOCALE}'\",\"musicProviderId\":\"'${PROVIDERID}'\",\"searchPhrase\":\"'${SEARCHPHRASE}'\"}"}'
|
||||||
|
fi
|
||||||
|
|
||||||
|
${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\
|
||||||
|
-H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\
|
||||||
|
-H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d "${JSON}" \
|
||||||
|
"https://${ALEXA}/api/behaviors/operation/validate" | jq -r '.operationPayload.sanitizedSearchPhrase'
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# build node_to_execute string
|
# build node_to_execute string
|
||||||
# ARG1 - SEQUENCECMD
|
# ARG1 - SEQUENCECMD
|
||||||
@ -684,6 +723,14 @@ if [ -n "${SEQUENCECMD}" ] ; then
|
|||||||
VOLUMEPRENODESTOEXECUTE=''
|
VOLUMEPRENODESTOEXECUTE=''
|
||||||
VOLUMEPOSTNODESTOEXECUTE=''
|
VOLUMEPOSTNODESTOEXECUTE=''
|
||||||
NODESTOEXECUTE=''
|
NODESTOEXECUTE=''
|
||||||
|
|
||||||
|
# sanitize search phrase
|
||||||
|
if [ -n "${SEARCHPHRASE}" -a -n "${PROVIDERID}" ] ; then
|
||||||
|
SEQUENCEVAL=${SEQUENCEVAL}'\"searchPhrase\":\"'${SEARCHPHRASE}'\",\"sanitizedSearchPhrase\":\"'$(sanitize_search)'\"'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# iterate over member devices if target is multiroom
|
||||||
|
# !!! this is no true multi-room - it just tries to play on every member device in parallel !!!
|
||||||
if [ "${DEVICEFAMILY}" = "WHA" ] ; then
|
if [ "${DEVICEFAMILY}" = "WHA" ] ; then
|
||||||
MEMBERDEVICESERIALS=$(jq --arg device "${DEVICE}" -r '.devices[] | select(.accountName == $device) | .clusterMembers[]' ${DEVLIST})
|
MEMBERDEVICESERIALS=$(jq --arg device "${DEVICE}" -r '.devices[] | select(.accountName == $device) | .clusterMembers[]' ${DEVLIST})
|
||||||
for DEVICESERIALNUMBER in $MEMBERDEVICESERIALS ; do
|
for DEVICESERIALNUMBER in $MEMBERDEVICESERIALS ; do
|
||||||
@ -691,7 +738,8 @@ if [ -n "${SEQUENCECMD}" ] ; then
|
|||||||
NODESTOEXECUTE=$(add_node "$(node)" "${NODESTOEXECUTE}")
|
NODESTOEXECUTE=$(add_node "$(node)" "${NODESTOEXECUTE}")
|
||||||
|
|
||||||
# add volume setting per device - the WHA volume is unrelyable
|
# add volume setting per device - the WHA volume is unrelyable
|
||||||
if [ $SPEAKVOL -gt 0 -o -n "${DEVICEVOLSPEAK}" ] ; then
|
# don't set volume if Alexa.Music.PlaySearchPhrase is used
|
||||||
|
if [ \( $SPEAKVOL -gt 0 -o -n "${DEVICEVOLSPEAK}" \) -a "${SEQUENCECMD}" != "Alexa.Music.PlaySearchPhrase" ] ; then
|
||||||
DEVICE=$(jq --arg device "${DEVICESERIALNUMBER}" -r '.devices[] | select(.serialNumber == $device) | .accountName' ${DEVLIST})
|
DEVICE=$(jq --arg device "${DEVICESERIALNUMBER}" -r '.devices[] | select(.serialNumber == $device) | .accountName' ${DEVLIST})
|
||||||
get_volumes
|
get_volumes
|
||||||
VOLUMEPRENODESTOEXECUTE=$(add_node $(node Alexa.DeviceControls.Volume ',\"value\":\"'${SVOL}'\"') ${VOLUMEPRENODESTOEXECUTE})
|
VOLUMEPRENODESTOEXECUTE=$(add_node $(node Alexa.DeviceControls.Volume ',\"value\":\"'${SVOL}'\"') ${VOLUMEPRENODESTOEXECUTE})
|
||||||
@ -705,7 +753,9 @@ if [ -n "${SEQUENCECMD}" ] ; then
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
NODESTOEXECUTE=$(add_node "$(node)" "${NODESTOEXECUTE}")
|
NODESTOEXECUTE=$(add_node "$(node)" "${NODESTOEXECUTE}")
|
||||||
if [ $SPEAKVOL -gt 0 -o -n "${DEVICEVOLSPEAK}" ] ; then
|
|
||||||
|
# don't set volume if Alexa.Music.PlaySearchPhrase is used
|
||||||
|
if [ \( $SPEAKVOL -gt 0 -o -n "${DEVICEVOLSPEAK}" \) -a "${SEQUENCECMD}" != "Alexa.Music.PlaySearchPhrase" ] ; then
|
||||||
get_volumes
|
get_volumes
|
||||||
VOLUMEPRENODESTOEXECUTE=$(add_node $(node Alexa.DeviceControls.Volume ',\"value\":\"'${SVOL}'\"') ${VOLUMEPRENODESTOEXECUTE})
|
VOLUMEPRENODESTOEXECUTE=$(add_node $(node Alexa.DeviceControls.Volume ',\"value\":\"'${SVOL}'\"') ${VOLUMEPRENODESTOEXECUTE})
|
||||||
VOLUMEPOSTNODESTOEXECUTE=$(add_node $(node Alexa.DeviceControls.Volume ',\"value\":\"'${VOL}'\"') ${VOLUMEPOSTNODESTOEXECUTE})
|
VOLUMEPOSTNODESTOEXECUTE=$(add_node $(node Alexa.DeviceControls.Volume ',\"value\":\"'${VOL}'\"') ${VOLUMEPOSTNODESTOEXECUTE})
|
||||||
@ -730,7 +780,7 @@ if [ -n "${SEQUENCECMD}" ] ; then
|
|||||||
-H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d @"${TMP}/.alexa.cmd" \
|
-H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST -d @"${TMP}/.alexa.cmd" \
|
||||||
"https://${ALEXA}/api/behaviors/preview"
|
"https://${ALEXA}/api/behaviors/preview"
|
||||||
|
|
||||||
# rm -f "${TMP}/.alexa.cmd"
|
rm -f "${TMP}/.alexa.cmd"
|
||||||
else
|
else
|
||||||
${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\
|
${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\
|
||||||
-H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\
|
-H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\
|
||||||
@ -744,10 +794,12 @@ fi
|
|||||||
#
|
#
|
||||||
play_radio()
|
play_radio()
|
||||||
{
|
{
|
||||||
${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\
|
JSON='{"contentToken":"music:'$(echo '["music/tuneIn/stationId","'${STATIONID}'"]|{"previousPageId":"TuneIn_SEARCH"}'| base64 -w 0| base64 -w 0 )'"}'
|
||||||
|
|
||||||
|
${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\
|
||||||
-H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\
|
-H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\
|
||||||
-H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST\
|
-H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X PUT -d "${JSON}" \
|
||||||
"https://${ALEXA}/api/tunein/queue-and-play?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}&guideId=${STATIONID}&contentType=station&callSign=&mediaOwnerCustomerId=${MEDIAOWNERCUSTOMERID}"
|
"https://${ALEXA}/api/entertainment/v1/player/queue?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -897,6 +949,14 @@ show_queue()
|
|||||||
"https://${ALEXA}/api/np/queue?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}" | jq '.'
|
"https://${ALEXA}/api/np/queue?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}" | jq '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_music_channels()
|
||||||
|
{
|
||||||
|
${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\
|
||||||
|
-H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\
|
||||||
|
-H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X GET \
|
||||||
|
"https://${ALEXA}/api/behaviors/entities?skillId=amzn1.ask.1p.music" | jq -r '.[] | select( .supportedProperties[] == "Alexa.Music.PlaySearchPhrase" ) | "\(.id) - \(.displayName) \(.description)"'
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# device specific SPEAKVOL/NORMALVOL (sets SVOL/VOL)
|
# device specific SPEAKVOL/NORMALVOL (sets SVOL/VOL)
|
||||||
#
|
#
|
||||||
@ -1103,7 +1163,7 @@ rm -f ${TMP}/.alexa.*.list
|
|||||||
rm -f ${TMP}/.alexa.volume.*
|
rm -f ${TMP}/.alexa.volume.*
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -z "$LASTALEXA" -a -z "$LASTCOMMAND" -a -z "$BLUETOOTH" -a -z "$LEMUR" -a -z "$PLIST" -a -z "$HIST" -a -z "$SEEDID" -a -z "$ASIN" -a -z "$PRIME" -a -z "$TYPE" -a -z "$QUEUE" -a -z "$NOTIFICATIONS" -a -z "$LIST" -a -z "$COMMAND" -a -z "$STATIONID" -a -z "$SONG" -a -z "$GETVOL" -a -n "$LOGOFF" ] ; then
|
if [ -z "$LASTALEXA" -a -z "$LASTCOMMAND" -a -z "$CHANNEL" -a -z "$BLUETOOTH" -a -z "$LEMUR" -a -z "$PLIST" -a -z "$HIST" -a -z "$SEEDID" -a -z "$ASIN" -a -z "$PRIME" -a -z "$TYPE" -a -z "$QUEUE" -a -z "$NOTIFICATIONS" -a -z "$LIST" -a -z "$COMMAND" -a -z "$STATIONID" -a -z "$SONG" -a -z "$GETVOL" -a -n "$LOGOFF" ] ; then
|
||||||
echo "only logout option present, logging off ..."
|
echo "only logout option present, logging off ..."
|
||||||
log_off
|
log_off
|
||||||
exit 0
|
exit 0
|
||||||
@ -1139,6 +1199,11 @@ if [ -n "$LOGIN" ] ; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$CHANNEL" ] ; then
|
||||||
|
get_music_channels
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$COMMAND" -o -n "$QUEUE" -o -n "$NOTIFICATIONS" -o -n "$GETVOL" ] ; then
|
if [ -n "$COMMAND" -o -n "$QUEUE" -o -n "$NOTIFICATIONS" -o -n "$GETVOL" ] ; then
|
||||||
if [ "${DEVICE}" = "ALL" ] ; then
|
if [ "${DEVICE}" = "ALL" ] ; then
|
||||||
for DEVICE in $( jq -r '.devices[] | select( ( .deviceFamily == "ECHO" or .deviceFamily == "KNIGHT" or .deviceFamily == "ROOK" or .deviceFamily == "WHA" ) and .online == true ) | .accountName' ${DEVLIST} | sed -r 's/ /%20/g') ; do
|
for DEVICE in $( jq -r '.devices[] | select( ( .deviceFamily == "ECHO" or .deviceFamily == "KNIGHT" or .deviceFamily == "ROOK" or .deviceFamily == "WHA" ) and .online == true ) | .accountName' ${DEVLIST} | sed -r 's/ /%20/g') ; do
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# alex(at)loetzimmer.de
|
# alex(at)loetzimmer.de
|
||||||
#
|
#
|
||||||
# 2021-01-28: v0.17c (for updates see http://blog.loetzimmer.de/2017/10/amazon-alexa-hort-auf-die-shell-echo.html)
|
# 2021-01-28: v0.17c (for updates see http://blog.loetzimmer.de/2017/10/amazon-alexa-hort-auf-die-shell-echo.html)
|
||||||
|
# 2021-09-02: v0.17d includes fixes for playing tunein (base64 required)
|
||||||
#
|
#
|
||||||
# !!! THIS IS THE FINAL VERSION !!!
|
# !!! THIS IS THE FINAL VERSION !!!
|
||||||
#
|
#
|
||||||
@ -15,6 +16,7 @@
|
|||||||
# (no BASHisms were used, should run with any shell)
|
# (no BASHisms were used, should run with any shell)
|
||||||
# - requires cURL for web communication
|
# - requires cURL for web communication
|
||||||
# - (GNU) sed and awk for extraction
|
# - (GNU) sed and awk for extraction
|
||||||
|
# - base64 for B64 encoding (make sure "-w 0" option is available on your platform)
|
||||||
# - oathtool as OATH one-time password tool (optional for two-factor authentication)
|
# - oathtool as OATH one-time password tool (optional for two-factor authentication)
|
||||||
#
|
#
|
||||||
##########################################
|
##########################################
|
||||||
@ -148,7 +150,7 @@ usage()
|
|||||||
while [ "$#" -gt 0 ] ; do
|
while [ "$#" -gt 0 ] ; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--version)
|
--version)
|
||||||
echo "v0.17a"
|
echo "v0.17d"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
-d)
|
-d)
|
||||||
@ -719,10 +721,12 @@ fi
|
|||||||
#
|
#
|
||||||
play_radio()
|
play_radio()
|
||||||
{
|
{
|
||||||
${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\
|
JSON='{"contentToken":"music:'$(echo '["music/tuneIn/stationId","'${STATIONID}'"]|{"previousPageId":"TuneIn_SEARCH"}'| base64 -w 0| base64 -w 0 )'"}'
|
||||||
|
|
||||||
|
${CURL} ${OPTS} -s -b ${COOKIE} -A "${BROWSER}" -H "DNT: 1" -H "Connection: keep-alive" -L\
|
||||||
-H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\
|
-H "Content-Type: application/json; charset=UTF-8" -H "Referer: https://alexa.${AMAZON}/spa/index.html" -H "Origin: https://alexa.${AMAZON}"\
|
||||||
-H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X POST\
|
-H "csrf: $(awk "\$0 ~/.${AMAZON}.*csrf[ \\s\\t]+/ {print \$7}" ${COOKIE})" -X PUT -d "${JSON}" \
|
||||||
"https://${ALEXA}/api/tunein/queue-and-play?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}&guideId=${STATIONID}&contentType=station&callSign=&mediaOwnerCustomerId=${MEDIAOWNERCUSTOMERID}"
|
"https://${ALEXA}/api/entertainment/v1/player/queue?deviceSerialNumber=${DEVICESERIALNUMBER}&deviceType=${DEVICETYPE}"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user