2021-05-08 02:21:01 +00:00
< ? php
/**
2024-01-02 20:57:26 +00:00
* @ copyright Copyright ( C ) 2010 - 2024 , the Friendica project
2021-05-08 02:21:01 +00:00
*
* @ 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 />.
*
*/
namespace Friendica\Module\Api\Mastodon\Timelines ;
2024-04-19 21:09:23 +00:00
use Friendica\App ;
use Friendica\Core\L10n ;
2023-01-25 23:03:51 +00:00
use Friendica\Core\Logger ;
2021-05-08 02:21:01 +00:00
use Friendica\Database\DBA ;
use Friendica\DI ;
2024-04-19 21:09:23 +00:00
use Friendica\Model\Contact ;
use Friendica\Model\Conversation ;
2022-09-12 21:12:11 +00:00
use Friendica\Model\Item ;
2021-05-08 02:21:01 +00:00
use Friendica\Model\Post ;
2024-04-19 21:09:23 +00:00
use Friendica\Model\Verb ;
use Friendica\Module\Api\ApiResponse ;
2021-05-08 02:21:01 +00:00
use Friendica\Module\BaseApi ;
2024-04-19 21:09:23 +00:00
use Friendica\Module\Conversation\Timeline ;
2021-05-08 02:21:01 +00:00
use Friendica\Network\HTTPException ;
2023-02-28 16:36:24 +00:00
use Friendica\Object\Api\Mastodon\TimelineOrderByTypes ;
2024-04-19 21:09:23 +00:00
use Friendica\Protocol\Activity ;
use Friendica\Util\Profiler ;
use Psr\Log\LoggerInterface ;
2021-05-08 02:21:01 +00:00
/**
* @ see https :// docs . joinmastodon . org / methods / timelines /
*/
class ListTimeline extends BaseApi
{
2024-04-19 21:09:23 +00:00
/** @var Timeline */
protected $timeline ;
public function __construct ( Timeline $timeline , \Friendica\Factory\Api\Mastodon\Error $errorFactory , App $app , L10n $l10n , App\BaseURL $baseUrl , App\Arguments $args , LoggerInterface $logger , Profiler $profiler , ApiResponse $response , array $server , array $parameters = [])
{
parent :: __construct ( $errorFactory , $app , $l10n , $baseUrl , $args , $logger , $profiler , $response , $server , $parameters );
$this -> timeline = $timeline ;
}
2021-05-08 02:21:01 +00:00
/**
* @ throws HTTPException\InternalServerErrorException
*/
2021-11-20 14:38:03 +00:00
protected function rawContent ( array $request = [])
2021-05-08 02:21:01 +00:00
{
2023-10-11 13:30:42 +00:00
$this -> checkAllowedScope ( self :: SCOPE_READ );
2021-05-08 02:21:01 +00:00
$uid = self :: getCurrentUserID ();
2021-11-14 22:19:25 +00:00
if ( empty ( $this -> parameters [ 'id' ])) {
2023-10-11 13:37:49 +00:00
$this -> logAndJsonError ( 422 , $this -> errorFactory -> UnprocessableEntity ());
2021-05-08 02:21:01 +00:00
}
2021-11-28 12:22:27 +00:00
$request = $this -> getRequest ([
2023-02-28 16:36:24 +00:00
'max_id' => null , // Return results older than id
'since_id' => null , // Return results newer than id
'min_id' => null , // Return results immediately newer than id
2021-05-19 06:55:08 +00:00
'limit' => 20 , // Maximum number of results to return. Defaults to 20.Return results older than this ID.
'with_muted' => false , // Pleroma extension: return activities by muted (not by blocked!) users.
'only_media' => false , // Show only statuses with media attached? Defaults to false.
'local' => false , // Show only local statuses? Defaults to false.
'remote' => false , // Show only remote statuses? Defaults to false.
'exclude_replies' => false , // Don't show comments
2023-02-28 16:36:24 +00:00
'friendica_order' => TimelineOrderByTypes :: ID , // Sort order options (defaults to ID)
2021-11-27 23:30:41 +00:00
], $request );
2021-05-08 02:21:01 +00:00
2024-04-19 21:09:23 +00:00
$display_quotes = self :: appSupportsQuotes ();
if ( substr ( $this -> parameters [ 'id' ], 0 , 6 ) == 'group:' ) {
$items = $this -> getStatusesForGroup ( $uid , $request );
} elseif ( substr ( $this -> parameters [ 'id' ], 0 , 8 ) == 'channel:' ) {
$items = $this -> getStatusesForChannel ( $uid , $request );
} else {
$items = $this -> getStatusesForCircle ( $uid , $request );
}
$statuses = [];
foreach ( $items as $item ) {
try {
$status = DI :: mstdnStatus () -> createFromUriId ( $item [ 'uri-id' ], $uid , $display_quotes );
$this -> updateBoundaries ( $status , $item , $request [ 'friendica_order' ]);
$statuses [] = $status ;
} catch ( \Throwable $th ) {
Logger :: info ( 'Post not fetchable' , [ 'uri-id' => $item [ 'uri-id' ], 'uid' => $uid , 'error' => $th ]);
}
}
if ( ! empty ( $request [ 'min_id' ])) {
$statuses = array_reverse ( $statuses );
}
self :: setLinkHeader ( $request [ 'friendica_order' ] != TimelineOrderByTypes :: ID );
$this -> jsonExit ( $statuses );
}
private function getStatusesForGroup ( int $uid , array $request ) : array
{
$cdata = Contact :: getPublicAndUserContactID (( int ) substr ( $this -> parameters [ 'id' ], 6 ), $uid );
$cid = $cdata [ 'public' ];
$condition = [ " (`uid` = ? OR (`uid` = ? AND NOT `global`)) " , 0 , $uid ];
$condition1 = DBA :: mergeConditions ( $condition , [ " `owner-id` = ? AND `gravity` = ? " , $cid , Item :: GRAVITY_PARENT ]);
$condition2 = DBA :: mergeConditions ( $condition , [
" `author-id` = ? AND `gravity` = ? AND `vid` = ? AND `protocol` != ? AND `thr-parent-id` = `parent-uri-id` " ,
$cid , Item :: GRAVITY_ACTIVITY , Verb :: getID ( Activity :: ANNOUNCE ), Conversation :: PARCEL_DIASPORA
]);
$condition1 = $this -> addPagingConditions ( $request , $condition1 );
$condition2 = $this -> addPagingConditions ( $request , $condition2 );
$sql1 = " SELECT `uri-id` FROM `post-thread-user-view` WHERE " . array_shift ( $condition1 );
$sql2 = " SELECT `thr-parent-id` AS `uri-id` FROM `post-user-view` WHERE " . array_shift ( $condition2 );
$condition = array_merge ( $condition1 , $condition2 );
$sql = $sql1 . " UNION " . $sql2 . " GROUP BY `uri-id` " . DBA :: buildParameter ( $this -> buildOrderAndLimitParams ( $request ));
return Post :: toArray ( DBA :: p ( $sql , $condition ));
}
private function getStatusesForChannel ( int $uid , array $request ) : array
{
$request [ 'friendica_order' ] = TimelineOrderByTypes :: ID ;
return $this -> timeline -> getChannelItemsForAPI ( substr ( $this -> parameters [ 'id' ], 8 ), $uid , $request [ 'limit' ], $request [ 'min_id' ], $request [ 'max_id' ]);
}
private function getStatusesForCircle ( int $uid , array $request ) : array
{
2023-10-18 08:11:36 +00:00
$condition = [
" `uid` = ? AND `gravity` IN (?, ?) AND `contact-id` IN (SELECT `contact-id` FROM `group_member` WHERE `gid` = ?) " ,
$uid , Item :: GRAVITY_PARENT , Item :: GRAVITY_COMMENT , $this -> parameters [ 'id' ]
];
2021-05-08 02:21:01 +00:00
2023-02-28 16:36:24 +00:00
$condition = $this -> addPagingConditions ( $request , $condition );
$params = $this -> buildOrderAndLimitParams ( $request );
2021-05-08 02:21:01 +00:00
2021-05-19 06:18:42 +00:00
if ( $request [ 'only_media' ]) {
2023-10-18 08:11:36 +00:00
$condition = DBA :: mergeConditions ( $condition , [
" `uri-id` IN (SELECT `uri-id` FROM `post-media` WHERE `type` IN (?, ?, ?)) " ,
Post\Media :: AUDIO , Post\Media :: IMAGE , Post\Media :: VIDEO
]);
2021-05-19 06:18:42 +00:00
}
2021-05-19 06:55:08 +00:00
if ( $request [ 'exclude_replies' ]) {
2022-09-12 21:12:11 +00:00
$condition = DBA :: mergeConditions ( $condition , [ 'gravity' => Item :: GRAVITY_PARENT ]);
2021-05-19 06:55:08 +00:00
}
2021-05-19 06:18:42 +00:00
if ( $request [ 'local' ]) {
$condition = DBA :: mergeConditions ( $condition , [ " `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin`) " ]);
}
if ( $request [ 'remote' ]) {
2022-11-01 06:02:44 +00:00
$condition = DBA :: mergeConditions ( $condition , [ " NOT `uri-id` IN (SELECT `uri-id` FROM `post-user` WHERE `origin` AND `post-user`.`uri-id` = `post-user-view`.`uri-id`) " ]);
2021-05-19 06:18:42 +00:00
}
2023-10-18 08:11:36 +00:00
$items = Post :: selectTimelineForUser ( $uid , [ 'uri-id' ], $condition , $params );
2024-04-19 21:09:23 +00:00
return Post :: toArray ( $items );
2021-05-08 02:21:01 +00:00
}
}