]> git.mxchange.org Git - friendica-addons.git/commitdiff
Merge pull request #16 from CatoTH/master
authorfriendica <info@friendica.com>
Thu, 8 Mar 2012 22:43:22 +0000 (14:43 -0800)
committerfriendica <info@friendica.com>
Thu, 8 Mar 2012 22:43:22 +0000 (14:43 -0800)
Support for Facebook's Real-Time Updates
CatoTH - you might wish to consider moving delete_url to include/network.php, but since that is in a separate repository best to wrap it in "if (! function_exists('delete_url')) ..." in case somebody git updates the addon at a different time than the main code.

facebook/README
facebook/facebook.php

index 9e381e7dca9e151fefec783e31fa052895ce08ca..9687558e70bd9a0d1b8aefd167e4aea1a8f64402 100755 (executable)
@@ -25,7 +25,10 @@ Installing the Friendica/Facebook connector
    and click 'Install Facebook Connector'.
 4. This will ask you to login to Facebook and grant permission to the 
    plugin to do its stuff. Allow it to do so. 
-5. You're done. To turn it off visit the Plugin Settings page again and
+5. Optional step: If you want to use Facebook Real Time Updates (so new messages
+   and new contacts are added ~1min after they are postet / added on FB), go to
+   Settings -> plugins -> facebook and press the "Activate Real-Time Updates"-button.
+6. You're done. To turn it off visit the Plugin Settings page again and
    'Remove Facebook posting'.
 
 Vidoes and embeds will not be posted if there is no other content. Links 
