kopia lustrzana https://github.com/nextcloud/social
better index of streams
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>pull/794/head
rodzic
38fc103762
commit
a2d94040fa
|
@ -34,14 +34,20 @@ namespace OCA\Social\Command;
|
|||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use Exception;
|
||||
use OC\Core\Command\Base;
|
||||
use OCA\Social\Db\StreamDestRequest;
|
||||
use OCA\Social\Db\StreamRequest;
|
||||
use OCA\Social\Db\StreamTagsRequest;
|
||||
use OCA\Social\Service\CacheActorService;
|
||||
use OCA\Social\Service\CheckService;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCA\Social\Service\PushService;
|
||||
use OCP\IUserManager;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
|
||||
|
||||
class CheckInstall extends Base {
|
||||
|
@ -53,12 +59,27 @@ class CheckInstall extends Base {
|
|||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
|
||||
/** @var StreamRequest */
|
||||
private $streamRequest;
|
||||
|
||||
/** @var CacheActorService */
|
||||
private $cacheActorService;
|
||||
|
||||
/** @var StreamDestRequest */
|
||||
private $streamDestRequest;
|
||||
|
||||
/** @var StreamTagsRequest */
|
||||
private $streamTagsRequest;
|
||||
|
||||
/** @var CheckService */
|
||||
private $checkService;
|
||||
|
||||
/** @var */
|
||||
private $configService;
|
||||
|
||||
/** @var PushService */
|
||||
private $pushService;
|
||||
|
||||
/** @var MiscService */
|
||||
private $miscService;
|
||||
|
||||
|
@ -67,26 +88,34 @@ class CheckInstall extends Base {
|
|||
* CacheUpdate constructor.
|
||||
*
|
||||
* @param IUserManager $userManager
|
||||
* @param StreamRequest $streamRequest
|
||||
* @param StreamDestRequest $streamDestRequest
|
||||
* @param StreamTagsRequest $streamTagsRequest
|
||||
* @param CacheActorService $cacheActorService
|
||||
* @param CheckService $checkService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
* @param PushService $pushService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
IUserManager $userManager, CheckService $checkService, ConfigService $configService,
|
||||
MiscService $miscService, PushService $pushService
|
||||
IUserManager $userManager, StreamRequest $streamRequest, StreamDestRequest $streamDestRequest,
|
||||
StreamTagsRequest $streamTagsRequest, CacheActorService $cacheActorService,
|
||||
CheckService $checkService, ConfigService $configService, PushService $pushService,
|
||||
MiscService $miscService
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->userManager = $userManager;
|
||||
$this->streamRequest = $streamRequest;
|
||||
$this->streamDestRequest = $streamDestRequest;
|
||||
$this->streamTagsRequest = $streamTagsRequest;
|
||||
$this->cacheActorService = $cacheActorService;
|
||||
$this->checkService = $checkService;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
$this->pushService = $pushService;
|
||||
}
|
||||
|
||||
/** @var PushService */
|
||||
private $pushService;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -94,6 +123,7 @@ class CheckInstall extends Base {
|
|||
protected function configure() {
|
||||
parent::configure();
|
||||
$this->setName('social:check:install')
|
||||
->addOption('index', '', InputOption::VALUE_NONE, 'regenerate your index')
|
||||
->addOption(
|
||||
'push', '', InputOption::VALUE_REQUIRED,
|
||||
'a local account used to test integration to Nextcloud Push',
|
||||
|
@ -110,12 +140,16 @@ class CheckInstall extends Base {
|
|||
* @throws Exception
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
$result = $this->checkService->checkInstallationStatus();
|
||||
if ($this->askRegenerateIndex($input, $output)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->checkPushApp($input, $output)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$result = $this->checkService->checkInstallationStatus();
|
||||
|
||||
$output->writeln('- ' . $this->getInt('invalidFollowers', $result, 0) . ' invalid followers removed');
|
||||
$output->writeln('- ' . $this->getInt('invalidNotes', $result, 0) . ' invalid notes removed');
|
||||
|
||||
|
@ -150,5 +184,62 @@ class CheckInstall extends Base {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function askRegenerateIndex(InputInterface $input, OutputInterface $output): bool {
|
||||
if (!$input->getOption('index')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$helper = $this->getHelper('question');
|
||||
$output->writeln('<error>This command will regenerate the index of the Social App.</error>');
|
||||
$output->writeln(
|
||||
'<error>This operation can takes a while, and the Social App might not be stable during the process.</error>'
|
||||
);
|
||||
$output->writeln('');
|
||||
$question = new ConfirmationQuestion(
|
||||
'<info>Do you confirm this operation?</info> (y/N) ', false, '/^(y|Y)/i'
|
||||
);
|
||||
|
||||
if (!$helper->ask($input, $output, $question)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->streamDestRequest->emptyStreamDest();
|
||||
$this->streamTagsRequest->emptyStreamTags();
|
||||
$this->regenerateIndex($input, $output);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*/
|
||||
private function regenerateIndex(InputInterface $input, OutputInterface $output) {
|
||||
$streams = $this->streamRequest->getAll();
|
||||
$progressBar = new ProgressBar($output, count($streams));
|
||||
$progressBar->start();
|
||||
|
||||
foreach ($streams as $stream) {
|
||||
try {
|
||||
$this->streamDestRequest->generateStreamDest($stream);
|
||||
$this->streamTagsRequest->generateStreamTags($stream);
|
||||
} catch (Exception $e) {
|
||||
echo '-- ' . get_class($e) . ' - ' . $e->getMessage() . ' - ' . json_encode($stream) . "\n";
|
||||
}
|
||||
$progressBar->advance();
|
||||
}
|
||||
|
||||
$progressBar->finish();
|
||||
$output->writeln('');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -379,7 +379,7 @@ class LocalController extends Controller {
|
|||
public function streamHome($since = 0, int $limit = 5): DataResponse {
|
||||
try {
|
||||
$this->initViewer(true);
|
||||
$posts = $this->streamService->getStreamHome($this->viewer, $since, $limit);
|
||||
$posts = $this->streamService->getStreamHome($since, $limit);
|
||||
|
||||
return $this->success($posts);
|
||||
} catch (Exception $e) {
|
||||
|
@ -445,7 +445,7 @@ class LocalController extends Controller {
|
|||
public function streamDirect(int $since = 0, int $limit = 5): DataResponse {
|
||||
try {
|
||||
$this->initViewer(true);
|
||||
$posts = $this->streamService->getStreamDirect($this->viewer, $since, $limit);
|
||||
$posts = $this->streamService->getStreamDirect($since, $limit);
|
||||
|
||||
return $this->success($posts);
|
||||
} catch (Exception $e) {
|
||||
|
|
|
@ -43,7 +43,7 @@ class SocialFiltersQueryBuilder extends SocialLimitsQueryBuilder {
|
|||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
*
|
||||
*/
|
||||
public function filterDuplicate() {
|
||||
if (!$this->hasViewer()) {
|
||||
|
|
|
@ -387,5 +387,6 @@ class SocialLimitsQueryBuilder extends SocialCrossQueryBuilder {
|
|||
|
||||
$this->andWhere($orX);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,14 @@ namespace OCA\Social\Db;
|
|||
|
||||
use daita\MySmallPhpTools\Traits\TStringTools;
|
||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||
use Exception;
|
||||
use OCA\Social\Model\ActivityPub\Internal\SocialAppNotification;
|
||||
use OCA\Social\Model\ActivityPub\Stream;
|
||||
use OCA\Social\Service\CacheActorService;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\ILogger;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -47,17 +54,47 @@ class StreamDestRequest extends StreamDestRequestBuilder {
|
|||
use TStringTools;
|
||||
|
||||
|
||||
/** @var CacheActorService */
|
||||
private $cacheActorService;
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* StreamDestRequest constructor.
|
||||
*
|
||||
* @param IDBConnection $connection
|
||||
* @param ILogger $logger
|
||||
* @param CacheActorService $cacheActorService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function countStreamDest(): int {
|
||||
$qb = $this->countStreamDestSelectSql();
|
||||
public function __construct(
|
||||
IDBConnection $connection, ILogger $logger, CacheActorService $cacheActorService,
|
||||
ConfigService $configService, MiscService $miscService
|
||||
) {
|
||||
parent::__construct($connection, $logger, $configService, $miscService);
|
||||
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
$this->cacheActorService = $cacheActorService;
|
||||
}
|
||||
|
||||
return $this->getInt('count', $data, 0);
|
||||
|
||||
/**
|
||||
* @param string $streamId
|
||||
* @param string $actorId
|
||||
* @param string $type
|
||||
* @param string $subType
|
||||
*/
|
||||
public function create(string $streamId, string $actorId, string $type, string $subType = '') {
|
||||
$qb = $this->getStreamDestInsertSql();
|
||||
|
||||
$qb->setValue('stream_id', $qb->createNamedParameter($qb->prim($streamId)));
|
||||
$qb->setValue('actor_id', $qb->createNamedParameter($qb->prim($actorId)));
|
||||
$qb->setValue('type', $qb->createNamedParameter($type));
|
||||
$qb->setValue('subtype', $qb->createNamedParameter($subType));
|
||||
|
||||
try {
|
||||
$qb->execute();
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,6 +102,24 @@ class StreamDestRequest extends StreamDestRequestBuilder {
|
|||
* @param Stream $stream
|
||||
*/
|
||||
public function generateStreamDest(Stream $stream) {
|
||||
if ($this->generateStreamNotification($stream)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->generateStreamDirect($stream)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->generateStreamHome($stream);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Stream $stream
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function generateStreamHome(Stream $stream): bool {
|
||||
$recipients =
|
||||
[
|
||||
'to' => array_merge($stream->getToAll(), [$stream->getAttributedTo()]),
|
||||
|
@ -77,32 +132,76 @@ class StreamDestRequest extends StreamDestRequestBuilder {
|
|||
continue;
|
||||
}
|
||||
|
||||
$qb = $this->getStreamDestInsertSql();
|
||||
$streamId = $qb->prim($stream->getId());
|
||||
$qb->setValue('stream_id', $qb->createNamedParameter($streamId));
|
||||
$qb->setValue('actor_id', $qb->createNamedParameter($qb->prim($actorId)));
|
||||
$qb->setValue('type', $qb->createNamedParameter('recipient'));
|
||||
$qb->setValue('subtype', $qb->createNamedParameter($subtype));
|
||||
try {
|
||||
$qb->execute();
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
\OC::$server->getLogger()
|
||||
->log(1, 'Social - Duplicate recipient on Stream ' . json_encode($stream));
|
||||
}
|
||||
$this->create($stream->getId(), $actorId, 'recipient', $subtype);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Stream $stream
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function generateStreamDirect(Stream $stream): bool {
|
||||
try {
|
||||
$author = $this->cacheActorService->getFromId($stream->getAttributedTo());
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$all = array_merge(
|
||||
$stream->getToAll(), [$stream->getAttributedTo()], $stream->getCcArray(), $stream->getBccArray()
|
||||
);
|
||||
|
||||
foreach ($all as $item) {
|
||||
if ($item === Stream::CONTEXT_PUBLIC || $item === $author->getFollowers()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($all as $actorId) {
|
||||
if ($actorId === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->create($stream->getId(), $actorId, 'dm');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Stream $stream
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function generateStreamNotification(Stream $stream): bool {
|
||||
if ($stream->getType() !== SocialAppNotification::TYPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($stream->getToAll() as $actorId) {
|
||||
if ($actorId === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->create($stream->getId(), $actorId, 'notif');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function generateRandomDest() {
|
||||
$qb = $this->getStreamDestInsertSql();
|
||||
|
||||
$qb->setValue('actor_id', $qb->createNamedParameter($this->uuid()));
|
||||
$qb->setValue('stream_id', $qb->createNamedParameter($this->uuid()));
|
||||
$qb->setValue('type', $qb->createNamedParameter('unk'));
|
||||
public function emptyStreamDest() {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->delete(self::TABLE_STREAM_DEST);
|
||||
|
||||
$qb->execute();
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ use OCA\Social\Model\ActivityPub\Internal\SocialAppNotification;
|
|||
use OCA\Social\Model\ActivityPub\Object\Document;
|
||||
use OCA\Social\Model\ActivityPub\Object\Note;
|
||||
use OCA\Social\Model\ActivityPub\Stream;
|
||||
use OCA\Social\Service\CacheActorService;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
|
@ -59,6 +60,9 @@ use OCP\ILogger;
|
|||
class StreamRequest extends StreamRequestBuilder {
|
||||
|
||||
|
||||
/** @var CacheActorService */
|
||||
private $cacheActorService;
|
||||
|
||||
/** @var StreamDestRequest */
|
||||
private $streamDestRequest;
|
||||
|
||||
|
@ -71,16 +75,20 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
*
|
||||
* @param IDBConnection $connection
|
||||
* @param ILogger $logger
|
||||
* @param CacheActorService $cacheActorService
|
||||
* @param StreamDestRequest $streamDestRequest
|
||||
* @param StreamTagsRequest $streamTagsRequest
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
IDBConnection $connection, ILogger $logger, StreamDestRequest $streamDestRequest,
|
||||
StreamTagsRequest $streamTagsRequest, ConfigService $configService, MiscService $miscService
|
||||
IDBConnection $connection, ILogger $logger, CacheActorService $cacheActorService,
|
||||
StreamDestRequest $streamDestRequest, StreamTagsRequest $streamTagsRequest,
|
||||
ConfigService $configService, MiscService $miscService
|
||||
) {
|
||||
parent::__construct($connection, $logger, $configService, $miscService);
|
||||
|
||||
$this->cacheActorService = $cacheActorService;
|
||||
$this->streamDestRequest = $streamDestRequest;
|
||||
$this->streamTagsRequest = $streamTagsRequest;
|
||||
}
|
||||
|
@ -358,22 +366,20 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
* * Own posts,
|
||||
* * Followed accounts
|
||||
*
|
||||
* @param Person $actor
|
||||
* @param int $since
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Stream[]
|
||||
* @throws DateTimeException
|
||||
*/
|
||||
public function getTimelineHome(Person $actor, int $since = 0, int $limit = 5): array {
|
||||
public function getTimelineHome(int $since = 0, int $limit = 5): array {
|
||||
$qb = $this->getStreamSelectSql();
|
||||
$expr = $qb->expr();
|
||||
|
||||
$qb->linkToCacheActors('ca', 'f.object_id_prim');
|
||||
$qb->filterType(SocialAppNotification::TYPE);
|
||||
$qb->limitPaginate($since, $limit);
|
||||
|
||||
$qb->andWhere($qb->exprLimitToDBField('type', SocialAppNotification::TYPE, false));
|
||||
$qb->limitToViewer('sd', 'f', false);
|
||||
$this->timelineHomeLinkCacheActor($qb, 'ca', 'f');
|
||||
|
||||
$qb->leftJoinStreamAction('sa');
|
||||
$qb->filterDuplicate();
|
||||
|
@ -403,7 +409,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->limitPaginate($since, $limit);
|
||||
|
||||
$qb->selectDestFollowing('sd', '');
|
||||
$qb->limitToDest($actor->getId(), 'recipient', '', 'sd');
|
||||
$qb->limitToDest($actor->getId(), 'notif', '', 'sd');
|
||||
$qb->limitToType(SocialAppNotification::TYPE);
|
||||
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
|
@ -447,14 +453,13 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
* * Private message.
|
||||
* - group messages. (not yet)
|
||||
*
|
||||
* @param Person $actor
|
||||
* @param int $since
|
||||
* @param int $limit
|
||||
*
|
||||
* @return Stream[]
|
||||
* @throws DateTimeException
|
||||
*/
|
||||
public function getTimelineDirect(Person $actor, int $since = 0, int $limit = 5): array {
|
||||
public function getTimelineDirect(int $since = 0, int $limit = 5): array {
|
||||
$qb = $this->getStreamSelectSql();
|
||||
|
||||
$qb->filterType(SocialAppNotification::TYPE);
|
||||
|
@ -462,13 +467,9 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
|
||||
$viewer = $qb->getViewer();
|
||||
$qb->selectDestFollowing('sd', '');
|
||||
$qb->innerJoinSteamDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->limitToDest($actor->getId(), 'recipient', '', 'sd');
|
||||
|
||||
$qb->filterDest(ACore::CONTEXT_PUBLIC);
|
||||
$qb->filterDest($actor->getFollowers());
|
||||
$qb->andWhere($qb->exprLimitToDBFieldInt('hidden_on_timeline', 1, 's'));
|
||||
$qb->limitToDest($viewer->getId(), 'dm', '', 'sd');
|
||||
|
||||
return $this->getStreamsFromRequest($qb);
|
||||
}
|
||||
|
|
|
@ -27,25 +27,21 @@ declare(strict_types=1);
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace OCA\Social\Db;
|
||||
|
||||
|
||||
use daita\MySmallPhpTools\Exceptions\CacheItemNotFoundException;
|
||||
use daita\MySmallPhpTools\Exceptions\RowNotFoundException;
|
||||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
use OCA\Social\AP;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Exceptions\ItemUnknownException;
|
||||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Exceptions\StreamNotFoundException;
|
||||
use OCA\Social\Model\ActivityPub\ACore;
|
||||
use OCA\Social\Model\ActivityPub\Actor\Person;
|
||||
use OCA\Social\Model\ActivityPub\Object\Announce;
|
||||
use OCA\Social\Model\ActivityPub\Stream;
|
||||
use OCA\Social\Model\InstancePath;
|
||||
use OCP\DB\QueryBuilder\ICompositeExpression;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -139,232 +135,29 @@ class StreamRequestBuilder extends CoreRequestBuilder {
|
|||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
*/
|
||||
protected function limitToViewer(IQueryBuilder $qb) {
|
||||
$actor = $this->viewer;
|
||||
|
||||
// TODO - rewrite this request to use stream_dest !
|
||||
if ($this->viewer === null) {
|
||||
$qb->andWhere($this->exprLimitToRecipient($qb, ACore::CONTEXT_PUBLIC, false));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$on = $this->exprJoinFollowing($qb, $actor);
|
||||
$on->add($this->exprLimitToRecipient($qb, ACore::CONTEXT_PUBLIC, false));
|
||||
$on->add($this->exprLimitToRecipient($qb, $actor->getId(), true));
|
||||
$qb->join($this->defaultSelectAlias, CoreRequestBuilder::TABLE_FOLLOWS, 'f', $on);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param Person $actor
|
||||
*/
|
||||
protected function leftJoinFollowing(IQueryBuilder $qb, Person $actor) {
|
||||
if ($qb->getType() !== QueryBuilder::SELECT) {
|
||||
return;
|
||||
}
|
||||
|
||||
$on = $this->exprJoinFollowing($qb, $actor);
|
||||
$qb->selectAlias('f.object_id', 'following_actor_id');
|
||||
$qb->leftJoin($this->defaultSelectAlias, CoreRequestBuilder::TABLE_FOLLOWS, 'f', $on);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param Person $actor
|
||||
*
|
||||
* @return ICompositeExpression
|
||||
* @deprecated - use the new table social_stream_dest
|
||||
*/
|
||||
protected function exprJoinFollowing(IQueryBuilder $qb, Person $actor) {
|
||||
$expr = $qb->expr();
|
||||
$func = $qb->func();
|
||||
$pf = $this->defaultSelectAlias . '.';
|
||||
|
||||
$on = $expr->orX();
|
||||
|
||||
// list of possible recipient as a follower (to, to_array, cc, ...)
|
||||
$recipientFields = $expr->orX();
|
||||
$recipientFields->add($expr->eq($func->lower($pf . 'to'), $func->lower('f.follow_id')));
|
||||
$recipientFields->add($this->exprFieldWithinJsonFormat($qb, 'to_array', 'f.follow_id'));
|
||||
$recipientFields->add($this->exprFieldWithinJsonFormat($qb, 'cc', 'f.follow_id'));
|
||||
$recipientFields->add($this->exprFieldWithinJsonFormat($qb, 'bcc', 'f.follow_id'));
|
||||
|
||||
// all possible follow, but linked by followers (actor_id) and accepted follow
|
||||
$crossFollows = $expr->andX();
|
||||
$crossFollows->add($recipientFields);
|
||||
$crossFollows->add(
|
||||
$this->exprLimitToDBField($qb, 'actor_id', $actor->getId(), true, false, 'f')
|
||||
);
|
||||
$crossFollows->add($this->exprLimitToDBFieldInt($qb, 'accepted', 1, 'f'));
|
||||
$on->add($crossFollows);
|
||||
|
||||
return $on;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $field
|
||||
* @param string $fieldRight
|
||||
* @param SocialQueryBuilder $qb
|
||||
* @param string $alias
|
||||
*
|
||||
* @return string
|
||||
* @param string $aliasFollow
|
||||
*/
|
||||
protected function exprFieldWithinJsonFormat(
|
||||
IQueryBuilder $qb, string $field, string $fieldRight, string $alias = ''
|
||||
protected function timelineHomeLinkCacheActor(
|
||||
SocialQueryBuilder $qb, string $alias = 'ca', string $aliasFollow = 'f'
|
||||
) {
|
||||
$func = $qb->func();
|
||||
$expr = $qb->expr();
|
||||
|
||||
if ($alias === '') {
|
||||
$alias = $this->defaultSelectAlias;
|
||||
}
|
||||
|
||||
$concat = $func->concat(
|
||||
$qb->createNamedParameter('%"'),
|
||||
$func->concat($fieldRight, $qb->createNamedParameter('"%'))
|
||||
);
|
||||
|
||||
return $expr->iLike($alias . '.' . $field, $concat);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function exprValueWithinJsonFormat(IQueryBuilder $qb, string $field, string $value): string {
|
||||
$dbConn = $this->getConnection();
|
||||
$expr = $qb->expr();
|
||||
|
||||
return $expr->iLike(
|
||||
$field,
|
||||
$qb->createNamedParameter('%"' . $dbConn->escapeLikeParameter($value) . '"%')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $field
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function exprValueNotWithinJsonFormat(IQueryBuilder $qb, string $field, string $value): string {
|
||||
$dbConn = $this->getConnection();
|
||||
$expr = $qb->expr();
|
||||
$func = $qb->func();
|
||||
|
||||
return $expr->notLike(
|
||||
$func->lower($field),
|
||||
$qb->createNamedParameter(
|
||||
'%"' . $func->lower($dbConn->escapeLikeParameter($value)) . '"%'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $recipient
|
||||
* @param bool $asAuthor
|
||||
* @param array $type
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
protected function limitToRecipient(
|
||||
IQueryBuilder &$qb, string $recipient, bool $asAuthor = false, array $type = []
|
||||
) {
|
||||
$qb->andWhere($this->exprLimitToRecipient($qb, $recipient, $asAuthor, $type));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $recipient
|
||||
* @param bool $asAuthor
|
||||
* @param array $type
|
||||
*
|
||||
* @return ICompositeExpression
|
||||
* @deprecated
|
||||
*/
|
||||
protected function exprLimitToRecipient(
|
||||
IQueryBuilder &$qb, string $recipient, bool $asAuthor = false, array $type = []
|
||||
): ICompositeExpression {
|
||||
$qb->linkToCacheActors($alias);
|
||||
|
||||
$expr = $qb->expr();
|
||||
$limit = $expr->orX();
|
||||
$orX = $expr->orX();
|
||||
|
||||
if ($asAuthor === true) {
|
||||
$func = $qb->func();
|
||||
$limit->add(
|
||||
$expr->eq(
|
||||
$func->lower('attributed_to'),
|
||||
$func->lower($qb->createNamedParameter($recipient))
|
||||
)
|
||||
);
|
||||
}
|
||||
$follow = $expr->andX();
|
||||
$follow->add($expr->eq($aliasFollow . '.type', $qb->createNamedParameter('Follow')));
|
||||
$follow->add($expr->eq($alias . '.id_prim', $aliasFollow . '.object_id_prim'));
|
||||
$orX->add($follow);
|
||||
|
||||
if ($type === []) {
|
||||
$type = ['to', 'cc', 'bcc'];
|
||||
}
|
||||
$loopback = $expr->andX();
|
||||
$loopback->add($expr->eq($aliasFollow . '.type', $qb->createNamedParameter('Loopback')));
|
||||
$loopback->add($expr->eq($alias . '.id_prim', $qb->getDefaultSelectAlias() . '.attributed_to_prim'));
|
||||
$orX->add($loopback);
|
||||
|
||||
$this->addLimitToRecipient($qb, $limit, $type, $recipient);
|
||||
|
||||
return $limit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param ICompositeExpression $limit
|
||||
* @param array $type
|
||||
* @param string $to
|
||||
*/
|
||||
private function addLimitToRecipient(
|
||||
IQueryBuilder $qb, ICompositeExpression &$limit, array $type, string $to
|
||||
) {
|
||||
|
||||
$expr = $qb->expr();
|
||||
if (in_array('to', $type)) {
|
||||
$limit->add($expr->eq('to', $qb->createNamedParameter($to)));
|
||||
$limit->add($this->exprValueWithinJsonFormat($qb, 'to_array', $to));
|
||||
}
|
||||
|
||||
if (in_array('cc', $type)) {
|
||||
$limit->add($this->exprValueWithinJsonFormat($qb, 'cc', $to));
|
||||
}
|
||||
|
||||
if (in_array('bcc', $type)) {
|
||||
$limit->add($this->exprValueWithinJsonFormat($qb, 'bcc', $to));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $recipient
|
||||
*/
|
||||
protected function filterRecipient(IQueryBuilder &$qb, string $recipient) {
|
||||
|
||||
$expr = $qb->expr();
|
||||
$filter = $expr->andX();
|
||||
|
||||
$filter->add($expr->neq('to', $qb->createNamedParameter($recipient)));
|
||||
$filter->add($this->exprValueNotWithinJsonFormat($qb, 'to_array', $recipient));
|
||||
$filter->add($this->exprValueNotWithinJsonFormat($qb, 'cc', $recipient));
|
||||
$filter->add($this->exprValueNotWithinJsonFormat($qb, 'bcc', $recipient));
|
||||
|
||||
$qb->andWhere($filter);
|
||||
$qb->andWhere($orX);
|
||||
}
|
||||
|
||||
|
||||
|
@ -401,7 +194,6 @@ class StreamRequestBuilder extends CoreRequestBuilder {
|
|||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param string $as
|
||||
*
|
||||
* @return Stream
|
||||
* @throws ItemUnknownException
|
||||
|
|
|
@ -73,5 +73,16 @@ class StreamTagsRequest extends StreamTagsRequestBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function emptyStreamTags() {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->delete(self::TABLE_STREAM_TAGS);
|
||||
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -204,11 +204,10 @@ class AnnounceInterface implements IActivityPubInterface {
|
|||
* @throws Exception
|
||||
*/
|
||||
public function save(ACore $item) {
|
||||
|
||||
/** @var Announce $item */
|
||||
|
||||
try {
|
||||
$knownItem =
|
||||
$this->streamRequest->getStreamByObjectId($item->getObjectId(), Announce::TYPE);
|
||||
$knownItem = $this->streamRequest->getStreamByObjectId($item->getObjectId(), Announce::TYPE);
|
||||
|
||||
if ($item->hasActor()) {
|
||||
$actor = $item->getActor();
|
||||
|
@ -216,6 +215,7 @@ class AnnounceInterface implements IActivityPubInterface {
|
|||
$actor = $this->cacheActorService->getFromId($item->getActorId());
|
||||
}
|
||||
|
||||
$knownItem->setAttributedTo($actor->getId());
|
||||
if (!$knownItem->hasCc($actor->getFollowers())) {
|
||||
$knownItem->addCc($actor->getFollowers());
|
||||
$this->streamRequest->update($knownItem);
|
||||
|
@ -232,6 +232,7 @@ class AnnounceInterface implements IActivityPubInterface {
|
|||
} catch (StreamNotFoundException $e) {
|
||||
$objectId = $item->getObjectId();
|
||||
$item->addCacheItem($objectId);
|
||||
$item->setAttributedTo($item->getActorId());
|
||||
$this->streamRequest->save($item);
|
||||
|
||||
$this->streamQueueService->generateStreamQueue(
|
||||
|
@ -356,10 +357,6 @@ class AnnounceInterface implements IActivityPubInterface {
|
|||
* @param Stream $post
|
||||
*/
|
||||
private function updateDetails(Stream $post) {
|
||||
// if (!$post->isLocal()) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
$post->setDetailInt(
|
||||
'boosts', $this->actionsRequest->countActions($post->getId(), Announce::TYPE)
|
||||
);
|
||||
|
|
|
@ -36,6 +36,7 @@ use OCA\Social\Db\StreamRequest;
|
|||
use OCA\Social\Exceptions\AccountAlreadyExistsException;
|
||||
use OCA\Social\Exceptions\ActorDoesNotExistException;
|
||||
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
|
||||
use OCA\Social\Exceptions\ItemAlreadyExistsException;
|
||||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
use OCA\Social\Model\ActivityPub\Object\Follow;
|
||||
|
@ -240,18 +241,6 @@ class CheckService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* create a fake follow entry. Mandatory to have Home Stream working.
|
||||
*/
|
||||
public function checkStatusTableStreamDest() {
|
||||
if ($this->streamDestRequest->countStreamDest() > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->streamDestRequest->generateRandomDest();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* create entries in follows so that user follows itself.
|
||||
*
|
||||
|
@ -259,6 +248,7 @@ class CheckService {
|
|||
* @throws NoUserException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws UrlCloudException
|
||||
* @throws ItemAlreadyExistsException
|
||||
*/
|
||||
public function checkLocalAccountFollowingItself() {
|
||||
$users = $this->userManager->search('');
|
||||
|
|
|
@ -413,8 +413,8 @@ class StreamService {
|
|||
* @return Note[]
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getStreamHome(Person $actor, int $since = 0, int $limit = 5): array {
|
||||
return $this->streamRequest->getTimelineHome($actor, $since, $limit);
|
||||
public function getStreamHome(int $since = 0, int $limit = 5): array {
|
||||
return $this->streamRequest->getTimelineHome($since, $limit);
|
||||
}
|
||||
|
||||
|
||||
|
@ -452,8 +452,8 @@ class StreamService {
|
|||
* @return Note[]
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getStreamDirect(Person $actor, int $since = 0, int $limit = 5): array {
|
||||
return $this->streamRequest->getTimelineDirect($actor, $since, $limit);
|
||||
public function getStreamDirect(int $since = 0, int $limit = 5): array {
|
||||
return $this->streamRequest->getTimelineDirect($since, $limit);
|
||||
}
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue