diff --git a/FAQ.md b/FAQ.md
index 30d1c13d..b597e78c 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -341,10 +341,10 @@ $ docker exec -ti watchstate console system:tasks
### How to add webhooks?
-The Webhook URL is backend specific, the request path is `/v1/api/backends/[BACKEND_NAME]/webhook?apikey=[APIKEY]`,
+The Webhook URL is backend specific, the request path is `/v1/api/backend/[BACKEND_NAME]/webhook?apikey=[APIKEY]`,
Where `[BACKEND_NAME]` is the name of the backend you want to add webhook for, and `[APIKEY]` is the global api key
which you can get via the `system:apikey` command. Typically, the full path
-is `http://localhost:8080/v1/api/backends/[BACKEND_NAME]/webhook?apikey=[APIKEY]`. if the tool
+is `http://localhost:8080/v1/api/backend/[BACKEND_NAME]/webhook?apikey=[APIKEY]`. if the tool
port is directly exposed or via the reverse proxy you have setup.
If your media backend support sending headers then remove query parameter `?apikey=[APIKEY]`, and add this header
@@ -371,7 +371,7 @@ Go to your Manage Emby Server > Server > Webhooks > (Click Add Webhook)
##### Webhook/Notifications URL:
-`http://localhost:8080/v1/api/backends/[BACKEND_NAME]/webhook?apikey=[APIKEY]`
+`http://localhost:8080/v1/api/backend/[BACKEND_NAME]/webhook?apikey=[APIKEY]`
* Replace `[BACKEND_NAME]` with the name you have chosen for your backend.
* Replace `[APIKEY]` with the global apikey.
@@ -412,7 +412,7 @@ Go to your Plex Web UI > Settings > Your Account > Webhooks > (Click ADD WEBHOOK
##### URL:
-`http://localhost:8080/v1/api/backends/[BACKEND_NAME]/webhook?apikey=[APIKEY]`
+`http://localhost:8080/v1/api/backend/[BACKEND_NAME]/webhook?apikey=[APIKEY]`
* Replace `[BACKEND_NAME]` with the name you have chosen for your backend.
* Replace `[APIKEY]` with the global apikey.
@@ -441,7 +441,7 @@ go back again to dashboard > plugins > webhook. Add `Add Generic Destination`,
##### Webhook Url:
-`http://localhost:8080/v1/api/backends/[BACKEND_NAME]/webhook`
+`http://localhost:8080/v1/api/backend/[BACKEND_NAME]/webhook`
* Replace `[BACKEND_NAME]` with the name you have chosen for your backend.
diff --git a/README.md b/README.md
index 7c23be43..636320ed 100644
--- a/README.md
+++ b/README.md
@@ -11,9 +11,12 @@ out of the box, this tool support `Jellyfin`, `Plex` and `Emby` media servers.
### 2024-04-30 - [BREAKING CHANGE]
-We are going to retire the old webhooks endpoint, please refer to the [FAQ](FAQ.md#how-to-add-webhooks) to know how to update
-to the new API endpoint. We are going to include `WebUI` for alpha testing after two weeks from today `2024-05-15`. Which most likely means the old webhooks
-endpoint will be removed. We will try to preseve the old endpoint for a while, but it's not guaranteed we will be able to.
+We are going to retire the old webhooks endpoint, please refer to the [FAQ](FAQ.md#how-to-add-webhooks) to know how to
+update
+to the new API endpoint. We are going to include `WebUI` for alpha testing after two weeks from today `2024-05-15`.
+Which most likely means the old webhooks
+endpoint will be removed. We will try to preserve the old endpoint for a while, but it's not guaranteed we will be able
+to.
Refer to [NEWS](NEWS.md) for old updates.
diff --git a/frontend/pages/backends/[backend]/edit.vue b/frontend/pages/backends/[backend]/edit.vue
new file mode 100644
index 00000000..65a25503
--- /dev/null
+++ b/frontend/pages/backends/[backend]/edit.vue
@@ -0,0 +1,130 @@
+
+
+
+
+ Backends
+ : Edit -
+ {{ id }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/API/Backends/Ignore.php b/src/API/Backend/Ignore.php
similarity index 99%
rename from src/API/Backends/Ignore.php
rename to src/API/Backend/Ignore.php
index 7e818840..d427b823 100644
--- a/src/API/Backends/Ignore.php
+++ b/src/API/Backend/Ignore.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\API\Backends;
+namespace App\API\Backend;
use App\Libs\Attributes\Route\Delete;
use App\Libs\Attributes\Route\Get;
diff --git a/src/API/Backend/Index.php b/src/API/Backend/Index.php
new file mode 100644
index 00000000..baa5d34e
--- /dev/null
+++ b/src/API/Backend/Index.php
@@ -0,0 +1,45 @@
+getBackends(name: $name);
+
+ if (empty($data)) {
+ return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
+ }
+
+ $apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
+ $data = array_pop($data);
+
+ $response = [
+ ...$data,
+ 'links' => [
+ 'self' => (string)$apiUrl,
+ 'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
+ ],
+ ];
+
+ return api_response(HTTP_STATUS::HTTP_OK, ['backend' => $response]);
+ }
+}
diff --git a/src/API/Backends/Info.php b/src/API/Backend/Info.php
similarity index 98%
rename from src/API/Backends/Info.php
rename to src/API/Backend/Info.php
index f8faaa76..53dda85d 100644
--- a/src/API/Backends/Info.php
+++ b/src/API/Backend/Info.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\API\Backends;
+namespace App\API\Backend;
use App\Libs\Attributes\Route\Get;
use App\Libs\DataUtil;
diff --git a/src/API/Backends/Library/Ignore.php b/src/API/Backend/Library/Ignore.php
similarity index 97%
rename from src/API/Backends/Library/Ignore.php
rename to src/API/Backend/Library/Ignore.php
index 699b0ef4..5a183065 100644
--- a/src/API/Backends/Library/Ignore.php
+++ b/src/API/Backend/Library/Ignore.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace App\API\Backends\Library;
+namespace App\API\Backend\Library;
-use App\API\Backends\Index as BackendsIndex;
+use App\API\Backend\Index as BackendsIndex;
use App\Libs\Attributes\Route\Route;
use App\Libs\Config;
use App\Libs\ConfigFile;
diff --git a/src/API/Backends/Library/Index.php b/src/API/Backend/Library/Index.php
similarity index 94%
rename from src/API/Backends/Library/Index.php
rename to src/API/Backend/Library/Index.php
index 62a4eb22..ab103335 100644
--- a/src/API/Backends/Library/Index.php
+++ b/src/API/Backend/Library/Index.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace App\API\Backends\Library;
+namespace App\API\Backend\Library;
-use App\API\Backends\Index as BackendsIndex;
+use App\API\Backend\Index as BackendsIndex;
use App\Libs\Attributes\Route\Get;
use App\Libs\Config;
use App\Libs\Exceptions\RuntimeException;
diff --git a/src/API/Backends/Library/Mismatched.php b/src/API/Backend/Library/Mismatched.php
similarity index 97%
rename from src/API/Backends/Library/Mismatched.php
rename to src/API/Backend/Library/Mismatched.php
index 3f102821..ba1cb6fc 100644
--- a/src/API/Backends/Library/Mismatched.php
+++ b/src/API/Backend/Library/Mismatched.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace App\API\Backends\Library;
+namespace App\API\Backend\Library;
-use App\API\Backends\Index as BackendsIndex;
+use App\API\Backend\Index as BackendsIndex;
use App\Commands\Backend\Library\MismatchCommand;
use App\Libs\Attributes\Route\Get;
use App\Libs\DataUtil;
diff --git a/src/API/Backends/Library/Unmatched.php b/src/API/Backend/Library/Unmatched.php
similarity index 96%
rename from src/API/Backends/Library/Unmatched.php
rename to src/API/Backend/Library/Unmatched.php
index a3ba8036..ba16045d 100644
--- a/src/API/Backends/Library/Unmatched.php
+++ b/src/API/Backend/Library/Unmatched.php
@@ -2,9 +2,9 @@
declare(strict_types=1);
-namespace App\API\Backends\Library;
+namespace App\API\Backend\Library;
-use App\API\Backends\Index as BackendsIndex;
+use App\API\Backend\Index as BackendsIndex;
use App\Libs\Attributes\Route\Get;
use App\Libs\DataUtil;
use App\Libs\Exceptions\RuntimeException;
diff --git a/src/API/Backend/PartialUpdate.php b/src/API/Backend/PartialUpdate.php
new file mode 100644
index 00000000..c24a47f8
--- /dev/null
+++ b/src/API/Backend/PartialUpdate.php
@@ -0,0 +1,71 @@
+has($name)) {
+ return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
+ }
+
+ try {
+ $data = json_decode((string)$request->getBody(), true, flags: JSON_THROW_ON_ERROR);
+ } catch (JsonException $e) {
+ return api_error(r('Invalid JSON data. {error}', ['error' => $e->getMessage()]),
+ HTTP_STATUS::HTTP_BAD_REQUEST);
+ }
+
+ foreach ($data as $update) {
+ if (!ag_exists($update, 'key')) {
+ return api_error('No key to update was present.', HTTP_STATUS::HTTP_BAD_REQUEST);
+ }
+
+ $list->set($name . '.' . ag($update, 'key'), ag($update, 'value'));
+ }
+
+ $apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
+
+ $list->persist();
+
+ $backend = $this->getBackends(name: $name);
+
+ if (empty($backend)) {
+ return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
+ }
+ $backend = array_pop($backend);
+
+ return api_response(HTTP_STATUS::HTTP_OK, [
+ 'backend' => array_filter(
+ $backend,
+ fn($key) => false === in_array($key, ['options', 'webhook'], true),
+ ARRAY_FILTER_USE_KEY
+ ),
+ 'links' => [
+ 'self' => (string)$apiUrl,
+ 'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
+ ],
+ ]);
+ }
+}
diff --git a/src/API/Backends/Search.php b/src/API/Backend/Search.php
similarity index 98%
rename from src/API/Backends/Search.php
rename to src/API/Backend/Search.php
index 30d0ae66..1f8d0d7a 100644
--- a/src/API/Backends/Search.php
+++ b/src/API/Backend/Search.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\API\Backends;
+namespace App\API\Backend;
use App\Libs\Attributes\Route\Get;
use App\Libs\DataUtil;
diff --git a/src/API/Backends/Sessions.php b/src/API/Backend/Sessions.php
similarity index 98%
rename from src/API/Backends/Sessions.php
rename to src/API/Backend/Sessions.php
index 1dd8417e..eb95e486 100644
--- a/src/API/Backends/Sessions.php
+++ b/src/API/Backend/Sessions.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\API\Backends;
+namespace App\API\Backend;
use App\Libs\Attributes\Route\Get;
use App\Libs\DataUtil;
diff --git a/src/API/Backends/Users.php b/src/API/Backend/Users.php
similarity index 98%
rename from src/API/Backends/Users.php
rename to src/API/Backend/Users.php
index 92efab7f..11590fc4 100644
--- a/src/API/Backends/Users.php
+++ b/src/API/Backend/Users.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\API\Backends;
+namespace App\API\Backend;
use App\Libs\Attributes\Route\Get;
use App\Libs\DataUtil;
diff --git a/src/API/Backends/Version.php b/src/API/Backend/Version.php
similarity index 98%
rename from src/API/Backends/Version.php
rename to src/API/Backend/Version.php
index 1581c0e5..21dbf8ea 100644
--- a/src/API/Backends/Version.php
+++ b/src/API/Backend/Version.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\API\Backends;
+namespace App\API\Backend;
use App\Libs\Attributes\Route\Get;
use App\Libs\DataUtil;
diff --git a/src/API/Backends/Webhooks.php b/src/API/Backend/Webhooks.php
similarity index 96%
rename from src/API/Backends/Webhooks.php
rename to src/API/Backend/Webhooks.php
index eece6825..46bc788a 100644
--- a/src/API/Backends/Webhooks.php
+++ b/src/API/Backend/Webhooks.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace App\API\Backends;
+namespace App\API\Backend;
use App\Libs\Attributes\Route\Route;
use App\Libs\Config;
@@ -27,20 +27,20 @@ final class Webhooks
{
use APITraits;
- private iLogger $accesslog;
+ private iLogger $accessLog;
public function __construct(private iCache $cache)
{
- $this->accesslog = new Logger(name: 'http', processors: [new LogMessageProcessor()]);
+ $this->accessLog = new Logger(name: 'http', processors: [new LogMessageProcessor()]);
$level = Config::get('webhook.debug') ? Level::Debug : Level::Info;
if (null !== ($logfile = Config::get('webhook.logfile'))) {
- $this->accesslog = $this->accesslog->pushHandler(new StreamHandler($logfile, $level, true));
+ $this->accessLog = $this->accessLog->pushHandler(new StreamHandler($logfile, $level, true));
}
if (true === inContainer()) {
- $this->accesslog->pushHandler(new StreamHandler('php://stderr', $level, true));
+ $this->accessLog->pushHandler(new StreamHandler('php://stderr', $level, true));
}
}
@@ -257,9 +257,9 @@ final class Webhooks
}
if (true === (Config::get('logs.context') || $forceContext)) {
- $this->accesslog->log($level, $message, $context);
+ $this->accessLog->log($level, $message, $context);
} else {
- $this->accesslog->log($level, r($message, $context));
+ $this->accessLog->log($level, r($message, $context));
}
}
}
diff --git a/src/API/Backends/Index.php b/src/API/Backends/Index.php
index d7e46dc0..7e486ff2 100644
--- a/src/API/Backends/Index.php
+++ b/src/API/Backends/Index.php
@@ -5,13 +5,9 @@ declare(strict_types=1);
namespace App\API\Backends;
use App\Libs\Attributes\Route\Get;
-use App\Libs\Attributes\Route\Patch;
-use App\Libs\Config;
-use App\Libs\ConfigFile;
use App\Libs\HTTP_STATUS;
use App\Libs\Options;
use App\Libs\Traits\APITraits;
-use JsonException;
use Psr\Http\Message\ResponseInterface as iResponse;
use Psr\Http\Message\ServerRequestInterface as iRequest;
@@ -28,7 +24,7 @@ final class Index
];
#[Get(self::URL . '[/]', name: 'backends.index')]
- public function backendsIndex(iRequest $request): iResponse
+ public function __invoke(iRequest $request): iResponse
{
$apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
$urlPath = $request->getUri()->getPath();
@@ -48,7 +44,9 @@ final class Index
);
$backend['links'] = [
- 'self' => (string)$apiUrl->withPath($urlPath . '/' . $backend['name']),
+ 'self' => (string)$apiUrl->withPath(
+ parseConfigValue(\App\API\Backend\Index::URL) . '/' . $backend['name']
+ ),
];
$response['backends'][] = $backend;
@@ -57,82 +55,4 @@ final class Index
return api_response(HTTP_STATUS::HTTP_OK, $response);
}
- #[Get(Index::URL . '/{name:backend}[/]', name: 'backends.view')]
- public function backendsView(iRequest $request, array $args = []): iResponse
- {
- if (null === ($name = ag($args, 'name'))) {
- return api_error('Invalid value for id path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
- }
-
- $data = $this->getBackends(name: $name);
-
- if (empty($data)) {
- return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
- }
-
- $apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
- $data = array_pop($data);
-
- $response = [
- ...$data,
- 'links' => [
- 'self' => (string)$apiUrl,
- 'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
- ],
- ];
-
- return api_response(HTTP_STATUS::HTTP_OK, ['backend' => $response]);
- }
-
- #[Patch(Index::URL . '/{name:backend}[/]', name: 'backends.view')]
- public function backendsUpdatePartial(iRequest $request, array $args = []): iResponse
- {
- if (null === ($name = ag($args, 'name'))) {
- return api_error('Invalid value for name path parameter.', HTTP_STATUS::HTTP_BAD_REQUEST);
- }
-
- $list = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
-
- if (false === $list->has($name)) {
- return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
- }
-
- try {
- $data = json_decode((string)$request->getBody(), true, flags: JSON_THROW_ON_ERROR);
- } catch (JsonException $e) {
- return api_error(r('Invalid JSON data. {error}', ['error' => $e->getMessage()]),
- HTTP_STATUS::HTTP_BAD_REQUEST);
- }
-
- foreach ($data as $update) {
- if (!ag_exists($update, 'key')) {
- return api_error('No key to update was present.', HTTP_STATUS::HTTP_BAD_REQUEST);
- }
-
- $list->set($name . '.' . ag($update, 'key'), ag($update, 'value'));
- }
-
- $apiUrl = $request->getUri()->withHost('')->withPort(0)->withScheme('');
-
- $list->persist();
-
- $backend = $this->getBackends(name: $name);
-
- if (empty($backend)) {
- return api_error(r("Backend '{name}' not found.", ['name' => $name]), HTTP_STATUS::HTTP_NOT_FOUND);
- }
- $backend = array_pop($backend);
-
- return api_response(HTTP_STATUS::HTTP_OK, [
- 'backend' => array_filter(
- $backend,
- fn($key) => false === in_array($key, ['options', 'webhook'], true),
- ARRAY_FILTER_USE_KEY
- ),
- 'links' => [
- 'self' => (string)$apiUrl,
- 'list' => (string)$apiUrl->withPath(parseConfigValue(Index::URL)),
- ],
- ]);
- }
}
diff --git a/src/API/System/Supported.php b/src/API/System/Supported.php
new file mode 100644
index 00000000..54138adc
--- /dev/null
+++ b/src/API/System/Supported.php
@@ -0,0 +1,24 @@
+ array_keys(Config::get('supported')),
+ ]);
+ }
+}
diff --git a/src/Libs/Initializer.php b/src/Libs/Initializer.php
index 2366b126..d0835f6e 100644
--- a/src/Libs/Initializer.php
+++ b/src/Libs/Initializer.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Libs;
-use App\API\Backends\Webhooks;
+use App\API\Backend\Webhooks;
use App\Cli;
use App\Libs\Exceptions\Backends\RuntimeException;
use App\Libs\Exceptions\HttpException;