From 3f0f556a803743848382a316a66cd2656941bfb7 Mon Sep 17 00:00:00 2001 From: Phyks Date: Sun, 18 Jan 2015 23:35:33 +0100 Subject: [PATCH] Crosspost of status and bookmarks is working --- DiasporaAPI.php | 190 +++++++++++++++------ Main.php | 63 ++++--- Pages/Account.php | 18 +- templates/default/account/diaspora.tpl.php | 18 +- 4 files changed, 181 insertions(+), 108 deletions(-) diff --git a/DiasporaAPI.php b/DiasporaAPI.php index 3584518..b836288 100644 --- a/DiasporaAPI.php +++ b/DiasporaAPI.php @@ -6,75 +6,153 @@ namespace IdnoPlugins\KnownDiaspora { + /** + * Based on class from https://github.com/Faldrian/WP-diaspora-postwidget/blob/master/wp-diaspora-postwidget/diasphp.php -- Thanks, Faldrian! + * + * Ein fies zusammengehackter PHP-Diaspory-Client, der direkt von diesem abgeschaut ist: + * https://github.com/Javafant/diaspy/blob/master/client.py + */ + class DiasporaAPI { + function __construct($pod) { + $this->token_regex = '/content="(.*?)" name="csrf-token/'; - static $_token_regex = '#content="(.*?)"\s+name="csrf-token#'; - - - private function _curl($url, $verb="get", $postfields=array(), $headers=array()) { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - if ($verb == "post") { - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields); - } - if (!empty($headers)) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - } - curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($ch, CURLOPT_COOKIEFILE, $this->tmp_cookie_file); - curl_setopt($ch, CURLOPT_COOKIEJAR, $this->tmp_cookie_file); - $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $content = curl_exec($ch); - curl_close($ch); - - return array('status_code' => $http_status, 'text' => $content); + $this->pod = $pod; + $this->cookiejar = tempnam(sys_get_temp_dir(), 'cookies'); } - public function __construct($pod, $username, $password) { - $this->tmp_cookie_file = tempnam(sys_get_temp_dir(), 'cookiejar'); - $this->pod = $pod; - $data = array( + function __destruct() { + unlink($this->cookiejar); + } + + function _fetch_token() { + $ch = curl_init(); + $max_redirects = 10; + + curl_setopt ($ch, CURLOPT_URL, $this->pod . "/stream"); + curl_setopt ($ch, CURLOPT_COOKIEFILE, $this->cookiejar); + curl_setopt ($ch, CURLOPT_COOKIEJAR, $this->cookiejar); + curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); + + if (ini_get('open_basedir') === '' && ini_get('safe_mode' === 'Off')) { + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_MAXREDIRS, $max_redirects); + $output = curl_exec($ch); + } else { + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); + $mr = $max_redirects; + if ($mr > 0) { + $newurl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); + + $rcurl = curl_copy_handle($ch); + curl_setopt($rcurl, CURLOPT_HEADER, true); + curl_setopt($rcurl, CURLOPT_NOBODY, true); + curl_setopt($rcurl, CURLOPT_FORBID_REUSE, false); + curl_setopt($rcurl, CURLOPT_RETURNTRANSFER, true); + do { + curl_setopt($rcurl, CURLOPT_URL, $newurl); + $header = curl_exec($rcurl); + if (curl_errno($rcurl)) { + $code = 0; + } else { + $code = curl_getinfo($rcurl, CURLINFO_HTTP_CODE); + if ($code == 301 || $code == 302) { + preg_match('/Location:(.*?)\n/', $header, $matches); + $newurl = trim(array_pop($matches)); + } else { + $code = 0; + } + } + } while ($code && --$mr); + curl_close($rcurl); + if ($mr > 0) { + curl_setopt($ch, CURLOPT_URL, $newurl); + } + } + + if($mr == 0 && $max_redirects > 0) { + $output = false; + } else { + $output = curl_exec($ch); + } + } + curl_close($ch); + + // Token holen und zurückgeben + preg_match($this->token_regex, $output, $matches); + return $matches[1]; + } + + function login($username, $password) { + $datatopost = array( 'user[username]' => $username, 'user[password]' => $password, 'authenticity_token' => $this->_fetch_token() ); - $response = $this->_curl($this->pod."/users/sign_in", "post", $data); - if ($response['status_code'] != 302) { - throw new \Exception("Invalid status code: ".$response['status_code']); + + $poststr = http_build_query($datatopost); + + // Adresse per cURL abrufen + $ch = curl_init(); + + curl_setopt ($ch, CURLOPT_URL, $this->pod . "/users/sign_in"); + curl_setopt ($ch, CURLOPT_COOKIEFILE, $this->cookiejar); + curl_setopt ($ch, CURLOPT_COOKIEJAR, $this->cookiejar); + curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, false); + curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt ($ch, CURLOPT_POST, true); + curl_setopt ($ch, CURLOPT_POSTFIELDS, $poststr); + + curl_exec ($ch); + $info = curl_getinfo($ch); + curl_close($ch); + + if($info['http_code'] != 302) { + throw new \Exception('Login error '.print_r($info, true)); } + + // Das Objekt zurückgeben, damit man Aurufe verketten kann. + return $this; } - public function __destruct() { - unlink($this->tmp_cookie_file); - } - - private function _fetch_token() { - $response = $this->_curl($this->pod."/stream"); - $matches = array(); - preg_match(self::$_token_regex, $response['text'], $matches); - return $matches[1]; - } - - public function post($text, $aspect_ids='public') { - $data = json_encode(array( - 'status_message' => array('text' => $text), - 'aspect_ids' => $aspect_ids + function post($text, $provider = "diasphp") { + // post-daten vorbereiten + $datatopost = json_encode(array( + 'aspect_ids' => 'public', + 'status_message' => array('text' => $text, + 'provider_display_name' => $provider) )); - $headers = array( - 'content-type' => 'application/json', - 'accept' => 'application/json', - 'x-csrf-token' => $this->_fetch_token() - ); - $response = $this->_curl($this->pod."/status_messages", "post", $data, $headers); - var_dump($response); - exit(); - if ($response['status_code'] != 201) { - throw new \Exception("Invalid status code: ".$response['status_code']); - } - } + // header vorbereiten + $headers = array( + 'Content-Type: application/json', + 'accept: application/json', + 'x-csrf-token: '.$this->_fetch_token() + ); + + // Adresse per cURL abrufen + $ch = curl_init(); + + curl_setopt ($ch, CURLOPT_URL, $this->pod . "/status_messages"); + curl_setopt ($ch, CURLOPT_COOKIEFILE, $this->cookiejar); + curl_setopt ($ch, CURLOPT_COOKIEJAR, $this->cookiejar); + curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, false); + curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt ($ch, CURLOPT_POST, true); + curl_setopt ($ch, CURLOPT_POSTFIELDS, $datatopost); + curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers); + + curl_exec ($ch); + $info = curl_getinfo($ch); + curl_close($ch); + + if($info['http_code'] != 201) { + throw new \Exception('Post error '.print_r($info, true)); + } + + // Ende der möglichen Kette, gib mal "true" zurück. + return true; + } } } diff --git a/Main.php b/Main.php index c06cf0d..9c2fcda 100644 --- a/Main.php +++ b/Main.php @@ -17,67 +17,53 @@ \Idno\Core\site()->template()->extendTemplate('account/menu/items', 'account/diaspora/menu'); } - /*function registerEventHooks() - { // TODO + function registerEventHooks() + { \Idno\Core\site()->syndication()->registerService('diaspora', function () { return $this->hasDiaspora(); }, array('note', 'article', 'image', 'media','rsvp', 'bookmark')); if ($this->hasDiaspora()) { - if (is_array(\Idno\Core\site()->session()->currentUser()->diaspora) && !array_key_exists('access_token', \Idno\Core\site()->session()->currentUser()->facebook)) { - foreach(\Idno\Core\site()->session()->currentUser()->facebook as $username => $details) { - \Idno\Core\site()->syndication()->registerServiceAccount('facebook', $username, $details['name']); - } - } + \Idno\Core\site()->syndication()->registerServiceAccount('diaspora', \Idno\Core\site()->session()->currentUser()->diaspora['diaspora_username'], 'Diaspora ('.\Idno\Core\site()->session()->currentUser()->diaspora['diaspora_username'].')'); } $notes_function = function (\Idno\Core\Event $event) { $eventdata = $event->data(); $object = $eventdata['object']; - if ($this->hasFacebook()) { + if ($this->hasDiaspora()) { $object = $eventdata['object']; - if (!empty($eventdata['syndication_account'])) { - $facebookAPI = $this->connect($eventdata['syndication_account']); - } else { - $facebookAPI = $this->connect(); - } - if (!empty($facebookAPI)) { + $diasporaAPI = new DiasporaAPI(\Idno\Core\site()->session()->currentUser()->diaspora['diaspora_pod']); + $diasporaAPI->login(\Idno\Core\site()->session()->currentUser()->diaspora['diaspora_username'], \Idno\Core\site()->session()->currentUser()->diaspora['diaspora_password']); + if (!empty($diasporaAPI)) { $message = preg_replace('/<[^\>]*>/', '', $object->getDescription()); //strip_tags($object->getDescription()); // Obey the IndieWeb reference setting if (!substr_count($message, \Idno\Core\site()->config()->host) && \Idno\Core\site()->config()->indieweb_reference) { - $message .= "\n\n(" . $object->getShortURL(true, false) . ")"; + $message .= "\n\n(getShortURL(true, false) . "\">" . $object->getShortURL(true, false) . ")"; } if (!empty($message) && substr($message, 0, 1) != '@') { - $params = array( - 'message' => $message, - 'actions' => json_encode([['name' => 'See Original', 'link' => $object->getURL()]]), - ); - if (preg_match('/(?"\'\(\)]+)/i', $message, $matches)) { - $params['link'] = $matches[0]; // Set the first discovered link as the match - } try { - $result = $facebookAPI->api('/'.$this->endpoint.'/feed', 'POST', $params); + $result = $diasporaAPI->post($message, 'KnownDiaspora'); if (!empty($result['id'])) { $result['id'] = str_replace('_', '/posts/', $result['id']); - $object->setPosseLink('facebook', 'https://facebook.com/' . $result['id']); $object->save(); } } catch (\Exception $e) { - error_log('There was a problem posting to Facebook: ' . $e->getMessage()); - \Idno\Core\site()->session()->addMessage('There was a problem posting to Facebook: ' . $e->getMessage()); + error_log('There was a problem posting to Diaspora: ' . $e->getMessage()); + \Idno\Core\site()->session()->addMessage('There was a problem posting to Diaspora: ' . $e->getMessage()); } } } } }; - // Push "notes" to Facebook - \Idno\Core\site()->addEventHook('post/note/facebook', $notes_function); - \Idno\Core\site()->addEventHook('post/bookmark/facebook', $notes_function); + // Push "notes" to Diaspora + \Idno\Core\site()->addEventHook('post/note/diaspora', $notes_function); + \Idno\Core\site()->addEventHook('post/bookmark/diaspora', $notes_function); + // TODO $article_function = function (\Idno\Core\Event $event) { $eventdata = $event->data(); $object = $eventdata['object']; @@ -104,11 +90,12 @@ }; // Push "articles" and "rsvps" to Facebook - \Idno\Core\site()->addEventHook('post/rsvp/facebook', $article_function); - \Idno\Core\site()->addEventHook('post/article/facebook', $article_function); + \Idno\Core\site()->addEventHook('post/rsvp/diaspora', $article_function); + \Idno\Core\site()->addEventHook('post/article/diaspora', $article_function); + // TODO // Push "media" to Facebook - \Idno\Core\site()->addEventHook('post/media/facebook', function (\Idno\Core\Event $event) { + \Idno\Core\site()->addEventHook('post/media/diaspora', function (\Idno\Core\Event $event) { $eventdata = $event->data(); $object = $eventdata['object']; if ($this->hasFacebook()) { @@ -133,8 +120,9 @@ } }); + // TODO // Push "images" to Facebook - \Idno\Core\site()->addEventHook('post/image/facebook', function (\Idno\Core\Event $event) { + \Idno\Core\site()->addEventHook('post/image/diaspora', function (\Idno\Core\Event $event) { $eventdata = $event->data(); $object = $eventdata['object']; if ($attachments = $object->getAttachments()) { @@ -172,7 +160,14 @@ } } }); - }*/ + } + + /** + * Check if Diaspora plugin is enabled. + */ + function hasDiaspora() { + return !empty(\Idno\Core\site()->session()->currentUser()->diaspora['diaspora_username']) && !empty(\Idno\Core\site()->session()->currentUser()->diaspora['diaspora_pod']) && !empty(\Idno\Core\site()->session()->currentUser()->diaspora['diaspora_password']); + } } } diff --git a/Pages/Account.php b/Pages/Account.php index 9b07ee5..9309ed5 100644 --- a/Pages/Account.php +++ b/Pages/Account.php @@ -15,11 +15,7 @@ function getContent() { if(isset($_GET['remove'])) { - \Idno\Core\site()->config->config['diaspora'] = [ - 'diaspora_username' => '', - 'diaspora_password' => '', - 'diaspora_pod' => '' - ]; + unset(\Idno\Core\site()->session()->currentUser()->diaspora); \Idno\Core\site()->config()->save(); \Idno\Core\site()->session()->addMessage('Your Diaspora credentials were removed.'); $this->forward(\Idno\Core\site()->config()->getDisplayURL() . 'account/diaspora/'); @@ -35,14 +31,18 @@ $pod = $this->getInput('pod'); $username = $this->getInput('user'); $password = $this->getInput('pass'); - \Idno\Core\site()->config->config['diaspora'] = [ + $user = \Idno\Core\site()->session()->currentUser(); + $user->diaspora = [ 'diaspora_username' => $username, 'diaspora_pod' => $pod ]; - if (empty(\Idno\Core\site()->config->config['diaspora']['diaspora_password']) || !empty($password) ) { - \Idno\Core\site()->config->config['diaspora']['diaspora_password'] = $password; + if (empty($user->diaspora['diaspora_password']) || !empty($password) ) { + $user->diaspora['diaspora_password'] = $password; } - \Idno\Core\site()->config()->save(); + else { + $user->diaspora['diaspora_password'] = $user->diaspora['diaspora_password']; + } + $user->save(); \Idno\Core\site()->session()->addMessage('Your Diaspora credentials were saved.'); $this->forward(\Idno\Core\site()->config()->getDisplayURL() . 'account/diaspora/'); } diff --git a/templates/default/account/diaspora.tpl.php b/templates/default/account/diaspora.tpl.php index 5298042..e136c52 100644 --- a/templates/default/account/diaspora.tpl.php +++ b/templates/default/account/diaspora.tpl.php @@ -22,19 +22,19 @@
-

-
-

Your Diaspora pod.

+

+
+

Your Diaspora pod.

-

-
-

Your Diaspora username.

+

+
+

Your Diaspora username.

-

-
-

Your Diaspora password.

+

+
+

Your Diaspora password.