index 6b6c7f8447ec8e3cfc4373b409c0629870f864ed..35338fa16d7bbff606b3217d1c99f9f0cc0af159 100755 (executable)
@@ -1,8 +1,9 @@
 <?php
 /**
  * Name: Facebook Connector
- * Version: 1.0
+ * Version: 1.1
  * Author: Mike Macgirvin <http://macgirvin.com/profile/mike>
+ *         Tobias Hößl <https://github.com/CatoTH/>
  */
 
 /**
  *    and click 'Install Facebook Connector'.
  * 4. This will ask you to login to Facebook and grant permission to the 
  *    plugin to do its stuff. Allow it to do so. 
- * 5. You're done. To turn it off visit the Plugin Settings page again and
+ * 5. Optional step: If you want to use Facebook Real Time Updates (so new messages
+ *    and new contacts are added ~1min after they are postet / added on FB), go to
+ *    Settings -> plugins -> facebook and press the "Activate Real-Time Updates"-button.
+ * 6. You're done. To turn it off visit the Plugin Settings page again and
  *    'Remove Facebook posting'.
  *
  * Vidoes and embeds will not be posted if there is no other content. Links 
@@ -53,6 +57,8 @@ function facebook_install() {
        register_hook('connector_settings',  'addon/facebook/facebook.php', 'facebook_plugin_settings');
        register_hook('cron',             'addon/facebook/facebook.php', 'facebook_cron');
        register_hook('queue_predeliver', 'addon/facebook/facebook.php', 'fb_queue_hook');
+       
+       if (get_config('facebook', 'realtime_active') == 1) facebook_subscription_add_users(); // Restore settings, if the plugin was installed before
 }
 
 
@@ -67,6 +73,8 @@ function facebook_uninstall() {
        // hook moved
        unregister_hook('post_local_end',  'addon/facebook/facebook.php', 'facebook_post_hook');
        unregister_hook('plugin_settings',  'addon/facebook/facebook.php', 'facebook_plugin_settings');
+       
+       if (get_config('facebook', 'realtime_active') == 1) facebook_subscription_del_users();
 }
 
 
@@ -76,10 +84,93 @@ function facebook_module() {}
 
 
 
-/* If a->argv[1] is a nickname, this is a callback from Facebook oauth requests. */
+// If a->argv[1] is a nickname, this is a callback from Facebook oauth requests.
+// If $_REQUEST["realtime_cb"] is set, this is a callback from the Real-Time Updates API
 
 function facebook_init(&$a) {
+       
+       if (x($_REQUEST, "realtime_cb") && x($_REQUEST, "realtime_cb")) {
+               logger("facebook_init: Facebook Real-Time callback called", LOGGER_DEBUG);
+               
+               if (x($_REQUEST, "hub_verify_token")) {
+                       // this is the verification callback while registering for real time updates
+                       
+                       $verify_token = get_config('facebook', 'cb_verify_token');
+                       if ($verify_token != $_REQUEST["hub_verify_token"]) {
+                               logger('facebook_init: Wrong Facebook Callback Verifier - expected ' . $verify_token . ', got ' . $_REQUEST["hub_verify_token"]);
+                               return;
+                       }
+                       
+                       if (x($_REQUEST, "hub_challenge")) {
+                               logger('facebook_init: Answering Challenge: ' . $_REQUEST["hub_challenge"], LOGGER_DATA);
+                               echo $_REQUEST["hub_challenge"];
+                               die();
+                       }
+               }
+               
+               require_once('include/items.php');
+               
+               // this is a status update
+               $content = file_get_contents("php://input");
+               if (is_numeric($content)) $content = file_get_contents("php://input");
+               $js = json_decode($content);
+               logger(print_r($js, true), LOGGER_DATA);
+               
+               if (!isset($js->object) || $js->object != "user" || !isset($js->entry)) {
+                       logger('facebook_init: Could not parse Real-Time Update data', LOGGER_DEBUG);
+                       return;
+               }
+               
+               $affected_users = array("feed" => array(), "friends" => array());
+               
+               foreach ($js->entry as $entry) {
+                       $fbuser = $entry->uid;
+                       foreach ($entry->changed_fields as $field) {
+                               if (!isset($affected_users[$field])) {
+                                       logger('facebook_init: Unknown field "' . $field . '"');
+                                       continue;
+                               }
+                               if (in_array($fbuser, $affected_users[$field])) continue;
+                               
+                               $r = q("SELECT `uid` FROM `pconfig` WHERE `cat` = 'facebook' AND `k` = 'self_id' AND `v` = '%s' LIMIT 1", dbesc($fbuser));
+                               if(! count($r))
+                                       continue;
+                               $uid = $r[0]['uid'];
+                               
+                               $access_token = get_pconfig($uid,'facebook','access_token');
+                               if(! $access_token)
+                                       return;
+                               
+                               switch ($field) {
+                                       case "feed":
+                                               logger('facebook_init: FB-User ' . $fbuser . ' / feed', LOGGER_DEBUG);
+                                               
+                                               if(! get_pconfig($uid,'facebook','no_wall')) {
+                                                       $private_wall = intval(get_pconfig($uid,'facebook','private_wall'));
+                                                       $s = fetch_url('https://graph.facebook.com/me/feed?access_token=' . $access_token);
+                                                       if($s) {
+                                                               $j = json_decode($s);
+                                                               logger('facebook_init: wall: ' . print_r($j,true), LOGGER_DATA);
+                                                               fb_consume_stream($uid,$j,($private_wall) ? false : true);
+                                                       }
+                                               }
+                                               
+                                       break;
+                                       case "friends":
+                                               logger('facebook_init: FB-User ' . $fbuser . ' / friends', LOGGER_DEBUG);
+                                               
+                                               fb_get_friends($uid, false);
+                                               set_pconfig($uid,'facebook','friend_check',time());
+                                       break;
+                                       default:
+                                               logger('facebook_init: Unknown callback field for ' . $fbuser, LOGGER_NORMAL);
+                               }
+                               $affected_users[$field][] = $fbuser;
+                       }
+               }
+       }
 
+       
        if($a->argc != 2)
                return;
        $nick = $a->argv[1];
@@ -91,8 +182,8 @@ function facebook_init(&$a) {
                return;
 
        $uid           = $r[0]['uid'];
-       $auth_code     = (($_GET['code']) ? $_GET['code'] : '');
-       $error         = (($_GET['error_description']) ? $_GET['error_description'] : '');
+       $auth_code     = (x($_GET, 'code') ? $_GET['code'] : '');
+       $error         = (x($_GET, 'error_description') ? $_GET['error_description'] : '');
 
 
        if($error)
@@ -119,7 +210,7 @@ function facebook_init(&$a) {
                        if(get_pconfig($uid,'facebook','no_linking') === false)
                                set_pconfig($uid,'facebook','no_linking',1);
                        fb_get_self($uid);
-                       fb_get_friends($uid);
+                       fb_get_friends($uid, true);
                        fb_consume_all($uid);
 
                }
@@ -140,116 +231,46 @@ function fb_get_self($uid) {
        }
 }
 
-
-
-function fb_get_friends($uid) {
-
-       $r = q("SELECT `uid` FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1",
-               intval($uid)
+function fb_get_friends_sync_new($uid, $access_token, $person) {
+       $link = 'http://facebook.com/profile.php?id=' . $person->id;
+       
+       $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
+               intval($uid),
+               dbesc($link)
        );
-       if(! count($r))
-               return;
-
-       $access_token = get_pconfig($uid,'facebook','access_token');
-
-       $no_linking = get_pconfig($uid,'facebook','no_linking');
-       if($no_linking)
-               return;
+       
+       if (count($r) == 0) {
+               logger('fb_get_friends: new contact found: ' . $link, LOGGER_DEBUG);
+               
+               fb_get_friends_sync_full($uid, $access_token, $person);
+       }
+}
 
-       if(! $access_token)
-               return;
-       $s = fetch_url('https://graph.facebook.com/me/friends?access_token=' . $access_token);
+function fb_get_friends_sync_full($uid, $access_token, $person) {
+       $s = fetch_url('https://graph.facebook.com/' . $person->id . '?access_token=' . $access_token);
        if($s) {
-               logger('facebook: fb_get_friends: ' . $s, LOGGER_DATA);
-               $j = json_decode($s);
-               logger('facebook: fb_get_friends: json: ' . print_r($j,true), LOGGER_DATA);
-               if(! $j->data)
-                       return;
-               foreach($j->data as $person) {
-                       $s = fetch_url('https://graph.facebook.com/' . $person->id . '?access_token=' . $access_token);
-                       if($s) {
-                               $jp = json_decode($s);
-                               logger('fb_get_friends: info: ' . print_r($jp,true), LOGGER_DATA);
+               $jp = json_decode($s);
+               logger('fb_get_friends: info: ' . print_r($jp,true), LOGGER_DATA);
 
-                               // always use numeric link for consistency
+               // always use numeric link for consistency
 
-                               $jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
+               $jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
 
-                               // check if we already have a contact
+               // check if we already have a contact
 
-                               $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
-                                       intval($uid),
-                                       dbesc($jp->link)
-                               );                      
-
-                               if(count($r)) {
-
-                                       // check that we have all the photos, this has been known to fail on occasion
-
-                                       if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro'])) {  
-                                               require_once("Photo.php");
-
-                                               $photos = import_profile_photo('https://graph.facebook.com/' . $jp->id . '/picture', $uid, $r[0]['id']);
-
-                                               $r = q("UPDATE `contact` SET `photo` = '%s', 
-                                                       `thumb` = '%s',
-                                                       `micro` = '%s', 
-                                                       `name-date` = '%s', 
-                                                       `uri-date` = '%s', 
-                                                       `avatar-date` = '%s'
-                                                       WHERE `id` = %d LIMIT 1
-                                               ",
-                                                       dbesc($photos[0]),
-                                                       dbesc($photos[1]),
-                                                       dbesc($photos[2]),
-                                                       dbesc(datetime_convert()),
-                                                       dbesc(datetime_convert()),
-                                                       dbesc(datetime_convert()),
-                                                       intval($r[0]['id'])
-                                               );                      
-                                       }       
-                                       continue;
-                               }
-                               else {
+               $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
+                       intval($uid),
+                       dbesc($jp->link)
+               );                      
 
-                                       // create contact record 
-                                       $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`, 
-                                               `name`, `nick`, `photo`, `network`, `rel`, `priority`,
-                                               `writable`, `blocked`, `readonly`, `pending` )
-                                               VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ",
-                                               intval($uid),
-                                               dbesc(datetime_convert()),
-                                               dbesc($jp->link),
-                                               dbesc(normalise_link($jp->link)),
-                                               dbesc(''),
-                                               dbesc(''),
-                                               dbesc($jp->id),
-                                               dbesc('facebook ' . $jp->id),
-                                               dbesc($jp->name),
-                                               dbesc(($jp->nickname) ? $jp->nickname : strtolower($jp->first_name)),
-                                               dbesc('https://graph.facebook.com/' . $jp->id . '/picture'),
-                                               dbesc(NETWORK_FACEBOOK),
-                                               intval(CONTACT_IS_FRIEND),
-                                               intval(1),
-                                               intval(1)
-                                       );
-                               }
-
-                               $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
-                                       dbesc($jp->link),
-                                       intval($uid)
-                               );
-
-                               if(! count($r)) {
-                                       continue;
-                               }
+               if(count($r)) {
 
-                               $contact = $r[0];
-                               $contact_id  = $r[0]['id'];
+                       // check that we have all the photos, this has been known to fail on occasion
 
+                       if((! $r[0]['photo']) || (! $r[0]['thumb']) || (! $r[0]['micro'])) {  
                                require_once("Photo.php");
 
-                               $photos = import_profile_photo($r[0]['photo'],$uid,$contact_id);
+                               $photos = import_profile_photo('https://graph.facebook.com/' . $jp->id . '/picture', $uid, $r[0]['id']);
 
                                $r = q("UPDATE `contact` SET `photo` = '%s', 
                                        `thumb` = '%s',
@@ -265,11 +286,102 @@ function fb_get_friends($uid) {
                                        dbesc(datetime_convert()),
                                        dbesc(datetime_convert()),
                                        dbesc(datetime_convert()),
-                                       intval($contact_id)
+                                       intval($r[0]['id'])
                                );                      
+                       }       
+                       return;
+               }
+               else {
 
-                       }
+                       // create contact record 
+                       $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`, 
+                               `name`, `nick`, `photo`, `network`, `rel`, `priority`,
+                               `writable`, `blocked`, `readonly`, `pending` )
+                               VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d, 0, 0, 0 ) ",
+                               intval($uid),
+                               dbesc(datetime_convert()),
+                               dbesc($jp->link),
+                               dbesc(normalise_link($jp->link)),
+                               dbesc(''),
+                               dbesc(''),
+                               dbesc($jp->id),
+                               dbesc('facebook ' . $jp->id),
+                               dbesc($jp->name),
+                               dbesc(($jp->nickname) ? $jp->nickname : strtolower($jp->first_name)),
+                               dbesc('https://graph.facebook.com/' . $jp->id . '/picture'),
+                               dbesc(NETWORK_FACEBOOK),
+                               intval(CONTACT_IS_FRIEND),
+                               intval(1),
+                               intval(1)
+                       );
+               }
+
+               $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
+                       dbesc($jp->link),
+                       intval($uid)
+               );
+
+               if(! count($r)) {
+                       return;
                }
