diff --git a/database.sql b/database.sql index 5d9cc2abb0..b59a3fc0d2 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- 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-name` varchar(255) COMMENT 'Name 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`), UNIQUE INDEX `uri-id-url` (`uri-id`,`url`(512)), INDEX `uri-id-id` (`uri-id`,`id`), diff --git a/doc/database/db_post-media.md b/doc/database/db_post-media.md index 02c9a7d98a..acbd1f75cb 100644 --- a/doc/database/db_post-media.md +++ b/doc/database/db_post-media.md @@ -30,6 +30,9 @@ Fields | 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-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 ------------ diff --git a/src/BaseModule.php b/src/BaseModule.php index 27f156bef0..933f38600b 100644 --- a/src/BaseModule.php +++ b/src/BaseModule.php @@ -512,7 +512,7 @@ abstract class BaseModule implements ICanHandleRequests * @throws HTTPException\InternalServerErrorException * @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); } diff --git a/src/Factory/Api/Mastodon/Card.php b/src/Factory/Api/Mastodon/Card.php index 32388b4776..f4f69045e8 100644 --- a/src/Factory/Api/Mastodon/Card.php +++ b/src/Factory/Api/Mastodon/Card.php @@ -48,6 +48,7 @@ class Card extends BaseFactory $data['url'] = $media[0]['url']; $data['title'] = $media[0]['name']; $data['description'] = $media[0]['description']; + $data['language'] = $media[0]['language']; $data['type'] = 'link'; $data['author_name'] = $media[0]['author-name']; $data['author_url'] = $media[0]['author-url']; @@ -57,6 +58,7 @@ class Card extends BaseFactory $data['width'] = $media[0]['preview-width']; $data['height'] = $media[0]['preview-height']; $data['blurhash'] = $media[0]['blurhash']; + $data['published'] = $media[0]['published']; return new \Friendica\Object\Api\Mastodon\Card($data, $history); } diff --git a/src/Factory/Api/Mastodon/Relationship.php b/src/Factory/Api/Mastodon/Relationship.php index d12b563f10..7411f063f9 100644 --- a/src/Factory/Api/Mastodon/Relationship.php +++ b/src/Factory/Api/Mastodon/Relationship.php @@ -38,7 +38,8 @@ class Relationship extends BaseFactory $pcid, $contact, Contact\User::isBlocked($cid, $uid), - Contact\User::isIgnored($cid, $uid) + Contact\User::isIgnored($cid, $uid), + Contact\User::isIsBlocked($cid, $uid), ); } } diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 9ef6eef9ea..af5895557b 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -362,6 +362,13 @@ class Media $media['publisher-name'] = $gserver['site_name'] ?? 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']]); return $media; } @@ -403,6 +410,9 @@ class Media $media['publisher-url'] = $gserver['url'] ?? null; $media['publisher-name'] = $gserver['site_name'] ?? 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']]); return $media; @@ -439,6 +449,9 @@ class Media $media['publisher-url'] = $data['publisher_url'] ?? null; $media['publisher-name'] = $data['publisher_name'] ?? 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; } diff --git a/src/Module/Api/Mastodon/Accounts/Relationships.php b/src/Module/Api/Mastodon/Accounts/Relationships.php index 4f0c79ebfc..afdcf4cdeb 100644 --- a/src/Module/Api/Mastodon/Accounts/Relationships.php +++ b/src/Module/Api/Mastodon/Accounts/Relationships.php @@ -28,7 +28,7 @@ class Relationships extends BaseApi ], $request); if (empty($request['id'])) { - $this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity()); + $this->jsonExit([]); } if (!is_array($request['id'])) { diff --git a/src/Module/Api/Mastodon/Search.php b/src/Module/Api/Mastodon/Search.php index 9301c60cdc..668bb4d8d0 100644 --- a/src/Module/Api/Mastodon/Search.php +++ b/src/Module/Api/Mastodon/Search.php @@ -50,6 +50,10 @@ class Search extends BaseApi $limit = min($request['limit'], 40); + if (Network::isValidHttpUrl($request['q']) && ($request['offset'] == 0)) { + $this->searchLinks($uid, $request['q'], $request['type']); + } + $result = ['accounts' => [], 'statuses' => [], 'hashtags' => []]; if (empty($request['type']) || ($request['type'] == 'accounts')) { @@ -79,6 +83,43 @@ class Search extends BaseApi $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 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) { - if (($offset == 0) && (strrpos($q, '@') > 0 || Network::isValidHttpUrl($q)) - && $id = Contact::getIdForURL($q, 0, $resolve ? null : false) - ) { + if (($offset == 0) && (strrpos($q, '@') > 0) && $id = Contact::getIdForURL($q, 0, $resolve ? null : false)) { 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) { - 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]]; if (substr($q, 0, 1) == '#') { diff --git a/src/Object/Api/Mastodon/Account.php b/src/Object/Api/Mastodon/Account.php index de6cac6041..b4009b6e69 100644 --- a/src/Object/Api/Mastodon/Account.php +++ b/src/Object/Api/Mastodon/Account.php @@ -38,6 +38,8 @@ class Account extends BaseDataTransferObject /** @var bool */ protected $discoverable; /** @var bool */ + protected $indexable; + /** @var bool */ protected $group; /** @var string|null (Datetime) */ protected $created_at; @@ -45,6 +47,8 @@ class Account extends BaseDataTransferObject protected $note; /** @var string (URL)*/ protected $url; + /** @var string (URL)*/ + protected $uri; /** @var string (URL) */ protected $avatar; /** @var string (URL) */ @@ -61,6 +65,8 @@ class Account extends BaseDataTransferObject protected $statuses_count; /** @var string|null (Datetime) */ protected $last_status_at = null; + /** @var bool */ + protected $hide_collections = false; /** @var Emoji[] */ protected $emojis; /** @var Account|null */ @@ -78,36 +84,37 @@ class Account extends BaseDataTransferObject */ public function __construct(BaseURL $baseUrl, array $account, Fields $fields) { - $this->id = (string)$account['pid']; - $this->username = $account['nick']; - $this->acct = - strpos($account['url'], $baseUrl . '/') === 0 ? + $this->id = (string)$account['pid']; + $this->username = $account['nick']; + $this->acct = strpos($account['url'], $baseUrl . '/') === 0 ? $account['nick'] : $account['addr']; - $this->display_name = $account['name']; - $this->locked = (bool)$account['manually-approve']; - $this->bot = ($account['contact-type'] == Contact::TYPE_NEWS); - $this->discoverable = !$account['unsearchable']; - $this->group = ($account['contact-type'] == Contact::TYPE_COMMUNITY); + $this->display_name = $account['name']; + $this->locked = (bool)$account['manually-approve']; + $this->bot = ($account['contact-type'] == Contact::TYPE_NEWS); + $this->discoverable = !$account['unsearchable']; + $this->indexable = $this->discoverable; + $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->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_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_static = Contact::getHeaderUrlForId($account['id'] ?? 0 ?: $account['pid'], '', $account['updated'], $account['guid'] ?? '', true); $this->followers_count = $account['ap-followers_count'] ?? $account['diaspora-interacted_count'] ?? 0; $this->following_count = $account['ap-following_count'] ?? $account['diaspora-interacting_count'] ?? 0; - $this->statuses_count = $account['ap-statuses_count'] ?? $account['diaspora-post_count'] ?? 0; + $this->statuses_count = $account['ap-statuses_count'] ?? $account['diaspora-post_count'] ?? 0; - $lastItem = $account['last-item'] ? DateTimeFormat::utc($account['last-item'], 'Y-m-d') : DBA::NULL_DATETIME; - $this->last_status_at = $lastItem != DBA::NULL_DATETIME ? DateTimeFormat::utc($lastItem, DateTimeFormat::JSON) : null; + $lastItem = $account['last-item'] ? DateTimeFormat::utc($account['last-item'], 'Y-m-d') : DBA::NULL_DATETIME; + $this->last_status_at = $lastItem != DBA::NULL_DATETIME ? DateTimeFormat::utc($lastItem, DateTimeFormat::JSON) : null; // No custom emojis per account in Friendica - $this->emojis = []; - $this->fields = $fields->getArrayCopy(); + $this->emojis = []; + $this->fields = $fields->getArrayCopy(); } /** diff --git a/src/Object/Api/Mastodon/Application.php b/src/Object/Api/Mastodon/Application.php index 50837f90cb..8126bebe55 100644 --- a/src/Object/Api/Mastodon/Application.php +++ b/src/Object/Api/Mastodon/Application.php @@ -63,8 +63,8 @@ class Application extends BaseDataTransferObject unset($application['redirect_uri']); } - if (empty($application['website'])) { - unset($application['website']); + if (empty($application['vapid_key'])) { + unset($application['vapid_key']); } return $application; diff --git a/src/Object/Api/Mastodon/Attachment.php b/src/Object/Api/Mastodon/Attachment.php index e3d7600f16..604ef41fac 100644 --- a/src/Object/Api/Mastodon/Attachment.php +++ b/src/Object/Api/Mastodon/Attachment.php @@ -27,6 +27,8 @@ class Attachment extends BaseDataTransferObject /** @var string */ protected $remote_url; /** @var string */ + protected $preview_remote_url; + /** @var string */ protected $text_url; /** @var string */ protected $description; @@ -52,7 +54,6 @@ class Attachment extends BaseDataTransferObject $this->url = $url; $this->preview_url = $preview; $this->remote_url = $remote; - $this->text_url = $this->remote_url ?? $this->url; $this->description = $attachment['description']; $this->blurhash = $attachment['blurhash']; if ($type === 'image') { diff --git a/src/Object/Api/Mastodon/Card.php b/src/Object/Api/Mastodon/Card.php index 7f097abe22..7a1983ff8b 100644 --- a/src/Object/Api/Mastodon/Card.php +++ b/src/Object/Api/Mastodon/Card.php @@ -8,6 +8,7 @@ namespace Friendica\Object\Api\Mastodon; use Friendica\BaseDataTransferObject; +use Friendica\Util\DateTimeFormat; /** * Class Card @@ -23,6 +24,8 @@ class Card extends BaseDataTransferObject /** @var string */ protected $description; /** @var string */ + protected $language; + /** @var string */ protected $type; /** @var string */ protected $author_name; @@ -41,9 +44,15 @@ class Card extends BaseDataTransferObject /** @var string */ protected $image; /** @var string */ + protected $image_description = ''; + /** @var string */ protected $embed_url; /** @var string */ protected $blurhash; + /** @var string|null (Datetime) */ + protected $published_at; + /** @var array */ + protected $authors = []; /** @var array */ protected $history; @@ -55,20 +64,22 @@ class Card extends BaseDataTransferObject */ public function __construct(array $attachment, array $history = []) { - $this->url = $attachment['url'] ?? ''; - $this->title = $attachment['title'] ?? ''; - $this->description = $attachment['description'] ?? ''; - $this->type = $attachment['type'] ?? ''; - $this->author_name = $attachment['author_name'] ?? ''; - $this->author_url = $attachment['author_url'] ?? ''; + $this->url = $attachment['url'] ?? ''; + $this->title = $attachment['title'] ?? ''; + $this->description = $attachment['description'] ?? ''; + $this->language = $attachment['language'] ?? ''; + $this->type = $attachment['type'] ?? ''; + $this->author_name = $attachment['author_name'] ?? ''; + $this->author_url = $attachment['author_url'] ?? ''; $this->provider_name = $attachment['provider_name'] ?? ''; - $this->provider_url = $attachment['provider_url'] ?? ''; + $this->provider_url = $attachment['provider_url'] ?? ''; $this->html = ''; - $this->width = $attachment['width'] ?? 0; + $this->width = $attachment['width'] ?? 0; $this->height = $attachment['height'] ?? 0; - $this->image = $attachment['image'] ?? ''; + $this->image = $attachment['image'] ?? ''; $this->embed_url = ''; $this->blurhash = $attachment['blurhash'] ?? ''; + $this->published_at = !empty($attachment['published']) ? DateTimeFormat::utc($attachment['published'], DateTimeFormat::JSON) : null; $this->history = $history; } @@ -83,6 +94,10 @@ class Card extends BaseDataTransferObject return []; } + if (empty($this->history)) { + unset($this->history); + } + return parent::toArray(); } } diff --git a/src/Object/Api/Mastodon/Relationship.php b/src/Object/Api/Mastodon/Relationship.php index 1d708425cd..1158aa5459 100644 --- a/src/Object/Api/Mastodon/Relationship.php +++ b/src/Object/Api/Mastodon/Relationship.php @@ -46,15 +46,19 @@ class Relationship extends BaseDataTransferObject protected $blocking = false; /** @var bool */ protected $domain_blocking = false; + /** @var bool */ + protected $blocked_by = false; + /** + * Unsupported + * @var array + */ + protected $languages = []; /** * Unsupported * @var bool */ - protected $blocked_by = false; - /** - * Unsupported - * @var string - */ + protected $requested_by = false; + /** @var string */ protected $note = ''; /** @@ -63,7 +67,7 @@ class Relationship extends BaseDataTransferObject * @param bool $blocked "true" if user is blocked * @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->following = false; @@ -86,6 +90,7 @@ class Relationship extends BaseDataTransferObject $this->muting = (bool)($contactRecord['readonly'] ?? false) || $muted; $this->notifying = (bool)$contactRecord['notify_new_posts'] ?? false; $this->blocking = (bool)($contactRecord['blocked'] ?? false) || $blocked; + $this->blocked_by = $isBlocked; $this->note = $contactRecord['info']; } diff --git a/src/Object/Api/Mastodon/Status.php b/src/Object/Api/Mastodon/Status.php index 0e487a989c..9f68d27d14 100644 --- a/src/Object/Api/Mastodon/Status.php +++ b/src/Object/Api/Mastodon/Status.php @@ -64,6 +64,8 @@ class Status extends BaseDataTransferObject protected $pinned = false; /** @var string */ protected $content; + /** @var array */ + protected $filtered = []; /** @var Status|null */ protected $reblog = null; /** @var Status|null - Akkoma extension, see issue https://github.com/friendica/friendica/issues/12603 */ @@ -95,10 +97,10 @@ class Status extends BaseDataTransferObject */ public function __construct(array $item, Account $account, Counts $counts, UserAttributes $userAttributes, bool $sensitive, Application $application, array $mentions, array $tags, Card $card, array $attachments, array $in_reply, array $reblog, FriendicaExtension $friendica, array $quote = null, array $poll = null, array $emojis = null) { - $reblogged = !empty($reblog); - $this->id = (string)$item['uri-id']; - $this->created_at = DateTimeFormat::utc($item['created'], DateTimeFormat::JSON); - $this->edited_at = DateTimeFormat::utc($item['edited'], DateTimeFormat::JSON); + $reblogged = !empty($reblog); + $this->id = (string)$item['uri-id']; + $this->created_at = DateTimeFormat::utc($item['created'], DateTimeFormat::JSON); + $this->edited_at = DateTimeFormat::utc($item['edited'], DateTimeFormat::JSON); if ($item['gravity'] == Item::GRAVITY_COMMENT) { $this->in_reply_to_id = (string)$item['thr-parent-id']; @@ -109,7 +111,7 @@ class Status extends BaseDataTransferObject $this->sensitive = $sensitive; $this->spoiler_text = $item['title'] ?: $item['content-warning'] ?: ''; - $visibility = ['public', 'private', 'unlisted']; + $visibility = ['public', 'private', 'unlisted']; $this->visibility = $visibility[$item['private']]; $languages = json_decode($item['language'] ?? '', true); @@ -120,28 +122,28 @@ class Status extends BaseDataTransferObject $this->language = null; } - $this->uri = $item['uri']; - $this->url = $item['plink'] ?? null; - $this->replies_count = $reblogged ? 0 : $counts->replies; - $this->reblogs_count = $reblogged ? 0 : $counts->reblogs; - $this->favourites_count = $reblogged ? 0 : $counts->favourites; - $this->favourited = $userAttributes->favourited; - $this->reblogged = $userAttributes->reblogged; - $this->muted = $userAttributes->muted; - $this->bookmarked = $userAttributes->bookmarked; - $this->pinned = $userAttributes->pinned; - $this->content = $reblogged ? '' : BBCode::convertForUriId($item['uri-id'], BBCode::setMentionsToNicknames($item['raw-body'] ?? $item['body']), BBCode::MASTODON_API); - $this->reblog = $reblog; - $this->quote = $quote; - $this->application = $application->toArray(); - $this->account = $account->toArray(); + $this->uri = $item['uri']; + $this->url = $item['plink'] ?? null; + $this->replies_count = $reblogged ? 0 : $counts->replies; + $this->reblogs_count = $reblogged ? 0 : $counts->reblogs; + $this->favourites_count = $reblogged ? 0 : $counts->favourites; + $this->favourited = $userAttributes->favourited; + $this->reblogged = $userAttributes->reblogged; + $this->muted = $userAttributes->muted; + $this->bookmarked = $userAttributes->bookmarked; + $this->pinned = $userAttributes->pinned; + $this->content = $reblogged ? '' : BBCode::convertForUriId($item['uri-id'], BBCode::setMentionsToNicknames($item['raw-body'] ?? $item['body']), BBCode::MASTODON_API); + $this->reblog = $reblog; + $this->quote = $quote; + $this->application = $application->toArray(); + $this->account = $account->toArray(); $this->media_attachments = $reblogged ? [] : $attachments; - $this->mentions = $reblogged ? [] : $mentions; - $this->tags = $reblogged ? [] : $tags; - $this->emojis = $reblogged ? [] : ($emojis ?: []); - $this->card = $reblogged ? null : ($card->toArray() ?: null); - $this->poll = $reblogged ? null : $poll; - $this->friendica = $reblogged ? null : $friendica; + $this->mentions = $reblogged ? [] : $mentions; + $this->tags = $reblogged ? [] : $tags; + $this->emojis = $reblogged ? [] : ($emojis ?: []); + $this->card = $reblogged ? null : ($card->toArray() ?: null); + $this->poll = $reblogged ? null : $poll; + $this->friendica = $reblogged ? null : $friendica; } /** diff --git a/src/Object/Api/Mastodon/Tag.php b/src/Object/Api/Mastodon/Tag.php index 3c14a5e616..808e4c3cea 100644 --- a/src/Object/Api/Mastodon/Tag.php +++ b/src/Object/Api/Mastodon/Tag.php @@ -42,4 +42,13 @@ class Tag extends BaseDataTransferObject $this->history = $history; $this->following = $following; } + + public function toArray(): array + { + if (empty($this->history)) { + unset($this->history); + } + + return parent::toArray(); + } } diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index f717d17d8b..ad50269186 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -296,6 +296,17 @@ class ParseUrl $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]'); foreach ($list as $node) { $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]); Hook::callAll('getsiteinfo', $siteinfo); diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 18990c36fc..183b2281d3 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -44,7 +44,7 @@ use Friendica\Database\DBA; // This file is required several times during the test in DbaDefinition which justifies this condition if (!defined('DB_UPDATE_VERSION')) { - define('DB_UPDATE_VERSION', 1579); + define('DB_UPDATE_VERSION', 1580); } return [ @@ -1447,6 +1447,9 @@ return [ "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-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" => [ "PRIMARY" => ["id"],