{"id":942,"date":"2010-11-20T05:16:53","date_gmt":"2010-11-20T04:16:53","guid":{"rendered":"http:\/\/blog.benny-baumann.de\/?p=942"},"modified":"2010-11-22T09:50:54","modified_gmt":"2010-11-22T08:50:54","slug":"turen-offnen","status":"publish","type":"post","link":"https:\/\/blog.benny-baumann.de\/?p=942","title":{"rendered":"T\u00fcren \u00f6ffnen"},"content":{"rendered":"<p>B\u00f6se Zungen behaupten ja immer, Twitter sei zu nix anderem gut, als der Welt mitzuteilen, welche Farbe der Output des eigenen Stoffwechsels besitzt. Nunja, das stimmt so nicht ganz. Neben der F\u00e4rbung der Stoffwechselprodukte erf\u00e4hrt man noch zahlreiche Tipps, wie man die Produktion dieser verbessern, oder die Pr\u00e4sentation globaler gestalten kann, um auch jedem zu erm\u00f6glichen, die richtige Farbe f\u00fcr seine Stoffwechselendprodukte zu finden.<\/p>\n<p>Was viele aber nicht wissen, ist, dass Twitter sogar noch mehr kann. Nein, keine Links zu niedlichem Katzencontent transportieren; das geht auch anders. Was ich meine ist: T\u00fcren \u00f6ffnen!<!--more--><\/p>\n<p>Im konkreten Fall ging es um einen kleinen Hack, um mich in die Nutzung der Twitter-API einzuarbeiten. Als Grundlage hierzu habe ich die PEAR-Klassen von PHP verwendet, die bereits ein Interface zur Twitter-API bereitstellen, aber nunja: nicht die beste Dokumentation aufweisen. Von daher gibt es hier zwei kleine Projekte von mir, die die Nutzung der API recht einfach dokumentieren. Bevor ich aber zum \u00d6ffnen von T\u00fcren komme, pr\u00e4sentiere ich: Den OfflineTweeter!<\/p>\n<p>Der OfflineTweeter entstand im Zuge meiner USA-Reise, um meine Follower auch ohne die M\u00f6glichkeit einer Internet-Verbindung \u00fcber meinen ungef\u00e4hren Aufenthaltsort und meine T\u00e4tigkeiten auf dem Laufenden zu halten. Hierzu wurden im Vorfeld eine Reihe von Nachrichten festgelegt, die sp\u00e4ter zu bestimmten Zeitpunkten automatisch gepostet wurden.<\/p>\n<p>Um mit der Twitter-API zu arbeiten ben\u00f6tigt man neben einem Account bei Twitter einen API-Schl\u00fcssel. Diesen erh\u00e4lt man, indem man sein Projekt bei Twitter registriert. Zus\u00e4tzlich ben\u00f6tigt man f\u00fcr OAuth noch einen Auth Token und das zugeh\u00f6rige Token Secret. Diese bekommt man f\u00fcr den eigenen Account direkt auf der Projekt-Seite seiner Twitter-App.<\/p>\n<p>Hat man alle ben\u00f6tigten Daten beisammen, kann man diese in einer Datei zusammenfassen. Bei mir sieht diese Datei etwa wie folgt aus:<\/p>\n<pre lang=\"php\" escaped=\"true\">&lt;?\r\n\r\n\/\/ Offline Tweeter\r\n\/\/ http:\/\/dev.twitter.com\/apps\/457571\r\n\r\n$oa_access_token = \"\";\r\n$oa_token_secret = \"\";\r\n\r\n$twAPIKey = \"\";\r\n\r\n$twConsumerKey = \"\";\r\n$twConsumerSecret = \"\";\r\n\r\n$twRequestTokenURL = \"https:\/\/api.twitter.com\/oauth\/request_token\";\r\n$twAccessTokenURL = \"https:\/\/api.twitter.com\/oauth\/access_token\";\r\n$twAuthorizeURL = \"https:\/\/api.twitter.com\/oauth\/authorize\";\r\n\r\n?&gt;<\/pre>\n<p>Wenn man diese Daten zusammengetragen hat, ben\u00f6tigt man als n\u00e4chstes noch die <a href=\"http:\/\/pear.php.net\/package\/Services_Twitter\">Twitter-Bindings f\u00fcr PHP<\/a>. Diese erh\u00e4lt man am einfachsten via <a href=\"http:\/\/pear.php.net\/\">PEAR<\/a>:<\/p>\n<pre lang=\"bash\">pear upgrade\r\npear install -a -f Service_Twitter<\/pre>\n<p>Wichtig ist hierbei zudem, dass man zwingend die Klassen f\u00fcr OAuth ben\u00f6tigt, da die Twitter-API ansonsten nur f\u00fcr die unauthentifizierten Aufrufe verwendet werden kann. Ist die Installation abgeschlossen, kann es nun losgehen:<\/p>\n<pre lang=\"php\" escaped=\"true\">&lt;?\r\n\r\nrequire_once 'Services\/Twitter.php';\r\nrequire_once 'HTTP\/OAuth\/Consumer.php';\r\n\r\nrequire_once 'twitter.OfflineTweeter.php'; \/\/Load our authentication data\r\n\r\nfunction myLog($message) {\r\n    echo sprintf(\"[%s] %s\\n\", date('d.m.Y H:i:s'), $message);\r\n}\r\n\r\n\/\/ Offline Tweeter\r\n\r\ntry {\r\n    \/\/Connect to Twitter\r\n    $twitter = new Services_Twitter();\r\n    $oauth   = new HTTP_OAuth_Consumer(\r\n        $twConsumerKey,                         \/\/ 'consumer_key',\r\n        $twConsumerSecret,                      \/\/ 'consumer_secret',\r\n        $oa_access_token,                       \/\/ 'auth_token',\r\n        $oa_token_secret                        \/\/ 'token_secret'\r\n        );\r\n    $twitter-&gt;setOAuth($oauth);\r\n\r\n    \/\/Define our messages\r\n    $times = array(\r\n        mktime(00,00,00,12,25,2010,0) =&gt; 'Hello World!',\r\n        );\r\n\r\n    \/\/Sort by time for convenience\r\n    ksort($times);\r\n\r\n    while(count($times)) {\r\n        $k = array_keys($times);\r\n        $k = $k[0];\r\n        if(($k &lt; time()) && (time() - $k &lt; 120)) {\r\n            myLog('Tweeting for: ' . date('d.m.Y H:i:s', $k) . ' at ' . date('d.m.Y H:i:s', time()) . ': ' . $times[$k]);\r\n            $msg = $twitter-&gt;statuses-&gt;update($times[$k]);\r\n            print_r($msg);\r\n            unset($times[$k]);\r\n        }\r\n        sleep(1);\r\n    }\r\n} catch (Services_Twitter_Exception $e) {\r\n    echo $e-&gt;getMessage().\"\\n\";\r\n}\r\n\r\n?&gt;<\/pre>\n<p>Die Funktionalit\u00e4t der Schleife ist nun recht einfach: Es wird die erste Nachricht aus dem Array gegriffen (daher das ksort, um nach dem Zeitpunkt zu sortieren) und wenn diese zu senden ist, wird sie versendet.<\/p>\n<p>Okay, somit k\u00f6nnen wir der Welt schonmal mitteilen, wie unser Stoffwechsel arbeitet. Interessanter ist aber ein praktisches Real World-Beispiel, wie ich es selbst \u00fcbrigens grad in San Francisco nutze.<\/p>\n<p>N\u00e4chste App, wieder unsere Authentifizierungsdaten in eine Datei und los geht&#8217;s:<\/p>\n<pre lang=\"php\" escaped=\"true\">&lt;?php\r\n\r\nrequire_once 'Services\/Twitter.php';\r\nrequire_once 'HTTP\/OAuth\/Consumer.php';\r\n\r\nrequire_once 'twitter.NBSesam.php';\r\n\r\n\/\/ Noisebridge Sesam\r\n\r\ntry {\r\n    $twitter = new Services_Twitter();\r\n    $oauth   = new HTTP_OAuth_Consumer(\r\n        $twConsumerKey,                         \/\/ 'consumer_key',\r\n        $twConsumerSecret,                      \/\/ 'consumer_secret',\r\n        $oa_access_token,                       \/\/ 'auth_token',\r\n        $oa_token_secret                        \/\/ 'token_secret'\r\n        );\r\n    $twitter-&gt;setOAuth($oauth);\r\n\r\n    \/\/ Read the current user's information\r\n    $acc = $twitter-&gt;account-&gt;verify_credentials();\r\n\r\n$last_dm_id = 0;\r\n\r\nwhile (1) {\r\n\r\n    \/\/ Rate limiting - IMPORTANT!\r\n    sleep(15);\r\n\r\n    \/\/ Read the recent direct messages\r\n    $dm = $twitter-&gt;direct_messages();\r\n\r\n    \/\/ Get the most recent direct message\r\n    $dmrecent = $dm[0];\r\n\r\n    \/\/Limit the local load ...\r\n    if($last_dm_id == $dmrecent-&gt;id) {\r\n        continue;\r\n    }\r\n    $last_dm_id = $dmrecent-&gt;id;\r\n\r\n    \/\/ Read sender and recipient of the most recent direct message\r\n    $dms = $dmrecent-&gt;sender;\r\n    $dmr = $dmrecent-&gt;recipient;\r\n\r\n    \/\/ Okay, was it by us for us?\r\n    if($dms-&gt;screen_name == $acc-&gt;screen_name &amp;&amp; $dmr-&gt;screen_name == $acc-&gt;screen_name) {\r\n        echo \"Let's check the text!\\n\";\r\n\r\n        \/\/Display the text!\r\n        echo $dmrecent-&gt;text.\"\\n\";\r\n\r\n        \/\/Display the id!\r\n        echo $dmrecent-&gt;id.\"\\n\";\r\n\r\n        \/\/Was it our secret message?\r\n        if(\"The magic text!\" == $dmrecent-&gt;text) {\r\n\r\n            $gate = file_get_contents($nbGateUrl);\r\n\r\n            $dmtest = $twitter-&gt;direct_messages-&gt;new($acc-&gt;screen_name, 'Sesam will open now!');\r\n            var_dump($dmtest);\r\n\r\n            $twitter-&gt;direct_messages-&gt;destroy($dmrecent-&gt;id);\r\n\r\n        }\r\n\r\n    }\r\n\r\n}    \r\n\r\n} catch (Services_Twitter_Exception $e) {\r\n    echo $e-&gt;getMessage().\"\\n\";\r\n}\r\n\r\n?&gt;<\/pre>\n<p>Und fertig sind wir. 36 LOC und unser T\u00fcr\u00f6ffner funktioniert. Nun ist die Sache, dass dieses Skript an sich recht unn\u00fctz ist, wenn man sowieso Internet-Zugriff hat, weil man dann auch einfach den T\u00fcr\u00f6ffner-Link selbst bet\u00e4tigen k\u00f6nnte. Nun ist es aber so, dass der Hackerspace in SF so gebaut ist, dass das WiFi meist nicht verbindet und das UMTS f\u00fcr Prepaid-Vertr\u00e4ge eher ein Wunschtraum ist.<\/p>\n<p>Twitter bietet nun aber an, dass man via SMS Tweets schreiben kann, bzw. anderweitig mit Twitter interagieren kann. Und genau hier setzt das Skript an: Da ich auf meinem Prepaid-Vertrag kostenlos SMS schreiben kann, sende ich an Twitter den magischen Text als Direktnachricht an mich selbst und warte etwa 5-30 Sekunden, bis der T\u00fcr\u00f6ffner &#8211; angesto\u00dfen durch meine App &#8211; mir die T\u00fcr \u00f6ffnet.<\/p>\n<p>Viel Spa\u00df beim Arbeiten mit der API \ud83d\ude09<\/p>\n<p class=\"wp-flattr-button\"><a href=\"https:\/\/blog.benny-baumann.de\/?flattrss_redirect&amp;id=942&amp;md5=807ccd43daca11647c320a92e1cc8632\" title=\"Flattr\" target=\"_blank\"><img src=\"http:\/\/blog.benny-baumann.de\/wp-content\/plugins\/flattr\/img\/flattr-badge-large.png\" srcset=\"http:\/\/blog.benny-baumann.de\/wp-content\/plugins\/flattr\/img\/flattr-badge-large.png\" alt=\"Flattr this!\"\/><\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>B\u00f6se Zungen behaupten ja immer, Twitter sei zu nix anderem gut, als der Welt mitzuteilen, welche Farbe der Output des eigenen Stoffwechsels besitzt. Nunja, das stimmt so nicht ganz. Neben der F\u00e4rbung der Stoffwechselprodukte erf\u00e4hrt man noch zahlreiche Tipps, wie man die Produktion dieser verbessern, oder die Pr\u00e4sentation globaler gestalten kann, um auch jedem zu [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[29],"tags":[309],"class_list":["post-942","post","type-post","status-publish","format-standard","hentry","category-software","tag-twitter"],"_links":{"self":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/942","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=942"}],"version-history":[{"count":6,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/942\/revisions"}],"predecessor-version":[{"id":948,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/942\/revisions\/948"}],"wp:attachment":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=942"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=942"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=942"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}