Merge branch 'develop' into show_image_upload_limit

This commit is contained in:
Marek Bachmann 2022-11-29 00:28:05 +01:00
commit 77c68d10e8
21 changed files with 450 additions and 69 deletions

View File

@ -51,6 +51,6 @@ AddType audio/ogg .oga
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?pagename=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
RewriteRule ^(.*)$ index.php?pagename=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA,B]
</IfModule>

View File

@ -1,5 +1,6 @@
Version 2022.12 (unreleased)
Friendica Core
The rewrite rule in .htaccess-dist has been changed. The change has to be applied manually to the existing .htaccess
Friendica Addons
BREAKING: The functions from the boot.php file have been moved into better fitting classes

View File

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 2022.12-dev (Giant Rhubarb)
-- DB_UPDATE_VERSION 1491
-- DB_UPDATE_VERSION 1493
-- ------------------------------------------
@ -2437,6 +2437,8 @@ CREATE VIEW `post-thread-view` AS SELECT
`post-question`.`end-time` AS `question-end-time`,
0 AS `has-categories`,
EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-thread`.`uri-id`) AS `has-media`,
(SELECT COUNT(*) FROM `post` WHERE `parent-uri-id` = `post-thread`.`uri-id` AND `gravity` = 6) AS `total-comments`,
(SELECT COUNT(DISTINCT(`author-id`)) FROM `post` WHERE `parent-uri-id` = `post-thread`.`uri-id` AND `gravity` = 6) AS `total-actors`,
`diaspora-interaction`.`interaction` AS `signed_text`,
`parent-item-uri`.`guid` AS `parent-guid`,
`parent-post`.`network` AS `parent-network`,

View File

@ -73,7 +73,7 @@ These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/en
- `:id` is a follow request ID, not a regular account id
- Returns a [Relationship](https://docs.joinmastodon.org/entities/relationship) object.
- [`GET /api/v1/followed_tags'](https://docs.joinmastodon.org/methods/followed_tags/)
- [`GET /api/v1/instance`](https://docs.joinmastodon.org/methods/instance#fetch-instance)
- `GET /api/v1/instance/rules` Undocumented, returns Terms of Service
- [`GET /api/v1/instance/peers`](https://docs.joinmastodon.org/methods/instance#list-of-connected-domains)
@ -126,12 +126,18 @@ These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/en
- [`GET /api/v1/statuses/:id/source`](https://docs.joinmastodon.org/methods/statuses/#source)
- [`GET /api/v1/statuses/:id/card`](https://docs.joinmastodon.org/methods/statuses/#card)
- [`GET /api/v1/suggestions`](https://docs.joinmastodon.org/methods/accounts/suggestions/)
- [`GET /api/v1/tags/:id`](https://docs.joinmastodon.org/methods/tags/#get)
- [`GET /api/v1/tags/:id/follow`](https://docs.joinmastodon.org/methods/tags/#follow)
- [`GET /api/v1/tags/:id/unfollow`](https://docs.joinmastodon.org/methods/tags/#unfollow)
- [`GET /api/v1/timelines/direct`](https://docs.joinmastodon.org/methods/timelines/)
- [`GET /api/v1/timelines/home`](https://docs.joinmastodon.org/methods/timelines/)
- [`GET /api/v1/timelines/list/:id`](https://docs.joinmastodon.org/methods/timelines/)
- [`GET /api/v1/timelines/public`](https://docs.joinmastodon.org/methods/timelines/)
- [`GET /api/v1/timelines/tag/:hashtag`](https://docs.joinmastodon.org/methods/timelines/)
- [`GET /api/v1/trends`](https://docs.joinmastodon.org/methods/instance/trends/)
- [`GET /api/v1/trends/links`](https://github.com/mastodon/mastodon/pull/16917)
- [`GET /api/v1/trends/statuses`](https://docs.joinmastodon.org/methods/trends/#statuses)
- [`GET /api/v1/trends/tags`](https://docs.joinmastodon.org/methods/trends/#tags)
- [`GET /api/v2/search`](https://docs.joinmastodon.org/methods/search/)
@ -142,9 +148,6 @@ These emdpoints are planned to be implemented somewhere in the future.
- [`POST /api/v1/accounts/:id/remove_from_followers`](https://github.com/mastodon/mastodon/pull/16864)
- [`GET /api/v1/accounts/familiar_followers`](https://github.com/mastodon/mastodon/pull/17700)
- [`GET /api/v1/accounts/lookup`](https://github.com/mastodon/mastodon/pull/15740)
- [`GET /api/v1/trends/links`](https://github.com/mastodon/mastodon/pull/16917)
- [`GET /api/v1/trends/statuses`](https://github.com/mastodon/mastodon/pull/17431)
- [`GET /api/v1/trends/tags`](https://github.com/mastodon/mastodon/pull/16917)
- [`POST /api/v1/polls/:id/votes`](https://docs.joinmastodon.org/methods/statuses/polls/)
- [`GET /api/v1/featured_tags`](https://docs.joinmastodon.org/methods/accounts/featured_tags/)
- [`POST /api/v1/featured_tags`](https://docs.joinmastodon.org/methods/accounts/featured_tags/)

View File

@ -80,7 +80,7 @@ class Router
/**
* @var array Module parameters
*/
private $parameters = [];
protected $parameters = [];
/** @var L10n */
private $l10n;
@ -268,7 +268,6 @@ class Router
*
* @throws InternalServerErrorException
* @throws MethodNotAllowedException
* @throws NotFoundException
*/
public function getModuleClass(): string
{
@ -284,9 +283,8 @@ class Router
*
* @return void
*
* @throws HTTPException\InternalServerErrorException
* @throws HTTPException\MethodNotAllowedException If a rule matched but the method didn't
* @throws HTTPException\NotFoundException If no rule matched
* @throws HTTPException\InternalServerErrorException Unexpected exceptions
* @throws HTTPException\MethodNotAllowedException If a rule is private only
*/
private function determineModuleClass(): void
{
@ -295,39 +293,26 @@ class Router
$dispatcher = new FriendicaGroupCountBased($this->getCachedDispatchData());
$this->parameters = [];
$this->parameters = [$this->server];
// Check if the HTTP method is OPTIONS and return the special Options Module with the possible HTTP methods
if ($this->args->getMethod() === static::OPTIONS) {
$this->moduleClass = Options::class;
$this->parameters = ['allowedMethods' => $dispatcher->getOptions($cmd)];
} else {
$routeInfo = $dispatcher->dispatch($this->args->getMethod(), $cmd);
if ($routeInfo[0] === Dispatcher::FOUND) {
$this->moduleClass = $routeInfo[1];
$this->parameters = $routeInfo[2];
} elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) {
throw new HTTPException\MethodNotAllowedException($this->l10n->t('Method not allowed for this module. Allowed method(s): %s', implode(', ', $routeInfo[1])));
} else {
throw new HTTPException\NotFoundException($this->l10n->t('Page not found.'));
}
}
}
public function getModule(?string $module_class = null): ICanHandleRequests
{
$module_parameters = [$this->server];
/**
* ROUTING
*
* From the request URL, routing consists of obtaining the name of a BaseModule-extending class of which the
* post() and/or content() static methods can be respectively called to produce a data change or an output.
**/
try {
$module_class = $module_class ?? $this->getModuleClass();
$module_parameters[] = $this->parameters;
// Check if the HTTP method is OPTIONS and return the special Options Module with the possible HTTP methods
if ($this->args->getMethod() === static::OPTIONS) {
$this->moduleClass = Options::class;
$this->parameters = ['allowedMethods' => $dispatcher->getOptions($cmd)];
} else {
$routeInfo = $dispatcher->dispatch($this->args->getMethod(), $cmd);
if ($routeInfo[0] === Dispatcher::FOUND) {
$this->moduleClass = $routeInfo[1];
$this->parameters[] = $routeInfo[2];
} else if ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) {
throw new HTTPException\MethodNotAllowedException($this->l10n->t('Method not allowed for this module. Allowed method(s): %s', implode(', ', $routeInfo[1])));
} else {
throw new HTTPException\NotFoundException($this->l10n->t('Page not found.'));
}
}
} catch (MethodNotAllowedException $e) {
$module_class = MethodNotAllowed::class;
$this->moduleClass = MethodNotAllowed::class;
} catch (NotFoundException $e) {
$moduleName = $this->args->getModuleName();
// Then we try addon-provided modules that we wrap in the LegacyModule class
@ -339,8 +324,8 @@ class Router
} else {
include_once "addon/{$moduleName}/{$moduleName}.php";
if (function_exists($moduleName . '_module')) {
$module_parameters[] = "addon/{$moduleName}/{$moduleName}.php";
$module_class = LegacyModule::class;
$this->parameters[] = "addon/{$moduleName}/{$moduleName}.php";
$this->moduleClass = LegacyModule::class;
}
}
}
@ -348,24 +333,29 @@ class Router
/* Finally, we look for a 'standard' program module in the 'mod' directory
* We emulate a Module class through the LegacyModule class
*/
if (!$module_class && file_exists("mod/{$moduleName}.php")) {
$module_parameters[] = "mod/{$moduleName}.php";
$module_class = LegacyModule::class;
if (!$this->moduleClass && file_exists("mod/{$moduleName}.php")) {
$this->parameters[] = "mod/{$moduleName}.php";
$this->moduleClass = LegacyModule::class;
}
$module_class = $module_class ?: PageNotFound::class;
$this->moduleClass = $this->moduleClass ?: PageNotFound::class;
}
}
public function getModule(?string $module_class = null): ICanHandleRequests
{
$moduleClass = $module_class ?? $this->getModuleClass();
$stamp = microtime(true);
try {
/** @var ICanHandleRequests $module */
return $this->dice->create($module_class, $module_parameters);
return $this->dice->create($moduleClass, $this->parameters);
} finally {
if ($this->dice_profiler_threshold > 0) {
$dur = floatval(microtime(true) - $stamp);
if ($dur >= $this->dice_profiler_threshold) {
$this->logger->notice('Dice module creation lasts too long.', ['duration' => round($dur, 3), 'module' => $module_class, 'parameters' => $module_parameters]);
$this->logger->notice('Dice module creation lasts too long.', ['duration' => round($dur, 3), 'module' => $moduleClass, 'parameters' => $this->parameters]);
}
}
}

View File

@ -37,7 +37,7 @@ class SavedSearches
public static function getHTML(string $return_url, string $search = ''): string
{
$saved = [];
$saved_searches = DBA::select('search', ['id', 'term'], ['uid' => DI::userSession()->getLocalUserId()]);
$saved_searches = DBA::select('search', ['id', 'term'], ['uid' => DI::userSession()->getLocalUserId()], ['order' => ['term']]);
while ($saved_search = DBA::fetch($saved_searches)) {
$saved[] = [
'id' => $saved_search['id'],

View File

@ -30,13 +30,14 @@ use Friendica\Util\Strings;
class Card extends BaseFactory
{
/**
* @param int $uriId Uri-ID of the item
* @param int $uriId Uri-ID of the item
* @param array $history Link request history
*
* @return \Friendica\Object\Api\Mastodon\Card
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException*@throws \Exception
*/
public function createFromUriId(int $uriId): \Friendica\Object\Api\Mastodon\Card
public function createFromUriId(int $uriId, array $history = []): \Friendica\Object\Api\Mastodon\Card
{
$item = Post::selectFirst(['body'], ['uri-id' => $uriId]);
if (!empty($item['body'])) {
@ -76,6 +77,6 @@ class Card extends BaseFactory
}
}
return new \Friendica\Object\Api\Mastodon\Card($data);
return new \Friendica\Object\Api\Mastodon\Card($data, $history);
}
}

View File

@ -374,6 +374,21 @@ class Post
return self::selectView('post-thread-user-view', $selected, $condition, $params);
}
/**
* Select rows from the post-thread-view view
*
* @param array $selected Array of selected fields, empty for all
* @param array $condition Array of fields for condition
* @param array $params Array of several parameters
*
* @return boolean|object
* @throws \Exception
*/
public static function selectPostThread(array $selected = [], array $condition = [], array $params = [])
{
return self::selectView('post-thread-view', $selected, $condition, $params);
}
/**
* Select rows from the given view for a given user
*

View File

@ -0,0 +1,83 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @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;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Module\BaseApi;
/**
* @see https://docs.joinmastodon.org/methods/followed_tags/
*/
class FollowedTags extends BaseApi
{
protected function rawContent(array $request = [])
{
self::checkAllowedScope(self::SCOPE_READ);
$uid = self::getCurrentUserID();
$request = $this->getRequest([
'max_id' => 0,
'since_id' => 0,
'min_id' => 0,
'limit' => 100, // Maximum number of results to return. Defaults to 100. Paginate using the HTTP Link header.
], $request);
$params = ['order' => ['id' => true], 'limit' => $request['limit']];
$condition = ["`uid` = ? AND `term` LIKE ?", $uid, '#%'];
if (!empty($request['max_id'])) {
$condition = DBA::mergeConditions($condition, ["`id` < ?", $request['max_id']]);
}
if (!empty($request['since_id'])) {
$condition = DBA::mergeConditions($condition, ["`id` > ?", $request['since_id']]);
}
if (!empty($request['min_id'])) {
$condition = DBA::mergeConditions($condition, ["`id` > ?", $request['min_id']]);
$params['order'] = ['id'];
}
$return = [];
$saved_searches = DBA::select('search', ['id', 'term'], $condition);
while ($saved_search = DBA::fetch($saved_searches)) {
self::setBoundaries($saved_search['id']);
$tag = ['name' => ltrim($saved_search['term'], '#')];
$hashtag = new \Friendica\Object\Api\Mastodon\Tag($this->baseUrl, $tag, [], true);
$return[] = $hashtag->toArray();
}
DBA::close($saved_searches);
if (!empty($request['min_id'])) {
$return = array_reverse($return);
}
self::setLinkHeader();
System::jsonExit($return);
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @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;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Module\BaseApi;
/**
* @see https://docs.joinmastodon.org/methods/tags/
*/
class Tags extends BaseApi
{
/**
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
protected function rawContent(array $request = [])
{
self::checkAllowedScope(self::SCOPE_READ);
$uid = self::getCurrentUserID();
if (empty($this->parameters['hashtag'])) {
DI::mstdnError()->UnprocessableEntity();
}
$tag = ltrim($this->parameters['hashtag'], '#');
$following = DBA::exists('search', ['uid' => $uid, 'term' => '#' . $tag]);
$term = ['term' => $tag];
$hashtag = new \Friendica\Object\Api\Mastodon\Tag($this->baseUrl, $term, [], $following);
System::jsonExit($hashtag->toArray());
}
}

View File

@ -0,0 +1,51 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @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\Tags;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Module\BaseApi;
/**
* @see https://docs.joinmastodon.org/methods/tags/#follow
*/
class Follow extends BaseApi
{
protected function post(array $request = [])
{
self::checkAllowedScope(self::SCOPE_WRITE);
$uid = self::getCurrentUserID();
if (empty($this->parameters['hashtag'])) {
DI::mstdnError()->UnprocessableEntity();
}
$fields = ['uid' => $uid, 'term' => '#' . ltrim($this->parameters['hashtag'], '#')];
if (!DBA::exists('search', $fields)) {
DBA::insert('search', $fields);
}
$hashtag = new \Friendica\Object\Api\Mastodon\Tag($this->baseUrl, $fields, [], true);
System::jsonExit($hashtag->toArray());
}
}

View File

@ -0,0 +1,50 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @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\Tags;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Module\BaseApi;
/**
* @see https://docs.joinmastodon.org/methods/tags/#unfollow
*/
class Unfollow extends BaseApi
{
protected function post(array $request = [])
{
self::checkAllowedScope(self::SCOPE_WRITE);
$uid = self::getCurrentUserID();
if (empty($this->parameters['hashtag'])) {
DI::mstdnError()->UnprocessableEntity();
}
$term = ['uid' => $uid, 'term' => '#' . ltrim($this->parameters['hashtag'], '#')];
DBA::delete('search', $term);
$hashtag = new \Friendica\Object\Api\Mastodon\Tag($this->baseUrl, $term, [], false);
System::jsonExit($hashtag->toArray());
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @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\Trends;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Post;
use Friendica\Module\BaseApi;
use Friendica\Util\DateTimeFormat;
/**
* @see https://docs.joinmastodon.org/methods/trends/#links
*/
class Links extends BaseApi
{
/**
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
protected function rawContent(array $request = [])
{
$request = $this->getRequest([
'limit' => 10, // Maximum number of results to return. Defaults to 10.
], $request);
$condition = ["EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-thread-view`.`uri-id` AND `type` = ? AND NOT `name` IS NULL AND NOT `description` IS NULL) AND NOT `private` AND `commented` > ? AND `created` > ?",
Post\Media::HTML, DateTimeFormat::utc('now -1 day'), DateTimeFormat::utc('now -1 week')];
$condition = DBA::mergeConditions($condition, ['network' => Protocol::FEDERATED]);
$trending = [];
$statuses = Post::selectPostThread(['uri-id', 'total-comments', 'total-actors'], $condition, ['limit' => $request['limit'], 'order' => ['total-actors' => true]]);
while ($status = Post::fetch($statuses)) {
$history = [['day' => (string)time(), 'uses' => (string)$status['total-comments'], 'accounts' => (string)$status['total-actors']]];
$trending[] = DI::mstdnCard()->createFromUriId($status['uri-id'], $history)->toArray();
}
DBA::close($statuses);
System::jsonExit($trending);
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @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\Trends;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Post;
use Friendica\Module\BaseApi;
use Friendica\Util\DateTimeFormat;
/**
* @see https://docs.joinmastodon.org/methods/trends/#statuses
*/
class Statuses extends BaseApi
{
/**
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
protected function rawContent(array $request = [])
{
$uid = self::getCurrentUserID();
$request = $this->getRequest([
'limit' => 10, // Maximum number of results to return. Defaults to 10.
], $request);
$condition = ["NOT `private` AND `commented` > ? AND `created` > ?", DateTimeFormat::utc('now -1 day'), DateTimeFormat::utc('now -1 week')];
$condition = DBA::mergeConditions($condition, ['network' => Protocol::FEDERATED]);
$trending = [];
$statuses = Post::selectPostThread(['uri-id'], $condition, ['limit' => $request['limit'], 'order' => ['total-actors' => true]]);
while ($status = Post::fetch($statuses)) {
$trending[] = DI::mstdnStatus()->createFromUriId($status['uri-id'], $uid);
}
DBA::close($statuses);
System::jsonExit($trending);
}
}

View File

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Module\Api\Mastodon;
namespace Friendica\Module\Api\Mastodon\Trends;
use Friendica\Core\System;
use Friendica\DI;
@ -29,7 +29,7 @@ use Friendica\Module\BaseApi;
/**
* @see https://docs.joinmastodon.org/methods/instance/trends/
*/
class Trends extends BaseApi
class Tags extends BaseApi
{
/**
* @throws \Friendica\Network\HTTPException\InternalServerErrorException

View File

@ -59,7 +59,7 @@ class Card extends BaseDataTransferObject
* @param array $attachment Attachment record
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function __construct(array $attachment)
public function __construct(array $attachment, array $history = [])
{
$this->url = $attachment['url'] ?? '';
$this->title = $attachment['title'] ?? '';
@ -72,6 +72,7 @@ class Card extends BaseDataTransferObject
$this->width = $attachment['width'] ?? 0;
$this->height = $attachment['height'] ?? 0;
$this->image = $attachment['image'] ?? '';
$this->history = $history;
}
/**

View File

@ -37,18 +37,23 @@ class Tag extends BaseDataTransferObject
protected $url = null;
/** @var array */
protected $history = [];
/** @var bool */
protected $following = false;
/**
* Creates a hashtag record from an tag-view record.
*
* @param BaseURL $baseUrl
* @param array $tag tag-view record
* @param array $tag tag-view record
* @param array $history
* @param array $following "true" if the user is following this tag
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function __construct(BaseURL $baseUrl, array $tag, array $history = [])
public function __construct(BaseURL $baseUrl, array $tag, array $history = [], bool $following = false)
{
$this->name = strtolower($tag['name']);
$this->url = $baseUrl . '/search?tag=' . urlencode($this->name);
$this->history = $history;
$this->name = strtolower($tag['name']);
$this->url = $baseUrl . '/search?tag=' . urlencode($this->name);
$this->history = $history;
$this->following = $following;
}
}

View File

@ -622,7 +622,7 @@ class Post
public function addChild(Post $item)
{
if (!$item->getId()) {
Logger::fatal('Post object has no id', ['post' => $item]);
Logger::error('Post object has no id', ['post' => $item]);
return false;
} elseif ($this->getChild($item->getId())) {
Logger::warning('Post object already exists', ['post' => $item]);
@ -633,7 +633,7 @@ class Post
* Only add what will be displayed
*/
if ($item->getDataValue('network') === Protocol::MAIL && DI::userSession()->getLocalUserId() != $item->getDataValue('uid')) {
Logger::warning('Post object does not belong to local user', ['post' => $item, 'local_user' => $local_user]);
Logger::warning('Post object does not belong to local user', ['post' => $item, 'local_user' => DI::userSession()->getLocalUserId()]);
return false;
} elseif (DI::activity()->match($item->getDataValue('verb'), Activity::LIKE) ||
DI::activity()->match($item->getDataValue('verb'), Activity::DISLIKE)) {

View File

@ -55,7 +55,7 @@
use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1491);
define('DB_UPDATE_VERSION', 1493);
}
return [

View File

@ -664,6 +664,8 @@
"question-end-time" => ["post-question", "end-time"],
"has-categories" => "0",
"has-media" => "EXISTS(SELECT `id` FROM `post-media` WHERE `post-media`.`uri-id` = `post-thread`.`uri-id`)",
"total-comments" => "(SELECT COUNT(*) FROM `post` WHERE `parent-uri-id` = `post-thread`.`uri-id` AND `gravity` = 6)",
"total-actors" => "(SELECT COUNT(DISTINCT(`author-id`)) FROM `post` WHERE `parent-uri-id` = `post-thread`.`uri-id` AND `gravity` = 6)",
"signed_text" => ["diaspora-interaction", "interaction"],
"parent-guid" => ["parent-item-uri", "guid"],
"parent-network" => ["parent-post", "network"],

View File

@ -233,10 +233,10 @@ return [
'/featured_tags' => [Module\Api\Mastodon\Unimplemented::class, [R::GET, R::POST]], // not supported
'/featured_tags/{id:\d+}' => [Module\Api\Mastodon\Unimplemented::class, [R::DELETE ]], // not supported
'/featured_tags/suggestions' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not supported
'/filters' => [Module\Api\Mastodon\Filters::class, [R::GET ]], // Dummy, not supported
'/filters/{id:\d+}' => [Module\Api\Mastodon\Unimplemented::class, [R::GET, R::POST, R::PUT, R::DELETE]], // not supported
'/follow_requests' => [Module\Api\Mastodon\FollowRequests::class, [R::GET ]],
'/follow_requests/{id:\d+}/{action}' => [Module\Api\Mastodon\FollowRequests::class, [ R::POST]],
'/followed_tags' => [Module\Api\Mastodon\FollowedTags::class, [R::GET ]],
'/instance' => [Module\Api\Mastodon\Instance::class, [R::GET ]],
'/instance/activity' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // @todo
'/instance/peers' => [Module\Api\Mastodon\Instance\Peers::class, [R::GET ]],
@ -287,18 +287,22 @@ return [
'/streaming/user' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not implemented
'/streaming/user/notification' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not implemented
'/suggestions/{id:\d+}' => [Module\Api\Mastodon\Unimplemented::class, [R::DELETE ]], // not implemented
'/tags/{hashtag}' => [Module\Api\Mastodon\Tags::class, [R::GET ]],
'/tags/{hashtag}/follow' => [Module\Api\Mastodon\Tags\Follow::class, [ R::POST]],
'/tags/{hashtag}/unfollow' => [Module\Api\Mastodon\Tags\Unfollow::class, [ R::POST]],
'/timelines/direct' => [Module\Api\Mastodon\Timelines\Direct::class, [R::GET ]],
'/timelines/home' => [Module\Api\Mastodon\Timelines\Home::class, [R::GET ]],
'/timelines/list/{id:\d+}' => [Module\Api\Mastodon\Timelines\ListTimeline::class, [R::GET ]],
'/timelines/public' => [Module\Api\Mastodon\Timelines\PublicTimeline::class, [R::GET ]],
'/timelines/tag/{hashtag}' => [Module\Api\Mastodon\Timelines\Tag::class, [R::GET ]],
'/trends' => [Module\Api\Mastodon\Trends::class, [R::GET ]],
'/trends/links' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not implemented
'/trends/statuses' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not implemented
'/trends/tags' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not implemented
'/trends' => [Module\Api\Mastodon\Trends\Tags::class, [R::GET ]],
'/trends/links' => [Module\Api\Mastodon\Trends\Links::class, [R::GET ]],
'/trends/statuses' => [Module\Api\Mastodon\Trends\Statuses::class, [R::GET ]],
'/trends/tags' => [Module\Api\Mastodon\Trends\Tags::class, [R::GET ]],
],
'/v{version:\d+}' => [
'/admin/accounts' => [Module\Api\Mastodon\Unimplemented::class, [R::GET ]], // not supported
'/filters' => [Module\Api\Mastodon\Filters::class, [R::GET ]], // Dummy, not supported
'/media' => [Module\Api\Mastodon\Media::class, [ R::POST]],
'/search' => [Module\Api\Mastodon\Search::class, [R::GET ]],
'/suggestions' => [Module\Api\Mastodon\Suggestions::class, [R::GET ]],