Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
f8f60a429f | |||
4e0d69385f |
23
.dockerignore
Normal file
23
.dockerignore
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
|
||||||
|
.marginalia
|
||||||
|
|
||||||
|
js/
|
||||||
|
build/
|
||||||
|
coverage/
|
||||||
|
utils/docker-ci
|
||||||
|
|
||||||
|
vendor/
|
||||||
|
.php-cs-fixer.cache
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -18,3 +18,6 @@ js/
|
|||||||
build/
|
build/
|
||||||
coverage/
|
coverage/
|
||||||
utils/docker-ci
|
utils/docker-ci
|
||||||
|
|
||||||
|
vendor/
|
||||||
|
.php-cs-fixer.cache
|
||||||
|
31
.php-cs-fixer.dist.php
Normal file
31
.php-cs-fixer.dist.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
require_once './vendor/autoload.php';
|
||||||
|
|
||||||
|
use Nextcloud\CodingStandard\Config;
|
||||||
|
|
||||||
|
class MyConfig extends Config
|
||||||
|
{
|
||||||
|
public function getRules(): array
|
||||||
|
{
|
||||||
|
$rules = parent::getRules();
|
||||||
|
$rules['@PhpCsFixer'] = true;
|
||||||
|
$rules['curly_braces_position']['classes_opening_brace'] = 'next_line_unless_newline_at_signature_end';
|
||||||
|
$rules['phpdoc_to_comment'] = false;
|
||||||
|
return $rules;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = new MyConfig();
|
||||||
|
$config
|
||||||
|
->getFinder()
|
||||||
|
->notPath('build')
|
||||||
|
->notPath('l10n')
|
||||||
|
->notPath('node_modules')
|
||||||
|
->notPath('src')
|
||||||
|
->notPath('vendor')
|
||||||
|
->in(__DIR__);
|
||||||
|
|
||||||
|
return $config;
|
21
Dockerfile
Normal file
21
Dockerfile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
FROM nextcloud:30
|
||||||
|
|
||||||
|
ARG APP_NAME=radio
|
||||||
|
ENV NEXTCLOUD_UPDATE=1
|
||||||
|
ENV NEXTCLOUD_ADMIN_USER=$APP_NAME
|
||||||
|
ENV NEXTCLOUD_ADMIN_PASSWORD=$APP_NAME
|
||||||
|
ENV NEXTCLOUD_INIT_HTACCESS=1
|
||||||
|
ENV SQLITE_DATABASE=$APP_NAME
|
||||||
|
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y nodejs npm sqlite3 && \
|
||||||
|
rm -f /usr/local/etc/php/conf.d/opcache-recommended.ini && \
|
||||||
|
/entrypoint.sh true
|
||||||
|
|
||||||
|
USER www-data
|
||||||
|
|
||||||
|
COPY --chown=www-data:www-data . apps/$APP_NAME
|
||||||
|
RUN php occ app:enable $APP_NAME && \
|
||||||
|
php occ config:system:set debug --value=true
|
||||||
|
|
||||||
|
USER root
|
16
Makefile
16
Makefile
@ -4,7 +4,7 @@
|
|||||||
all: dev-setup lint build-js-production test
|
all: dev-setup lint build-js-production test
|
||||||
|
|
||||||
# Dev env management
|
# Dev env management
|
||||||
dev-setup: clean clean-dev npm-init
|
dev-setup: clean clean-dev composer-init npm-init
|
||||||
|
|
||||||
npm-init:
|
npm-init:
|
||||||
npm ci
|
npm ci
|
||||||
@ -12,6 +12,12 @@ npm-init:
|
|||||||
npm-update:
|
npm-update:
|
||||||
npm update
|
npm update
|
||||||
|
|
||||||
|
composer-init:
|
||||||
|
composer install
|
||||||
|
|
||||||
|
composer-update:
|
||||||
|
composer update
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
build-js:
|
build-js:
|
||||||
npm run dev
|
npm run dev
|
||||||
@ -52,6 +58,7 @@ clean:
|
|||||||
|
|
||||||
clean-dev:
|
clean-dev:
|
||||||
rm -rf node_modules
|
rm -rf node_modules
|
||||||
|
rm -rf vendor
|
||||||
|
|
||||||
release:
|
release:
|
||||||
krankerl package
|
krankerl package
|
||||||
@ -63,6 +70,13 @@ translations:
|
|||||||
php utils/docker-ci/translations/translationtool/translationtool.phar create-pot-files
|
php utils/docker-ci/translations/translationtool/translationtool.phar create-pot-files
|
||||||
php utils/docker-ci/translations/translationtool/translationtool.phar convert-po-files
|
php utils/docker-ci/translations/translationtool/translationtool.phar convert-po-files
|
||||||
|
|
||||||
|
dev: dev-setup
|
||||||
|
docker stop radio || true
|
||||||
|
docker rm radio || true
|
||||||
|
docker build -t radio .
|
||||||
|
docker run -itd --rm --name radio -v $(PWD):/var/www/html/apps/radio -p 80:80 radio
|
||||||
|
npm run watch
|
||||||
|
|
||||||
publish-appstore-nightly:
|
publish-appstore-nightly:
|
||||||
$(eval ASSET_URL = $(shell curl -s https://git.project-insanity.org/api/v4/projects/onny%2Fnextcloud-app-radio/releases | jq -r '.[0].assets.links[0].url'))
|
$(eval ASSET_URL = $(shell curl -s https://git.project-insanity.org/api/v4/projects/onny%2Fnextcloud-app-radio/releases | jq -r '.[0].assets.links[0].url'))
|
||||||
wget $(ASSET_URL) -O build/artifacts/radio.tar.gz
|
wget $(ASSET_URL) -O build/artifacts/radio.tar.gz
|
||||||
|
@ -16,17 +16,17 @@ app uses radio-browser.info database as a backend.
|
|||||||
- 👂 Smoth audio playback and transitions
|
- 👂 Smoth audio playback and transitions
|
||||||
|
|
||||||
</description>
|
</description>
|
||||||
<version>1.1.0</version>
|
<version>2.0.0</version>
|
||||||
<licence>agpl</licence>
|
<licence>agpl</licence>
|
||||||
<author mail="onny@project-insanity.org" >Jonas Heinrich</author>
|
<author mail="onny@project-insanity.org">Jonas Heinrich</author>
|
||||||
<namespace>Radio</namespace>
|
<namespace>Radio</namespace>
|
||||||
<category>multimedia</category>
|
<category>multimedia</category>
|
||||||
<website>https://git.project-insanity.org/onny/nextcloud-app-radio</website>
|
<website>https://git.project-insanity.org/onny/nextcloud-app-radio</website>
|
||||||
<bugs>https://git.project-insanity.org/onny/nextcloud-app-radio/issues</bugs>
|
<bugs>https://git.project-insanity.org/onny/nextcloud-app-radio/issues</bugs>
|
||||||
<screenshot small-thumbnail="https://git.project-insanity.org/onny/nextcloud-app-radio/raw/master/screenshot-thumbnail.jpg">https://git.project-insanity.org/onny/nextcloud-app-radio/raw/master/screenshot.png</screenshot>
|
<screenshot small-thumbnail="https://git.project-insanity.org/onny/nextcloud-app-radio/raw/master/screenshot-thumbnail.jpg">https://git.project-insanity.org/onny/nextcloud-app-radio/raw/master/screenshot.png</screenshot>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<php min-version="7.4" max-version="8" />
|
<php min-version="8.1" />
|
||||||
<nextcloud min-version="20" max-version="21"/>
|
<nextcloud min-version="29" max-version="30"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<navigations>
|
<navigations>
|
||||||
<navigation>
|
<navigation>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,7 +20,6 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -29,42 +30,41 @@ return [
|
|||||||
'station' => ['url' => '/station'],
|
'station' => ['url' => '/station'],
|
||||||
],
|
],
|
||||||
'routes' => [
|
'routes' => [
|
||||||
|
|
||||||
// Web page templates
|
// Web page templates
|
||||||
[
|
[
|
||||||
'name' => 'page#index',
|
'name' => 'page#index',
|
||||||
'url' => '/',
|
'url' => '/',
|
||||||
'verb' => 'GET'
|
'verb' => 'GET',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'page#index',
|
'name' => 'page#index',
|
||||||
'url' => '/top',
|
'url' => '/top',
|
||||||
'verb' => 'GET',
|
'verb' => 'GET',
|
||||||
'postfix' => 'top'
|
'postfix' => 'top',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'page#index',
|
'name' => 'page#index',
|
||||||
'url' => '/recent',
|
'url' => '/recent',
|
||||||
'verb' => 'GET',
|
'verb' => 'GET',
|
||||||
'postfix' => 'recent'
|
'postfix' => 'recent',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'page#index',
|
'name' => 'page#index',
|
||||||
'url' => '/new',
|
'url' => '/new',
|
||||||
'verb' => 'GET',
|
'verb' => 'GET',
|
||||||
'postfix' => 'new'
|
'postfix' => 'new',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'page#index',
|
'name' => 'page#index',
|
||||||
'url' => '/favorites',
|
'url' => '/favorites',
|
||||||
'verb' => 'GET',
|
'verb' => 'GET',
|
||||||
'postfix' => 'favorites'
|
'postfix' => 'favorites',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'page#index',
|
'name' => 'page#index',
|
||||||
'url' => '/categories',
|
'url' => '/categories',
|
||||||
'verb' => 'GET',
|
'verb' => 'GET',
|
||||||
'postfix' => 'categories'
|
'postfix' => 'categories',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'page#index',
|
'name' => 'page#index',
|
||||||
@ -78,14 +78,13 @@ return [
|
|||||||
'name' => 'favorite_api#preflighted_cors',
|
'name' => 'favorite_api#preflighted_cors',
|
||||||
'url' => '/api/0.1/{path}',
|
'url' => '/api/0.1/{path}',
|
||||||
'verb' => 'OPTIONS',
|
'verb' => 'OPTIONS',
|
||||||
'requirements' => ['path' => '.+']
|
'requirements' => ['path' => '.+'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'recent_api#preflighted_cors',
|
'name' => 'recent_api#preflighted_cors',
|
||||||
'url' => '/api/0.1/{path}',
|
'url' => '/api/0.1/{path}',
|
||||||
'verb' => 'OPTIONS',
|
'verb' => 'OPTIONS',
|
||||||
'requirements' => ['path' => '.+']
|
'requirements' => ['path' => '.+'],
|
||||||
]
|
],
|
||||||
|
],
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
@ -2,11 +2,35 @@
|
|||||||
"name": "onny/radio",
|
"name": "onny/radio",
|
||||||
"description": "Lint config for onny/radio",
|
"description": "Lint config for onny/radio",
|
||||||
"license": "AGPL",
|
"license": "AGPL",
|
||||||
"config": {
|
"autoload": {
|
||||||
"optimize-autoloader": true,
|
"psr-4": {
|
||||||
"classmap-authoritative": true
|
"OCA\\Radio\\": "lib/"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "find . -name \\*.php -not -path './vendor/*' -exec php -l \"{}\" \\;"
|
"lint": "find . -name \\*.php -not -path './vendor/*' -not -path './vendor-bin/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l",
|
||||||
|
"cs:check": "php-cs-fixer fix --dry-run --diff",
|
||||||
|
"cs:fix": "php-cs-fixer fix",
|
||||||
|
"psalm": "psalm --threads=1 --no-cache --show-info=true",
|
||||||
|
"rector": "rector && composer cs:fix"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"nextcloud/ocp": "^30.0.2",
|
||||||
|
"roave/security-advisories": "dev-latest",
|
||||||
|
"nextcloud/coding-standard": "^1.3.2",
|
||||||
|
"nextcloud/rector": "^0.2.1",
|
||||||
|
"rector/rector": "^1.2.10",
|
||||||
|
"vimeo/psalm": "^5.26.1",
|
||||||
|
"doctrine/dbal": "^4.2.1"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"optimize-autoloader": true,
|
||||||
|
"classmap-authoritative": true,
|
||||||
|
"platform": {
|
||||||
|
"php": "8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
3567
composer.lock
generated
Normal file
3567
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,25 +18,23 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\Radio\AppInfo;
|
namespace OCA\Radio\AppInfo;
|
||||||
|
|
||||||
use OC\Security\CSP\ContentSecurityPolicy;
|
use OCA\Radio\Dashboard\RadioWidget;
|
||||||
use OCA\Radio\Search\SearchProvider;
|
use OCA\Radio\Search\SearchProvider;
|
||||||
use OCP\AppFramework\App;
|
use OCP\AppFramework\App;
|
||||||
use OCP\AppFramework\Bootstrap\IBootContext;
|
use OCP\AppFramework\Bootstrap\IBootContext;
|
||||||
use OCP\AppFramework\Bootstrap\IBootstrap;
|
use OCP\AppFramework\Bootstrap\IBootstrap;
|
||||||
use OCP\AppFramework\Bootstrap\IRegistrationContext;
|
use OCP\AppFramework\Bootstrap\IRegistrationContext;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
use OCA\Radio\Dashboard\RadioWidget;
|
class Application extends App implements IBootstrap
|
||||||
|
{
|
||||||
class Application extends App implements IBootstrap {
|
|
||||||
|
|
||||||
public const APP_ID = 'radio';
|
public const APP_ID = 'radio';
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
@ -44,32 +42,11 @@ class Application extends App implements IBootstrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function register(IRegistrationContext $context): void {
|
public function register(IRegistrationContext $context): void {
|
||||||
|
|
||||||
$context->registerSearchProvider(SearchProvider::class);
|
$context->registerSearchProvider(SearchProvider::class);
|
||||||
$context->registerDashboardWidget(RadioWidget::class);
|
$context->registerDashboardWidget(RadioWidget::class);
|
||||||
|
|
||||||
$context->registerService('request', static function ($c) {
|
$context->registerService('request', static fn (ContainerInterface $c): mixed => $c->get(IRequest::class));
|
||||||
return $c->get(IRequest::class);
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->registerCsp();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function boot(IBootContext $context): void {
|
public function boot(IBootContext $context): void {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow radio-browser hosts in the csp
|
|
||||||
*
|
|
||||||
* @throws \OCP\AppFramework\QueryException
|
|
||||||
*/
|
|
||||||
public function registerCsp() {
|
|
||||||
$manager = $this->getContainer()->getServer()->getContentSecurityPolicyManager();
|
|
||||||
$policy = new ContentSecurityPolicy();
|
|
||||||
$policy->addAllowedConnectDomain('https://de1.api.radio-browser.info');
|
|
||||||
$policy->addAllowedImageDomain('*');
|
|
||||||
$policy->addAllowedMediaDomain('*');
|
|
||||||
$manager->addDefaultPolicy($policy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,24 +20,23 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Controller;
|
namespace OCA\Radio\Controller;
|
||||||
|
|
||||||
use Closure;
|
use OCA\Radio\Service\StationNotFound;
|
||||||
|
|
||||||
use OCP\AppFramework\Http;
|
use OCP\AppFramework\Http;
|
||||||
use OCP\AppFramework\Http\DataResponse;
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
|
|
||||||
use OCA\Radio\Service\StationNotFound;
|
trait Errors
|
||||||
|
{
|
||||||
trait Errors {
|
protected function handleNotFound(\Closure $callback): DataResponse {
|
||||||
protected function handleNotFound(Closure $callback): DataResponse {
|
|
||||||
try {
|
try {
|
||||||
|
/** @psalm-suppress MixedArgument */
|
||||||
return new DataResponse($callback());
|
return new DataResponse($callback());
|
||||||
} catch (StationNotFound $e) {
|
} catch (StationNotFound $stationNotFound) {
|
||||||
$message = ['message' => $e->getMessage()];
|
$message = ['message' => $stationNotFound->getMessage()];
|
||||||
|
|
||||||
return new DataResponse($message, Http::STATUS_NOT_FOUND);
|
return new DataResponse($message, Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,60 +20,70 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Controller;
|
namespace OCA\Radio\Controller;
|
||||||
|
|
||||||
use OC;
|
|
||||||
use OCA\Radio\ExportResponse;
|
|
||||||
use OCA\Radio\AppInfo\Application;
|
use OCA\Radio\AppInfo\Application;
|
||||||
use OCA\Radio\Service\FavoriteService;
|
use OCA\Radio\Service\FavoriteService;
|
||||||
|
use OCA\Radio\Service\UserService;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
use OCP\AppFramework\Http\DataResponse;
|
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||||
|
use OCP\AppFramework\Http\DataDownloadResponse;
|
||||||
|
use OCP\Defaults;
|
||||||
|
use OCP\HintException;
|
||||||
|
use OCP\IDateTimeFormatter;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
use SimpleXMLElement;
|
|
||||||
use DOMDocument;
|
|
||||||
|
|
||||||
class ExportController extends Controller {
|
|
||||||
/** @var FavoriteService */
|
|
||||||
private $service;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $userId;
|
|
||||||
|
|
||||||
|
class ExportController extends Controller
|
||||||
|
{
|
||||||
use Errors;
|
use Errors;
|
||||||
|
|
||||||
public function __construct(IRequest $request,
|
public function __construct(
|
||||||
FavoriteService $service,
|
IRequest $request,
|
||||||
$userId) {
|
private readonly FavoriteService $service,
|
||||||
|
private readonly UserService $user,
|
||||||
|
private readonly Defaults $defaults,
|
||||||
|
private readonly IDateTimeFormatter $dateTime,
|
||||||
|
) {
|
||||||
parent::__construct(Application::APP_ID, $request);
|
parent::__construct(Application::APP_ID, $request);
|
||||||
$this->service = $service;
|
|
||||||
$this->userId = $userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
public function index(): DataDownloadResponse {
|
||||||
*/
|
$user = $this->user->getUser();
|
||||||
public function index() {
|
if (is_null($user)) {
|
||||||
|
throw new HintException('User not logged in');
|
||||||
|
}
|
||||||
|
|
||||||
$xml = new SimpleXMLElement('<?xml version="1.0"?><playlist></playlist>');
|
$xml = new \SimpleXMLElement('<?xml version="1.0"?><playlist></playlist>');
|
||||||
$xml->addAttribute('encoding', 'UTF-8');
|
$xml->addAttribute('encoding', 'UTF-8');
|
||||||
|
|
||||||
$trackList = $xml->addChild('trackList');
|
$trackList = $xml->addChild('trackList');
|
||||||
foreach($this->service->findAll($this->userId) as $station) {
|
if ($trackList instanceof \SimpleXMLElement) {
|
||||||
|
foreach ($this->service->findAll($user->getUID()) as $station) {
|
||||||
$track = $trackList->addChild('track');
|
$track = $trackList->addChild('track');
|
||||||
|
if ($track instanceof \SimpleXMLElement) {
|
||||||
$track->addChild('location', $station->getUrlresolved());
|
$track->addChild('location', $station->getUrlresolved());
|
||||||
$track->addChild('title', $station->getName());
|
$track->addChild('title', $station->getName());
|
||||||
$track->addChild('image', $station->getFavicon());
|
$track->addChild('image', $station->getFavicon());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$dom = new DOMDocument("1.0");
|
|
||||||
$dom->preserveWhiteSpace = false;
|
|
||||||
$dom->formatOutput = true;
|
|
||||||
$dom->loadXML($xml->asXML());
|
|
||||||
|
|
||||||
return new ExportResponse($dom->saveXML());
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$dom = new \DOMDocument('1.0');
|
||||||
|
$dom->preserveWhiteSpace = false;
|
||||||
|
$dom->formatOutput = true;
|
||||||
|
|
||||||
|
/** @psalm-suppress ArgumentTypeCoercion */
|
||||||
|
$dom->loadXML($xml->asXML());
|
||||||
|
$returnstring = $dom->saveXML();
|
||||||
|
|
||||||
|
$userName = $user->getDisplayName();
|
||||||
|
$productName = $this->defaults->getName();
|
||||||
|
$date = $this->dateTime->formatDate(time());
|
||||||
|
$export_name = sprintf('%s Radio Favorites (%s) (%s).xspf', $productName, $userName, $date);
|
||||||
|
|
||||||
|
return new DataDownloadResponse($returnstring, $export_name, 'application/xspf+xml');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,83 +20,101 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Controller;
|
namespace OCA\Radio\Controller;
|
||||||
|
|
||||||
use OCA\Radio\AppInfo\Application;
|
use OCA\Radio\AppInfo\Application;
|
||||||
|
use OCA\Radio\Db\Station;
|
||||||
use OCA\Radio\Service\FavoriteService;
|
use OCA\Radio\Service\FavoriteService;
|
||||||
|
use OCA\Radio\Service\UserService;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||||
use OCP\AppFramework\Http\DataResponse;
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
|
|
||||||
class FavoriteController extends Controller {
|
class FavoriteController extends Controller
|
||||||
/** @var FavoriteService */
|
{
|
||||||
private $service;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $userId;
|
|
||||||
|
|
||||||
use Errors;
|
use Errors;
|
||||||
|
|
||||||
public function __construct(IRequest $request,
|
public function __construct(
|
||||||
FavoriteService $service,
|
IRequest $request,
|
||||||
$userId) {
|
private readonly FavoriteService $service,
|
||||||
|
private readonly UserService $user,
|
||||||
|
) {
|
||||||
parent::__construct(Application::APP_ID, $request);
|
parent::__construct(Application::APP_ID, $request);
|
||||||
$this->service = $service;
|
|
||||||
$this->userId = $userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function index(): DataResponse {
|
public function index(): DataResponse {
|
||||||
return new DataResponse($this->service->findAll($this->userId));
|
return new DataResponse($this->service->findAll($this->user->getUserUID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function show(int $id): DataResponse {
|
public function show(int $id): DataResponse {
|
||||||
return $this->handleNotFound(function () use ($id) {
|
return $this->handleNotFound(fn (): ?Station => $this->service->find($id, $this->user->getUserUID()));
|
||||||
return $this->service->find($id, $this->userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
public function create(
|
||||||
*/
|
string $stationuuid,
|
||||||
public function create(string $stationuuid, string $name, string $favicon, string $urlresolved,
|
string $name,
|
||||||
string $bitrate, string $country, string $language, string $homepage,
|
string $favicon,
|
||||||
string $codec, string $tags): DataResponse {
|
string $urlresolved,
|
||||||
return new DataResponse($this->service->create($stationuuid, $name,
|
string $bitrate,
|
||||||
$favicon, $urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $country,
|
||||||
$tags, $this->userId));
|
string $language,
|
||||||
|
string $homepage,
|
||||||
|
string $codec,
|
||||||
|
string $tags
|
||||||
|
): DataResponse {
|
||||||
|
return new DataResponse($this->service->create(
|
||||||
|
$stationuuid,
|
||||||
|
$name,
|
||||||
|
$favicon,
|
||||||
|
$urlresolved,
|
||||||
|
$bitrate,
|
||||||
|
$country,
|
||||||
|
$language,
|
||||||
|
$homepage,
|
||||||
|
$codec,
|
||||||
|
$tags,
|
||||||
|
$this->user->getUserUID()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
public function update(
|
||||||
*/
|
int $id,
|
||||||
public function update(int $id, string $stationuuid,
|
string $stationuuid,
|
||||||
string $name, string $favicon, string $urlresolved,
|
string $name,
|
||||||
string $bitrate, string $country, string $language, string $homepage,
|
string $favicon,
|
||||||
string $codec, string $tags): DataResponse {
|
string $urlresolved,
|
||||||
return $this->handleNotFound(function () use ($id, $stationuuid, $name,
|
string $bitrate,
|
||||||
$favicon, $urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $country,
|
||||||
$tags) {
|
string $language,
|
||||||
return $this->service->update($id, $stationuuid, $name, $favicon,
|
string $homepage,
|
||||||
$urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $codec,
|
||||||
$tags, $this->userId);
|
string $tags
|
||||||
});
|
): DataResponse {
|
||||||
|
return $this->handleNotFound(fn (): ?Station => $this->service->update(
|
||||||
|
$id,
|
||||||
|
$stationuuid,
|
||||||
|
$name,
|
||||||
|
$favicon,
|
||||||
|
$urlresolved,
|
||||||
|
$bitrate,
|
||||||
|
$country,
|
||||||
|
$language,
|
||||||
|
$homepage,
|
||||||
|
$codec,
|
||||||
|
$tags,
|
||||||
|
$this->user->getUserUID()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function destroy(int $id): DataResponse {
|
public function destroy(int $id): DataResponse {
|
||||||
return $this->handleNotFound(function () use ($id) {
|
return $this->handleNotFound(fn (): ?Station => $this->service->delete($id, $this->user->getUserUID()));
|
||||||
return $this->service->delete($id, $this->userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,36 +18,42 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\Radio\Controller;
|
namespace OCA\Radio\Controller;
|
||||||
|
|
||||||
use OCP\IRequest;
|
use OCA\Radio\AppInfo\Application;
|
||||||
use OCP\AppFramework\Http\TemplateResponse;
|
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||||
|
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||||
|
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||||
|
use OCP\AppFramework\Http\TemplateResponse;
|
||||||
|
use OCP\IRequest;
|
||||||
use OCP\Util;
|
use OCP\Util;
|
||||||
|
|
||||||
class PageController extends Controller {
|
class PageController extends Controller
|
||||||
|
{
|
||||||
protected $appName;
|
public function __construct(IRequest $request) {
|
||||||
|
parent::__construct(Application::APP_ID, $request);
|
||||||
public function __construct($appName, IRequest $request) {
|
|
||||||
parent::__construct($appName, $request);
|
|
||||||
$this->appName = $appName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
#[NoCSRFRequired]
|
||||||
* @NoCSRFRequired
|
public function index(): TemplateResponse {
|
||||||
*/
|
Util::addScript(Application::APP_ID, 'radio-main');
|
||||||
public function index() {
|
Util::addStyle(Application::APP_ID, 'icons');
|
||||||
Util::addScript($this->appName, 'radio-main');
|
|
||||||
Util::addStyle($this->appName, 'icons');
|
// Allow radio-browser hosts in the csp
|
||||||
|
$policy = new ContentSecurityPolicy();
|
||||||
|
$policy->addAllowedConnectDomain('https://de1.api.radio-browser.info');
|
||||||
|
$policy->addAllowedImageDomain('*');
|
||||||
|
$policy->addAllowedMediaDomain('*');
|
||||||
|
|
||||||
|
$response = new TemplateResponse(Application::APP_ID, 'main');
|
||||||
|
$response->setContentSecurityPolicy($policy);
|
||||||
|
|
||||||
$response = new TemplateResponse($this->appName, 'main');
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,82 +20,101 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Controller;
|
namespace OCA\Radio\Controller;
|
||||||
|
|
||||||
use OCA\Radio\AppInfo\Application;
|
use OCA\Radio\AppInfo\Application;
|
||||||
|
use OCA\Radio\Db\Station;
|
||||||
use OCA\Radio\Service\RecentService;
|
use OCA\Radio\Service\RecentService;
|
||||||
|
use OCA\Radio\Service\UserService;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||||
use OCP\AppFramework\Http\DataResponse;
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
|
|
||||||
class RecentController extends Controller {
|
class RecentController extends Controller
|
||||||
/** @var RecentService */
|
{
|
||||||
private $service;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $userId;
|
|
||||||
|
|
||||||
use Errors;
|
use Errors;
|
||||||
|
|
||||||
public function __construct(IRequest $request,
|
public function __construct(
|
||||||
RecentService $service,
|
IRequest $request,
|
||||||
$userId) {
|
private readonly RecentService $service,
|
||||||
|
private readonly UserService $user,
|
||||||
|
) {
|
||||||
parent::__construct(Application::APP_ID, $request);
|
parent::__construct(Application::APP_ID, $request);
|
||||||
$this->service = $service;
|
|
||||||
$this->userId = $userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function index(): DataResponse {
|
public function index(): DataResponse {
|
||||||
return new DataResponse($this->service->findAll($this->userId));
|
return new DataResponse($this->service->findAll($this->user->getUserUID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function show(int $id): DataResponse {
|
public function show(int $id): DataResponse {
|
||||||
return $this->handleNotFound(function () use ($id) {
|
return $this->handleNotFound(fn (): ?Station => $this->service->find($id, $this->user->getUserUID()));
|
||||||
return $this->service->find($id, $this->userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
public function create(
|
||||||
*/
|
string $stationuuid,
|
||||||
public function create(string $stationuuid, string $name, string $favicon, string $urlresolved,
|
string $name,
|
||||||
string $bitrate, string $country, string $language, string $homepage,
|
string $favicon,
|
||||||
string $codec, string $tags): DataResponse {
|
string $urlresolved,
|
||||||
return new DataResponse($this->service->create($stationuuid, $name,
|
string $bitrate,
|
||||||
$favicon, $urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $country,
|
||||||
$tags, $this->userId));
|
string $language,
|
||||||
|
string $homepage,
|
||||||
|
string $codec,
|
||||||
|
string $tags
|
||||||
|
): DataResponse {
|
||||||
|
return new DataResponse($this->service->create(
|
||||||
|
$stationuuid,
|
||||||
|
$name,
|
||||||
|
$favicon,
|
||||||
|
$urlresolved,
|
||||||
|
$bitrate,
|
||||||
|
$country,
|
||||||
|
$language,
|
||||||
|
$homepage,
|
||||||
|
$codec,
|
||||||
|
$tags,
|
||||||
|
$this->user->getUserUID()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
public function update(
|
||||||
*/
|
int $id,
|
||||||
public function update(int $id, string $stationuuid, string $name,
|
string $stationuuid,
|
||||||
string $favicon, string $urlresolved, string $bitrate, string $country,
|
string $name,
|
||||||
string $language, string $homepage, string $codec, string $tags): DataResponse {
|
string $favicon,
|
||||||
return $this->handleNotFound(function () use ($id, $stationuuid, $name,
|
string $urlresolved,
|
||||||
$favicon, $urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $bitrate,
|
||||||
$tags) {
|
string $country,
|
||||||
return $this->service->update($id, $stationuuid, $name, $favicon,
|
string $language,
|
||||||
$urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $homepage,
|
||||||
$tags, $this->userId);
|
string $codec,
|
||||||
});
|
string $tags
|
||||||
|
): DataResponse {
|
||||||
|
return $this->handleNotFound(fn (): ?Station => $this->service->update(
|
||||||
|
$id,
|
||||||
|
$stationuuid,
|
||||||
|
$name,
|
||||||
|
$favicon,
|
||||||
|
$urlresolved,
|
||||||
|
$bitrate,
|
||||||
|
$country,
|
||||||
|
$language,
|
||||||
|
$homepage,
|
||||||
|
$codec,
|
||||||
|
$tags,
|
||||||
|
$this->user->getUserUID()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function destroy(int $id): DataResponse {
|
public function destroy(int $id): DataResponse {
|
||||||
return $this->handleNotFound(function () use ($id) {
|
return $this->handleNotFound(fn (): ?Station => $this->service->delete($id, $this->user->getUserUID()));
|
||||||
return $this->service->delete($id, $this->userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,87 +20,103 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Controller;
|
namespace OCA\Radio\Controller;
|
||||||
|
|
||||||
use OCA\Radio\AppInfo\Application;
|
use OCA\Radio\AppInfo\Application;
|
||||||
|
use OCA\Radio\Db\Station;
|
||||||
|
use OCA\Radio\Service\RadioBrowserApiService;
|
||||||
use OCA\Radio\Service\RecentService;
|
use OCA\Radio\Service\RecentService;
|
||||||
|
use OCA\Radio\Service\UserService;
|
||||||
use OCP\AppFramework\Controller;
|
use OCP\AppFramework\Controller;
|
||||||
|
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||||
use OCP\AppFramework\Http\DataResponse;
|
use OCP\AppFramework\Http\DataResponse;
|
||||||
use OCP\IRequest;
|
use OCP\IRequest;
|
||||||
|
|
||||||
class StationController extends Controller {
|
class StationController extends Controller
|
||||||
/** @var StationController */
|
{
|
||||||
private $service;
|
|
||||||
|
|
||||||
/** @var RadioBrowserApiService */
|
|
||||||
private $radiobrowserapi;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $userId;
|
|
||||||
|
|
||||||
use Errors;
|
use Errors;
|
||||||
|
|
||||||
public function __construct(IRequest $request,
|
public function __construct(
|
||||||
RecentService $service,
|
IRequest $request,
|
||||||
RadioBrowserApiService $radiobrowserapi,
|
private readonly RecentService $service,
|
||||||
$userId) {
|
private readonly RadioBrowserApiService $radiobrowserapi,
|
||||||
|
private readonly UserService $user,
|
||||||
|
) {
|
||||||
parent::__construct(Application::APP_ID, $request);
|
parent::__construct(Application::APP_ID, $request);
|
||||||
$this->service = $service;
|
|
||||||
$this->radiobrowserapi = $radiobrowserapi;
|
|
||||||
$this->userId = $userId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function index(): DataResponse {
|
public function index(): DataResponse {
|
||||||
return new DataResponse($this->service->findAll($this->userId));
|
return new DataResponse($this->service->findAll($this->user->getUserUID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function show(int $id): DataResponse {
|
public function show(int $id): DataResponse {
|
||||||
return $this->handleNotFound(function () use ($id) {
|
return $this->handleNotFound(fn (): ?Station => $this->service->find($id, $this->user->getUserUID()));
|
||||||
return $this->service->find($id, $this->userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
public function create(
|
||||||
*/
|
string $stationuuid,
|
||||||
public function create(string $stationuuid, string $name, string $favicon, string $urlresolved,
|
string $name,
|
||||||
string $bitrate, string $country, string $language, string $homepage,
|
string $favicon,
|
||||||
string $codec, string $tags): DataResponse {
|
string $urlresolved,
|
||||||
return new DataResponse($this->service->create($stationuuid, $name,
|
string $bitrate,
|
||||||
$favicon, $urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $country,
|
||||||
$tags, $this->userId));
|
string $language,
|
||||||
|
string $homepage,
|
||||||
|
string $codec,
|
||||||
|
string $tags
|
||||||
|
): DataResponse {
|
||||||
|
return new DataResponse($this->service->create(
|
||||||
|
$stationuuid,
|
||||||
|
$name,
|
||||||
|
$favicon,
|
||||||
|
$urlresolved,
|
||||||
|
$bitrate,
|
||||||
|
$country,
|
||||||
|
$language,
|
||||||
|
$homepage,
|
||||||
|
$codec,
|
||||||
|
$tags,
|
||||||
|
$this->user->getUserUID()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
public function update(
|
||||||
*/
|
int $id,
|
||||||
public function update(int $id, string $stationuuid, string $name,
|
string $stationuuid,
|
||||||
string $favicon, string $urlresolved, string $bitrate, string $country,
|
string $name,
|
||||||
string $language, string $homepage, string $codec, string $tags): DataResponse {
|
string $favicon,
|
||||||
return $this->handleNotFound(function () use ($id, $stationuuid, $name,
|
string $urlresolved,
|
||||||
$favicon, $urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $bitrate,
|
||||||
$tags) {
|
string $country,
|
||||||
return $this->service->update($id, $stationuuid, $name, $favicon,
|
string $language,
|
||||||
$urlresolved, $bitrate, $country, $language, $homepage, $codec,
|
string $homepage,
|
||||||
$tags, $this->userId);
|
string $codec,
|
||||||
});
|
string $tags
|
||||||
|
): DataResponse {
|
||||||
|
return $this->handleNotFound(fn (): ?Station => $this->service->update(
|
||||||
|
$id,
|
||||||
|
$stationuuid,
|
||||||
|
$name,
|
||||||
|
$favicon,
|
||||||
|
$urlresolved,
|
||||||
|
$bitrate,
|
||||||
|
$country,
|
||||||
|
$language,
|
||||||
|
$homepage,
|
||||||
|
$codec,
|
||||||
|
$tags,
|
||||||
|
$this->user->getUserUID()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#[NoAdminRequired]
|
||||||
* @NoAdminRequired
|
|
||||||
*/
|
|
||||||
public function destroy(int $id): DataResponse {
|
public function destroy(int $id): DataResponse {
|
||||||
return $this->handleNotFound(function () use ($id) {
|
return $this->handleNotFound(fn (): ?Station => $this->service->delete($id, $this->user->getUserUID()));
|
||||||
return $this->service->delete($id, $this->userId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,72 +20,43 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Dashboard;
|
namespace OCA\Radio\Dashboard;
|
||||||
|
|
||||||
|
use OCA\Radio\AppInfo\Application;
|
||||||
use OCP\Dashboard\IWidget;
|
use OCP\Dashboard\IWidget;
|
||||||
use OCP\IL10N;
|
use OCP\IL10N;
|
||||||
use OCP\IURLGenerator;
|
use OCP\IURLGenerator;
|
||||||
use OCP\Util;
|
use OCP\Util;
|
||||||
|
|
||||||
use OCA\Radio\AppInfo\Application;
|
class RadioWidget implements IWidget
|
||||||
|
{
|
||||||
class RadioWidget implements IWidget {
|
|
||||||
|
|
||||||
/** @var IL10N */
|
|
||||||
private $l10n;
|
|
||||||
|
|
||||||
/** @var IURLGenerator */
|
|
||||||
private $urlGenerator;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IL10N $l10n,
|
private readonly IL10N $l10n,
|
||||||
IURLGenerator $urlGenerator
|
private readonly IURLGenerator $urlGenerator
|
||||||
) {
|
) {}
|
||||||
$this->l10n = $l10n;
|
|
||||||
$this->urlGenerator = $urlGenerator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function getId(): string {
|
public function getId(): string {
|
||||||
return Application::APP_ID;
|
return Application::APP_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function getTitle(): string {
|
public function getTitle(): string {
|
||||||
return $this->l10n->t('Radio stations');
|
return $this->l10n->t('Radio stations');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function getOrder(): int {
|
public function getOrder(): int {
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function getIconClass(): string {
|
public function getIconClass(): string {
|
||||||
return 'icon-radio';
|
return 'icon-radio';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function getUrl(): ?string {
|
public function getUrl(): ?string {
|
||||||
return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute('radio.page.index'));
|
return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkToRoute('radio.page.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function load(): void {
|
public function load(): void {
|
||||||
Util::addScript(Application::APP_ID, 'radio-dashboard');
|
Util::addScript(Application::APP_ID, 'radio-dashboard');
|
||||||
Util::addStyle(Application::APP_ID, 'dashboard');
|
Util::addStyle(Application::APP_ID, 'dashboard');
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,49 +20,50 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Db;
|
namespace OCA\Radio\Db;
|
||||||
|
|
||||||
use OCP\AppFramework\Db\DoesNotExistException;
|
use OCP\AppFramework\Db\DoesNotExistException;
|
||||||
use OCP\AppFramework\Db\Entity;
|
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||||
use OCP\AppFramework\Db\QBMapper;
|
use OCP\AppFramework\Db\QBMapper;
|
||||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\IDBConnection;
|
use OCP\IDBConnection;
|
||||||
|
|
||||||
class FavoriteMapper extends QBMapper {
|
/**
|
||||||
|
* @extends QBMapper<Station>
|
||||||
|
*/
|
||||||
|
class FavoriteMapper extends QBMapper
|
||||||
|
{
|
||||||
public function __construct(IDBConnection $db) {
|
public function __construct(IDBConnection $db) {
|
||||||
parent::__construct($db, 'favorites', Station::class);
|
parent::__construct($db, 'favorites', Station::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $id
|
* @throws MultipleObjectsReturnedException
|
||||||
* @param string $userId
|
|
||||||
* @return Entity|Station
|
|
||||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
|
||||||
* @throws DoesNotExistException
|
* @throws DoesNotExistException
|
||||||
*/
|
*/
|
||||||
public function find(int $id, string $userId): Station {
|
public function find(int $id, string $userId): Station {
|
||||||
/* @var $qb IQueryBuilder */
|
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('*')
|
||||||
->from('favorites')
|
->from('favorites')
|
||||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
|
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
|
||||||
->andWhere($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
|
->andWhere($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)))
|
||||||
|
;
|
||||||
|
|
||||||
return $this->findEntity($qb);
|
return $this->findEntity($qb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $userId
|
* @return Station[]
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function findAll(string $userId): array {
|
public function findAll(string $userId): array {
|
||||||
/* @var $qb IQueryBuilder */
|
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->select('*')
|
$qb->select('*')
|
||||||
->from('favorites')
|
->from('favorites')
|
||||||
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
|
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)))
|
||||||
|
;
|
||||||
|
|
||||||
return $this->findEntities($qb);
|
return $this->findEntities($qb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,31 +20,30 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Db;
|
namespace OCA\Radio\Db;
|
||||||
|
|
||||||
use OCP\AppFramework\Db\DoesNotExistException;
|
use OCP\AppFramework\Db\DoesNotExistException;
|
||||||
use OCP\AppFramework\Db\Entity;
|
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||||
use OCP\AppFramework\Db\QBMapper;
|
use OCP\AppFramework\Db\QBMapper;
|
||||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\IDBConnection;
|
use OCP\IDBConnection;
|
||||||
|
|
||||||
class RecentMapper extends QBMapper {
|
/**
|
||||||
|
* @extends QBMapper<Station>
|
||||||
|
*/
|
||||||
|
class RecentMapper extends QBMapper
|
||||||
|
{
|
||||||
public function __construct(IDBConnection $db) {
|
public function __construct(IDBConnection $db) {
|
||||||
parent::__construct($db, 'recent', Station::class);
|
parent::__construct($db, 'recent', Station::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $id
|
* @throws MultipleObjectsReturnedException
|
||||||
* @param string $userId
|
|
||||||
* @return Entity|Station
|
|
||||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
|
||||||
* @throws DoesNotExistException
|
* @throws DoesNotExistException
|
||||||
*/
|
*/
|
||||||
public function find(int $id, string $userId): Station {
|
public function find(int $id, string $userId): Station {
|
||||||
/* @var $qb IQueryBuilder */
|
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->selectDistinct('stationuuid')
|
$qb->selectDistinct('stationuuid')
|
||||||
->addSelect('name')
|
->addSelect('name')
|
||||||
@ -57,16 +58,16 @@ class RecentMapper extends QBMapper {
|
|||||||
->from('recent')
|
->from('recent')
|
||||||
->orderBy('id', 'DESC')
|
->orderBy('id', 'DESC')
|
||||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
|
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
|
||||||
->andWhere($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
|
->andWhere($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)))
|
||||||
|
;
|
||||||
|
|
||||||
return $this->findEntity($qb);
|
return $this->findEntity($qb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $userId
|
* @return Station[]
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function findAll(string $userId): array {
|
public function findAll(string $userId): array {
|
||||||
/* @var $qb IQueryBuilder */
|
|
||||||
$qb = $this->db->getQueryBuilder();
|
$qb = $this->db->getQueryBuilder();
|
||||||
$qb->selectDistinct('stationuuid')
|
$qb->selectDistinct('stationuuid')
|
||||||
->addSelect('name')
|
->addSelect('name')
|
||||||
@ -80,7 +81,9 @@ class RecentMapper extends QBMapper {
|
|||||||
->addSelect('tags')
|
->addSelect('tags')
|
||||||
->from('recent')
|
->from('recent')
|
||||||
->orderBy('id', 'DESC')
|
->orderBy('id', 'DESC')
|
||||||
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
|
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)))
|
||||||
|
;
|
||||||
|
|
||||||
return $this->findEntities($qb);
|
return $this->findEntities($qb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,27 +20,61 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Db;
|
namespace OCA\Radio\Db;
|
||||||
|
|
||||||
use JsonSerializable;
|
|
||||||
|
|
||||||
use OCP\AppFramework\Db\Entity;
|
use OCP\AppFramework\Db\Entity;
|
||||||
|
|
||||||
class Station extends Entity implements JsonSerializable {
|
/**
|
||||||
protected $stationuuid;
|
* @method string getStationuuid()
|
||||||
protected $name;
|
* @method string getName()
|
||||||
protected $favicon;
|
* @method ?string getFavicon()
|
||||||
protected $urlresolved;
|
* @method ?string getUrlresolved()
|
||||||
protected $bitrate;
|
* @method ?string getBitrate()
|
||||||
protected $country;
|
* @method ?string getCountry()
|
||||||
protected $language;
|
* @method ?string getLanguage()
|
||||||
protected $homepage;
|
* @method ?string getHomepage()
|
||||||
protected $codec;
|
* @method ?string getCodec()
|
||||||
protected $tags;
|
* @method ?string getTags()
|
||||||
protected $userId;
|
* @method string getUserId()
|
||||||
|
* @method void setStationuuid(string $stationuuid)
|
||||||
|
* @method void setName(string $name)
|
||||||
|
* @method void setFavicon(?string $favicon)
|
||||||
|
* @method void setUrlresolved(?string $urlresolved)
|
||||||
|
* @method void setBitrate(?string $bitrate)
|
||||||
|
* @method void setCountry(?string $country)
|
||||||
|
* @method void setLanguage(?string $language)
|
||||||
|
* @method void setHomepage(?string $homepage)
|
||||||
|
* @method void setCodec(?string $codec)
|
||||||
|
* @method void setTags(?string $tags)
|
||||||
|
* @method void setUserId(string $userId)
|
||||||
|
*
|
||||||
|
* @psalm-suppress PropertyNotSetInConstructor
|
||||||
|
*/
|
||||||
|
class Station extends Entity implements \JsonSerializable
|
||||||
|
{
|
||||||
|
protected string $stationuuid;
|
||||||
|
|
||||||
|
protected string $name;
|
||||||
|
|
||||||
|
protected ?string $favicon = null;
|
||||||
|
|
||||||
|
protected ?string $urlresolved = null;
|
||||||
|
|
||||||
|
protected ?string $bitrate = null;
|
||||||
|
|
||||||
|
protected ?string $country = null;
|
||||||
|
|
||||||
|
protected ?string $language = null;
|
||||||
|
|
||||||
|
protected ?string $homepage = null;
|
||||||
|
|
||||||
|
protected ?string $codec = null;
|
||||||
|
|
||||||
|
protected ?string $tags = null;
|
||||||
|
|
||||||
|
protected string $userId;
|
||||||
|
|
||||||
public function jsonSerialize(): array {
|
public function jsonSerialize(): array {
|
||||||
return [
|
return [
|
||||||
@ -52,7 +88,8 @@ class Station extends Entity implements JsonSerializable {
|
|||||||
'language' => $this->language,
|
'language' => $this->language,
|
||||||
'homepage' => $this->homepage,
|
'homepage' => $this->homepage,
|
||||||
'codec' => $this->codec,
|
'codec' => $this->codec,
|
||||||
'tags' => $this->tags
|
'tags' => $this->tags,
|
||||||
|
'userId' => $this->userId,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Radio App
|
|
||||||
*
|
|
||||||
* @author Jonas Heinrich
|
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 3 of the License, or any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public
|
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace OCA\Radio;
|
|
||||||
|
|
||||||
use OC;
|
|
||||||
use OC\HintException;
|
|
||||||
use OCP\AppFramework\Http\Response;
|
|
||||||
|
|
||||||
class ExportResponse extends Response {
|
|
||||||
private $returnstring;
|
|
||||||
|
|
||||||
public function __construct($returnstring) {
|
|
||||||
parent::__construct();
|
|
||||||
|
|
||||||
$user = OC::$server->getUserSession()->getUser();
|
|
||||||
if (is_null($user)) {
|
|
||||||
throw new HintException('User not logged in');
|
|
||||||
}
|
|
||||||
|
|
||||||
$userName = $user->getDisplayName();
|
|
||||||
$productName = OC::$server->getThemingDefaults()->getName();
|
|
||||||
$dateTime = OC::$server->getDateTimeFormatter();
|
|
||||||
|
|
||||||
$export_name = '"' . $productName . ' Radio Favorites (' . $userName . ') (' . $dateTime->formatDate(time()) . ').xspf"';
|
|
||||||
$this->addHeader("Cache-Control", "private");
|
|
||||||
$this->addHeader("Content-Type", " application/xspf+xml");
|
|
||||||
$this->addHeader("Content-Length", strlen($returnstring));
|
|
||||||
$this->addHeader("Content-Disposition", "attachment; filename=" . $export_name);
|
|
||||||
$this->returnstring = $returnstring;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render() {
|
|
||||||
return $this->returnstring;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,27 +18,24 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\Radio\Migration;
|
namespace OCA\Radio\Migration;
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use OCP\DB\ISchemaWrapper;
|
use OCP\DB\ISchemaWrapper;
|
||||||
use OCP\Migration\SimpleMigrationStep;
|
|
||||||
use OCP\Migration\IOutput;
|
use OCP\Migration\IOutput;
|
||||||
|
use OCP\Migration\SimpleMigrationStep;
|
||||||
|
|
||||||
class Version000000Date20181013124731 extends SimpleMigrationStep {
|
class Version000000Date20181013124731 extends SimpleMigrationStep
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* @param IOutput $output
|
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
*
|
||||||
* @param array $options
|
|
||||||
* @return null|ISchemaWrapper
|
* @return null|ISchemaWrapper
|
||||||
*/
|
*/
|
||||||
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
|
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||||
/** @var ISchemaWrapper $schema */
|
/** @var ISchemaWrapper $schema */
|
||||||
$schema = $schemaClosure();
|
$schema = $schemaClosure();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,7 +18,6 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@ -26,32 +25,22 @@ declare(strict_types=1);
|
|||||||
namespace OCA\Radio\Search;
|
namespace OCA\Radio\Search;
|
||||||
|
|
||||||
use OCA\Radio\AppInfo\Application;
|
use OCA\Radio\AppInfo\Application;
|
||||||
use OCP\IUser;
|
use OCP\Http\Client\IClientService;
|
||||||
use OCP\IURLGenerator;
|
use OCP\IURLGenerator;
|
||||||
|
use OCP\IUser;
|
||||||
use OCP\Search\IProvider;
|
use OCP\Search\IProvider;
|
||||||
use OCP\Search\ISearchQuery;
|
use OCP\Search\ISearchQuery;
|
||||||
use OCP\Search\SearchResult;
|
use OCP\Search\SearchResult;
|
||||||
use OCP\Search\SearchResultEntry;
|
use OCP\Search\SearchResultEntry;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
use OCP\Http\Client\IClientService;
|
class SearchProvider implements IProvider
|
||||||
|
{
|
||||||
use function urlencode;
|
|
||||||
|
|
||||||
class SearchProvider implements IProvider {
|
|
||||||
|
|
||||||
/** @var IClientService */
|
|
||||||
private $clientService;
|
|
||||||
|
|
||||||
/** @var IURLGenerator */
|
|
||||||
private $url;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IClientService $clientService,
|
private readonly IClientService $clientService,
|
||||||
IURLGenerator $url
|
private readonly IURLGenerator $url,
|
||||||
) {
|
private readonly LoggerInterface $logger,
|
||||||
$this->clientService = $clientService;
|
) {}
|
||||||
$this->url = $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getId(): string {
|
public function getId(): string {
|
||||||
return Application::APP_ID;
|
return Application::APP_ID;
|
||||||
@ -62,38 +51,43 @@ class SearchProvider implements IProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getOrder(string $route, array $routeParameters): int {
|
public function getOrder(string $route, array $routeParameters): int {
|
||||||
if (strpos($route, 'files' . '.') === 0) {
|
if (str_starts_with($route, 'files.')) {
|
||||||
return 25;
|
return 25;
|
||||||
} elseif (strpos($route, Application::APP_ID . '.') === 0) {
|
}
|
||||||
|
|
||||||
|
if (str_starts_with($route, Application::APP_ID.'.')) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function search(IUser $user, ISearchQuery $query): SearchResult {
|
public function search(IUser $user, ISearchQuery $query): SearchResult {
|
||||||
|
|
||||||
$term = $query->getTerm();
|
$term = $query->getTerm();
|
||||||
$url = "https://de1.api.radio-browser.info/json/stations/byname/" . $term . "?limit=20";
|
$url = 'https://de1.api.radio-browser.info/json/stations/byname/'.$term.'?limit=20';
|
||||||
|
|
||||||
$client = $this->clientService->newClient();
|
$client = $this->clientService->newClient();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $client->get($url);
|
$response = $client->get($url);
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->logger->error("Could not search for radio stations: " . $e->getMessage());
|
$this->logger->error('Could not search for radio stations: '.$exception->getMessage());
|
||||||
throw $e;
|
|
||||||
|
throw $exception;
|
||||||
}
|
}
|
||||||
$body = $response->getBody();
|
|
||||||
|
$body = (string) $response->getBody();
|
||||||
|
|
||||||
|
/** @var array<array<string, string>> $parsed */
|
||||||
$parsed = json_decode($body, true);
|
$parsed = json_decode($body, true);
|
||||||
|
|
||||||
$result = array_map(function (array $result) use ($term) {
|
$result = array_map(fn (array $result): SearchResultEntry => new SearchResultEntry(
|
||||||
return new SearchResultEntry(
|
|
||||||
$result['favicon'],
|
$result['favicon'],
|
||||||
$result['name'],
|
$result['name'],
|
||||||
str_replace(",",", ",$result['tags']),
|
str_replace(',', ', ', $result['tags']),
|
||||||
$this->url->linkToRouteAbsolute('radio.page.index') . '#/search/' . $term,
|
$this->url->linkToRouteAbsolute('radio.page.index').'#/search/'.$term,
|
||||||
'icon-radio-trans'
|
'icon-radio-trans'
|
||||||
);
|
), $parsed);
|
||||||
}, $parsed);
|
|
||||||
|
|
||||||
return SearchResult::complete(
|
return SearchResult::complete(
|
||||||
$this->getName(),
|
$this->getName(),
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,56 +20,55 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Service;
|
namespace OCA\Radio\Service;
|
||||||
|
|
||||||
use Exception;
|
use OCA\Radio\Db\FavoriteMapper;
|
||||||
|
use OCA\Radio\Db\Station;
|
||||||
use OCP\AppFramework\Db\DoesNotExistException;
|
use OCP\AppFramework\Db\DoesNotExistException;
|
||||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||||
|
|
||||||
use OCA\Radio\Db\Station;
|
class FavoriteService
|
||||||
use OCA\Radio\Db\FavoriteMapper;
|
{
|
||||||
|
public function __construct(
|
||||||
class FavoriteService {
|
private readonly FavoriteMapper $mapper
|
||||||
|
) {
|
||||||
/** @var FavoriteMapper */
|
|
||||||
private $mapper;
|
|
||||||
|
|
||||||
public function __construct(FavoriteMapper $mapper) {
|
|
||||||
$this->mapper = $mapper;
|
$this->mapper = $mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Station[]
|
||||||
|
*/
|
||||||
public function findAll(string $userId): array {
|
public function findAll(string $userId): array {
|
||||||
return $this->mapper->findAll($userId);
|
return $this->mapper->findAll($userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleException(Exception $e): void {
|
public function find(int $id, string $userId): ?Station {
|
||||||
if ($e instanceof DoesNotExistException ||
|
|
||||||
$e instanceof MultipleObjectsReturnedException) {
|
|
||||||
throw new StationNotFound($e->getMessage());
|
|
||||||
} else {
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id, $userId) {
|
|
||||||
try {
|
try {
|
||||||
return $this->mapper->find($id, $userId);
|
return $this->mapper->find($id, $userId);
|
||||||
|
|
||||||
// in order to be able to plug in different storage backends like files
|
// in order to be able to plug in different storage backends like files
|
||||||
// for instance it is a good idea to turn storage related exceptions
|
// for instance it is a good idea to turn storage related exceptions
|
||||||
// into service related exceptions so controllers and service users
|
// into service related exceptions so controllers and service users
|
||||||
// have to deal with only one type of exception
|
// have to deal with only one type of exception
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->handleException($e);
|
return $this->handleException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create($stationuuid, $name, $favicon, $urlresolved,
|
public function create(
|
||||||
$bitrate, $country, $language, $homepage, $codec, $tags, $userId) {
|
string $stationuuid,
|
||||||
|
string $name,
|
||||||
|
?string $favicon,
|
||||||
|
?string $urlresolved,
|
||||||
|
?string $bitrate,
|
||||||
|
?string $country,
|
||||||
|
?string $language,
|
||||||
|
?string $homepage,
|
||||||
|
?string $codec,
|
||||||
|
?string $tags,
|
||||||
|
string $userId
|
||||||
|
): Station {
|
||||||
$station = new Station();
|
$station = new Station();
|
||||||
$station->setStationuuid($stationuuid);
|
$station->setStationuuid($stationuuid);
|
||||||
$station->setName($name);
|
$station->setName($name);
|
||||||
@ -80,11 +81,24 @@ class FavoriteService {
|
|||||||
$station->setCodec($codec);
|
$station->setCodec($codec);
|
||||||
$station->setTags($tags);
|
$station->setTags($tags);
|
||||||
$station->setUserId($userId);
|
$station->setUserId($userId);
|
||||||
|
|
||||||
return $this->mapper->insert($station);
|
return $this->mapper->insert($station);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($id, $stationuuid, $name, $favicon, $urlresolved,
|
public function update(
|
||||||
$bitrate, $country, $language, $homepage, $codec, $tags, $userId) {
|
int $id,
|
||||||
|
string $stationuuid,
|
||||||
|
string $name,
|
||||||
|
?string $favicon,
|
||||||
|
?string $urlresolved,
|
||||||
|
?string $bitrate,
|
||||||
|
?string $country,
|
||||||
|
?string $language,
|
||||||
|
?string $homepage,
|
||||||
|
?string $codec,
|
||||||
|
?string $tags,
|
||||||
|
string $userId
|
||||||
|
): ?Station {
|
||||||
try {
|
try {
|
||||||
$station = $this->mapper->find($id, $userId);
|
$station = $this->mapper->find($id, $userId);
|
||||||
$station->setStationuuid($stationuuid);
|
$station->setStationuuid($stationuuid);
|
||||||
@ -97,19 +111,30 @@ class FavoriteService {
|
|||||||
$station->setHomepage($homepage);
|
$station->setHomepage($homepage);
|
||||||
$station->setCodec($codec);
|
$station->setCodec($codec);
|
||||||
$station->setTags($tags);
|
$station->setTags($tags);
|
||||||
|
|
||||||
return $this->mapper->update($station);
|
return $this->mapper->update($station);
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->handleException($e);
|
return $this->handleException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($id, $userId) {
|
public function delete(int $id, string $userId): ?Station {
|
||||||
try {
|
try {
|
||||||
$station = $this->mapper->find($id, $userId);
|
$station = $this->mapper->find($id, $userId);
|
||||||
$this->mapper->delete($station);
|
$this->mapper->delete($station);
|
||||||
|
|
||||||
return $station;
|
return $station;
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->handleException($e);
|
return $this->handleException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleException(\Throwable $e): void {
|
||||||
|
if ($e instanceof DoesNotExistException
|
||||||
|
|| $e instanceof MultipleObjectsReturnedException) {
|
||||||
|
throw new StationNotFound($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,119 +18,116 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\Radio\Service;
|
namespace OCA\Radio\Service;
|
||||||
|
|
||||||
use OCP\IURLGenerator;
|
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
use function urlencode;
|
class RadioBrowserApiService
|
||||||
|
{
|
||||||
class RadioBrowserApiService {
|
public string $baseUrl = 'https://api.fyyd.de/0.2';
|
||||||
|
|
||||||
/** @var IClientService */
|
|
||||||
private $clientService;
|
|
||||||
|
|
||||||
/** @var IURLGenerator */
|
|
||||||
private $url;
|
|
||||||
|
|
||||||
public $baseUrl = "https://api.fyyd.de/0.2";
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IClientService $clientService,
|
private readonly IClientService $clientService,
|
||||||
IURLGenerator $url
|
private readonly LoggerInterface $logger,
|
||||||
) {
|
) {}
|
||||||
$this->clientService = $clientService;
|
|
||||||
$this->url = $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function queryEpisodes(int $podcast_id, int $count = 20, int $page = 0) {
|
public function queryEpisodes(int $podcast_id, int $count = 20, int $page = 0): mixed {
|
||||||
|
$url = $this->baseUrl.'/podcast/episodes';
|
||||||
$url = $this->baseUrl . "/podcast/episodes";
|
$options = [];
|
||||||
|
|
||||||
$options['query'] = [
|
$options['query'] = [
|
||||||
'podcast_id' => $podcast_id,
|
'podcast_id' => $podcast_id,
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
'page' => $page
|
'page' => $page,
|
||||||
];
|
];
|
||||||
|
|
||||||
$client = $this->clientService->newClient();
|
$client = $this->clientService->newClient();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $client->get($url, $options);
|
$response = $client->get($url, $options);
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->logger->error("Could not search for podcasts: " . $e->getMessage());
|
$this->logger->error('Could not search for podcasts: '.$exception->getMessage());
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
$body = $response->getBody();
|
|
||||||
|
|
||||||
$parsed = json_decode($body, true);
|
throw $exception;
|
||||||
|
|
||||||
return $parsed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function queryEpisode(int $episode_id) {
|
$body = (string) $response->getBody();
|
||||||
|
|
||||||
$url = $this->baseUrl . "/episode";
|
return json_decode($body, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function queryEpisode(int $episode_id): mixed {
|
||||||
|
$url = $this->baseUrl.'/episode';
|
||||||
|
$options = [];
|
||||||
|
|
||||||
$options['query'] = [
|
$options['query'] = [
|
||||||
'episode_id' => $episode_id,
|
'episode_id' => $episode_id,
|
||||||
];
|
];
|
||||||
|
|
||||||
$client = $this->clientService->newClient();
|
$client = $this->clientService->newClient();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $client->get($url, $options);
|
$response = $client->get($url, $options);
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->logger->error("Could not search for podcasts: " . $e->getMessage());
|
$this->logger->error('Could not search for podcasts: '.$exception->getMessage());
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
$body = $response->getBody();
|
|
||||||
$parsed = json_decode($body, true);
|
|
||||||
|
|
||||||
return $parsed;
|
throw $exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function queryPodcast(int $podcast_id) {
|
$body = (string) $response->getBody();
|
||||||
|
|
||||||
$url = $this->baseUrl . "/podcast";
|
return json_decode($body, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function queryPodcast(int $podcast_id): mixed {
|
||||||
|
$url = $this->baseUrl.'/podcast';
|
||||||
|
$options = [];
|
||||||
|
|
||||||
$options['query'] = [
|
$options['query'] = [
|
||||||
'podcast_id' => $podcast_id,
|
'podcast_id' => $podcast_id,
|
||||||
];
|
];
|
||||||
|
|
||||||
$client = $this->clientService->newClient();
|
$client = $this->clientService->newClient();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $client->get($url, $options);
|
$response = $client->get($url, $options);
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->logger->error("Could not search for podcasts: " . $e->getMessage());
|
$this->logger->error('Could not search for podcasts: '.$exception->getMessage());
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
$body = $response->getBody();
|
|
||||||
$parsed = json_decode($body, true);
|
|
||||||
|
|
||||||
return $parsed;
|
throw $exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function queryCategory(string $category, int $count = 20,
|
$body = (string) $response->getBody();
|
||||||
int $page = 0) {
|
|
||||||
|
|
||||||
if ($category === 'hot') {
|
return json_decode($body, true);
|
||||||
$url = $this->baseUrl . "/feature/podcast/hot";
|
}
|
||||||
|
|
||||||
|
public function queryCategory(
|
||||||
|
string $category,
|
||||||
|
int $count = 20,
|
||||||
|
int $page = 0
|
||||||
|
): mixed {
|
||||||
|
$options = [];
|
||||||
|
|
||||||
|
if ('hot' === $category) {
|
||||||
|
$url = $this->baseUrl.'/feature/podcast/hot';
|
||||||
$options['query'] = [
|
$options['query'] = [
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
];
|
];
|
||||||
} else if ($category === 'latest') {
|
} elseif ('latest' === $category) {
|
||||||
$url = $this->baseUrl . "/podcast/latest";
|
$url = $this->baseUrl.'/podcast/latest';
|
||||||
$options['query'] = [
|
$options['query'] = [
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
$url = $this->baseUrl . "/category";
|
$url = $this->baseUrl.'/category';
|
||||||
$options['query'] = [
|
$options['query'] = [
|
||||||
'count' => $count,
|
'count' => $count,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
@ -139,15 +136,17 @@ class RadioBrowserApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$client = $this->clientService->newClient();
|
$client = $this->clientService->newClient();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $client->get($url, $options);
|
$response = $client->get($url, $options);
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->logger->error("Could not search for podcasts: " . $e->getMessage());
|
$this->logger->error('Could not search for podcasts: '.$exception->getMessage());
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
$body = $response->getBody();
|
|
||||||
$parsed = json_decode($body, true);
|
|
||||||
|
|
||||||
return $parsed;
|
throw $exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = (string) $response->getBody();
|
||||||
|
|
||||||
|
return json_decode($body, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,56 +20,55 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Service;
|
namespace OCA\Radio\Service;
|
||||||
|
|
||||||
use Exception;
|
use OCA\Radio\Db\RecentMapper;
|
||||||
|
use OCA\Radio\Db\Station;
|
||||||
use OCP\AppFramework\Db\DoesNotExistException;
|
use OCP\AppFramework\Db\DoesNotExistException;
|
||||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||||
|
|
||||||
use OCA\Radio\Db\Station;
|
class RecentService
|
||||||
use OCA\Radio\Db\RecentMapper;
|
{
|
||||||
|
public function __construct(
|
||||||
class RecentService {
|
private readonly RecentMapper $mapper
|
||||||
|
) {
|
||||||
/** @var RecentMapper */
|
|
||||||
private $mapper;
|
|
||||||
|
|
||||||
public function __construct(RecentMapper $mapper) {
|
|
||||||
$this->mapper = $mapper;
|
$this->mapper = $mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Station[]
|
||||||
|
*/
|
||||||
public function findAll(string $userId): array {
|
public function findAll(string $userId): array {
|
||||||
return $this->mapper->findAll($userId);
|
return $this->mapper->findAll($userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleException(Exception $e): void {
|
public function find(int $id, string $userId): ?Station {
|
||||||
if ($e instanceof DoesNotExistException ||
|
|
||||||
$e instanceof MultipleObjectsReturnedException) {
|
|
||||||
throw new StationNotFound($e->getMessage());
|
|
||||||
} else {
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id, $userId) {
|
|
||||||
try {
|
try {
|
||||||
return $this->mapper->find($id, $userId);
|
return $this->mapper->find($id, $userId);
|
||||||
|
|
||||||
// in order to be able to plug in different storage backends like files
|
// in order to be able to plug in different storage backends like files
|
||||||
// for instance it is a good idea to turn storage related exceptions
|
// for instance it is a good idea to turn storage related exceptions
|
||||||
// into service related exceptions so controllers and service users
|
// into service related exceptions so controllers and service users
|
||||||
// have to deal with only one type of exception
|
// have to deal with only one type of exception
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->handleException($e);
|
return $this->handleException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create($stationuuid, $name, $favicon, $urlresolved,
|
public function create(
|
||||||
$bitrate, $country, $language, $homepage, $codec, $tags, $userId) {
|
string $stationuuid,
|
||||||
|
string $name,
|
||||||
|
?string $favicon,
|
||||||
|
?string $urlresolved,
|
||||||
|
?string $bitrate,
|
||||||
|
?string $country,
|
||||||
|
?string $language,
|
||||||
|
?string $homepage,
|
||||||
|
?string $codec,
|
||||||
|
?string $tags,
|
||||||
|
string $userId
|
||||||
|
): Station {
|
||||||
$station = new Station();
|
$station = new Station();
|
||||||
$station->setStationuuid($stationuuid);
|
$station->setStationuuid($stationuuid);
|
||||||
$station->setName($name);
|
$station->setName($name);
|
||||||
@ -80,11 +81,24 @@ class RecentService {
|
|||||||
$station->setCodec($codec);
|
$station->setCodec($codec);
|
||||||
$station->setTags($tags);
|
$station->setTags($tags);
|
||||||
$station->setUserId($userId);
|
$station->setUserId($userId);
|
||||||
|
|
||||||
return $this->mapper->insert($station);
|
return $this->mapper->insert($station);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update($id, $stationuuid, $name, $favicon, $urlresolved,
|
public function update(
|
||||||
$bitrate, $country, $language, $homepage, $codec, $tags, $userId) {
|
int $id,
|
||||||
|
string $stationuuid,
|
||||||
|
string $name,
|
||||||
|
?string $favicon,
|
||||||
|
?string $urlresolved,
|
||||||
|
?string $bitrate,
|
||||||
|
?string $country,
|
||||||
|
?string $language,
|
||||||
|
?string $homepage,
|
||||||
|
?string $codec,
|
||||||
|
?string $tags,
|
||||||
|
string $userId
|
||||||
|
): ?Station {
|
||||||
try {
|
try {
|
||||||
$station = $this->mapper->find($id, $userId);
|
$station = $this->mapper->find($id, $userId);
|
||||||
$station->setStationuuid($stationuuid);
|
$station->setStationuuid($stationuuid);
|
||||||
@ -97,19 +111,33 @@ class RecentService {
|
|||||||
$station->setHomepage($homepage);
|
$station->setHomepage($homepage);
|
||||||
$station->setCodec($codec);
|
$station->setCodec($codec);
|
||||||
$station->setTags($tags);
|
$station->setTags($tags);
|
||||||
|
|
||||||
return $this->mapper->update($station);
|
return $this->mapper->update($station);
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->handleException($e);
|
return $this->handleException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($id, $userId) {
|
public function delete(int $id, string $userId): ?Station {
|
||||||
try {
|
try {
|
||||||
$station = $this->mapper->find($id, $userId);
|
$station = $this->mapper->find($id, $userId);
|
||||||
$this->mapper->delete($station);
|
$this->mapper->delete($station);
|
||||||
|
|
||||||
return $station;
|
return $station;
|
||||||
} catch (Exception $e) {
|
} catch (\Exception $exception) {
|
||||||
$this->handleException($e);
|
return $this->handleException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
private function handleException(\Throwable $e): void {
|
||||||
|
if ($e instanceof DoesNotExistException
|
||||||
|
|| $e instanceof MultipleObjectsReturnedException) {
|
||||||
|
throw new StationNotFound($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,10 +20,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace OCA\Radio\Service;
|
namespace OCA\Radio\Service;
|
||||||
|
|
||||||
class StationNotFound extends \Exception {
|
class StationNotFound extends \Exception {}
|
||||||
}
|
|
||||||
|
25
lib/Service/UserService.php
Normal file
25
lib/Service/UserService.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace OCA\Radio\Service;
|
||||||
|
|
||||||
|
use OCP\IUser;
|
||||||
|
use OCP\IUserSession;
|
||||||
|
|
||||||
|
class UserService
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly IUserSession $userSession
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function getUserUID(): string {
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
return $user instanceof IUser ? $user->getUID() : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser(): ?IUser {
|
||||||
|
return $this->userSession->getUser();
|
||||||
|
}
|
||||||
|
}
|
21
psalm.xml
Normal file
21
psalm.xml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<psalm
|
||||||
|
errorLevel="1"
|
||||||
|
resolveFromConfigFile="true"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="https://getpsalm.org/schema/config"
|
||||||
|
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||||
|
findUnusedBaselineEntry="true"
|
||||||
|
findUnusedCode="false"
|
||||||
|
phpVersion="8.1"
|
||||||
|
>
|
||||||
|
<projectFiles>
|
||||||
|
<directory name="lib" />
|
||||||
|
<ignoreFiles>
|
||||||
|
<directory name="vendor" />
|
||||||
|
</ignoreFiles>
|
||||||
|
</projectFiles>
|
||||||
|
<extraFiles>
|
||||||
|
<directory name="vendor"/>
|
||||||
|
</extraFiles>
|
||||||
|
</psalm>
|
34
rector.php
Normal file
34
rector.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Nextcloud\Rector\Set\NextcloudSets;
|
||||||
|
use Rector\Config\RectorConfig;
|
||||||
|
|
||||||
|
return RectorConfig::configure()
|
||||||
|
->withPaths([
|
||||||
|
__DIR__.'/appinfo',
|
||||||
|
__DIR__.'/lib',
|
||||||
|
])
|
||||||
|
->withPhpSets(php81: true)
|
||||||
|
->withSets([
|
||||||
|
NextcloudSets::NEXTCLOUD_27,
|
||||||
|
])
|
||||||
|
->withPreparedSets(
|
||||||
|
deadCode: true,
|
||||||
|
codeQuality: true,
|
||||||
|
codingStyle: true,
|
||||||
|
typeDeclarations: true,
|
||||||
|
privatization: true,
|
||||||
|
instanceOf: true,
|
||||||
|
earlyReturn: true,
|
||||||
|
strictBooleans: true,
|
||||||
|
rectorPreset: true,
|
||||||
|
phpunitCodeQuality: true,
|
||||||
|
doctrineCodeQuality: true,
|
||||||
|
symfonyCodeQuality: true,
|
||||||
|
symfonyConfigs: true,
|
||||||
|
twig: true,
|
||||||
|
phpunit: true,
|
||||||
|
)
|
||||||
|
;
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radio App
|
* Radio App.
|
||||||
*
|
*
|
||||||
* @author Jonas Heinrich
|
* @author Jonas Heinrich
|
||||||
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
* @copyright 2021 Jonas Heinrich <onny@project-insanity.org>
|
||||||
@ -18,7 +18,5 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public
|
* You should have received a copy of the GNU Affero General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
echo "<div id='vue-content'></div>";
|
echo "<div id='vue-content'></div>";
|
||||||
|
Loading…
Reference in New Issue
Block a user