mirror of
https://github.com/ad-aures/castopod.git
synced 2026-04-11 10:46:43 +02:00
feat(import): run podcast imports' processes asynchronously using tasks
- use codeigniter4/tasks project to handle cron tasks - use yassinedoghri/podcast-feed project to parse feeds for imports
This commit is contained in:
parent
85505d4b31
commit
d8e1d4031d
106 changed files with 1805 additions and 1097 deletions
181
modules/PodcastImport/Controllers/PodcastImportController.php
Normal file
181
modules/PodcastImport/Controllers/PodcastImportController.php
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright 2023 Ad Aures
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace Modules\PodcastImport\Controllers;
|
||||
|
||||
use App\Entities\Podcast;
|
||||
use App\Models\CategoryModel;
|
||||
use App\Models\LanguageModel;
|
||||
use App\Models\PodcastModel;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\HTTP\RedirectResponse;
|
||||
use CodeIgniter\I18n\Time;
|
||||
use Exception;
|
||||
use Modules\Admin\Controllers\BaseController;
|
||||
use Modules\PodcastImport\Entities\PodcastImportTask;
|
||||
use Modules\PodcastImport\Entities\TaskStatus;
|
||||
|
||||
class PodcastImportController extends BaseController
|
||||
{
|
||||
public function list(): string
|
||||
{
|
||||
helper('podcast_import');
|
||||
|
||||
return view('import/queue', [
|
||||
'podcastImportsQueue' => get_import_tasks(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function podcastList(int $podcastId): string
|
||||
{
|
||||
if (! ($podcast = (new PodcastModel())->getPodcastById($podcastId)) instanceof Podcast) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
helper('podcast_import');
|
||||
|
||||
replace_breadcrumb_params([
|
||||
0 => $podcast->at_handle,
|
||||
]);
|
||||
return view('import/podcast_queue', [
|
||||
'podcast' => $podcast,
|
||||
'podcastImportsQueue' => get_import_tasks($podcast->handle),
|
||||
]);
|
||||
}
|
||||
|
||||
public function addToQueueView(): string
|
||||
{
|
||||
helper(['form', 'misc']);
|
||||
|
||||
$languageOptions = (new LanguageModel())->getLanguageOptions();
|
||||
$categoryOptions = (new CategoryModel())->getCategoryOptions();
|
||||
|
||||
$data = [
|
||||
'languageOptions' => $languageOptions,
|
||||
'categoryOptions' => $categoryOptions,
|
||||
'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE')),
|
||||
];
|
||||
|
||||
return view('import/add_to_queue', $data);
|
||||
}
|
||||
|
||||
public function addToQueueAction(): RedirectResponse
|
||||
{
|
||||
$rules = [
|
||||
'handle' => 'required|regex_match[/^[a-zA-Z0-9\_]{1,32}$/]',
|
||||
'imported_feed_url' => 'required|valid_url_strict',
|
||||
'max_episodes' => 'is_natural_no_zero|permit_empty',
|
||||
];
|
||||
|
||||
if (! $this->validate($rules)) {
|
||||
return redirect()
|
||||
->back()
|
||||
->withInput()
|
||||
->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
// TODO: check that handle is not already in use
|
||||
|
||||
$importTask = new PodcastImportTask([
|
||||
'handle' => $this->request->getPost('handle'),
|
||||
'feed_url' => $this->request->getPost('imported_feed_url'),
|
||||
'language' => $this->request->getPost('language'),
|
||||
'category' => $this->request->getPost('category'),
|
||||
'status' => TaskStatus::Queued,
|
||||
'created_by' => user_id(),
|
||||
'updated_by' => user_id(),
|
||||
'created_at' => Time::now(),
|
||||
'updated_at' => Time::now(),
|
||||
]);
|
||||
|
||||
$importTask->save();
|
||||
|
||||
return redirect()->route('all-podcast-imports')
|
||||
->with('message', lang('PodcastImport.messages.importTaskQueued'));
|
||||
}
|
||||
|
||||
public function syncImport(int $podcastId): RedirectResponse
|
||||
{
|
||||
if (! ($podcast = (new PodcastModel())->getPodcastById($podcastId)) instanceof Podcast) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
if ($podcast->imported_feed_url === null) {
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', lang('PodcastImport.messages.podcastNotImported'));
|
||||
}
|
||||
|
||||
// create update task in podcastImport
|
||||
$importTask = new PodcastImportTask([
|
||||
'handle' => $podcast->handle,
|
||||
'feed_url' => $podcast->imported_feed_url,
|
||||
'language' => $podcast->language_code,
|
||||
'category' => $podcast->category_id,
|
||||
'status' => TaskStatus::Queued,
|
||||
'created_by' => user_id(),
|
||||
'updated_by' => user_id(),
|
||||
'created_at' => Time::now(),
|
||||
'updated_at' => Time::now(),
|
||||
]);
|
||||
|
||||
$importTask->save();
|
||||
|
||||
return redirect()->route('podcast-imports', [$podcastId])
|
||||
->with('message', lang('PodcastImport.messages.syncTaskQueued'));
|
||||
}
|
||||
|
||||
public function taskAction(string $taskId, string $action): RedirectResponse
|
||||
{
|
||||
/** @var array<string, PodcastImportTask> $importQueue */
|
||||
$importQueue = service('settings')
|
||||
->get('Import.queue') ?? [];
|
||||
|
||||
if (! array_key_exists($taskId, $importQueue)) {
|
||||
throw PageNotFoundException::forPageNotFound();
|
||||
}
|
||||
|
||||
$importTask = $importQueue[$taskId];
|
||||
switch ($action) {
|
||||
case 'cancel':
|
||||
$importTask->cancel();
|
||||
return redirect()->back()
|
||||
->with('message', lang('PodcastImport.messages.canceled'));
|
||||
case 'retry':
|
||||
if ($importTask->status === TaskStatus::Running) {
|
||||
return redirect()->back()
|
||||
->with('error', lang('PodcastImport.messages.alreadyRunning'));
|
||||
}
|
||||
|
||||
$newImportTask = new PodcastImportTask([
|
||||
'handle' => $importTask->handle,
|
||||
'feed_url' => $importTask->feed_url,
|
||||
'language' => $importTask->language,
|
||||
'category' => $importTask->category,
|
||||
'status' => TaskStatus::Queued,
|
||||
'created_by' => user_id(),
|
||||
'updated_by' => user_id(),
|
||||
'created_at' => Time::now(),
|
||||
'updated_at' => Time::now(),
|
||||
]);
|
||||
|
||||
$newImportTask->save();
|
||||
|
||||
return redirect()->back()
|
||||
->with('message', lang('PodcastImport.messages.retried'));
|
||||
case 'delete':
|
||||
$importTask->delete();
|
||||
return redirect()->back()
|
||||
->with('message', lang('PodcastImport.messages.deleted'));
|
||||
default:
|
||||
throw new Exception('Task action ' . $action . ' was not implemented');
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue