Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to Manage command, better error handling and disabled command on non-tty mode. #35

Merged
merged 4 commits into from
Mar 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
return (function () {
$config = [
'name' => 'WatchState',
'version' => 'v0.0.19-alpha',
'version' => 'v0.0.20-alpha',
'tz' => null,
'path' => fixPath(
env('WS_DATA_PATH', fn() => env('IN_DOCKER') ? '/config' : realpath(__DIR__ . '/../var'))
Expand Down
26 changes: 20 additions & 6 deletions docker/files/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
#!/usr/bin/env sh
set -e
set -eo pipefail

WS_UID=${WS_UID:-1000}
WS_GID=${WS_GID:-1000}
WS_NO_CHOWN=${WS_NO_CHOWN:-0}
WS_DISABLE_HTTP=${WS_DISABLE_HTTP:-0}
WS_CRON_IMPORT=${WS_CRON_IMPORT:-0}
WS_CRON_PUSH=${WS_CRON_PUSH:-0}
WS_CRON_EXPORT=${WS_CRON_EXPORT:-0}

usermod -u ${WS_UID} www-data
groupmod -g ${WS_GID} www-data
set -u

if [ "${WS_UID}" != "$(id -u www-data)" ]; then
usermod -u ${WS_UID} www-data
fi

if [ "${WS_GID}" != "$(id -g www-data)" ]; then
groupmod -g ${WS_GID} www-data
fi

if [ ! -f "/app/vendor/autoload.php" ]; then
if [ ! -f "/usr/bin/composer" ]; then
Expand All @@ -24,7 +36,7 @@ if [ ! -f "/usr/bin/run-app-cron" ]; then
chmod +x /usr/bin/run-app-cron
fi

if [ -z "${WS_NO_CHOWN}" ]; then
if [ 0 == "${WS_NO_CHOWN}" ]; then
chown -R www-data:www-data /config
fi

Expand All @@ -33,11 +45,13 @@ fi
/usr/bin/console storage:migrations
/usr/bin/console storage:maintenance

if [ ! -z "${WS_DISABLE_HTTP}" ] && [ -f "/etc/caddy/Caddyfile" ]; then
if [ 0 == "${WS_DISABLE_HTTP}" ] && [ -f "/etc/caddy/Caddyfile" ]; then
echo "Starting Caddy server.."
caddy start -config /etc/caddy/Caddyfile
fi

if [ "1" == "${WS_CRON_IMPORT}" ] || [ "1" == "${WS_CRON_EXPORT}" ] || [ "1" == "${WS_CRON_PUSH}"]; then
if [ "1" == "${WS_CRON_IMPORT}" ] || [ "1" == "${WS_CRON_EXPORT}" ] || [ "1" == "${WS_CRON_PUSH}" ]; then
echo "Starting cron..."
/usr/sbin/crond -b -l 2
fi

Expand Down
46 changes: 38 additions & 8 deletions src/Commands/Servers/ManageCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,16 @@ protected function configure(): void
*/
protected function runCommand(InputInterface $input, OutputInterface $output, null|array $rerun = null): int
{
if ($input->getOption('no-interaction')) {
if (function_exists('stream_isatty') && defined('STDERR')) {
$tty = stream_isatty(STDERR);
} else {
$tty = true;
}

if (false === $tty || $input->getOption('no-interaction')) {
$output->writeln('<error>ERROR: This command require interaction.</error>');
$output->writeln(
'<comment>If you are running this tool inside docker run you have to enable interaction</comment>'
'<comment>If you are running this tool inside docker, you have to enable interaction using "-ti" flag</comment>'
);
$output->writeln(
'<comment>For example: docker exec -ti watchstate console servers:manage my_home_server</comment>'
Expand All @@ -52,7 +58,7 @@ protected function runCommand(InputInterface $input, OutputInterface $output, nu
try {
$this->checkCustomServersFile($config);
$custom = true;
$servers = Yaml::parseFile($config);
$servers = (array)Yaml::parseFile($config);
} catch (\RuntimeException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return self::FAILURE;
Expand All @@ -62,7 +68,7 @@ protected function runCommand(InputInterface $input, OutputInterface $output, nu
if (!file_exists($config)) {
touch($config);
}
$servers = Config::get('servers', []);
$servers = (array)Config::get('servers', []);
}

$add = $input->getOption('add');
Expand Down Expand Up @@ -179,8 +185,21 @@ protected function runCommand(InputInterface $input, OutputInterface $output, nu
// -- $name.uuid
(function () use ($input, $output, &$u, $name) {
try {
$chosen = ag($u, 'uuid', fn() => makeServer($u, $name)->getServerUUID(true));
} catch (Throwable) {
$output->writeln(
'<info>Trying to get server unique identifier from given information... Please wait</info>'
);

$server = array_replace_recursive($u, ['options' => ['client' => ['timeout' => 5]]]);
$chosen = ag($u, 'uuid', fn() => makeServer($server, $name)->getServerUUID(true));
} catch (Throwable $e) {
$output->writeln('<error>Failed to get the server unique identifier.</error>');
$output->writeln(
sprintf(
'<error>ERROR - %s: %s.</error>' . PHP_EOL,
afterLast(get_class($e), '\\'),
$e->getMessage()
)
);
$chosen = null;
}

Expand Down Expand Up @@ -244,8 +263,14 @@ protected function runCommand(InputInterface $input, OutputInterface $output, nu
$chosen = ag($u, 'user');

try {
$output->writeln(
'<info>Trying to get users list from server Please wait</info>'
);

$list = $map = $ids = [];
$users = makeServer($u, $name)->getUsersList();
$server = array_replace_recursive($u, ['options' => ['client' => ['timeout' => 5]]]);
$users = makeServer($server, $name)->getUsersList();

if (empty($users)) {
throw new \RuntimeException('Empty users list returned');
}
Expand Down Expand Up @@ -279,8 +304,13 @@ protected function runCommand(InputInterface $input, OutputInterface $output, nu

return;
} catch (Throwable $e) {
$output->writeln('<error>Failed to get the users list from server.</error>');
$output->writeln(
sprintf('<error>Failed to get user list from server. \'%s\' </error>', $e->getMessage())
sprintf(
'<error>ERROR - %s: %s.</error>' . PHP_EOL,
afterLast(get_class($e), '\\'),
$e->getMessage()
)
);
}

Expand Down
24 changes: 11 additions & 13 deletions src/Commands/Servers/RemoteCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Libs\Config;
use App\Libs\Extends\CliLogger;
use App\Libs\Servers\ServerInterface;
use JsonException;
use RuntimeException;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableSeparator;
Expand All @@ -16,6 +17,7 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Yaml;
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;

final class RemoteCommand extends Command
{
Expand All @@ -31,6 +33,10 @@ protected function configure(): void
->addArgument('name', InputArgument::REQUIRED, 'Server name');
}

/**
* @throws ExceptionInterface
* @throws JsonException
*/
protected function runCommand(InputInterface $input, OutputInterface $output): int
{
// -- Use Custom servers.yaml file.
Expand Down Expand Up @@ -68,17 +74,20 @@ protected function runCommand(InputInterface $input, OutputInterface $output): i
}

if ($input->getOption('list-users') || $input->getOption('list-users-with-tokens')) {
$this->listUsers($input, $output, $server, $config);
$this->listUsers($input, $output, $server);
}

return self::SUCCESS;
}

/**
* @throws JsonException
* @throws ExceptionInterface
*/
private function listUsers(
InputInterface $input,
OutputInterface $output,
ServerInterface $server,
array $config = []
): void {
$opts = [];

Expand All @@ -88,17 +97,6 @@ private function listUsers(

$users = $server->getUsersList($opts);

if (null === $users) {
$output->writeln(
sprintf(
'<error>%s: \'%s\' Does not support users concept.</error>',
ag($config, 'type'),
ag($config, 'name'),
)
);
return;
}

if (count($users) < 1) {
$output->writeln('<comment>No users reported by server.</comment>');
return;
Expand Down
95 changes: 31 additions & 64 deletions src/Libs/Servers/JellyfinServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,85 +127,52 @@ public function getServerUUID(bool $forceRefresh = false): int|string|null

$this->checkConfig(checkUser: false);

try {
$this->logger->debug(
sprintf('Requesting server Unique id info from %s.', $this->name),
['url' => $this->url->getHost()]
);

$url = $this->url->withPath('/system/Info');
$this->logger->debug(
sprintf('Requesting server Unique id info from %s.', $this->name),
['url' => $this->url->getHost()]
);

$response = $this->http->request('GET', (string)$url, $this->getHeaders());
$url = $this->url->withPath('/system/Info');

if (200 !== $response->getStatusCode()) {
$this->logger->error(
sprintf(
'Request to %s responded with unexpected code (%d).',
$this->name,
$response->getStatusCode()
)
);

return null;
}
$response = $this->http->request('GET', (string)$url, $this->getHeaders());

$json = json_decode($response->getContent(false), true, flags: JSON_THROW_ON_ERROR);

return ag($json, 'Id', null);
} catch (ExceptionInterface $e) {
$this->logger->error(
sprintf('Request to %s failed. Reason: \'%s\'.', $this->name, $e->getMessage()),
[
'file' => $e->getFile(),
'line' => $e->getLine(),
],
);
return null;
} catch (JsonException $e) {
if (200 !== $response->getStatusCode()) {
$this->logger->error(
sprintf('Unable to decode %s response. Reason: \'%s\'.', $this->name, $e->getMessage()),
[
'file' => $e->getFile(),
'line' => $e->getLine(),
],
sprintf(
'Request to %s responded with unexpected code (%d).',
$this->name,
$response->getStatusCode()
)
);

return null;
}
}

public function getUsersList(array $opts = []): array|null
{
$this->checkConfig(checkUser: false);
$json = json_decode($response->getContent(false), true, flags: JSON_THROW_ON_ERROR);

try {
$this->logger->debug(
sprintf('Requesting users list info from %s.', $this->name),
['url' => $this->url->getHost()]
);
$this->uuid = ag($json, 'Id', null);

$response = $this->http->request('GET', (string)$this->url->withPath('/Users/'), $this->getHeaders());
return $this->uuid;
}

if (200 !== $response->getStatusCode()) {
$this->logger->error(
sprintf(
'Request to %s responded with unexpected code (%d).',
$this->name,
$response->getStatusCode()
)
);
public function getUsersList(array $opts = []): array
{
$this->checkConfig(checkUser: false);

return null;
}
$response = $this->http->request('GET', (string)$this->url->withPath('/Users/'), $this->getHeaders());

$json = json_decode($response->getContent(), true, flags: JSON_THROW_ON_ERROR);
} catch (Throwable $e) {
$this->logger->error($e->getMessage(), [
'file' => $e->getFile(),
'line' => $e->getLine(),
]);
return null;
if (200 !== $response->getStatusCode()) {
throw new RuntimeException(
sprintf(
'Request to %s responded with unexpected code (%d).',
$this->name,
$response->getStatusCode()
)
);
}

$json = json_decode($response->getContent(), true, flags: JSON_THROW_ON_ERROR);

$list = [];

foreach ($json ?? [] as $user) {
Expand Down
Loading