kopia lustrzana https://github.com/nextcloud/social
commit
0a6aea1fe4
|
@ -18,7 +18,7 @@
|
|||
|
||||
**🕸 Open standards:** We use the established ActivityPub standard!
|
||||
]]></description>
|
||||
<version>0.6.0-beta2</version>
|
||||
<version>0.6.0-beta3</version>
|
||||
<licence>agpl</licence>
|
||||
<author mail="maxence@artificial-owl.com" homepage="https://artificial-owl.com/">Maxence Lange</author>
|
||||
<author mail="jus@bitgrid.net">Julius Härtl</author>
|
||||
|
|
|
@ -90,6 +90,8 @@ return [
|
|||
['name' => 'Api#statusNew', 'url' => '/api/v1/statuses', 'verb' => 'POST'],
|
||||
['name' => 'Api#statusGet', 'url' => '/api/v1/statuses/{nid}', 'verb' => 'GET'],
|
||||
['name' => 'Api#statusContext', 'url' => '/api/v1/statuses/{nid}/context', 'verb' => 'GET'],
|
||||
['name' => 'Api#statusAction', 'url' => '/api/v1/statuses/{nid}/{act}', 'verb' => 'POST'],
|
||||
|
||||
['name' => 'Api#accountStatuses', 'url' => '/api/v1/accounts/{account}/statuses', 'verb' => 'GET'],
|
||||
|
||||
// Api for local front-end
|
||||
|
|
|
@ -35,7 +35,6 @@ use Exception;
|
|||
use OC\Core\Command\Base;
|
||||
use OCA\Social\Service\AccountService;
|
||||
use OCA\Social\Service\BoostService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCA\Social\Service\StreamService;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
@ -51,18 +50,17 @@ class NoteBoost extends Base {
|
|||
private StreamService $streamService;
|
||||
private AccountService $accountService;
|
||||
private BoostService $boostService;
|
||||
private MiscService $miscService;
|
||||
|
||||
public function __construct(
|
||||
AccountService $accountService, StreamService $streamService, BoostService $boostService,
|
||||
MiscService $miscService
|
||||
AccountService $accountService,
|
||||
StreamService $streamService,
|
||||
BoostService $boostService
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->streamService = $streamService;
|
||||
$this->boostService = $boostService;
|
||||
$this->accountService = $accountService;
|
||||
$this->miscService = $miscService;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ use OCA\Social\Model\Client\SocialClient;
|
|||
use OCA\Social\Model\Client\Status;
|
||||
use OCA\Social\Model\Post;
|
||||
use OCA\Social\Service\AccountService;
|
||||
use OCA\Social\Service\ActionService;
|
||||
use OCA\Social\Service\CacheActorService;
|
||||
use OCA\Social\Service\CacheDocumentService;
|
||||
use OCA\Social\Service\ClientService;
|
||||
|
@ -85,6 +86,7 @@ class ApiController extends Controller {
|
|||
private DocumentService $documentService;
|
||||
private FollowService $followService;
|
||||
private StreamService $streamService;
|
||||
private ActionService $actionService;
|
||||
private PostService $postService;
|
||||
private ConfigService $configService;
|
||||
|
||||
|
@ -105,6 +107,7 @@ class ApiController extends Controller {
|
|||
DocumentService $documentService,
|
||||
FollowService $followService,
|
||||
StreamService $streamService,
|
||||
ActionService $actionService,
|
||||
PostService $postService,
|
||||
ConfigService $configService
|
||||
) {
|
||||
|
@ -121,6 +124,7 @@ class ApiController extends Controller {
|
|||
$this->documentService = $documentService;
|
||||
$this->followService = $followService;
|
||||
$this->streamService = $streamService;
|
||||
$this->actionService = $actionService;
|
||||
$this->postService = $postService;
|
||||
$this->configService = $configService;
|
||||
|
||||
|
@ -256,9 +260,14 @@ class ApiController extends Controller {
|
|||
}
|
||||
|
||||
$activity = $this->postService->createPost($post);
|
||||
$activity->setExportFormat(ACore::FORMAT_LOCAL);
|
||||
|
||||
return new DataResponse($activity, Http::STATUS_OK);
|
||||
$item = $this->streamService->getStreamById(
|
||||
$activity->getObjectId(),
|
||||
true,
|
||||
ACore::FORMAT_LOCAL
|
||||
);
|
||||
|
||||
return new DataResponse($item, Http::STATUS_OK);
|
||||
} catch (Exception $e) {
|
||||
$this->logger->warning('issues while statusNew', ['exception' => $e]);
|
||||
|
||||
|
@ -461,6 +470,31 @@ class ApiController extends Controller {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @PublicPage
|
||||
*
|
||||
* @param int $nid
|
||||
* @param string $action
|
||||
*
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function statusAction(int $nid, string $act): DataResponse {
|
||||
try {
|
||||
$this->initViewer(true);
|
||||
$item = $this->actionService->action($this->viewer->getId(), $nid, $act);
|
||||
|
||||
if ($item === null) {
|
||||
$item = $this->streamService->getStreamByNid($nid);
|
||||
}
|
||||
|
||||
return new DataResponse($item, Http::STATUS_OK);
|
||||
} catch (Exception $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @PublicPage
|
||||
|
@ -469,6 +503,7 @@ class ApiController extends Controller {
|
|||
* @param int $limit
|
||||
* @param int $max_id
|
||||
* @param int $min_id
|
||||
* @param int $since
|
||||
*
|
||||
* @return DataResponse
|
||||
*/
|
||||
|
|
|
@ -202,6 +202,7 @@ class CoreRequestBuilder {
|
|||
'nid',
|
||||
'id',
|
||||
'id_prim',
|
||||
'visibility',
|
||||
'type',
|
||||
'subtype',
|
||||
'to',
|
||||
|
|
|
@ -891,6 +891,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb = $this->getStreamInsertSql();
|
||||
$qb->setValue('nid', $qb->createNamedParameter($stream->getNid()))
|
||||
->setValue('id', $qb->createNamedParameter($stream->getId()))
|
||||
->setValue('visibility', $qb->createNamedParameter($stream->getVisibility()))
|
||||
->setValue('type', $qb->createNamedParameter($stream->getType()))
|
||||
->setValue('subtype', $qb->createNamedParameter($stream->getSubType()))
|
||||
->setValue('to', $qb->createNamedParameter($stream->getTo()))
|
||||
|
|
|
@ -31,9 +31,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Social\Db;
|
||||
|
||||
use OCA\Social\Tools\Exceptions\CacheItemNotFoundException;
|
||||
use OCA\Social\Tools\Exceptions\RowNotFoundException;
|
||||
use OCA\Social\Tools\Traits\TArrayTools;
|
||||
use OCA\Social\AP;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Exceptions\ItemUnknownException;
|
||||
|
@ -42,6 +39,9 @@ use OCA\Social\Exceptions\StreamNotFoundException;
|
|||
use OCA\Social\Model\ActivityPub\Object\Announce;
|
||||
use OCA\Social\Model\ActivityPub\Stream;
|
||||
use OCA\Social\Model\InstancePath;
|
||||
use OCA\Social\Tools\Exceptions\CacheItemNotFoundException;
|
||||
use OCA\Social\Tools\Exceptions\RowNotFoundException;
|
||||
use OCA\Social\Tools\Traits\TArrayTools;
|
||||
|
||||
/**
|
||||
* Class StreamRequestBuilder
|
||||
|
@ -92,9 +92,9 @@ class StreamRequestBuilder extends CoreRequestBuilder {
|
|||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
$qb->selectDistinct('s.id')
|
||||
->addSelect(
|
||||
's.nid', 's.type', 's.subtype', 's.to', 's.to_array', 's.cc', 's.bcc', 's.content',
|
||||
's.summary', 's.attachments', 's.published', 's.published_time', 's.cache',
|
||||
's.object_id', 's.attributed_to', 's.in_reply_to', 's.source', 's.local',
|
||||
's.nid', 's.type', 's.subtype', 's.visibility', 's.to', 's.to_array', 's.cc',
|
||||
's.bcc', 's.content', 's.summary', 's.attachments', 's.published', 's.published_time',
|
||||
's.cache', 's.object_id', 's.attributed_to', 's.in_reply_to', 's.source', 's.local',
|
||||
's.instances', 's.creation', 's.filter_duplicate', 's.details', 's.hashtags'
|
||||
)
|
||||
->from(self::TABLE_STREAM, 's');
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Nextcloud - Social Support
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @copyright 2023, Maxence Lange <maxence@artificial-owl.com>
|
||||
* @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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Social\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidActionException extends Exception {
|
||||
}
|
|
@ -537,6 +537,14 @@ class Version1000Date20221118000001 extends SimpleMigrationStep {
|
|||
'default' => ''
|
||||
]
|
||||
);
|
||||
$table->addColumn(
|
||||
'visibility', Types::STRING,
|
||||
[
|
||||
'notnull' => false,
|
||||
'length' => 31,
|
||||
'default' => ''
|
||||
]
|
||||
);
|
||||
$table->addColumn(
|
||||
'to', Types::TEXT,
|
||||
[
|
||||
|
|
|
@ -40,6 +40,21 @@ class Version1000Date20230217000002 extends SimpleMigrationStep {
|
|||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
if ($schema->hasTable('social_stream')) {
|
||||
$table = $schema->getTable('social_stream');
|
||||
|
||||
if (!$table->hasColumn('visibility')) {
|
||||
$table->addColumn(
|
||||
'visibility', Types::STRING,
|
||||
[
|
||||
'notnull' => false,
|
||||
'length' => 31,
|
||||
'default' => ''
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($schema->hasTable('social_cache_doc')) {
|
||||
$table = $schema->getTable('social_cache_doc');
|
||||
|
||||
|
|
|
@ -33,15 +33,10 @@ namespace OCA\Social\Model\ActivityPub;
|
|||
use DateTime;
|
||||
use Exception;
|
||||
use JsonSerializable;
|
||||
use OCA\Social\AP;
|
||||
use OCA\Social\Exceptions\InvalidResourceEntryException;
|
||||
use OCA\Social\Exceptions\ItemAlreadyExistsException;
|
||||
use OCA\Social\Exceptions\ItemUnknownException;
|
||||
use OCA\Social\Model\ActivityPub\Actor\Person;
|
||||
use OCA\Social\Model\ActivityPub\Object\Announce;
|
||||
use OCA\Social\Model\ActivityPub\Object\Document;
|
||||
use OCA\Social\Model\ActivityPub\Object\Follow;
|
||||
use OCA\Social\Model\ActivityPub\Object\Image;
|
||||
use OCA\Social\Model\ActivityPub\Object\Like;
|
||||
use OCA\Social\Model\Client\MediaAttachment;
|
||||
use OCA\Social\Model\StreamAction;
|
||||
|
@ -70,6 +65,7 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
|
|||
|
||||
private string $activityId = '';
|
||||
private string $content = '';
|
||||
private string $visibility = '';
|
||||
private string $spoilerText = '';
|
||||
private string $language = 'en';
|
||||
private string $attributedTo = '';
|
||||
|
@ -130,6 +126,24 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $visibility
|
||||
*
|
||||
* @return Stream
|
||||
*/
|
||||
public function setVisibility(string $visibility): self {
|
||||
$this->visibility = $visibility;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getVisibility(): string {
|
||||
return $this->visibility;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
|
@ -470,6 +484,7 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
|
|||
$this->setDetailsAll($this->getArray('details', $data, []));
|
||||
$this->setFilterDuplicate($this->getBool('filter_duplicate', $data, false));
|
||||
$this->setAttachments($this->getArray('attachments', $data, []));
|
||||
$this->setVisibility($this->get('visibility', $data));
|
||||
|
||||
$cache = new Cache();
|
||||
$cache->import($this->getArray('cache', $data, []));
|
||||
|
@ -545,7 +560,7 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
|
|||
"content" => $this->getContent(),
|
||||
"sensitive" => $this->isSensitive(),
|
||||
"spoiler_text" => $this->getSpoilerText(),
|
||||
"visibility" => 'unlisted',
|
||||
"visibility" => $this->getVisibility(),
|
||||
"language" => $this->getLanguage(),
|
||||
"in_reply_to_id" => null,
|
||||
"in_reply_to_account_id" => null,
|
||||
|
@ -560,7 +575,8 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
|
|||
'url' => $this->getId(),
|
||||
"reblog" => null,
|
||||
'media_attachments' => $this->getAttachments(),
|
||||
"created_at" => date('Y-m-d\TH:i:s', $this->getPublishedTime()) . '.000Z'
|
||||
"created_at" => date('Y-m-d\TH:i:s', $this->getPublishedTime()) . '.000Z',
|
||||
'noindex' => false
|
||||
];
|
||||
|
||||
// TODO - store created_at full string with milliseconds ?
|
||||
|
@ -592,7 +608,7 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
|
|||
'id' => $this->getId(),
|
||||
'type' => $type,
|
||||
'created_at' => $this->getOriginCreationTime(),
|
||||
'status' => $this->getDetails('post')
|
||||
'status' => $this->getDetails('post'),
|
||||
];
|
||||
|
||||
if ($this->hasActor()) {
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Nextcloud - Social Support
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Maxence Lange <maxence@artificial-owl.com>
|
||||
* @copyright 2023, Maxence Lange <maxence@artificial-owl.com>
|
||||
* @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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Social\Service;
|
||||
|
||||
use OCA\Social\Exceptions\InvalidActionException;
|
||||
use OCA\Social\Exceptions\StreamNotFoundException;
|
||||
use OCA\Social\Model\ActivityPub\Stream;
|
||||
use OCA\Social\Model\StreamAction;
|
||||
use OCA\Social\Tools\Traits\TStringTools;
|
||||
|
||||
class ActionService {
|
||||
use TStringTools;
|
||||
|
||||
private StreamService $streamService;
|
||||
private StreamActionService $streamActionService;
|
||||
|
||||
private const TRANSLATE = 'translate';
|
||||
private const FAVOURITE = 'favourite';
|
||||
private const UNFAVOURITE = 'unfavourite';
|
||||
private const REBLOG = 'reblog';
|
||||
private const UNREBLOG = 'unreblog';
|
||||
private const BOOKMARK = 'bookmark';
|
||||
private const UNBOOKMARK = 'unbookmark';
|
||||
private const MUTE = 'mute';
|
||||
private const UNMUTE = 'unmute';
|
||||
private const PIN = 'pin';
|
||||
private const UNPIN = 'unpin';
|
||||
|
||||
private static array $availableStatusAction = [
|
||||
self::TRANSLATE,
|
||||
self::FAVOURITE,
|
||||
self::UNFAVOURITE,
|
||||
self::REBLOG,
|
||||
self::UNREBLOG,
|
||||
self::BOOKMARK,
|
||||
self::UNBOOKMARK,
|
||||
self::MUTE,
|
||||
self::UNMUTE,
|
||||
self::PIN,
|
||||
self::UNPIN
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
StreamService $streamService,
|
||||
StreamActionService $streamActionService
|
||||
) {
|
||||
$this->streamService = $streamService;
|
||||
$this->streamActionService = $streamActionService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* should return null
|
||||
* will return Stream only with translate action
|
||||
*
|
||||
* @param int $nid
|
||||
* @param string $action
|
||||
*
|
||||
* @return Stream|null
|
||||
* @throws InvalidActionException
|
||||
*/
|
||||
public function action(string $actorId, int $nid, string $action): ?Stream {
|
||||
if (!in_array($action, self::$availableStatusAction)) {
|
||||
throw new InvalidActionException();
|
||||
}
|
||||
|
||||
$post = $this->streamService->getStreamByNid($nid);
|
||||
|
||||
switch ($action) {
|
||||
case self::TRANSLATE:
|
||||
return $this->translate($nid);
|
||||
|
||||
case self::FAVOURITE:
|
||||
$this->favourite($actorId, $post->getId());
|
||||
break;
|
||||
|
||||
case self::UNFAVOURITE:
|
||||
$this->favourite($actorId, $post->getId(), false);
|
||||
break;
|
||||
|
||||
case self::REBLOG:
|
||||
$this->reblog($actorId, $post->getId());
|
||||
break;
|
||||
|
||||
case self::UNREBLOG:
|
||||
$this->reblog($actorId, $post->getId(), false);
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO: returns a translated version of the Status
|
||||
*
|
||||
* @param int $nid
|
||||
*
|
||||
* @return Stream
|
||||
* @throws StreamNotFoundException
|
||||
*/
|
||||
private function translate(int $nid): Stream {
|
||||
return $this->streamService->getStreamByNid($nid);
|
||||
}
|
||||
|
||||
private function favourite(string $actorId, string $postId, bool $enabled = true): void {
|
||||
$this->streamActionService->setActionBool($actorId, $postId, StreamAction::LIKED, $enabled);
|
||||
}
|
||||
|
||||
private function reblog(string $actorId, string $postId, bool $enabled = true): void {
|
||||
$this->streamActionService->setActionBool($actorId, $postId, StreamAction::BOOSTED, $enabled);
|
||||
}
|
||||
}
|
|
@ -107,6 +107,7 @@ class PostService {
|
|||
$note->setAttributedTo($actor->getId());
|
||||
$note->setContent(htmlentities($post->getContent(), ENT_QUOTES));
|
||||
$note->setAttachments($post->getMedias());
|
||||
$note->setVisibility($post->getType());
|
||||
|
||||
// $this->generateDocumentsFromAttachments($note, $post);
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ class StreamActionService {
|
|||
* @param string $key
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setActionBool(string $actorId, string $streamId, string $key, bool $value) {
|
||||
public function setActionBool(string $actorId, string $streamId, string $key, bool $value): void {
|
||||
$action = $this->loadAction($actorId, $streamId);
|
||||
$action->updateValueBool($key, $value);
|
||||
$this->saveAction($action);
|
||||
|
|
Ładowanie…
Reference in New Issue