diff --git a/appinfo/routes.php b/appinfo/routes.php
index bec44f7a..b029b16c 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -79,8 +79,9 @@ return [
['name' => 'Api#instance', 'url' => '/api/v1/instance/', 'verb' => 'GET'],
['name' => 'Api#customEmojis', 'url' => '/api/v1/custom_emojis', 'verb' => 'GET'],
['name' => 'Api#savedSearches', 'url' => '/api/saved_searches/list.json', 'verb' => 'GET'],
- ['name' => 'Api#timelines', 'url' => '/api/v1/timelines/{timeline}/', 'verb' => 'GET'],
+ ['name' => 'Api#favourites', 'url' => '/api/v1/favourites/', 'verb' => 'GET'],
['name' => 'Api#notifications', 'url' => '/api/v1/notifications', 'verb' => 'GET'],
+ ['name' => 'Api#tag', 'url' => '/api/v1/timelines/tag/{hashtag}', 'verb' => 'GET'],
['name' => 'Api#statusNew', 'url' => '/api/v1/statuses', 'verb' => 'POST'],
// Api for local front-end
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index e2a70004..7ef42a73 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -31,11 +31,8 @@ declare(strict_types=1);
namespace OCA\Social\AppInfo;
-use Closure;
use OCA\Social\Notification\Notifier;
use OCA\Social\Search\UnifiedSearchProvider;
-use OCA\Social\Service\ConfigService;
-use OCA\Social\Service\UpdateService;
use OCA\Social\WellKnown\WebfingerHandler;
use OCA\Social\Listeners\ProfileSectionListener;
use OCA\Social\Dashboard\SocialWidget;
@@ -43,13 +40,7 @@ use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
-use OCP\AppFramework\QueryException;
use OCP\Profile\BeforeTemplateRenderedEvent;
-use OCP\IDBConnection;
-use OCP\IServerContainer;
-use OC\DB\SchemaWrapper;
-use OCP\DB\ISchemaWrapper;
-use Throwable;
require_once __DIR__ . '/../../vendor/autoload.php';
diff --git a/lib/Command/ExtendedBase.php b/lib/Command/ExtendedBase.php
index feca6ff9..0755beea 100644
--- a/lib/Command/ExtendedBase.php
+++ b/lib/Command/ExtendedBase.php
@@ -62,6 +62,7 @@ class ExtendedBase extends Base {
protected function outputStreams(array $streams) {
if ($this->asJson) {
$this->output->writeln(json_encode($streams, JSON_PRETTY_PRINT));
+ return;
}
$table = new Table($this->output);
diff --git a/lib/Command/Timeline.php b/lib/Command/Timeline.php
index 433118c2..6ab9988d 100644
--- a/lib/Command/Timeline.php
+++ b/lib/Command/Timeline.php
@@ -33,12 +33,10 @@ namespace OCA\Social\Command;
use Exception;
use OCA\Social\Db\StreamRequest;
-use OCA\Social\Exceptions\UnknownTimelineException;
use OCA\Social\Model\ActivityPub\Stream;
use OCA\Social\Model\Client\Options\TimelineOptions;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\ConfigService;
-use OCA\Social\Tools\Exceptions\DateTimeException;
use OCP\IUserManager;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -88,15 +86,15 @@ class Timeline extends ExtendedBase {
*/
protected function configure() {
parent::configure();
- $this->setName('social:stream')
+ $this->setName('social:timeline')
->addArgument('userId', InputArgument::REQUIRED, 'viewer')
->addArgument('timeline', InputArgument::REQUIRED, 'timeline')
->addOption('local', '', InputOption::VALUE_NONE, 'public')
- ->addOption('count', '', InputOption::VALUE_REQUIRED, 'number of elements', '5')
->addOption('min_id', '', InputOption::VALUE_REQUIRED, 'min_id', 0)
->addOption('max_id', '', InputOption::VALUE_REQUIRED, 'max_id', 0)
+ ->addOption('since', '', InputOption::VALUE_REQUIRED, 'since', 0)
+ ->addOption('limit', '', InputOption::VALUE_REQUIRED, 'limit', 5)
->addOption('crop', '', InputOption::VALUE_REQUIRED, 'crop', 0)
- ->addOption('json', '', InputOption::VALUE_NONE, 'return JSON format')
->setDescription('Get stream by timeline and viewer');
}
@@ -111,7 +109,7 @@ class Timeline extends ExtendedBase {
$output = new ConsoleOutput();
$this->output = $output->section();
- $this->asJson = $input->getOption('json');
+ $this->asJson = (strtolower($input->getOption('output')) === 'json');
$this->crop = intval($input->getOption('crop'));
$userId = $input->getArgument('userId');
@@ -129,46 +127,17 @@ class Timeline extends ExtendedBase {
$options = new TimelineOptions();
$options->setFormat(Stream::FORMAT_LOCAL);
- $options->setLimit(intval($input->getOption('count')))
+ $options->setLimit(intval($input->getOption('limit')))
->setMinId(intval($input->getOption('min_id')))
- ->setMaxId(intval($input->getOption('max_id')));
+ ->setMaxId(intval($input->getOption('max_id')))
+ ->setSince(intval($input->getOption('since')));
- try {
- if ($input->getOption('local')) {
- $options->setLocal(true);
- }
- $options->setTimeline($timeline = $input->getArgument('timeline'));
- $this->outputStreams($this->streamRequest->getTimeline($options));
- } catch (UnknownTimelineException $e) {
- $this->displayUnsupportedStream($options);
+ if ($input->getOption('local')) {
+ $options->setLocal(true);
}
+ $options->setTimeline($input->getArgument('timeline'));
+ $this->outputStreams($this->streamRequest->getTimeline($options));
return 0;
}
-
-
- /**
- * @param TimelineOptions $options
- *
- * @throws DateTimeException
- */
- private function displayUnsupportedStream(TimelineOptions $options) {
- switch ($options->getTimeline()) {
- case 'notifications':
- $stream = $this->streamRequest->getTimelineNotifications(0, $options->getLimit());
- $this->outputStreams($stream);
- break;
-
- case 'liked':
- $stream = $this->streamRequest->getTimelineLiked(0, $options->getLimit());
- $this->outputStreams($stream);
- break;
-
- default:
- throw new Exception(
- 'Unknown timeline. Try ' . implode(', ', TimelineOptions::$availableTimelines)
- . ', direct, notifications, liked'
- );
- }
- }
}
diff --git a/lib/Controller/ActivityPubController.php b/lib/Controller/ActivityPubController.php
index 05258855..b2302232 100644
--- a/lib/Controller/ActivityPubController.php
+++ b/lib/Controller/ActivityPubController.php
@@ -39,7 +39,6 @@ use OCA\Social\Exceptions\SignatureIsGoneException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\StreamNotFoundException;
use OCA\Social\Exceptions\UrlCloudException;
-use OCA\Social\Model\ActivityPub\Activity\Delete;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\ConfigService;
@@ -76,6 +75,7 @@ class ActivityPubController extends Controller {
private FollowService $followService;
private StreamService $streamService;
private ConfigService $configService;
+ private LoggerInterface $logger;
public function __construct(
IRequest $request,
diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php
index c089b003..7fbd5006 100644
--- a/lib/Controller/ApiController.php
+++ b/lib/Controller/ApiController.php
@@ -193,23 +193,6 @@ class ApiController extends Controller {
}
- /**
- * @NoCSRFRequired
- * @PublicPage
- *
- * @return DataResponse
- */
- public function notifications(): DataResponse {
- try {
- $this->initViewer(true);
-
- return new DataResponse([], Http::STATUS_OK);
- } catch (Exception $e) {
- return $this->error($e->getMessage());
- }
- }
-
-
/**
* @NoCSRFRequired
* @PublicPage
@@ -273,18 +256,133 @@ class ApiController extends Controller {
bool $local = false,
int $limit = 20,
int $max_id = 0,
- int $min_id = 0
+ int $min_id = 0,
+ int $since = 0
): DataResponse {
try {
$this->initViewer(true);
$options = new TimelineOptions($this->request);
$options->setFormat(ACore::FORMAT_LOCAL);
- $options->setTimeline($timeline);
- $options->setLocal($local);
- $options->setLimit($limit);
- $options->setMaxId($max_id);
- $options->setMinId($min_id);
+ $options->setTimeline($timeline)
+ ->setLocal($local)
+ ->setLimit($limit)
+ ->setMaxId($max_id)
+ ->setMinId($min_id)
+ ->setSince($since);
+
+ $posts = $this->streamService->getTimeline($options);
+
+ return new DataResponse($posts, Http::STATUS_OK);
+ } catch (Exception $e) {
+ return $this->error($e->getMessage());
+ }
+ }
+
+
+ /**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
+ * @param int $limit
+ * @param int $max_id
+ * @param int $min_id
+ * @param int $since
+ *
+ * @return DataResponse
+ */
+ public function favourites(
+ int $limit = 20,
+ int $max_id = 0,
+ int $min_id = 0,
+ int $since = 0
+ ): DataResponse {
+ try {
+ $this->initViewer(true);
+
+ $options = new TimelineOptions($this->request);
+ $options->setFormat(ACore::FORMAT_LOCAL);
+ $options->setTimeline(TimelineOptions::TIMELINE_FAVOURITES)
+ ->setLimit($limit)
+ ->setMaxId($max_id)
+ ->setMinId($min_id)
+ ->setSince($since);
+
+ $posts = $this->streamService->getTimeline($options);
+
+ return new DataResponse($posts, Http::STATUS_OK);
+ } catch (Exception $e) {
+ return $this->error($e->getMessage());
+ }
+ }
+
+
+ /**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
+ * @return DataResponse
+ */
+ public function notifications(
+ int $limit = 20,
+ int $max_id = 0,
+ int $min_id = 0,
+ int $since = 0,
+ array $types = [],
+ array $exclude_types = [],
+ string $accountId = ''
+ ): DataResponse {
+ try {
+ $this->initViewer(true);
+
+ $options = new TimelineOptions($this->request);
+ $options->setFormat(ACore::FORMAT_LOCAL);
+ $options->setTimeline(TimelineOptions::TIMELINE_NOTIFICATIONS)
+ ->setLimit($limit)
+ ->setMaxId($max_id)
+ ->setMinId($min_id)
+ ->setSince($since)
+ ->setTypes($types)
+ ->setExcludeTypes($exclude_types)
+ ->setAccountId($accountId);
+
+ $posts = $this->streamService->getTimeline($options);
+
+ return new DataResponse($posts, Http::STATUS_OK);
+ } catch (Exception $e) {
+ return $this->error($e->getMessage());
+ }
+ }
+
+
+ /**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
+ * @return DataResponse
+ */
+ public function tag(
+ string $hashtag,
+ int $limit = 20,
+ int $max_id = 0,
+ int $min_id = 0,
+ int $since = 0,
+ bool $local = false,
+ bool $only_media = false
+ ): DataResponse {
+ try {
+ $this->initViewer(true);
+
+ $options = new TimelineOptions($this->request);
+ $options->setFormat(ACore::FORMAT_LOCAL);
+ $options->setTimeline('hashtag')
+ ->setLimit($limit)
+ ->setMaxId($max_id)
+ ->setMinId($min_id)
+ ->setSince($since)
+ ->setLocal($local)
+ ->setOnlyMedia($only_media)
+ ->setArgument($hashtag);
$posts = $this->streamService->getTimeline($options);
diff --git a/lib/Controller/OAuthController.php b/lib/Controller/OAuthController.php
index ec36c308..680d4f08 100644
--- a/lib/Controller/OAuthController.php
+++ b/lib/Controller/OAuthController.php
@@ -36,7 +36,6 @@ use OCA\Social\Exceptions\ClientNotFoundException;
use OCA\Social\Exceptions\InstanceDoesNotExistException;
use OCA\Social\Model\Client\SocialClient;
use OCA\Social\Service\AccountService;
-use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\ClientService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\InstanceService;
diff --git a/lib/Db/ActorsRequestBuilder.php b/lib/Db/ActorsRequestBuilder.php
index d9247f86..98b9ec82 100644
--- a/lib/Db/ActorsRequestBuilder.php
+++ b/lib/Db/ActorsRequestBuilder.php
@@ -33,7 +33,6 @@ namespace OCA\Social\Db;
use OCA\Social\Tools\Traits\TArrayTools;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Model\ActivityPub\Actor\Person;
-use OCP\DB\QueryBuilder\IQueryBuilder;
class ActorsRequestBuilder extends CoreRequestBuilder {
use TArrayTools;
@@ -42,7 +41,7 @@ class ActorsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Insert request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getActorsInsertSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -55,7 +54,7 @@ class ActorsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Update request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getActorsUpdateSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -90,7 +89,7 @@ class ActorsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Delete request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getActorsDeleteSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
diff --git a/lib/Db/CoreRequestBuilder.php b/lib/Db/CoreRequestBuilder.php
index c2ff47d5..a7c93c11 100644
--- a/lib/Db/CoreRequestBuilder.php
+++ b/lib/Db/CoreRequestBuilder.php
@@ -36,7 +36,6 @@ use DateTime;
use Doctrine\DBAL\Query\QueryBuilder;
use Exception;
use OC;
-use OC\DB\Connection;
use OC\DB\SchemaWrapper;
use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Model\ActivityPub\Actor\Person;
@@ -65,6 +64,7 @@ class CoreRequestBuilder {
public const TABLE_FOLLOWS = 'social_follow';
public const TABLE_HASHTAGS = 'social_hashtag';
public const TABLE_INSTANCE = 'social_instance';
+ public const TABLE_NOTIFICATION = 'social_notif';
public const TABLE_REQUEST_QUEUE = 'social_req_queue';
public const TABLE_STREAM = 'social_stream';
public const TABLE_STREAM_ACTIONS = 'social_stream_act';
@@ -1013,11 +1013,11 @@ class CoreRequestBuilder {
/**
- * @param IQueryBuilder $qb
+ * @param SocialQueryBuilder $qb
*
* @deprecated
*/
- protected function leftJoinStreamAction(IQueryBuilder &$qb) {
+ protected function leftJoinStreamAction(SocialQueryBuilder &$qb) {
if ($qb->getType() !== QueryBuilder::SELECT || $this->viewer === null) {
return;
}
@@ -1187,8 +1187,8 @@ class CoreRequestBuilder {
->selectAlias($prefix . '_f.follow_id', $prefix . '_follow_id')
->selectAlias($prefix . '_f.creation', $prefix . '_creation')
->leftJoin(
- $this->defaultSelectAlias, CoreRequestBuilder::TABLE_FOLLOWS, $prefix . '_f',
- $andX
+ $this->defaultSelectAlias, CoreRequestBuilder::TABLE_FOLLOWS, $prefix . '_f',
+ $andX
);
}
@@ -1263,7 +1263,7 @@ class CoreRequestBuilder {
* this just empty all tables from the app.
*/
public function emptyAll() {
- $schema = new SchemaWrapper(Server::get(Connection::class));
+ $schema = new SchemaWrapper(Server::get(IDBConnection::class));
foreach (array_keys(self::$tables) as $table) {
if ($schema->hasTable($table)) {
$qb = $this->dbConnection->getQueryBuilder();
@@ -1278,7 +1278,7 @@ class CoreRequestBuilder {
* this just empty all tables from the app.
*/
public function uninstallSocialTables() {
- $schema = new SchemaWrapper(Server::get(Connection::class));
+ $schema = new SchemaWrapper(Server::get(IDBConnection::class));
foreach (array_keys(self::$tables) as $table) {
if ($schema->hasTable($table)) {
$schema->dropTable($table);
diff --git a/lib/Db/HashtagsRequestBuilder.php b/lib/Db/HashtagsRequestBuilder.php
index b2cc075b..cc3598aa 100644
--- a/lib/Db/HashtagsRequestBuilder.php
+++ b/lib/Db/HashtagsRequestBuilder.php
@@ -32,7 +32,6 @@ declare(strict_types=1);
namespace OCA\Social\Db;
use OCA\Social\Tools\Traits\TArrayTools;
-use OCP\DB\QueryBuilder\IQueryBuilder;
/**
* Class HashtagsRequestBuilder
@@ -46,7 +45,7 @@ class HashtagsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Insert request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getHashtagsInsertSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -59,7 +58,7 @@ class HashtagsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Update request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getHashtagsUpdateSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -91,7 +90,7 @@ class HashtagsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Delete request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getHashtagsDeleteSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
diff --git a/lib/Db/RequestQueueRequestBuilder.php b/lib/Db/RequestQueueRequestBuilder.php
index a0ae7b33..a0731ada 100644
--- a/lib/Db/RequestQueueRequestBuilder.php
+++ b/lib/Db/RequestQueueRequestBuilder.php
@@ -32,7 +32,6 @@ namespace OCA\Social\Db;
use OCA\Social\Tools\Traits\TArrayTools;
use OCA\Social\Model\RequestQueue;
-use OCP\DB\QueryBuilder\IQueryBuilder;
class RequestQueueRequestBuilder extends CoreRequestBuilder {
use TArrayTools;
@@ -41,7 +40,7 @@ class RequestQueueRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Insert request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getRequestQueueInsertSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -54,7 +53,7 @@ class RequestQueueRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Update request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getRequestQueueUpdateSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -89,7 +88,7 @@ class RequestQueueRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Delete request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getRequestQueueDeleteSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
diff --git a/lib/Db/SocialLimitsQueryBuilder.php b/lib/Db/SocialLimitsQueryBuilder.php
index 68c5ae82..e025c740 100644
--- a/lib/Db/SocialLimitsQueryBuilder.php
+++ b/lib/Db/SocialLimitsQueryBuilder.php
@@ -335,8 +335,9 @@ class SocialLimitsQueryBuilder extends SocialCrossQueryBuilder {
$expr = $this->expr();
$pf = $this->getDefaultSelectAlias();
- if ($options->getSinceId() > 0) {
- $this->andWhere($expr->gt($pf . '.nid', $this->createNamedParameter($options->getSinceId())));
+ if ($options->getSince() > 0) {
+ $options->setInverted(true);
+ $this->andWhere($expr->gt($pf . '.nid', $this->createNamedParameter($options->getSince())));
}
if ($options->getMaxId() > 0) {
@@ -344,7 +345,6 @@ class SocialLimitsQueryBuilder extends SocialCrossQueryBuilder {
}
if ($options->getMinId() > 0) {
- $options->setInverted(true);
$this->andWhere($expr->gt($pf . '.nid', $this->createNamedParameter($options->getMinId())));
}
diff --git a/lib/Db/StreamActionsRequestBuilder.php b/lib/Db/StreamActionsRequestBuilder.php
index 5f61506a..ae5186ea 100644
--- a/lib/Db/StreamActionsRequestBuilder.php
+++ b/lib/Db/StreamActionsRequestBuilder.php
@@ -32,7 +32,6 @@ namespace OCA\Social\Db;
use OCA\Social\Tools\Traits\TArrayTools;
use OCA\Social\Model\StreamAction;
-use OCP\DB\QueryBuilder\IQueryBuilder;
/**
* Class StreamActionsRequestBuilder
@@ -46,7 +45,7 @@ class StreamActionsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Insert request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getStreamActionInsertSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -59,7 +58,7 @@ class StreamActionsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Update request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getStreamActionUpdateSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -91,7 +90,7 @@ class StreamActionsRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Delete request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getStreamActionDeleteSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
diff --git a/lib/Db/StreamQueueRequestBuilder.php b/lib/Db/StreamQueueRequestBuilder.php
index 37c5f8fd..626c4466 100644
--- a/lib/Db/StreamQueueRequestBuilder.php
+++ b/lib/Db/StreamQueueRequestBuilder.php
@@ -32,7 +32,6 @@ namespace OCA\Social\Db;
use OCA\Social\Tools\Traits\TArrayTools;
use OCA\Social\Model\StreamQueue;
-use OCP\DB\QueryBuilder\IQueryBuilder;
class StreamQueueRequestBuilder extends CoreRequestBuilder {
use TArrayTools;
@@ -41,7 +40,7 @@ class StreamQueueRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Insert request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getStreamQueueInsertSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -54,7 +53,7 @@ class StreamQueueRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Update request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getStreamQueueUpdateSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
@@ -88,7 +87,7 @@ class StreamQueueRequestBuilder extends CoreRequestBuilder {
/**
* Base of the Sql Delete request
*
- * @return IQueryBuilder
+ * @return SocialQueryBuilder
*/
protected function getStreamQueueDeleteSql(): SocialQueryBuilder {
$qb = $this->getQueryBuilder();
diff --git a/lib/Db/StreamRequest.php b/lib/Db/StreamRequest.php
index 813b3e87..156dfa2d 100644
--- a/lib/Db/StreamRequest.php
+++ b/lib/Db/StreamRequest.php
@@ -338,24 +338,38 @@ class StreamRequest extends StreamRequestBuilder {
return $this->getStreamFromRequest($qb);
}
-
+ /**
+ * @param TimelineOptions $options
+ *
+ * @return Stream[]
+ */
public function getTimeline(TimelineOptions $options): array {
switch (strtolower($options->getTimeline())) {
- case 'home':
+ case TimelineOptions::TIMELINE_HOME:
$result = $this->getTimelineHome($options);
break;
- case 'direct':
+ case TimelineOptions::TIMELINE_DIRECT:
$result = $this->getTimelineDirect($options);
break;
- case 'public':
+ case TimelineOptions::TIMELINE_FAVOURITES:
+ $result = $this->getTimelineFavourites($options);
+ break;
+ case TimelineOptions::TIMELINE_HASHTAG:
+ $result = $this->getTimelineHashtag($options, $options->getArgument());
+ break;
+ case TimelineOptions::TIMELINE_NOTIFICATIONS:
+ $options->setFormat(ACore::FORMAT_NOTIFICATION);
+ $result = $this->getTimelineNotifications($options);
+ break;
+ case TimelineOptions::TIMELINE_PUBLIC:
$result = $this->getTimelinePublic($options);
break;
-
default:
return [];
}
if ($options->isInverted()) {
+ // in cae we inverted the order during the request, we revert the results
$result = array_reverse($result);
}
@@ -412,6 +426,64 @@ class StreamRequest extends StreamRequestBuilder {
}
+ /**
+ * @param TimelineOptions $options
+ *
+ * @return Stream[]
+ */
+ private function getTimelineFavourites(TimelineOptions $options): array {
+ $qb = $this->getStreamSelectSql($options->getFormat());
+ $actor = $qb->getViewer();
+ $expr = $qb->expr();
+
+ $qb->limitToType(Note::TYPE);
+ $qb->paginate($options);
+ $qb->linkToCacheActors('ca', 's.attributed_to_prim');
+
+ $qb->selectStreamActions('sa');
+ $qb->andWhere($expr->eq('sa.stream_id_prim', 's.id_prim'));
+ $qb->andWhere($expr->eq('sa.actor_id_prim', $qb->createNamedParameter($qb->prim($actor->getId()))));
+ $qb->andWhere($expr->eq('sa.liked', $qb->createNamedParameter(1)));
+
+ return $this->getStreamsFromRequest($qb);
+ }
+
+
+ /**
+ * @param TimelineOptions $options
+ *
+ * @return Stream[]
+ */
+ private function getTimelineHashtag(TimelineOptions $options, string $hashtag): array {
+ $qb = $this->getStreamSelectSql($options->getFormat());
+
+ return [];
+
+ return $this->getStreamsFromRequest($qb);
+ }
+
+
+ /**
+ * @param TimelineOptions $options
+ *
+ * @return Stream[]
+ */
+ private function getTimelineNotifications(TimelineOptions $options): array {
+ $qb = $this->getStreamSelectSql($options->getFormat());
+ $actor = $qb->getViewer();
+
+ $qb->limitToType(SocialAppNotification::TYPE);
+ $qb->paginate($options);
+
+ $qb->selectDestFollowing('sd', '');
+ $qb->limitToDest($actor->getId(), 'notif', '', 'sd');
+ $qb->linkToCacheActors('ca', 's.attributed_to_prim');
+ $qb->leftJoinStreamAction();
+
+ return $this->getStreamsFromRequest($qb);
+ }
+
+
/**
* Should return:
* * Own posts,
@@ -456,8 +528,9 @@ class StreamRequest extends StreamRequestBuilder {
*
* @return Stream[]
* @throws DateTimeException
+ * @deprecated
*/
- public function getTimelineNotifications(int $since = 0, int $limit = 5): array {
+ public function getTimelineNotifications_dep(int $since = 0, int $limit = 5): array {
$qb = $this->getStreamSelectSql();
$actor = $qb->getViewer();
diff --git a/lib/Model/ActivityPub/ACore.php b/lib/Model/ActivityPub/ACore.php
index 00feb456..1451cb2d 100644
--- a/lib/Model/ActivityPub/ACore.php
+++ b/lib/Model/ActivityPub/ACore.php
@@ -30,9 +30,6 @@ declare(strict_types=1);
namespace OCA\Social\Model\ActivityPub;
-use OCA\Social\Tools\Traits\TArrayTools;
-use OCA\Social\Tools\Traits\TPathTools;
-use OCA\Social\Tools\Traits\TStringTools;
use JsonSerializable;
use OCA\Social\Exceptions\ActivityCantBeVerifiedException;
use OCA\Social\Exceptions\InvalidOriginException;
@@ -40,6 +37,9 @@ use OCA\Social\Exceptions\InvalidResourceEntryException;
use OCA\Social\Exceptions\UrlCloudException;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\LinkedDataSignature;
+use OCA\Social\Tools\Traits\TArrayTools;
+use OCA\Social\Tools\Traits\TPathTools;
+use OCA\Social\Tools\Traits\TStringTools;
class ACore extends Item implements JsonSerializable {
use TArrayTools;
@@ -63,6 +63,7 @@ class ACore extends Item implements JsonSerializable {
public const FORMAT_ACTIVITYPUB = 1;
public const FORMAT_LOCAL = 2;
+ public const FORMAT_NOTIFICATION = 3;
/** @var null Item */
@@ -681,6 +682,10 @@ class ACore extends Item implements JsonSerializable {
return $this->exportAsLocal();
}
+ if ($this->getExportFormat() === self::FORMAT_NOTIFICATION) {
+ return $this->exportAsNotification();
+ }
+
return $this->exportAsActivityPub();
}
@@ -767,4 +772,19 @@ class ACore extends Item implements JsonSerializable {
return $result;
}
+
+ /**
+ * @return array
+ */
+ public function exportAsNotification(): array {
+ $result = [
+ 'id' => $this->getId()
+ ];
+
+ if ($this->getNid() > 0) {
+ $result['id'] = (string)$this->getNid();
+ }
+
+ return $result;
+ }
}
diff --git a/lib/Model/ActivityPub/Stream.php b/lib/Model/ActivityPub/Stream.php
index 61ca03b3..03421f34 100644
--- a/lib/Model/ActivityPub/Stream.php
+++ b/lib/Model/ActivityPub/Stream.php
@@ -30,14 +30,17 @@ declare(strict_types=1);
namespace OCA\Social\Model\ActivityPub;
-use OCA\Social\Tools\IQueryRow;
-use OCA\Social\Tools\Model\Cache;
-use OCA\Social\Tools\Model\CacheItem;
use DateTime;
use Exception;
use JsonSerializable;
use OCA\Social\Model\ActivityPub\Actor\Person;
+use OCA\Social\Model\ActivityPub\Object\Announce;
+use OCA\Social\Model\ActivityPub\Object\Follow;
+use OCA\Social\Model\ActivityPub\Object\Like;
use OCA\Social\Model\StreamAction;
+use OCA\Social\Tools\IQueryRow;
+use OCA\Social\Tools\Model\Cache;
+use OCA\Social\Tools\Model\CacheItem;
use OCA\Social\Traits\TDetails;
/**
@@ -496,4 +499,35 @@ class Stream extends ACore implements IQueryRow, JsonSerializable {
return array_merge(parent::exportAsLocal(), $result);
}
+
+
+ public function exportAsNotification(): array {
+ switch ($this->getSubType()) {
+ case Like::TYPE:
+ $type = 'favourites';
+ break;
+ case Announce::TYPE:
+ $type = 'mention';
+ break;
+ case Follow::TYPE:
+ $type = 'follow';
+ break;
+ default:
+ $type = '';
+ }
+
+ $result = [
+ 'id' => $this->getId(),
+ 'type' => $type,
+ 'created_at' => $this->getOriginCreationTime(),
+ 'status' => $this->getDetails('post')
+ ];
+
+ if ($this->hasActor()) {
+ $actor = $this->getActor();
+ $result['account'] = $actor->exportAsLocal();
+ }
+
+ return array_merge(parent::exportAsNotification(), $result);
+ }
}
diff --git a/lib/Model/Client/Options/TimelineOptions.php b/lib/Model/Client/Options/TimelineOptions.php
index c009dd40..ae844d41 100644
--- a/lib/Model/Client/Options/TimelineOptions.php
+++ b/lib/Model/Client/Options/TimelineOptions.php
@@ -44,22 +44,35 @@ use OCP\IRequest;
class TimelineOptions extends CoreOptions implements JsonSerializable {
use TArrayTools;
+ public const TIMELINE_HOME = 'home';
+ public const TIMELINE_PUBLIC = 'public';
+ public const TIMELINE_DIRECT = 'direct';
+ public const TIMELINE_FAVOURITES = 'favourites';
+ public const TIMELINE_HASHTAG = 'hashtag';
+ public const TIMELINE_NOTIFICATIONS = 'notifications';
+
private string $timeline = '';
private bool $local = false;
private bool $remote = false;
private bool $onlyMedia = false;
private int $minId = 0;
private int $maxId = 0;
- private int $sinceId = 0;
+ private int $since = 0;
private int $limit = 20;
private bool $inverted = false;
+ private string $argument = '';
+ private array $types = [];
+ private array $excludeTypes = [];
+ private string $accountId = '';
public static array $availableTimelines = [
- 'home',
- 'public'
+ self::TIMELINE_HOME,
+ self::TIMELINE_PUBLIC,
+ self::TIMELINE_DIRECT,
+ self::TIMELINE_FAVOURITES,
+ self::TIMELINE_NOTIFICATIONS
];
-
/**
* TimelineOptions constructor.
*
@@ -197,17 +210,17 @@ class TimelineOptions extends CoreOptions implements JsonSerializable {
/**
* @return int
*/
- public function getSinceId(): int {
- return $this->sinceId;
+ public function getSince(): int {
+ return $this->since;
}
/**
- * @param int $sinceId
+ * @param int $since
*
* @return TimelineOptions
*/
- public function setSinceId(int $sinceId): self {
- $this->sinceId = $sinceId;
+ public function setSince(int $since): self {
+ $this->since = $since;
return $this;
}
@@ -251,6 +264,83 @@ class TimelineOptions extends CoreOptions implements JsonSerializable {
}
+ /**
+ * @param string $argument
+ *
+ * @return TimelineOptions
+ */
+ public function setArgument(string $argument): self {
+ $this->argument = $argument;
+
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getArgument(): string {
+ return $this->argument;
+ }
+
+
+ /**
+ * @param array $types
+ *
+ * @return TimelineOptions
+ */
+ public function setTypes(array $types): self {
+ $this->types = $types;
+
+ return $this;
+ }
+
+ /**
+ * @return array
+ */
+ public function getTypes(): array {
+ return $this->types;
+ }
+
+
+ /**
+ * @param array $excludeTypes
+ *
+ * @return TimelineOptions
+ */
+ public function setExcludeTypes(array $excludeTypes): self {
+ $this->excludeTypes = $excludeTypes;
+
+ return $this;
+ }
+
+ /**
+ * @return array
+ */
+ public function getExcludeTypes(): array {
+ return $this->excludeTypes;
+ }
+
+
+ /**
+ * @param string $accountId
+ *
+ * @return TimelineOptions
+ */
+ public function setAccountId(string $accountId): self {
+ $this->accountId = $accountId;
+
+ return $this;
+ }
+
+
+ /**
+ * @return string
+ */
+ public function getAccountId(): string {
+ return $this->accountId;
+ }
+
+
/**
* @param array $arr
*
@@ -262,8 +352,9 @@ class TimelineOptions extends CoreOptions implements JsonSerializable {
$this->setRemote($this->getBool('only_media', $arr, $this->isOnlyMedia()));
$this->setMinId($this->getInt('min_id', $arr, $this->getMinId()));
$this->setMaxId($this->getInt('max_id', $arr, $this->getMaxId()));
- $this->setSinceId($this->getInt('since_id', $arr, $this->getSinceId()));
+ $this->setSince($this->getInt('since', $arr, $this->getSince()));
$this->setLimit($this->getInt('limit', $arr, $this->getLimit()));
+ $this->setArgument($this->get('argument', $arr, $this->getArgument()));
return $this;
}
@@ -281,8 +372,9 @@ class TimelineOptions extends CoreOptions implements JsonSerializable {
'only_media' => $this->isOnlyMedia(),
'min_id' => $this->getMinId(),
'max_id' => $this->getMaxId(),
- 'since_id' => $this->getSinceId(),
- 'limit' => $this->getLimit()
+ 'since' => $this->getSince(),
+ 'limit' => $this->getLimit(),
+ 'argument' => $this->getArgument()
];
}
}
diff --git a/lib/Service/CurlService.php b/lib/Service/CurlService.php
index e21b2857..82b79996 100644
--- a/lib/Service/CurlService.php
+++ b/lib/Service/CurlService.php
@@ -52,7 +52,6 @@ use OCA\Social\Tools\Model\NCRequest;
use OCA\Social\Tools\Model\Request;
use OCA\Social\Tools\Traits\TArrayTools;
use OCA\Social\Tools\Traits\TPathTools;
-use OCP\AppFramework\Http;
use Psr\Log\LoggerInterface;
class CurlService {
diff --git a/lib/Service/StreamService.php b/lib/Service/StreamService.php
index 62ca49d0..473f049c 100644
--- a/lib/Service/StreamService.php
+++ b/lib/Service/StreamService.php
@@ -431,7 +431,7 @@ class StreamService {
* @deprecated
*/
public function getStreamNotifications(int $since = 0, int $limit = 5): array {
- return $this->streamRequest->getTimelineNotifications($since, $limit);
+ return $this->streamRequest->getTimelineNotifications_dep($since, $limit);
}
diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml
index ab16b035..46d5c462 100644
--- a/tests/psalm-baseline.xml
+++ b/tests/psalm-baseline.xml
@@ -56,6 +56,13 @@
$this->instance
+
+
+ dropTable
+ hasTable
+ hasTable
+
+
(bool)($this->cache->get(self::CACHE_PREFIX . 'wellknown') === 'true')
@@ -71,6 +78,9 @@
is_array($result)
+
+ $this->maxDownloadSizeReached === true
+