2017-11-19 18:59:55 +00:00
< ? php
/**
2020-02-09 15:18:46 +00:00
* @ copyright Copyright ( C ) 2020 , Friendica
*
* @ license GNU AGPL version 3 or any later version
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < https :// www . gnu . org / licenses />.
*
2017-11-19 18:59:55 +00:00
*/
2020-02-09 15:18:46 +00:00
2017-11-19 18:59:55 +00:00
namespace Friendica\Worker ;
2018-10-21 05:15:02 +00:00
use Friendica\Core\Hook ;
2018-10-29 21:20:46 +00:00
use Friendica\Core\Logger ;
2018-08-11 20:40:44 +00:00
use Friendica\Core\Protocol ;
2017-11-19 18:59:55 +00:00
use Friendica\Core\Worker ;
2018-07-20 12:19:26 +00:00
use Friendica\Database\DBA ;
2019-12-15 21:34:11 +00:00
use Friendica\DI ;
2019-01-30 19:33:08 +00:00
use Friendica\Model\APContact ;
2017-12-07 14:04:24 +00:00
use Friendica\Model\Contact ;
2018-10-21 05:15:02 +00:00
use Friendica\Model\Conversation ;
2017-12-09 18:45:17 +00:00
use Friendica\Model\Group ;
2018-06-17 21:35:33 +00:00
use Friendica\Model\Item ;
2020-05-02 19:34:02 +00:00
use Friendica\Model\Post ;
2018-05-17 23:30:49 +00:00
use Friendica\Model\PushSubscriber ;
2020-05-05 05:11:59 +00:00
use Friendica\Model\Tag ;
2018-07-20 02:15:21 +00:00
use Friendica\Model\User ;
2017-11-19 18:59:55 +00:00
use Friendica\Network\Probe ;
2018-09-17 21:13:08 +00:00
use Friendica\Protocol\ActivityPub ;
2017-11-19 18:59:55 +00:00
use Friendica\Protocol\Diaspora ;
use Friendica\Protocol\OStatus ;
2017-12-02 14:32:45 +00:00
use Friendica\Protocol\Salmon ;
2017-11-19 18:59:55 +00:00
/*
* The notifier is typically called with :
*
* Worker :: add ( PRIORITY_HIGH , " Notifier " , COMMAND , ITEM_ID );
*
2019-06-10 14:19:24 +00:00
* where COMMAND is one of the constants that are defined in Worker / Delivery . php
2017-11-19 18:59:55 +00:00
* and ITEM_ID is the id of the item in the database that needs to be sent to others .
*/
2018-07-10 02:39:59 +00:00
class Notifier
{
2018-12-05 04:49:48 +00:00
public static function execute ( $cmd , $target_id )
2018-07-10 02:39:59 +00:00
{
2019-12-15 21:34:11 +00:00
$a = DI :: app ();
2017-11-19 18:59:55 +00:00
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Invoked' , [ 'cmd' => $cmd , 'target' => $target_id ]);
2017-11-19 18:59:55 +00:00
$top_level = false ;
2018-01-15 13:05:12 +00:00
$recipients = [];
$url_recipients = [];
2017-11-19 18:59:55 +00:00
2018-12-05 05:35:52 +00:00
$delivery_contacts_stmt = null ;
2018-12-05 04:49:48 +00:00
$target_item = [];
2019-11-22 08:01:23 +00:00
$parent = [];
$thr_parent = [];
2018-12-05 04:49:48 +00:00
$items = [];
2018-12-07 05:52:14 +00:00
$delivery_queue_count = 0 ;
2017-11-19 18:59:55 +00:00
2018-05-01 06:37:12 +00:00
if ( $cmd == Delivery :: MAIL ) {
2018-12-05 04:49:48 +00:00
$message = DBA :: selectFirst ( 'mail' , [ 'uid' , 'contact-id' ], [ 'id' => $target_id ]);
2018-07-21 12:46:04 +00:00
if ( ! DBA :: isResult ( $message )) {
2017-11-19 18:59:55 +00:00
return ;
}
2018-05-01 06:37:12 +00:00
$uid = $message [ 'uid' ];
$recipients [] = $message [ 'contact-id' ];
2019-05-14 17:50:45 +00:00
$mail = ActivityPub\Transmitter :: ItemArrayFromMail ( $target_id );
2019-05-18 09:09:13 +00:00
$inboxes = ActivityPub\Transmitter :: fetchTargetInboxes ( $mail , $uid , true );
2019-05-14 17:50:45 +00:00
foreach ( $inboxes as $inbox ) {
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Delivery via ActivityPub' , [ 'cmd' => $cmd , 'target' => $target_id , 'inbox' => $inbox ]);
2019-05-14 17:50:45 +00:00
Worker :: add ([ 'priority' => PRIORITY_HIGH , 'created' => $a -> queue [ 'created' ], 'dont_fork' => true ],
'APDelivery' , $cmd , $target_id , $inbox , $uid );
}
2018-05-01 06:37:12 +00:00
} elseif ( $cmd == Delivery :: SUGGESTION ) {
2020-01-31 22:50:46 +00:00
$suggest = DI :: fsuggest () -> getById ( $target_id );
$uid = $suggest -> uid ;
$recipients [] = $suggest -> cid ;
2018-05-01 06:37:12 +00:00
} elseif ( $cmd == Delivery :: REMOVAL ) {
2018-12-05 05:06:48 +00:00
return self :: notifySelfRemoval ( $target_id , $a -> queue [ 'priority' ], $a -> queue [ 'created' ]);
2018-05-01 06:37:12 +00:00
} elseif ( $cmd == Delivery :: RELOCATION ) {
2018-12-05 04:49:48 +00:00
$uid = $target_id ;
2017-11-19 18:59:55 +00:00
2018-12-05 05:35:52 +00:00
$condition = [ 'uid' => $target_id , 'self' => false , 'network' => [ Protocol :: DFRN , Protocol :: DIASPORA ]];
2019-10-06 21:59:23 +00:00
$delivery_contacts_stmt = DBA :: select ( 'contact' , [ 'id' , 'url' , 'addr' , 'network' , 'protocol' , 'batch' ], $condition );
2017-11-19 18:59:55 +00:00
} else {
// find ancestors
2018-12-05 04:49:48 +00:00
$condition = [ 'id' => $target_id , 'visible' => true , 'moderated' => false ];
2018-06-17 21:35:33 +00:00
$target_item = Item :: selectFirst ([], $condition );
2017-11-19 18:59:55 +00:00
2018-07-21 12:46:04 +00:00
if ( ! DBA :: isResult ( $target_item ) || ! intval ( $target_item [ 'parent' ])) {
2019-10-06 21:59:23 +00:00
Logger :: info ( 'No target item' , [ 'cmd' => $cmd , 'target' => $target_id ]);
2017-11-19 18:59:55 +00:00
return ;
}
2019-01-17 23:06:27 +00:00
if ( ! empty ( $target_item [ 'contact-uid' ])) {
$uid = $target_item [ 'contact-uid' ];
} elseif ( ! empty ( $target_item [ 'uid' ])) {
$uid = $target_item [ 'uid' ];
} else {
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Only public users, quitting' , [ 'target' => $target_id ]);
2019-01-17 23:06:27 +00:00
return ;
}
2018-12-05 04:49:48 +00:00
$condition = [ 'parent' => $target_item [ 'parent' ], 'visible' => true , 'moderated' => false ];
2018-06-17 21:35:33 +00:00
$params = [ 'order' => [ 'id' ]];
2018-12-05 04:49:48 +00:00
$items_stmt = Item :: select ([], $condition , $params );
if ( ! DBA :: isResult ( $items_stmt )) {
2019-10-06 21:59:23 +00:00
Logger :: info ( 'No item found' , [ 'cmd' => $cmd , 'target' => $target_id ]);
2017-11-19 18:59:55 +00:00
return ;
}
2018-12-05 04:49:48 +00:00
$items = Item :: inArray ( $items_stmt );
2018-06-17 21:35:33 +00:00
2017-11-19 18:59:55 +00:00
// 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' ])) {
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Top level post' , [ 'target' => $target_id ]);
2017-11-19 18:59:55 +00:00
$top_level = true ;
}
}
2017-12-19 23:12:37 +00:00
$owner = User :: getOwnerDataById ( $uid );
if ( ! $owner ) {
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Owner not found' , [ 'cmd' => $cmd , 'target' => $target_id ]);
2017-11-19 18:59:55 +00:00
return ;
}
// Should the post be transmitted to Diaspora?
$diaspora_delivery = true ;
// If this is a public conversation, notify the feed hub
$public_message = true ;
2020-03-02 07:57:23 +00:00
$unlisted = false ;
2017-11-19 18:59:55 +00:00
// Do a PuSH
$push_notify = false ;
// Deliver directly to a forum, don't PuSH
$direct_forum_delivery = false ;
2018-02-14 05:05:00 +00:00
$followup = false ;
$recipients_followup = [];
2017-11-19 18:59:55 +00:00
2018-12-05 04:49:48 +00:00
if ( ! empty ( $target_item ) && ! empty ( $items )) {
2017-11-19 18:59:55 +00:00
$parent = $items [ 0 ];
2020-06-27 15:10:06 +00:00
$fields = [ 'network' , 'author-id' , 'author-link' , 'author-network' , 'owner-id' ];
2018-06-03 08:36:05 +00:00
$condition = [ 'uri' => $target_item [ " thr-parent " ], 'uid' => $target_item [ " uid " ]];
2018-07-07 18:14:16 +00:00
$thr_parent = Item :: selectFirst ( $fields , $condition );
2019-10-30 06:50:20 +00:00
if ( empty ( $thr_parent )) {
$thr_parent = $parent ;
}
2017-11-19 18:59:55 +00:00
2018-11-05 20:35:17 +00:00
Logger :: log ( 'GUID: ' . $target_item [ " guid " ] . ': Parent is ' . $parent [ 'network' ] . '. Thread parent is ' . $thr_parent [ 'network' ], Logger :: DEBUG );
2017-11-19 18:59:55 +00:00
2019-10-06 21:59:23 +00:00
if ( ! self :: isRemovalActivity ( $cmd , $owner , Protocol :: ACTIVITYPUB )) {
$delivery_queue_count += self :: activityPubDelivery ( $cmd , $target_item , $parent , $thr_parent , $a -> queue [ 'priority' ], $a -> queue [ 'created' ], $owner );
}
2019-07-28 19:13:17 +00:00
// Only deliver threaded replies (comment to a comment) to Diaspora
// when the original comment author does support the Diaspora protocol.
if ( $target_item [ 'parent-uri' ] != $target_item [ 'thr-parent' ]) {
$diaspora_delivery = Diaspora :: isSupportedByContactUrl ( $thr_parent [ 'author-link' ]);
Logger :: info ( 'Threaded comment' , [ 'diaspora_delivery' => ( int ) $diaspora_delivery ]);
}
2020-03-02 07:57:23 +00:00
$unlisted = $target_item [ 'private' ] == Item :: UNLISTED ;
2017-11-19 18:59:55 +00:00
// 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.
2019-12-15 23:47:24 +00:00
$localhost = str_replace ( 'www.' , '' , DI :: baseUrl () -> getHostname ());
2017-11-19 18:59:55 +00:00
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 ;
2018-01-17 23:22:01 +00:00
if ( ! $top_level && ( $parent [ 'wall' ] == 0 ) && ( stristr ( $target_item [ 'uri' ], $localhost ))) {
2017-11-19 18:59:55 +00:00
$relay_to_owner = true ;
}
2019-06-10 14:19:24 +00:00
if (( $cmd === Delivery :: UPLINK ) && ( intval ( $parent [ 'forum_mode' ]) == 1 ) && ! $top_level ) {
2017-11-19 18:59:55 +00:00
$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.
2017-12-19 23:12:37 +00:00
if ( ! $target_item [ 'origin' ]) {
2017-11-19 18:59:55 +00:00
$relay_to_owner = false ;
}
if ( $parent [ 'origin' ]) {
$relay_to_owner = false ;
}
// Special treatment for forum posts
2019-03-14 18:44:41 +00:00
if ( Item :: isForumPost ( $target_item , $owner )) {
2018-09-01 03:23:12 +00:00
$relay_to_owner = true ;
$direct_forum_delivery = true ;
}
2017-11-19 18:59:55 +00:00
2018-09-01 03:23:12 +00:00
// Avoid that comments in a forum thread are sent to OStatus
2019-03-14 18:44:41 +00:00
if ( Item :: isForumPost ( $parent , $owner )) {
2018-09-01 03:23:12 +00:00
$direct_forum_delivery = true ;
2017-11-19 18:59:55 +00:00
}
2018-09-01 03:23:12 +00:00
2017-11-19 18:59:55 +00:00
if ( $relay_to_owner ) {
// local followup to remote post
$followup = true ;
$public_message = false ; // not public
2018-01-15 13:05:12 +00:00
$recipients = [ $parent [ 'contact-id' ]];
$recipients_followup = [ $parent [ 'contact-id' ]];
2017-11-19 18:59:55 +00:00
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Followup' , [ 'target' => $target_id , 'guid' => $target_item [ 'guid' ], 'to' => $parent [ 'contact-id' ]]);
2017-12-27 21:51:16 +00:00
2020-03-02 07:57:23 +00:00
if (( $target_item [ 'private' ] != Item :: PRIVATE ) &&
2017-11-19 18:59:55 +00:00
( strlen ( $target_item [ 'allow_cid' ] . $target_item [ 'allow_gid' ] .
$target_item [ 'deny_cid' ] . $target_item [ 'deny_gid' ]) == 0 ))
$push_notify = true ;
2018-08-11 20:40:44 +00:00
if (( $thr_parent && ( $thr_parent [ 'network' ] == Protocol :: OSTATUS )) || ( $parent [ 'network' ] == Protocol :: OSTATUS )) {
2017-11-19 18:59:55 +00:00
$push_notify = true ;
2018-08-11 20:40:44 +00:00
if ( $parent [ " network " ] == Protocol :: OSTATUS ) {
2017-11-19 18:59:55 +00:00
// 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
2018-12-05 05:35:52 +00:00
$condition = [ 'uid' => $uid , 'network' => Protocol :: DFRN , 'blocked' => false , 'pending' => false , 'archive' => false ];
$followup_contacts_stmt = DBA :: select ( 'contact' , [ 'id' ], $condition );
while ( $followup_contact = DBA :: fetch ( $followup_contacts_stmt )) {
$recipients_followup [] = $followup_contact [ 'id' ];
2017-11-19 18:59:55 +00:00
}
2018-12-05 05:35:52 +00:00
DBA :: close ( $followup_contacts_stmt );
2017-11-19 18:59:55 +00:00
}
}
if ( $direct_forum_delivery ) {
$push_notify = false ;
}
2018-11-05 20:35:17 +00:00
Logger :: log ( 'Notify ' . $target_item [ " guid " ] . ' via PuSH: ' . ( $push_notify ? " Yes " : " No " ), Logger :: DEBUG );
2017-11-19 18:59:55 +00:00
} else {
$followup = false ;
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Distributing directly' , [ 'target' => $target_id , 'guid' => $target_item [ 'guid' ]]);
2017-11-19 18:59:55 +00:00
// don't send deletions onward for other people's stuff
2017-12-19 23:12:37 +00:00
if ( $target_item [ 'deleted' ] && ! intval ( $target_item [ 'wall' ])) {
2018-11-05 20:35:17 +00:00
Logger :: log ( 'Ignoring delete notification for non-wall item' );
2017-11-19 18:59:55 +00:00
return ;
}
2017-12-19 23:12:37 +00:00
if ( strlen ( $parent [ 'allow_cid' ])
|| strlen ( $parent [ 'allow_gid' ])
|| strlen ( $parent [ 'deny_cid' ])
|| strlen ( $parent [ 'deny_gid' ])) {
2017-11-19 18:59:55 +00:00
$public_message = false ; // private recipients, not public
}
2019-12-15 22:28:01 +00:00
$aclFormatter = DI :: aclFormatter ();
2019-10-22 22:40:14 +00:00
2019-11-01 13:13:29 +00:00
$allow_people = $aclFormatter -> expand ( $parent [ 'allow_cid' ]);
$allow_groups = Group :: expand ( $uid , $aclFormatter -> expand ( $parent [ 'allow_gid' ]), true );
$deny_people = $aclFormatter -> expand ( $parent [ 'deny_cid' ]);
$deny_groups = Group :: expand ( $uid , $aclFormatter -> expand ( $parent [ 'deny_gid' ]));
2017-11-19 18:59:55 +00:00
// 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
2019-06-10 14:19:24 +00:00
if (( intval ( $parent [ 'forum_mode' ]) == 1 ) && ! $top_level && ( $cmd !== Delivery :: UPLINK )) {
Worker :: add ( $a -> queue [ 'priority' ], 'Notifier' , Delivery :: UPLINK , $target_id );
2017-11-19 18:59:55 +00:00
}
foreach ( $items as $item ) {
$recipients [] = $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 ));
} else {
$url_recipients [] = substr ( $person , 4 );
}
}
}
}
2017-12-19 23:12:37 +00:00
if ( count ( $url_recipients )) {
2019-10-06 21:59:23 +00:00
Logger :: notice ( 'Deliver' , [ 'target' => $target_id , 'guid' => $target_item [ 'guid' ], 'recipients' => $url_recipients ]);
2017-12-19 23:12:37 +00:00
}
2017-11-19 18:59:55 +00:00
2018-11-04 23:17:41 +00:00
$recipients = array_unique ( array_merge ( $recipients , $allow_people , $allow_groups ));
$deny = array_unique ( array_merge ( $deny_people , $deny_groups ));
$recipients = array_diff ( $recipients , $deny );
2018-12-06 03:23:24 +00:00
// If this is a public message and pubmail is set on the parent, include all your email contacts
if (
function_exists ( 'imap_open' )
2020-01-19 20:21:13 +00:00
&& ! DI :: config () -> get ( 'system' , 'imap_disabled' )
2018-12-06 03:23:24 +00:00
&& $public_message
&& intval ( $target_item [ 'pubmail' ])
) {
$mail_contacts_stmt = DBA :: select ( 'contact' , [ 'id' ], [ 'uid' => $uid , 'network' => Protocol :: MAIL ]);
while ( $mail_contact = DBA :: fetch ( $mail_contacts_stmt )) {
$recipients [] = $mail_contact [ 'id' ];
}
DBA :: close ( $mail_contacts_stmt );
}
2017-11-19 18:59:55 +00:00
}
// 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.
2018-08-11 20:40:44 +00:00
if (( $thr_parent && ( $thr_parent [ 'network' ] == Protocol :: OSTATUS )) || ( $parent [ 'network' ] == Protocol :: OSTATUS )) {
2017-11-19 18:59:55 +00:00
$diaspora_delivery = false ;
2018-10-30 13:58:45 +00:00
Logger :: log ( 'Some parent is OStatus for ' . $target_item [ " guid " ] . " - Author: " . $thr_parent [ 'author-id' ] . " - Owner: " . $thr_parent [ 'owner-id' ], Logger :: DEBUG );
2017-11-19 18:59:55 +00:00
// Send a salmon to the parent author
2018-07-20 12:19:26 +00:00
$probed_contact = DBA :: selectFirst ( 'contact' , [ 'url' , 'notify' ], [ 'id' => $thr_parent [ 'author-id' ]]);
2018-07-21 12:46:04 +00:00
if ( DBA :: isResult ( $probed_contact ) && ! empty ( $probed_contact [ " notify " ])) {
2020-07-16 10:22:14 +00:00
Logger :: notice ( 'Notify parent author' , [ 'url' => $probed_contact [ " url " ], 'notify' => $probed_contact [ " notify " ]]);
2017-11-19 18:59:55 +00:00
$url_recipients [ $probed_contact [ " notify " ]] = $probed_contact [ " notify " ];
}
// Send a salmon to the parent owner
2018-07-20 12:19:26 +00:00
$probed_contact = DBA :: selectFirst ( 'contact' , [ 'url' , 'notify' ], [ 'id' => $thr_parent [ 'owner-id' ]]);
2018-07-21 12:46:04 +00:00
if ( DBA :: isResult ( $probed_contact ) && ! empty ( $probed_contact [ " notify " ])) {
2020-07-16 10:22:14 +00:00
Logger :: notice ( 'Notify parent owner' , [ 'url' => $probed_contact [ " url " ], 'notify' => $probed_contact [ " notify " ]]);
2017-11-19 18:59:55 +00:00
$url_recipients [ $probed_contact [ " notify " ]] = $probed_contact [ " notify " ];
}
// Send a salmon notification to every person we mentioned in the post
2020-05-05 05:11:59 +00:00
foreach ( Tag :: getByURIId ( $target_item [ 'uri-id' ], [ Tag :: MENTION , Tag :: EXCLUSIVE_MENTION , Tag :: IMPLICIT_MENTION ]) as $tag ) {
2020-07-16 10:22:14 +00:00
$probed_contact = Contact :: getByURL ( $tag [ 'url' ]);
if ( ! empty ( $probed_contact [ 'notify' ])) {
Logger :: notice ( 'Notify mentioned user' , [ 'url' => $probed_contact [ " url " ], 'notify' => $probed_contact [ " notify " ]]);
$url_recipients [ $probed_contact [ 'notify' ]] = $probed_contact [ 'notify' ];
2017-11-19 18:59:55 +00:00
}
}
// It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora
2019-07-28 19:13:17 +00:00
$networks = [ Protocol :: DFRN ];
} elseif ( $diaspora_delivery ) {
$networks = [ Protocol :: DFRN , Protocol :: DIASPORA , Protocol :: MAIL ];
2019-10-06 21:59:23 +00:00
if (( $parent [ 'network' ] == Protocol :: DIASPORA ) || ( $thr_parent [ 'network' ] == Protocol :: DIASPORA )) {
Logger :: info ( 'Add AP contacts' , [ 'target' => $target_id , 'guid' => $target_item [ 'guid' ]]);
$networks [] = Protocol :: ACTIVITYPUB ;
}
2017-11-19 18:59:55 +00:00
} else {
2019-07-28 19:13:17 +00:00
$networks = [ Protocol :: DFRN , Protocol :: MAIL ];
2017-11-19 18:59:55 +00:00
}
} else {
$public_message = false ;
}
2018-12-05 05:35:52 +00:00
if ( empty ( $delivery_contacts_stmt )) {
2018-05-01 06:37:12 +00:00
if ( $followup ) {
$recipients = $recipients_followup ;
}
$condition = [ 'id' => $recipients , 'self' => false ,
'blocked' => false , 'pending' => false , 'archive' => false ];
if ( ! empty ( $networks )) {
$condition [ 'network' ] = $networks ;
}
2019-10-06 21:59:23 +00:00
$delivery_contacts_stmt = DBA :: select ( 'contact' , [ 'id' , 'addr' , 'url' , 'network' , 'protocol' , 'batch' ], $condition );
2017-11-19 18:59:55 +00:00
}
2018-11-04 23:17:41 +00:00
$conversants = [];
$batch_delivery = false ;
2017-11-19 18:59:55 +00:00
2018-11-04 23:17:41 +00:00
if ( $public_message && ! in_array ( $cmd , [ Delivery :: MAIL , Delivery :: SUGGESTION ]) && ! $followup ) {
2018-12-05 05:35:52 +00:00
$relay_list = [];
2017-11-19 18:59:55 +00:00
2020-03-02 07:57:23 +00:00
if ( $diaspora_delivery && ! $unlisted ) {
2018-11-04 23:17:41 +00:00
$batch_delivery = true ;
2018-12-05 05:35:52 +00:00
$relay_list_stmt = DBA :: p (
" SELECT
2019-05-11 05:58:22 +00:00
`batch` ,
ANY_VALUE ( `id` ) AS `id` ,
2019-10-31 07:33:25 +00:00
ANY_VALUE ( `url` ) AS `url` ,
2019-05-11 05:58:22 +00:00
ANY_VALUE ( `name` ) AS `name` ,
ANY_VALUE ( `network` ) AS `network` ,
ANY_VALUE ( `protocol` ) AS `protocol`
2018-12-05 05:35:52 +00:00
FROM `contact`
WHERE `network` = ?
AND `batch` != ''
AND `uid` = ?
AND `rel` != ?
AND NOT `blocked`
AND NOT `pending`
AND NOT `archive`
GROUP BY `batch` " ,
Protocol :: DIASPORA ,
$owner [ 'uid' ],
Contact :: SHARING
2017-11-19 18:59:55 +00:00
);
2018-12-05 05:35:52 +00:00
$relay_list = DBA :: toArray ( $relay_list_stmt );
2018-01-12 20:52:43 +00:00
// Fetch the participation list
// The function will ensure that there are no duplicates
2020-05-06 15:20:49 +00:00
$relay_list = Diaspora :: participantsForThread ( $target_item , $relay_list );
2018-01-12 20:52:43 +00:00
2019-01-19 12:30:16 +00:00
// Add the relay to the list, avoid duplicates.
// Don't send community posts to the relay. Forum posts via the Diaspora protocol are looking ugly.
2019-03-14 18:44:41 +00:00
if ( ! $followup && ! Item :: isForumPost ( $target_item , $owner )) {
2018-12-05 05:35:52 +00:00
$relay_list = Diaspora :: relayList ( $target_id , $relay_list );
2018-04-11 19:01:25 +00:00
}
2017-11-19 18:59:55 +00:00
}
2018-09-17 21:13:08 +00:00
$condition = [ 'network' => Protocol :: DFRN , 'uid' => $owner [ 'uid' ], 'blocked' => false ,
2018-07-25 02:53:46 +00:00
'pending' => false , 'archive' => false , 'rel' => [ Contact :: FOLLOWER , Contact :: FRIEND ]];
2019-10-06 21:59:23 +00:00
$r2 = DBA :: toArray ( DBA :: select ( 'contact' , [ 'id' , 'url' , 'addr' , 'name' , 'network' , 'protocol' ], $condition ));
2018-01-12 20:52:43 +00:00
2018-12-05 05:35:52 +00:00
$r = array_merge ( $r2 , $relay_list );
2017-11-19 18:59:55 +00:00
2018-07-21 12:46:04 +00:00
if ( DBA :: isResult ( $r )) {
2017-11-19 18:59:55 +00:00
foreach ( $r as $rr ) {
2020-01-11 18:25:48 +00:00
// Ensure that local contacts are delivered via DFRN
if ( Contact :: isLocal ( $rr [ 'url' ])) {
2020-01-11 18:28:04 +00:00
$contact [ 'network' ] = Protocol :: DFRN ;
2020-01-11 18:25:48 +00:00
}
2019-10-06 21:59:23 +00:00
if ( ! empty ( $rr [ 'addr' ]) && ( $rr [ 'network' ] == Protocol :: ACTIVITYPUB ) && ! DBA :: exists ( 'fcontact' , [ 'addr' => $rr [ 'addr' ]])) {
2020-06-27 12:18:36 +00:00
Logger :: info ( 'Contact is AP omly, so skip delivery via legacy DFRN/Diaspora' , [ 'target' => $target_id , 'contact' => $rr [ 'url' ]]);
2019-10-06 21:59:23 +00:00
continue ;
}
2019-08-27 19:01:11 +00:00
if ( ! empty ( $rr [ 'id' ]) && Contact :: isArchived ( $rr [ 'id' ])) {
2020-06-27 12:18:36 +00:00
Logger :: info ( 'Contact is archived, so skip delivery' , [ 'target' => $target_id , 'contact' => $rr [ 'url' ]]);
2019-08-27 19:01:11 +00:00
continue ;
}
2019-02-11 20:30:08 +00:00
if ( self :: isRemovalActivity ( $cmd , $owner , $rr [ 'network' ])) {
2020-06-27 12:18:36 +00:00
Logger :: info ( 'Contact does no supports account removal commands, so skip delivery' , [ 'target' => $target_id , 'contact' => $rr [ 'url' ]]);
2019-02-11 20:30:08 +00:00
continue ;
}
2019-10-06 21:59:23 +00:00
if ( self :: skipDFRN ( $rr , $target_item , $parent , $thr_parent , $cmd )) {
Logger :: info ( 'Contact can be delivered via AP, so skip delivery via legacy DFRN/Diaspora' , [ 'id' => $target_id , 'url' => $rr [ 'url' ]]);
2019-01-30 19:33:08 +00:00
continue ;
}
2020-06-27 12:18:36 +00:00
if ( self :: skipActivityPubForDiaspora ( $rr , $target_item , $thr_parent )) {
Logger :: info ( 'Contact is from Diaspora, but the replied author is from ActivityPub, so skip delivery via Diaspora' , [ 'id' => $target_id , 'url' => $rr [ 'url' ]]);
continue ;
}
2018-11-04 23:17:41 +00:00
$conversants [] = $rr [ 'id' ];
2018-12-07 05:52:14 +00:00
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Public delivery' , [ 'target' => $target_id , 'guid' => $target_item [ " guid " ], 'to' => $rr ]);
2019-01-19 12:30:16 +00:00
// Ensure that posts with our own protocol arrives before Diaspora posts arrive.
// Situation is that sometimes Friendica servers receive Friendica posts over the Diaspora protocol first.
// The conversion in Markdown reduces the formatting, so these posts should arrive after the Friendica posts.
2019-03-08 05:53:36 +00:00
// This is only important for high and medium priority tasks and not for Low priority jobs like deletions.
if (( $rr [ 'network' ] == Protocol :: DIASPORA ) && in_array ( $a -> queue [ 'priority' ], [ PRIORITY_HIGH , PRIORITY_MEDIUM ])) {
2019-01-19 12:30:16 +00:00
$deliver_options = [ 'priority' => $a -> queue [ 'priority' ], 'dont_fork' => true ];
} else {
$deliver_options = [ 'priority' => $a -> queue [ 'priority' ], 'created' => $a -> queue [ 'created' ], 'dont_fork' => true ];
}
2019-09-02 03:25:05 +00:00
if ( Worker :: add ( $deliver_options , 'Delivery' , $cmd , $target_id , ( int ) $rr [ 'id' ])) {
$delivery_queue_count ++ ;
}
2018-11-04 23:17:41 +00:00
}
}
2017-11-19 18:59:55 +00:00
2018-11-04 23:17:41 +00:00
$push_notify = true ;
}
2017-11-19 18:59:55 +00:00
2018-11-04 23:17:41 +00:00
// delivery loop
2018-12-05 05:35:52 +00:00
while ( $contact = DBA :: fetch ( $delivery_contacts_stmt )) {
2020-01-11 18:25:48 +00:00
// Ensure that local contacts are delivered via DFRN
if ( Contact :: isLocal ( $contact [ 'url' ])) {
2020-01-11 18:28:04 +00:00
$contact [ 'network' ] = Protocol :: DFRN ;
2020-01-11 18:25:48 +00:00
}
2019-10-06 21:59:23 +00:00
if ( ! empty ( $contact [ 'addr' ]) && ( $contact [ 'network' ] == Protocol :: ACTIVITYPUB ) && ! DBA :: exists ( 'fcontact' , [ 'addr' => $contact [ 'addr' ]])) {
2020-06-27 12:18:36 +00:00
Logger :: info ( 'Contact is AP omly, so skip delivery via legacy DFRN/Diaspora' , [ 'target' => $target_id , 'contact' => $contact [ 'url' ]]);
2019-10-06 21:59:23 +00:00
continue ;
}
2019-08-27 19:01:11 +00:00
if ( ! empty ( $contact [ 'id' ]) && Contact :: isArchived ( $contact [ 'id' ])) {
2020-06-27 12:18:36 +00:00
Logger :: info ( 'Contact is archived, so skip delivery' , [ 'target' => $target_id , 'contact' => $contact [ 'url' ]]);
2019-08-27 19:01:11 +00:00
continue ;
}
2019-02-11 20:30:08 +00:00
if ( self :: isRemovalActivity ( $cmd , $owner , $contact [ 'network' ])) {
2020-06-27 12:18:36 +00:00
Logger :: info ( 'Contact does no supports account removal commands, so skip delivery' , [ 'target' => $target_id , 'contact' => $contact [ 'url' ]]);
2019-02-11 20:30:08 +00:00
continue ;
}
2019-10-06 21:59:23 +00:00
if ( self :: skipDFRN ( $contact , $target_item , $parent , $thr_parent , $cmd )) {
2019-10-30 09:44:07 +00:00
Logger :: info ( 'Contact can be delivered via AP, so skip delivery via legacy DFRN/Diaspora' , [ 'target' => $target_id , 'url' => $contact [ 'url' ]]);
2019-01-30 19:33:08 +00:00
continue ;
}
2020-06-27 12:18:36 +00:00
if ( self :: skipActivityPubForDiaspora ( $contact , $target_item , $thr_parent )) {
Logger :: info ( 'Contact is from Diaspora, but the replied author is from ActivityPub, so skip delivery via Diaspora' , [ 'id' => $target_id , 'url' => $rr [ 'url' ]]);
continue ;
}
2018-12-05 05:35:52 +00:00
// Don't deliver to Diaspora if it already had been done as batch delivery
if (( $contact [ 'network' ] == Protocol :: DIASPORA ) && $batch_delivery ) {
Logger :: log ( 'Already delivered id ' . $target_id . ' via batch to ' . json_encode ( $contact ), Logger :: DEBUG );
continue ;
}
2018-11-04 23:17:41 +00:00
2018-12-05 05:35:52 +00:00
// Don't deliver to folks who have already been delivered to
if ( in_array ( $contact [ 'id' ], $conversants )) {
Logger :: log ( 'Already delivered id ' . $target_id . ' to ' . json_encode ( $contact ), Logger :: DEBUG );
continue ;
}
2018-11-04 23:17:41 +00:00
2019-10-06 21:59:23 +00:00
Logger :: info ( 'Delivery' , [ 'id' => $target_id , 'to' => $contact ]);
2019-01-19 12:30:16 +00:00
2018-12-05 05:35:52 +00:00
// Ensure that posts with our own protocol arrives before Diaspora posts arrive.
// Situation is that sometimes Friendica servers receive Friendica posts over the Diaspora protocol first.
// The conversion in Markdown reduces the formatting, so these posts should arrive after the Friendica posts.
if ( $contact [ 'network' ] == Protocol :: DIASPORA ) {
$deliver_options = [ 'priority' => $a -> queue [ 'priority' ], 'dont_fork' => true ];
} else {
$deliver_options = [ 'priority' => $a -> queue [ 'priority' ], 'created' => $a -> queue [ 'created' ], 'dont_fork' => true ];
2017-11-19 18:59:55 +00:00
}
2019-09-02 03:25:05 +00:00
if ( Worker :: add ( $deliver_options , 'Delivery' , $cmd , $target_id , ( int ) $contact [ 'id' ])) {
$delivery_queue_count ++ ;
}
2018-11-04 23:17:41 +00:00
}
2018-12-05 05:35:52 +00:00
DBA :: close ( $delivery_contacts_stmt );
2017-11-19 18:59:55 +00:00
2018-12-06 03:23:24 +00:00
$url_recipients = array_filter ( $url_recipients );
2018-11-04 23:17:41 +00:00
// 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.
2020-01-19 20:21:13 +00:00
if ( ! DI :: config () -> get ( 'system' , 'dfrn_only' ) && count ( $url_recipients ) && ( $public_message || $push_notify ) && ! empty ( $target_item )) {
2018-11-04 23:17:41 +00:00
$slap = OStatus :: salmon ( $target_item , $owner );
foreach ( $url_recipients as $url ) {
2018-12-06 03:23:24 +00:00
Logger :: log ( 'Salmon delivery of item ' . $target_id . ' to ' . $url );
/// @TODO Redeliver/queue these items on failure, though there is no contact record
2019-09-02 03:25:05 +00:00
$delivery_queue_count ++ ;
2018-12-06 03:23:24 +00:00
Salmon :: slapper ( $owner , $url , $slap );
2020-05-02 19:34:02 +00:00
Post\DeliveryData :: incrementQueueDone ( $target_item [ 'uri-id' ], Post\DeliveryData :: OSTATUS );
2018-11-04 23:17:41 +00:00
}
2017-11-19 18:59:55 +00:00
}
// Notify PuSH subscribers (Used for OStatus distribution of regular posts)
if ( $push_notify ) {
2018-12-05 04:49:48 +00:00
Logger :: log ( 'Activating internal PuSH for item ' . $target_id , Logger :: DEBUG );
2017-11-19 18:59:55 +00:00
// Handling the pubsubhubbub requests
2018-05-19 03:56:29 +00:00
PushSubscriber :: publishFeed ( $owner [ 'uid' ], $a -> queue [ 'priority' ]);
2017-11-19 18:59:55 +00:00
}
2018-12-06 03:23:24 +00:00
if ( ! empty ( $target_item )) {
Logger :: log ( 'Calling hooks for ' . $cmd . ' ' . $target_id , Logger :: DEBUG );
2017-11-19 18:59:55 +00:00
2018-10-21 05:15:02 +00:00
Hook :: fork ( $a -> queue [ 'priority' ], 'notifier_normal' , $target_item );
2017-11-19 18:59:55 +00:00
2018-12-06 03:23:24 +00:00
Hook :: callAll ( 'notifier_end' , $target_item );
2019-06-11 19:35:03 +00:00
// Workaround for pure connector posts
if ( in_array ( $cmd , [ Delivery :: POST , Delivery :: POKE ])) {
2019-09-04 21:06:25 +00:00
if ( $delivery_queue_count == 0 ) {
2020-05-02 19:34:02 +00:00
Post\DeliveryData :: incrementQueueDone ( $target_item [ 'uri-id' ]);
2019-09-04 21:06:25 +00:00
$delivery_queue_count = 1 ;
}
2020-05-02 19:34:02 +00:00
Post\DeliveryData :: incrementQueueCount ( $target_item [ 'uri-id' ], $delivery_queue_count );
2019-06-11 19:35:03 +00:00
}
2018-12-06 03:23:24 +00:00
}
2017-11-19 18:59:55 +00:00
return ;
}
2018-09-01 03:23:12 +00:00
2020-06-27 12:18:36 +00:00
/**
* Checks if the current delivery shouldn ' t be transported to Diaspora .
* This is done for posts from AP authors or posts that are comments to AP authors .
*
* @ param array $contact Receiver of the post
* @ param array $item The post
* @ param array $thr_parent The thread parent
* @ return bool
*/
private static function skipActivityPubForDiaspora ( array $contact , array $item , array $thr_parent )
{
// No skipping needs to be done when delivery isn't done to Diaspora
if ( $contact [ 'network' ] != Protocol :: DIASPORA ) {
return false ;
}
// Skip the delivery to Diaspora if the item is from an ActivityPub author
if ( $item [ 'author-network' ] == Protocol :: ACTIVITYPUB ) {
return true ;
}
// Skip the delivery to Diaspora if the thread parent is from an ActivityPub author
if ( $thr_parent [ 'author-network' ] == Protocol :: ACTIVITYPUB ) {
return true ;
}
return false ;
}
2019-07-15 04:33:00 +00:00
/**
* Checks if the current delivery process needs to be transported via DFRN .
*
2019-10-06 21:59:23 +00:00
* @ param array $contact Receiver of the post
* @ param array $item The post
* @ param array $parent The parent
* @ param array $thr_parent The thread parent
* @ param string $cmd Notifier command
2019-07-15 04:33:00 +00:00
* @ return bool
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
* @ throws \ImagickException
*/
2019-10-06 21:59:23 +00:00
private static function skipDFRN ( $contact , $item , $parent , $thr_parent , $cmd )
2019-07-15 04:33:00 +00:00
{
2019-11-22 08:01:23 +00:00
if ( empty ( $parent [ 'network' ])) {
return false ;
}
2019-10-06 21:59:23 +00:00
// Don't skip when the starting post is delivered via Diaspora
if ( $parent [ 'network' ] == Protocol :: DIASPORA ) {
return false ;
}
// Also don't skip when the direct thread parent was delivered via Diaspora
if ( $thr_parent [ 'network' ] == Protocol :: DIASPORA ) {
return false ;
}
2019-09-21 12:39:07 +00:00
// Use DFRN if we are on the same site
2019-09-21 13:00:53 +00:00
if ( ! empty ( $contact [ 'url' ]) && Contact :: isLocal ( $contact [ 'url' ])) {
2019-09-21 12:39:07 +00:00
return false ;
}
2019-07-15 04:33:00 +00:00
// Don't skip when author or owner don't have AP profiles
2019-07-16 19:58:47 +00:00
if (( ! empty ( $item [ 'author-link' ]) && empty ( APContact :: getByURL ( $item [ 'author-link' ], false ))) || ( ! empty ( $item [ 'owner-link' ]) && empty ( APContact :: getByURL ( $item [ 'owner-link' ], false )))) {
2019-07-15 04:33:00 +00:00
return false ;
}
// Don't skip DFRN delivery for these commands
if ( in_array ( $cmd , [ Delivery :: SUGGESTION , Delivery :: REMOVAL , Delivery :: RELOCATION , Delivery :: POKE ])) {
return false ;
}
2019-12-08 22:04:32 +00:00
// We deliver reshares via AP whenever possible
if ( ActivityPub\Transmitter :: isAnnounce ( $item )) {
return true ;
}
2019-07-15 04:36:55 +00:00
// Skip DFRN when the item will be (forcefully) delivered via AP
2020-01-19 20:21:13 +00:00
if ( DI :: config () -> get ( 'debug' , 'total_ap_delivery' ) && ( $contact [ 'network' ] == Protocol :: DFRN ) && ! empty ( APContact :: getByURL ( $contact [ 'url' ], false ))) {
2019-07-15 04:33:00 +00:00
return true ;
}
// Skip DFRN delivery if the contact speaks ActivityPub
return in_array ( $contact [ 'network' ], [ Protocol :: DFRN , Protocol :: DIASPORA ]) && ( $contact [ 'protocol' ] == Protocol :: ACTIVITYPUB );
}
2019-02-11 20:30:08 +00:00
/**
* Checks if the current action is a deletion command of a account removal activity
* For Diaspora and ActivityPub we don ' t need to send single item deletion calls .
* These protocols do have a dedicated command for deleting a whole account .
*
* @ param string $cmd Notifier command
* @ param array $owner Sender of the post
* @ param string $network Receiver network
* @ return bool
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
* @ throws \ImagickException
*/
private static function isRemovalActivity ( $cmd , $owner , $network )
{
2019-03-23 04:05:47 +00:00
return ( $cmd == Delivery :: DELETION ) && $owner [ 'account_removed' ] && in_array ( $network , [ Protocol :: ACTIVITYPUB , Protocol :: DIASPORA ]);
2019-02-11 20:30:08 +00:00
}
2018-12-05 05:06:48 +00:00
/**
* @ param int $self_user_id
2019-01-06 21:06:53 +00:00
* @ param int $priority The priority the Notifier queue item was created with
* @ param string $created The date the Notifier queue item was created on
2018-12-05 05:06:48 +00:00
* @ return bool
2019-01-06 21:06:53 +00:00
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
* @ throws \ImagickException
2018-12-05 05:06:48 +00:00
*/
private static function notifySelfRemoval ( $self_user_id , $priority , $created )
{
$owner = User :: getOwnerDataById ( $self_user_id );
if ( ! $owner ) {
return false ;
}
$contacts_stmt = DBA :: select ( 'contact' , [], [ 'self' => false , 'uid' => $self_user_id ]);
if ( ! DBA :: isResult ( $contacts_stmt )) {
return false ;
}
while ( $contact = DBA :: fetch ( $contacts_stmt )) {
Contact :: terminateFriendship ( $owner , $contact , true );
}
2018-12-05 05:35:52 +00:00
DBA :: close ( $contacts_stmt );
2018-12-05 05:06:48 +00:00
$inboxes = ActivityPub\Transmitter :: fetchTargetInboxesforUser ( 0 );
foreach ( $inboxes as $inbox ) {
2019-05-14 17:50:45 +00:00
Logger :: info ( 'Account removal via ActivityPub' , [ 'uid' => $self_user_id , 'inbox' => $inbox ]);
2018-12-05 05:06:48 +00:00
Worker :: add ([ 'priority' => PRIORITY_NEGLIGIBLE , 'created' => $created , 'dont_fork' => true ],
'APDelivery' , Delivery :: REMOVAL , '' , $inbox , $self_user_id );
}
return true ;
}
2018-12-05 04:49:48 +00:00
/**
* @ param string $cmd
* @ param array $target_item
* @ param array $parent
2019-10-06 21:59:23 +00:00
* @ param array $thr_parent
2019-01-06 21:06:53 +00:00
* @ param int $priority The priority the Notifier queue item was created with
* @ param string $created The date the Notifier queue item was created on
2018-12-07 05:52:14 +00:00
* @ return int The number of delivery tasks created
2019-01-06 21:06:53 +00:00
* @ throws \Friendica\Network\HTTPException\InternalServerErrorException
* @ throws \ImagickException
2018-12-05 04:49:48 +00:00
*/
2019-10-06 21:59:23 +00:00
private static function activityPubDelivery ( $cmd , array $target_item , array $parent , array $thr_parent , $priority , $created , $owner )
2018-10-06 03:16:38 +00:00
{
2019-10-06 21:59:23 +00:00
// Don't deliver via AP when the starting post is delivered via Diaspora
if ( $parent [ 'network' ] == Protocol :: DIASPORA ) {
return 0 ;
}
// Also don't deliver when the direct thread parent was delivered via Diaspora
if ( $thr_parent [ 'network' ] == Protocol :: DIASPORA ) {
return 0 ;
}
2018-10-06 03:16:38 +00:00
$inboxes = [];
2019-01-22 13:31:39 +00:00
$uid = $target_item [ 'contact-uid' ] ? : $target_item [ 'uid' ];
2018-10-06 03:16:38 +00:00
if ( $target_item [ 'origin' ]) {
2019-01-22 13:31:39 +00:00
$inboxes = ActivityPub\Transmitter :: fetchTargetInboxes ( $target_item , $uid );
2018-12-05 04:49:48 +00:00
Logger :: log ( 'Origin item ' . $target_item [ 'id' ] . ' with URL ' . $target_item [ 'uri' ] . ' will be distributed.' , Logger :: DEBUG );
2019-03-14 18:44:41 +00:00
} elseif ( Item :: isForumPost ( $target_item , $owner )) {
$inboxes = ActivityPub\Transmitter :: fetchTargetInboxes ( $target_item , $uid , false , 0 , true );
Logger :: log ( 'Forum item ' . $target_item [ 'id' ] . ' with URL ' . $target_item [ 'uri' ] . ' will be distributed.' , Logger :: DEBUG );
2018-10-06 13:16:52 +00:00
} elseif ( ! DBA :: exists ( 'conversation' , [ 'item-uri' => $target_item [ 'uri' ], 'protocol' => Conversation :: PARCEL_ACTIVITYPUB ])) {
2018-12-05 04:49:48 +00:00
Logger :: log ( 'Remote item ' . $target_item [ 'id' ] . ' with URL ' . $target_item [ 'uri' ] . ' is no AP post. It will not be distributed.' , Logger :: DEBUG );
2018-12-07 05:52:14 +00:00
return 0 ;
2019-01-17 23:06:27 +00:00
} elseif ( $parent [ 'origin' ]) {
2018-10-20 07:53:45 +00:00
// Remote items are transmitted via the personal inboxes.
// Doing so ensures that the dedicated receiver will get the message.
2019-01-22 13:31:39 +00:00
$inboxes = ActivityPub\Transmitter :: fetchTargetInboxes ( $parent , $uid , true , $target_item [ 'id' ]);
2018-12-05 04:49:48 +00:00
Logger :: log ( 'Remote item ' . $target_item [ 'id' ] . ' with URL ' . $target_item [ 'uri' ] . ' will be distributed.' , Logger :: DEBUG );
2018-10-06 03:16:38 +00:00
}
2018-10-06 13:16:52 +00:00
if ( empty ( $inboxes )) {
2018-12-05 04:49:48 +00:00
Logger :: log ( 'No inboxes found for item ' . $target_item [ 'id' ] . ' with URL ' . $target_item [ 'uri' ] . '. It will not be distributed.' , Logger :: DEBUG );
2018-12-07 05:52:14 +00:00
return 0 ;
2018-10-06 13:16:52 +00:00
}
2018-10-06 03:16:38 +00:00
// Fill the item cache
2018-12-05 04:49:48 +00:00
ActivityPub\Transmitter :: createCachedActivityFromItem ( $target_item [ 'id' ], true );
2018-10-06 03:16:38 +00:00
2019-09-02 03:25:05 +00:00
$delivery_queue_count = 0 ;
2018-10-06 03:16:38 +00:00
foreach ( $inboxes as $inbox ) {
2019-05-14 17:50:45 +00:00
Logger :: info ( 'Delivery via ActivityPub' , [ 'cmd' => $cmd , 'id' => $target_item [ 'id' ], 'inbox' => $inbox ]);
2018-10-06 03:16:38 +00:00
2019-09-02 03:25:05 +00:00
if ( Worker :: add ([ 'priority' => $priority , 'created' => $created , 'dont_fork' => true ],
'APDelivery' , $cmd , $target_item [ 'id' ], $inbox , $uid )) {
$delivery_queue_count ++ ;
}
2018-10-06 03:16:38 +00:00
}
2018-12-07 05:52:14 +00:00
2019-09-02 03:25:05 +00:00
return $delivery_queue_count ;
2018-10-06 03:16:38 +00:00
}
2017-11-19 18:59:55 +00:00
}