diff --git a/CHANGELOG b/CHANGELOG index a15edc0..4490db5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,12 @@ +SlackBundle v1.3.0 +================== +- Feature: File upload service now accepts an array of channels, string usage is deprecated +- Feature: Implement action to invite users to a channel +- Feature: Implement action and service to get details about users on the team +- Feature: Implement console command to read userdata from api +- Patch: File upload no longer need to lookup channel id due to api changes +- Patch: Set aliases for command names - old names with dzunke: prefix will be removed in the future! + SlackBundle v1.2.2 ================== - Patch: MessageAttachment support complete attachment-api (by @shimmi) diff --git a/Command/BotMessagingCommand.php b/Command/BotMessagingCommand.php index bc4edac..a0dd2bd 100644 --- a/Command/BotMessagingCommand.php +++ b/Command/BotMessagingCommand.php @@ -22,6 +22,7 @@ protected function configure() { $this ->setName('dzunke:slack:run-bot') + ->setAliases(['slack:run-bot']) ->setDescription('Running the Bot-User to a Channel') ->addArgument( 'channel', diff --git a/Command/ChangeChannelsTopicCommand.php b/Command/ChangeChannelsTopicCommand.php index 4da6472..cd4533a 100644 --- a/Command/ChangeChannelsTopicCommand.php +++ b/Command/ChangeChannelsTopicCommand.php @@ -15,6 +15,7 @@ protected function configure() { $this ->setName('dzunke:slack:channels:topic') + ->setAliases(['slack:channels:topic']) ->setDescription('Changing the Topic of a Channel') ->addOption('discover', 'd', InputOption::VALUE_NONE, 'channel name is given, so discover the id') ->addArgument('channel', InputArgument::REQUIRED, 'an existing channel in your team to change the topic') diff --git a/Command/DebugCommand.php b/Command/DebugCommand.php index d5911cc..98ccaab 100644 --- a/Command/DebugCommand.php +++ b/Command/DebugCommand.php @@ -31,6 +31,7 @@ protected function configure() { $this ->setName('dzunke:slack:debug') + ->setAliases(['slack:debug']) ->setDescription('Gives some Debug Informations about the SlackBundle'); } diff --git a/Command/MessageCommand.php b/Command/MessageCommand.php index 9cdf518..2e2aa84 100644 --- a/Command/MessageCommand.php +++ b/Command/MessageCommand.php @@ -14,6 +14,7 @@ protected function configure() { $this ->setName('dzunke:slack:message') + ->setAliases(['slack:message']) ->setDescription('Sending a Message to a Channel or User') ->addArgument('channel', InputArgument::REQUIRED, 'an existing channel in your team to send to') ->addArgument('username', InputArgument::REQUIRED, 'an username from configured identities to send with') diff --git a/Command/UsersCommand.php b/Command/UsersCommand.php new file mode 100644 index 0000000..5e3cf69 --- /dev/null +++ b/Command/UsersCommand.php @@ -0,0 +1,75 @@ +setName('dzunke:slack:users') + ->setAliases(['slack:users']) + ->setDescription('work with the users of your team') + ->addOption('only-active', 'a', InputOption::VALUE_NONE, 'lists only active users') + ->addOption('only-deleted', 'd', InputOption::VALUE_NONE, 'lists only deleted users') + ->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'get a single user'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $formatter = $this->getHelper('formatter'); + + try { + $api = $this->getContainer()->get('dz.slack.users'); + + if ($input->getOption('only-active')) { + $response = $api->getActiveUsers(); + } elseif ($input->getOption('only-deleted')) { + $response = $api->getDeletedUsers(); + } elseif ($input->getOption('user')) { + $response = $api->getUser($input->getOption('user')); + + if (is_array($response)) { + $response = [$response['name'] => $response]; + } + } else { + $response = $api->getUsers(); + } + + if (empty($response)) { + $output->writeln($formatter->formatBlock('✘ no data found', 'error')); + return; + } + + array_walk( + $response, + function (&$row) { + foreach ($row as &$col) { + if (is_bool($col)) { + $col = $col ? 'true' : 'false'; + } + } + } + ); + + $table = $this->getHelper('table'); + $table->setHeaders(array_keys(reset($response)))->setRows($response); + $table->render($output); + + + } catch (\Exception $e) { + $output->writeln( + $formatter->formatBlock( + sprintf('✘ there was an error with your request: "%s"', $e->getMessage()), + 'error' + ) + ); + } + } +} diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 7111d19..85a0e42 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -17,3 +17,7 @@ services: dz.slack.channels: class: DZunke\SlackBundle\Slack\Channels arguments: [@dz.slack.client] + + dz.slack.users: + class: DZunke\SlackBundle\Slack\Users + arguments: [@dz.slack.client] diff --git a/Resources/doc/actions-list.md b/Resources/doc/actions-list.md index 2ca7ea0..2e7eea1 100644 --- a/Resources/doc/actions-list.md +++ b/Resources/doc/actions-list.md @@ -38,6 +38,23 @@ protected $parameter = [ ]; ``` +## channels.invite + +[Slack Documentation](https://api.slack.com/methods/channels.invite) + +Constant: \DZunke\SlackBundle\Slack\Client::ACTION_CHANNELS_INVITE + +Available Parameters: + +Both Parameters have to be the if of the entity and not the raw name + +``` php +protected $parameter = [ + 'channel' => null, + 'user' => null, +]; +``` + ## channels.list [Slack Documentation](https://api.slack.com/methods/channels.list) @@ -105,3 +122,15 @@ protected $parameter = [ 'channels' => null # If no Channel is given the File will be private to the API-User ]; ``` + +## users.list + +[Slack Documentation](https://api.slack.com/methods/users.list) + +Constant: \DZunke\SlackBundle\Slack\Client::ACTION_USERS_LIST + +``` php +protected $parameter = [ + 'presence' => 1 +]; +``` diff --git a/Resources/doc/commands.md b/Resources/doc/commands.md index 490d46b..822d859 100644 --- a/Resources/doc/commands.md +++ b/Resources/doc/commands.md @@ -5,7 +5,7 @@ Output of Debug Informations like Connection, Identities, Channels etc. ``` bash -php app/console dzunke:slack:debug +php app/console slack:debug ``` ## Messaging @@ -13,8 +13,8 @@ php app/console dzunke:slack:debug Sending a Message directly from Console ``` bash -php app/console dzunke:slack:message @fooUser BazUser "Lorem ipsum dolor sit amet .." -php app/console dzunke:slack:message "#FooChannel" BazUser "Lorem ipsum dolor sit amet .." +php app/console slack:message @fooUser BazUser "Lorem ipsum dolor sit amet .." +php app/console slack:message "#FooChannel" BazUser "Lorem ipsum dolor sit amet .." ``` ## Switch Topic of a Channel @@ -22,8 +22,20 @@ php app/console dzunke:slack:message "#FooChannel" BazUser "Lorem ipsum dolor si You can switch the Topic of a Channel ``` bash -php app/console dzunke:slack:channels:topic "C02GABTDT" "Lorem ipsum dolor sit amet .." +php app/console slack:channels:topic "C02GABTDT" "Lorem ipsum dolor sit amet .." # If you don't have the ChannelId it must be discovered while processing -php app/console dzunke:slack:channels:topic "#foo-channel" "Lorem ipsum dolor sit amet .." -d +php app/console slack:channels:topic "#foo-channel" "Lorem ipsum dolor sit amet .." -d ``` + +## Read userdata from api + +you will get a table of userdata. + +``` bash +# Read all users from your team +php app/console slack:users + +# Read a single user +php app/console slack:users --user=nameOfTheUser +``` diff --git a/Resources/doc/services.md b/Resources/doc/services.md index 16bd40a..5999f8d 100644 --- a/Resources/doc/services.md +++ b/Resources/doc/services.md @@ -65,3 +65,25 @@ $service->info($channelId); $service->setTopic($channelId, $newTopic); ``` +## Users + +To get more information about the users in your team there is a service to read user specific things. In lack of an +api method to load single users every method of the service will load the complete list of users in your team. Beware +of using this service without caching informations you often need. + +``` php +$service = $container->get('dz.slack.users'); + +# get the list of all users in your team +$service->getUsers(); + +# get all users that are not deleted +$service->getActiveUsers(); + +# get all deleted users +$service->getDeletedUsers(); + +# get the id of a single user - needed for some actions +$service->getId($username); + +``` diff --git a/Slack/Client.php b/Slack/Client.php index 1bd6753..866f40e 100644 --- a/Slack/Client.php +++ b/Slack/Client.php @@ -30,7 +30,7 @@ public function __construct(Connection $connection) * @param array $parameter * @return Response|bool */ - public function send($action, array $parameter) + public function send($action, array $parameter = []) { if (!$this->connection->isValid()) { return false; diff --git a/Slack/Client/Actions.php b/Slack/Client/Actions.php index 163024a..1100ed5 100644 --- a/Slack/Client/Actions.php +++ b/Slack/Client/Actions.php @@ -12,8 +12,10 @@ class Actions const ACTION_AUTH_TEST = 'auth.test'; const ACTION_CHANNELS_SET_TOPIC = 'channels.setTopic'; const ACTION_CHANNELS_INFO = 'channels.info'; + const ACTION_CHANNELS_INVITE = 'channels.invite'; const ACTION_CHANNELS_HISTORY = 'channels.history'; const ACTION_FILES_UPLOAD = 'files.upload'; + const ACTION_USERS_LIST = 'users.list'; /** * @var array @@ -25,8 +27,10 @@ class Actions self::ACTION_AUTH_TEST => 'AuthTest', self::ACTION_CHANNELS_SET_TOPIC => 'ChannelsSetTopic', self::ACTION_CHANNELS_INFO => 'ChannelsInfo', + self::ACTION_CHANNELS_INVITE => 'ChannelsInvite', self::ACTION_CHANNELS_HISTORY => 'ChannelsHistory', - self::ACTION_FILES_UPLOAD => 'FilesUpload' + self::ACTION_FILES_UPLOAD => 'FilesUpload', + self::ACTION_USERS_LIST => 'UsersList' ]; /** diff --git a/Slack/Client/Actions/ApiTest.php b/Slack/Client/Actions/ApiTest.php index 6627e46..92238d9 100644 --- a/Slack/Client/Actions/ApiTest.php +++ b/Slack/Client/Actions/ApiTest.php @@ -4,6 +4,9 @@ use DZunke\SlackBundle\Slack\Client\Actions; +/** + * @see https://api.slack.com/methods/api.test + */ class ApiTest implements ActionsInterface { diff --git a/Slack/Client/Actions/AuthTest.php b/Slack/Client/Actions/AuthTest.php index 972c8fc..cf38265 100644 --- a/Slack/Client/Actions/AuthTest.php +++ b/Slack/Client/Actions/AuthTest.php @@ -4,6 +4,9 @@ use DZunke\SlackBundle\Slack\Client\Actions; +/** + * @see https://api.slack.com/methods/auth.test + */ class AuthTest implements ActionsInterface { diff --git a/Slack/Client/Actions/ChannelsHistory.php b/Slack/Client/Actions/ChannelsHistory.php index 2e43d41..025ec6b 100644 --- a/Slack/Client/Actions/ChannelsHistory.php +++ b/Slack/Client/Actions/ChannelsHistory.php @@ -4,6 +4,9 @@ use DZunke\SlackBundle\Slack\Client\Actions; +/** + * @see https://api.slack.com/methods/channels.history + */ class ChannelsHistory implements ActionsInterface { diff --git a/Slack/Client/Actions/ChannelsInfo.php b/Slack/Client/Actions/ChannelsInfo.php index 7703a8d..7ef01f9 100644 --- a/Slack/Client/Actions/ChannelsInfo.php +++ b/Slack/Client/Actions/ChannelsInfo.php @@ -4,6 +4,9 @@ use DZunke\SlackBundle\Slack\Client\Actions; +/** + * @see https://api.slack.com/methods/channels.info + */ class ChannelsInfo implements ActionsInterface { diff --git a/Slack/Client/Actions/ChannelsInvite.php b/Slack/Client/Actions/ChannelsInvite.php new file mode 100644 index 0000000..a753db5 --- /dev/null +++ b/Slack/Client/Actions/ChannelsInvite.php @@ -0,0 +1,65 @@ + null, + 'user' => null + ]; + + /** + * @return array + * @throws \Exception + */ + public function getRenderedRequestParams() + { + if (is_null($this->parameter['channel']) || is_null($this->parameter['user'])) { + throw new \Exception('both parameters channel and user must be given'); + } + + return $this->parameter; + } + + /** + * @param array $parameter + * @return $this + */ + public function setParameter(array $parameter) + { + foreach ($parameter as $key => $value) { + if (array_key_exists($key, $this->parameter)) { + $this->parameter[$key] = $value; + } + } + + return $this; + } + + /** + * @return string + */ + public function getAction() + { + return Actions::ACTION_CHANNELS_INVITE; + } + + /** + * @param array $response + * @return array + */ + public function parseResponse(array $response) + { + return []; + } +} diff --git a/Slack/Client/Actions/ChannelsList.php b/Slack/Client/Actions/ChannelsList.php index 2e4bdb2..707daac 100644 --- a/Slack/Client/Actions/ChannelsList.php +++ b/Slack/Client/Actions/ChannelsList.php @@ -4,6 +4,9 @@ use DZunke\SlackBundle\Slack\Client\Actions; +/** + * @see https://api.slack.com/methods/channels.list + */ class ChannelsList implements ActionsInterface { diff --git a/Slack/Client/Actions/ChannelsSetTopic.php b/Slack/Client/Actions/ChannelsSetTopic.php index 0df3a2d..39315dd 100644 --- a/Slack/Client/Actions/ChannelsSetTopic.php +++ b/Slack/Client/Actions/ChannelsSetTopic.php @@ -4,6 +4,9 @@ use DZunke\SlackBundle\Slack\Client\Actions; +/** + * @see https://api.slack.com/methods/channels.setTopic + */ class ChannelsSetTopic implements ActionsInterface { diff --git a/Slack/Client/Actions/ChatPostMessage.php b/Slack/Client/Actions/ChatPostMessage.php index 8651acf..71964d4 100644 --- a/Slack/Client/Actions/ChatPostMessage.php +++ b/Slack/Client/Actions/ChatPostMessage.php @@ -6,6 +6,9 @@ use DZunke\SlackBundle\Slack\Entity\MessageAttachment as Attachment; use DZunke\SlackBundle\Slack\Messaging\Identity; +/** + * @see https://api.slack.com/methods/chat.postMessage + */ class ChatPostMessage implements ActionsInterface { /** diff --git a/Slack/Client/Actions/FilesUpload.php b/Slack/Client/Actions/FilesUpload.php index f2c1779..661d795 100644 --- a/Slack/Client/Actions/FilesUpload.php +++ b/Slack/Client/Actions/FilesUpload.php @@ -4,6 +4,9 @@ use DZunke\SlackBundle\Slack\Client\Actions; +/** + * @see https://api.slack.com/methods/files.upload + */ class FilesUpload implements ActionsInterface { diff --git a/Slack/Client/Actions/UsersList.php b/Slack/Client/Actions/UsersList.php new file mode 100644 index 0000000..815bd94 --- /dev/null +++ b/Slack/Client/Actions/UsersList.php @@ -0,0 +1,72 @@ + 1 + ]; + + /** + * @return array + */ + public function getRenderedRequestParams() + { + return $this->parameter; + } + + /** + * @param array $parameter + * @return $this + */ + public function setParameter(array $parameter) + { + foreach ($parameter as $key => $value) { + if (array_key_exists($key, $this->parameter)) { + $this->parameter[$key] = $value; + } + } + + return $this; + } + + /** + * @return string + */ + public function getAction() + { + return Actions::ACTION_USERS_LIST; + } + + /** + * @param array $response + * @return array + */ + public function parseResponse(array $response) + { + $users = []; + foreach ($response['members'] as $user) { + $users[$user['name']] = [ + 'id' => $user['id'], + 'name' => $user['name'], + 'deleted' => (bool)$user['deleted'], + 'real_name' => $user['profile']['real_name'], + 'email' => $user['profile']['email'], + 'is_bot' => (bool)$user['is_bot'], + 'presence' => isset($user['presence']) ? $user['presence'] : null + ]; + } + + return $users; + } +} diff --git a/Slack/Messaging.php b/Slack/Messaging.php index 1120e5e..551ea53 100644 --- a/Slack/Messaging.php +++ b/Slack/Messaging.php @@ -72,7 +72,7 @@ public function message($channel, $message, $identity, array $attachments = []) /** - * @param string $channel + * @param string|array $channel # String is DEPRECATED scince v1.3 - Deliver Array * @param string $title * @param string $file * @param string|null $comment @@ -84,18 +84,15 @@ public function upload($channel, $title, $file, $comment = null) return false; } + if (!is_array($channel)) { + @trigger_error('Channel as String is deprecated scince v1.3, please deliver an Array of Channels', E_USER_DEPRECATED); + $channel = [$channel]; + } + $params = []; $params['title'] = $title; $params['initial_comment'] = $comment; - $params['channels'] = null; - - $channelDiscover = new Channels($this->client); - $channelId = $channelDiscover->getId($channel); - - if (!empty($channelId)) { - $params['channels'] = $channelId; - } - + $params['channels'] = implode(',', $channel); $params['content'] = file_get_contents($file); $params['fileType'] = mime_content_type($file); $params['filename'] = basename($file); diff --git a/Slack/Users.php b/Slack/Users.php new file mode 100644 index 0000000..fa9770b --- /dev/null +++ b/Slack/Users.php @@ -0,0 +1,85 @@ +client = $client; + } + + /** + * @return Client + */ + public function getClient() + { + return $this->client; + } + + /** + * @return array + */ + public function getUsers() + { + return $this->client->send(Actions::ACTION_USERS_LIST)->getData(); + } + + /** + * @return array + */ + public function getActiveUsers() + { + return array_filter( + $this->getUsers(), + function ($user) { + return $user['deleted'] === false; + } + ); + } + + /** + * @return array + */ + public function getDeletedUsers() + { + return array_filter( + $this->getUsers(), + function ($user) { + return $user['deleted'] === true; + } + ); + } + + /** + * @param string $name + * @return null|array + */ + public function getUser($name) + { + $users = $this->getUsers(); + + return array_key_exists($name, $users) ? $users[$name] : null; + } + + /** + * @param string $name + * @return null|array + */ + public function getId($name) + { + $user = $this->getUser($name); + + return !is_null($user) ? $user['id'] : null; + } +}