+
+               $contact = $r[0];
+               $contact_id  = $r[0]['id'];
+
+               require_once("Photo.php");
+
+               $photos = import_profile_photo($r[0]['photo'],$uid,$contact_id);
+
+               $r = q("UPDATE `contact` SET `photo` = '%s', 
+                       `thumb` = '%s',
+                       `micro` = '%s', 
+                       `name-date` = '%s', 
+                       `uri-date` = '%s', 
+                       `avatar-date` = '%s'
+                       WHERE `id` = %d LIMIT 1
+               ",
+                       dbesc($photos[0]),
+                       dbesc($photos[1]),
+                       dbesc($photos[2]),
+                       dbesc(datetime_convert()),
+                       dbesc(datetime_convert()),
+                       dbesc(datetime_convert()),
+                       intval($contact_id)
+               );                      
+
+       }
+}
+
+// if $fullsync is true, only new contacts are searched for
+
+function fb_get_friends($uid, $fullsync = true) {
+
+       $r = q("SELECT `uid` FROM `user` WHERE `uid` = %d AND `account_expired` = 0 LIMIT 1",
+               intval($uid)
+       );
+       if(! count($r))
+               return;
+
+       $access_token = get_pconfig($uid,'facebook','access_token');
+
+       $no_linking = get_pconfig($uid,'facebook','no_linking');
+       if($no_linking)
+               return;
+
+       if(! $access_token)
+               return;
+       $s = fetch_url('https://graph.facebook.com/me/friends?access_token=' . $access_token);
+       if($s) {
+               logger('facebook: fb_get_friends: ' . $s, LOGGER_DATA);
+               $j = json_decode($s);
+               logger('facebook: fb_get_friends: json: ' . print_r($j,true), LOGGER_DATA);
+               if(! $j->data)
+                       return;
+               foreach($j->data as $person)
+                       if ($fullsync)
+                               fb_get_friends_sync_full($uid, $access_token, $person);
+                       else
+                               fb_get_friends_sync_new($uid, $access_token, $person);
        }
 }
 
