Add console commands to manage commands

Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
Joas Schilling 2019-01-30 16:59:03 +01:00
Родитель 18aa82dabf
Коммит 835e6bdc77
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 7076EA9751AACDDA
10 изменённых файлов: 465 добавлений и 28 удалений

Просмотреть файл

@ -62,6 +62,10 @@ And in the works for the [coming versions](https://github.com/nextcloud/spreed/m
</repair-steps>
<commands>
<command>OCA\Spreed\Command\Command\Add</command>
<command>OCA\Spreed\Command\Command\Delete</command>
<command>OCA\Spreed\Command\Command\ListCommand</command>
<command>OCA\Spreed\Command\Command\Update</command>
<command>OCA\Spreed\Command\Stun\Add</command>
<command>OCA\Spreed\Command\Stun\Delete</command>
<command>OCA\Spreed\Command\Stun\ListCommand</command>

104
lib/Command/Command/Add.php Normal file
Просмотреть файл

@ -0,0 +1,104 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Spreed\Command\Command;
use OCA\Spreed\Service\CommandService;
use OC\Core\Command\Base;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Add extends Base {
use TRenderCommand;
/** @var CommandService */
private $service;
public function __construct(CommandService $service) {
parent::__construct();
$this->service = $service;
}
protected function configure(): void {
$this
->setName('talk:command:add')
->setDescription('Add a new command')
->addArgument(
'cmd',
InputArgument::REQUIRED,
'The command as used in the chat "/help" => "help"'
)
->addArgument(
'name',
InputArgument::REQUIRED,
'Name of the user posting the response'
)
->addArgument(
'script',
InputArgument::REQUIRED,
'Script to execute'
)
->addArgument(
'response',
InputArgument::REQUIRED,
'Who should see the response: 0 - No one, 1 - User, 2 - All'
)
->addArgument(
'enabled',
InputArgument::REQUIRED,
'Who can use this command: 0 - Disabled, 1 - Moderators, 2 - Users, 3 - Guests'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$cmd = $input->getArgument('cmd');
$name = $input->getArgument('name');
$script = $input->getArgument('script');
$response = (int) $input->getArgument('response');
$enabled = (int) $input->getArgument('enabled');
try {
$command = $this->service->create('', $cmd, $name, $script, $response, $enabled);
} catch (\InvalidArgumentException $e) {
switch ($e->getCode()) {
case 1:
$output->writeln('<error>The command already exists</error>');
break;
case 4:
$output->writeln('<error>The response value is invalid</error>');
break;
case 5:
$output->writeln('<error>The enabled value is invalid</error>');
break;
}
return 1;
}
$output->writeln('<info>Command added</info>');
$output->writeln('');
$this->renderCommands(Base::OUTPUT_FORMAT_PLAIN, $output, [$command]);
}
}

Просмотреть файл

@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Spreed\Command\Command;
use OCA\Spreed\Service\CommandService;
use OC\Core\Command\Base;
use OCP\AppFramework\Db\DoesNotExistException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Delete extends Base {
/** @var CommandService */
private $service;
public function __construct(CommandService $service) {
parent::__construct();
$this->service = $service;
}
protected function configure():void {
$this
->setName('talk:command:delete')
->setDescription('Remove an existing command')
->addArgument(
'command-id',
InputArgument::REQUIRED
);
}
protected function execute(InputInterface $input, OutputInterface $output) {
$id = (int) $input->getArgument('command-id');
try {
$this->service->delete($id);
} catch (DoesNotExistException $e) {
$output->writeln('<error>The given command ID does not exist</error>');
return 1;
} catch (\InvalidArgumentException $e) {
$output->writeln('<error>The help command cannot be deleted</error>');
return 2;
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Spreed\Command\Command;
use OCA\Spreed\Service\CommandService;
use OC\Core\Command\Base;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ListCommand extends Base {
use TRenderCommand;
/** @var CommandService */
private $service;
public function __construct(CommandService $service) {
parent::__construct();
$this->service = $service;
}
protected function configure(): void {
parent::configure();
$this
->setName('talk:command:list')
->setDescription('List all available commands')
->addArgument('app', InputArgument::OPTIONAL, 'Only list the commands of a specific app, "custom" to list all custom commands')
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$app = $input->getArgument('app');
if ($app === null) {
$commands = $this->service->findAll();
} else {
$commands = $this->service->findByApp($app === 'custom' ? '' : $app);
}
$this->renderCommands($input->getOption('output'), $output, $commands, true);
}
}

Просмотреть файл

@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Spreed\Command\Command;
use OCA\Spreed\Model\Command;
use OC\Core\Command\Base;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
trait TRenderCommand {
protected function renderCommands(string $outputFormat, OutputInterface $output, array $commands, bool $showHelp = false): void {
$result = array_map(function(Command $command) {
return $command->asArray();
}, $commands);
if ($outputFormat === Base::OUTPUT_FORMAT_PLAIN) {
if ($showHelp) {
$output->writeln('Response values: 0 - No one, 1 - User, 2 - All');
$output->writeln('Enabled values: 0 - Disabled, 1 - Moderators, 2 - Users, 3 - Guests');
$output->writeln('');
}
$table = new Table($output);
if (isset($result[0])) {
$table->setHeaders(array_keys($result[0]));
}
$table->addRows($result);
$table->render();
} else {
$this->writeMixedInOutputFormat($input, $output, $result);
}
}
}

Просмотреть файл

@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Spreed\Command\Command;
use OCA\Spreed\Service\CommandService;
use OC\Core\Command\Base;
use OCP\AppFramework\Db\DoesNotExistException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Update extends Base {
use TRenderCommand;
/** @var CommandService */
private $service;
public function __construct(CommandService $service) {
parent::__construct();
$this->service = $service;
}
protected function configure(): void {
$this
->setName('talk:command:update')
->setDescription('Add a new command')
->addArgument(
'command-id',
InputArgument::REQUIRED
)
->addArgument(
'cmd',
InputArgument::REQUIRED,
'The command as used in the chat "/help" => "help"'
)
->addArgument(
'name',
InputArgument::REQUIRED,
'Name of the user posting the response'
)
->addArgument(
'script',
InputArgument::REQUIRED,
'Script to execute'
)
->addArgument(
'response',
InputArgument::REQUIRED,
'Who should see the response: 0 - No one, 1 - User, 2 - All'
)
->addArgument(
'enabled',
InputArgument::REQUIRED,
'Who can use this command: 0 - Disabled, 1 - Moderators, 2 - Users, 3 - Guests'
)
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
$id = (int) $input->getArgument('command-id');
$cmd = $input->getArgument('cmd');
$name = $input->getArgument('name');
$script = $input->getArgument('script');
$response = (int) $input->getArgument('response');
$enabled = (int) $input->getArgument('enabled');
try {
$command = $this->service->update($id, $cmd, $name, $script, $response, $enabled);
} catch (DoesNotExistException $e) {
$output->writeln('<error>The given command ID does not exist</error>');
return 1;
} catch (\InvalidArgumentException $e) {
switch ($e->getCode()) {
case 0:
$output->writeln('<error>The help command and predefined commands cannot be updated</error>');
break;
case 1:
$output->writeln('<error>The command already exists</error>');
break;
case 4:
$output->writeln('<error>The response value is invalid</error>');
break;
case 5:
$output->writeln('<error>The enabled value is invalid</error>');
break;
}
return 2;
}
$output->writeln('<info>Command updated</info>');
$output->writeln('');
$this->renderCommands(Base::OUTPUT_FORMAT_PLAIN, $output, [$command]);
}
}

Просмотреть файл

@ -23,6 +23,7 @@
namespace OCA\Spreed\Controller;
use OCA\Spreed\Model\Command;
use OCA\Spreed\Service\CommandService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
@ -53,18 +54,9 @@ class CommandController extends OCSController {
public function index(): DataResponse {
$commands = $this->commandService->findAll();
$result = [];
foreach ($commands as $command) {
$result[] = [
'id' => $command->getId(),
'app' => $command->getApp(),
'name' => $command->getName(),
'pattern' => $command->getCommand(),
'script' => $command->getScript(),
'response' => $command->getResponse(),
'enabled' => $command->getEnabled(),
];
}
$result = array_map(function(Command $command) {
return $command->asArray();
}, $commands);
return new DataResponse($result);
}
@ -84,15 +76,7 @@ class CommandController extends OCSController {
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
return new DataResponse([
'id' => $command->getId(),
'app' => $command->getApp(),
'name' => $command->getName(),
'pattern' => $command->getCommand(),
'script' => $command->getScript(),
'response' => $command->getResponse(),
'enabled' => $command->getEnabled(),
]);
return new DataResponse($command->asArray());
}
/**
@ -104,6 +88,8 @@ class CommandController extends OCSController {
$this->commandService->delete($id);
} catch (DoesNotExistException $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
} catch (\InvalidArgumentException $e) {
return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
}
return new DataResponse();

Просмотреть файл

@ -75,4 +75,19 @@ class Command extends Entity {
$this->addType('response', 'int');
$this->addType('enabled', 'int');
}
/**
* @return array
*/
public function asArray(): array {
return [
'id' => $this->getId(),
'app' => $this->getApp(),
'name' => $this->getName(),
'command' => $this->getCommand(),
'script' => $this->getScript(),
'response' => $this->getResponse(),
'enabled' => $this->getEnabled(),
];
}
}

Просмотреть файл

@ -38,12 +38,12 @@ class CommandMapper extends QBMapper {
* @return Command[]
*/
public function findAll(): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
$query = $this->db->getQueryBuilder();
$query->select('*')
->from($this->getTableName())
->orderBy('id', 'ASC');
return $this->findEntities($qb);
return $this->findEntities($query);
}
/**
@ -60,6 +60,20 @@ class CommandMapper extends QBMapper {
return $this->findEntity($query);
}
/**
* @param string $app
* @return Command[]
*/
public function findByApp(string $app): array {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from($this->getTableName())
->where($query->expr()->eq('app', $query->createNamedParameter($app)))
->orderBy('id', 'ASC');
return $this->findEntities($query);
}
/**
* @param string $app
* @param string $cmd

Просмотреть файл

@ -100,6 +100,10 @@ class CommandService {
*/
public function update(int $id, string $cmd, string $name, string $script, int $response, int $enabled): Command {
$command = $this->mapper->findById($id);
if ($command->getApp() !== '' || $command->getCommand() === 'help') {
throw new \InvalidArgumentException('app', 0);
}
if (!\in_array($response, [Command::RESPONSE_NONE, Command::RESPONSE_USER, Command::RESPONSE_ALL], true)) {
throw new \InvalidArgumentException('response', 4);
}
@ -108,10 +112,6 @@ class CommandService {
throw new \InvalidArgumentException('enabled', 5);
}
if ($command->getApp() !== '' || $command->getCommand() === 'help') {
throw new \InvalidArgumentException('app', 0);
}
if ($cmd !== $command->getCommand()) {
try {
$this->mapper->find('', $cmd);
@ -136,11 +136,18 @@ class CommandService {
* @param int $id
* @return Command
* @throws DoesNotExistException
* @throws \InvalidArgumentException
*/
public function delete(int $id): Command {
$command = $this->mapper->findById($id);
if ($command->getApp() !== '' || $command->getCommand() === 'help') {
throw new \InvalidArgumentException('app', 0);
}
return $this->mapper->delete($command);
}
/**
* @param string $app
* @param string $cmd
@ -151,6 +158,14 @@ class CommandService {
return $this->mapper->find($app, $cmd);
}
/**
* @param string $app
* @return Command[]
*/
public function findByApp(string $app): array {
return $this->mapper->findByApp($app);
}
/**
* @param int $id
* @return Command