I discovered a bunch of bugs. This is still buggy, but less so.
#!/bin/zsh
zmodload -i zsh/net/tcp || exit 245 zmodload -i zsh/zselect || exit 246 zmodload -i zsh/datetime || exit 247 setopt extendedglob autoload -U tcp_open TCP_SILENT=yes TCP_PROMPT= audioscrobbler_handshake() { local username="$1" local -a http_headers local -a response local xferencoding tcp_open post.audioscrobbler.com 80 scrobbler tcp_send -s scrobbler -- "GET /?hs=true&p=1.1&c=tst&v=1.0&u=${username} HTTP/1.1" tcp_send -s scrobbler -- "Host: post.audioscrobbler.com" tcp_send -s scrobbler -- "" sleep 1 tcp_read -d -s scrobbler tcp_close -s scrobbler if [[ $tcp_lines[1] != "HTTP/1.1 200 OK " ]]; then return 1 fi http_headers=(${tcp_lines[1,(r) ]}) xferencoding="${${http_headers[(r)Transfer-Encoding:*]}#Transfer-Encoding: }" #the following case statement is broken somehow case "$xferencoding" in (chunked*) response=(${tcp_lines[$tcp_lines[(i) ]+1,(r)0]}) ;; (*) response=(${tcp_lines[(r) ,-1]}) ;; esac local rstatus=${response[2]} case "$rstatus" in (UPTODATE|UPDATE *) challenge="${response[3]/ (#e)/}" submiturl="$response[4]" interval="$response[5]" ;; (FAILED *|BADUSER) interval="$response[3]" print $rstatus return 1 ;; (*) print $rstatus what the fuck print '[[[' print -l ${http_headers} print ']]]' print '{{{' print -l ${response} print '}}}' return 1 ;; esac } audioscrobbler_urlencode() { setopt localoptions extendedglob input=( ${(s::)1} ) print ${(j::)input/(#b)([^A-Za-z0-9_.!~*\'\(\)-])/%$(([##16]#match))} } audioscrobbler_submit() { local username=$(audioscrobbler_urlencode "$1") local password=$(audioscrobbler_urlencode "$2") local artist=$(audioscrobbler_urlencode "$3") local track=$(audioscrobbler_urlencode "$4") local album=$(audioscrobbler_urlencode "$5") local mbid="$6" length="$7" ttime="$8" local cr="$(print -n "${password}" | md5sum | awk '{print $1}')${challenge}" local challengeresponse="$(print -n "${cr}" | md5sum | awk '{print $1}')" tcp_open $submithost $submitport scrobmit tcp_send -s scrobmit -- "GET /${submitcgi}?u=${username}&s=${challengeresponse}&a[0]=${artist}&t[0]=${track}&b[0]=${album}&m[0]=${mbid}&l[0]=${length}&i[0]=${ttime}" tcp_send -s scrobmit -- "" print -r "GET /${submitcgi}?u=${username}&s=${challengeresponse}&a[0]=${artist}&t[0]=${track}&b[0]=${album}&m[0]=${mbid}&l[0]=${length}&i[0]=${ttime}" sleep 2 tcp_read -d -s scrobmit tcp_close -s scrobmit print -l ${tcp_lines} } parse_submiturl() { if [[ "$submiturl" == http://(#b)(*):(*)/(*) ]]; then submithost=$match[1] submitport=$match[2] submitcgi=$match[3] else submithost=post.audioscrobbler.com submitport=80 submitcgi=/protocol_1.1 fi } LASTFM_USER=TestUser LASTFM_PASSWORD=testpassword audioscrobbler_handshake $LASTFM_USER || exit 1 parse_submiturl sleep 5 #tstamp=$(TZ=UTC strftime "%Y-%m-%d %H:%M:%S" ${EPOCHSECONDS}) tstamp=$(date -u +"%Y-%m-%d %H:%M:%S") #audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "Caetano Veloso" "Cucurrucucu Paloma" "Divina Estampa" "" "230" "${tstamp// /%20}" #audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "The Superjesus" "Gravity" "Jet Age" "6c6f24ed-f742-42b7-8d18-5c255100ac47" "239" $(audioscrobbler_urlencode "2005-11-17 22:45:42") #audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "Regurgitator" "Black Bugs" "Black Bugs" "0fb17a20-bdd5-43e2-b822-fd0b6253546d" "182" $(audioscrobbler_urlencode "2005-11-18 00:21:02") #audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "Warren Zevon" "Veracruz" "Excitable Boy" "e41b751b-f2a7-4c32-bbeb-a7fa79496460" "212" $(audioscrobbler_urlencode "$tstamp") #audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "Flaming Lips" "Pilot Can at the Queer of God" "Transmissions from the Satellite Heart" "1f04b225-6be6-42e3-a827-d0b5609709e2" "257" $(audioscrobbler_urlencode "$tstamp") #audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "The Whitlams" "Blow Up The Pokies" "Love This City" "27447aa3-2978-4ba3-908d-afc79b9b0f35" "207" $(audioscrobbler_urlencode "$tstamp") #audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "Powderfinger" "My Happiness" "My Happiness" "fc2dc965-9c9e-4a59-9b08-534f18412f75" "279" $(audioscrobbler_urlencode "$tstamp") #audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "Bob Marley & The Wailers" "Is This Love" "Kaya" "0217f60a-b2aa-42ca-8720-15978416e8b2" "232" $(audioscrobbler_urlencode "$tstamp") audioscrobbler_submit $LASTFM_USER $LASTFM_PASSWORD "The Decemberists" "The Engine Driver" "Picaresque" "fc1ee1d4-8b3b-436b-b9ff-cb6cc21bd1ef" "255" $(audioscrobbler_urlencode "$tstamp")