PHPライブラリは誰かの「twitter2mixivoice.php」もあったけど、
(1) PEAR依存 (2) 自前だと修正・拡張ができる
なんで、ライブラリも自前で。
■問題点 (1) mixiボイスのAPIがない →よって、無理矢理ログインしてHTMLパース以外方法なし
(2) クロスドメイン制限 →swfで直接通信が理想なんだけど、mixiもtwitterもクロスドメイン制限があるので断念 サーバかまして処理する事に
■主なポイント (1) AMF通信 →高速かつFlexとオブジェクトの親和性が高いAMFを採用 JSON、XML変換できるけど、今は必要なし てか、XMLって遅いし面倒だし通信においてメリットあるのか?といつも疑問に思う。
(2) データのマージ twitterはJSON、mixiはテキスト取得して日付ソートしながらデータマージ (超暫定で最低限のタイトルと日付だけ)
とりあえずデータ取得&マージまで作ったので、あとはマルチ投稿の仕様考える。 ある程度まとったら機能毎にクラス化へ。
途中までのソース うーん、デザイン的にコードは別途コンポーネント作った方がいいなw swf側ソースは、色々ネタが多いので別途記事にする予定(?)
■VoiceService.php
require_once 'Service.php';
class VoiceService extends Service {
/**
* データ取得
**/
public function getVoices() {
$voices['mixi'] = $this->mixi_voices();
$voices['twitter'] = $this->twitter_user_timeline();
$results = $this->_marge_voices($voices);
return $results;
}
/**
* Twitterタイムライン取得
**/
private function twitter_user_timeline()
{
$this->_twitter_auth();
$url = "http://twitter.com/statuses/user_timeline/{$this->twitter_user_name}.json";
$url.= "?since=".urlencode(date('D, d M Y G:i:s GMT', strtotime('-10 day')));
$results = $this->_twitter_request($url);
return $results;
}
/**
* Twitter投稿
**/
private function post_twitter()
{
if ($_POST['message']) {
$this->_twitter_auth();
$message = rawurlencode($_POST['message']);
$url = "http://twitter.com/statuses/update.json";
$posts = "status={$message}";
$results = $this->_twitter_request($url, $posts);
return $results;
}
}
/**
* mixiボイス取得
**/
private function mixi_voices()
{
$this->_mixi_login();
$url = 'http://mixi.jp/list_echo.pl';
$headers[] = "Cookie: {$this->cookie}";
$html = $this->_mixi_request($url, $headers, 'POST');
$results = $this->_parse_mixi_voice($html);
return json_encode($results);
}
/**
* mixiボイス投稿
**/
private function post_mixi_voice()
{
$this->_mixi_login();
$url = 'http://mixi.jp/list_echo.pl';
$headers[] = "Cookie: {$this->cookie}";
$html = $this->_mixi_request($url, $headers, 'GET');
$post_key = $this->_get_mixi_voice_post_key($html);
$url = 'http://mixi.jp/add_echo.pl';
$body = 'てすとー'.date('Y/m/d H:i');
$posts = array(
'body' => $body,
'post_key' => $post_key,
'redirect' => 'recent_echo',
'default_value' => $body,
);
$html = $this->_mixi_request($url, $headers, 'POST', $posts);
$results = mb_convert_encoding($html, 'UTF-8', 'EUC-JP');
echo($results);
}
/**
* データ形式の統一
**/
private function _marge_voices($values)
{
if (is_array($values)) {
foreach ($values as $type => $value) {
$voices = json_decode($value);
foreach ($voices as $key => $voice) {
$time = strtotime($voice->created_at);
$sort_times['time'] = $time;
$result['type'] = $type;
$result['time'] = $time;
$result['created_at'] = date('Y-m-d H:i:s', $time);
$result['text'] = $voice->text;
$results[] = $result;
}
}
}
if (is_array($result)) {
array_multisort($sort_times, SORT_DESC, $results);
json_encode($results);
return $results; }
}
/**
* twitter認証設定
**/
private function _twitter_auth()
{
$this->twitter_user_name = TWITTER_USER_NAME;
$this->twitter_email = TWITTER_EMAIL;
$this->twitter_password = TWITTER_PASS;
}
/**
* mixi認証設定
**/
private function _mixi_auth()
{
$this->mixi_id = MIXI_ID;
$this->mixi_email = MIXI_EMAIL;
$this->mixi_password = MIXI_PASS;
}
/**
* mixiログイン処理
**/
private function _mixi_login()
{
$this->_mixi_auth();
$posts = array(
'email' => $this->mixi_email,
'password' => $this->mixi_password,
'next_url' => 'http://mixi.jp/home.pl'
);
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
$url = 'http://mixi.jp/login.pl';
$this->_mixi_request($url, $headers, 'POST', $posts);
}
/**
* mixiボイスpost_key取得
**/
private function _get_mixi_voice_post_key($html)
{
if ($html) {
$html = mb_convert_encoding($html, 'UTF-8', 'EUC-JP');
}
$rows = explode("\n", $html);
if (is_array($rows)) {
foreach ($rows as $key => $row) {
$pattern = '|]+>(.*)]+>|U';
preg_match("{$pattern}", $row, $values);
preg_match('/post_key=(.+)&/', $row, $params);
if ($params) {
$post_key = $params[1];
if ($post_key) {
return $post_key;
}
}
}
}
}
/**
* mixiボイスパース
**/
private function _parse_mixi_voice($html)
{
if ($html) {
$html = mb_convert_encoding($html, 'UTF-8', 'EUC-JP');
}
$rows = explode("\n", $html);
if (is_array($rows)) {
foreach ($rows as $key => $row) {
$pattern = '|]+>(.*)]+>|U';
preg_match("{$pattern}", $row, $values);
$pattern_posttime = '';
if (preg_match("{$pattern_posttime}", $values[0])) {
$voice['created_at'] = $values[1];
$voice['type'] = 'mixi';
}
$pattern_body = '';
if (preg_match("{$pattern_body}", $values[0])) {
$voice['text'] = $values[1];
$voices[] = $voice;
$voice = null;
$values = null;
}
}
}
return $voices;
}
/**
* mixi共通リクエスト
**/
private function _mixi_request($url, $headers, $method, $posts=null) {
if (is_array($posts)) {
$content = http_build_query($posts, '', '&');
$content_length = strlen($content);
$headers[] = "Content-Length: {$content_length}";
$params['http']['content'] = $content;
}
$params['http']['method'] = $method;
$params['http']['header'] = implode("\r\n", $headers);
$context = stream_context_create($params);
$contents = file_get_contents($url, false, $context);
//cookie設定
$this->_set_cokkie_for_response_header($http_response_header);
return $contents;
}
private function _set_cokkie_for_response_header($http_response_header) {
if (is_array($http_response_header)) {
foreach ($http_response_header as $r) {
if (strpos($r, 'Set-Cookie') === false) {
continue;
}
$params = explode(' ', $r);
$this->cookies[] = str_replace(';', '', $params[1]);
}
if (is_array($this->cookies)) {
$this->cookie = implode('; ', $this->cookies);
}
}
}
/**
* twitter共通リクエスト
**/
private function _twitter_request($url, $posts=null)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if ($posts) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $posts);
}
curl_setopt($ch, CURLOPT_USERPWD, "{$this->twitter_email}:{$this->twitter_password}");
$results = curl_exec($ch);
curl_close($ch);
return $results;
}
// WSSE Authentication
function _mixi_wsse_authentication_header() {
$nonce = pack('H*', sha1(md5(time().rand().posix_getpid())));
$created = date('Y-m-d\TH:i:s\Z');
$digest = base64_encode(pack('H*', sha1($nonce . $created . $this->mixi_password)));
$wsse_format = 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"';
$wsse = sprintf($wsse_format, $this->mixi_email, $digest, base64_encode($nonce), $created);
$header = "X-WSSE: {$wsse}";
return $header;
}
}