From ba4492ea8144474c06c6df749903fe489a0d3ca9 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Sun, 2 May 2021 18:32:49 +0200 Subject: [PATCH 1/5] Add console contact command --- src/Console/Contact.php | 289 ++++++++++++++++++++++++++++++++++++++++ src/Core/Console.php | 2 + 2 files changed, 291 insertions(+) create mode 100644 src/Console/Contact.php diff --git a/src/Console/Contact.php b/src/Console/Contact.php new file mode 100644 index 0000000000..5506881ae8 --- /dev/null +++ b/src/Console/Contact.php @@ -0,0 +1,289 @@ +. + * + */ + +namespace Friendica\Console; + +use Console_Table; +use Friendica\App; +use Friendica\Content\Pager; +use Friendica\Model\Contact as ContactModel; +use Friendica\Model\User as UserModel; +use Friendica\Util\Temporal; +use RuntimeException; +use Seld\CliPrompt\CliPrompt; + +/** + * tool to manage contacts of users of the current node + */ +class Contact extends \Asika\SimpleConsole\Console +{ + protected $helpOptions = ['h', 'help', '?']; + + /** + * @var App\Mode + */ + private $appMode; + /** + * @var IPConfig + */ + private $pConfig; + + protected function getHelp() + { + $help = << [] [-h|--help|-?] [-v] + bin/console contact remove [-h|--help|-?] [-v] + bin/console contact search id [-h|--help|-?] [-v] + bin/console contact search url [-h|--help|-?] [-v] + bin/console contact terminate [-h|--help|-?] [-v] + +Description + Modify contact settings per console commands. + +Options + -h|--help|-? Show help information + -v Show more debug information + -y Non-interactive mode, assume "yes" as answer to the user deletion prompt +HELP; + return $help; + } + + public function __construct(App\Mode $appMode, array $argv = null) + { + parent::__construct($argv); + + $this->appMode = $appMode; + } + + protected function doExecute() + { + if ($this->getOption('v')) { + $this->out('Class: ' . __CLASS__); + $this->out('Arguments: ' . var_export($this->args, true)); + $this->out('Options: ' . var_export($this->options, true)); + } + + if (count($this->args) == 0) { + $this->out($this->getHelp()); + return 0; + } + + if ($this->appMode->isInstall()) { + throw new RuntimeException('Database isn\'t ready or populated yet'); + } + + $command = $this->getArgument(0); + + switch ($command) { + case 'add': + return $this->addContact(); + case 'remove': + return $this->removeContact(); + case 'search': + return $this->searchContact(); + case 'terminate': + return $this->terminateContact(); + default: + throw new \Asika\SimpleConsole\CommandArgsException('Wrong command.'); + } + } + + /** + * Retrieves the user from a nick supplied as an argument or from a prompt + * + * @param int $arg_index Index of the nick argument in the arguments list + * + * @return array|boolean User record with uid field, or false if user is not found + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + private function getUserByNick($arg_index) + { + $nick = $this->getArgument($arg_index); + + if (empty($nick)) { + $this->out('Enter user nickname: '); + $nick = CliPrompt::prompt(); + if (empty($nick)) { + throw new RuntimeException('A user nickname must be specified.'); + } + } + + $user = UserModel::getByNickname($nick, ['uid', 'nickname']); + if (empty($user)) { + throw new RuntimeException('User not found'); + } + + return $user; + } + + /** + * Adds a contact to a user from a URL + * + * @return bool True, if the command was successful + */ + private function addContact() + { + $user = $this->getUserByNick(1); + + $url = $this->getArgument(2); + if (empty($url)) { + $this->out('Enter contact URL: '); + $url = CliPrompt::prompt(); + if (empty($url)) { + throw new RuntimeException('A contact URL must be specified.'); + } + } + + $contact = ContactModel::getByURLForUser($url, $user['uid']); + if (!empty($contact)) { + throw new RuntimeException('Contact already exists'); + } + + $network = $this->getArgument(3); + if (empty($network) && $network !== '') { + $this->out('Enter network, or leave blank: '); + $network = CliPrompt::prompt(); + } + + $result = ContactModel::createFromProbe($user, $url, false, $network); + + if ($result['success']) { + $this->out('User ' . $user['nickname'] . ' now connected to ' . $url . ', contact ID ' . $result['cid']); + } + else { + throw new RuntimeException($result['message']); + } + } + + /** + * Sends an unfriend message. Does not remove the contact + * + * @return bool True, if the command was successful + */ + private function terminateContact() + { + $cid = $this->getArgument(1); + if (empty($cid)) { + $this->out('Enter contact ID: '); + $cid = CliPrompt::prompt(); + if (empty($cid)) { + throw new RuntimeException('A contact ID must be specified.'); + } + } + + $contact = ContactModel::getById($cid); + if (empty($contact)) { + throw new RuntimeException('Contact not found'); + } + + $user = UserModel::getById($contact['uid']); + + $result = ContactModel::terminateFriendship($user, $contact); + } + + /** + * Marks a contact for removal + * + * @return bool True, if the command was successful + */ + private function removeContact() + { + $cid = $this->getArgument(1); + if (empty($cid)) { + $this->out('Enter contact ID: '); + $cid = CliPrompt::prompt(); + if (empty($cid)) { + throw new RuntimeException('A contact ID must be specified.'); + } + } + + $result = ContactModel::remove($cid); + } + + /** + * Returns a contact based on search parameter + * + * @return bool True, if the command was successful + */ + private function searchContact() + { + $fields = [ + 'id', + 'uid', + 'network', + 'name', + 'nick', + 'url', + 'addr', + 'created', + 'updated', + 'blocked', + 'deleted', + ]; + + $subCmd = $this->getArgument(1); + + $table = new Console_Table(); + $table->setHeaders(['ID', 'UID', 'Network', 'Name', 'Nick', 'URL', 'E-Mail', 'Created', 'Updated', 'Blocked', 'Deleted']); + + $addRow = function($row) use (&$table) { + $table->addRow([ + $row['id'], + $row['uid'], + $row['network'], + $row['name'], + $row['nick'], + $row['url'], + $row['addr'], + Temporal::getRelativeDate($row['created']), + Temporal::getRelativeDate($row['updated']), + $row['blocked'], + $row['deleted'], + ]); + }; + switch ($subCmd) { + case 'id': + $cid = $this->getArgument(2); + $contact = ContactModel::getById($cid, $fields); + if (!empty($contact)) { + $addRow($contact); + } + break; + case 'url': + $user = $this->getUserByNick(2); + $url = $this->getArgument(3); + $contact = ContactModel::getByURLForUser($url, $user['uid'], false, $fields); + if (!empty($contact)) { + $addRow($contact); + } + break; + default: + $this->out($this->getHelp()); + return false; + } + + $this->out($table->getTable()); + + return true; + } +} diff --git a/src/Core/Console.php b/src/Core/Console.php index 9289e22341..56a294062b 100644 --- a/src/Core/Console.php +++ b/src/Core/Console.php @@ -47,6 +47,7 @@ Commands: addon Addon management cache Manage node cache config Edit site config + contact Contact management createdoxygen Generate Doxygen headers dbstructure Do database updates docbloxerrorchecker Check the file tree for DocBlox errors @@ -78,6 +79,7 @@ HELP; 'addon' => Friendica\Console\Addon::class, 'cache' => Friendica\Console\Cache::class, 'config' => Friendica\Console\Config::class, + 'contact' => Friendica\Console\Contact::class, 'createdoxygen' => Friendica\Console\CreateDoxygen::class, 'docbloxerrorchecker' => Friendica\Console\DocBloxErrorChecker::class, 'dbstructure' => Friendica\Console\DatabaseStructure::class, From 05481cab3dfef51418926f9822b161db3e84fc55 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Mon, 3 May 2021 20:17:43 +0200 Subject: [PATCH 2/5] fix formatting issues --- src/Console/Contact.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Console/Contact.php b/src/Console/Contact.php index 5506881ae8..a64ae660c3 100644 --- a/src/Console/Contact.php +++ b/src/Console/Contact.php @@ -23,7 +23,6 @@ namespace Friendica\Console; use Console_Table; use Friendica\App; -use Friendica\Content\Pager; use Friendica\Model\Contact as ContactModel; use Friendica\Model\User as UserModel; use Friendica\Util\Temporal; @@ -169,8 +168,7 @@ HELP; if ($result['success']) { $this->out('User ' . $user['nickname'] . ' now connected to ' . $url . ', contact ID ' . $result['cid']); - } - else { + } else { throw new RuntimeException($result['message']); } } @@ -246,7 +244,7 @@ HELP; $table = new Console_Table(); $table->setHeaders(['ID', 'UID', 'Network', 'Name', 'Nick', 'URL', 'E-Mail', 'Created', 'Updated', 'Blocked', 'Deleted']); - $addRow = function($row) use (&$table) { + $addRow = function ($row) use (&$table) { $table->addRow([ $row['id'], $row['uid'], @@ -263,7 +261,7 @@ HELP; }; switch ($subCmd) { case 'id': - $cid = $this->getArgument(2); + $cid = $this->getArgument(2); $contact = ContactModel::getById($cid, $fields); if (!empty($contact)) { $addRow($contact); @@ -271,7 +269,7 @@ HELP; break; case 'url': $user = $this->getUserByNick(2); - $url = $this->getArgument(3); + $url = $this->getArgument(3); $contact = ContactModel::getByURLForUser($url, $user['uid'], false, $fields); if (!empty($contact)) { $addRow($contact); From 7a8f9f382e2c167080a25fa7adc7df5eb01f5025 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Mon, 3 May 2021 20:56:41 +0200 Subject: [PATCH 3/5] Fix assignment statement alignment Co-authored-by: Philipp --- src/Console/Contact.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/Contact.php b/src/Console/Contact.php index a64ae660c3..8bff00f1d6 100644 --- a/src/Console/Contact.php +++ b/src/Console/Contact.php @@ -269,7 +269,7 @@ HELP; break; case 'url': $user = $this->getUserByNick(2); - $url = $this->getArgument(3); + $url = $this->getArgument(3); $contact = ContactModel::getByURLForUser($url, $user['uid'], false, $fields); if (!empty($contact)) { $addRow($contact); From 312de957f43f6d3b2c17eb935cca06d9132ff034 Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Mon, 3 May 2021 20:56:49 +0200 Subject: [PATCH 4/5] Fix assignment statement alignment Co-authored-by: Philipp --- src/Console/Contact.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/Contact.php b/src/Console/Contact.php index 8bff00f1d6..57f64fd9ac 100644 --- a/src/Console/Contact.php +++ b/src/Console/Contact.php @@ -268,7 +268,7 @@ HELP; } break; case 'url': - $user = $this->getUserByNick(2); + $user = $this->getUserByNick(2); $url = $this->getArgument(3); $contact = ContactModel::getByURLForUser($url, $user['uid'], false, $fields); if (!empty($contact)) { From 1ce7c337f5f41e6ecd6a5b1a4c3e97fae8544fbe Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Tue, 4 May 2021 13:16:00 +0200 Subject: [PATCH 5/5] Simplify test for empty network selection Co-authored-by: Hypolite Petovan --- src/Console/Contact.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Console/Contact.php b/src/Console/Contact.php index 57f64fd9ac..55fd5024ca 100644 --- a/src/Console/Contact.php +++ b/src/Console/Contact.php @@ -159,7 +159,7 @@ HELP; } $network = $this->getArgument(3); - if (empty($network) && $network !== '') { + if ($network === null) { $this->out('Enter network, or leave blank: '); $network = CliPrompt::prompt(); }