Real-Time Updates

This commit is contained in:
Tobias Hößl 2012-02-29 14:06:19 +00:00
parent b83a5a7424
commit 5a4ca9459d
2 changed files with 210 additions and 143 deletions

View File

@ -23,7 +23,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

View File

@ -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/>
*/
/**
@ -31,7 +32,10 @@
* 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();
}
@ -113,7 +121,7 @@ function facebook_init(&$a) {
return;
}
$affected_users = array("feed" => array(), "friends" => array(), "activities" => array());
$affected_users = array("feed" => array(), "friends" => array());
foreach ($js->entry as $entry) {
$fbuser = $entry->uid;
@ -123,19 +131,20 @@ function facebook_init(&$a) {
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);
$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;
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);
@ -147,12 +156,14 @@ function facebook_init(&$a) {
}
break;
case "friend":
// @TODO
break;
case "activities":
//@TODO
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;
}
@ -171,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)
@ -199,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);
}
@ -220,9 +231,130 @@ function fb_get_self($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) == 0) {
logger('fb_get_friends: new contact found: ' . $link, LOGGER_DEBUG);
fb_get_friends_sync_full($uid, $access_token, $person);
}
}
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) {
$jp = json_decode($s);
logger('fb_get_friends: info: ' . print_r($jp,true), LOGGER_DATA);
function fb_get_friends($uid) {
// always use numeric link for consistency
$jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
// 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 {
// 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;
}
$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)
@ -245,111 +377,11 @@ function fb_get_friends($uid) {
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);
// always use numeric link for consistency
$jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
// 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 {
// 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;
}
$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)
);
}
}
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);
}
}
@ -394,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);
}
@ -419,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);
}
@ -537,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());
}
@ -562,12 +621,7 @@ function facebook_plugin_settings(&$a,&$b) {
function facebook_plugin_admin(&$a, &$o){
$activated = false;
$access_token = fb_get_app_access_token();
if ($access_token) {
$ret = facebook_subscriptions_get();
if (is_array($ret)) foreach ($ret as $re) if (is_object($re) && $re->object == "user") $activated = true;
}
$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') . '">';
@ -1300,7 +1354,9 @@ function facebook_subscription_del_users() {
$access_token = fb_get_app_access_token();
$url = "https://graph.facebook.com/" . get_config('facebook', 'appid' ) . "/subscriptions?access_token=" . $access_token;
delete_url($url);
facebook_delete_url($url);
del_config('facebook', 'realtime_active');
}
function facebook_subscription_add_users() {
@ -1318,7 +1374,7 @@ function facebook_subscription_add_users() {
$j = post_url($url,array(
"object" => "user",
"fields" => "feed,friends,activities",
"fields" => "feed,friends",
"callback_url" => $cb,
"verify_token" => $verify_token,
));
@ -1326,12 +1382,15 @@ function facebook_subscription_add_users() {
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);
@ -1344,15 +1403,20 @@ function facebook_subscriptions_get() {
}
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('delete_url')) {
function delete_url($url,$headers = null, &$redirects = 0, $timeout = 0) {
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))