Extracted PodcastData to its own endpoint
This commit is contained in:
parent
403ead674d
commit
4771a52b63
@ -15,5 +15,6 @@ return [
|
|||||||
['name' => 'subscription_change#list', 'url' => '/subscriptions', 'verb' => 'GET'],
|
['name' => 'subscription_change#list', 'url' => '/subscriptions', 'verb' => 'GET'],
|
||||||
['name' => 'subscription_change#create', 'url' => '/subscription_change/create', 'verb' => 'POST'],
|
['name' => 'subscription_change#create', 'url' => '/subscription_change/create', 'verb' => 'POST'],
|
||||||
['name' => 'personal_settings#metrics', 'url' => '/personal_settings/metrics', 'verb' => 'GET'],
|
['name' => 'personal_settings#metrics', 'url' => '/personal_settings/metrics', 'verb' => 'GET'],
|
||||||
|
['name' => 'personal_settings#podcastData', 'url' => '/personal_settings/podcast_data', 'verb' => 'GET'],
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
@ -3,10 +3,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace OCA\GPodderSync\Controller;
|
namespace OCA\GPodderSync\Controller;
|
||||||
|
|
||||||
use OCA\GPodderSync\Core\PodcastData\PodcastMetrics;
|
use OCA\GPodderSync\Core\PodcastData\PodcastDataReader;
|
||||||
use OCA\GPodderSync\Core\PodcastData\PodcastMetricsReader;
|
use OCA\GPodderSync\Core\PodcastData\PodcastMetricsReader;
|
||||||
|
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http;
|
||||||
use OCP\AppFramework\Http\JSONResponse;
|
use OCP\AppFramework\Http\JSONResponse;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
|
|
||||||
@ -14,16 +15,19 @@ class PersonalSettingsController extends Controller {
|
|||||||
|
|
||||||
private string $userId;
|
private string $userId;
|
||||||
private PodcastMetricsReader $metricsReader;
|
private PodcastMetricsReader $metricsReader;
|
||||||
|
private PodcastDataReader $dataReader;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $AppName,
|
string $AppName,
|
||||||
IRequest $request,
|
IRequest $request,
|
||||||
string $UserId,
|
string $UserId,
|
||||||
PodcastMetricsReader $metricsReader,
|
PodcastMetricsReader $metricsReader,
|
||||||
|
PodcastDataReader $dataReader,
|
||||||
) {
|
) {
|
||||||
parent::__construct($AppName, $request);
|
parent::__construct($AppName, $request);
|
||||||
$this->userId = $UserId ?? '';
|
$this->userId = $UserId ?? '';
|
||||||
$this->metricsReader = $metricsReader;
|
$this->metricsReader = $metricsReader;
|
||||||
|
$this->dataReader = $dataReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,4 +43,23 @@ class PersonalSettingsController extends Controller {
|
|||||||
'subscriptions' => $metrics,
|
'subscriptions' => $metrics,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NoAdminRequired
|
||||||
|
* @NoCSRFRequired
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function podcastData(string $url = ''): JsonResponse {
|
||||||
|
if ($url === '') {
|
||||||
|
return new JSONResponse([
|
||||||
|
'message' => "Missing query parameter 'url'.",
|
||||||
|
'data' => null,
|
||||||
|
], statusCode: Http::STATUS_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
return new JsonResponse([
|
||||||
|
'data' => $this->dataReader->getCachedOrFetchPodcastData($url, $this->userId),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,39 +3,51 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace OCA\GPodderSync\Core\PodcastData;
|
namespace OCA\GPodderSync\Core\PodcastData;
|
||||||
|
|
||||||
|
use OCA\GPodderSync\Db\SubscriptionChange\SubscriptionChangeRepository;
|
||||||
use OCP\Http\Client\IClient;
|
use OCP\Http\Client\IClient;
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
use OCP\ICache;
|
use OCP\ICache;
|
||||||
use OCP\ICacheFactory;
|
use OCP\ICacheFactory;
|
||||||
|
|
||||||
class PodcastDataCache {
|
class PodcastDataReader {
|
||||||
private ?ICache $cache = null;
|
private ?ICache $cache = null;
|
||||||
private IClient $httpClient;
|
private IClient $httpClient;
|
||||||
|
private SubscriptionChangeRepository $subscriptionChangeRepository;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ICacheFactory $cacheFactory,
|
ICacheFactory $cacheFactory,
|
||||||
IClientService $httpClientService,
|
IClientService $httpClientService,
|
||||||
|
SubscriptionChangeRepository $subscriptionChangeRepository,
|
||||||
) {
|
) {
|
||||||
if ($cacheFactory->isLocalCacheAvailable()) {
|
if ($cacheFactory->isLocalCacheAvailable()) {
|
||||||
$this->cache = $cacheFactory->createLocal('GPodderSync-Podcasts');
|
$this->cache = $cacheFactory->createLocal('GPodderSync-Podcasts');
|
||||||
}
|
}
|
||||||
$this->httpClient = $httpClientService->newClient();
|
$this->httpClient = $httpClientService->newClient();
|
||||||
|
$this->subscriptionChangeRepository = $subscriptionChangeRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCachedOrFetchPodcastData(string $url): PodcastData {
|
public function getCachedOrFetchPodcastData(string $url, string $userId): ?PodcastData {
|
||||||
if ($this->cache == null) {
|
if ($this->cache == null) {
|
||||||
return $this->fetchPodcastData($url);
|
return $this->fetchPodcastData($url, $userId);
|
||||||
}
|
}
|
||||||
$oldData = $this->tryGetCachedPodcastData($url);
|
$oldData = $this->tryGetCachedPodcastData($url);
|
||||||
if ($oldData) {
|
if ($oldData) {
|
||||||
return $oldData;
|
return $oldData;
|
||||||
}
|
}
|
||||||
$newData = $this->fetchPodcastData($url);
|
$newData = $this->fetchPodcastData($url, $userId);
|
||||||
$this->trySetCachedPodcastData($url, $newData);
|
$this->trySetCachedPodcastData($url, $newData);
|
||||||
return $newData;
|
return $newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchPodcastData(string $url): PodcastData {
|
private function userHasPodcast(string $url, string $userId): bool {
|
||||||
|
$subscriptionChanges = $this->subscriptionChangeRepository->findByUrl($url, $userId);
|
||||||
|
return $subscriptionChanges !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchPodcastData(string $url, string $userId): PodcastData {
|
||||||
|
if (!$this->userHasPodcast($url, $userId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
$resp = $this->httpClient->get($url);
|
$resp = $this->httpClient->get($url);
|
||||||
$statusCode = $resp->getStatusCode();
|
$statusCode = $resp->getStatusCode();
|
||||||
if ($statusCode < 200 || $statusCode >= 300) {
|
if ($statusCode < 200 || $statusCode >= 300) {
|
||||||
@ -53,7 +65,7 @@ class PodcastDataCache {
|
|||||||
return PodcastData::fromArray($oldData);
|
return PodcastData::fromArray($oldData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trySetCachedPodcastData(string $url, PodcastData $data) {
|
public function trySetCachedPodcastData(string $url, PodcastData $data): bool {
|
||||||
$this->cache->set($url, $data->toArray());
|
return $this->cache->set($url, $data->toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,18 +9,15 @@ class PodcastMetrics implements JsonSerializable {
|
|||||||
private string $url;
|
private string $url;
|
||||||
private int $listenedSeconds;
|
private int $listenedSeconds;
|
||||||
private PodcastActionCounts $actionCounts;
|
private PodcastActionCounts $actionCounts;
|
||||||
private ?PodcastData $podcastData;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $url,
|
string $url,
|
||||||
int $listenedSeconds = 0,
|
int $listenedSeconds = 0,
|
||||||
?PodcastActionCounts $actionCounts = null,
|
?PodcastActionCounts $actionCounts = null,
|
||||||
?PodcastData $podcastData = null,
|
|
||||||
) {
|
) {
|
||||||
$this->url = $url;
|
$this->url = $url;
|
||||||
$this->actionCounts = $actionCounts ?? new PodcastActionCounts;
|
$this->actionCounts = $actionCounts ?? new PodcastActionCounts;
|
||||||
$this->listenedSeconds = $listenedSeconds;
|
$this->listenedSeconds = $listenedSeconds;
|
||||||
$this->podcastData = $podcastData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,13 +48,6 @@ class PodcastMetrics implements JsonSerializable {
|
|||||||
$this->listenedSeconds += $seconds;
|
$this->listenedSeconds += $seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return PodcastData|null
|
|
||||||
*/
|
|
||||||
public function getPodcastData(): ?PodcastData {
|
|
||||||
return $this->podcastData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string,mixed>
|
* @return array<string,mixed>
|
||||||
*/
|
*/
|
||||||
@ -67,7 +57,6 @@ class PodcastMetrics implements JsonSerializable {
|
|||||||
'url' => $this->url,
|
'url' => $this->url,
|
||||||
'listenedSeconds' => $this->listenedSeconds,
|
'listenedSeconds' => $this->listenedSeconds,
|
||||||
'actionCounts' => $this->actionCounts->toArray(),
|
'actionCounts' => $this->actionCounts->toArray(),
|
||||||
'podcastData' => $this->podcastData->toArray(),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,21 +13,15 @@ use Psr\Log\LoggerInterface;
|
|||||||
|
|
||||||
class PodcastMetricsReader {
|
class PodcastMetricsReader {
|
||||||
|
|
||||||
private LoggerInterface $logger;
|
|
||||||
private SubscriptionChangeRepository $subscriptionChangeRepository;
|
private SubscriptionChangeRepository $subscriptionChangeRepository;
|
||||||
private EpisodeActionRepository $episodeActionRepository;
|
private EpisodeActionRepository $episodeActionRepository;
|
||||||
private PodcastDataCache $cache;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
LoggerInterface $logger,
|
|
||||||
SubscriptionChangeRepository $subscriptionChangeRepository,
|
SubscriptionChangeRepository $subscriptionChangeRepository,
|
||||||
EpisodeActionRepository $episodeActionRepository,
|
EpisodeActionRepository $episodeActionRepository,
|
||||||
PodcastDataCache $cache,
|
|
||||||
) {
|
) {
|
||||||
$this->logger = $logger;
|
|
||||||
$this->subscriptionChangeRepository = $subscriptionChangeRepository;
|
$this->subscriptionChangeRepository = $subscriptionChangeRepository;
|
||||||
$this->episodeActionRepository = $episodeActionRepository;
|
$this->episodeActionRepository = $episodeActionRepository;
|
||||||
$this->cache = $cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,24 +63,12 @@ class PodcastMetricsReader {
|
|||||||
return $subscriptions;
|
return $subscriptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function tryGetParsedPodcastData(string $url): ?PodcastData {
|
|
||||||
try {
|
|
||||||
return $this->cache->getCachedOrFetchPodcastData($url);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
$this->logger->error("Failed to get podcast data.", [
|
|
||||||
'exception' => $e,
|
|
||||||
'podcastUrl' => $url,
|
|
||||||
]);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createMetricsForUrl(string $url): PodcastMetrics {
|
private function createMetricsForUrl(string $url): PodcastMetrics {
|
||||||
return new PodcastMetrics(
|
return new PodcastMetrics(
|
||||||
url: $url,
|
url: $url,
|
||||||
listenedSeconds: 0,
|
listenedSeconds: 0,
|
||||||
actionCounts: new PodcastActionCounts(),
|
actionCounts: new PodcastActionCounts(),
|
||||||
podcastData: $this->tryGetParsedPodcastData($url),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ class SubscriptionChangeMapper extends \OCP\AppFramework\Db\QBMapper {
|
|||||||
return $this->findEntities($qb);
|
return $this->findEntities($qb);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findByUrl(string $url, string $userId): SubscriptionChangeEntity {
|
public function findByUrl(string $url, string $userId): ?SubscriptionChangeEntity {
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
|
|
||||||
$qb->select('*')
|
$qb->select('*')
|
||||||
@ -42,6 +42,7 @@ class SubscriptionChangeMapper extends \OCP\AppFramework\Db\QBMapper {
|
|||||||
} catch (DoesNotExistException $e) {
|
} catch (DoesNotExistException $e) {
|
||||||
} catch (MultipleObjectsReturnedException $e) {
|
} catch (MultipleObjectsReturnedException $e) {
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function remove(SubscriptionChangeEntity $subscriptionChangeEntity) {
|
public function remove(SubscriptionChangeEntity $subscriptionChangeEntity) {
|
||||||
|
@ -18,7 +18,7 @@ class SubscriptionChangeRepository {
|
|||||||
return $this->subscriptionChangeMapper->findAll();
|
return $this->subscriptionChangeMapper->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findByUrl(string $episode, string $userId): SubscriptionChangeEntity {
|
public function findByUrl(string $episode, string $userId): ?SubscriptionChangeEntity {
|
||||||
return $this->subscriptionChangeMapper->findByUrl($episode, $userId);
|
return $this->subscriptionChangeMapper->findByUrl($episode, $userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user