From 8cd21269ff7b0ca48537b59496a85b06049453aa Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 19 Nov 2017 18:59:55 +0000 Subject: [PATCH] The last of the big workers moved ... delivery and notifier --- include/Contact.php | 2 +- include/items.php | 10 +- include/like.php | 4 +- include/message.php | 2 +- include/notifier.php | 617 ------------------ include/uimport.php | 2 +- mod/admin.php | 2 +- mod/dfrn_confirm.php | 4 +- mod/events.php | 2 +- mod/fsuggest.php | 2 +- mod/item.php | 4 +- mod/mood.php | 4 +- mod/photos.php | 8 +- mod/poke.php | 4 +- mod/profiles.php | 2 +- mod/settings.php | 2 +- mod/tagger.php | 2 +- mod/videos.php | 2 +- src/Core/Worker.php | 2 +- src/Protocol/DFRN.php | 6 +- src/Protocol/Diaspora.php | 8 +- .../delivery.php => src/Worker/Delivery.php | 68 +- src/Worker/Notifier.php | 606 +++++++++++++++++ 23 files changed, 672 insertions(+), 693 deletions(-) delete mode 100644 include/notifier.php rename include/delivery.php => src/Worker/Delivery.php (94%) create mode 100644 src/Worker/Notifier.php diff --git a/include/Contact.php b/include/Contact.php index 636bbc4a7a..cd1696af56 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -34,7 +34,7 @@ function user_remove($uid) { // The user and related data will be deleted in "cron_expire_and_remove_users" (cronjobs.php) q("UPDATE `user` SET `account_removed` = 1, `account_expires_on` = UTC_TIMESTAMP() WHERE `uid` = %d", intval($uid)); - Worker::add(PRIORITY_HIGH, "notifier", "removeme", $uid); + Worker::add(PRIORITY_HIGH, "Notifier", "removeme", $uid); // Send an update to the directory Worker::add(PRIORITY_LOW, "Directory", $r['url']); diff --git a/include/items.php b/include/items.php index 64ee3ffbf1..ed2204f608 100644 --- a/include/items.php +++ b/include/items.php @@ -1138,7 +1138,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f check_item_notification($current_post, $uid); if ($notify) { - Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "notifier", $notify_type, $current_post); + Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "Notifier", $notify_type, $current_post); } return $current_post; @@ -1421,7 +1421,7 @@ function tag_deliver($uid, $item_id) { ); update_thread($item_id); - Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'notifier', 'tgroup', $item_id); + Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), 'Notifier', 'tgroup', $item_id); } @@ -2055,7 +2055,7 @@ function item_expire($uid, $days, $network = "", $force = false) { drop_item($item['id'], false); } - Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "notifier", "expire", $uid); + Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "Notifier", "expire", $uid); } /// @TODO type-hint is array @@ -2077,7 +2077,7 @@ function drop_items($items) { // multiple threads may have been deleted, send an expire notification if ($uid) { - Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "notifier", "expire", $uid); + Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "Notifier", "expire", $uid); } } @@ -2269,7 +2269,7 @@ function drop_item($id, $interactive = true) { $drop_id = intval($item['id']); $priority = ($interactive ? PRIORITY_HIGH : PRIORITY_LOW); - Worker::add(array('priority' => $priority, 'dont_fork' => true), "notifier", "drop", $drop_id); + Worker::add(array('priority' => $priority, 'dont_fork' => true), "Notifier", "drop", $drop_id); if (! $interactive) { return $owner; diff --git a/include/like.php b/include/like.php index eee89168a9..5e05121f69 100644 --- a/include/like.php +++ b/include/like.php @@ -167,7 +167,7 @@ function do_like($item_id, $verb) { ); $like_item_id = $like_item['id']; - Worker::add(PRIORITY_HIGH, "notifier", "like", $like_item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "like", $like_item_id); if (!$event_verb_flag || $like_item['verb'] == $activity) { return true; @@ -254,7 +254,7 @@ EOT; call_hooks('post_local_end', $new_item); - Worker::add(PRIORITY_HIGH, "notifier", "like", $new_item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "like", $new_item_id); return true; } diff --git a/include/message.php b/include/message.php index dcc1fbc12e..e49647b6ef 100644 --- a/include/message.php +++ b/include/message.php @@ -145,7 +145,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){ } if ($post_id) { - Worker::add(PRIORITY_HIGH, "notifier", "mail", $post_id); + Worker::add(PRIORITY_HIGH, "Notifier", "mail", $post_id); return intval($post_id); } else { return -3; diff --git a/include/notifier.php b/include/notifier.php deleted file mode 100644 index 58926b9359..0000000000 --- a/include/notifier.php +++ /dev/null @@ -1,617 +0,0 @@ - UTC_TIMESTAMP() - INTERVAL 10 MINUTE", - intval($item_id) - ); - $uid = $item_id; - $item_id = 0; - if (! count($items)) { - return; - } - } elseif ($cmd === 'suggest') { - $normal_mode = false; - $fsuggest = true; - - $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1", - intval($item_id) - ); - if (! count($suggest)) { - return; - } - $uid = $suggest[0]['uid']; - $recipients[] = $suggest[0]['cid']; - $item = $suggest[0]; - } elseif ($cmd === 'removeme') { - $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`, - `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, - `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`, `user`.`guid` - FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` - WHERE `contact`.`uid` = %d AND `contact`.`self` LIMIT 1", - intval($item_id)); - if (!$r) - return; - - $user = $r[0]; - - $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($item_id)); - if (!$r) - return; - - $self = $r[0]; - - $r = q("SELECT * FROM `contact` WHERE NOT `self` AND `uid` = %d", intval($item_id)); - if (!$r) { - return; - } - require_once 'include/Contact.php'; - foreach ($r as $contact) { - terminate_friendship($user, $self, $contact); - } - return; - } elseif ($cmd === 'relocate') { - $normal_mode = false; - $relocate = true; - $uid = $item_id; - - $recipients_relocate = q("SELECT * FROM `contact` WHERE `uid` = %d AND NOT `self` AND `network` IN ('%s', '%s')", - intval($uid), NETWORK_DFRN, NETWORK_DIASPORA); - } else { - // find ancestors - $r = q("SELECT * FROM `item` WHERE `id` = %d AND visible = 1 AND moderated = 0 LIMIT 1", - intval($item_id) - ); - - if ((! DBM::is_result($r)) || (! intval($r[0]['parent']))) { - return; - } - - $target_item = $r[0]; - $parent_id = intval($r[0]['parent']); - $uid = $r[0]['uid']; - $updated = $r[0]['edited']; - - $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer` - FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d AND visible = 1 AND moderated = 0 ORDER BY `id` ASC", - intval($parent_id) - ); - - if (! count($items)) { - return; - } - - // avoid race condition with deleting entries - - if ($items[0]['deleted']) { - foreach ($items as $item) { - $item['deleted'] = 1; - } - } - - if ((count($items) == 1) && ($items[0]['id'] === $target_item['id']) && ($items[0]['uri'] === $items[0]['parent-uri'])) { - logger('notifier: top level post'); - $top_level = true; - } - - } - - $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`, - `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, - `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type` - FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` - WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", - intval($uid) - ); - - if (! DBM::is_result($r)) { - return; - } - - $owner = $r[0]; - - $walltowall = ((($top_level) && ($owner['id'] != $items[0]['contact-id'])) ? true : false); - - // Should the post be transmitted to Diaspora? - $diaspora_delivery = true; - - // If this is a public conversation, notify the feed hub - $public_message = true; - - // Do a PuSH - $push_notify = false; - - // Deliver directly to a forum, don't PuSH - $direct_forum_delivery = false; - - // fill this in with a single salmon slap if applicable - $slap = ''; - - if (! ($mail || $fsuggest || $relocate)) { - - $slap = OStatus::salmon($target_item, $owner); - - require_once 'include/group.php'; - - $parent = $items[0]; - - $thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d", - dbesc($target_item["thr-parent"]), intval($target_item["uid"])); - - logger('GUID: '.$target_item["guid"].': Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG); - - // This is IMPORTANT!!!! - - // We will only send a "notify owner to relay" or followup message if the referenced post - // originated on our system by virtue of having our hostname somewhere - // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere. - - // if $parent['wall'] == 1 we will already have the parent message in our array - // and we will relay the whole lot. - - // expire sends an entire group of expire messages and cannot be forwarded. - // However the conversation owner will be a part of the conversation and will - // be notified during this run. - // Other DFRN conversation members will be alerted during polled updates. - - - - // Diaspora members currently are not notified of expirations, and other networks have - // either limited or no ability to process deletions. We should at least fix Diaspora - // by stringing togther an array of retractions and sending them onward. - - - $localhost = str_replace('www.','',$a->get_hostname()); - if (strpos($localhost,':')) { - $localhost = substr($localhost,0,strpos($localhost,':')); - } - /** - * - * Be VERY CAREFUL if you make any changes to the following several lines. Seemingly innocuous changes - * have been known to cause runaway conditions which affected several servers, along with - * permissions issues. - * - */ - - $relay_to_owner = false; - - if (!$top_level && ($parent['wall'] == 0) && !$expire && (stristr($target_item['uri'],$localhost))) { - $relay_to_owner = true; - } - - - if (($cmd === 'uplink') && (intval($parent['forum_mode']) == 1) && !$top_level) { - $relay_to_owner = true; - } - - // until the 'origin' flag has been in use for several months - // we will just use it as a fallback test - // later we will be able to use it as the primary test of whether or not to relay. - - if (! $target_item['origin']) { - $relay_to_owner = false; - } - if ($parent['origin']) { - $relay_to_owner = false; - } - - // Special treatment for forum posts - if (($target_item['author-link'] != $target_item['owner-link']) && - ($owner['id'] != $target_item['contact-id']) && - ($target_item['uri'] === $target_item['parent-uri'])) { - - $fields = array('forum', 'prv'); - $condition = array('id' => $target_item['contact-id']); - $contact = dba::select('contact', $fields, $condition, array('limit' => 1)); - if (!DBM::is_result($contact)) { - // Should never happen - return false; - } - - // Is the post from a forum? - if ($contact['forum'] || $contact['prv']) { - $relay_to_owner = true; - $direct_forum_delivery = true; - } - } - if ($relay_to_owner) { - logger('notifier: followup '.$target_item["guid"], LOGGER_DEBUG); - // local followup to remote post - $followup = true; - $public_message = false; // not public - $conversant_str = dbesc($parent['contact-id']); - $recipients = array($parent['contact-id']); - $recipients_followup = array($parent['contact-id']); - - //if (!$target_item['private'] && $target_item['wall'] && - if (!$target_item['private'] && - (strlen($target_item['allow_cid'].$target_item['allow_gid']. - $target_item['deny_cid'].$target_item['deny_gid']) == 0)) - $push_notify = true; - - if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) { - - $push_notify = true; - - if ($parent["network"] == NETWORK_OSTATUS) { - // Distribute the message to the DFRN contacts as if this wasn't a followup since OStatus can't relay comments - // Currently it is work at progress - $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s' AND NOT `blocked` AND NOT `pending` AND NOT `archive`", - intval($uid), - dbesc(NETWORK_DFRN) - ); - if (DBM::is_result($r)) { - foreach ($r as $rr) { - $recipients_followup[] = $rr['id']; - } - } - } - } - - if ($direct_forum_delivery) { - $push_notify = false; - } - - logger("Notify ".$target_item["guid"]." via PuSH: ".($push_notify?"Yes":"No"), LOGGER_DEBUG); - } else { - $followup = false; - - logger('Distributing directly '.$target_item["guid"], LOGGER_DEBUG); - - // don't send deletions onward for other people's stuff - - if ($target_item['deleted'] && (! intval($target_item['wall']))) { - logger('notifier: ignoring delete notification for non-wall item'); - return; - } - - if ((strlen($parent['allow_cid'])) - || (strlen($parent['allow_gid'])) - || (strlen($parent['deny_cid'])) - || (strlen($parent['deny_gid']))) { - $public_message = false; // private recipients, not public - } - - $allow_people = expand_acl($parent['allow_cid']); - $allow_groups = expand_groups(expand_acl($parent['allow_gid']),true); - $deny_people = expand_acl($parent['deny_cid']); - $deny_groups = expand_groups(expand_acl($parent['deny_gid'])); - - // if our parent is a public forum (forum_mode == 1), uplink to the origional author causing - // a delivery fork. private groups (forum_mode == 2) do not uplink - - if ((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) { - Worker::add($a->queue['priority'], 'notifier', 'uplink', $item_id); - } - - $conversants = array(); - - foreach ($items as $item) { - $recipients[] = $item['contact-id']; - $conversants[] = $item['contact-id']; - // pull out additional tagged people to notify (if public message) - if ($public_message && strlen($item['inform'])) { - $people = explode(',',$item['inform']); - foreach ($people as $person) { - if (substr($person,0,4) === 'cid:') { - $recipients[] = intval(substr($person,4)); - $conversants[] = intval(substr($person,4)); - } else { - $url_recipients[] = substr($person,4); - } - } - } - } - - if (count($url_recipients)) - logger('notifier: '.$target_item["guid"].' url_recipients ' . print_r($url_recipients,true)); - - $conversants = array_unique($conversants); - - - $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups)); - $deny = array_unique(array_merge($deny_people,$deny_groups)); - $recipients = array_diff($recipients,$deny); - - $conversant_str = dbesc(implode(', ',$conversants)); - } - - // If the thread parent is OStatus then do some magic to distribute the messages. - // We have not only to look at the parent, since it could be a Friendica thread. - if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) { - - $diaspora_delivery = false; - - logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent[0]['author-link']." - Owner: ".$thr_parent[0]['owner-link'], LOGGER_DEBUG); - - // Send a salmon to the parent author - $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''", - dbesc(normalise_link($thr_parent[0]['author-link'])), - intval($uid)); - if (DBM::is_result($r)) { - $probed_contact = $r[0]; - } else { - $probed_contact = Probe::uri($thr_parent[0]['author-link']); - } - - if ($probed_contact["notify"] != "") { - logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]); - $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; - } - - // Send a salmon to the parent owner - $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''", - dbesc(normalise_link($thr_parent[0]['owner-link'])), - intval($uid)); - if (DBM::is_result($r)) { - $probed_contact = $r[0]; - } else { - $probed_contact = Probe::uri($thr_parent[0]['owner-link']); - } - - if ($probed_contact["notify"] != "") { - logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]); - $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; - } - - // Send a salmon notification to every person we mentioned in the post - $arr = explode(',',$target_item['tag']); - foreach ($arr as $x) { - //logger('Checking tag '.$x, LOGGER_DEBUG); - $matches = null; - if (preg_match('/@\[url=([^\]]*)\]/',$x,$matches)) { - $probed_contact = Probe::uri($matches[1]); - if ($probed_contact["notify"] != "") { - logger('Notify mentioned user '.$probed_contact["url"].': '.$probed_contact["notify"]); - $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; - } - } - } - - // It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora - $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."')"; - } else { - $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."', '".NETWORK_DIASPORA."', '".NETWORK_MAIL."', '".NETWORK_MAIL2."')"; - } - } else { - $public_message = false; - } - - // If this is a public message and pubmail is set on the parent, include all your email contacts - - $mail_disabled = ((function_exists('imap_open') && (!Config::get('system','imap_disabled'))) ? 0 : 1); - - if (! $mail_disabled) { - if ((! strlen($target_item['allow_cid'])) && (! strlen($target_item['allow_gid'])) - && (! strlen($target_item['deny_cid'])) && (! strlen($target_item['deny_gid'])) - && (intval($target_item['pubmail']))) { - $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s'", - intval($uid), - dbesc(NETWORK_MAIL) - ); - if (DBM::is_result($r)) { - foreach ($r as $rr) { - $recipients[] = $rr['id']; - } - } - } - } - - if ($followup) { - $recip_str = implode(', ', $recipients_followup); - } else { - $recip_str = implode(', ', $recipients); - } - if ($relocate) { - $r = $recipients_relocate; - } else { - $r = q("SELECT `id`, `url`, `network`, `self` FROM `contact` - WHERE `id` IN (%s) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra, - dbesc($recip_str) - ); - } - - // delivery loop - - if (DBM::is_result($r)) { - foreach ($r as $contact) { - if ($contact['self']) { - continue; - } - logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG); - - Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), - 'delivery', $cmd, $item_id, (int)$contact['id']); - } - } - - // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts - // They are especially used for notifications to OStatus users that don't follow us. - - if ($slap && count($url_recipients) && ($public_message || $push_notify) && $normal_mode) { - if (!Config::get('system','dfrn_only')) { - foreach ($url_recipients as $url) { - if ($url) { - logger('notifier: urldelivery: ' . $url); - $deliver_status = slapper($owner,$url,$slap); - /// @TODO Redeliver/queue these items on failure, though there is no contact record - } - } - } - } - - - if ($public_message) { - - $r0 = array(); - $r1 = array(); - - if ($diaspora_delivery) { - if (!$followup) { - $r0 = Diaspora::relay_list(); - } - - $r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network` - FROM `contact` WHERE `network` = '%s' AND `batch` != '' - AND `uid` = %d AND `rel` != %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` GROUP BY `batch`", - dbesc(NETWORK_DIASPORA), - intval($owner['uid']), - intval(CONTACT_IS_SHARING) - ); - } - - $r2 = q("SELECT `id`, `name`,`network` FROM `contact` - WHERE `network` in ('%s', '%s') AND `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `rel` != %d", - dbesc(NETWORK_DFRN), - dbesc(NETWORK_MAIL2), - intval($owner['uid']), - intval(CONTACT_IS_SHARING) - ); - - $r = array_merge($r2,$r1,$r0); - - if (DBM::is_result($r)) { - logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG); - - foreach ($r as $rr) { - - // except for Diaspora batch jobs - // Don't deliver to folks who have already been delivered to - - if (($rr['network'] !== NETWORK_DIASPORA) && (in_array($rr['id'],$conversants))) { - logger('notifier: already delivered id=' . $rr['id']); - continue; - } - - if ((! $mail) && (! $fsuggest) && (! $followup)) { - logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]); - Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), - 'delivery', $cmd, $item_id, (int)$rr['id']); - } - } - } - - $push_notify = true; - - } - - // Notify PuSH subscribers (Used for OStatus distribution of regular posts) - if ($push_notify) { - // Set push flag for PuSH subscribers to this topic, - // they will be notified in queue.php - q("UPDATE `push_subscriber` SET `push` = 1 ". - "WHERE `nickname` = '%s' AND `push` = 0", dbesc($owner['nickname'])); - - logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG); - - // Handling the pubsubhubbub requests - Worker::add(array('priority' => PRIORITY_HIGH, 'created' => $a->queue['created'], 'dont_fork' => true), - 'PubSubPublish'); - } - - logger('notifier: calling hooks', LOGGER_DEBUG); - - if ($normal_mode) { - call_hooks('notifier_normal',$target_item); - } - - call_hooks('notifier_end',$target_item); - - return; -} diff --git a/include/uimport.php b/include/uimport.php index af4f434d4b..e0edb7091d 100644 --- a/include/uimport.php +++ b/include/uimport.php @@ -286,7 +286,7 @@ function import_account(App $a, $file) { } // send relocate messages - Worker::add(PRIORITY_HIGH, 'notifier', 'relocate', $newuid); + Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $newuid); info(t("Done. You can now login with your username and password")); goaway(System::baseUrl() . "/login"); diff --git a/mod/admin.php b/mod/admin.php index cda6d1a3b0..ee456a23f0 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -778,7 +778,7 @@ function admin_page_site_post(App $a) { $users = q("SELECT `uid` FROM `user` WHERE `account_removed` = 0 AND `account_expired` = 0"); foreach ($users as $user) { - Worker::add(PRIORITY_HIGH, 'notifier', 'relocate', $user['uid']); + Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', $user['uid']); } info("Relocation started. Could take a while to complete."); diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index 98bdfbe150..8484ace2cf 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -498,7 +498,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { $i = item_store($arr); if($i) - Worker::add(PRIORITY_HIGH, "notifier", "activity", $i); + Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i); } } } @@ -800,7 +800,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { $i = item_store($arr); if($i) - Worker::add(PRIORITY_HIGH, "notifier", "activity", $i); + Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i); } } diff --git a/mod/events.php b/mod/events.php index b72c8f1884..7a05274e23 100644 --- a/mod/events.php +++ b/mod/events.php @@ -180,7 +180,7 @@ function events_post(App $a) { $item_id = event_store($datarray); if (! $cid) { - Worker::add(PRIORITY_HIGH, "notifier", "event", $item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id); } goaway($_SESSION['return_url']); diff --git a/mod/fsuggest.php b/mod/fsuggest.php index c2d9455b0d..dd698db58e 100644 --- a/mod/fsuggest.php +++ b/mod/fsuggest.php @@ -61,7 +61,7 @@ function fsuggest_post(App $a) { intval($fsuggest_id), intval(local_user()) ); - Worker::add(PRIORITY_HIGH, 'notifier', 'suggest', $fsuggest_id); + Worker::add(PRIORITY_HIGH, 'Notifier', 'suggest', $fsuggest_id); } info( t('Friend suggestion sent.') . EOL); diff --git a/mod/item.php b/mod/item.php index 5f5a96d5e9..0e2e657049 100644 --- a/mod/item.php +++ b/mod/item.php @@ -834,7 +834,7 @@ function item_post(App $a) { // update filetags in pconfig file_tag_update_pconfig($uid,$categories_old,$categories_new,'category'); - Worker::add(PRIORITY_HIGH, "notifier", 'edit_post', $post_id); + Worker::add(PRIORITY_HIGH, "Notifier", 'edit_post', $post_id); if ((x($_REQUEST, 'return')) && strlen($return_path)) { logger('return: ' . $return_path); goaway($return_path); @@ -1067,7 +1067,7 @@ function item_post(App $a) { Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "CreateShadowentry", $post_id); // Call the background process that is delivering the item to the receivers - Worker::add(PRIORITY_HIGH, "notifier", $notify_type, $post_id); + Worker::add(PRIORITY_HIGH, "Notifier", $notify_type, $post_id); logger('post_complete'); diff --git a/mod/mood.php b/mod/mood.php index 084750ef80..bffe37f3be 100644 --- a/mod/mood.php +++ b/mod/mood.php @@ -100,13 +100,13 @@ function mood_init(App $a) { intval($uid), intval($item_id) ); - Worker::add(PRIORITY_HIGH, "notifier", "tag", $item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "tag", $item_id); } call_hooks('post_local_end', $arr); - Worker::add(PRIORITY_HIGH, "notifier", "like", $post_id); + Worker::add(PRIORITY_HIGH, "Notifier", "like", $post_id); return; } diff --git a/mod/photos.php b/mod/photos.php index f18ce38af5..1546bd9a87 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -306,7 +306,7 @@ function photos_post(App $a) { // send the notification upstream/downstream as the case may be if ($rr['visible']) { - Worker::add(PRIORITY_HIGH, "notifier", "drop", $drop_id); + Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id); } } } @@ -383,7 +383,7 @@ function photos_post(App $a) { photo_albums($page_owner_uid, true); if ($i[0]['visible']) { - Worker::add(PRIORITY_HIGH, "notifier", "drop", $drop_id); + Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id); } } } @@ -731,7 +731,7 @@ function photos_post(App $a) { $item_id = item_store($arr); if ($item_id) { - Worker::add(PRIORITY_HIGH, "notifier", "tag", $item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "tag", $item_id); } } } @@ -936,7 +936,7 @@ function photos_post(App $a) { photo_albums($page_owner_uid, true); if ($visible) { - Worker::add(PRIORITY_HIGH, "notifier", 'wall-new', $item_id); + Worker::add(PRIORITY_HIGH, "Notifier", 'wall-new', $item_id); } call_hooks('photo_post_end',intval($item_id)); diff --git a/mod/poke.php b/mod/poke.php index 848ed817d6..2f989dd7d3 100644 --- a/mod/poke.php +++ b/mod/poke.php @@ -139,13 +139,13 @@ function poke_init(App $a) { // intval($uid), // intval($item_id) //); - Worker::add(PRIORITY_HIGH, "notifier", "tag", $item_id); + Worker::add(PRIORITY_HIGH, "Notifier", "tag", $item_id); } call_hooks('post_local_end', $arr); - Worker::add(PRIORITY_HIGH, "notifier", "like", $post_id); + Worker::add(PRIORITY_HIGH, "Notifier", "like", $post_id); return; } diff --git a/mod/profiles.php b/mod/profiles.php index 5a5a649bcf..bbce17c33b 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -600,7 +600,7 @@ function profile_activity($changed, $value) { $i = item_store($arr); if ($i) { - Worker::add(PRIORITY_HIGH, "notifier", "activity", $i); + Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i); } } diff --git a/mod/settings.php b/mod/settings.php index a3ba2ecb91..6a32b7ed0d 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -360,7 +360,7 @@ function settings_post(App $a) { check_form_security_token_redirectOnErr('/settings', 'settings'); if (x($_POST,'resend_relocate')) { - Worker::add(PRIORITY_HIGH, 'notifier', 'relocate', local_user()); + Worker::add(PRIORITY_HIGH, 'Notifier', 'relocate', local_user()); info(t("Relocate message has been send to your contacts")); goaway('settings'); } diff --git a/mod/tagger.php b/mod/tagger.php index c91fb4abaa..c7e8a9469a 100644 --- a/mod/tagger.php +++ b/mod/tagger.php @@ -216,7 +216,7 @@ EOT; call_hooks('post_local_end', $arr); - Worker::add(PRIORITY_HIGH, "notifier", "tag", $post_id); + Worker::add(PRIORITY_HIGH, "Notifier", "tag", $post_id); killme(); diff --git a/mod/videos.php b/mod/videos.php index bea315c590..a46f5de1ab 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -173,7 +173,7 @@ function videos_post(App $a) { $drop_id = intval($i[0]['id']); if ($i[0]['visible']) { - Worker::add(PRIORITY_HIGH, "notifier", "drop", $drop_id); + Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id); } } } diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 88b5bdea89..7d130c1e3a 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -922,7 +922,7 @@ class Worker { * @param (integer|array) priority or parameter array, strings are deprecated and are ignored * * next args are passed as $cmd command line - * or: Worker::add(PRIORITY_HIGH, "notifier", "drop", $drop_id); + * or: Worker::add(PRIORITY_HIGH, "Notifier", "drop", $drop_id); * or: Worker::add(array('priority' => PRIORITY_HIGH, 'dont_fork' => true), "CreateShadowentry", $post_id); * * @note $cmd and string args are surrounded with "" diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index a88d69d563..d4a5efe8d9 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2106,7 +2106,7 @@ class DFRN $changed = true; if ($entrytype == DFRN_REPLY_RC) { - Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $current["id"]); + Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $current["id"]); } } @@ -2752,7 +2752,7 @@ class DFRN if ($posted_id && $parent && ($entrytype == DFRN_REPLY_RC)) { logger("Notifying followers about comment ".$posted_id, LOGGER_DEBUG); - Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $posted_id); + Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $posted_id); } return true; @@ -2940,7 +2940,7 @@ class DFRN if ($entrytype == DFRN_REPLY_RC) { logger("Notifying followers about deletion of post " . $item["id"], LOGGER_DEBUG); - Worker::add(PRIORITY_HIGH, "notifier", "drop", $item["id"]); + Worker::add(PRIORITY_HIGH, "Notifier", "drop", $item["id"]); } } } diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 0c0c3bb2fa..bf58f23e9b 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -1696,7 +1696,7 @@ class Diaspora dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($data))); // notify others - Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $message_id); + Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $message_id); } return true; @@ -2024,7 +2024,7 @@ class Diaspora dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($data))); // notify others - Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $message_id); + Worker::add(PRIORITY_HIGH, "Notifier", "comment-import", $message_id); } return true; @@ -2320,7 +2320,7 @@ class Diaspora $i = item_store($arr); if ($i) { - Worker::add(PRIORITY_HIGH, "notifier", "activity", $i); + Worker::add(PRIORITY_HIGH, "Notifier", "activity", $i); } } } @@ -2768,7 +2768,7 @@ class Diaspora // Now check if the retraction needs to be relayed by us if ($parent["origin"]) { // notify others - Worker::add(PRIORITY_HIGH, "notifier", "drop", $item["id"]); + Worker::add(PRIORITY_HIGH, "Notifier", "drop", $item["id"]); } } diff --git a/include/delivery.php b/src/Worker/Delivery.php similarity index 94% rename from include/delivery.php rename to src/Worker/Delivery.php index 15b97567e2..e450deed10 100644 --- a/include/delivery.php +++ b/src/Worker/Delivery.php @@ -1,7 +1,10 @@ UTC_TIMESTAMP() - INTERVAL 10 MINUTE", + intval($item_id) + ); + $uid = $item_id; + $item_id = 0; + if (! count($items)) { + return; + } + } elseif ($cmd === 'suggest') { + $normal_mode = false; + $fsuggest = true; + + $suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1", + intval($item_id) + ); + if (! count($suggest)) { + return; + } + $uid = $suggest[0]['uid']; + $recipients[] = $suggest[0]['cid']; + $item = $suggest[0]; + } elseif ($cmd === 'removeme') { + $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`, + `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, + `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type`, `user`.`guid` + FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` + WHERE `contact`.`uid` = %d AND `contact`.`self` LIMIT 1", + intval($item_id)); + if (!$r) + return; + + $user = $r[0]; + + $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($item_id)); + if (!$r) + return; + + $self = $r[0]; + + $r = q("SELECT * FROM `contact` WHERE NOT `self` AND `uid` = %d", intval($item_id)); + if (!$r) { + return; + } + require_once 'include/Contact.php'; + foreach ($r as $contact) { + terminate_friendship($user, $self, $contact); + } + return; + } elseif ($cmd === 'relocate') { + $normal_mode = false; + $relocate = true; + $uid = $item_id; + + $recipients_relocate = q("SELECT * FROM `contact` WHERE `uid` = %d AND NOT `self` AND `network` IN ('%s', '%s')", + intval($uid), NETWORK_DFRN, NETWORK_DIASPORA); + } else { + // find ancestors + $r = q("SELECT * FROM `item` WHERE `id` = %d AND visible = 1 AND moderated = 0 LIMIT 1", + intval($item_id) + ); + + if ((! DBM::is_result($r)) || (! intval($r[0]['parent']))) { + return; + } + + $target_item = $r[0]; + $parent_id = intval($r[0]['parent']); + $uid = $r[0]['uid']; + $updated = $r[0]['edited']; + + $items = q("SELECT `item`.*, `sign`.`signed_text`,`sign`.`signature`,`sign`.`signer` + FROM `item` LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` WHERE `parent` = %d AND visible = 1 AND moderated = 0 ORDER BY `id` ASC", + intval($parent_id) + ); + + if (! count($items)) { + return; + } + + // avoid race condition with deleting entries + + if ($items[0]['deleted']) { + foreach ($items as $item) { + $item['deleted'] = 1; + } + } + + if ((count($items) == 1) && ($items[0]['id'] === $target_item['id']) && ($items[0]['uri'] === $items[0]['parent-uri'])) { + logger('notifier: top level post'); + $top_level = true; + } + + } + + $r = q("SELECT `contact`.*, `user`.`pubkey` AS `upubkey`, `user`.`prvkey` AS `uprvkey`, + `user`.`timezone`, `user`.`nickname`, `user`.`sprvkey`, `user`.`spubkey`, + `user`.`page-flags`, `user`.`prvnets`, `user`.`account-type` + FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` + WHERE `contact`.`uid` = %d AND `contact`.`self` = 1 LIMIT 1", + intval($uid) + ); + + if (! DBM::is_result($r)) { + return; + } + + $owner = $r[0]; + + $walltowall = ((($top_level) && ($owner['id'] != $items[0]['contact-id'])) ? true : false); + + // Should the post be transmitted to Diaspora? + $diaspora_delivery = true; + + // If this is a public conversation, notify the feed hub + $public_message = true; + + // Do a PuSH + $push_notify = false; + + // Deliver directly to a forum, don't PuSH + $direct_forum_delivery = false; + + // fill this in with a single salmon slap if applicable + $slap = ''; + + if (! ($mail || $fsuggest || $relocate)) { + + $slap = OStatus::salmon($target_item, $owner); + + require_once 'include/group.php'; + + $parent = $items[0]; + + $thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d", + dbesc($target_item["thr-parent"]), intval($target_item["uid"])); + + logger('GUID: '.$target_item["guid"].': Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG); + + // This is IMPORTANT!!!! + + // We will only send a "notify owner to relay" or followup message if the referenced post + // originated on our system by virtue of having our hostname somewhere + // in the URI, AND it was a comment (not top_level) AND the parent originated elsewhere. + + // if $parent['wall'] == 1 we will already have the parent message in our array + // and we will relay the whole lot. + + // expire sends an entire group of expire messages and cannot be forwarded. + // However the conversation owner will be a part of the conversation and will + // be notified during this run. + // Other DFRN conversation members will be alerted during polled updates. + + + + // Diaspora members currently are not notified of expirations, and other networks have + // either limited or no ability to process deletions. We should at least fix Diaspora + // by stringing togther an array of retractions and sending them onward. + + + $localhost = str_replace('www.','',$a->get_hostname()); + if (strpos($localhost,':')) { + $localhost = substr($localhost,0,strpos($localhost,':')); + } + /** + * + * Be VERY CAREFUL if you make any changes to the following several lines. Seemingly innocuous changes + * have been known to cause runaway conditions which affected several servers, along with + * permissions issues. + * + */ + + $relay_to_owner = false; + + if (!$top_level && ($parent['wall'] == 0) && !$expire && (stristr($target_item['uri'],$localhost))) { + $relay_to_owner = true; + } + + + if (($cmd === 'uplink') && (intval($parent['forum_mode']) == 1) && !$top_level) { + $relay_to_owner = true; + } + + // until the 'origin' flag has been in use for several months + // we will just use it as a fallback test + // later we will be able to use it as the primary test of whether or not to relay. + + if (! $target_item['origin']) { + $relay_to_owner = false; + } + if ($parent['origin']) { + $relay_to_owner = false; + } + + // Special treatment for forum posts + if (($target_item['author-link'] != $target_item['owner-link']) && + ($owner['id'] != $target_item['contact-id']) && + ($target_item['uri'] === $target_item['parent-uri'])) { + + $fields = array('forum', 'prv'); + $condition = array('id' => $target_item['contact-id']); + $contact = dba::select('contact', $fields, $condition, array('limit' => 1)); + if (!DBM::is_result($contact)) { + // Should never happen + return false; + } + + // Is the post from a forum? + if ($contact['forum'] || $contact['prv']) { + $relay_to_owner = true; + $direct_forum_delivery = true; + } + } + if ($relay_to_owner) { + logger('notifier: followup '.$target_item["guid"], LOGGER_DEBUG); + // local followup to remote post + $followup = true; + $public_message = false; // not public + $conversant_str = dbesc($parent['contact-id']); + $recipients = array($parent['contact-id']); + $recipients_followup = array($parent['contact-id']); + + //if (!$target_item['private'] && $target_item['wall'] && + if (!$target_item['private'] && + (strlen($target_item['allow_cid'].$target_item['allow_gid']. + $target_item['deny_cid'].$target_item['deny_gid']) == 0)) + $push_notify = true; + + if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) { + + $push_notify = true; + + if ($parent["network"] == NETWORK_OSTATUS) { + // Distribute the message to the DFRN contacts as if this wasn't a followup since OStatus can't relay comments + // Currently it is work at progress + $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s' AND NOT `blocked` AND NOT `pending` AND NOT `archive`", + intval($uid), + dbesc(NETWORK_DFRN) + ); + if (DBM::is_result($r)) { + foreach ($r as $rr) { + $recipients_followup[] = $rr['id']; + } + } + } + } + + if ($direct_forum_delivery) { + $push_notify = false; + } + + logger("Notify ".$target_item["guid"]." via PuSH: ".($push_notify?"Yes":"No"), LOGGER_DEBUG); + } else { + $followup = false; + + logger('Distributing directly '.$target_item["guid"], LOGGER_DEBUG); + + // don't send deletions onward for other people's stuff + + if ($target_item['deleted'] && (! intval($target_item['wall']))) { + logger('notifier: ignoring delete notification for non-wall item'); + return; + } + + if ((strlen($parent['allow_cid'])) + || (strlen($parent['allow_gid'])) + || (strlen($parent['deny_cid'])) + || (strlen($parent['deny_gid']))) { + $public_message = false; // private recipients, not public + } + + $allow_people = expand_acl($parent['allow_cid']); + $allow_groups = expand_groups(expand_acl($parent['allow_gid']),true); + $deny_people = expand_acl($parent['deny_cid']); + $deny_groups = expand_groups(expand_acl($parent['deny_gid'])); + + // if our parent is a public forum (forum_mode == 1), uplink to the origional author causing + // a delivery fork. private groups (forum_mode == 2) do not uplink + + if ((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) { + Worker::add($a->queue['priority'], 'Notifier', 'uplink', $item_id); + } + + $conversants = array(); + + foreach ($items as $item) { + $recipients[] = $item['contact-id']; + $conversants[] = $item['contact-id']; + // pull out additional tagged people to notify (if public message) + if ($public_message && strlen($item['inform'])) { + $people = explode(',',$item['inform']); + foreach ($people as $person) { + if (substr($person,0,4) === 'cid:') { + $recipients[] = intval(substr($person,4)); + $conversants[] = intval(substr($person,4)); + } else { + $url_recipients[] = substr($person,4); + } + } + } + } + + if (count($url_recipients)) + logger('notifier: '.$target_item["guid"].' url_recipients ' . print_r($url_recipients,true)); + + $conversants = array_unique($conversants); + + + $recipients = array_unique(array_merge($recipients,$allow_people,$allow_groups)); + $deny = array_unique(array_merge($deny_people,$deny_groups)); + $recipients = array_diff($recipients,$deny); + + $conversant_str = dbesc(implode(', ',$conversants)); + } + + // If the thread parent is OStatus then do some magic to distribute the messages. + // We have not only to look at the parent, since it could be a Friendica thread. + if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) { + + $diaspora_delivery = false; + + logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent[0]['author-link']." - Owner: ".$thr_parent[0]['owner-link'], LOGGER_DEBUG); + + // Send a salmon to the parent author + $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''", + dbesc(normalise_link($thr_parent[0]['author-link'])), + intval($uid)); + if (DBM::is_result($r)) { + $probed_contact = $r[0]; + } else { + $probed_contact = Probe::uri($thr_parent[0]['author-link']); + } + + if ($probed_contact["notify"] != "") { + logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]); + $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; + } + + // Send a salmon to the parent owner + $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''", + dbesc(normalise_link($thr_parent[0]['owner-link'])), + intval($uid)); + if (DBM::is_result($r)) { + $probed_contact = $r[0]; + } else { + $probed_contact = Probe::uri($thr_parent[0]['owner-link']); + } + + if ($probed_contact["notify"] != "") { + logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]); + $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; + } + + // Send a salmon notification to every person we mentioned in the post + $arr = explode(',',$target_item['tag']); + foreach ($arr as $x) { + //logger('Checking tag '.$x, LOGGER_DEBUG); + $matches = null; + if (preg_match('/@\[url=([^\]]*)\]/',$x,$matches)) { + $probed_contact = Probe::uri($matches[1]); + if ($probed_contact["notify"] != "") { + logger('Notify mentioned user '.$probed_contact["url"].': '.$probed_contact["notify"]); + $url_recipients[$probed_contact["notify"]] = $probed_contact["notify"]; + } + } + } + + // It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora + $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."')"; + } else { + $sql_extra = " AND `network` IN ('".NETWORK_OSTATUS."', '".NETWORK_DFRN."', '".NETWORK_DIASPORA."', '".NETWORK_MAIL."', '".NETWORK_MAIL2."')"; + } + } else { + $public_message = false; + } + + // If this is a public message and pubmail is set on the parent, include all your email contacts + + $mail_disabled = ((function_exists('imap_open') && (!Config::get('system','imap_disabled'))) ? 0 : 1); + + if (! $mail_disabled) { + if ((! strlen($target_item['allow_cid'])) && (! strlen($target_item['allow_gid'])) + && (! strlen($target_item['deny_cid'])) && (! strlen($target_item['deny_gid'])) + && (intval($target_item['pubmail']))) { + $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `network` = '%s'", + intval($uid), + dbesc(NETWORK_MAIL) + ); + if (DBM::is_result($r)) { + foreach ($r as $rr) { + $recipients[] = $rr['id']; + } + } + } + } + + if ($followup) { + $recip_str = implode(', ', $recipients_followup); + } else { + $recip_str = implode(', ', $recipients); + } + if ($relocate) { + $r = $recipients_relocate; + } else { + $r = q("SELECT `id`, `url`, `network`, `self` FROM `contact` + WHERE `id` IN (%s) AND NOT `blocked` AND NOT `pending` AND NOT `archive`".$sql_extra, + dbesc($recip_str) + ); + } + + // delivery loop + + if (DBM::is_result($r)) { + foreach ($r as $contact) { + if ($contact['self']) { + continue; + } + logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG); + + Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), + 'Delivery', $cmd, $item_id, (int)$contact['id']); + } + } + + // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts + // They are especially used for notifications to OStatus users that don't follow us. + + if ($slap && count($url_recipients) && ($public_message || $push_notify) && $normal_mode) { + if (!Config::get('system','dfrn_only')) { + foreach ($url_recipients as $url) { + if ($url) { + logger('notifier: urldelivery: ' . $url); + $deliver_status = slapper($owner,$url,$slap); + /// @TODO Redeliver/queue these items on failure, though there is no contact record + } + } + } + } + + + if ($public_message) { + + $r0 = array(); + $r1 = array(); + + if ($diaspora_delivery) { + if (!$followup) { + $r0 = Diaspora::relay_list(); + } + + $r1 = q("SELECT `batch`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`name`) AS `name`, ANY_VALUE(`network`) AS `network` + FROM `contact` WHERE `network` = '%s' AND `batch` != '' + AND `uid` = %d AND `rel` != %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` GROUP BY `batch`", + dbesc(NETWORK_DIASPORA), + intval($owner['uid']), + intval(CONTACT_IS_SHARING) + ); + } + + $r2 = q("SELECT `id`, `name`,`network` FROM `contact` + WHERE `network` in ('%s', '%s') AND `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `rel` != %d", + dbesc(NETWORK_DFRN), + dbesc(NETWORK_MAIL2), + intval($owner['uid']), + intval(CONTACT_IS_SHARING) + ); + + $r = array_merge($r2,$r1,$r0); + + if (DBM::is_result($r)) { + logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG); + + foreach ($r as $rr) { + + // except for Diaspora batch jobs + // Don't deliver to folks who have already been delivered to + + if (($rr['network'] !== NETWORK_DIASPORA) && (in_array($rr['id'],$conversants))) { + logger('notifier: already delivered id=' . $rr['id']); + continue; + } + + if ((! $mail) && (! $fsuggest) && (! $followup)) { + logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]); + Worker::add(array('priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true), + 'Delivery', $cmd, $item_id, (int)$rr['id']); + } + } + } + + $push_notify = true; + + } + + // Notify PuSH subscribers (Used for OStatus distribution of regular posts) + if ($push_notify) { + // Set push flag for PuSH subscribers to this topic, + // they will be notified in queue.php + q("UPDATE `push_subscriber` SET `push` = 1 ". + "WHERE `nickname` = '%s' AND `push` = 0", dbesc($owner['nickname'])); + + logger('Activating internal PuSH for item '.$item_id, LOGGER_DEBUG); + + // Handling the pubsubhubbub requests + Worker::add(array('priority' => PRIORITY_HIGH, 'created' => $a->queue['created'], 'dont_fork' => true), + 'PubSubPublish'); + } + + logger('notifier: calling hooks', LOGGER_DEBUG); + + if ($normal_mode) { + call_hooks('notifier_normal',$target_item); + } + + call_hooks('notifier_end',$target_item); + + return; + } +}