Skip to content

Commit 6acb8bb

Browse files
committed
introduce a content provider interface
also: - migrate functions to be compatible with app_api v2 - stubs migrated to .php files - addition of a new route /deleteMatchingSources Signed-off-by: Anupam Kumar <[email protected]>
1 parent 92fc5ec commit 6acb8bb

28 files changed

+1511
-367
lines changed

appinfo/info.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<description><![CDATA[
77
Ask questions to nextcloud Assistant about the content of your documents.
88
]]></description>
9-
<version>1.0.0</version>
9+
<version>1.1.0</version>
1010
<licence>agpl</licence>
1111
<author>Julien Veyssier</author>
1212
<namespace>ContextChat</namespace>
@@ -20,7 +20,7 @@
2020
<screenshot>https://github.com/nextcloud/context_chat/raw/main/img/screenshot2.jpg</screenshot>
2121
<screenshot>https://github.com/nextcloud/context_chat/raw/main/img/screenshot3.jpg</screenshot>
2222
<dependencies>
23-
<nextcloud min-version="28" max-version="28"/>
23+
<nextcloud min-version="28" max-version="29"/>
2424
</dependencies>
2525
<background-jobs>
2626
<job>OCA\ContextChat\BackgroundJobs\SchedulerJob</job>

composer.lock

+94-77
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/AppInfo/Application.php

+3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99

1010
namespace OCA\ContextChat\AppInfo;
1111

12+
use OCA\ContextChat\Listener\AppDisableListener;
1213
use OCA\ContextChat\Listener\FileListener;
1314
use OCA\ContextChat\TextProcessing\ContextChatProvider;
1415
use OCA\ContextChat\TextProcessing\FreePromptProvider;
16+
use OCP\App\Events\AppDisableEvent;
1517
use OCP\AppFramework\App;
1618
use OCP\AppFramework\Bootstrap\IBootContext;
1719
use OCP\AppFramework\Bootstrap\IBootstrap;
@@ -66,6 +68,7 @@ public function register(IRegistrationContext $context): void {
6668
$context->registerEventListener(CacheEntryInsertedEvent::class, FileListener::class);
6769
$context->registerEventListener(NodeRemovedFromCache::class, FileListener::class);
6870
$context->registerEventListener(NodeWrittenEvent::class, FileListener::class);
71+
$context->registerEventListener(AppDisableEvent::class, AppDisableListener::class);
6972
$context->registerTextProcessingProvider(ContextChatProvider::class);
7073
$context->registerTextProcessingProvider(FreePromptProvider::class);
7174
}

lib/BackgroundJobs/IndexerJob.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ protected function index(array $files): void {
130130
$this->logger->error('Could not find file ' . $file->getPath(), ['exception' => $e]);
131131
continue 2;
132132
}
133-
$this->langRopeService->indexSources($userId, [$source]);
133+
$this->langRopeService->indexSources([$source]);
134134
}
135135
try {
136136
$this->queue->removeFromQueue($queueFile);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
/**
3+
* Nextcloud - ContextChat
4+
*
5+
* This file is licensed under the Affero General Public License version 3 or
6+
* later. See the COPYING file.
7+
*
8+
* @author Anupam Kumar <[email protected]>
9+
* @copyright Anupam Kumar 2024
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace OCA\ContextChat\BackgroundJobs;
15+
16+
use OCA\ContextChat\Public\IContentProvider;
17+
use OCA\ContextChat\Service\ProviderConfigService;
18+
use OCP\App\IAppManager;
19+
use OCP\AppFramework\Utility\ITimeFactory;
20+
use OCP\BackgroundJob\QueuedJob;
21+
use OCP\IUserManager;
22+
use OCP\Server;
23+
use Psr\Container\ContainerExceptionInterface;
24+
use Psr\Container\NotFoundExceptionInterface;
25+
use Psr\Log\LoggerInterface;
26+
27+
class InitialContentImportJob extends QueuedJob {
28+
public function __construct(
29+
private IAppManager $appManager,
30+
private ProviderConfigService $configService,
31+
private LoggerInterface $logger,
32+
private IUserManager $userMan,
33+
ITimeFactory $timeFactory,
34+
private ?string $userId,
35+
) {
36+
parent::__construct($timeFactory);
37+
}
38+
39+
/**
40+
* @param class-string<IContentProvider> $argument Provider class name
41+
* @return void
42+
*/
43+
protected function run($argument): void {
44+
if (!is_string($argument)) {
45+
return;
46+
}
47+
48+
try {
49+
/** @var IContentProvider */
50+
$providerObj = Server::get($argument);
51+
} catch (ContainerExceptionInterface | NotFoundExceptionInterface $e) {
52+
$this->logger->warning('Could not run initial import for content provider', ['exception' => $e]);
53+
return;
54+
}
55+
56+
if (!$this->appManager->isEnabledForUser($providerObj->getAppId())) {
57+
return;
58+
}
59+
60+
$registeredProviders = $this->configService->getProviders();
61+
$identifier = ProviderConfigService::getConfigKey($providerObj->getAppId(), $providerObj->getId());
62+
if (!isset($registeredProviders[$identifier])
63+
|| $registeredProviders[$identifier]['isInitiated']
64+
) {
65+
return;
66+
}
67+
68+
$providerObj->triggerInitialImport();
69+
$this->configService->updateProvider($providerObj->getAppId(), $providerObj->getId(), $argument, true);
70+
}
71+
}
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
/**
3+
* Nextcloud - ContextChat
4+
*
5+
* This file is licensed under the Affero General Public License version 3 or
6+
* later. See the COPYING file.
7+
*
8+
* @author Anupam Kumar <[email protected]>
9+
* @copyright Anupam Kumar 2024
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace OCA\ContextChat\BackgroundJobs;
15+
16+
use OCA\ContextChat\Db\QueueContentItem;
17+
use OCA\ContextChat\Db\QueueContentItemMapper;
18+
use OCA\ContextChat\Service\LangRopeService;
19+
use OCA\ContextChat\Service\ProviderConfigService;
20+
use OCA\ContextChat\Type\Source;
21+
use OCP\AppFramework\Utility\ITimeFactory;
22+
use OCP\BackgroundJob\IJobList;
23+
use OCP\BackgroundJob\QueuedJob;
24+
25+
class SubmitContentJob extends QueuedJob {
26+
private const BATCH_SIZE = 20;
27+
28+
public function __construct(
29+
ITimeFactory $timeFactory,
30+
private LangRopeService $service,
31+
private QueueContentItemMapper $mapper,
32+
private IJobList $jobList,
33+
) {
34+
parent::__construct($timeFactory);
35+
}
36+
37+
/**
38+
* @param $argument
39+
* @return void
40+
*/
41+
protected function run($argument): void {
42+
$entities = $this->mapper->getFromQueue(static::BATCH_SIZE);
43+
44+
if (empty($entities)) {
45+
return;
46+
}
47+
48+
/** @var array<string, array<QueueContentItem>> */
49+
$bucketed = [];
50+
foreach ($entities as $entity) {
51+
foreach (explode(',', $entity->getUsers()) as $userId) {
52+
if (!is_array($bucketed[$userId])) {
53+
$bucketed[$userId] = [];
54+
}
55+
$bucketed[$userId][] = $entity;
56+
}
57+
}
58+
59+
foreach ($bucketed as $userId => $entities) {
60+
$sources = array_map(function (QueueContentItem $item) use ($userId) {
61+
$sourceId = ProviderConfigService::getConfigKey($item->getAppId(), $item->getProviderId()) . ': ' . $item->getItemId();
62+
return new Source(
63+
$userId,
64+
$sourceId,
65+
$item->getTitle(),
66+
$item->getContent(),
67+
$item->getLastModified()->getTimeStamp(),
68+
$item->getDocumentType(),
69+
);
70+
}, $entities);
71+
72+
$this->service->indexSources($sources);
73+
}
74+
75+
foreach ($entities as $entity) {
76+
$this->mapper->removeFromQueue($entity);
77+
}
78+
79+
$this->jobList->add(static::class);
80+
}
81+
}

