"Twitterbox", "X-Twitter-Client-URL" => "http://ordinalmalaprop.com/twitter/", "X-Twitter-Client-Version" => "0.3")); $response = @curl_exec($c); if (chop($response)) { $json = json_decode($response, TRUE); curl_close($c); // print_r($json); return $json; } else die("Could not contact Twitter!"); } // Get the TinyURL of the first entry in an RSS feed function feedlink_get($url) { $c = curl_init(); curl_setopt($c, CURLOPT_URL, $url); curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($c, CURLOPT_HEADER, FALSE); $feed_data = curl_exec($c); curl_close($c); if (!$feed_data) die("Failed to get stream at $url"); else { // Try RSS parsing if (preg_match('/.+?\s*?(\S.+?\S)\s*?<\/link>/is', $feed_data, $matches)) { $feed_data = get_tinyurl($matches[1]); return $feed_data; } // Try Atom parsing else if (preg_match('/.+?/is', $feed_data, $matches)) { $feed_data = get_tinyurl($matches[1]); return $feed_data; } // Give up else { die("Failed to find new feed link at $url"); } } } // Get a tinyurl for something function get_tinyurl($bigurl) { $c = curl_init(); curl_setopt($c, CURLOPT_URL, "http://tinyurl.com/api-create.php?url=$bigurl"); curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($c, CURLOPT_HEADER, FALSE); $tinyurl = curl_exec($c); curl_close($c); if (!$tinyurl) die("Failed to get TinyURL"); return $tinyurl; } // Main code header("Content-type: text/plain"); // Read POST input $post = file('php://input'); // If there isn't anything in the POST, don't do anything if (!$post) { die("go away"); } // Read in the information that was sent $user = urldecode(chop($post[0])); $pass = urldecode(chop($post[1])); $action = urldecode(chop($post[2])); $status = urldecode(chop($post[3])); // location to add slurl for, in the form simname/x/y/z/ $location = urldecode(chop($post[4])); // RSS feeds to check and replace $feeds_raw = explode(",", urldecode(chop($post[5]))); $f = 0; do { $feeds[$feeds_raw[$f]] = $feeds_raw[$f+1]; $f += 2; } while ($f < sizeof($feeds_raw)); ob_flush(); flush(); // Allow for slight clock irregularities $now = time() - 5; // Now process the action requested // All of these request feedback from Twitter in JSON format, which is parsed by the above function. if ($action == "update") { if (strpos($status, "SLURL") !== FALSE && $location) { // SLurl page strips out all HTML in the msg - didn't know that... $slurl = "http://slurl.com/secondlife/". str_replace(" ", "%20", $location). "?x=200&y=120&title=". urlencode(gmdate("j M y @ H:i", time() - 28800). " SLT"). "&msg=". rawurlencode(htmlentities($status)). "&img=http%3A//ordinalmalaprop.com/twitter/twitterbox-credit.jpg"; $tiny_slurl = get_tinyurl($slurl); $status = str_replace("SLURL", $tiny_slurl, $status); } ob_flush(); flush(); // Go through each feed keyword checking to see if it occurs foreach (array_keys($feeds) as $feed_name) { // Do we have any keywords for that feed here? if (strpos($status, $feed_name) !== FALSE) { // If so, get the tinyurl for the first element there $tinyurl = feedlink_get($feeds[$feed_name]); // and replace instances of that keyword with it $status = str_replace($feed_name, $tinyurl. " ", $status); ob_flush(); flush(); } } $json = twitter_send('update', $user, $pass, "status=". rawurlencode($status)); // The update procedure // Check the time that the last update was posted at $created = strtotime($json["created_at"]); // If the time is before now, that means it's failed! if ($created < $now) { die("Failed to post!"); } // Otherwise say "ok" and coincidentally update the screen name and ID else { echo "OK,". $json["user"]["id"]. ",". $json["user"]["screen_name"]. ",posted"; } } else if ($action == "get id" && ($json = twitter_send('update', $user, $pass, ""))) { // To just update the screen name and ID, send a blank update which will not be displayed // and read in the information. echo "OK,". $json["user"]["id"]. ",". $json["user"]["screen_name"]; } else if ($action == "check" && ($json = twitter_send('friends_timeline', $user, $pass, ""))) { // Check recent tweets // Go through them and compile a list of the last few, up to an appropriate size limit to send back to LSL // 1500 bytes should work - longer than that and the header gets in the way // LSL doesn't like receiving any real quantity of data $length = 0; $entry = ""; $f = 0; $max = count($json); do { $length += strlen($entry); if ($entry != "") $tweets[] = $entry; // Format for each tweet: // // // // NB Twitter used to provide "relative_created_at", but now doesn't, so we // use absolute time instead $unixtime = strtotime($json[$f]["created_at"]); $entry = $json[$f]["user"]["screen_name"]. "\n". $json[$f]["text"]. " (". date("j M H:i", $unixtime). " SLT)\n$unixtime"; ob_flush(); flush(); } while (++$f < $max && $length + strlen($entry) < 1500); // Put them in chronological order $tweets = array_reverse($tweets); // and output echo "OK\n". implode("\n", $tweets); } else echo "pardon?"; ?>