mirror of
https://github.com/friendica/friendica
synced 2025-03-10 23:08:25 +00:00
Merge pull request #14835 from annando/api
Improved Mastodon API compatibility
This commit is contained in:
commit
af17e33d4e
17 changed files with 186 additions and 81 deletions
|
@ -1,6 +1,6 @@
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- Friendica 2025.02-dev (Interrupted Fern)
|
-- Friendica 2025.02-dev (Interrupted Fern)
|
||||||
-- DB_UPDATE_VERSION 1579
|
-- DB_UPDATE_VERSION 1580
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -1441,6 +1441,9 @@ CREATE TABLE IF NOT EXISTS `post-media` (
|
||||||
`publisher-url` varbinary(383) COMMENT 'URL of the publisher of the media',
|
`publisher-url` varbinary(383) COMMENT 'URL of the publisher of the media',
|
||||||
`publisher-name` varchar(255) COMMENT 'Name of the publisher of the media',
|
`publisher-name` varchar(255) COMMENT 'Name of the publisher of the media',
|
||||||
`publisher-image` varbinary(383) COMMENT 'Image of the publisher of the media',
|
`publisher-image` varbinary(383) COMMENT 'Image of the publisher of the media',
|
||||||
|
`language` char(3) COMMENT 'Language information about this media in the ISO 639 format',
|
||||||
|
`published` datetime COMMENT 'Publification date of this media',
|
||||||
|
`modified` datetime COMMENT 'Modification date of this media',
|
||||||
PRIMARY KEY(`id`),
|
PRIMARY KEY(`id`),
|
||||||
UNIQUE INDEX `uri-id-url` (`uri-id`,`url`(512)),
|
UNIQUE INDEX `uri-id-url` (`uri-id`,`url`(512)),
|
||||||
INDEX `uri-id-id` (`uri-id`,`id`),
|
INDEX `uri-id-id` (`uri-id`,`id`),
|
||||||
|
|
|
@ -30,6 +30,9 @@ Fields
|
||||||
| publisher-url | URL of the publisher of the media | varbinary(383) | YES | | NULL | |
|
| publisher-url | URL of the publisher of the media | varbinary(383) | YES | | NULL | |
|
||||||
| publisher-name | Name of the publisher of the media | varchar(255) | YES | | NULL | |
|
| publisher-name | Name of the publisher of the media | varchar(255) | YES | | NULL | |
|
||||||
| publisher-image | Image of the publisher of the media | varbinary(383) | YES | | NULL | |
|
| publisher-image | Image of the publisher of the media | varbinary(383) | YES | | NULL | |
|
||||||
|
| language | Language information about this media in the ISO 639 format | char(3) | YES | | NULL | |
|
||||||
|
| published | Publification date of this media | datetime | YES | | NULL | |
|
||||||
|
| modified | Modification date of this media | datetime | YES | | NULL | |
|
||||||
|
|
||||||
Indexes
|
Indexes
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -512,7 +512,7 @@ abstract class BaseModule implements ICanHandleRequests
|
||||||
* @throws HTTPException\InternalServerErrorException
|
* @throws HTTPException\InternalServerErrorException
|
||||||
* @see json_encode()
|
* @see json_encode()
|
||||||
*/
|
*/
|
||||||
public function jsonExit($content, string $content_type = 'application/json', int $options = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
|
public function jsonExit($content, string $content_type = 'application/json; charset=utf-8', int $options = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)
|
||||||
{
|
{
|
||||||
$this->httpExit(json_encode($content, $options), ICanCreateResponses::TYPE_JSON, $content_type);
|
$this->httpExit(json_encode($content, $options), ICanCreateResponses::TYPE_JSON, $content_type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ class Card extends BaseFactory
|
||||||
$data['url'] = $media[0]['url'];
|
$data['url'] = $media[0]['url'];
|
||||||
$data['title'] = $media[0]['name'];
|
$data['title'] = $media[0]['name'];
|
||||||
$data['description'] = $media[0]['description'];
|
$data['description'] = $media[0]['description'];
|
||||||
|
$data['language'] = $media[0]['language'];
|
||||||
$data['type'] = 'link';
|
$data['type'] = 'link';
|
||||||
$data['author_name'] = $media[0]['author-name'];
|
$data['author_name'] = $media[0]['author-name'];
|
||||||
$data['author_url'] = $media[0]['author-url'];
|
$data['author_url'] = $media[0]['author-url'];
|
||||||
|
@ -57,6 +58,7 @@ class Card extends BaseFactory
|
||||||
$data['width'] = $media[0]['preview-width'];
|
$data['width'] = $media[0]['preview-width'];
|
||||||
$data['height'] = $media[0]['preview-height'];
|
$data['height'] = $media[0]['preview-height'];
|
||||||
$data['blurhash'] = $media[0]['blurhash'];
|
$data['blurhash'] = $media[0]['blurhash'];
|
||||||
|
$data['published'] = $media[0]['published'];
|
||||||
|
|
||||||
return new \Friendica\Object\Api\Mastodon\Card($data, $history);
|
return new \Friendica\Object\Api\Mastodon\Card($data, $history);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,8 @@ class Relationship extends BaseFactory
|
||||||
$pcid,
|
$pcid,
|
||||||
$contact,
|
$contact,
|
||||||
Contact\User::isBlocked($cid, $uid),
|
Contact\User::isBlocked($cid, $uid),
|
||||||
Contact\User::isIgnored($cid, $uid)
|
Contact\User::isIgnored($cid, $uid),
|
||||||
|
Contact\User::isIsBlocked($cid, $uid),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,6 +362,13 @@ class Media
|
||||||
$media['publisher-name'] = $gserver['site_name'] ?? null;
|
$media['publisher-name'] = $gserver['site_name'] ?? null;
|
||||||
$media['publisher-image'] = null;
|
$media['publisher-image'] = null;
|
||||||
|
|
||||||
|
if (!empty($item['language'])) {
|
||||||
|
$media['language'] = array_key_first(json_decode($item['language'], true));
|
||||||
|
}
|
||||||
|
|
||||||
|
$media['published'] = $item['created'];
|
||||||
|
$media['modified'] = $item['changed'];
|
||||||
|
|
||||||
DI::logger()->debug('Activity detected', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'plink' => $item['plink'], 'uri' => $item['uri']]);
|
DI::logger()->debug('Activity detected', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'plink' => $item['plink'], 'uri' => $item['uri']]);
|
||||||
return $media;
|
return $media;
|
||||||
}
|
}
|
||||||
|
@ -403,6 +410,9 @@ class Media
|
||||||
$media['publisher-url'] = $gserver['url'] ?? null;
|
$media['publisher-url'] = $gserver['url'] ?? null;
|
||||||
$media['publisher-name'] = $gserver['site_name'] ?? null;
|
$media['publisher-name'] = $gserver['site_name'] ?? null;
|
||||||
$media['publisher-image'] = null;
|
$media['publisher-image'] = null;
|
||||||
|
$media['language'] = null;
|
||||||
|
$media['published'] = $contact['created'];
|
||||||
|
$media['modified'] = $contact['updated'];
|
||||||
|
|
||||||
DI::logger()->debug('Account detected', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'uri' => $contact['url']]);
|
DI::logger()->debug('Account detected', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'uri' => $contact['url']]);
|
||||||
return $media;
|
return $media;
|
||||||
|
@ -439,6 +449,9 @@ class Media
|
||||||
$media['publisher-url'] = $data['publisher_url'] ?? null;
|
$media['publisher-url'] = $data['publisher_url'] ?? null;
|
||||||
$media['publisher-name'] = $data['publisher_name'] ?? null;
|
$media['publisher-name'] = $data['publisher_name'] ?? null;
|
||||||
$media['publisher-image'] = $data['publisher_img'] ?? null;
|
$media['publisher-image'] = $data['publisher_img'] ?? null;
|
||||||
|
$media['language'] = $data['language'] ?? null;
|
||||||
|
$media['published'] = $data['published'] ?? null;
|
||||||
|
$media['modified'] = $data['modified'] ?? null;
|
||||||
|
|
||||||
return $media;
|
return $media;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Relationships extends BaseApi
|
||||||
], $request);
|
], $request);
|
||||||
|
|
||||||
if (empty($request['id'])) {
|
if (empty($request['id'])) {
|
||||||
$this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity());
|
$this->jsonExit([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_array($request['id'])) {
|
if (!is_array($request['id'])) {
|
||||||
|
|
|
@ -50,6 +50,10 @@ class Search extends BaseApi
|
||||||
|
|
||||||
$limit = min($request['limit'], 40);
|
$limit = min($request['limit'], 40);
|
||||||
|
|
||||||
|
if (Network::isValidHttpUrl($request['q']) && ($request['offset'] == 0)) {
|
||||||
|
$this->searchLinks($uid, $request['q'], $request['type']);
|
||||||
|
}
|
||||||
|
|
||||||
$result = ['accounts' => [], 'statuses' => [], 'hashtags' => []];
|
$result = ['accounts' => [], 'statuses' => [], 'hashtags' => []];
|
||||||
|
|
||||||
if (empty($request['type']) || ($request['type'] == 'accounts')) {
|
if (empty($request['type']) || ($request['type'] == 'accounts')) {
|
||||||
|
@ -79,6 +83,43 @@ class Search extends BaseApi
|
||||||
$this->jsonExit($result);
|
$this->jsonExit($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for links (either accounts or statuses). Return an empty result otherwise
|
||||||
|
*
|
||||||
|
* @param integer $uid User id
|
||||||
|
* @param string $q Search term (HTTP link)
|
||||||
|
* @param string $type Search type (or empty if not provided)
|
||||||
|
*/
|
||||||
|
private function searchLinks(int $uid, string $q, string $type)
|
||||||
|
{
|
||||||
|
$result = ['accounts' => [], 'statuses' => [], 'hashtags' => []];
|
||||||
|
|
||||||
|
$data = ['uri-id' => -1, 'type' => Post\Media::UNKNOWN, 'url' => $q];
|
||||||
|
$data = Post\Media::fetchAdditionalData($data);
|
||||||
|
|
||||||
|
if ((empty($type) || ($type == 'statuses')) && in_array($data['type'], [Post\Media::HTML, Post\Media::ACTIVITY, Post\Media::UNKNOWN])) {
|
||||||
|
$q = Network::convertToIdn($q);
|
||||||
|
// If the user-specific search failed, we search and probe a public post
|
||||||
|
$item_id = Item::fetchByLink($q, $uid) ?: Item::fetchByLink($q);
|
||||||
|
if ($item_id && $item = Post::selectFirst(['uri-id'], ['id' => $item_id])) {
|
||||||
|
$result['statuses'] = [DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, self::appSupportsQuotes())];
|
||||||
|
$this->jsonExit($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((empty($type) || ($type == 'accounts')) && in_array($data['type'], [Post\Media::HTML, Post\Media::ACCOUNT, Post\Media::UNKNOWN])) {
|
||||||
|
$id = Contact::getIdForURL($q, 0, false);
|
||||||
|
if ($id) {
|
||||||
|
$result['accounts'] = [DI::mstdnAccount()->createFromContactId($id, $uid)];
|
||||||
|
$this->jsonExit($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($data['type'], [Post\Media::HTML, Post\Media::TEXT, Post\Media::ACCOUNT, Post\Media::ACTIVITY, Post\Media::UNKNOWN])) {
|
||||||
|
$this->jsonExit($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $uid
|
* @param int $uid
|
||||||
* @param string $q
|
* @param string $q
|
||||||
|
@ -93,9 +134,7 @@ class Search extends BaseApi
|
||||||
*/
|
*/
|
||||||
private function searchAccounts(int $uid, string $q, bool $resolve, int $limit, int $offset, bool $following)
|
private function searchAccounts(int $uid, string $q, bool $resolve, int $limit, int $offset, bool $following)
|
||||||
{
|
{
|
||||||
if (($offset == 0) && (strrpos($q, '@') > 0 || Network::isValidHttpUrl($q))
|
if (($offset == 0) && (strrpos($q, '@') > 0) && $id = Contact::getIdForURL($q, 0, $resolve ? null : false)) {
|
||||||
&& $id = Contact::getIdForURL($q, 0, $resolve ? null : false)
|
|
||||||
) {
|
|
||||||
return DI::mstdnAccount()->createFromContactId($id, $uid);
|
return DI::mstdnAccount()->createFromContactId($id, $uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,19 +161,6 @@ class Search extends BaseApi
|
||||||
*/
|
*/
|
||||||
private function searchStatuses(int $uid, string $q, string $account_id, int $max_id, int $min_id, int $limit, int $offset)
|
private function searchStatuses(int $uid, string $q, string $account_id, int $max_id, int $min_id, int $limit, int $offset)
|
||||||
{
|
{
|
||||||
if (Network::isValidHttpUrl($q)) {
|
|
||||||
// Unique post search, any offset greater than 0 should return empty result
|
|
||||||
if ($offset > 0) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
$q = Network::convertToIdn($q);
|
|
||||||
// If the user-specific search failed, we search and probe a public post
|
|
||||||
$item_id = Item::fetchByLink($q, $uid) ?: Item::fetchByLink($q);
|
|
||||||
if ($item_id && $item = Post::selectFirst(['uri-id'], ['id' => $item_id])) {
|
|
||||||
return DI::mstdnStatus()->createFromUriId($item['uri-id'], $uid, self::appSupportsQuotes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$params = ['order' => ['uri-id' => true], 'limit' => [$offset, $limit]];
|
$params = ['order' => ['uri-id' => true], 'limit' => [$offset, $limit]];
|
||||||
|
|
||||||
if (substr($q, 0, 1) == '#') {
|
if (substr($q, 0, 1) == '#') {
|
||||||
|
|
|
@ -38,6 +38,8 @@ class Account extends BaseDataTransferObject
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
protected $discoverable;
|
protected $discoverable;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
|
protected $indexable;
|
||||||
|
/** @var bool */
|
||||||
protected $group;
|
protected $group;
|
||||||
/** @var string|null (Datetime) */
|
/** @var string|null (Datetime) */
|
||||||
protected $created_at;
|
protected $created_at;
|
||||||
|
@ -45,6 +47,8 @@ class Account extends BaseDataTransferObject
|
||||||
protected $note;
|
protected $note;
|
||||||
/** @var string (URL)*/
|
/** @var string (URL)*/
|
||||||
protected $url;
|
protected $url;
|
||||||
|
/** @var string (URL)*/
|
||||||
|
protected $uri;
|
||||||
/** @var string (URL) */
|
/** @var string (URL) */
|
||||||
protected $avatar;
|
protected $avatar;
|
||||||
/** @var string (URL) */
|
/** @var string (URL) */
|
||||||
|
@ -61,6 +65,8 @@ class Account extends BaseDataTransferObject
|
||||||
protected $statuses_count;
|
protected $statuses_count;
|
||||||
/** @var string|null (Datetime) */
|
/** @var string|null (Datetime) */
|
||||||
protected $last_status_at = null;
|
protected $last_status_at = null;
|
||||||
|
/** @var bool */
|
||||||
|
protected $hide_collections = false;
|
||||||
/** @var Emoji[] */
|
/** @var Emoji[] */
|
||||||
protected $emojis;
|
protected $emojis;
|
||||||
/** @var Account|null */
|
/** @var Account|null */
|
||||||
|
@ -80,20 +86,21 @@ class Account extends BaseDataTransferObject
|
||||||
{
|
{
|
||||||
$this->id = (string)$account['pid'];
|
$this->id = (string)$account['pid'];
|
||||||
$this->username = $account['nick'];
|
$this->username = $account['nick'];
|
||||||
$this->acct =
|
$this->acct = strpos($account['url'], $baseUrl . '/') === 0 ?
|
||||||
strpos($account['url'], $baseUrl . '/') === 0 ?
|
|
||||||
$account['nick'] :
|
$account['nick'] :
|
||||||
$account['addr'];
|
$account['addr'];
|
||||||
$this->display_name = $account['name'];
|
$this->display_name = $account['name'];
|
||||||
$this->locked = (bool)$account['manually-approve'];
|
$this->locked = (bool)$account['manually-approve'];
|
||||||
$this->bot = ($account['contact-type'] == Contact::TYPE_NEWS);
|
$this->bot = ($account['contact-type'] == Contact::TYPE_NEWS);
|
||||||
$this->discoverable = !$account['unsearchable'];
|
$this->discoverable = !$account['unsearchable'];
|
||||||
|
$this->indexable = $this->discoverable;
|
||||||
$this->group = ($account['contact-type'] == Contact::TYPE_COMMUNITY);
|
$this->group = ($account['contact-type'] == Contact::TYPE_COMMUNITY);
|
||||||
|
|
||||||
$this->created_at = DateTimeFormat::utc($account['created'] ?: DBA::NULL_DATETIME, DateTimeFormat::JSON);
|
$this->created_at = DateTimeFormat::utc($account['created'] ?: DBA::NULL_DATETIME, DateTimeFormat::JSON);
|
||||||
|
|
||||||
$this->note = BBCode::convertForUriId($account['uri-id'], $account['about'], BBCode::EXTERNAL);
|
$this->note = BBCode::convertForUriId($account['uri-id'], $account['about'], BBCode::EXTERNAL);
|
||||||
$this->url = $account['url'];
|
$this->url = $account['alias'] ?: $account['url'];
|
||||||
|
$this->uri = $account['url'];
|
||||||
$this->avatar = Contact::getAvatarUrlForId($account['id'] ?? 0 ?: $account['pid'], Proxy::SIZE_SMALL, $account['updated'], $account['guid'] ?? '');
|
$this->avatar = Contact::getAvatarUrlForId($account['id'] ?? 0 ?: $account['pid'], Proxy::SIZE_SMALL, $account['updated'], $account['guid'] ?? '');
|
||||||
$this->avatar_static = Contact::getAvatarUrlForId($account['id'] ?? 0 ?: $account['pid'], Proxy::SIZE_SMALL, $account['updated'], $account['guid'] ?? '', true);
|
$this->avatar_static = Contact::getAvatarUrlForId($account['id'] ?? 0 ?: $account['pid'], Proxy::SIZE_SMALL, $account['updated'], $account['guid'] ?? '', true);
|
||||||
$this->header = Contact::getHeaderUrlForId($account['id'] ?? 0 ?: $account['pid'], '', $account['updated'], $account['guid'] ?? '');
|
$this->header = Contact::getHeaderUrlForId($account['id'] ?? 0 ?: $account['pid'], '', $account['updated'], $account['guid'] ?? '');
|
||||||
|
|
|
@ -63,8 +63,8 @@ class Application extends BaseDataTransferObject
|
||||||
unset($application['redirect_uri']);
|
unset($application['redirect_uri']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($application['website'])) {
|
if (empty($application['vapid_key'])) {
|
||||||
unset($application['website']);
|
unset($application['vapid_key']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $application;
|
return $application;
|
||||||
|
|
|
@ -27,6 +27,8 @@ class Attachment extends BaseDataTransferObject
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $remote_url;
|
protected $remote_url;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
protected $preview_remote_url;
|
||||||
|
/** @var string */
|
||||||
protected $text_url;
|
protected $text_url;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $description;
|
protected $description;
|
||||||
|
@ -52,7 +54,6 @@ class Attachment extends BaseDataTransferObject
|
||||||
$this->url = $url;
|
$this->url = $url;
|
||||||
$this->preview_url = $preview;
|
$this->preview_url = $preview;
|
||||||
$this->remote_url = $remote;
|
$this->remote_url = $remote;
|
||||||
$this->text_url = $this->remote_url ?? $this->url;
|
|
||||||
$this->description = $attachment['description'];
|
$this->description = $attachment['description'];
|
||||||
$this->blurhash = $attachment['blurhash'];
|
$this->blurhash = $attachment['blurhash'];
|
||||||
if ($type === 'image') {
|
if ($type === 'image') {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
namespace Friendica\Object\Api\Mastodon;
|
namespace Friendica\Object\Api\Mastodon;
|
||||||
|
|
||||||
use Friendica\BaseDataTransferObject;
|
use Friendica\BaseDataTransferObject;
|
||||||
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Card
|
* Class Card
|
||||||
|
@ -23,6 +24,8 @@ class Card extends BaseDataTransferObject
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $description;
|
protected $description;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
protected $language;
|
||||||
|
/** @var string */
|
||||||
protected $type;
|
protected $type;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $author_name;
|
protected $author_name;
|
||||||
|
@ -41,9 +44,15 @@ class Card extends BaseDataTransferObject
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $image;
|
protected $image;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
protected $image_description = '';
|
||||||
|
/** @var string */
|
||||||
protected $embed_url;
|
protected $embed_url;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $blurhash;
|
protected $blurhash;
|
||||||
|
/** @var string|null (Datetime) */
|
||||||
|
protected $published_at;
|
||||||
|
/** @var array */
|
||||||
|
protected $authors = [];
|
||||||
/** @var array */
|
/** @var array */
|
||||||
protected $history;
|
protected $history;
|
||||||
|
|
||||||
|
@ -58,6 +67,7 @@ class Card extends BaseDataTransferObject
|
||||||
$this->url = $attachment['url'] ?? '';
|
$this->url = $attachment['url'] ?? '';
|
||||||
$this->title = $attachment['title'] ?? '';
|
$this->title = $attachment['title'] ?? '';
|
||||||
$this->description = $attachment['description'] ?? '';
|
$this->description = $attachment['description'] ?? '';
|
||||||
|
$this->language = $attachment['language'] ?? '';
|
||||||
$this->type = $attachment['type'] ?? '';
|
$this->type = $attachment['type'] ?? '';
|
||||||
$this->author_name = $attachment['author_name'] ?? '';
|
$this->author_name = $attachment['author_name'] ?? '';
|
||||||
$this->author_url = $attachment['author_url'] ?? '';
|
$this->author_url = $attachment['author_url'] ?? '';
|
||||||
|
@ -69,6 +79,7 @@ class Card extends BaseDataTransferObject
|
||||||
$this->image = $attachment['image'] ?? '';
|
$this->image = $attachment['image'] ?? '';
|
||||||
$this->embed_url = '';
|
$this->embed_url = '';
|
||||||
$this->blurhash = $attachment['blurhash'] ?? '';
|
$this->blurhash = $attachment['blurhash'] ?? '';
|
||||||
|
$this->published_at = !empty($attachment['published']) ? DateTimeFormat::utc($attachment['published'], DateTimeFormat::JSON) : null;
|
||||||
$this->history = $history;
|
$this->history = $history;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +94,10 @@ class Card extends BaseDataTransferObject
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty($this->history)) {
|
||||||
|
unset($this->history);
|
||||||
|
}
|
||||||
|
|
||||||
return parent::toArray();
|
return parent::toArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,15 +46,19 @@ class Relationship extends BaseDataTransferObject
|
||||||
protected $blocking = false;
|
protected $blocking = false;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
protected $domain_blocking = false;
|
protected $domain_blocking = false;
|
||||||
|
/** @var bool */
|
||||||
|
protected $blocked_by = false;
|
||||||
|
/**
|
||||||
|
* Unsupported
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $languages = [];
|
||||||
/**
|
/**
|
||||||
* Unsupported
|
* Unsupported
|
||||||
* @var bool
|
* @var bool
|
||||||
*/
|
*/
|
||||||
protected $blocked_by = false;
|
protected $requested_by = false;
|
||||||
/**
|
/** @var string */
|
||||||
* Unsupported
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $note = '';
|
protected $note = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +67,7 @@ class Relationship extends BaseDataTransferObject
|
||||||
* @param bool $blocked "true" if user is blocked
|
* @param bool $blocked "true" if user is blocked
|
||||||
* @param bool $muted "true" if user is muted
|
* @param bool $muted "true" if user is muted
|
||||||
*/
|
*/
|
||||||
public function __construct(int $contactId, array $contactRecord, bool $blocked = false, bool $muted = false)
|
public function __construct(int $contactId, array $contactRecord, bool $blocked = false, bool $muted = false, bool $isBlocked = false)
|
||||||
{
|
{
|
||||||
$this->id = (string)$contactId;
|
$this->id = (string)$contactId;
|
||||||
$this->following = false;
|
$this->following = false;
|
||||||
|
@ -86,6 +90,7 @@ class Relationship extends BaseDataTransferObject
|
||||||
$this->muting = (bool)($contactRecord['readonly'] ?? false) || $muted;
|
$this->muting = (bool)($contactRecord['readonly'] ?? false) || $muted;
|
||||||
$this->notifying = (bool)$contactRecord['notify_new_posts'] ?? false;
|
$this->notifying = (bool)$contactRecord['notify_new_posts'] ?? false;
|
||||||
$this->blocking = (bool)($contactRecord['blocked'] ?? false) || $blocked;
|
$this->blocking = (bool)($contactRecord['blocked'] ?? false) || $blocked;
|
||||||
|
$this->blocked_by = $isBlocked;
|
||||||
$this->note = $contactRecord['info'];
|
$this->note = $contactRecord['info'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ class Status extends BaseDataTransferObject
|
||||||
protected $pinned = false;
|
protected $pinned = false;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $content;
|
protected $content;
|
||||||
|
/** @var array */
|
||||||
|
protected $filtered = [];
|
||||||
/** @var Status|null */
|
/** @var Status|null */
|
||||||
protected $reblog = null;
|
protected $reblog = null;
|
||||||
/** @var Status|null - Akkoma extension, see issue https://github.com/friendica/friendica/issues/12603 */
|
/** @var Status|null - Akkoma extension, see issue https://github.com/friendica/friendica/issues/12603 */
|
||||||
|
|
|
@ -42,4 +42,13 @@ class Tag extends BaseDataTransferObject
|
||||||
$this->history = $history;
|
$this->history = $history;
|
||||||
$this->following = $following;
|
$this->following = $following;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
if (empty($this->history)) {
|
||||||
|
unset($this->history);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::toArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,6 +296,17 @@ class ParseUrl
|
||||||
|
|
||||||
$xpath = new DOMXPath($doc);
|
$xpath = new DOMXPath($doc);
|
||||||
|
|
||||||
|
$list = $xpath->query('//html[@lang]');
|
||||||
|
foreach ($list as $node) {
|
||||||
|
if ($node->attributes->length) {
|
||||||
|
foreach ($node->attributes as $attribute) {
|
||||||
|
if ($attribute->name == 'lang') {
|
||||||
|
$siteinfo['language'] = $attribute->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$list = $xpath->query('//meta[@content]');
|
$list = $xpath->query('//meta[@content]');
|
||||||
foreach ($list as $node) {
|
foreach ($list as $node) {
|
||||||
$meta_tag = [];
|
$meta_tag = [];
|
||||||
|
@ -495,6 +506,10 @@ class ParseUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($siteinfo['language'])) {
|
||||||
|
$siteinfo['language'] = explode('_', str_replace('-', '_', $siteinfo['language']))[0];
|
||||||
|
}
|
||||||
|
|
||||||
DI::logger()->info('Siteinfo fetched', ['url' => $url, 'siteinfo' => $siteinfo]);
|
DI::logger()->info('Siteinfo fetched', ['url' => $url, 'siteinfo' => $siteinfo]);
|
||||||
|
|
||||||
Hook::callAll('getsiteinfo', $siteinfo);
|
Hook::callAll('getsiteinfo', $siteinfo);
|
||||||
|
|
|
@ -44,7 +44,7 @@ use Friendica\Database\DBA;
|
||||||
|
|
||||||
// This file is required several times during the test in DbaDefinition which justifies this condition
|
// This file is required several times during the test in DbaDefinition which justifies this condition
|
||||||
if (!defined('DB_UPDATE_VERSION')) {
|
if (!defined('DB_UPDATE_VERSION')) {
|
||||||
define('DB_UPDATE_VERSION', 1579);
|
define('DB_UPDATE_VERSION', 1580);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -1447,6 +1447,9 @@ return [
|
||||||
"publisher-url" => ["type" => "varbinary(383)", "comment" => "URL of the publisher of the media"],
|
"publisher-url" => ["type" => "varbinary(383)", "comment" => "URL of the publisher of the media"],
|
||||||
"publisher-name" => ["type" => "varchar(255)", "comment" => "Name of the publisher of the media"],
|
"publisher-name" => ["type" => "varchar(255)", "comment" => "Name of the publisher of the media"],
|
||||||
"publisher-image" => ["type" => "varbinary(383)", "comment" => "Image of the publisher of the media"],
|
"publisher-image" => ["type" => "varbinary(383)", "comment" => "Image of the publisher of the media"],
|
||||||
|
"language" => ["type" => "char(3)", "comment" => "Language information about this media in the ISO 639 format"],
|
||||||
|
"published" => ["type" => "datetime", "comment" => "Publification date of this media"],
|
||||||
|
"modified" => ["type" => "datetime", "comment" => "Modification date of this media"],
|
||||||
],
|
],
|
||||||
"indexes" => [
|
"indexes" => [
|
||||||
"PRIMARY" => ["id"],
|
"PRIMARY" => ["id"],
|
||||||
|
|
Loading…
Add table
Reference in a new issue