@@ -314,7 +426,7 @@ function facebook_post(&$a) {
                elseif(intval($no_linking) && intval($linkvalue)) {
                        // FB linkage is now allowed - import stuff.
                        fb_get_self($uid);
-                       fb_get_friends($uid);
+                       fb_get_friends($uid, true);
                        fb_consume_all($uid);
                }
 
@@ -339,7 +451,7 @@ function facebook_content(&$a) {
        }
 
        if($a->argc > 1 && $a->argv[1] === 'friends') {
-               fb_get_friends(local_user());
+               fb_get_friends(local_user(), true);
                info( t('Updating contacts') . EOL);
        }
 
@@ -457,13 +569,40 @@ function facebook_cron($a,$b) {
                        if($last_friend_check) 
                                $next_friend_check = $last_friend_check + 86400;
                        if($next_friend_check <= time()) {
-                               fb_get_friends($rr['uid']);
+                               fb_get_friends($rr['uid'], true);
                                set_pconfig($rr['uid'],'facebook','friend_check',time());
                        }
                        fb_consume_all($rr['uid']);
                }
-       }       
-
+       }
+       
+       if (get_config('facebook', 'realtime_active') == 1) {
+               if (!facebook_check_realtime_active()) {
+                       
+                       logger('facebook_cron: Facebook is not sending Real-Time Updates any more, although it is supposed to. Trying to fix it...', LOGGER_NORMAL);
+                       facebook_subscription_add_users();
+                       
+                       if (facebook_check_realtime_active()) 
+                               logger('facebook_cron: Successful', LOGGER_NORMAL);
+                       else {
+                               logger('facebook_cron: Failed', LOGGER_NORMAL);
+                               
+                               if(strlen($a->config['admin_email']) && !get_config('facebook', 'realtime_err_mailsent')) {
+                                       $res = mail($a->config['admin_email'], t('Problems with Facebook Real-Time Updates'), 
+                                               "Hi!\n\nThere's a problem with the Facebook Real-Time Updates that cannob be solved automatically. Maybe an permission issue?\n\nThis e-mail will only be sent once.",
+                                               'From: ' . t('Administrator') . '@' . $_SERVER['SERVER_NAME'] . "\n"
+                                               . 'Content-type: text/plain; charset=UTF-8' . "\n"
+                                               . 'Content-transfer-encoding: 8bit'
+                                       );
+                                       
+                                       set_config('facebook', 'realtime_err_mailsent', 1);
+                               }
+                       }
+               } else { // !facebook_check_realtime_active()
+                       del_config('facebook', 'realtime_err_mailsent');
+               }
+       }
+       
        set_config('facebook','last_poll', time());
 
 }
