Gestern Abend wurde während Bohn Jour endlich die offizielle Rocket Beans TV App - Pocket Beans - vorgestellt und damit auch endlich ein offizieller, maschinenlesbarer Sendeplan! Woohoo!

Leider sind die APIs (Ja, es gibt mehrere) nicht so ganz öffentlich. Die eigentliche API scheint auf api.rocketmgmt.de zu liegen. Außerdem exististieren mindestens zwei Wrapper auf einer Domain der Appentwickler (refreshbutton.net), über welche Dinge wie der Sendeplan, eine Liste der Sendungen und - am wenigsten spannend - einem scheinbar bei jedem User-Request neu geparsten JSON-Äquivalent zum offiziellen RSS Feed zu finden sind (Reddit).

Spannender ist aber die andere API. Über sie erhält man sowohl den Sendeplan, Sendungen, etc., als auch den Podcast und die Möglichkeit zu Voten. Außerdem ist sie bloß mit WSSE-Authentication verfügbar - Was sie sowieso interessanter macht. Schaut man sich in der App ein wenig um, findet man neben den bereits angegebenen Adressen auch mehrere Endpunkte auf api.rocketmgmt.de: /podcast, /shows, …

Um auf diese zuzugreifen, braucht es den (bei allen Clients gleichen) Username und ein personalisiertes PasswordDigest. Ersteres steht direkt im String, letzteres besteht aus einem SHA1-Hash der Android ID, einem Zeitstempel (YYYY-MM-DDTHH:mm:ssZ), einem zufälligen String und Salt. Username und PasswordDigest werde ich hier nicht veröffentlichen, allerdings ist beides relativ leicht auffindbar.

WSSE-Authentication funktioniert über Daten im Header. Dieser muss mindestens um

'Authorization': 'WSSE profile="UsernameToken"'
'X-WSSE': 'UsernameToken Username="...", PasswordDigest="...", Nonce="...", Created="..."'

erweitert werden, wobei Username und PasswordDigest Base64-Kodiert werden.

Nonce besteht aus der Android ID, dem Zeitstempel und dem Random-String, das PasswordDigest aus SHA1 von Nonce, erneut dem Zeitstempel und dem Salt:

var user    = '';
var salt    = '';
var id      = '00000000-0000-0000-0000-000000000000';
var created = moment().format("YYYY-MM-DDTHH:mm:ss") + '+0200'.trim();
var nonce   = id + created + rand(10).trim();
var sha1    = sha1h(nonce + created + salt);

An dieser Stelle kann man ganz bequem ein sehr kurzes Script schreiben, das alle geforderten Informationen generiert. Beispielsweise in Node.js:

bake@kreis ~/Desktop> node rbapi.js | jq '.'
{
    "podcasts": [
        {
            "title": "BeansCast #1",
            "description": "Schön dass ihr euch unsere App zugelegt habt! Als erstes exklusives Item präsentieren wir euch den BeansCast. Johannes wird euch ab sofort einmal pro Woche mit einem spannenden Gespräch zu aktuellen Themen versorgen, in dem immer wieder neue Gäste zu Wort kommen werden. In der ersten Ausgabe holt er mit Colin ganz weit aus uns spricht über die Entwicklung von Rocket Beans TV vom Start bis heute, über die Highlights der diesjährigen E3 und über so einiges mehr. Viel Freude beim Zuhören!",
            "length": "4680",
            "url": "http://cdn.rocketmgmt.de/mp3/beanscast/beanscast_e01.mp3",
            "filesize": "113"
        }
    ]
}

Anmerkung: Der aus refreshbutton.net verfügbare Teil der API kann sicherlich als öffentlich angesehen werden - immerhin ist er nur lesbar und über ihn läuft unverschlüsselter und ungesicherter Traffic. Bei api.rocketmgmt.de hingegen haben sich die Entwickler immerhin etwas Mühe gegeben, sie nicht der breiten Masse zugänglich zu machen. Weshalb auch immer. Der Post ist bloß Spielerei und fordert nicht dazu auf was-auch-immer mit mit der API anzustellen. Falls RBTV den Post nicht möchte, schreibt mir bitte auf Twitter.

Update 1: Kurz nach dem Post erschien ein Thread mit dem Selben Thema im Subreddit.

Update 2: Auf GitHub liegt eine kleine Sendeplan-App.

Update 3: Das ganze ist wohl endlich an der Stelle angelangt, an die es immer gehörte: Vor dem Grafischen Sendeplan. Außerdem hat die App nun einen eigenen Thread im RB-Subreddit.

Update 4: Seit Gestern gibt es eine Brew-Cask-Formel: $ brew cask install yarbs.