Merge remote-tracking branch 'upstream/develop' into item-lock

pull/9472/head
Michael 2020-10-29 21:07:24 +00:00
commit 930897046d
36 zmienionych plików z 918 dodań i 106 usunięć

Wyświetl plik

@ -37,7 +37,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
tools: pecl
tools: pecl, composer:v1
extensions: pdo_mysql, gd, zip, opcache, ctype, pcntl, ldap, apcu, memcached, redis, imagick, memcache
coverage: xdebug
ini-values: apc.enabled=1, apc.enable_cli=1

Wyświetl plik

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 2020.12-dev (Red Hot Poker)
-- DB_UPDATE_VERSION 1370
-- DB_UPDATE_VERSION 1372
-- ------------------------------------------
@ -775,6 +775,7 @@ CREATE TABLE IF NOT EXISTS `item-content` (
`title` varchar(255) NOT NULL DEFAULT '' COMMENT 'item title',
`content-warning` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`body` mediumtext COMMENT 'item body content',
`raw-body` mediumtext COMMENT 'Body without embedded media links',
`location` varchar(255) NOT NULL DEFAULT '' COMMENT 'text location where this item originated',
`coord` varchar(255) NOT NULL DEFAULT '' COMMENT 'longitude/latitude pair representing location where this item originated',
`language` text COMMENT 'Language information about this post',
@ -1064,6 +1065,27 @@ CREATE TABLE IF NOT EXISTS `post-delivery-data` (
FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Delivery data for items';
--
-- TABLE post-media
--
CREATE TABLE IF NOT EXISTS `post-media` (
`id` int unsigned NOT NULL auto_increment COMMENT 'sequential ID',
`uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri',
`url` varbinary(511) NOT NULL COMMENT 'Media URL',
`type` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'Media type',
`mimetype` varchar(60) COMMENT '',
`height` smallint unsigned COMMENT 'Height of the media',
`width` smallint unsigned COMMENT 'Width of the media',
`size` int unsigned COMMENT 'Media size',
`preview` varbinary(255) COMMENT 'Preview URL',
`preview-height` smallint unsigned COMMENT 'Height of the preview picture',
`preview-width` smallint unsigned COMMENT 'Width of the preview picture',
`description` text COMMENT '',
PRIMARY KEY(`id`),
UNIQUE INDEX `uri-id-url` (`uri-id`,`url`),
FOREIGN KEY (`uri-id`) REFERENCES `item-uri` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Attached media';
--
-- TABLE post-tag
--
@ -1390,7 +1412,7 @@ CREATE TABLE IF NOT EXISTS `workerqueue` (
PRIMARY KEY(`id`),
INDEX `done_parameter` (`done`,`parameter`(64)),
INDEX `done_executed` (`done`,`executed`),
INDEX `done_priority_created` (`done`,`priority`,`created`),
INDEX `done_priority_retrial_created` (`done`,`priority`,`retrial`,`created`),
INDEX `done_priority_next_try` (`done`,`priority`,`next_try`),
INDEX `done_pid_next_try` (`done`,`pid`,`next_try`),
INDEX `done_pid_retrial` (`done`,`pid`,`retrial`),

Wyświetl plik

@ -182,7 +182,7 @@ By default, any (valid) email address is allowed in registrations.
#### Allow Users to set remote_self
If you enable the `Allow Users to set remote_self` users can select Atom feeds from their contact list being their *remote self* in the advanced contact settings.
If you enable the `Allow Users to set remote_self` users can select Atom feeds from their contact list being their *remote self* in the contact settings.
Which means that postings by the remote self are automatically reposted by Friendica in their names.
This feature can be used to let the user mirror e.g. blog postings into their Friendica postings.

Wyświetl plik

@ -172,7 +172,7 @@ Wildcards werden akzeptiert Standardmäßig sind alle gültigen Email-Adressen e
#### Nutzern erlauben das remote_self Flag zu setzen
Webb du die Option `Nutzern erlauben das remote_self Flag zu setzen` aktivierst, können alle Nutzer Atom Feeds in den erweiterten Einstellungen des Kontakts als "Entferntes Konto" markieren.
Webb du die Option `Nutzern erlauben das remote_self Flag zu setzen` aktivierst, können alle Nutzer Atom Feeds in den Kontakteinstellungen als "Entferntes Konto" markieren.
Dadurch werden automatisch alle Beiträge dieser Feeds für diesen Nutzer gespiegelt und an die Kontakte bei Friendica verteilt.
Dieses Feature kann z.B. dafür genutzt werden Blogbeiträge zu spiegeln.

Wyświetl plik

@ -292,7 +292,7 @@ class PageInfo
$quotedUrl
)$#isx", function ($match) use ($url) {
// Stripping URLs with no label
if (!isset($match[1])) {
if (empty($match[1])) {
return '';
}

Wyświetl plik

@ -146,13 +146,15 @@ class BBCode
public static function getAttachmentData($body)
{
$data = [
'type' => '',
'text' => '',
'after' => '',
'image' => null,
'url' => '',
'title' => '',
'description' => '',
'type' => '',
'text' => '',
'after' => '',
'image' => null,
'url' => '',
'provider_name' => '',
'provider_url' => '',
'title' => '',
'description' => '',
];
if (!preg_match("/(.*)\[attachment(.*?)\](.*?)\[\/attachment\](.*)/ism", $body, $match)) {
@ -253,6 +255,16 @@ class BBCode
$data['after'] = trim($match[4]);
$parts = parse_url($data['url']);
if (!empty($parts['scheme']) && !empty($parts['host'])) {
$data['provider_name'] = $parts['host'];
$data['provider_url'] = $parts['scheme'] . '://' . $parts['host'];
if (!empty($parts['port'])) {
$data['provider_url'] .= ':' . $parts['port'];
}
}
return $data;
}

Wyświetl plik

@ -225,6 +225,7 @@ class Process
public function run($command, $args)
{
if (!function_exists('proc_open')) {
$this->logger->notice('"proc_open" not available - quitting');
return;
}
@ -242,6 +243,7 @@ class Process
}
if ($this->isMinMemoryReached()) {
$this->logger->notice('Memory limit reached - quitting');
return;
}
@ -251,9 +253,11 @@ class Process
$resource = proc_open($cmdline . ' &', [], $foo, $this->basePath);
}
if (!is_resource($resource)) {
$this->logger->debug('We got no resource for command.', ['cmd' => $cmdline]);
$this->logger->notice('We got no resource for command.', ['command' => $cmdline]);
return;
}
proc_close($resource);
$this->logger->info('Executed "proc_open"', ['command' => $cmdline, 'callstack' => System::callstack(10)]);
}
}

Wyświetl plik

@ -279,6 +279,22 @@ abstract class DI
return self::$dice->create(Factory\Api\Mastodon\Status::class);
}
/**
* @return Factory\Api\Mastodon\Mention
*/
public static function mstdnMention()
{
return self::$dice->create(Factory\Api\Mastodon\Mention::class);
}
/**
* @return Factory\Api\Mastodon\Tag
*/
public static function mstdnTag()
{
return self::$dice->create(Factory\Api\Mastodon\Tag::class);
}
/**
* @return Factory\Api\Twitter\User
*/

Wyświetl plik

@ -69,7 +69,15 @@ class Account extends BaseFactory
$apcontact = APContact::getByURL($publicContact['url'], false);
return new \Friendica\Object\Api\Mastodon\Account($this->baseUrl, $publicContact, new Fields(), $apcontact, $userContact);
$self_contact = Contact::selectFirst(['uid'], ['nurl' => $publicContact['nurl'], 'self' => true]);
if (!empty($self_contact['uid'])) {
$profileFields = $this->profileField->select(['uid' => $self_contact['uid'], 'psid' => PermissionSet::PUBLIC]);
$fields = $this->mstdnField->createFromProfileFields($profileFields);
} else {
$fields = new Fields();
}
return new \Friendica\Object\Api\Mastodon\Account($this->baseUrl, $publicContact, $fields, $apcontact, $userContact);
}
/**

Wyświetl plik

@ -37,7 +37,7 @@ class Field extends BaseFactory
*/
public function createFromProfileField(ProfileField $profileField)
{
return new \Friendica\Api\Entity\Mastodon\Field($profileField->label, BBCode::convert($profileField->value, false, BBCode::ACTIVITYPUB));
return new \Friendica\Object\Api\Mastodon\Field($profileField->label, BBCode::convert($profileField->value, false, BBCode::ACTIVITYPUB));
}
/**

Wyświetl plik

@ -0,0 +1,67 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @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\Factory\Api\Mastodon;
use Friendica\App\BaseURL;
use Friendica\BaseFactory;
use Friendica\Model\Contact;
use Friendica\Model\Tag;
use Friendica\Network\HTTPException;
use Friendica\Repository\ProfileField;
use Psr\Log\LoggerInterface;
class Mention extends BaseFactory
{
/** @var BaseURL */
protected $baseUrl;
/** @var ProfileField */
protected $profileField;
/** @var Field */
protected $mstdnField;
public function __construct(LoggerInterface $logger, BaseURL $baseURL, ProfileField $profileField, Field $mstdnField)
{
parent::__construct($logger);
$this->baseUrl = $baseURL;
$this->profileField = $profileField;
$this->mstdnField = $mstdnField;
}
/**
* @param int $uriId Uri-ID of the item
* @return array
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public function createFromUriId(int $uriId)
{
$mentions = [];
$tags = Tag::getByURIId($uriId, [Tag::MENTION, Tag::EXCLUSIVE_MENTION, Tag::IMPLICIT_MENTION]);
foreach ($tags as $tag) {
$contact = Contact::getByURL($tag['url'], false);
$mention = new \Friendica\Object\Api\Mastodon\Mention($this->baseUrl, $tag, $contact);
$mentions[] = $mention->toArray();
}
return $mentions;
}
}

Wyświetl plik

@ -23,6 +23,7 @@ namespace Friendica\Factory\Api\Mastodon;
use Friendica\App\BaseURL;
use Friendica\BaseFactory;
use Friendica\Content\Text\BBCode;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Item;
@ -68,6 +69,22 @@ class Status extends BaseFactory
DBA::count('item', ['thr-parent-id' => $uriId, 'uid' => $uid, 'gravity' => GRAVITY_ACTIVITY, 'vid' => Verb::getID(Activity::LIKE)])
);
return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts);
$userAttributes = new \Friendica\Object\Api\Mastodon\Status\UserAttributes(
DBA::exists('item', ['thr-parent-id' => $uriId, 'uid' => $uid, 'origin' => true, 'gravity' => GRAVITY_ACTIVITY, 'vid' => Verb::getID(Activity::LIKE)]),
DBA::exists('item', ['thr-parent-id' => $uriId, 'uid' => $uid, 'origin' => true, 'gravity' => GRAVITY_ACTIVITY, 'vid' => Verb::getID(Activity::ANNOUNCE)]),
DBA::exists('thread', ['iid' => $item['id'], 'uid' => $item['uid'], 'ignored' => true]),
(bool)$item['starred'],
DBA::exists('user-item', ['iid' => $item['id'], 'uid' => $item['uid'], 'pinned' => true])
);
$sensitive = DBA::exists('tag-view', ['uri-id' => $uriId, 'name' => 'nsfw']);
$application = new \Friendica\Object\Api\Mastodon\Application($item['app'] ?? '');
$mentions = DI::mstdnMention()->createFromUriId($uriId);
$tags = DI::mstdnTag()->createFromUriId($uriId);
$attachment = BBCode::getAttachmentData($item['body']);
$card = new \Friendica\Object\Api\Mastodon\Card($attachment);
return new \Friendica\Object\Api\Mastodon\Status($item, $account, $counts, $userAttributes, $sensitive, $application, $mentions, $tags, $card);
}
}

Wyświetl plik

@ -0,0 +1,65 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @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\Factory\Api\Mastodon;
use Friendica\App\BaseURL;
use Friendica\BaseFactory;
use Friendica\Model\Tag as TagModel;
use Friendica\Network\HTTPException;
use Friendica\Repository\ProfileField;
use Psr\Log\LoggerInterface;
class Tag extends BaseFactory
{
/** @var BaseURL */
protected $baseUrl;
/** @var ProfileField */
protected $profileField;
/** @var Field */
protected $mstdnField;
public function __construct(LoggerInterface $logger, BaseURL $baseURL, ProfileField $profileField, Field $mstdnField)
{
parent::__construct($logger);
$this->baseUrl = $baseURL;
$this->profileField = $profileField;
$this->mstdnField = $mstdnField;
}
/**
* @param int $uriId Uri-ID of the item
* @return array
* @throws HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public function createFromUriId(int $uriId)
{
$hashtags = [];
$tags = TagModel::getByURIId($uriId, [TagModel::HASHTAG]);
foreach ($tags as $tag) {
$hashtag = new \Friendica\Object\Api\Mastodon\Tag($this->baseUrl, $tag);
$hashtags[] = $hashtag->toArray();
}
return $hashtags;
}
}

Wyświetl plik

@ -106,7 +106,7 @@ class Item
'object-type', 'object', 'target-type', 'target', 'plink'];
// Field list for "item-content" table that is not present in the "item" table
const CONTENT_FIELDLIST = ['language'];
const CONTENT_FIELDLIST = ['language', 'raw-body'];
// All fields in the item table
const ITEM_FIELDLIST = ['id', 'uid', 'parent', 'uri', 'parent-uri', 'thr-parent',
@ -1680,6 +1680,7 @@ class Item
$item['deny_gid'] = trim($item['deny_gid'] ?? '');
$item['private'] = intval($item['private'] ?? self::PUBLIC);
$item['body'] = trim($item['body'] ?? '');
$item['raw-body'] = trim($item['raw-body'] ?? $item['body']);
$item['attach'] = trim($item['attach'] ?? '');
$item['app'] = trim($item['app'] ?? '');
$item['origin'] = intval($item['origin'] ?? 0);
@ -1818,6 +1819,10 @@ class Item
self::setOwnerforResharedItem($item);
}
// Remove all media attachments from the body and store them in the post-media table
$item['raw-body'] = Post\Media::insertFromBody($item['uri-id'], $item['raw-body']);
$item['raw-body'] = self::setHashtags($item['raw-body']);
// Check for hashtags in the body and repair or add hashtag links
$item['body'] = self::setHashtags($item['body']);

Wyświetl plik

@ -0,0 +1,171 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @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\Model\Post;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Util\Images;
/**
* Class Media
*
* This Model class handles media interactions.
* This tables stores medias (images, videos, audio files) related to posts.
*/
class Media
{
const UNKNOWN = 0;
const IMAGE = 1;
const VIDEO = 2;
const AUDIO = 3;
const TORRENT = 16;
/**
* Insert a post-media record
*
* @param array $media
* @return void
*/
public static function insert(array $media)
{
if (empty($media['url']) || empty($media['uri-id'])) {
return;
}
if (DBA::exists('post-media', ['uri-id' => $media['uri-id'], 'url' => $media['url']])) {
Logger::info('Media already exists', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'callstack' => System::callstack()]);
return;
}
$fields = ['type', 'mimetype', 'height', 'width', 'size', 'preview', 'preview-height', 'preview-width', 'description'];
foreach ($fields as $field) {
if (empty($media[$field])) {
unset($media[$field]);
}
}
if ($media['type'] == self::IMAGE) {
$imagedata = Images::getInfoFromURLCached($media['url']);
if (!empty($imagedata)) {
$media['mimetype'] = $imagedata['mime'];
$media['size'] = $imagedata['size'];
$media['width'] = $imagedata[0];
$media['height'] = $imagedata[1];
}
if (!empty($media['preview'])) {
$imagedata = Images::getInfoFromURLCached($media['preview']);
if (!empty($imagedata)) {
$media['preview-width'] = $imagedata[0];
$media['preview-height'] = $imagedata[1];
}
}
}
$result = DBA::insert('post-media', $media, true);
Logger::info('Stored media', ['result' => $result, 'media' => $media, 'callstack' => System::callstack()]);
}
/**
* Tests for path patterns that are usef for picture links in Friendica
*
* @param string $page Link to the image page
* @param string $preview Preview picture
* @return boolean
*/
private static function isPictureLink(string $page, string $preview)
{
return preg_match('#/photos/.*/image/#ism', $page) && preg_match('#/photo/.*-1\.#ism', $preview);
}
/**
* Add media links and remove them from the body
*
* @param integer $uriid
* @param string $body
* @return string Body without media links
*/
public static function insertFromBody(int $uriid, string $body)
{
// Simplify image codes
$body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body);
$attachments = [];
if (preg_match_all("#\[url=([^\]]+?)\]\s*\[img=([^\[\]]*)\]([^\[\]]*)\[\/img\]\s*\[/url\]#ism", $body, $pictures, PREG_SET_ORDER)) {
foreach ($pictures as $picture) {
if (!self::isPictureLink($picture[1], $picture[2])) {
continue;
}
$body = str_replace($picture[0], '', $body);
$image = str_replace('-1.', '-0.', $picture[2]);
$attachments[] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $image,
'preview' => $picture[2], 'description' => $picture[3]];
}
}
if (preg_match_all("/\[img=([^\[\]]*)\]([^\[\]]*)\[\/img\]/Usi", $body, $pictures, PREG_SET_ORDER)) {
foreach ($pictures as $picture) {
$body = str_replace($picture[0], '', $body);
$attachments[] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $picture[1], 'description' => $picture[2]];
}
}
if (preg_match_all("#\[url=([^\]]+?)\]\s*\[img\]([^\[]+?)\[/img\]\s*\[/url\]#ism", $body, $pictures, PREG_SET_ORDER)) {
foreach ($pictures as $picture) {
if (!self::isPictureLink($picture[1], $picture[2])) {
continue;
}
$body = str_replace($picture[0], '', $body);
$image = str_replace('-1.', '-0.', $picture[2]);
$attachments[] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $image,
'preview' => $picture[2], 'description' => null];
}
}
if (preg_match_all("/\[img\]([^\[\]]*)\[\/img\]/ism", $body, $pictures, PREG_SET_ORDER)) {
foreach ($pictures as $picture) {
$body = str_replace($picture[0], '', $body);
$attachments[] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $picture[1]];
}
}
if (preg_match_all("/\[audio\]([^\[\]]*)\[\/audio\]/ism", $body, $audios, PREG_SET_ORDER)) {
foreach ($audios as $audio) {
$body = str_replace($audio[0], '', $body);
$attachments[] = ['uri-id' => $uriid, 'type' => self::AUDIO, 'url' => $audio[1]];
}
}
if (preg_match_all("/\[video\]([^\[\]]*)\[\/video\]/ism", $body, $videos, PREG_SET_ORDER)) {
foreach ($videos as $video) {
$body = str_replace($video[0], '', $body);
$attachments[] = ['uri-id' => $uriid, 'type' => self::VIDEO, 'url' => $video[1]];
}
}
foreach ($attachments as $attachment) {
self::insert($attachment);
}
return trim($body);
}
}

Wyświetl plik

@ -417,7 +417,11 @@ class Site extends BaseAdmin
DI::config()->set('system', 'only_tag_search' , $only_tag_search);
DI::config()->set('system', 'worker_queues' , $worker_queues);
DI::config()->set('system', 'worker_dont_fork' , $worker_dont_fork);
if (function_exists('proc_open')) {
DI::config()->set('system', 'worker_dont_fork', $worker_dont_fork);
}
DI::config()->set('system', 'worker_fastlane' , $worker_fastlane);
DI::config()->set('system', 'frontend_worker' , $worker_frontend);
@ -578,6 +582,14 @@ class Site extends BaseAdmin
}
}
if (function_exists('proc_open')) {
$worker_dont_fork = DI::config()->get('system', 'worker_dont_fork');
$worker_dont_fork_disabled = '';
} else {
$worker_dont_fork = true;
$worker_dont_fork_disabled = 'disabled';
}
$t = Renderer::getMarkupTemplate('admin/site.tpl');
return Renderer::replaceMacros($t, [
'$title' => DI::l10n()->t('Administration'),
@ -689,7 +701,7 @@ class Site extends BaseAdmin
'$rino' => ['rino', DI::l10n()->t('RINO Encryption'), intval(DI::config()->get('system', 'rino_encrypt')), DI::l10n()->t('Encryption layer between nodes.'), [0 => DI::l10n()->t('Disabled'), 1 => DI::l10n()->t('Enabled')]],
'$worker_queues' => ['worker_queues', DI::l10n()->t('Maximum number of parallel workers'), DI::config()->get('system', 'worker_queues'), DI::l10n()->t('On shared hosters set this to %d. On larger systems, values of %d are great. Default value is %d.', 5, 20, 10)],
'$worker_dont_fork' => ['worker_dont_fork', DI::l10n()->t('Don\'t use "proc_open" with the worker'), DI::config()->get('system', 'worker_dont_fork'), DI::l10n()->t('Enable this if your system doesn\'t allow the use of "proc_open". This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.')],
'$worker_dont_fork' => ['worker_dont_fork', DI::l10n()->t('Don\'t use "proc_open" with the worker'), $worker_dont_fork, DI::l10n()->t('Enable this if your system doesn\'t allow the use of "proc_open". This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.'), $worker_dont_fork_disabled],
'$worker_fastlane' => ['worker_fastlane', DI::l10n()->t('Enable fastlane'), DI::config()->get('system', 'worker_fastlane'), DI::l10n()->t('When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.')],
'$worker_frontend' => ['worker_frontend', DI::l10n()->t('Enable frontend worker'), DI::config()->get('system', 'frontend_worker'), DI::l10n()->t('When enabled the Worker process is triggered when backend access is performed (e.g. messages being delivered). On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.', DI::baseUrl()->get())],

Wyświetl plik

@ -21,7 +21,6 @@
namespace Friendica\Module;
use Friendica\App;
use Friendica\BaseModule;
use Friendica\Content\ContactSelector;
use Friendica\Content\Nav;
@ -132,6 +131,8 @@ class Contact extends BaseModule
$fetch_further_information = intval($_POST['fetch_further_information'] ?? 0);
$remote_self = $_POST['remote_self'] ?? false;
$ffi_keyword_denylist = Strings::escapeHtml(trim($_POST['ffi_keyword_denylist'] ?? ''));
$priority = intval($_POST['poll'] ?? 0);
@ -147,6 +148,7 @@ class Contact extends BaseModule
'hidden' => $hidden,
'notify_new_posts' => $notify,
'fetch_further_information' => $fetch_further_information,
'remote_self' => $remote_self,
'ffi_keyword_denylist' => $ffi_keyword_denylist],
['id' => $contact_id, 'uid' => local_user()]
);
@ -555,6 +557,18 @@ class Contact extends BaseModule
];
}
// Disable remote self for everything except feeds.
// There is an issue when you repeat an item from maybe twitter and you got comments from friendica and twitter
// Problem is, you couldn't reply to both networks.
$allow_remote_self = in_array($contact['network'], [Protocol::FEED, Protocol::DFRN, Protocol::DIASPORA, Protocol::TWITTER])
&& DI::config()->get('system', 'allow_users_remote_self');
if ($contact['network'] == Protocol::FEED) {
$remote_self_options = ['0' => DI::l10n()->t('No mirroring'), '1' => DI::l10n()->t('Mirror as forwarded posting'), '2' => DI::l10n()->t('Mirror as my own posting')];
} else {
$remote_self_options = ['0' => DI::l10n()->t('No mirroring'), '2' => DI::l10n()->t('Mirror as my own posting')];
}
$poll_interval = null;
if ((($contact['network'] == Protocol::FEED) && !DI::config()->get('system', 'adjust_poll_frequency')) || ($contact['network']== Protocol::MAIL)) {
$poll_interval = ContactSelector::pollInterval($contact['priority'], !$poll_enabled);
@ -629,6 +643,13 @@ class Contact extends BaseModule
'$contact_status' => DI::l10n()->t('Status'),
'$contact_settings_label' => $contact_settings_label,
'$contact_profile_label' => DI::l10n()->t('Profile'),
'$allow_remote_self' => $allow_remote_self,
'$remote_self' => ['remote_self',
DI::l10n()->t('Mirror postings from this contact'),
$contact['remote_self'],
DI::l10n()->t('Mark this contact as remote_self, this will cause friendica to repost new entries from this contact.'),
$remote_self_options
],
]);
$arr = ['contact' => $contact, 'output' => $o];
@ -916,7 +937,7 @@ class Contact extends BaseModule
],
];
if ($cid != $pcid) {
if (!empty($contact['network']) && in_array($contact['network'], [Protocol::FEED, Protocol::MAIL]) && ($cid != $pcid)) {
$tabs[] = ['label' => DI::l10n()->t('Advanced'),
'url' => 'contact/' . $cid . '/advanced/',
'sel' => (($active_tab == self::TAB_ADVANCED) ? 'active' : ''),

Wyświetl plik

@ -63,7 +63,6 @@ class Advanced extends BaseModule
$poll = $_POST['poll'] ?? '';
$attag = $_POST['attag'] ?? '';
$photo = $_POST['photo'] ?? '';
$remote_self = $_POST['remote_self'] ?? false;
$nurl = Strings::normaliseLink($url);
$r = DI::dba()->update(
@ -79,7 +78,6 @@ class Advanced extends BaseModule
'notify' => $notify,
'poll' => $poll,
'attag' => $attag,
'remote_self' => $remote_self,
],
['id' => $contact['id'], 'uid' => local_user()]
);
@ -113,18 +111,6 @@ class Advanced extends BaseModule
$returnaddr = "contact/$cid";
// Disable remote self for everything except feeds.
// There is an issue when you repeat an item from maybe twitter and you got comments from friendica and twitter
// Problem is, you couldn't reply to both networks.
$allow_remote_self = in_array($contact['network'], [Protocol::FEED, Protocol::DFRN, Protocol::DIASPORA, Protocol::TWITTER])
&& DI::config()->get('system', 'allow_users_remote_self');
if ($contact['network'] == Protocol::FEED) {
$remote_self_options = ['0' => DI::l10n()->t('No mirroring'), '1' => DI::l10n()->t('Mirror as forwarded posting'), '2' => DI::l10n()->t('Mirror as my own posting')];
} else {
$remote_self_options = ['0' => DI::l10n()->t('No mirroring'), '2' => DI::l10n()->t('Mirror as my own posting')];
}
// This data is fetched automatically for most networks.
// Editing does only makes sense for mail and feed contacts.
if (!in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) {
@ -146,14 +132,6 @@ class Advanced extends BaseModule
'$udprofilenow' => DI::l10n()->t('Refetch contact data'),
'$contact_id' => $contact['id'],
'$lbl_submit' => DI::l10n()->t('Submit'),
'$label_remote_self' => DI::l10n()->t('Remote Self'),
'$allow_remote_self' => $allow_remote_self,
'$remote_self' => ['remote_self',
DI::l10n()->t('Mirror postings from this contact'),
$contact['remote_self'],
DI::l10n()->t('Mark this contact as remote_self, this will cause friendica to repost new entries from this contact.'),
$remote_self_options
],
'$name' => ['name', DI::l10n()->t('Name'), $contact['name'], '', '', $readonly],
'$nick' => ['nick', DI::l10n()->t('Account Nickname'), $contact['nick'], '', '', $readonly],

Wyświetl plik

@ -283,30 +283,32 @@ class Network extends BaseModule
self::$forumContactId = $parameters['contact_id'] ?? 0;
self::$selectedTab = Session::get('network-tab', '');
self::$selectedTab = Session::get('network-tab', DI::pConfig()->get(local_user(), 'network.view', 'selected_tab', ''));
self::$order = 'commented';
if (!empty($get['star'])) {
self::$selectedTab = 'star';
self::$order = 'received';
}
if (!empty($get['mention'])) {
self::$selectedTab = 'mention';
self::$order = 'received';
}
if (!empty($get['order'])) {
self::$selectedTab = $get['order'];
self::$order = $get['order'];
}
Session::set('network-tab', self::$selectedTab);
self::$star = intval($get['star'] ?? 0);
self::$mention = intval($get['mention'] ?? 0);
self::$order = $get['order'] ?? Session::get('network-order', 'commented');
self::$selectedTab = self::$selectedTab ?? self::$order;
Session::set('network-tab', self::$selectedTab);
Session::set('network-order', self::$order);
DI::pConfig()->set(local_user(), 'network.view', 'selected_tab', self::$selectedTab);
self::$accountTypeString = $get['accounttype'] ?? $parameters['accounttype'] ?? '';
self::$accountType = User::getAccountTypeByString(self::$accountTypeString);
@ -331,15 +333,15 @@ class Network extends BaseModule
case 'received':
self::$max_id = $get['last_received'] ?? self::$max_id;
break;
case 'commented':
self::$max_id = $get['last_commented'] ?? self::$max_id;
break;
case 'created':
self::$max_id = $get['last_created'] ?? self::$max_id;
break;
case 'uriid':
self::$max_id = $get['last_uriid'] ?? self::$max_id;
break;
default:
self::$order = 'commented';
self::$max_id = $get['last_commented'] ?? self::$max_id;
}
}

Wyświetl plik

@ -99,7 +99,7 @@ class Account extends BaseEntity
$publicContact['nick'] :
$publicContact['addr'];
$this->display_name = $publicContact['name'];
$this->locked = $publicContact['manually-approve'] ?? !empty($apcontact['manually-approve']);
$this->locked = (bool)$publicContact['manually-approve'] ?? !empty($apcontact['manually-approve']);
$this->bot = ($publicContact['contact-type'] == Contact::TYPE_NEWS);
$this->discoverable = !$publicContact['unsearchable'];
$this->group = ($publicContact['contact-type'] == Contact::TYPE_COMMUNITY);
@ -132,4 +132,20 @@ class Account extends BaseEntity
$this->fields = $fields->getArrayCopy();
}
/**
* Returns the current entity as an array
*
* @return array
*/
public function toArray()
{
$account = parent::toArray();
if (empty($account['moved'])) {
unset($account['moved']);
}
return $account;
}
}

Wyświetl plik

@ -0,0 +1,78 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @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\Object\Api\Mastodon;
use Friendica\BaseEntity;
/**
* Class Card
*
* @see https://docs.joinmastodon.org/entities/card
*/
class Card extends BaseEntity
{
/** @var string */
protected $url;
/** @var string */
protected $title;
/** @var string */
protected $description;
/** @var string */
protected $type;
/** @var string */
protected $provider_name;
/** @var string */
protected $provider_url;
/** @var string */
protected $image;
/**
* Creates a card record from an attachment array.
*
* @param array $attachment Attachment record
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function __construct(array $attachment)
{
$this->url = $attachment['url'] ?? '';
$this->title = $attachment['title'] ?? '';
$this->description = $attachment['description'] ?? '';
$this->type = $attachment['type'] ?? '';
$this->image = $attachment['image'] ?? '';
$this->provider_name = $attachment['provider_name'] ?? '';
$this->provider_url = $attachment['provider_url'] ?? '';
}
/**
* Returns the current entity as an array
*
* @return array
*/
public function toArray()
{
if (empty($this->url)) {
return null;
}
return parent::toArray();
}
}

Wyświetl plik

@ -0,0 +1,66 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @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\Object\Api\Mastodon;
use Friendica\App\BaseURL;
use Friendica\BaseEntity;
/**
* Class Mention
*
* @see https://docs.joinmastodon.org/entities/mention
*/
class Mention extends BaseEntity
{
/** @var string */
protected $id;
/** @var string */
protected $username;
/** @var string */
protected $url = null;
/** @var string */
protected $acct = null;
/**
* Creates a mention record from an tag-view record.
*
* @param BaseURL $baseUrl
* @param array $tag tag-view record
* @param array $contact contact table record
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function __construct(BaseURL $baseUrl, array $tag, array $contact)
{
$this->id = $contact['id'] ?? 0;
$this->username = $tag['name'];
$this->url = $tag['url'];
if (!empty($contact)) {
$this->acct =
strpos($contact['url'], $baseUrl->get() . '/') === 0 ?
$contact['nick'] :
$contact['addr'];
} else {
$this->acct = '';
}
}
}

Wyświetl plik

@ -24,6 +24,7 @@ namespace Friendica\Object\Api\Mastodon;
use Friendica\BaseEntity;
use Friendica\Content\Text\BBCode;
use Friendica\Object\Api\Mastodon\Status\Counts;
use Friendica\Object\Api\Mastodon\Status\UserAttributes;
use Friendica\Util\DateTimeFormat;
/**
@ -96,7 +97,7 @@ class Status extends BaseEntity
* @param array $item
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function __construct(array $item, Account $account, Counts $counts)
public function __construct(array $item, Account $account, Counts $counts, UserAttributes $userAttributes, bool $sensitive, Application $application, array $mentions, array $tags, Card $card)
{
$this->id = (string)$item['uri-id'];
$this->created_at = DateTimeFormat::utc($item['created'], DateTimeFormat::ATOM);
@ -106,32 +107,54 @@ class Status extends BaseEntity
$this->in_reply_to_account_id = (string)$item['parent-author-id'];
}
$this->sensitive = false;
$this->sensitive = $sensitive;
$this->spoiler_text = $item['title'];
$visibility = ['public', 'private', 'unlisted'];
$this->visibility = $visibility[$item['private']];
$this->language = null;
$languages = json_decode($item['language'], true);
$this->language = is_array($languages) ? array_key_first($languages) : null;
$this->uri = $item['uri'];
$this->url = $item['plink'] ?? null;
$this->replies_count = $counts->replies;
$this->reblogs_count = $counts->reblogs;
$this->favourites_count = $counts->favourites;
$this->favourited = false;
$this->reblogged = false;
$this->muted = false;
$this->bookmarked = false;
$this->pinned = false;
$this->favourited = $userAttributes->favourited;
$this->reblogged = $userAttributes->reblogged;
$this->muted = $userAttributes->muted;
$this->bookmarked = $userAttributes->bookmarked;
$this->pinned = $userAttributes->pinned;
$this->content = BBCode::convert($item['body'], false);
$this->reblog = null;
$this->application = null;
$this->reblog = null; /// @todo
$this->application = $application->toArray();
$this->account = $account->toArray();
$this->media_attachments = [];
$this->mentions = [];
$this->tags = [];
$this->media_attachments = []; /// @todo
$this->mentions = $mentions;
$this->tags = $tags;
$this->emojis = [];
$this->card = null;
$this->card = $card->toArray();
$this->poll = null;
}
/**
* Returns the current entity as an array
*
* @return array
*/
public function toArray()
{
$status = parent::toArray();
if (!$status['pinned']) {
unset($status['pinned']);
}
if (empty($status['application']['name'])) {
unset($status['application']);
}
return $status;
}
}

Wyświetl plik

@ -51,6 +51,6 @@ class Counts
}
public function __get($name) {
return $this->$name;
}
return $this->$name;
}
}

Wyświetl plik

@ -0,0 +1,64 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @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\Object\Api\Mastodon\Status;
/**
* Class UserAttributes
*
* @see https://docs.joinmastodon.org/entities/status
*/
class UserAttributes
{
/** @var bool */
protected $favourited;
/** @var bool */
protected $reblogged;
/** @var bool */
protected $muted;
/** @var bool */
protected $bookmarked;
/** @var bool */
protected $pinned;
/**
* Creates a authorized user attributes object
*
* @param bool $favourited
* @param bool $reblogged
* @param bool $muted
* @param bool $bookmarked
* @param bool $pinned
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function __construct(bool $favourited, bool $reblogged, bool $muted, bool $bookmarked, bool $pinned)
{
$this->favourited = $favourited;
$this->reblogged = $reblogged;
$this->muted = $muted;
$this->bookmarked = $bookmarked;
$this->pinned = $pinned;
}
public function __get($name) {
return $this->$name;
}
}

Wyświetl plik

@ -0,0 +1,51 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @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\Object\Api\Mastodon;
use Friendica\App\BaseURL;
use Friendica\BaseEntity;
/**
* Class Tag
*
* @see https://docs.joinmastodon.org/entities/tag
*/
class Tag extends BaseEntity
{
/** @var string */
protected $name;
/** @var string */
protected $url = null;
/**
* Creates a hashtag record from an tag-view record.
*
* @param BaseURL $baseUrl
* @param array $tag tag-view record
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function __construct(BaseURL $baseUrl, array $tag)
{
$this->name = strtolower($tag['name']);
$this->url = $baseUrl . '/search?tag=' . urlencode($this->name);
}
}

Wyświetl plik

@ -37,6 +37,7 @@ use Friendica\Model\ItemURI;
use Friendica\Model\Mail;
use Friendica\Model\Tag;
use Friendica\Model\User;
use Friendica\Model\Post;
use Friendica\Protocol\Activity;
use Friendica\Protocol\ActivityPub;
use Friendica\Protocol\Relay;
@ -81,6 +82,45 @@ class Processor
return $body;
}
/**
* Store attached media files in the post-media table
*
* @param int $uriid
* @param array $attachment
* @return void
*/
private static function storeAttachmentAsMedia(int $uriid, array $attachment)
{
if (empty($attachment['url'])) {
return;
}
$data = ['uri-id' => $uriid];
$filetype = strtolower(substr($attachment['mediaType'], 0, strpos($attachment['mediaType'], '/')));
if ($filetype == 'image') {
$data['type'] = Post\Media::IMAGE;
} elseif ($filetype == 'video') {
$data['type'] = Post\Media::VIDEO;
} elseif ($filetype == 'audio') {
$data['type'] = Post\Media::AUDIO;
} elseif (in_array($attachment['mediaType'], ['application/x-bittorrent', 'application/x-bittorrent;x-scheme-handler/magnet'])) {
$data['type'] = Post\Media::TORRENT;
} else {
Logger::info('Unknown type', ['attachment' => $attachment]);
return;
}
$data['url'] = $attachment['url'];
$data['mimetype'] = $attachment['mediaType'];
$data['height'] = $attachment['height'] ?? null;
$data['size'] = $attachment['size'] ?? null;
$data['preview'] = $attachment['image'] ?? null;
$data['description'] = $attachment['name'] ?? null;
Post\Media::insert($data);
}
/**
* Add attachment data to the item array
*
@ -95,6 +135,8 @@ class Processor
return $item;
}
$item['attach'] = '';
foreach ($activity['attachments'] as $attach) {
switch ($attach['type']) {
case 'link':
@ -110,6 +152,8 @@ class Processor
$item['body'] = PageInfo::appendDataToBody($item['body'], $data);
break;
default:
self::storeAttachmentAsMedia($item['uri-id'], $attach);
$filetype = strtolower(substr($attach['mediaType'], 0, strpos($attach['mediaType'], '/')));
if ($filetype == 'image') {
if (!empty($activity['source']) && strpos($activity['source'], $attach['url'])) {
@ -146,13 +190,13 @@ class Processor
$item['body'] .= "\n[video]" . $attach['url'] . '[/video]';
} else {
if (!empty($item["attach"])) {
$item["attach"] .= ',';
if (!empty($item['attach'])) {
$item['attach'] .= ',';
} else {
$item["attach"] = '';
$item['attach'] = '';
}
$item["attach"] .= '[attach]href="' . $attach['url'] . '" length="' . ($attach['length'] ?? '0') . '" type="' . $attach['mediaType'] . '" title="' . ($attach['name'] ?? '') . '"[/attach]';
$item['attach'] .= '[attach]href="' . $attach['url'] . '" length="' . ($attach['length'] ?? '0') . '" type="' . $attach['mediaType'] . '" title="' . ($attach['name'] ?? '') . '"[/attach]';
}
}
}
@ -180,6 +224,9 @@ class Processor
$item['edited'] = DateTimeFormat::utc($activity['updated']);
$item = self::processContent($activity, $item);
$item = self::constructAttachList($activity, $item);
if (empty($item)) {
return;
}
@ -403,17 +450,18 @@ class Processor
{
$item['title'] = HTML::toBBCode($activity['name']);
$content = HTML::toBBCode($activity['content']);
if (!empty($activity['emojis'])) {
$content = self::replaceEmojis($content, $activity['emojis']);
}
$content = self::convertMentions($content);
if (!empty($activity['source'])) {
$item['body'] = $activity['source'];
$item['raw-body'] = $content;
} else {
$content = HTML::toBBCode($activity['content']);
if (!empty($activity['emojis'])) {
$content = self::replaceEmojis($content, $activity['emojis']);
}
$content = self::convertMentions($content);
if (empty($activity['directmessage']) && ($item['thr-parent'] != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) {
$item_private = !in_array(0, $activity['item_receiver']);
$parent = Item::selectFirst(['id', 'uri-id', 'private', 'author-link', 'alias'], ['uri' => $item['thr-parent']]);
@ -429,7 +477,7 @@ class Processor
$content = self::removeImplicitMentionsFromBody($content, $parent);
}
$item['content-warning'] = HTML::toBBCode($activity['summary']);
$item['body'] = $content;
$item['raw-body'] = $item['body'] = $content;
}
self::storeFromBody($item);

Wyświetl plik

@ -1231,24 +1231,36 @@ class Receiver
$filetype = strtolower(substr($mediatype, 0, strpos($mediatype, '/')));
if ($filetype == 'audio') {
$attachments[$filetype] = ['type' => $mediatype, 'url' => $href];
$attachments[$filetype] = ['type' => $mediatype, 'url' => $href, 'height' => null, 'size' => null];
} elseif ($filetype == 'video') {
$height = (int)JsonLD::fetchElement($url, 'as:height', '@value');
$size = (int)JsonLD::fetchElement($url, 'pt:size', '@value');
// We save bandwidth by using a moderate height
// We save bandwidth by using a moderate height (alt least 480 pixel height)
// Peertube normally uses these heights: 240, 360, 480, 720, 1080
if (!empty($attachments[$filetype]['height']) &&
(($height > 480) || $height < $attachments[$filetype]['height'])) {
($height > $attachments[$filetype]['height']) && ($attachments[$filetype]['height'] >= 480)) {
continue;
}
$attachments[$filetype] = ['type' => $mediatype, 'url' => $href, 'height' => $height];
$attachments[$filetype] = ['type' => $mediatype, 'url' => $href, 'height' => $height, 'size' => $size];
} elseif (in_array($mediatype, ['application/x-bittorrent', 'application/x-bittorrent;x-scheme-handler/magnet'])) {
$height = (int)JsonLD::fetchElement($url, 'as:height', '@value');
// For Torrent links we always store the highest resolution
if (!empty($attachments[$mediatype]['height']) && ($height < $attachments[$mediatype]['height'])) {
continue;
}
$attachments[$mediatype] = ['type' => $mediatype, 'url' => $href, 'height' => $height, 'size' => null];
}
}
foreach ($attachments as $type => $attachment) {
$object_data['attachments'][] = ['type' => $type,
'mediaType' => $attachment['type'],
'height' => $attachment['height'],
'size' => $attachment['size'],
'name' => '',
'url' => $attachment['url']];
}

Wyświetl plik

@ -2810,6 +2810,26 @@ class Diaspora
return Relay::isSolicitedPost($tags, $body, $contact['id'], $url, Protocol::DIASPORA);
}
/**
* Store an attached photo in the post-media table
*
* @param int $uriid
* @param object $photo
* @return void
*/
private static function storePhotoAsMedia(int $uriid, $photo)
{
$data = [];
$data['uri-id'] = $uriid;
$data['type'] = Post\Media::IMAGE;
$data['url'] = XML::unescape($photo->remote_photo_path) . XML::unescape($photo->remote_photo_name);
$data['height'] = (int)XML::unescape($photo->height ?? 0);
$data['width'] = (int)XML::unescape($photo->width ?? 0);
$data['description'] = XML::unescape($photo->text ?? '');
Post\Media::insert($data);
}
/**
* Receives status messages
*
@ -2847,13 +2867,18 @@ class Diaspora
}
}
$body = Markdown::toBBCode($text);
$raw_body = $body = Markdown::toBBCode($text);
$datarray = [];
$datarray["guid"] = $guid;
$datarray["uri"] = $datarray["parent-uri"] = self::getUriFromGuid($author, $guid);
$datarray['uri-id'] = ItemURI::insert(['uri' => $datarray['uri'], 'guid' => $datarray['guid']]);
// Attach embedded pictures to the body
if ($data->photo) {
foreach ($data->photo as $photo) {
self::storePhotoAsMedia($datarray['uri-id'], $photo);
$body = "[img]".XML::unescape($photo->remote_photo_path).
XML::unescape($photo->remote_photo_name)."[/img]\n".$body;
}
@ -2887,10 +2912,6 @@ class Diaspora
$datarray["owner-link"] = $datarray["author-link"];
$datarray["owner-id"] = $datarray["author-id"];
$datarray["guid"] = $guid;
$datarray["uri"] = $datarray["parent-uri"] = self::getUriFromGuid($author, $guid);
$datarray['uri-id'] = ItemURI::insert(['uri' => $datarray['uri'], 'guid' => $datarray['guid']]);
$datarray["verb"] = Activity::POST;
$datarray["gravity"] = GRAVITY_PARENT;
@ -2904,6 +2925,7 @@ class Diaspora
}
$datarray["body"] = self::replacePeopleGuid($body, $contact["url"]);
$datarray["raw-body"] = self::replacePeopleGuid($raw_body, $contact["url"]);
self::storeMentions($datarray['uri-id'], $text);
Tag::storeRawTagsFromBody($datarray['uri-id'], $datarray["body"]);

Wyświetl plik

@ -31,9 +31,19 @@ class CleanItemUri
*/
public static function execute()
{
$ret = DBA::e("DELETE FROM `item-uri` WHERE NOT `id` IN (SELECT `uri-id` FROM `item`)
// We have to avoid deleting newly created "item-uri" entries.
// So we fetch a post that had been stored yesterday and only delete older ones.
$item = DBA::selectFirst('item', ['uri-id'], ["`uid` = ? AND `received` < UTC_TIMESTAMP() - INTERVAL ? DAY", 0, 1],
['order' => ['received' => true]]);
if (empty($item['uri-id'])) {
Logger::warning('No item with uri-id found - we better quit here');
return;
}
Logger::notice('Start deleting orphaned URI-ID', ['last-id' => $item['uri-id']]);
$ret = DBA::e("DELETE FROM `item-uri` WHERE `id` < ?
AND NOT `id` IN (SELECT `uri-id` FROM `item`)
AND NOT `id` IN (SELECT `parent-uri-id` FROM `item`)
AND NOT `id` IN (SELECT `thr-parent-id` FROM `item`)");
AND NOT `id` IN (SELECT `thr-parent-id` FROM `item`)", $item['uri-id']);
Logger::notice('Orphaned URI-ID entries removed', ['result' => $ret, 'rows' => DBA::affectedRows()]);
}
}

Wyświetl plik

@ -54,7 +54,7 @@
use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1371);
define('DB_UPDATE_VERSION', 1372);
}
return [
@ -843,6 +843,7 @@ return [
"title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "item title"],
"content-warning" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"body" => ["type" => "mediumtext", "comment" => "item body content"],
"raw-body" => ["type" => "mediumtext", "comment" => "Body without embedded media links"],
"location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "text location where this item originated"],
"coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "longitude/latitude pair representing location where this item originated"],
"language" => ["type" => "text", "comment" => "Language information about this post"],
@ -1133,6 +1134,27 @@ return [
"PRIMARY" => ["uri-id"],
]
],
"post-media" => [
"comment" => "Attached media",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uri-id" => ["type" => "int unsigned", "not null" => "1", "foreign" => ["item-uri" => "id"], "comment" => "Id of the item-uri table entry that contains the item uri"],
"url" => ["type" => "varbinary(511)", "not null" => "1", "comment" => "Media URL"],
"type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Media type"],
"mimetype" => ["type" => "varchar(60)", "comment" => ""],
"height" => ["type" => "smallint unsigned", "comment" => "Height of the media"],
"width" => ["type" => "smallint unsigned", "comment" => "Width of the media"],
"size" => ["type" => "int unsigned", "comment" => "Media size"],
"preview" => ["type" => "varbinary(255)", "comment" => "Preview URL"],
"preview-height" => ["type" => "smallint unsigned", "comment" => "Height of the preview picture"],
"preview-width" => ["type" => "smallint unsigned", "comment" => "Width of the preview picture"],
"description" => ["type" => "text", "comment" => ""],
],
"indexes" => [
"PRIMARY" => ["id"],
"uri-id-url" => ["UNIQUE", "uri-id", "url"],
]
],
"post-tag" => [
"comment" => "post relation to tags",
"fields" => [

Wyświetl plik

@ -39,12 +39,6 @@
{{include file="field_input.tpl" field=$photo}}
{{if $allow_remote_self eq 1}}
<h4>{{$label_remote_self}}</h4>
{{include file="field_select.tpl" field=$remote_self}}
{{/if}}
<input type="submit" name="submit" value="{{$lbl_submit}}" />
</form>

Wyświetl plik

@ -69,6 +69,10 @@
{{include file="field_select.tpl" field=$fetch_further_information}}
{{if $fetch_further_information.2 == 2 || $fetch_further_information.2 == 3}} {{include file="field_textarea.tpl" field=$ffi_keyword_denylist}} {{/if}}
{{/if}}
{{if $allow_remote_self}}
{{include file="field_select.tpl" field=$remote_self}}
{{/if}}
{{include file="field_checkbox.tpl" field=$hidden}}
<div id="contact-edit-info-wrapper">

Wyświetl plik

@ -41,12 +41,6 @@
{{include file="field_input.tpl" field=$photo}}
{{if $allow_remote_self eq 1}}
<h4>{{$label_remote_self}}</h4>
{{include file="field_select.tpl" field=$remote_self}}
{{/if}}
<div class="pull-right settings-submit-wrapper" >
<button type="submit" name="submit" class="btn btn-primary" value="{{$lbl_submit}}">{{$lbl_submit}}</button>
</div>

Wyświetl plik

@ -135,6 +135,10 @@
{{include file="field_select.tpl" field=$fetch_further_information}}
{{if $fetch_further_information.2 == 2 || $fetch_further_information.2 == 3}} {{include file="field_textarea.tpl" field=$ffi_keyword_denylist}} {{/if}}
{{/if}}
{{if $allow_remote_self}}
{{include file="field_select.tpl" field=$remote_self}}
{{/if}}
{{include file="field_checkbox.tpl" field=$hidden}}
<div class="pull-right settings-submit-wrapper" >

Wyświetl plik

@ -70,6 +70,10 @@
{{include file="field_select.tpl" field=$fetch_further_information}}
{{if $fetch_further_information.2 == 2 || $fetch_further_information.2 == 3}} {{include file="field_textarea.tpl" field=$ffi_keyword_denylist}} {{/if}}
{{/if}}
{{if $allow_remote_self}}
{{include file="field_select.tpl" field=$remote_self}}
{{/if}}
{{include file="field_checkbox.tpl" field=$hidden}}
<div id="contact-edit-info-wrapper">