lib/Db/QueueContentItem.php

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
/**
3+
* Nextcloud - ContextChat
4+
*
5+
* This file is licensed under the Affero General Public License version 3 or
6+
* later. See the COPYING file.
7+
*
8+
* @author Anupam Kumar <[email protected]>
9+
* @copyright Anupam Kumar 2024
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace OCA\ContextChat\Db;
15+
16+
use OCP\AppFramework\Db\Entity;
17+
use OCP\DB\Types;
18+
19+
/**
20+
* Class QueueContentItem
21+
*
22+
* @package OCA\ContextChat\Db
23+
* @method setItemId(string $itemId)
24+
* @method string getItemId()
25+
* @method setAppId(string $appId)
26+
* @method string getAppId()
27+
* @method setProviderId(string $providerId)
28+
* @method string getProviderId()
29+
* @method setTitle(string $title)
30+
* @method string getTitle()
31+
* @method setContent(string $content)
32+
* @method string getContent()
33+
* @method setDocumentType(string $documentType)
34+
* @method string getDocumentType()
35+
* @method setLastModified(\DateTime $lastModified)
36+
* @method \DateTime getLastModified()
37+
* @method setUsers(string $users)
38+
* @method string getUsers()
39+
*/
40+
class QueueContentItem extends Entity {
41+
public $id;
42+
protected $itemId;
43+
protected $appId;
44+
protected $providerId;
45+
protected $title;
46+
protected $content;
47+
protected $documentType;
48+
protected $lastModified;
49+
protected $users;
50+
51+
public static $columns = [
52+
'id',
53+
'item_id',
54+
'app_id',
55+
'provider_id',
56+
'title',
57+
'content',
58+
'document_type',
59+
'last_modified',
60+
'users'
61+
];
62+
public static $fields = [
63+
'id',
64+
'itemId',
65+
'appId',
66+
'providerId',
67+
'title',
68+
'content',
69+
'documentType',
70+
'lastModified',
71+
'users'
72+
];
73+
74+
public function __construct() {
75+
// add types in constructor
76+
$this->addType('id', Types::INTEGER);
77+
$this->addType('itemId', Types::STRING);
78+
$this->addType('appId', Types::STRING);
79+
$this->addType('providerId', Types::STRING);
80+
$this->addType('title', Types::STRING);
81+
$this->addType('content', Types::STRING);
82+
$this->addType('documentType', Types::STRING);
83+
$this->addType('lastModified', Types::DATETIME);
84+
$this->addType('users', Types::STRING);
85+
}
86+
}

lib/Db/QueueContentItemMapper.php

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
/**
3+
* Nextcloud - ContextChat
4+
*
5+
* This file is licensed under the Affero General Public License version 3 or
6+
* later. See the COPYING file.
7+
*
8+
* @author Anupam Kumar <[email protected]>
9+
* @copyright Anupam Kumar 2024
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace OCA\ContextChat\Db;
15+
16+
use OCP\AppFramework\Db\QBMapper;
17+
use OCP\IDBConnection;
18+
19+
/**
20+
* @template-extends QBMapper<QueueContentItem>
21+
*/
22+
class QueueContentItemMapper extends QBMapper {
23+
/**
24+
* @var IDBConnection $db
25+
*/
26+
protected $db;
27+
28+
public function __construct(IDBConnection $db) {
29+
parent::__construct($db, 'context_chat_content_queue', QueueContentItem::class);
30+
}
31+
32+
/**
33+
* @param int $limit
34+
* @return array<QueueContentItem>
35+
* @throws \OCP\DB\Exception
36+
*/
37+
public function getFromQueue(int $limit): array {
38+
$qb = $this->db->getQueryBuilder();
39+
$qb->select(QueueContentItem::$columns)
40+
->from($this->getTableName())
41+
->setMaxResults($limit);
42+
43+
return $this->findEntities($qb);
44+
}
45+
46+
/**
47+
* @param QueueContentItem $item
48+
* @return void
49+
* @throws \OCP\DB\Exception
50+
*/
51+
public function removeFromQueue(QueueContentItem $item): void {
52+
$qb = $this->db->getQueryBuilder();
53+
$qb->delete($this->getTableName())
54+
->where($qb->expr()->eq('id', $qb->createPositionalParameter($item->getId())))
55+
->executeStatement();
56+
}
57+
}

0 commit comments

Comments
 (0)