@@ -479,6 +618,27 @@ function facebook_plugin_settings(&$a,&$b) {
 
 }
 
+
+function facebook_plugin_admin(&$a, &$o){
+       
+       $activated = facebook_check_realtime_active();
+       if ($activated) {
+               $o = t('Real-Time Updates are activated.') . '<br><br>';
+               $o .= '<input type="submit" name="real_time_deactivate" value="' . t('Deactivate Real-Time Updates') . '">';
+       } else {
+               $o = t('Real-Time Updates not activated.') . '<br><input type="submit" name="real_time_activate" value="' . t('Activate Real-Time Updates') . '">';
+       }
+}
+
+function facebook_plugin_admin_post(&$a, &$o){
+       if (x($_REQUEST,'real_time_activate')) {
+               facebook_subscription_add_users();
+       }
+       if (x($_REQUEST,'real_time_deactivate')) {
+               facebook_subscription_del_users();
+       }
+}
+
 function facebook_jot_nets(&$a,&$b) {
        if(! local_user())
                return;
@@ -1153,3 +1313,188 @@ function fb_consume_stream($uid,$j,$wall = false) {
        }
 }
 
+
+function fb_get_app_access_token() {
+       
+       $acc_token = get_config('facebook','app_access_token');
+       
+       if ($acc_token !== false) return $acc_token;
+       
+       $appid = get_config('facebook','appid');
+       $appsecret = get_config('facebook', 'appsecret');
+       
+       if ($appid === false || $appsecret === false) {
+               logger('fb_get_app_access_token: appid and/or appsecret not set', LOGGER_DEBUG);
+               return false;
+       }
+       
+       $x = fetch_url('https://graph.facebook.com/oauth/access_token?client_id=' . $appid . '&client_secret=' . $appsecret . "&grant_type=client_credentials");
+       
+       if(strpos($x,'access_token=') !== false) {
+               logger('fb_get_app_access_token: returned access token: ' . $x, LOGGER_DATA);
+       
+               $token = str_replace('access_token=', '', $x);
+               if(strpos($token,'&') !== false)
+                       $token = substr($token,0,strpos($token,'&'));
+               
+               if ($token == "") {
+                       logger('fb_get_app_access_token: empty token: ' . $x, LOGGER_DEBUG);
+                       return false;
+               }
+               set_config('facebook','app_access_token',$token);
+               return $token;
+       } else {
+               logger('fb_get_app_access_token: response did not contain an access_token: ' . $x, LOGGER_DATA);
+               return false;
+       }
+}
+
+function facebook_subscription_del_users() {
+       $a = get_app();
+       $access_token = fb_get_app_access_token();
+       
+       $url = "https://graph.facebook.com/" . get_config('facebook', 'appid'  ) . "/subscriptions?access_token=" . $access_token;
+       facebook_delete_url($url);
+       
+       del_config('facebook', 'realtime_active');
+}
+
+function facebook_subscription_add_users() {
+       
+       $a = get_app();
+       $access_token = fb_get_app_access_token();
+       
+       $url = "https://graph.facebook.com/" . get_config('facebook', 'appid'  ) . "/subscriptions?access_token=" . $access_token;
+       
+       list($usec, $sec) = explode(" ", microtime());
+       $verify_token = sha1($usec . $sec . rand(0, 999999999));
+       set_config('facebook', 'cb_verify_token', $verify_token);
+       
+       $cb = $a->get_baseurl() . '/facebook/?realtime_cb=1';
+       
+       $j = post_url($url,array(
+               "object" => "user",
+               "fields" => "feed,friends",
+               "callback_url" => $cb,
+               "verify_token" => $verify_token,
+       ));
+       del_config('facebook', 'cb_verify_token');
+       
+       if ($j) {
+               logger("Facebook reponse: " . $j, LOGGER_DATA);
+               
+               if (facebook_check_realtime_active()) set_config('facebook', 'realtime_active', 1);
+       };
+}
+
+function facebook_subscriptions_get() {
+       
+       $access_token = fb_get_app_access_token();
+       if (!$access_token) return null;
+       
+       $url = "https://graph.facebook.com/" . get_config('facebook', 'appid'  ) . "/subscriptions?access_token=" . $access_token;
+       $j = fetch_url($url);
+       $ret = null;
+       if ($j) {
+               $x = json_decode($j);
+               if (isset($x->data)) $ret = $x->data;
+       }
+       return $ret;
+}
+
+
+function facebook_check_realtime_active() {
+       $ret = facebook_subscriptions_get();
+       if (is_null($ret)) return false;
+       if (is_array($ret)) foreach ($ret as $re) if (is_object($re) && $re->object == "user") return true;
+       return false;
+}
+
+
+
+
+// DELETE-request to $url
+
+if(! function_exists('facebook_delete_url')) {
+function facebook_delete_url($url,$headers = null, &$redirects = 0, $timeout = 0) {
+       $a = get_app();
+       $ch = curl_init($url);
+       if(($redirects > 8) || (! $ch)) 
+               return false;
+
+       curl_setopt($ch, CURLOPT_HEADER, true);
+       curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
+       curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
+       curl_setopt($ch, CURLOPT_USERAGENT, "Friendica");
+
+       if(intval($timeout)) {
+               curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
+       }
+       else {
+               $curl_time = intval(get_config('system','curl_timeout'));
+               curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_time !== false) ? $curl_time : 60));
+       }
+
+       if(defined('LIGHTTPD')) {
+               if(!is_array($headers)) {
+                       $headers = array('Expect:');
+               } else {
+                       if(!in_array('Expect:', $headers)) {
+                               array_push($headers, 'Expect:');
+                       }
+               }
+       }
+       if($headers)
+               curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+
+       $check_cert = get_config('system','verifyssl');
+       curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (($check_cert) ? true : false));
+       $prx = get_config('system','proxy');
+       if(strlen($prx)) {
+               curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
+               curl_setopt($ch, CURLOPT_PROXY, $prx);
+               $prxusr = get_config('system','proxyuser');
+               if(strlen($prxusr))
+                       curl_setopt($ch, CURLOPT_PROXYUSERPWD, $prxusr);
+       }
+
+       $a->set_curl_code(0);
+
+       // don't let curl abort the entire application
+       // if it throws any errors.
+
+       $s = @curl_exec($ch);
+
+       $base = $s;
+       $curl_info = curl_getinfo($ch);
+       $http_code = $curl_info['http_code'];
+
+       $header = '';
+
+       // Pull out multiple headers, e.g. proxy and continuation headers
+       // allow for HTTP/2.x without fixing code
+
+       while(preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/',$base)) {
+               $chunk = substr($base,0,strpos($base,"\r\n\r\n")+4);
+               $header .= $chunk;
+               $base = substr($base,strlen($chunk));
+       }
+
+       if($http_code == 301 || $http_code == 302 || $http_code == 303) {
+        $matches = array();
+        preg_match('/(Location:|URI:)(.*?)\n/', $header, $matches);
+        $url = trim(array_pop($matches));
+        $url_parsed = @parse_url($url);
+        if (isset($url_parsed)) {
+            $redirects++;
+            return delete_url($url,$headers,$redirects,$timeout);
+        }
+    }
+       $a->set_curl_code($http_code);
+       $body = substr($s,strlen($header));
+
+       $a->set_curl_headers($header);
+
+       curl_close($ch);
+       return($body);
+}}
\ No newline at end of file