Added support for using emby and jellyfin oauth tokens via config:add/manage.
This commit is contained in:
@@ -60,10 +60,13 @@ class JellyfinManage implements ManageInterface
|
||||
$chosen = ag($backend, 'token');
|
||||
|
||||
$question = new Question(
|
||||
r('<question>Enter [<value>{name}</value>] API token</question>. {default}' . PHP_EOL . '> ', [
|
||||
'name' => ag($backend, 'name'),
|
||||
'default' => null !== $chosen ? "<value>[Default: {$chosen}]</value>" : '',
|
||||
]),
|
||||
r(
|
||||
'<question>Enter [<value>{name}</value>] API key or "username:password" for oauth token generation</question>. {default}' . PHP_EOL . '> ',
|
||||
[
|
||||
'name' => ag($backend, 'name'),
|
||||
'default' => null !== $chosen ? "<value>[Default: {$chosen}]</value>" : '',
|
||||
]
|
||||
),
|
||||
$chosen
|
||||
);
|
||||
|
||||
@@ -86,7 +89,47 @@ class JellyfinManage implements ManageInterface
|
||||
});
|
||||
|
||||
$token = $this->questionHelper->ask($this->input, $this->output, $question);
|
||||
$backend = ag_set($backend, 'token', $token);
|
||||
|
||||
if (true === str_contains($token, ':')) {
|
||||
[$username, $password] = explode(':', $token, 2);
|
||||
if (empty($username) || empty($password)) {
|
||||
$this->output->writeln('<error>Invalid username or password was given.</error>');
|
||||
goto re_goto_token;
|
||||
}
|
||||
|
||||
// we are probably dealing with a username:password, try to generate oAuth token.
|
||||
$this->output->writeln(
|
||||
'<info>Attempting to generate oAuth token from username and password. Please wait...</info>'
|
||||
);
|
||||
|
||||
$backend = ag_set($backend, 'token', 'oauth_token');
|
||||
|
||||
try {
|
||||
$accessToken = makeBackend($backend)->generateAccessToken($username, $password);
|
||||
} catch (Throwable $e) {
|
||||
$this->output->writeln('<error>Failed to generate oAuth token from username and password.</error>');
|
||||
$this->output->writeln(
|
||||
sprintf(
|
||||
'<error>ERROR - %s: %s.</error>' . PHP_EOL,
|
||||
afterLast(get_class($e), '\\'),
|
||||
$e->getMessage()
|
||||
)
|
||||
);
|
||||
$backend = ag_set($backend, 'token', null);
|
||||
goto re_goto_token;
|
||||
}
|
||||
|
||||
$backend = ag_set($backend, 'token', ag($accessToken, 'accesstoken'));
|
||||
$backend = ag_set($backend, 'user', ag($accessToken, 'user'));
|
||||
$backend = ag_set($backend, 'uuid', ag($accessToken, 'identifier'));
|
||||
$backend = ag_set($backend, 'options.' . Options::IS_LIMITED_TOKEN, true);
|
||||
} else {
|
||||
$backend = ag_set($backend, 'token', $token);
|
||||
}
|
||||
|
||||
if (true === (bool)ag($backend, 'options.' . Options::IS_LIMITED_TOKEN, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->output->writeln('');
|
||||
|
||||
@@ -124,6 +167,8 @@ class JellyfinManage implements ManageInterface
|
||||
]
|
||||
)
|
||||
);
|
||||
$backend = ag_set($backend, 'uuid', $chosen);
|
||||
return;
|
||||
} catch (Throwable $e) {
|
||||
$this->output->writeln('<error>Failed to get the backend unique identifier.</error>');
|
||||
$this->output->writeln(r('<error>ERROR - {kind}: {message}.</error>' . PHP_EOL, [
|
||||
@@ -135,66 +180,6 @@ class JellyfinManage implements ManageInterface
|
||||
|
||||
goto re_goto_token;
|
||||
}
|
||||
|
||||
$question = new Question(
|
||||
r(
|
||||
<<<HELP
|
||||
<question>Enter [<value>{name}</value>] Unique identifier</question>. {default}
|
||||
------------------
|
||||
The Server Unique identifier is randomly generated string on server setup.
|
||||
------------------
|
||||
<notice>If you select invalid or give incorrect server unique identifier, Some checks will
|
||||
fail And you may not be able to sync your backend.</notice>
|
||||
------------------
|
||||
<error>DO NOT CHANGE the default value unless you know what you are doing, or was told by devs.</error>
|
||||
HELP. PHP_EOL . '> ',
|
||||
[
|
||||
'name' => ag($backend, 'name'),
|
||||
'default' => "<value>[Default: {$chosen}]</value>",
|
||||
]
|
||||
),
|
||||
$chosen
|
||||
);
|
||||
|
||||
$question->setValidator(function ($answer) use ($custom) {
|
||||
if (empty($answer)) {
|
||||
throw new RuntimeException('Backend unique identifier cannot be empty.');
|
||||
}
|
||||
|
||||
if (!is_string($answer) && !is_int($answer)) {
|
||||
throw new RuntimeException(
|
||||
r(
|
||||
"Backend unique identifier is invalid. Expecting string or integer, but got '{type}' instead.",
|
||||
[
|
||||
'type' => get_debug_type($answer)
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$backendUUid = makeBackend($custom, ag($custom, 'name'))->getIdentifier(true);
|
||||
|
||||
if ('auto' === $answer && !empty($backendUUid)) {
|
||||
return $backendUUid;
|
||||
}
|
||||
|
||||
if ($answer !== $backendUUid) {
|
||||
throw new RuntimeException(
|
||||
r(
|
||||
'Invalid backend unique identifier was given. Expecting "{uuid}", but got "{answer}" instead.',
|
||||
[
|
||||
'uuid' => $backendUUid,
|
||||
'answer' => $answer
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $answer;
|
||||
});
|
||||
|
||||
$uuid = $this->questionHelper->ask($this->input, $this->output, $question);
|
||||
$backend = ag_set($backend, 'uuid', $uuid);
|
||||
})();
|
||||
|
||||
$this->output->writeln('');
|
||||
|
||||
@@ -23,7 +23,7 @@ use Symfony\Component\Console\Question\Question;
|
||||
#[Cli(command: self::ROUTE)]
|
||||
final class AddCommand extends Command
|
||||
{
|
||||
public const ROUTE = 'config:add';
|
||||
public const string ROUTE = 'config:add';
|
||||
|
||||
/**
|
||||
* Configures the command.
|
||||
|
||||
@@ -5,11 +5,11 @@ declare(strict_types=1);
|
||||
namespace App\Commands\Config;
|
||||
|
||||
use App\Command;
|
||||
use App\Commands\State\ImportCommand;
|
||||
use App\Commands\System\IndexCommand;
|
||||
use App\Libs\Attributes\Route\Cli;
|
||||
use App\Libs\Config;
|
||||
use App\Libs\ConfigFile;
|
||||
use App\Libs\Exceptions\Backends\InvalidContextException;
|
||||
use App\Libs\Options;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Exception\ExceptionInterface;
|
||||
@@ -30,7 +30,7 @@ use Throwable;
|
||||
#[Cli(command: self::ROUTE)]
|
||||
final class ManageCommand extends Command
|
||||
{
|
||||
public const ROUTE = 'config:manage';
|
||||
public const string ROUTE = 'config:manage';
|
||||
|
||||
public function __construct(private LoggerInterface $logger)
|
||||
{
|
||||
@@ -117,6 +117,8 @@ final class ManageCommand extends Command
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
go_start:
|
||||
|
||||
if (true === $add) {
|
||||
if (null !== $configFile->get("{$name}.type", null)) {
|
||||
$output->writeln(
|
||||
@@ -384,7 +386,24 @@ final class ManageCommand extends Command
|
||||
);
|
||||
|
||||
if (false === $helper->ask($input, $output, $question)) {
|
||||
return $this->runCommand($input, $output, $u);
|
||||
goto go_start;
|
||||
}
|
||||
|
||||
try {
|
||||
$output->writeln('<info>Validating backend context. Please wait...</info>');
|
||||
$client = makeBackend($u, $name);
|
||||
$client->setLogger($this->logger);
|
||||
if (false === $client->validateContext($client->getContext())) {
|
||||
$output->writeln('<error>ERROR:</error> Backend context is invalid.');
|
||||
goto go_start;
|
||||
}
|
||||
} catch (InvalidContextException $e) {
|
||||
$output->writeln(
|
||||
r('<error>ERROR:</error> Backend context validation has failed. {error}', [
|
||||
'error' => $e->getMessage()
|
||||
])
|
||||
);
|
||||
goto go_start;
|
||||
}
|
||||
|
||||
$configFile->set($name, $u)->persist();
|
||||
@@ -411,41 +430,6 @@ final class ManageCommand extends Command
|
||||
if (true === $helper->ask($input, $output, $question)) {
|
||||
$this->getApplication()?->find(IndexCommand::ROUTE)->run(new ArrayInput([]), $output);
|
||||
}
|
||||
|
||||
$importEnabled = (bool)ag($u, 'import.enabled');
|
||||
$metaEnabled = (bool)ag($u, 'options.' . Options::IMPORT_METADATA_ONLY);
|
||||
|
||||
if (true === $importEnabled || true === $metaEnabled) {
|
||||
$importType = $importEnabled ? 'play state & metadata' : 'metadata only.';
|
||||
|
||||
$helper = $this->getHelper('question');
|
||||
$text =
|
||||
<<<TEXT
|
||||
|
||||
<question>Would you like to import <flag>{type}</flag> from the backend now</question>? [<value>Y|N</value>] [<value>Default: No</value>]
|
||||
-----------------
|
||||
<value>P.S: this could take few minutes to execute.</value>
|
||||
|
||||
TEXT;
|
||||
|
||||
$text = r($text, ['type' => $importType]);
|
||||
|
||||
$question = new ConfirmationQuestion($text . PHP_EOL . '> ', false);
|
||||
|
||||
if (true === $helper->ask($input, $output, $question)) {
|
||||
$output->writeln(
|
||||
r('<info>Importing {type} from {name}</info>', [
|
||||
'name' => $name,
|
||||
'type' => $importType
|
||||
])
|
||||
);
|
||||
|
||||
$cmd = $this->getApplication()?->find(ImportCommand::ROUTE);
|
||||
$cmd->run(new ArrayInput(['--quiet', '--select-backend' => [$name]]), $output);
|
||||
}
|
||||
|
||||
$output->writeln('<info>Import complete</info>');
|
||||
}
|
||||
}
|
||||
|
||||
return self::SUCCESS;
|
||||
|
||||
@@ -144,7 +144,7 @@ final class TestCommand extends Command
|
||||
foreach ($backends as $backendName => $backend) {
|
||||
$backend = $this->getBackend($backendName);
|
||||
$context = $backend->getContext();
|
||||
$output->writeln(r("Running '{client}' functional tests on '{backend}'.", [
|
||||
$output->writeln(r("Running '{client}' client functional tests on '{backend}'.", [
|
||||
'client' => $context->clientName,
|
||||
'backend' => $context->backendName,
|
||||
]));
|
||||
|
||||
Reference in New Issue
Block a user