X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=facebook%2Ffacebook.php;h=b2f21b93ed291abb84d56dcb696b72fe9df76f76;hb=746a42e4e03af3b0298c125e72d056607c7c43e7;hp=a103f2e8fde50f47e35b76f2a224d9ed76df8894;hpb=28405bfeb694515f2a569dae2c08dcbe2250d76e;p=friendica-addons.git
diff --git a/facebook/facebook.php b/facebook/facebook.php
old mode 100644
new mode 100755
index a103f2e8..b2f21b93
--- a/facebook/facebook.php
+++ b/facebook/facebook.php
@@ -1,24 +1,23 @@
+ * Tobias HöÃl
*/
/**
- * Installing the Friendika/Facebook connector
+ * Installing the Friendica/Facebook connector
*
* 1. register an API key for your site from developer.facebook.com
- * a. We'd be very happy if you include "Friendika" in the application name
- * to increase name recognition. The Friendika icons are also present
+ * a. We'd be very happy if you include "Friendica" in the application name
+ * to increase name recognition. The Friendica icons are also present
* in the images directory and may be uploaded as a Facebook app icon.
- * Use images/friendika-16.jpg for the Icon and images/friendika-128.jpg for the Logo.
+ * Use images/friendica-16.jpg for the Icon and images/friendica-128.jpg for the Logo.
* b. The url should be your site URL with a trailing slash.
- * You may use http://portal.friendika.com/privacy as the privacy policy
- * URL unless your site has different requirements, and
- * http://portal.friendika.com as the Terms of Service URL unless
- * you have different requirements. (Friendika is a software application
- * and does not require Terms of Service, though your installation of it might).
+ * Friendica is a software application and does not require a Privacy Policy
+ * or Terms of Service, though your installation of it might. Facebook may require
+ * that you provide a Privacy Policy, which we find ironic.
* c. Set the following values in your .htconfig.php file
* $a->config['facebook']['appid'] = 'xxxxxxxxxxx';
* $a->config['facebook']['appsecret'] = 'xxxxxxxxxxxxxxx';
@@ -26,13 +25,17 @@
* d. Navigate to Set Web->Site URL & Domain -> Website Settings. Set
* Site URL to yoursubdomain.yourdomain.com. Set Site Domain to your
* yourdomain.com.
- * 2. Enable the facebook plugin by including it in .htconfig.php - e.g.
+ * 2. (This step is now obsolete. Enable the plugin via the Admin panel.)
+ * Enable the facebook plugin by including it in .htconfig.php - e.g.
* $a->config['system']['addon'] = 'plugin1,plugin2,facebook';
* 3. Visit the Facebook Settings section of the "Settings->Plugin Settings" page.
* 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
@@ -54,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
}
@@ -68,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();
}
@@ -77,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];
@@ -92,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)
@@ -120,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);
}
@@ -141,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);
-
- // always use numeric link for consistency
+ $jp = json_decode($s);
+ logger('fb_get_friends: info: ' . print_r($jp,true), LOGGER_DATA);
- $jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
+ // always use numeric link for consistency
- // 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 {
+ $jp->link = 'http://facebook.com/profile.php?id=' . $person->id;
- // 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)
- );
- }
+ // check if we already have a contact
- $r = q("SELECT * FROM `contact` WHERE `url` = '%s' AND `uid` = %d LIMIT 1",
- dbesc($jp->link),
- intval($uid)
- );
+ $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' LIMIT 1",
+ intval($uid),
+ dbesc($jp->link)
+ );
- 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',
@@ -266,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);
}
}
@@ -294,6 +405,8 @@ function facebook_post(&$a) {
set_pconfig($uid,'facebook','private_wall',$private_wall);
+ set_pconfig($uid,'facebook','blocked_apps',escape_tags(trim($_POST['blocked_apps'])));
+
$linkvalue = ((x($_POST,'facebook_linking')) ? intval($_POST['facebook_linking']) : 0);
set_pconfig($uid,'facebook','no_linking', (($linkvalue) ? 0 : 1));
@@ -313,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);
}
@@ -338,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);
}
@@ -401,6 +514,12 @@ function facebook_content(&$a) {
$o .= '
' . t('If you choose to link conversations and leave both of these boxes unchecked, your Facebook profile wall will be merged with your profile wall on this website and your privacy settings on this website will be used to determine who may see the conversations.') . '
';
+
+ $blocked_apps = get_pconfig(local_user(),'facebook','blocked_apps');
+
+ $o .= '';
+ $o .= '';
+
$o .= '';
}
@@ -450,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());
}
@@ -472,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.') . '