2019-12-05 08:12:59 -05:00
< ? php
2020-02-09 15:45:36 +01:00
/**
2023-01-01 09:36:24 -05:00
* @ copyright Copyright ( C ) 2010 - 2023 , the Friendica project
2020-02-09 15:45:36 +01: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 />.
*
*/
2019-12-05 08:12:59 -05:00
2020-01-27 21:18:42 -05:00
namespace Friendica\Module ;
2019-12-05 08:12:59 -05:00
2023-02-21 15:37:32 -05:00
use DateTime ;
2021-11-21 21:52:36 +01:00
use Friendica\App ;
2021-11-28 14:10:40 +01:00
use Friendica\App\Router ;
2019-12-05 08:12:59 -05:00
use Friendica\BaseModule ;
2021-11-21 21:52:36 +01:00
use Friendica\Core\L10n ;
2021-05-08 09:14:19 +00:00
use Friendica\Core\Logger ;
use Friendica\Core\System ;
2023-02-21 15:37:32 -05:00
use Friendica\Database\DBA ;
2019-12-15 22:34:11 +01:00
use Friendica\DI ;
2021-11-18 22:20:19 +00:00
use Friendica\Model\Contact ;
2022-09-12 23:12:11 +02:00
use Friendica\Model\Item ;
2021-07-08 13:47:46 +00:00
use Friendica\Model\Post ;
2021-11-20 09:36:17 +00:00
use Friendica\Model\User ;
2021-11-21 21:52:36 +01:00
use Friendica\Module\Api\ApiResponse ;
2022-12-26 21:17:32 +01:00
use Friendica\Module\Special\HTTPException as ModuleHTTPException ;
2019-12-05 08:12:59 -05:00
use Friendica\Network\HTTPException ;
2023-02-28 10:36:11 -05:00
use Friendica\Object\Api\Mastodon\Status ;
2023-02-21 15:37:32 -05:00
use Friendica\Object\Api\Mastodon\TimelineOrderByTypes ;
2021-06-08 06:32:24 +00:00
use Friendica\Security\BasicAuth ;
use Friendica\Security\OAuth ;
2021-07-08 13:47:46 +00:00
use Friendica\Util\DateTimeFormat ;
2021-11-21 21:52:36 +01:00
use Friendica\Util\Profiler ;
2021-11-28 14:10:40 +01:00
use Psr\Http\Message\ResponseInterface ;
2021-11-21 21:52:36 +01:00
use Psr\Log\LoggerInterface ;
2019-12-05 08:12:59 -05:00
2020-01-27 21:18:42 -05:00
class BaseApi extends BaseModule
2019-12-05 08:12:59 -05:00
{
2021-11-26 07:55:02 +00:00
const LOG_PREFIX = 'API {action} - ' ;
2021-05-16 07:37:11 +00:00
const SCOPE_READ = 'read' ;
const SCOPE_WRITE = 'write' ;
const SCOPE_FOLLOW = 'follow' ;
const SCOPE_PUSH = 'push' ;
2021-06-16 15:02:33 +00:00
/**
* @ var array
*/
protected static $boundaries = [];
/**
* @ var array
*/
protected static $request = [];
2021-11-21 21:52:36 +01:00
/** @var App */
protected $app ;
/** @var ApiResponse */
protected $response ;
public function __construct ( App $app , L10n $l10n , App\BaseURL $baseUrl , App\Arguments $args , LoggerInterface $logger , Profiler $profiler , ApiResponse $response , array $server , array $parameters = [])
{
parent :: __construct ( $l10n , $baseUrl , $args , $logger , $profiler , $response , $server , $parameters );
2021-11-28 13:11:12 +01:00
$this -> app = $app ;
2021-11-21 21:52:36 +01:00
}
2021-11-28 14:10:40 +01:00
/**
* Additionally checks , if the caller is permitted to do this action
*
* { @ inheritDoc }
*
* @ throws HTTPException\ForbiddenException
*/
2022-12-26 21:17:32 +01:00
public function run ( ModuleHTTPException $httpException , array $request = [], bool $scopecheck = true ) : ResponseInterface
2019-12-05 08:12:59 -05:00
{
2021-12-17 07:04:52 +00:00
if ( $scopecheck ) {
2022-01-02 22:25:50 +01:00
switch ( $this -> args -> getMethod ()) {
2021-12-17 07:04:52 +00:00
case Router :: DELETE :
case Router :: PATCH :
case Router :: POST :
case Router :: PUT :
self :: checkAllowedScope ( self :: SCOPE_WRITE );
2023-01-01 09:36:24 -05:00
2021-12-17 07:04:52 +00:00
if ( ! self :: getCurrentUserID ()) {
throw new HTTPException\ForbiddenException ( $this -> t ( 'Permission denied.' ));
}
break ;
2023-01-01 09:36:24 -05:00
}
2019-12-05 08:12:59 -05:00
}
2021-05-08 09:14:19 +00:00
2022-12-26 21:17:32 +01:00
return parent :: run ( $httpException , $request );
2021-05-08 09:14:19 +00:00
}
2023-02-21 15:37:32 -05:00
/**
2023-02-22 11:27:54 -05:00
* Processes data from GET requests and sets paging conditions
2023-02-21 15:37:32 -05:00
*
2023-02-22 11:27:54 -05:00
* @ param array $request Custom REQUEST array
* @ param array $condition Existing conditions to merge
* @ return array paging data condition parameters data
2023-02-21 15:37:32 -05:00
* @ throws \Exception
*/
2023-02-28 08:20:08 -05:00
protected function addPagingConditions ( array $request , array $condition ) : array
2023-02-21 15:37:32 -05:00
{
$requested_order = $request [ 'friendica_order' ];
if ( $requested_order == TimelineOrderByTypes :: ID ) {
if ( ! empty ( $request [ 'max_id' ])) {
2023-02-22 11:02:52 -05:00
$condition = DBA :: mergeConditions ( $condition , [ " `uri-id` < ? " , intval ( $request [ 'max_id' ])]);
2023-02-21 15:37:32 -05:00
}
if ( ! empty ( $request [ 'since_id' ])) {
2023-02-22 11:02:52 -05:00
$condition = DBA :: mergeConditions ( $condition , [ " `uri-id` > ? " , intval ( $request [ 'since_id' ])]);
2023-02-21 15:37:32 -05:00
}
if ( ! empty ( $request [ 'min_id' ])) {
2023-02-22 11:02:52 -05:00
$condition = DBA :: mergeConditions ( $condition , [ " `uri-id` > ? " , intval ( $request [ 'min_id' ])]);
2023-02-21 15:37:32 -05:00
}
} else {
2023-02-28 13:10:45 -05:00
switch ( $requested_order ) {
case TimelineOrderByTypes :: RECEIVED :
case TimelineOrderByTypes :: CHANGED :
case TimelineOrderByTypes :: EDITED :
case TimelineOrderByTypes :: CREATED :
case TimelineOrderByTypes :: COMMENTED :
$order_field = $requested_order ;
break ;
default :
throw new \Exception ( " Unrecognized request order: $requested_order " );
}
2023-02-22 11:02:52 -05:00
if ( ! empty ( $request [ 'max_id' ])) {
$condition = DBA :: mergeConditions ( $condition , [ " ` $order_field ` < ? " , DateTimeFormat :: convert ( $request [ 'max_id' ], DateTimeFormat :: MYSQL )]);
2023-02-21 15:37:32 -05:00
}
2023-02-28 08:20:08 -05:00
if ( ! empty ( $request [ 'since_id' ])) {
$condition = DBA :: mergeConditions ( $condition , [ " ` $order_field ` > ? " , DateTimeFormat :: convert ( $request [ 'since_id' ], DateTimeFormat :: MYSQL )]);
}
2023-02-21 15:37:32 -05:00
2023-02-22 11:02:52 -05:00
if ( ! empty ( $request [ 'min_id' ])) {
$condition = DBA :: mergeConditions ( $condition , [ " ` $order_field ` > ? " , DateTimeFormat :: convert ( $request [ 'min_id' ], DateTimeFormat :: MYSQL )]);
2023-02-21 15:37:32 -05:00
}
}
return $condition ;
}
2023-02-22 11:27:54 -05:00
/**
* Processes data from GET requests and sets paging conditions
*
* @ param array $request Custom REQUEST array
* @ param array $params Existing $params element to build on
* @ return array ordering data added to the params blocks that was passed in
* @ throws \Exception
*/
2023-02-28 08:20:08 -05:00
protected function buildOrderAndLimitParams ( array $request , array $params = []) : array
2023-02-22 11:27:54 -05:00
{
$requested_order = $request [ 'friendica_order' ];
switch ( $requested_order ) {
2023-02-28 10:36:11 -05:00
case TimelineOrderByTypes :: CHANGED :
2023-02-22 11:27:54 -05:00
case TimelineOrderByTypes :: CREATED :
2023-02-28 10:36:11 -05:00
case TimelineOrderByTypes :: COMMENTED :
case TimelineOrderByTypes :: EDITED :
case TimelineOrderByTypes :: RECEIVED :
2023-02-28 13:49:23 -05:00
$order_field = $requested_order ;
2023-02-28 10:36:11 -05:00
break ;
2023-02-22 11:27:54 -05:00
case TimelineOrderByTypes :: ID :
default :
$order_field = 'uri-id' ;
}
2023-02-28 08:20:08 -05:00
if ( ! empty ( $request [ 'min_id' ])) {
2023-02-22 11:27:54 -05:00
$params [ 'order' ] = [ $order_field ];
} else {
$params [ 'order' ] = [ $order_field => true ];
}
2023-02-28 11:43:12 -05:00
$params [ 'limit' ] = $request [ 'limit' ];
2023-02-22 11:27:54 -05:00
return $params ;
}
2023-02-28 11:41:53 -05:00
/**
* Update the ID / time boundaries for this result set . Used for building Link Headers
*
* @ param Status $status
* @ param array $post_item
* @ param string $order
* @ return void
* @ throws \Exception
*/
protected function updateBoundaries ( Status $status , array $post_item , string $order )
{
2023-02-28 10:36:11 -05:00
try {
switch ( $order ) {
case TimelineOrderByTypes :: CHANGED :
2023-02-28 11:41:53 -05:00
if ( ! empty ( $status -> friendicaExtension () -> changedAt ())) {
2023-02-28 10:36:11 -05:00
self :: setBoundaries ( new DateTime ( DateTimeFormat :: utc ( $status -> friendicaExtension () -> changedAt (), DateTimeFormat :: JSON )));
}
break ;
case TimelineOrderByTypes :: CREATED :
2023-02-28 11:41:53 -05:00
if ( ! empty ( $status -> createdAt ())) {
2023-02-28 10:36:11 -05:00
self :: setBoundaries ( new DateTime ( DateTimeFormat :: utc ( $status -> createdAt (), DateTimeFormat :: JSON )));
}
break ;
case TimelineOrderByTypes :: COMMENTED :
2023-02-28 11:41:53 -05:00
if ( ! empty ( $status -> friendicaExtension () -> commentedAt ())) {
2023-02-28 10:36:11 -05:00
self :: setBoundaries ( new DateTime ( DateTimeFormat :: utc ( $status -> friendicaExtension () -> commentedAt (), DateTimeFormat :: JSON )));
}
break ;
case TimelineOrderByTypes :: EDITED :
2023-02-28 15:02:02 -05:00
if ( ! empty ( $status -> editedAt ())) {
self :: setBoundaries ( new DateTime ( DateTimeFormat :: utc ( $status -> editedAt (), DateTimeFormat :: JSON )));
2023-02-28 10:36:11 -05:00
}
break ;
case TimelineOrderByTypes :: RECEIVED :
2023-02-28 11:41:53 -05:00
if ( ! empty ( $status -> friendicaExtension () -> receivedAt ())) {
2023-02-28 10:36:11 -05:00
self :: setBoundaries ( new DateTime ( DateTimeFormat :: utc ( $status -> friendicaExtension () -> receivedAt (), DateTimeFormat :: JSON )));
}
break ;
case TimelineOrderByTypes :: ID :
default :
self :: setBoundaries ( $post_item [ 'uri-id' ]);
}
} catch ( \Exception $e ) {
Logger :: debug ( 'Error processing page boundary calculation, skipping' , [ 'error' => $e ]);
}
}
2021-05-18 06:31:22 +00:00
/**
* Processes data from GET requests and sets defaults
*
2021-11-27 18:30:41 -05:00
* @ param array $defaults Associative array of expected request keys and their default typed value . A null
* value will remove the request key from the resulting value array .
2021-11-28 13:44:42 +01:00
* @ param array $request Custom REQUEST array , superglobal instead
2021-05-18 06:31:22 +00:00
* @ return array request data
2021-11-27 18:30:41 -05:00
* @ throws \Exception
2021-05-18 06:31:22 +00:00
*/
2021-11-28 13:44:42 +01:00
public function getRequest ( array $defaults , array $request ) : array
2021-05-29 10:40:47 +00:00
{
2021-11-28 13:44:42 +01:00
self :: $request = $request ;
2021-06-16 15:02:33 +00:00
self :: $boundaries = [];
unset ( self :: $request [ 'pagename' ]);
2021-11-28 13:44:42 +01:00
return $this -> checkDefaults ( $defaults , $request );
2021-05-18 06:31:22 +00:00
}
2021-06-16 15:02:33 +00:00
/**
* Set boundaries for the " link " header
* @ param array $boundaries
2023-02-28 08:20:08 -05:00
* @ param int | \DateTime $id
2021-06-16 15:02:33 +00:00
*/
2023-02-28 08:20:08 -05:00
protected static function setBoundaries ( $id )
2021-06-16 15:02:33 +00:00
{
if ( ! isset ( self :: $boundaries [ 'min' ])) {
self :: $boundaries [ 'min' ] = $id ;
}
if ( ! isset ( self :: $boundaries [ 'max' ])) {
self :: $boundaries [ 'max' ] = $id ;
}
self :: $boundaries [ 'min' ] = min ( self :: $boundaries [ 'min' ], $id );
self :: $boundaries [ 'max' ] = max ( self :: $boundaries [ 'max' ], $id );
}
/**
2022-12-12 03:13:24 +00:00
* Get the " link " header with " next " and " prev " links
* @ return string
2021-06-16 15:02:33 +00:00
*/
2023-02-28 12:48:25 -05:00
protected static function getLinkHeader ( bool $asDate = false ) : string
2021-06-16 15:02:33 +00:00
{
if ( empty ( self :: $boundaries )) {
2022-12-12 03:13:24 +00:00
return '' ;
2021-06-16 15:02:33 +00:00
}
$request = self :: $request ;
unset ( $request [ 'min_id' ]);
unset ( $request [ 'max_id' ]);
unset ( $request [ 'since_id' ]);
$prev_request = $next_request = $request ;
2023-02-21 15:37:32 -05:00
if ( $asDate ) {
2023-02-28 08:20:08 -05:00
$max_date = self :: $boundaries [ 'max' ];
$min_date = self :: $boundaries [ 'min' ];
2023-02-22 11:02:52 -05:00
$prev_request [ 'min_id' ] = $max_date -> format ( DateTimeFormat :: JSON );
$next_request [ 'max_id' ] = $min_date -> format ( DateTimeFormat :: JSON );
2023-02-21 15:37:32 -05:00
} else {
$prev_request [ 'min_id' ] = self :: $boundaries [ 'max' ];
$next_request [ 'max_id' ] = self :: $boundaries [ 'min' ];
}
2021-06-16 15:02:33 +00:00
$command = DI :: baseUrl () . '/' . DI :: args () -> getCommand ();
$prev = $command . '?' . http_build_query ( $prev_request );
$next = $command . '?' . http_build_query ( $next_request );
2022-12-12 03:13:24 +00:00
return 'Link: <' . $next . '>; rel="next", <' . $prev . '>; rel="prev"' ;
}
2023-02-17 13:24:00 -05:00
/**
* Get the " link " header with " next " and " prev " links for an offset / limit type call
* @ return string
*/
protected static function getOffsetAndLimitLinkHeader ( int $offset , int $limit ) : string
{
$request = self :: $request ;
unset ( $request [ 'offset' ]);
$request [ 'limit' ] = $limit ;
$prev_request = $next_request = $request ;
$prev_request [ 'offset' ] = $offset - $limit ;
$next_request [ 'offset' ] = $offset + $limit ;
$command = DI :: baseUrl () . '/' . DI :: args () -> getCommand ();
$prev = $command . '?' . http_build_query ( $prev_request );
$next = $command . '?' . http_build_query ( $next_request );
if ( $prev_request [ 'offset' ] >= 0 ) {
return 'Link: <' . $next . '>; rel="next", <' . $prev . '>; rel="prev"' ;
} else {
return 'Link: <' . $next . '>; rel="next"' ;
}
}
2022-12-12 03:13:24 +00:00
/**
* Set the " link " header with " next " and " prev " links
* @ return void
*/
2023-02-21 15:37:32 -05:00
protected static function setLinkHeader ( bool $asDate = false )
2022-12-12 03:13:24 +00:00
{
2023-02-21 15:37:32 -05:00
$header = self :: getLinkHeader ( $asDate );
2022-12-12 03:13:24 +00:00
if ( ! empty ( $header )) {
header ( $header );
}
2021-06-16 15:02:33 +00:00
}
2023-02-17 13:24:00 -05:00
/**
* Set the " link " header with " next " and " prev " links
* @ return void
*/
protected static function setLinkHeaderByOffsetLimit ( int $offset , int $limit )
{
$header = self :: getOffsetAndLimitLinkHeader ( $offset , $limit );
if ( ! empty ( $header )) {
header ( $header );
}
}
2023-01-25 06:26:17 +00:00
/**
* Check if the app is known to support quoted posts
*
* @ return bool
*/
public static function appSupportsQuotes () : bool
{
2023-04-08 19:17:57 +00:00
$token = OAuth :: getCurrentApplicationToken ();
2023-01-25 06:26:17 +00:00
return ( ! empty ( $token [ 'name' ]) && in_array ( $token [ 'name' ], [ 'Fedilab' ]));
}
2021-05-15 22:40:57 +00:00
/**
2021-06-08 06:32:24 +00:00
* Get current application token
2021-05-15 22:40:57 +00:00
*
* @ return array token
*/
2021-11-24 06:44:25 +00:00
public static function getCurrentApplication ()
2021-05-15 22:40:57 +00:00
{
2021-06-08 06:32:24 +00:00
$token = OAuth :: getCurrentApplicationToken ();
2021-05-11 06:30:20 +00:00
2021-06-08 06:32:24 +00:00
if ( empty ( $token )) {
$token = BasicAuth :: getCurrentApplicationToken ();
2021-05-11 19:15:05 +00:00
}
2021-05-15 22:40:57 +00:00
return $token ;
2021-05-11 06:30:20 +00:00
}
2021-05-12 12:08:30 +00:00
/**
2021-06-08 06:32:24 +00:00
* Get current user id , returns 0 if not logged in
2021-05-12 12:08:30 +00:00
*
2021-06-08 06:32:24 +00:00
* @ return int User ID
2021-05-12 12:08:30 +00:00
*/
2021-11-09 21:41:37 +00:00
public static function getCurrentUserID ()
2021-05-11 06:30:20 +00:00
{
2021-06-08 06:32:24 +00:00
$uid = OAuth :: getCurrentUserID ();
2021-05-28 06:10:32 +00:00
2021-06-08 06:32:24 +00:00
if ( empty ( $uid )) {
$uid = BasicAuth :: getCurrentUserID ( false );
2021-05-11 06:30:20 +00:00
}
2021-06-08 06:32:24 +00:00
return ( int ) $uid ;
2021-05-11 06:30:20 +00:00
}
2021-05-12 06:50:27 +00:00
2021-06-08 09:11:56 +00:00
/**
* Check if the provided scope does exist .
* halts execution on missing scope or when not logged in .
*
* @ param string $scope the requested scope ( read , write , follow , push )
*/
public static function checkAllowedScope ( string $scope )
{
$token = self :: getCurrentApplication ();
if ( empty ( $token )) {
Logger :: notice ( 'Empty application token' );
DI :: mstdnError () -> Forbidden ();
}
if ( ! isset ( $token [ $scope ])) {
Logger :: warning ( 'The requested scope does not exist' , [ 'scope' => $scope , 'application' => $token ]);
DI :: mstdnError () -> Forbidden ();
}
if ( empty ( $token [ $scope ])) {
Logger :: warning ( 'The requested scope is not allowed' , [ 'scope' => $scope , 'application' => $token ]);
DI :: mstdnError () -> Forbidden ();
}
}
2021-07-08 13:47:46 +00:00
public static function checkThrottleLimit ()
{
$uid = self :: getCurrentUserID ();
// Check for throttling (maximum posts per day, week and month)
$throttle_day = DI :: config () -> get ( 'system' , 'throttle_limit_day' );
if ( $throttle_day > 0 ) {
$datefrom = date ( DateTimeFormat :: MYSQL , time () - 24 * 60 * 60 );
2022-09-12 23:12:11 +02:00
$condition = [ " `gravity` = ? AND `uid` = ? AND `wall` AND `received` > ? " , Item :: GRAVITY_PARENT , $uid , $datefrom ];
2021-07-08 17:32:41 +00:00
$posts_day = Post :: countThread ( $condition );
2021-07-08 13:47:46 +00:00
if ( $posts_day > $throttle_day ) {
2022-08-31 05:01:22 +00:00
Logger :: notice ( 'Daily posting limit reached' , [ 'uid' => $uid , 'posts' => $posts_day , 'limit' => $throttle_day ]);
2021-07-08 13:47:46 +00:00
$error = DI :: l10n () -> t ( 'Too Many Requests' );
$error_description = DI :: l10n () -> tt ( " Daily posting limit of %d post reached. The post was rejected. " , " Daily posting limit of %d posts reached. The post was rejected. " , $throttle_day );
$errorobj = new \Friendica\Object\Api\Mastodon\Error ( $error , $error_description );
System :: jsonError ( 429 , $errorobj -> toArray ());
}
}
$throttle_week = DI :: config () -> get ( 'system' , 'throttle_limit_week' );
if ( $throttle_week > 0 ) {
$datefrom = date ( DateTimeFormat :: MYSQL , time () - 24 * 60 * 60 * 7 );
2022-09-12 23:12:11 +02:00
$condition = [ " `gravity` = ? AND `uid` = ? AND `wall` AND `received` > ? " , Item :: GRAVITY_PARENT , $uid , $datefrom ];
2021-07-08 17:32:41 +00:00
$posts_week = Post :: countThread ( $condition );
2021-07-08 13:47:46 +00:00
if ( $posts_week > $throttle_week ) {
2022-08-31 05:01:22 +00:00
Logger :: notice ( 'Weekly posting limit reached' , [ 'uid' => $uid , 'posts' => $posts_week , 'limit' => $throttle_week ]);
2021-07-08 13:47:46 +00:00
$error = DI :: l10n () -> t ( 'Too Many Requests' );
$error_description = DI :: l10n () -> tt ( " Weekly posting limit of %d post reached. The post was rejected. " , " Weekly posting limit of %d posts reached. The post was rejected. " , $throttle_week );
$errorobj = new \Friendica\Object\Api\Mastodon\Error ( $error , $error_description );
System :: jsonError ( 429 , $errorobj -> toArray ());
}
}
$throttle_month = DI :: config () -> get ( 'system' , 'throttle_limit_month' );
if ( $throttle_month > 0 ) {
$datefrom = date ( DateTimeFormat :: MYSQL , time () - 24 * 60 * 60 * 30 );
2022-09-12 23:12:11 +02:00
$condition = [ " `gravity` = ? AND `uid` = ? AND `wall` AND `received` > ? " , Item :: GRAVITY_PARENT , $uid , $datefrom ];
2021-07-08 17:32:41 +00:00
$posts_month = Post :: countThread ( $condition );
2021-07-08 13:47:46 +00:00
if ( $posts_month > $throttle_month ) {
2022-08-31 05:01:22 +00:00
Logger :: notice ( 'Monthly posting limit reached' , [ 'uid' => $uid , 'posts' => $posts_month , 'limit' => $throttle_month ]);
2021-07-08 13:47:46 +00:00
$error = DI :: l10n () -> t ( 'Too Many Requests' );
2022-08-08 02:00:52 -04:00
$error_description = DI :: l10n () -> tt ( 'Monthly posting limit of %d post reached. The post was rejected.' , 'Monthly posting limit of %d posts reached. The post was rejected.' , $throttle_month );
2021-07-08 13:47:46 +00:00
$errorobj = new \Friendica\Object\Api\Mastodon\Error ( $error , $error_description );
System :: jsonError ( 429 , $errorobj -> toArray ());
}
}
}
2021-11-18 22:20:19 +00:00
2021-11-26 08:16:06 +00:00
public static function getContactIDForSearchterm ( string $screen_name = null , string $profileurl = null , int $cid = null , int $uid )
2021-11-18 22:20:19 +00:00
{
2021-11-20 09:36:17 +00:00
if ( ! empty ( $cid )) {
return $cid ;
}
2021-11-26 07:55:02 +00:00
if ( ! empty ( $profileurl )) {
return Contact :: getIdForURL ( $profileurl );
}
if ( empty ( $cid ) && ! empty ( $screen_name )) {
if ( strpos ( $screen_name , '@' ) !== false ) {
return Contact :: getIdForURL ( $screen_name , 0 , false );
}
2021-11-20 09:36:17 +00:00
$user = User :: getByNickname ( $screen_name , [ 'uid' ]);
if ( ! empty ( $user [ 'uid' ])) {
2021-11-26 07:55:02 +00:00
return Contact :: getPublicIdByUserId ( $user [ 'uid' ]);
2021-11-20 09:36:17 +00:00
}
}
2021-11-26 07:55:02 +00:00
if ( $uid != 0 ) {
return Contact :: getPublicIdByUserId ( $uid );
2021-11-18 22:20:19 +00:00
}
2021-11-26 07:55:02 +00:00
return null ;
2021-11-18 22:20:19 +00:00
}
2019-12-05 08:12:59 -05:00
}