├── .gitignore ├── .scrutinizer.yml ├── .travis.yml ├── LICENSE ├── README.md ├── box.json ├── bump-version.sh ├── composer.json ├── phpunit.xml.dist ├── slack └── src └── CL └── SlackCli ├── Command ├── AbstractApiCommand.php ├── AbstractCommand.php ├── ApiTestCommand.php ├── AuthTestCommand.php ├── ChannelsArchiveCommand.php ├── ChannelsCreateCommand.php ├── ChannelsHistoryCommand.php ├── ChannelsInfoCommand.php ├── ChannelsInviteCommand.php ├── ChannelsJoinCommand.php ├── ChannelsKickCommand.php ├── ChannelsLeaveCommand.php ├── ChannelsListCommand.php ├── ChannelsMarkCommand.php ├── ChannelsRenameCommand.php ├── ChannelsSetPurposeCommand.php ├── ChannelsSetTopicCommand.php ├── ChannelsUnarchiveCommand.php ├── ChatDeleteCommand.php ├── ChatPostMessageCommand.php ├── ChatUpdateCommand.php ├── ConfigEditCommand.php ├── ConfigGetCommand.php ├── ConfigListCommand.php ├── ConfigSetCommand.php ├── ConfigUnsetCommand.php ├── EmojiListCommand.php ├── FilesInfoCommand.php ├── FilesListCommand.php ├── FilesUploadCommand.php ├── GroupsArchiveCommand.php ├── GroupsCloseCommand.php ├── GroupsCreateChildCommand.php ├── GroupsCreateCommand.php ├── GroupsHistoryCommand.php ├── GroupsInviteCommand.php ├── GroupsKickCommand.php ├── GroupsLeaveCommand.php ├── GroupsListCommand.php ├── GroupsMarkCommand.php ├── GroupsOpenCommand.php ├── GroupsRenameCommand.php ├── GroupsSetPurposeCommand.php ├── GroupsSetTopicCommand.php ├── GroupsUnarchiveCommand.php ├── ImCloseCommand.php ├── ImHistoryCommand.php ├── ImListCommand.php ├── ImMarkCommand.php ├── ImOpenCommand.php ├── OauthAccessCommand.php ├── SearchAllCommand.php ├── SearchFilesCommand.php ├── SearchMessagesCommand.php ├── SelfUpdateCommand.php ├── StarsListCommand.php ├── UsersInfoCommand.php ├── UsersListCommand.php ├── UsersSetActiveCommand.php └── UsersSetPresenceCommand.php ├── Config ├── Config.php └── ConfigFactory.php ├── Console └── Application.php ├── Resources └── doc │ ├── contributing.md │ ├── installation.md │ └── usage.md └── Tests └── Command ├── AbstractApiCommandTest.php ├── AbstractCommandTest.php ├── ApiTestCommandTest.php ├── AuthTestCommandTest.php ├── ChannelsArchiveCommandTest.php ├── ChannelsCreateCommandTest.php ├── ChannelsHistoryCommandTest.php ├── ChannelsInfoCommandTest.php ├── ChannelsInviteCommandTest.php ├── ChannelsJoinCommandTest.php ├── ChannelsKickCommandTest.php ├── ChannelsLeaveCommandTest.php ├── ChannelsListCommandTest.php ├── ChannelsMarkCommandTest.php ├── ChannelsRenameCommandTest.php ├── ChannelsSetPurposeCommandTest.php ├── ChannelsSetTopicCommandTest.php ├── ChannelsUnarchiveCommandTest.php ├── ChatDeleteCommandTest.php ├── ChatPostMessageCommandTest.php ├── ChatUpdateCommandTest.php ├── ConfigEditCommandTest.php ├── ConfigGetCommandTest.php ├── ConfigListCommandTest.php ├── ConfigSetCommandTest.php └── ConfigUnsetCommandTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | composer.lock 3 | src/CL/SlackCli/Tests/config.json 4 | vendor/* 5 | manifest.phar 6 | slack.phar 7 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | before_commands: 2 | - 'composer install --no-interaction' 3 | 4 | filter: 5 | paths: 6 | - src/* 7 | excluded_paths: 8 | - src/CL/SlackCli/Resources/* 9 | - src/CL/SlackCli/Test/* 10 | - src/CL/SlackCli/Tests/* 11 | 12 | tools: 13 | external_code_coverage: 14 | timeout: 600 15 | php_analyzer: true 16 | php_code_sniffer: true 17 | php_cs_fixer: true 18 | php_loc: true 19 | php_mess_detector: true 20 | php_pdepend: true 21 | sensiolabs_security_checker: true 22 | php_cs_fixer: 23 | config: 24 | level: symfony 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | 5 | php: 6 | - 5.5 7 | - 5.6 8 | - 7.0 9 | 10 | matrix: 11 | fast_finish: true 12 | 13 | before_script: composer install 14 | 15 | script: ./bin/phpunit --coverage-clover=coverage.clover 16 | 17 | after_script: 18 | - if [ "$TRAVIS_PHP_VERSION" != "7.0" ]; then wget https://scrutinizer-ci.com/ocular.phar; fi 19 | - if [ "$TRAVIS_PHP_VERSION" != "7.0" ]; then php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Cas Leentfaar - https://github.com/cleentfaar 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -- 22 | 23 | PARTS OF THIS SOFTWARE CONTAIN CODE PRODUCED BY THIRD PARTIES, THEIR LICENSES ARE DISPLAYED BELOW 24 | 25 | -- 26 | 27 | COMPOSER 28 | 29 | Copyright (c) 2011 Nils Adermann, Jordi Boggiano 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to deal 33 | in the Software without restriction, including without limitation the rights 34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the Software is furnished 36 | to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in all 39 | copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 47 | THE SOFTWARE. 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slack CLI [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/cleentfaar/slack-cli/blob/master/LICENSE.md) 2 | 3 | Command-line application for interacting with the [Slack API library](https://github.com/cleentfaar/slack). 4 | Provides CLI commands for all of the API methods currently available using a single `phar` executable. 5 | 6 | [![Build Status](https://img.shields.io/travis/cleentfaar/slack-cli/master.svg?style=flat-square)](https://travis-ci.org/cleentfaar/slack-cli) 7 | [![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/cleentfaar/slack-cli.svg?style=flat-square)](https://scrutinizer-ci.com/g/cleentfaar/slack-cli/code-structure) 8 | [![Quality Score](https://img.shields.io/scrutinizer/g/cleentfaar/slack-cli.svg?style=flat-square)](https://scrutinizer-ci.com/g/cleentfaar/slack-cli) 9 | [![Latest Version](https://img.shields.io/github/release/cleentfaar/slack-cli.svg?style=flat-square)](https://github.com/cleentfaar/slack-cli/releases) 10 | [![Total Downloads](https://img.shields.io/packagist/dt/cleentfaar/slack-cli.svg?style=flat-square)](https://packagist.org/packages/cleentfaar/slack-cli) 11 | 12 | 13 | ### Quick look 14 | 15 | Sending a message to a Slack channel (in this case '#general') 16 | ```sh 17 | $ slack.phar chat:post-message general "Hello world!" 18 | ``` 19 | 20 | Update the application 21 | ```sh 22 | slack.phar self:update 23 | ``` 24 | 25 | Check out the documentation below for more examples and instructions on how to install the `.phar` file. 26 | 27 | 28 | ### Installation / Usage 29 | 30 | 1. Download the [`slack.phar`](http://cleentfaar.github.io/slack-cli/downloads/slack-latest.phar) executable or use the installer. 31 | 32 | ``` sh 33 | $ curl -sS http://cleentfaar.github.io/slack-cli/installer | php 34 | ``` 35 | 36 | 2. Run Slack CLI: `php slack.phar` 37 | 38 | 39 | #### Installation from Source 40 | 41 | To run tests, or develop Slack CLI itself, you must use the sources and not the phar 42 | file as described above. Before continuing, you should also install [Composer](https://getcomposer.org) either globally 43 | or in the cloned repository below. 44 | 45 | 1. Run `git clone https://github.com/cleentfaar/slack-cli.git` 46 | 2. Run Composer to get the dependencies: `cd slack-cli && composer install` 47 | 48 | You can now run Slack CLI by executing the `./slack` script: `php ./slack` 49 | 50 | 51 | #### Global installation (manual) 52 | 53 | Follow instructions [in the documentation](https://github.com/cleentfaar/slack-cli/blob/master/src/CL/SlackCli/Resources/doc/installation.md) 54 | 55 | 56 | ### Documentation 57 | 58 | - [Installation](https://github.com/cleentfaar/slack-cli/blob/master/src/CL/SlackCli/Resources/doc/installation.md) - Information on installing this package either globally or as a composer dependency. 59 | - [Usage](https://github.com/cleentfaar/slack-cli/blob/master/src/CL/SlackCli/Resources/doc/usage.md) - A few simple examples on how to use some of the console commands provided by this package. 60 | 61 | #### Detailed documentation 62 | 63 | This package only provides a command-line interface to access the Slack API methods; if you want to get your hands dirty 64 | on how to use the payloads and responses in your own application, check out the library that this package implements: [Slack API library](https://github.com/cleentfaar/slack-cli). 65 | 66 | 67 | ### Contributing 68 | 69 | Got a good idea for this project? Found a nasty bug that needs fixing? That's great! Before submitting your PR however, 70 | make sure it complies with the [contributing guide](https://github.com/cleentfaar/slack-cli/blob/master/src/CL/SlackCli/Resources/doc/contributing.md) to speed up the merging of your code. 71 | 72 | 73 | ### Related packages 74 | 75 | - [Slack](https://github.com/cleentfaar/slack) - Main library package consisting of the API client and model classes that adhere to the Slack API specs. 76 | - [SlackBundle](https://github.com/cleentfaar/CLSlackBundle) - Symfony Bundle providing integration with the [Slack API library](https://github.com/cleentfaar/slack) above. 77 | 78 | 79 | ### Attributions 80 | 81 | - The [Slack](https://slack.com/) staff, for making a great product and very clean API documentation. 82 | - [MattKetmo](https://github.com/MattKetmo), for his [very useful article](http://moquet.net/blog/distributing-php-cli/) 83 | on distributing CLI applications and his `bump-version.sh` script. 84 | - [Composer](https://github.com/composer/composer), for a shameless copy of their [installer script](https://getcomposer.org/installer) 85 | and relevant documentation. 86 | -------------------------------------------------------------------------------- /box.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": "slack.phar", 3 | "chmod": "0755", 4 | "main": "slack", 5 | "files": [ 6 | "LICENSE", 7 | "vendor/herrera-io/phar-update/res/schema.json" 8 | ], 9 | "finder": [ 10 | { 11 | "name": [ 12 | "*.php", 13 | "*.yml" 14 | ], 15 | "exclude": [ 16 | "Tests", 17 | "tests" 18 | ], 19 | "in": [ 20 | "vendor", 21 | "src" 22 | ] 23 | } 24 | ], 25 | "git-version": "git-version", 26 | "git-commit": "git-commit", 27 | "stub": true, 28 | "web": false 29 | } 30 | -------------------------------------------------------------------------------- /bump-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ $# -ne 1 ]; then 6 | echo "Usage: `basename $0` " 7 | exit 65 8 | fi 9 | 10 | 11 | # CHECK MASTER BRANCH 12 | CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) 13 | if [[ "$CURRENT_BRANCH" != "master" ]]; then 14 | echo "You have to be on master branch currently on $CURRENT_BRANCH . Aborting" 15 | exit 65 16 | fi 17 | 18 | # CHECK FORMAT OF THE TAG 19 | php -r "if(preg_match('/^\d+\.\d+\.\d+(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?\$/',\$argv[1])) exit(0) ;else{ echo 'format of version tag is not invalid' . PHP_EOL ; exit(1);}" $1 20 | 21 | 22 | # CHECK jsawk COMMAND 23 | command -v jsawk >/dev/null 2>&1 || { echo "Error : Command jsawk is not installed on the system"; echo "See : https://github.com/micha/jsawk "; echo "Exiting..." >&2; exit 65; } 24 | 25 | # CHECK js COMMAND 26 | command -v js >/dev/null 2>&1 || { echo "Error : Command js is not installed on the system"; echo "Should be fixed by installing spidermonkey "; echo "Exiting..." >&2; exit 65; } 27 | 28 | # CHECK box COMMAND 29 | command -v box >/dev/null 2>&1 || { echo "Error : Command box is not installed on the system"; echo "See : https://github.com/box-project/box2 "; echo "Exiting..." >&2; exit 65; } 30 | 31 | # CHECK python COMMAND 32 | command -v python >/dev/null 2>&1 || { echo "Error : Command python is not installed on the system"; echo "Exiting..." >&2; exit 65; } 33 | 34 | # CHECK THAT WE CAN CHANGE BRANCH 35 | git checkout gh-pages 36 | git checkout --quiet master 37 | 38 | 39 | TAG=$1 40 | 41 | 42 | # 43 | # Tag & build master branch 44 | # 45 | git checkout master 46 | git fetch --all 47 | git pull 48 | git tag ${TAG} 49 | box build 50 | 51 | # 52 | # Copy executable file into GH pages 53 | # 54 | git checkout gh-pages 55 | git fetch --all 56 | git pull 57 | 58 | cp slack.phar downloads/slack-${TAG}.phar 59 | cp -f slack.phar downloads/slack-latest.phar 60 | echo -n "${TAG}" > version 61 | git add downloads/slack-${TAG}.phar 62 | git add downloads/slack-latest.phar 63 | git add version 64 | 65 | SHA1=$(openssl sha1 slack.phar | awk '{ print $2 }') 66 | 67 | JSON='name:"slack.phar"' 68 | JSON="${JSON},sha1:\"${SHA1}\"" 69 | JSON="${JSON},url:\"http://cleentfaar.github.io/slack-cli/downloads/slack-${TAG}.phar\"" 70 | JSON="${JSON},version:\"${TAG}\"" 71 | 72 | if [ -f cliph.phar.pubkey ]; then 73 | cp cliph.phar.pubkey pubkeys/slack-${TAG}.phar.pubkeys 74 | git add pubkeys/slack-${TAG}.phar.pubkeys 75 | JSON="${JSON},publicKey:\"http://cleentfaar.github.io/slack-cli/pubkeys/slack-${TAG}.phar.pubkey\"" 76 | fi 77 | 78 | # 79 | # Update manifest 80 | # 81 | cat manifest.json | jsawk -a "this.push({${JSON}})" | python -mjson.tool > manifest.json.tmp 82 | mv manifest.json.tmp manifest.json 83 | git add manifest.json 84 | 85 | git commit -m "Bump version ${TAG}" 86 | 87 | # 88 | # Go back to master 89 | # 90 | git checkout master 91 | 92 | echo "New version created. Now you should run:" 93 | echo "git push origin gh-pages && git push --tags" 94 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cleentfaar/slack-cli", 3 | "description": "Command-line application for interacting with the Slack API.", 4 | "homepage": "http://cleentfaar.github.io/slack-cli/", 5 | "keywords": [ 6 | "slack", 7 | "command", 8 | "cli", 9 | "terminal" 10 | ], 11 | "type": "library", 12 | "license": "MIT", 13 | "authors": [ 14 | { 15 | "name": "Cas Leentfaar", 16 | "homepage": "https://github.com/cleentfaar", 17 | "email": "info@casleentfaar.com" 18 | } 19 | ], 20 | "bin": [ 21 | "slack" 22 | ], 23 | "require": { 24 | "php": ">=5.5", 25 | "cleentfaar/slack": "~0.20", 26 | "symfony/console": "^2.6|^3.0", 27 | "composer/composer": "^1.0", 28 | "herrera-io/phar-update": "^2.0" 29 | }, 30 | "require-dev": { 31 | "phpunit/phpunit": "^4.5|^5.0" 32 | }, 33 | "autoload": { 34 | "psr-4": { 35 | "CL\\SlackCli\\": "src/CL/SlackCli/" 36 | } 37 | }, 38 | "config": { 39 | "bin-dir": "bin" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ./src/CL/SlackCli/Tests/ 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /slack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | use CL\SlackCli\Command; 14 | use CL\SlackCli\Console\Application; 15 | 16 | if (version_compare(phpversion(), '5.4', '<')) { 17 | fwrite(STDERR, "PHP needs to be a minimum version of PHP 5.4\n"); 18 | exit(1); 19 | } 20 | 21 | // installed via composer? 22 | if (file_exists($a = __DIR__.'/../../autoload.php')) { 23 | require_once $a; 24 | } else { 25 | require_once __DIR__.'/vendor/autoload.php'; 26 | } 27 | 28 | $commands = [ 29 | new Command\ApiTestCommand(), 30 | new Command\AuthTestCommand(), 31 | new Command\ChannelsArchiveCommand(), 32 | new Command\ChannelsCreateCommand(), 33 | new Command\ChannelsHistoryCommand(), 34 | new Command\ChannelsInfoCommand(), 35 | new Command\ChannelsInviteCommand(), 36 | new Command\ChannelsJoinCommand(), 37 | new Command\ChannelsKickCommand(), 38 | new Command\ChannelsLeaveCommand(), 39 | new Command\ChannelsListCommand(), 40 | new Command\ChannelsMarkCommand(), 41 | new Command\ChannelsRenameCommand(), 42 | new Command\ChannelsSetPurposeCommand(), 43 | new Command\ChannelsSetTopicCommand(), 44 | new Command\ChannelsUnarchiveCommand(), 45 | new Command\ChatDeleteCommand(), 46 | new Command\ChatPostMessageCommand(), 47 | new Command\ChatUpdateCommand(), 48 | new Command\ConfigEditCommand(), 49 | new Command\ConfigGetCommand(), 50 | new Command\ConfigListCommand(), 51 | new Command\ConfigSetCommand(), 52 | new Command\ConfigUnsetCommand(), 53 | new Command\EmojiListCommand(), 54 | new Command\FilesInfoCommand(), 55 | new Command\FilesListCommand(), 56 | new Command\FilesUploadCommand(), 57 | new Command\GroupsArchiveCommand(), 58 | new Command\GroupsCloseCommand(), 59 | new Command\GroupsCreateChildCommand(), 60 | new Command\GroupsCreateCommand(), 61 | new Command\GroupsHistoryCommand(), 62 | new Command\GroupsInviteCommand(), 63 | new Command\GroupsKickCommand(), 64 | new Command\GroupsLeaveCommand(), 65 | new Command\GroupsListCommand(), 66 | new Command\GroupsMarkCommand(), 67 | new Command\GroupsOpenCommand(), 68 | new Command\GroupsRenameCommand(), 69 | new Command\GroupsSetPurposeCommand(), 70 | new Command\GroupsSetTopicCommand(), 71 | new Command\GroupsUnarchiveCommand(), 72 | new Command\ImCloseCommand(), 73 | new Command\ImHistoryCommand(), 74 | new Command\ImListCommand(), 75 | new Command\ImMarkCommand(), 76 | new Command\ImOpenCommand(), 77 | new Command\OauthAccessCommand(), 78 | new Command\SearchAllCommand(), 79 | new Command\SearchFilesCommand(), 80 | new Command\SearchMessagesCommand(), 81 | new Command\SelfUpdateCommand(), 82 | new Command\StarsListCommand(), 83 | new Command\UsersInfoCommand(), 84 | new Command\UsersListCommand(), 85 | new Command\UsersSetActiveCommand(), 86 | new Command\UsersSetPresenceCommand(), 87 | ]; 88 | 89 | $application = new Application(); 90 | $application->addCommands($commands); 91 | $application->run(); 92 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ApiTestCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ApiTestPayload; 15 | use CL\Slack\Payload\ApiTestPayloadResponse; 16 | use Symfony\Component\Console\Input\InputOption; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ApiTestCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * @var bool 25 | */ 26 | private $expectError = false; 27 | 28 | /** 29 | * {@inheritDoc} 30 | */ 31 | protected function configure() 32 | { 33 | parent::configure(); 34 | 35 | $this->setName('api:test'); 36 | $this->setDescription('Tests connecting with the Slack API using the token.'); 37 | $this->addOption('arguments', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Arguments to be tested in key:value format, such as "foo:bar"'); 38 | $this->addOption('error', null, InputOption::VALUE_REQUIRED, 'Optional error message to mock an error response from Slack with'); 39 | $this->setHelp(<<api:test command lets you connect with the Slack API for testing purposes. 41 | 42 | Testing arguments returned by Slack 43 | php bin/slack api.test --args="foo=bar&apple=pie" 44 | 45 | Testing an error response 46 | php bin/slack api.test --error="This is my error" 47 | 48 | For more information about the related API method, check out the official documentation: 49 | https://api.slack.com/methods/api.test 50 | EOT 51 | ); 52 | } 53 | 54 | /** 55 | * @return ApiTestPayload 56 | */ 57 | protected function createPayload() 58 | { 59 | $payload = new ApiTestPayload(); 60 | 61 | if ($this->input->getOption('arguments')) { 62 | $args = []; 63 | foreach ($this->input->getOption('arguments') as $keyValue) { 64 | list($key, $value) = explode(':', $keyValue); 65 | $args[$key] = $value; 66 | } 67 | 68 | $payload->replaceArguments($args); 69 | } 70 | 71 | if ($this->input->getOption('error')) { 72 | $this->expectError = true; 73 | $payload->setError($this->input->getOption('error')); 74 | } 75 | 76 | return $payload; 77 | } 78 | 79 | /** 80 | * {@inheritdoc} 81 | * 82 | * @param ApiTestPayloadResponse $payloadResponse 83 | */ 84 | protected function handleResponse($payloadResponse) 85 | { 86 | if ($this->expectError === true || $payloadResponse->isOk()) { 87 | $this->writeOk('Slack API seems to have responded correctly (no error expected, no error returned)'); 88 | $data = []; 89 | if (null !== $error = $payloadResponse->getError()) { 90 | $data['error'] = $error; 91 | } 92 | foreach ($payloadResponse->getArguments() as $key => $val) { 93 | if ($key == 'token') { 94 | continue; 95 | } 96 | 97 | $data['args'][$key] = $val; 98 | } 99 | $this->renderKeyValueTable($data); 100 | 101 | // force 0 so any error tested here won't trigger a failure 102 | return 0; 103 | } else { 104 | $this->writeError(sprintf( 105 | 'Slack API did not respond correctly (no error expected): %s', 106 | lcfirst($payloadResponse->getErrorExplanation()) 107 | )); 108 | 109 | return 1; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/AuthTestCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\AuthTestPayload; 15 | use CL\Slack\Payload\AuthTestPayloadResponse; 16 | use Symfony\Component\Console\Output\OutputInterface; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class AuthTestCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('auth:test'); 31 | $this->setDescription('Test authentication with the Slack API and, optionally, tells you who you are (use -v).'); 32 | $this->setHelp(<<auth:test command lets you test authenticating with the Slack API. 34 | 35 | Use the verbose option `-v` to also return information about the token's user. 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/auth.test 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return AuthTestPayload 45 | */ 46 | protected function createPayload() 47 | { 48 | return new AuthTestPayload(); 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | * 54 | * @param AuthTestPayloadResponse $payloadResponse 55 | */ 56 | protected function handleResponse($payloadResponse) 57 | { 58 | if ($payloadResponse->isOk()) { 59 | $this->writeOk('Successfully authenticated by the Slack API!'); 60 | if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { 61 | $data = [ 62 | 'User ID' => $payloadResponse->getUserId(), 63 | 'Username' => $payloadResponse->getUsername(), 64 | 'Team ID' => $payloadResponse->getTeamId(), 65 | 'Team' => $payloadResponse->getTeam(), 66 | ]; 67 | $this->renderKeyValueTable($data); 68 | } 69 | } else { 70 | $this->writeError(sprintf('Failed to be authenticated by the Slack API: %s', lcfirst($payloadResponse->getErrorExplanation()))); 71 | 72 | return 1; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsArchiveCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsArchivePayload; 15 | use CL\Slack\Payload\ChannelsArchivePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsArchiveCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:archive'); 31 | $this->setDescription('Archives a given Slack channel'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to archive'); 33 | $this->setHelp(<<channels:archive command let's you archive a given Slack channel. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/channels.archive 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return ChannelsArchivePayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new ChannelsArchivePayload(); 48 | $payload->setChannelId($this->input->getArgument('channel-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param ChannelsArchivePayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | $this->writeOk('Successfully archived channel!'); 62 | } else { 63 | $this->writeError(sprintf('Failed to archive channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsCreateCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsCreatePayload; 15 | use CL\Slack\Payload\ChannelsCreatePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class ChannelsCreateCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('channels:create'); 32 | $this->setDescription('Creates new Slack channel with the given name'); 33 | $this->addArgument('name', InputArgument::REQUIRED, 'The name of the channel to create (must not exist already)'); 34 | $this->setHelp(<<channels:create command let's you create a new Slack channel with the given name. 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/channels.create 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return ChannelsCreatePayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new ChannelsCreatePayload(); 49 | $payload->setName($this->input->getArgument('name')); 50 | 51 | return $payload; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | * 57 | * @param ChannelsCreatePayloadResponse $payloadResponse 58 | */ 59 | protected function handleResponse($payloadResponse) 60 | { 61 | if ($payloadResponse->isOk()) { 62 | $this->writeOk('Successfully created channel!'); 63 | if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { 64 | $channelData = $this->serializeObjectToArray($payloadResponse->getChannel()); 65 | $this->renderKeyValueTable($channelData); 66 | } 67 | } else { 68 | $this->writeError(sprintf('Failed to create channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsHistoryCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsHistoryPayload; 15 | use CL\Slack\Payload\ChannelsHistoryPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputOption; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class ChannelsHistoryCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('channels:history'); 32 | $this->setDescription('Returns a portion of messages/events from the specified channel (see `--help`)'); 33 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'Channel to fetch history for'); 34 | $this->addOption('latest', 'l', InputOption::VALUE_REQUIRED, 'Latest message timestamp to include in results'); 35 | $this->addOption('oldest', 'o', InputOption::VALUE_REQUIRED, 'Oldest message timestamp to include in results'); 36 | $this->addOption('count', 'c', InputOption::VALUE_REQUIRED, 'Number of messages to return, between 1 and 1000.'); 37 | $this->setHelp(<<channels:history command returns a portion of messages/events from the specified channel. 39 | To read the entire history for a channel, run the command with no `latest` or `oldest` options, and then continue paging 40 | using the instructions below. 41 | 42 | The messages array up to 100 messages between `--latest` and `--oldest`. If there were more than 100 messages between 43 | those two points, then has_more will be true. 44 | 45 | If a message has the same timestamp as latest or oldest it will not be included in the list. This allows a client to fetch 46 | all messages in a hole in channel history, by running the channels.history command with `--latest` 47 | set to the oldest message they have after the hole, and `--oldest` to the latest message they have before the hole. 48 | If the response includes `has_more` then the client can make another call, using the `ts` value of the final messages as 49 | the latest param to get the next page of messages. 50 | 51 | If there are more than 100 messages between the two timestamps then the messages returned are the ones closest to latest. 52 | In most cases an application will want the most recent messages and will page backward from there. If oldest is provided 53 | but not latest then the messages returned are those closest to oldest, allowing you to page forward through history if desired. 54 | 55 | If either of the latest or oldest arguments are provided then those timestamps will also be included in the output. 56 | 57 | For more information about the related API method, check out the official documentation: 58 | https://api.slack.com/methods/channels.history 59 | EOT 60 | ); 61 | } 62 | 63 | /** 64 | * @return ChannelsHistoryPayload 65 | */ 66 | protected function createPayload() 67 | { 68 | $payload = new ChannelsHistoryPayload(); 69 | $payload->setChannelId($this->input->getArgument('channel-id')); 70 | $payload->setLatest($this->input->getOption('latest')); 71 | $payload->setOldest($this->input->getOption('oldest')); 72 | $payload->setCount($this->input->getOption('count')); 73 | 74 | return $payload; 75 | } 76 | 77 | /** 78 | * {@inheritdoc} 79 | * 80 | * @param ChannelsHistoryPayloadResponse $payloadResponse 81 | */ 82 | protected function handleResponse($payloadResponse) 83 | { 84 | if ($payloadResponse->isOk()) { 85 | $this->writeOk('Successfully retrieved history'); 86 | $this->renderTable($payloadResponse->getMessages()); 87 | if ($payloadResponse->getLatest() !== null) { 88 | $this->output->writeln(sprintf('Latest: %s', $payloadResponse->getLatest())); 89 | } 90 | if ($payloadResponse->getHasMore() !== null) { 91 | $this->output->writeln(sprintf('Has more: %s', $payloadResponse->getHasMore() ? 'yes' : 'no')); 92 | } 93 | } else { 94 | $this->writeError(sprintf('Failed to retrieve history for this channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsInfoCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsInfoPayload; 15 | use CL\Slack\Payload\ChannelsInfoPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsInfoCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:info'); 31 | $this->setDescription('Returns information about a team channel.'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to get information on'); 33 | $this->setHelp(<<channels:info command returns information about a given channel. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/channels.info 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return ChannelsInfoPayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new ChannelsInfoPayload(); 48 | $payload->setChannelId($this->input->getArgument('channel-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param ChannelsInfoPayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | $data = $this->serializeObjectToArray($payloadResponse->getChannel()); 62 | $this->renderKeyValueTable($data); 63 | $this->writeOk('Successfully retrieved information about the channel!'); 64 | } else { 65 | $this->writeError(sprintf('Failed to retrieve information about the channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsInviteCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsInvitePayload; 15 | use CL\Slack\Payload\ChannelsInvitePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class ChannelsInviteCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('channels:invite'); 32 | $this->setDescription('Invites a user to a channel. The calling user must be a member of the channel.'); 33 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to invite the user to'); 34 | $this->addArgument('user-id', InputArgument::REQUIRED, 'The ID of the user to invite'); 35 | $this->setHelp(<<channels.invite command is used to invite a user to a channel. 37 | The calling user must be a member of the channel. 38 | 39 | For more information about the related API method, check out the official documentation: 40 | https://api.slack.com/methods/channels.invite 41 | EOT 42 | ); 43 | } 44 | 45 | /** 46 | * @return ChannelsInvitePayload 47 | */ 48 | protected function createPayload() 49 | { 50 | $payload = new ChannelsInvitePayload(); 51 | $payload->setChannelId($this->input->getArgument('channel-id')); 52 | $payload->setUserId($this->input->getArgument('user-id')); 53 | 54 | return $payload; 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | * 60 | * @param ChannelsInvitePayloadResponse $payloadResponse 61 | */ 62 | protected function handleResponse($payloadResponse) 63 | { 64 | if ($payloadResponse->isOk()) { 65 | $this->writeOk('Successfully invited user to the channel!'); 66 | if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { 67 | $this->output->writeln('Channel used:'); 68 | $data = $this->serializeObjectToArray($payloadResponse->getChannel()); 69 | $this->renderKeyValueTable($data); 70 | } 71 | } else { 72 | $this->writeError(sprintf('Failed to invite user to this channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsJoinCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsJoinPayload; 15 | use CL\Slack\Payload\ChannelsJoinPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class ChannelsJoinCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('channels:join'); 32 | $this->setDescription('Joins a channel with the token\'s user (creates channel if it doesn\'t exist)'); 33 | $this->addArgument('channel', InputArgument::REQUIRED, 'The name of the channel to join (or create if it doesn\'t exist yet)'); 34 | $this->setHelp(<<channels.join command is used to join a channel. 36 | If the channel does not exist, it is created. 37 | 38 | Unlike the other channels-commands, this command requires you to supply the NAME instead of the ID of the channel, 39 | because the channel might be created if it doesn't exist yet. 40 | 41 | For more information about the related API method, check out the official documentation: 42 | https://api.slack.com/methods/channels.join 43 | EOT 44 | ); 45 | } 46 | 47 | /** 48 | * @return ChannelsJoinPayload 49 | */ 50 | protected function createPayload() 51 | { 52 | $payload = new ChannelsJoinPayload(); 53 | $payload->setName($this->input->getArgument('channel')); 54 | 55 | return $payload; 56 | } 57 | 58 | /** 59 | * {@inheritdoc} 60 | * 61 | * @param ChannelsJoinPayloadResponse $payloadResponse 62 | */ 63 | protected function handleResponse($payloadResponse) 64 | { 65 | if ($payloadResponse->isOk()) { 66 | if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { 67 | if ($payloadResponse->isAlreadyInChannel()) { 68 | $this->writeError('You are already in this channel:'); 69 | } else { 70 | $this->writeOk('Successfully joined channel:'); 71 | } 72 | 73 | $data = $this->serializeObjectToArray($payloadResponse->getChannel()); 74 | $this->renderKeyValueTable($data); 75 | } 76 | } else { 77 | $this->writeError(sprintf('Failed to join channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsKickCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsInvitePayloadResponse; 15 | use CL\Slack\Payload\ChannelsKickPayload; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsKickCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:kick'); 31 | $this->setDescription('Removes (kicks) a given user from a given channel'); 32 | $this->addArgument('user-id', InputArgument::REQUIRED, 'The ID of the user to remove'); 33 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to remove the user from'); 34 | $this->setHelp(<<channels.kick command allows you to remove a given user from a given channel. 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/channels.kick 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return ChannelsKickPayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new ChannelsKickPayload(); 49 | $payload->setChannelId($this->input->getArgument('channel-id')); 50 | $payload->setUserId($this->input->getArgument('user-id')); 51 | 52 | return $payload; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | * 58 | * @param ChannelsInvitePayloadResponse $payloadResponse 59 | */ 60 | protected function handleResponse($payloadResponse) 61 | { 62 | if ($payloadResponse->isOk()) { 63 | $this->writeOk('Successfully kicked user from the channel!'); 64 | } else { 65 | $this->writeError(sprintf('Failed to kick user from the channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsLeaveCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsLeavePayload; 15 | use CL\Slack\Payload\ChannelsLeavePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsLeaveCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:leave'); 31 | $this->setDescription('Leave a channel (as the user of the token).'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to leav'); 33 | $this->setHelp(<<channels:leave command leaves a channel as the user of the token. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/channels.leave 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return ChannelsLeavePayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new ChannelsLeavePayload(); 48 | $payload->setChannelId($this->input->getArgument('channel-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param ChannelsLeavePayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | if ($payloadResponse->isNotInChannel()) { 62 | $this->writeError('Could not leave channel; not in channel'); 63 | } else { 64 | $this->writeOk('Successfully left channel!'); 65 | } 66 | } else { 67 | $this->writeError(sprintf('Failed to leave channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsListPayload; 15 | use CL\Slack\Payload\ChannelsListPayloadResponse; 16 | use Symfony\Component\Console\Input\InputOption; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsListCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:list'); 31 | $this->setDescription('Returns a list of all channels in your Slack team'); 32 | $this->addOption('exclude-archived', null, InputOption::VALUE_OPTIONAL, 'Don\'t return archived channels.'); 33 | $this->setHelp(<<channels:list command returns a list of all channels in your Slack team. 35 | This includes channels the caller is in, channels they are not currently in, and archived channels. 36 | The number of (non-deactivated) members in each channel is also returned. 37 | 38 | For more information about the related API method, check out the official documentation: 39 | https://api.slack.com/methods/channels.list 40 | EOT 41 | ); 42 | } 43 | 44 | /** 45 | * @return ChannelsListPayload 46 | */ 47 | protected function createPayload() 48 | { 49 | $payload = new ChannelsListPayload(); 50 | $payload->setExcludeArchived($this->input->getOption('exclude-archived')); 51 | 52 | return $payload; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | * 58 | * @param ChannelsListPayloadResponse $payloadResponse 59 | */ 60 | protected function handleResponse($payloadResponse) 61 | { 62 | if ($payloadResponse->isOk()) { 63 | $channels = $payloadResponse->getChannels(); 64 | $this->output->writeln(sprintf('Received %d channels...', count($channels))); 65 | if (!empty($channels)) { 66 | $rows = []; 67 | foreach ($payloadResponse->getChannels() as $channel) { 68 | $row = $this->serializeObjectToArray($channel); 69 | $row['purpose'] = !$channel->getPurpose() ?: $channel->getPurpose()->getValue(); 70 | $row['topic'] = !$channel->getTopic() ?: $channel->getTopic()->getValue(); 71 | 72 | $rows[] = $row; 73 | } 74 | $this->renderTable($rows, null); 75 | } else { 76 | $this->writeError('No channels seem to be assigned to your team... this is strange...'); 77 | } 78 | } else { 79 | $this->writeError(sprintf('Failed to list channels. %s', lcfirst($payloadResponse->getErrorExplanation()))); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsMarkCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsMarkPayload; 15 | use CL\Slack\Payload\ChannelsMarkPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsMarkCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:mark'); 31 | $this->setDescription('Moves the read cursor in a Slack channel'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'ID of the channel to set reading cursor in.'); 33 | $this->addArgument('timestamp', InputArgument::REQUIRED, 'Timestamp of the most recently seen message.'); 34 | $this->setHelp(<<channels:mark command is used to move the read cursor in a Slack channel. 36 | 37 | After making this call, the mark is saved to the database and broadcast via the message server to all open connections 38 | for the calling user. 39 | 40 | Clients should try to avoid making this call too often. When needing to mark a read position, a client should set a 41 | timer before making the call. In this way, any further updates needed during the timeout will not generate extra calls 42 | (just one per channel). This is useful for when reading scroll-back history, or following a busy live channel. 43 | 44 | A timeout of 5 seconds is a good starting point. Be sure to flush these calls on shutdown/logout. 45 | 46 | For more information about the related API method, check out the official documentation: 47 | https://api.slack.com/methods/channels.mark 48 | EOT 49 | ); 50 | } 51 | 52 | /** 53 | * @return ChannelsMarkPayload 54 | */ 55 | protected function createPayload() 56 | { 57 | $payload = new ChannelsMarkPayload(); 58 | $payload->setChannelId($this->input->getArgument('channel-id')); 59 | 60 | return $payload; 61 | } 62 | 63 | /** 64 | * {@inheritdoc} 65 | * 66 | * @param ChannelsMarkPayloadResponse $payloadResponse 67 | */ 68 | protected function handleResponse($payloadResponse) 69 | { 70 | if ($payloadResponse->isOk()) { 71 | $this->writeOk('Successfully moved the read cursor!'); 72 | } else { 73 | $this->writeError(sprintf('Failed to move the read cursor in the channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsRenameCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsRenamePayload; 15 | use CL\Slack\Payload\ChannelsRenamePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class ChannelsRenameCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('channels:rename'); 32 | $this->setDescription('Leave a channel (as the user of the token).'); 33 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to rename'); 34 | $this->addArgument('name', InputArgument::REQUIRED, 'The new name for this channel'); 35 | $this->setHelp(<<channels:rename command renames a team channel. 37 | 38 | The only people who can rename a channel are team admins, or the person that originally created the channel. 39 | Others will receive a "not_authorized" error. 40 | 41 | For more information about the related API method, check out the official documentation: 42 | https://api.slack.com/methods/channels.rename 43 | EOT 44 | ); 45 | } 46 | 47 | /** 48 | * @return ChannelsRenamePayload 49 | */ 50 | protected function createPayload() 51 | { 52 | $payload = new ChannelsRenamePayload(); 53 | $payload->setChannelId($this->input->getArgument('channel-id')); 54 | $payload->setName($this->input->getArgument('name')); 55 | 56 | return $payload; 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | * 62 | * @param ChannelsRenamePayloadResponse $payloadResponse 63 | */ 64 | protected function handleResponse($payloadResponse) 65 | { 66 | if ($payloadResponse->isOk()) { 67 | $this->writeOk('Successfully renamed channel!'); 68 | if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { 69 | $this->output->writeln('Renamed channel:'); 70 | $data = $this->serializeObjectToArray($payloadResponse->getChannel()); 71 | $this->renderKeyValueTable($data); 72 | } 73 | } else { 74 | $this->writeError(sprintf('Failed to rename channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsSetPurposeCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsSetPurposePayload; 15 | use CL\Slack\Payload\ChannelsSetPurposePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsSetPurposeCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:set-purpose'); 31 | $this->setDescription('Change the purpose of a channel. The calling user must be a member of the channel.'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to change the purpose of'); 33 | $this->addArgument('purpose', InputArgument::REQUIRED, 'The new purpose'); 34 | $this->setHelp(<<channels:set-purpose command changes the purpose of a channel. 36 | The calling user must be a member of the channel. 37 | 38 | For more information about the related API method, check out the official documentation: 39 | https://api.slack.com/methods/channels.setPurpose 40 | EOT 41 | ); 42 | } 43 | 44 | /** 45 | * @return ChannelsSetPurposePayload 46 | */ 47 | protected function createPayload() 48 | { 49 | $payload = new ChannelsSetPurposePayload(); 50 | $payload->setChannelId($this->input->getArgument('channel-id')); 51 | $payload->setPurpose($this->input->getArgument('purpose')); 52 | 53 | return $payload; 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | * 59 | * @param ChannelsSetPurposePayloadResponse $payloadResponse 60 | */ 61 | protected function handleResponse($payloadResponse) 62 | { 63 | if ($payloadResponse->isOk()) { 64 | $this->writeOk(sprintf('Successfully changed purpose of channel to: "%s"', $payloadResponse->getPurpose())); 65 | } else { 66 | $this->writeError(sprintf('Failed to change purpose of channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsSetTopicCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsSetTopicPayload; 15 | use CL\Slack\Payload\ChannelsSetTopicPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsSetTopicCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:set-topic'); 31 | $this->setDescription('Change the topic of a channel. The calling user must be a member of the channel.'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to change the topic of'); 33 | $this->addArgument('topic', InputArgument::REQUIRED, 'The new topic'); 34 | $this->setHelp(<<channels.setTopic command changes the topic of a channel. 36 | The calling user must be a member of the channel. 37 | 38 | For more information about the related API method, check out the official documentation: 39 | https://api.slack.com/methods/channels.setTopic 40 | EOT 41 | ); 42 | } 43 | 44 | /** 45 | * @return ChannelsSetTopicPayload 46 | */ 47 | protected function createPayload() 48 | { 49 | $payload = new ChannelsSetTopicPayload(); 50 | $payload->setChannelId($this->input->getArgument('channel-id')); 51 | $payload->setTopic($this->input->getArgument('topic')); 52 | 53 | return $payload; 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | * 59 | * @param ChannelsSetTopicPayloadResponse $payloadResponse 60 | */ 61 | protected function handleResponse($payloadResponse) 62 | { 63 | if ($payloadResponse->isOk()) { 64 | $this->writeOk(sprintf('Successfully changed topic of channel to: "%s"', $payloadResponse->getTopic())); 65 | } else { 66 | $this->writeError(sprintf('Failed to change topic of channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChannelsUnarchiveCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChannelsUnarchivePayload; 15 | use CL\Slack\Payload\ChannelsUnarchivePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChannelsUnarchiveCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('channels:unarchive'); 31 | $this->setDescription('Unarchives a channel. The token\'s user is automatically added to the channel'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel to archive'); 33 | $this->setHelp(<<channels:unarchive command unarchives a given channel. 35 | The user of the token is automatically added to the channel. 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/channels.unarchive 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return ChannelsUnarchivePayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new ChannelsUnarchivePayload(); 49 | $payload->setChannelId($this->input->getArgument('channel-id')); 50 | 51 | return $payload; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | * 57 | * @param ChannelsUnarchivePayloadResponse $payloadResponse 58 | */ 59 | protected function handleResponse($payloadResponse) 60 | { 61 | if ($payloadResponse->isOk()) { 62 | $this->writeOk('Successfully un-archived channel!'); 63 | } else { 64 | $this->writeError(sprintf('Failed to un-archive channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChatDeleteCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChatDeletePayload; 15 | use CL\Slack\Payload\ChatDeletePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChatDeleteCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('chat:delete'); 31 | $this->setDescription('Deletes a message from a given channel'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel containing the message to be deleted'); 33 | $this->addArgument('timestamp', InputArgument::REQUIRED, 'Timestamp of the message to be deleted'); 34 | $this->setHelp(<<chat:delete command deletes a message from a given channel. 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/chat.delete 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return ChatDeletePayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new ChatDeletePayload(); 49 | $payload->setChannelId($this->input->getArgument('channel-id')); 50 | $payload->setSlackTimestamp($this->input->getArgument('timestamp')); 51 | 52 | return $payload; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | * 58 | * @param ChatDeletePayloadResponse $payloadResponse 59 | */ 60 | protected function handleResponse($payloadResponse) 61 | { 62 | if ($payloadResponse->isOk()) { 63 | $this->writeOk('Successfully deleted message!'); 64 | } else { 65 | $this->writeError(sprintf('Failed to delete message: %s', lcfirst($payloadResponse->getErrorExplanation()))); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ChatUpdateCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ChatUpdatePayload; 15 | use CL\Slack\Payload\ChatUpdatePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ChatUpdateCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('chat:update'); 31 | $this->setDescription('Updates a message from a given channel'); 32 | $this->addArgument('channel-id', InputArgument::REQUIRED, 'The ID of the channel containing the message to be updated'); 33 | $this->addArgument('timestamp', InputArgument::REQUIRED, 'Timestamp of the message to be updated'); 34 | $this->addArgument('text', InputArgument::REQUIRED, 'New text for the message, using the default formatting rules'); 35 | $this->setHelp(<<chat:update command updates a message from a given channel. 37 | 38 | The new message uses the default formatting rules, which can be found here: https://api.slack.com/docs/formatting 39 | 40 | For more information about the related API method, check out the official documentation: 41 | https://api.slack.com/methods/chat.update 42 | EOT 43 | ); 44 | } 45 | 46 | /** 47 | * @return ChatUpdatePayload 48 | */ 49 | protected function createPayload() 50 | { 51 | $payload = new ChatUpdatePayload(); 52 | $payload->setChannelId($this->input->getArgument('channel-id')); 53 | $payload->setSlackTimestamp($this->input->getArgument('timestamp')); 54 | $payload->setText($this->input->getArgument('text')); 55 | 56 | return $payload; 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | * 62 | * @param ChatUpdatePayloadResponse $payloadResponse 63 | */ 64 | protected function handleResponse($payloadResponse) 65 | { 66 | if ($payloadResponse->isOk()) { 67 | $this->writeOk('Successfully updated message!'); 68 | } else { 69 | $this->writeError(sprintf('Failed to update message: %s', lcfirst($payloadResponse->getErrorExplanation()))); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ConfigEditCommand.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class ConfigEditCommand extends AbstractCommand 13 | { 14 | /** 15 | * {@inheritDoc} 16 | */ 17 | protected function configure() 18 | { 19 | parent::configure(); 20 | 21 | $this->setName('config:edit'); 22 | $this->setDescription('Edit config options'); 23 | 24 | $this->setHelp(<<config:edit command allows you to edit the Slack CLI settings using a pre-configured editor. 26 | 27 | To choose your editor you can set the "SLACK_CONFIG_EDITOR" environment variable. 28 | 29 | To get a list of configuration values in the file, use the `config:list` command: 30 | 31 | slack.phar config:list 32 | EOT 33 | ); 34 | } 35 | 36 | /** 37 | * {@inheritDoc} 38 | */ 39 | protected function execute(InputInterface $input, OutputInterface $output) 40 | { 41 | $editor = escapeshellcmd(getenv('SLACK_CONFIG_EDITOR')); 42 | if (!$editor) { 43 | if (defined('PHP_WINDOWS_VERSION_BUILD')) { 44 | $editor = 'notepad'; 45 | } else { 46 | foreach (['vim', 'vi', 'nano', 'pico', 'ed'] as $candidate) { 47 | if (exec('which ' . $candidate)) { 48 | $editor = $candidate; 49 | break; 50 | } 51 | } 52 | } 53 | } 54 | 55 | $file = $this->getConfigPath(); 56 | $to = defined('PHP_WINDOWS_VERSION_BUILD') ? '' : ' > `tty`'; 57 | $command = sprintf('%s %s%s', $editor, $file, $to); 58 | 59 | $this->output->writeln(sprintf('Editing `%s` using `%s`...', $file, $editor)); 60 | 61 | if (!$this->isTest()) { 62 | system($command); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ConfigGetCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use Symfony\Component\Console\Input\InputArgument; 15 | use Symfony\Component\Console\Input\InputInterface; 16 | use Symfony\Component\Console\Output\OutputInterface; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ConfigGetCommand extends AbstractCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('config:get'); 31 | $this->setDescription('Retrieves the value that is set for the given setting from the configuration'); 32 | $this->addArgument('setting', InputArgument::REQUIRED, 'The key to use'); 33 | $this->setHelp(<<config:get command retrieves the value that is set for the given setting from the configuration. 35 | 36 | To list all stored keys and values, use the config.list command. 37 | EOT 38 | ); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function execute(InputInterface $input, OutputInterface $output) 45 | { 46 | $key = $this->input->getArgument('setting'); 47 | 48 | if (!$this->getConfig()->has($key)) { 49 | $this->writeError(sprintf('There is no setting with that name in the configuration: `%s`', $key)); 50 | 51 | return 1; 52 | } 53 | 54 | $value = $this->getConfig()->get($key); 55 | 56 | $this->output->writeln(sprintf( 57 | 'Value of `%s` is %s', 58 | $key, 59 | is_null($value) ? 'NULL' : '`' . var_export($value, true) . '`' 60 | )); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ConfigListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use Symfony\Component\Console\Input\InputInterface; 15 | use Symfony\Component\Console\Output\OutputInterface; 16 | 17 | /** 18 | * @author Cas Leentfaar 19 | */ 20 | class ConfigListCommand extends AbstractCommand 21 | { 22 | /** 23 | * {@inheritDoc} 24 | */ 25 | protected function configure() 26 | { 27 | parent::configure(); 28 | 29 | $this->setName('config:list'); 30 | $this->setDescription('Lists all the keys and values from the global configuration'); 31 | $this->setHelp(<<config:list command lists all the keys and values from the global configuration. 33 | EOT 34 | ); 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function execute(InputInterface $input, OutputInterface $output) 41 | { 42 | $rows = $this->extractConfiguration($this->getConfig()->all(), $this->getConfig()->raw(), $output); 43 | 44 | $this->createKeyValueTable($rows)->render(); 45 | } 46 | 47 | /** 48 | * Extracts the contents of the configuration file recursively 49 | * 50 | * @param array $contents 51 | * @param array $rawContents 52 | * @param OutputInterface $output 53 | * @param string|null $k 54 | * @param array $currentRows 55 | * 56 | * @return array 57 | */ 58 | private function extractConfiguration( 59 | array $contents, 60 | array $rawContents, 61 | OutputInterface $output, 62 | $k = null, 63 | &$currentRows = [] 64 | ) { 65 | $origK = $k; 66 | foreach ($contents as $key => $value) { 67 | if ($k === null && !in_array($key, array('config'))) { 68 | continue; 69 | } 70 | 71 | $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null; 72 | 73 | if (is_array($value) && (!is_numeric(key($value)))) { 74 | $k .= preg_replace('{^config\.}', '', $key . '.'); 75 | $this->extractConfiguration($value, $rawVal, $output, $k, $currentRows); 76 | 77 | if (substr_count($k, '.') > 1) { 78 | $k = str_split($k, strrpos($k, '.', -2)); 79 | $k = $k[0] . '.'; 80 | } else { 81 | $k = $origK; 82 | } 83 | 84 | continue; 85 | } 86 | 87 | if (is_array($value)) { 88 | $value = array_map(function ($val) { 89 | return is_array($val) ? json_encode($val) : $val; 90 | }, $value); 91 | 92 | $value = '[' . implode(', ', $value) . ']'; 93 | } 94 | 95 | if (is_bool($value)) { 96 | $value = var_export($value, true); 97 | } 98 | 99 | if (is_string($rawVal) && $rawVal != $value) { 100 | $currentRows[$k . $key] = $rawVal . ' (' . $value . ')'; 101 | } else { 102 | $currentRows[$k . $key] = $value; 103 | } 104 | } 105 | 106 | return $currentRows; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ConfigSetCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use Symfony\Component\Console\Input\InputArgument; 15 | use Symfony\Component\Console\Input\InputInterface; 16 | use Symfony\Component\Console\Output\OutputInterface; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ConfigSetCommand extends AbstractCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('config:set'); 31 | $this->setDescription('Stores the given setting and value in the global configuration'); 32 | $this->addArgument('setting', InputArgument::REQUIRED, 'The setting to use'); 33 | $this->addArgument('value', InputArgument::REQUIRED, 'The value to set for this setting'); 34 | $this->setHelp(<<config:set command lets you store a given setting and value in the global configuration. 36 | 37 | To list all stored settings and values, use the config.list command. 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | public function execute(InputInterface $input, OutputInterface $output) 46 | { 47 | $setting = $this->input->getArgument('setting'); 48 | $value = $this->input->getArgument('value'); 49 | 50 | return $this->setConfig($setting, $value); 51 | } 52 | 53 | private function setConfig($setting, $value) 54 | { 55 | // handle config values 56 | $uniqueConfigValues = [ 57 | 'default_token' => ['is_string', function ($val) { 58 | return $val; 59 | }], 60 | ]; 61 | 62 | foreach ($uniqueConfigValues as $name => $callbacks) { 63 | if ($setting === $name) { 64 | list($validator, $normalizer) = $callbacks; 65 | 66 | if (true !== $validation = $validator($value)) { 67 | throw new \RuntimeException(sprintf( 68 | '"%s" is an invalid value' . ($validation ? ' (' . $validation . ')' : ''), 69 | $value 70 | )); 71 | } 72 | 73 | $this->getConfigSource()->addConfigSetting($setting, $normalizer($value)); 74 | 75 | $this->writeOk(sprintf( 76 | 'Successfully changed value of `%s` to `%s`!', 77 | $setting, 78 | $value 79 | )); 80 | 81 | return 0; 82 | } 83 | } 84 | 85 | $this->writeError(sprintf('There is no setting with that name in the configuration: `%s`', $setting)); 86 | 87 | return 1; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ConfigUnsetCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use Symfony\Component\Console\Input\InputArgument; 15 | use Symfony\Component\Console\Input\InputInterface; 16 | use Symfony\Component\Console\Output\OutputInterface; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ConfigUnsetCommand extends AbstractCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('config:unset'); 31 | $this->setDescription('Removes the given setting from the configuration'); 32 | $this->addArgument('setting', InputArgument::REQUIRED, 'The setting to remove'); 33 | $this->setHelp(<<config:unset command lets you remove a given setting (and it's value) in the global configuration. 35 | 36 | To list all stored settings and values, use the config.list command. 37 | EOT 38 | ); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function execute(InputInterface $input, OutputInterface $output) 45 | { 46 | $setting = $this->input->getArgument('setting'); 47 | 48 | if (!$this->getConfig()->has($setting)) { 49 | $this->writeComment(sprintf('No changes made; there is no setting defined with the name `%s`', $setting)); 50 | } else { 51 | $this->getConfigSource()->removeConfigSetting($setting); 52 | 53 | $this->writeOk(sprintf('Setting with name `%s` has been removed from the configuration!', $setting)); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/EmojiListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\EmojiListPayload; 15 | use CL\Slack\Payload\EmojiListPayloadResponse; 16 | 17 | /** 18 | * @author Cas Leentfaar 19 | */ 20 | class EmojiListCommand extends AbstractApiCommand 21 | { 22 | /** 23 | * {@inheritDoc} 24 | */ 25 | protected function configure() 26 | { 27 | parent::configure(); 28 | 29 | $this->setName('emoji:list'); 30 | $this->setDescription('Returns a list of all the custom emoji for your Slack team'); 31 | $this->setHelp(<<emoji:list command returns a list of all the custom emoji in your Slack team. 33 | 34 | The emoji property contains a map of name/url pairs, one for each custom emoji used by the team. 35 | 36 | The alias: pseudo-protocol will be used where the emoji is an alias, the string following the colon is 37 | the name of the other emoji this emoji is an alias to. 38 | 39 | For more information about the related API method, check out the official documentation: 40 | https://api.slack.com/methods/emoji.list 41 | EOT 42 | ); 43 | } 44 | 45 | /** 46 | * @return EmojiListPayload 47 | */ 48 | protected function createPayload() 49 | { 50 | $payload = new EmojiListPayload(); 51 | 52 | return $payload; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | * 58 | * @param EmojiListPayloadResponse $payloadResponse 59 | */ 60 | protected function handleResponse($payloadResponse) 61 | { 62 | if ($payloadResponse->isOk()) { 63 | $emojis = $payloadResponse->getEmojis(); 64 | $this->output->writeln(sprintf('Got %d emojis...', count($emojis))); 65 | if (!empty($emojis)) { 66 | $this->renderKeyValueTable($emojis, ['Name', 'URL']); 67 | } 68 | } else { 69 | $this->writeError(sprintf('Failed to fetch emojis: %s', lcfirst($payloadResponse->getErrorExplanation()))); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/FilesInfoCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\FilesInfoPayload; 15 | use CL\Slack\Payload\FilesInfoPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputOption; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class FilesInfoCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('files:info'); 32 | $this->setDescription('Returns information about a file in your Slack team'); 33 | $this->addArgument('file-id', InputArgument::REQUIRED, 'The ID of the file to get information on'); 34 | $this->addOption('count', 'c', InputOption::VALUE_REQUIRED, 'Number of items to return per page.'); 35 | $this->addOption('page', 'p', InputOption::VALUE_REQUIRED, 'Page number of results to return.'); 36 | $this->setHelp(<<files:info command returns information about a file in your team. 38 | 39 | Each comment object in the comments array contains details about a single comment. Comments are returned oldest first. 40 | 41 | The paging information contains the count of comments returned, the total number of comments, the page of results 42 | returned in this response and the total number of pages available. 43 | 44 | For more information about the related API method, check out the official documentation: 45 | https://api.slack.com/methods/files.info 46 | EOT 47 | ); 48 | } 49 | 50 | /** 51 | * @return FilesInfoPayload 52 | */ 53 | protected function createPayload() 54 | { 55 | $payload = new FilesInfoPayload(); 56 | $payload->setFileId($this->input->getArgument('file-id')); 57 | $payload->setCount($this->input->getOption('count')); 58 | $payload->setPage($this->input->getOption('page')); 59 | 60 | return $payload; 61 | } 62 | 63 | /** 64 | * {@inheritdoc} 65 | * 66 | * @param FilesInfoPayloadResponse $payloadResponse 67 | */ 68 | protected function handleResponse($payloadResponse) 69 | { 70 | if ($payloadResponse->isOk()) { 71 | $file = $payloadResponse->getFile(); 72 | $this->renderKeyValueTable($file); 73 | } else { 74 | $this->writeError(sprintf('Failed to fetch information about the file: %s', lcfirst($payloadResponse->getErrorExplanation()))); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/FilesListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\FilesListPayload; 15 | use CL\Slack\Payload\FilesListPayloadResponse; 16 | use Symfony\Component\Console\Input\InputOption; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class FilesListCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('files:list'); 31 | $this->setDescription('Returns a list of all files in your Slack team'); 32 | $this->addOption('user-id', 'u', InputOption::VALUE_REQUIRED, 'Filter files created by a single user.'); 33 | $this->addOption('from', null, InputOption::VALUE_REQUIRED, 'Filter files created after this timestamp (inclusive).'); 34 | $this->addOption('to', null, InputOption::VALUE_REQUIRED, 'Filter files created before this timestamp (inclusive).'); 35 | $this->addOption('types', null, InputOption::VALUE_REQUIRED, 'Filter files by type. You can pass multiple values in the types argument, like types=posts,snippets. The default value is all, which does not filter the list.'); 36 | $this->addOption('count', 'c', InputOption::VALUE_REQUIRED, 'Number of items to return per page.'); 37 | $this->addOption('page', 'p', InputOption::VALUE_REQUIRED, 'Page number of results to return.'); 38 | $this->setHelp(<<files:list command returns a list of files within the team. 40 | It can be filtered and sliced in various ways. 41 | 42 | The response contains a list of files, followed by some paging information. 43 | 44 | - Files are always returned with the most recent first. 45 | - Paging contains: 46 | - the count of files returned 47 | - the total number of files matching the filter(s) (if any were supplied) 48 | - the page of results returned in this response 49 | - the total number of pages available 50 | EOT 51 | ); 52 | } 53 | 54 | /** 55 | * @return FilesListPayload 56 | */ 57 | protected function createPayload() 58 | { 59 | $payload = new FilesListPayload(); 60 | $payload->setUserId($this->input->getOption('user-id')); 61 | $payload->setCount($this->input->getOption('count')); 62 | $payload->setPage($this->input->getOption('page')); 63 | $payload->setTimestampFrom($this->input->getOption('from')); 64 | $payload->setTimestampTo($this->input->getOption('to')); 65 | $payload->setTypes($this->input->getOption('types')); 66 | 67 | return $payload; 68 | } 69 | 70 | /** 71 | * {@inheritdoc} 72 | * 73 | * @param FilesListPayloadResponse $payloadResponse 74 | */ 75 | protected function handleResponse($payloadResponse) 76 | { 77 | if ($payloadResponse->isOk()) { 78 | $files = $payloadResponse->getFiles(); 79 | $this->writeOk(sprintf('Received %d files...', count($files))); 80 | if (!empty($files)) { 81 | $this->output->writeln('Listing files...'); 82 | $this->renderTable($files, null); 83 | } 84 | if ($payloadResponse->getPaging()) { 85 | $this->output->writeln('Paging...'); 86 | $this->renderKeyValueTable($payloadResponse->getPaging()); 87 | } 88 | } else { 89 | $this->writeError(sprintf('Failed to list files. %s', lcfirst($payloadResponse->getErrorExplanation()))); 90 | } 91 | } 92 | 93 | /** 94 | * @return string 95 | */ 96 | protected function getMethod() 97 | { 98 | return 'files.list'; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/FilesUploadCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\FilesUploadPayload; 15 | use CL\Slack\Payload\FilesUploadPayloadResponse; 16 | use Symfony\Component\Console\Input\InputOption; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class FilesUploadCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('files:upload'); 31 | $this->setDescription('Create or upload an existing file to Slack'); 32 | $this->addOption('path', 'p', InputOption::VALUE_REQUIRED, 'The path to the file to upload'); 33 | $this->addOption('content', 'c', InputOption::VALUE_REQUIRED, 'The raw content of the file to upload (alternative for `--path`)'); 34 | $this->addOption('filetype', 'ft', InputOption::VALUE_REQUIRED, 'Slack-internal file type identifier (e.g. `php`)'); 35 | $this->addOption('filename', 'fn', InputOption::VALUE_REQUIRED, 'Filename of the file'); 36 | $this->addOption('title', null, InputOption::VALUE_REQUIRED, 'Title of the file'); 37 | $this->addOption('initial-comment', null, InputOption::VALUE_REQUIRED, 'Initial comment to add to the file'); 38 | $this->addOption('channels', null, InputOption::VALUE_REQUIRED, 'Comma-separated list of channel IDs to share the file into'); 39 | $this->setHelp(<<files:upload command allows you to create or upload an existing file. 41 | 42 | The type of data in the file will be intuited from the filename and the magic bytes in the file, for supported formats. 43 | Using the `--filetype` option will override this behavior (if a valid type is given). 44 | 45 | The file can also be shared directly into channels on upload, by specifying the `--channels` option. 46 | Channel IDs should be comma separated if there is more than one. 47 | 48 | For more information about the related API method, check out the official documentation: 49 | https://api.slack.com/methods/files.upload 50 | EOT 51 | ); 52 | } 53 | 54 | /** 55 | * @return FilesUploadPayload 56 | */ 57 | protected function createPayload() 58 | { 59 | $payload = new FilesUploadPayload(); 60 | 61 | if ($this->input->getOption('path')) { 62 | $content = file_get_contents($this->input->getOption('path')); 63 | } elseif ($this->input->getOption('content')) { 64 | $content = $this->input->getOption('content'); 65 | } else { 66 | throw new \LogicException('Either the `--path` or the `--content` option must be used'); 67 | } 68 | 69 | $payload->setContent($content); 70 | $payload->setChannels($this->input->getOption('channels')); 71 | $payload->setFilename($this->input->getOption('filename')); 72 | $payload->setFileType($this->input->getOption('filetype')); 73 | $payload->setTitle($this->input->getOption('title')); 74 | 75 | return $payload; 76 | } 77 | 78 | /** 79 | * {@inheritdoc} 80 | * 81 | * @param FilesUploadPayloadResponse $payloadResponse 82 | */ 83 | protected function handleResponse($payloadResponse) 84 | { 85 | if ($payloadResponse->isOk()) { 86 | $this->writeOk('Successfully upload file to Slack:'); 87 | $file = $payloadResponse->getFile(); 88 | $this->renderKeyValueTable($file); 89 | } else { 90 | $this->writeError(sprintf('Failed to upload file: %s', lcfirst($payloadResponse->getErrorExplanation()))); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsArchiveCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsArchivePayload; 15 | use CL\Slack\Payload\GroupsArchivePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsArchiveCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:archive'); 31 | $this->setDescription('Archives a given Slack group'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of a private group to archive'); 33 | $this->setHelp(<<groups:archive command let's you archive a given Slack group. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/groups.archive 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return GroupsArchivePayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new GroupsArchivePayload(); 48 | $payload->setGroupId($this->input->getArgument('group-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param GroupsArchivePayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | $this->writeOk('Successfully archived group!'); 62 | } else { 63 | $this->writeError(sprintf('Failed to archive group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsCloseCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsClosePayload; 15 | use CL\Slack\Payload\GroupsClosePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsCloseCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:close'); 31 | $this->setDescription('Closes a given Slack group'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of a private group to close'); 33 | $this->setHelp(<<groups:close command let's you close a given Slack group. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/groups.close 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return GroupsClosePayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new GroupsClosePayload(); 48 | $payload->setGroupId($this->input->getArgument('group-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param GroupsClosePayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | if ($payloadResponse->isAlreadyClosed()) { 62 | $this->output->writeln('Couldn\'t close group: the group has already been closed'); 63 | } else { 64 | $this->writeOk('Successfully closed group!'); 65 | } 66 | } else { 67 | $this->writeError(sprintf('Failed to close group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsCreateChildCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsCreateChildPayload; 15 | use CL\Slack\Payload\GroupsCreateChildPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class GroupsCreateChildCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('groups:create-child'); 32 | $this->setDescription('This method creates a child group from an existing group (see `--help`)'); 33 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The name of the channel to create (must not exist already)'); 34 | $this->setHelp(<<groups:create-child command takes an existing private group and performs the following steps: 36 | 37 | - Renames the existing group (from "example" to "example-archived"). 38 | - Archives the existing group. 39 | - Creates a new group with the name of the existing group. 40 | - Adds all members of the existing group to the new group. 41 | 42 | This is useful when inviting a new member to an existing group while hiding all previous chat history from them. 43 | In this scenario you can run groups.createChild followed by groups.invite. 44 | 45 | The new group will have a special `parent_group` property pointing to the original archived group. 46 | This will only be returned for members of both groups, so will not be visible to any newly invited members. 47 | 48 | For more information about the related API method, check out the official documentation: 49 | https://api.slack.com/methods/groups.createChild 50 | EOT 51 | ); 52 | } 53 | 54 | /** 55 | * @return GroupsCreateChildPayload 56 | */ 57 | protected function createPayload() 58 | { 59 | $payload = new GroupsCreateChildPayload(); 60 | $payload->setGroupId($this->input->getArgument('group-id')); 61 | 62 | return $payload; 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | * 68 | * @param GroupsCreateChildPayloadResponse $payloadResponse 69 | */ 70 | protected function handleResponse($payloadResponse) 71 | { 72 | if ($payloadResponse->isOk()) { 73 | $this->writeOk('Successfully created child group!'); 74 | if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { 75 | $data = $this->serializeObjectToArray($payloadResponse->getGroup()); 76 | $this->renderKeyValueTable($data); 77 | } 78 | } else { 79 | $this->writeError(sprintf('Failed to create child group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsCreateCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsCreatePayload; 15 | use CL\Slack\Payload\GroupsCreatePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsCreateCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:create'); 31 | $this->setDescription('Creates a new Slack group with the given name'); 32 | $this->addArgument('name', InputArgument::REQUIRED, 'The name of the private group to create'); 33 | $this->setHelp(<<groups:create command let's you create a new Slack group. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/groups.create 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return GroupsCreatePayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new GroupsCreatePayload(); 48 | $payload->setName($this->input->getArgument('name')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param GroupsCreatePayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | $this->writeOk('Successfully created group!'); 62 | $this->renderKeyValueTable($payloadResponse->getGroup()); 63 | } else { 64 | $this->writeError(sprintf('Failed to create group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsInviteCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsInvitePayload; 15 | use CL\Slack\Payload\GroupsInvitePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class GroupsInviteCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('groups:invite'); 32 | $this->setDescription('Invites a user to a group. The token\'s user must be a member of the group'); 33 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of the group to invite the user into'); 34 | $this->addArgument('user-id', InputArgument::REQUIRED, 'The ID of the user to invite'); 35 | $this->setHelp(<<groups:invite command is used to invite a user to a private group. 37 | The calling user must be a member of the group. 38 | 39 | To invite a new member to a group without giving them access to the archives of the group 40 | run the groups.createChild command before inviting. 41 | 42 | For more information about the related API method, check out the official documentation: 43 | https://api.slack.com/methods/groups.invite 44 | EOT 45 | ); 46 | } 47 | 48 | /** 49 | * @return GroupsInvitePayload 50 | */ 51 | protected function createPayload() 52 | { 53 | $payload = new GroupsInvitePayload(); 54 | $payload->setGroupId($this->input->getArgument('group-id')); 55 | $payload->setUserId($this->input->getArgument('user-id')); 56 | 57 | return $payload; 58 | } 59 | 60 | /** 61 | * {@inheritdoc} 62 | * 63 | * @param GroupsInvitePayloadResponse $payloadResponse 64 | */ 65 | protected function handleResponse($payloadResponse) 66 | { 67 | if ($payloadResponse->isOk()) { 68 | if ($payloadResponse->getAlreadyInGroup()) { 69 | $this->output->writeln('The given user is already in this group'); 70 | } else { 71 | $this->writeOk('Successfully invited user to the group!'); 72 | if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { 73 | $this->output->writeln('Group used:'); 74 | $data = $this->serializeObjectToArray($payloadResponse->getGroup()); 75 | $this->renderKeyValueTable($data); 76 | } 77 | } 78 | } else { 79 | $this->writeError(sprintf('Failed to invite user: %s', lcfirst($payloadResponse->getErrorExplanation()))); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsKickCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsKickPayload; 15 | use CL\Slack\Payload\GroupsKickPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsKickCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:kick'); 31 | $this->setDescription('Removes (kicks) a given user from a group'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of the group to remove the user from'); 33 | $this->addArgument('user-id', InputArgument::REQUIRED, 'The ID of the user to remove'); 34 | $this->setHelp(<<groups:kick command allows you to remove another member from a grouo. 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/groups.kick 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return GroupsKickPayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new GroupsKickPayload(); 49 | $payload->setGroupId($this->input->getArgument('group-id')); 50 | $payload->setUserId($this->input->getArgument('user-id')); 51 | 52 | return $payload; 53 | } 54 | 55 | /** 56 | * {@inheritdoc} 57 | * 58 | * @param GroupsKickPayloadResponse $payloadResponse 59 | */ 60 | protected function handleResponse($payloadResponse) 61 | { 62 | if ($payloadResponse->isOk()) { 63 | $this->writeOk('Successfully kicked user from the group!'); 64 | } else { 65 | $this->writeError(sprintf('Failed to kick user from the group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsLeaveCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsLeavePayload; 15 | use CL\Slack\Payload\GroupsLeavePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsLeaveCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:leave'); 31 | $this->setDescription('Leave a group (as the user of the token).'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of the group to leave'); 33 | $this->setHelp(<<groups:leave command leaves a group as the user of the token. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/groups.leave 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return GroupsLeavePayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new GroupsLeavePayload(); 48 | $payload->setGroupId($this->input->getArgument('group-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param GroupsLeavePayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | $this->writeOk('Successfully left group!'); 62 | } else { 63 | $this->writeError(sprintf('Failed to leave group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsListPayload; 15 | use CL\Slack\Payload\GroupsListPayloadResponse; 16 | use Symfony\Component\Console\Input\InputOption; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsListCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:list'); 31 | $this->setDescription('Returns a list of all groups in your Slack team'); 32 | $this->addOption('exclude-archived', null, InputOption::VALUE_OPTIONAL, 'Don\'t return archived groups.'); 33 | $this->setHelp(<<https://api.slack.com/methods/groups.list 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return GroupsListPayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new GroupsListPayload(); 49 | $payload->setExcludeArchived($this->input->getOption('exclude-archived')); 50 | 51 | return $payload; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | * 57 | * @param GroupsListPayloadResponse $payloadResponse 58 | */ 59 | protected function handleResponse($payloadResponse) 60 | { 61 | if ($payloadResponse->isOk()) { 62 | $groups = $payloadResponse->getGroups(); 63 | $this->output->writeln(sprintf('Received %d groups...', count($groups))); 64 | if (!empty($groups)) { 65 | $rows = []; 66 | foreach ($payloadResponse->getGroups() as $group) { 67 | $row = $this->serializeObjectToArray($group); 68 | $row['purpose'] = !$group->getPurpose() ?: $group->getPurpose()->getValue(); 69 | $row['topic'] = !$group->getTopic() ?: $group->getTopic()->getValue(); 70 | 71 | $rows[] = $row; 72 | } 73 | $this->renderTable($rows, null); 74 | $this->writeOk('Finished listing groups'); 75 | } else { 76 | $this->writeComment('No groups to list'); 77 | } 78 | } else { 79 | $this->writeError(sprintf('Failed to list groups. %s', lcfirst($payloadResponse->getErrorExplanation()))); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsMarkCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsMarkPayload; 15 | use CL\Slack\Payload\GroupsMarkPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsMarkCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:mark'); 31 | $this->setDescription('Moves the read cursor in a Slack group'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'ID of the group to set reading cursor in.'); 33 | $this->addArgument('timestamp', InputArgument::REQUIRED, 'Timestamp of the most recently seen message.'); 34 | $this->setHelp(<<groups.mark command is used to move the read cursor in a Slack group. 36 | 37 | After running this command, the mark is saved to the database and broadcast via the message server to all open connections 38 | for the token's user. 39 | 40 | You should try to avoid running this command too often. When needing to mark a read position, you should set a timer 41 | before running the command. In this way, any further updates needed during the timeout will not generate extra calls 42 | (just one per channel). 43 | 44 | This is useful for when reading scroll-back history, or following a busy live channel. A timeout of 5 seconds is a good 45 | starting point. Be sure to flush these calls on shutdown/logout. 46 | 47 | For more information about the related API method, check out the official documentation: 48 | https://api.slack.com/methods/groups.mark 49 | EOT 50 | ); 51 | } 52 | 53 | /** 54 | * @return GroupsMarkPayload 55 | */ 56 | protected function createPayload() 57 | { 58 | $payload = new GroupsMarkPayload(); 59 | $payload->setGroupId($this->input->getArgument('group-id')); 60 | $payload->setSlackTimestamp($this->input->getArgument('timestamp')); 61 | 62 | return $payload; 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | * 68 | * @param GroupsMarkPayloadResponse $payloadResponse 69 | */ 70 | protected function handleResponse($payloadResponse) 71 | { 72 | if ($payloadResponse->isOk()) { 73 | $this->writeOk('Successfully moved the read cursor!'); 74 | } else { 75 | $this->writeError(sprintf('Failed to move the read cursor in the group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsOpenCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsOpenPayload; 15 | use CL\Slack\Payload\GroupsOpenPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsOpenCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:open'); 31 | $this->setDescription('Opens a given Slack group'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of a private group to open'); 33 | $this->setHelp(<<groups.open command let's you open a given Slack group. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/groups.open 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return GroupsOpenPayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new GroupsOpenPayload(); 48 | $payload->setGroupId($this->input->getArgument('group-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param GroupsOpenPayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | if ($payloadResponse->isAlreadyOpen()) { 62 | $this->output->writeln('Couldn\'t open group: the group has already been opened'); 63 | } else { 64 | $this->writeOk('Successfully opened group!'); 65 | } 66 | } else { 67 | $this->writeError(sprintf('Failed to open group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsRenameCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsRenamePayload; 15 | use CL\Slack\Payload\GroupsRenamePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Output\OutputInterface; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class GroupsRenameCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('groups:rename'); 32 | $this->setDescription('Leave a group (as the user of the token).'); 33 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of the group to rename'); 34 | $this->addArgument('name', InputArgument::REQUIRED, 'The new name for this group'); 35 | $this->setHelp(<<groups:rename command renames a team group. 37 | 38 | The only people who can rename a group are team admins, or the person that originally created the group. 39 | Others will receive a "not_authorized" error. 40 | 41 | For more information about the related API method, check out the official documentation: 42 | https://api.slack.com/methods/groups.rename 43 | EOT 44 | ); 45 | } 46 | 47 | /** 48 | * @return GroupsRenamePayload 49 | */ 50 | protected function createPayload() 51 | { 52 | $payload = new GroupsRenamePayload(); 53 | $payload->setGroupId($this->input->getArgument('group-id')); 54 | $payload->setName($this->input->getArgument('name')); 55 | 56 | return $payload; 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | * 62 | * @param GroupsRenamePayloadResponse $payloadResponse 63 | */ 64 | protected function handleResponse($payloadResponse) 65 | { 66 | if ($payloadResponse->isOk()) { 67 | $this->writeOk('Successfully renamed group!'); 68 | if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) { 69 | $this->output->writeln('Renamed group:'); 70 | $data = $this->serializeObjectToArray($payloadResponse->getGroup()); 71 | $this->renderKeyValueTable($data); 72 | } 73 | } else { 74 | $this->writeError(sprintf('Failed to leave group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsSetPurposeCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsSetPurposePayload; 15 | use CL\Slack\Payload\GroupsSetPurposePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsSetPurposeCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:set-purpose'); 31 | $this->setDescription('Change the purpose of a group. The calling user must be a member of the group.'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of the group to change the purpose of'); 33 | $this->addArgument('purpose', InputArgument::REQUIRED, 'The new purpose'); 34 | $this->setHelp(<<groups:set-purpose command changes the purpose of a group. 36 | The calling user must be a member of the group. 37 | 38 | For more information about the related API method, check out the official documentation: 39 | https://api.slack.com/methods/groups.setPurpose 40 | EOT 41 | ); 42 | } 43 | 44 | /** 45 | * @return GroupsSetPurposePayload 46 | */ 47 | protected function createPayload() 48 | { 49 | $payload = new GroupsSetPurposePayload(); 50 | $payload->setGroupId($this->input->getArgument('group-id')); 51 | $payload->setPurpose($this->input->getArgument('purpose')); 52 | 53 | return $payload; 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | * 59 | * @param GroupsSetPurposePayloadResponse $payloadResponse 60 | */ 61 | protected function handleResponse($payloadResponse) 62 | { 63 | if ($payloadResponse->isOk()) { 64 | $this->writeOk(sprintf('Successfully changed purpose of group to: "%s"', $payloadResponse->getPurpose())); 65 | } else { 66 | $this->writeError(sprintf('Failed to change purpose of group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsSetTopicCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsSetTopicPayload; 15 | use CL\Slack\Payload\GroupsSetTopicPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsSetTopicCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:set-topic'); 31 | $this->setDescription('Change the topic of a group. The calling user must be a member of the group.'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of the group to change the topic of'); 33 | $this->addArgument('topic', InputArgument::REQUIRED, 'The new topic'); 34 | $this->setHelp(<<groups:set-topic command changes the topic of a group. 36 | The calling user must be a member of the group. 37 | 38 | For more information about the related API method, check out the official documentation: 39 | https://api.slack.com/methods/groups.setTopic 40 | EOT 41 | ); 42 | } 43 | 44 | /** 45 | * @return GroupsSetTopicPayload 46 | */ 47 | protected function createPayload() 48 | { 49 | $payload = new GroupsSetTopicPayload(); 50 | $payload->setGroupId($this->input->getArgument('group-id')); 51 | $payload->setTopic($this->input->getArgument('topic')); 52 | 53 | return $payload; 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | * 59 | * @param GroupsSetTopicPayloadResponse $payloadResponse 60 | */ 61 | protected function handleResponse($payloadResponse) 62 | { 63 | if ($payloadResponse->isOk()) { 64 | $this->writeOk(sprintf('Successfully changed topic of group to: "%s"', $payloadResponse->getTopic())); 65 | } else { 66 | $this->writeError(sprintf('Failed to change topic of group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/GroupsUnarchiveCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\GroupsUnarchivePayload; 15 | use CL\Slack\Payload\GroupsUnarchivePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class GroupsUnarchiveCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('groups:unarchive'); 31 | $this->setDescription('Unarchives a group. The token\'s user is automatically added to the group'); 32 | $this->addArgument('group-id', InputArgument::REQUIRED, 'The ID of the group to archive'); 33 | $this->setHelp(<<groups:unarchive command unarchives a given group. 35 | The user of the token is automatically added to the group. 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/groups.unarchive 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return GroupsUnarchivePayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new GroupsUnarchivePayload(); 49 | $payload->setGroupId($this->input->getArgument('group-id')); 50 | 51 | return $payload; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | * 57 | * @param GroupsUnarchivePayloadResponse $payloadResponse 58 | */ 59 | protected function handleResponse($payloadResponse) 60 | { 61 | if ($payloadResponse->isOk()) { 62 | $this->writeOk('Successfully un-archived group!'); 63 | } else { 64 | $this->writeError(sprintf('Failed to un-archive group: %s', lcfirst($payloadResponse->getErrorExplanation()))); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ImCloseCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ImClosePayload; 15 | use CL\Slack\Payload\ImClosePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputInterface; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class ImCloseCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('im:close'); 32 | $this->setDescription('Closes a given Slack IM channel'); 33 | $this->addArgument('im-id', InputArgument::REQUIRED, 'The ID of an IM channel to close'); 34 | $this->setHelp(<<im:close command let's you close a IM channel 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/im.close 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return ImClosePayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new ImClosePayload(); 49 | $payload->setImId($this->input->getArgument('im-id')); 50 | 51 | return $payload; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | * 57 | * @param ImClosePayloadResponse $payloadResponse 58 | */ 59 | protected function handleResponse($payloadResponse) 60 | { 61 | if ($payloadResponse->isOk()) { 62 | if ($payloadResponse->isAlreadyClosed()) { 63 | $this->output->writeln('Couldn\'t close IM channel: the channel has already been closed'); 64 | } else { 65 | $this->writeOk('Successfully closed IM channel!'); 66 | } 67 | } else { 68 | $this->writeError(sprintf('Failed to close IM channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ImHistoryCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ImHistoryPayload; 15 | use CL\Slack\Payload\ImHistoryPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputOption; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class ImHistoryCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('im:history'); 32 | $this->setDescription('Returns a portion of messages/events from the specified im (see `--help`)'); 33 | $this->addArgument('im-id', InputArgument::REQUIRED, 'ID of the IM channel to fetch history for'); 34 | $this->addOption('latest', 'l', InputOption::VALUE_REQUIRED, 'Latest message timestamp to include in results'); 35 | $this->addOption('oldest', 'o', InputOption::VALUE_REQUIRED, 'Oldest message timestamp to include in results'); 36 | $this->addOption('count', 'c', InputOption::VALUE_REQUIRED, 'Number of messages to return, between 1 and 1000.'); 37 | $this->setHelp(<<im:history command returns a portion of messages/events from the specified im. 39 | To read the entire history for a im, run the command with no `latest` or `oldest` options, and then continue paging 40 | using the instructions below. 41 | 42 | The messages array up to 100 messages between `--latest` and `--oldest`. If there were more than 100 messages between 43 | those two points, then has_more will be true. 44 | 45 | If a message has the same timestamp as latest or oldest it will not be included in the list. This allows a client to fetch 46 | all messages in a hole in im history, by running the im.history command with `--latest` 47 | set to the oldest message they have after the hole, and `--oldest` to the latest message they have before the hole. 48 | If the response includes `has_more` then the client can make another call, using the `ts` value of the final messages as 49 | the latest param to get the next page of messages. 50 | 51 | If there are more than 100 messages between the two timestamps then the messages returned are the ones closest to latest. 52 | In most cases an application will want the most recent messages and will page backward from there. If oldest is provided 53 | but not latest then the messages returned are those closest to oldest, allowing you to page forward through history if desired. 54 | 55 | If either of the latest or oldest arguments are provided then those timestamps will also be included in the output. 56 | 57 | For more information about the related API method, check out the official documentation: 58 | https://api.slack.com/methods/im.history 59 | EOT 60 | ); 61 | } 62 | 63 | /** 64 | * @return ImHistoryPayload 65 | */ 66 | protected function createPayload() 67 | { 68 | $payload = new ImHistoryPayload(); 69 | $payload->setImId($this->input->getArgument('im-id')); 70 | $payload->setLatest($this->input->getOption('latest')); 71 | $payload->setOldest($this->input->getOption('oldest')); 72 | $payload->setCount($this->input->getOption('count')); 73 | 74 | return $payload; 75 | } 76 | 77 | /** 78 | * {@inheritdoc} 79 | * 80 | * @param ImHistoryPayloadResponse $payloadResponse 81 | */ 82 | protected function handleResponse($payloadResponse) 83 | { 84 | if ($payloadResponse->isOk()) { 85 | $this->writeOk('Successfully retrieved history'); 86 | $this->renderTable($payloadResponse->getMessages()); 87 | if ($payloadResponse->getLatest() !== null) { 88 | $this->output->writeln(sprintf('Latest: %s', $payloadResponse->getLatest())); 89 | } 90 | if ($payloadResponse->getHasMore() !== null) { 91 | $this->output->writeln(sprintf('Has more: %s', $payloadResponse->getHasMore() ? 'yes' : 'no')); 92 | } 93 | } else { 94 | $this->writeError(sprintf('Failed to retrieve history for this IM channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ImListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ImListPayload; 15 | use CL\Slack\Payload\ImListPayloadResponse; 16 | use Symfony\Component\Console\Input\InputOption; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ImListCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('im:list'); 31 | $this->setDescription('Returns a list of all IM channels in your Slack team'); 32 | $this->addOption('exclude-archived', null, InputOption::VALUE_OPTIONAL, 'Don\'t return archived IM channels.'); 33 | $this->setHelp(<<im:list command returns a list of all IM channels in your Slack team. 35 | This includes channels the caller is in, channels they are not currently in, and archived channels. 36 | The number of (non-deactivated) members in each channel is also returned. 37 | EOT 38 | ); 39 | } 40 | 41 | /** 42 | * @return ImListPayload 43 | */ 44 | protected function createPayload() 45 | { 46 | $payload = new ImListPayload(); 47 | $payload->setExcludeArchived($this->input->getOption('exclude-archived')); 48 | 49 | return $payload; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | * 55 | * @param ImListPayloadResponse $payloadResponse 56 | */ 57 | protected function handleResponse($payloadResponse) 58 | { 59 | if ($payloadResponse->isOk()) { 60 | $channels = $payloadResponse->getImChannels(); 61 | if (!empty($channels)) { 62 | $this->renderTable($channels, null); 63 | $this->writeOk('Finished listing channels'); 64 | } else { 65 | $this->writeComment('No IM channels to list'); 66 | } 67 | } else { 68 | $this->writeError(sprintf('Failed to list channels. %s', lcfirst($payloadResponse->getErrorExplanation()))); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ImMarkCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ImMarkPayload; 15 | use CL\Slack\Payload\ImMarkPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ImMarkCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('im:mark'); 31 | $this->setDescription('Moves the read cursor in a Slack IM channel'); 32 | $this->addArgument('im-id', InputArgument::REQUIRED, 'ID of the IM channel to set reading cursor in.'); 33 | $this->addArgument('timestamp', InputArgument::REQUIRED, 'Timestamp of the most recently seen message.'); 34 | $this->setHelp(<<im:mark command is used to move the read cursor in a Slack im. 36 | 37 | After making this call, the mark is saved to the database and broadcast via the message server to all open connections 38 | for the calling user. 39 | 40 | Clients should try to avoid making this call too often. When needing to mark a read position, a client should set a 41 | timer before making the call. In this way, any further updates needed during the timeout will not generate extra calls 42 | (just one per im). This is useful for when reading scroll-back history, or following a busy live im. 43 | 44 | A timeout of 5 seconds is a good starting point. Be sure to flush these calls on shutdown/logout. 45 | 46 | For more information about the related API method, check out the official documentation: 47 | https://api.slack.com/methods/im.mark 48 | EOT 49 | ); 50 | } 51 | 52 | /** 53 | * @return ImMarkPayload 54 | */ 55 | protected function createPayload() 56 | { 57 | $payload = new ImMarkPayload(); 58 | $payload->setImId($this->input->getArgument('im-id')); 59 | $payload->setSlackTimestamp($this->input->getArgument('timestamp')); 60 | 61 | return $payload; 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | * 67 | * @param ImMarkPayloadResponse $payloadResponse 68 | */ 69 | protected function handleResponse($payloadResponse) 70 | { 71 | if ($payloadResponse->isOk()) { 72 | $this->writeOk('Successfully moved the read cursor!'); 73 | } else { 74 | $this->writeError(sprintf('Failed to move the read cursor in the IM channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/ImOpenCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\ImOpenPayload; 15 | use CL\Slack\Payload\ImOpenPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class ImOpenCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('im:open'); 31 | $this->setDescription('Opens a Slack IM channel with another user'); 32 | $this->addArgument('user-id', InputArgument::REQUIRED, 'ID of the user to open a direct message channel with'); 33 | $this->setHelp(<<im:open command let's you open a Slack IM channel. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/im.open 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return ImOpenPayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new ImOpenPayload(); 48 | $payload->setUserId($this->input->getArgument('user-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param ImOpenPayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | if ($payloadResponse->isAlreadyOpen()) { 62 | $this->output->writeln('Couldn\'t open IM channel: the IM has already been opened'); 63 | } else { 64 | $this->writeOk('Successfully opened IM channel!'); 65 | } 66 | } else { 67 | $this->writeError(sprintf('Failed to open IM channel: %s', lcfirst($payloadResponse->getErrorExplanation()))); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/OauthAccessCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\OauthAccessPayload; 15 | use CL\Slack\Payload\OauthAccessPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputOption; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class OauthAccessCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('oauth:access'); 32 | $this->setDescription('Exchange a temporary OAuth code for an API access token'); 33 | $this->addArgument('client-id', InputArgument::REQUIRED, 'Issued when you created your application'); 34 | $this->addArgument('client-secret', InputArgument::REQUIRED, 'Issued when you created your application'); 35 | $this->addArgument('code', InputArgument::REQUIRED, 'The code param returned via the OAuth callback'); 36 | $this->addOption('redirect-uri', null, InputOption::VALUE_REQUIRED, 'This must match the originally submitted URI (if one was sent)'); 37 | $this->setHelp(<<oauth:access command allows you to exchange a temporary OAuth code for an API access token. 39 | This is used as part of the OAuth authentication flow. 40 | 41 | For more information about the related API method, check out the official documentation: 42 | https://api.slack.com/methods/oauth.access 43 | EOT 44 | ); 45 | } 46 | 47 | /** 48 | * @return OauthAccessPayload 49 | */ 50 | protected function createPayload() 51 | { 52 | $payload = new OauthAccessPayload(); 53 | $payload->setClientId($this->input->getArgument('client-id')); 54 | $payload->setClientSecret($this->input->getArgument('client-secret')); 55 | $payload->setCode($this->input->getArgument('code')); 56 | $payload->setRedirectUri($this->input->getOption('redirect-uri')); 57 | 58 | return $payload; 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | * 64 | * @param OauthAccessPayloadResponse $payloadResponse 65 | */ 66 | protected function handleResponse($payloadResponse) 67 | { 68 | if ($payloadResponse->isOk()) { 69 | $this->writeOk('Successfully authenticated through oauth!'); 70 | $this->output->writeln('Access token: %s', $payloadResponse->getAccessToken()); 71 | $this->output->writeln('Scope: %s', $payloadResponse->getScope()); 72 | } else { 73 | $this->writeError(sprintf('Failed to be authenticated through oauth. %s', lcfirst($payloadResponse->getErrorExplanation()))); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/SearchAllCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\SearchAllPayload; 15 | use CL\Slack\Payload\SearchAllPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputOption; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class SearchAllCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('search:all'); 32 | $this->setDescription('Searches messages and files within your Slack team'); 33 | $this->addArgument('query', InputArgument::REQUIRED, 'Search query. May contains booleans, etc.'); 34 | $this->addOption('sort', null, InputOption::VALUE_REQUIRED, 'Return matches sorted by either score or timestamp'); 35 | $this->addOption('sort-dir', null, InputOption::VALUE_REQUIRED, 'Change sort direction to ascending (asc) or descending (desc)'); 36 | $this->addOption('highlight', null, InputOption::VALUE_REQUIRED, 'Pass a value of 1 to enable query highlight markers'); 37 | $this->addOption('count', 'c', InputOption::VALUE_REQUIRED, 'Number of items to return per page'); 38 | $this->addOption('page', 'p', InputOption::VALUE_REQUIRED, 'Page number of results to return'); 39 | $this->setHelp(<<search:all command allows you to search both messages and files with a single query. 41 | 42 | The response returns matches broken down by their type of content, similar to the facebook/gmail auto-completed search widgets. 43 | 44 | For more information about the related API method, check out the official documentation: 45 | https://api.slack.com/methods/search.all 46 | EOT 47 | ); 48 | } 49 | 50 | /** 51 | * @return SearchAllPayload 52 | */ 53 | protected function createPayload() 54 | { 55 | $payload = new SearchAllPayload(); 56 | $payload->setQuery($this->input->getArgument('query')); 57 | $payload->setSort($this->input->getOption('sort')); 58 | $payload->setSortDir($this->input->getOption('sort-dir')); 59 | $payload->setPage($this->input->getOption('page')); 60 | $payload->setCount($this->input->getOption('count')); 61 | $payload->setHighlight($this->input->getOption('highlight')); 62 | 63 | return $payload; 64 | } 65 | 66 | /** 67 | * {@inheritdoc} 68 | * 69 | * @param SearchAllPayloadResponse $payloadResponse 70 | */ 71 | protected function handleResponse($payloadResponse) 72 | { 73 | if ($payloadResponse->isOk()) { 74 | $total = 0; 75 | if ($messageSearchResult = $payloadResponse->getMessageResult()) { 76 | $total += $messageSearchResult->getTotal(); 77 | } 78 | if ($fileSearchResult = $payloadResponse->getFileResult()) { 79 | $total += $fileSearchResult->getTotal(); 80 | } 81 | 82 | $this->writeComment(sprintf('Got %d results...', $total)); 83 | 84 | if ($total > 0) { 85 | $this->writeComment('Listing messages...'); 86 | if ($messageSearchResult->getTotal() > 1) { 87 | $this->renderTable($messageSearchResult->getMatches()); 88 | } else { 89 | $this->writeComment('No messages matched the query'); 90 | } 91 | 92 | $this->writeComment('Listing files...'); 93 | if ($fileSearchResult->getTotal() > 1) { 94 | $this->renderTable($fileSearchResult->getMatches()); 95 | } else { 96 | $this->writeComment('No files matched the query'); 97 | } 98 | } 99 | } else { 100 | $this->writeError(sprintf('Failed to search. %s', lcfirst($payloadResponse->getErrorExplanation()))); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/SearchFilesCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\SearchFilesPayload; 15 | use CL\Slack\Payload\SearchFilesPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputOption; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class SearchFilesCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('search:files'); 32 | $this->setDescription('Searches files within your Slack team'); 33 | $this->addArgument('query', InputArgument::REQUIRED, 'Search query. May contains booleans, etc.'); 34 | $this->addOption('sort', null, InputOption::VALUE_REQUIRED, 'Return matches sorted by either score or timestamp'); 35 | $this->addOption('sort-dir', null, InputOption::VALUE_REQUIRED, 'Change sort direction to ascending (asc) or descending (desc)'); 36 | $this->addOption('highlight', null, InputOption::VALUE_REQUIRED, 'Pass a value of 1 to enable query highlight markers'); 37 | $this->addOption('count', 'c', InputOption::VALUE_REQUIRED, 'Number of items to return per page'); 38 | $this->addOption('page', 'p', InputOption::VALUE_REQUIRED, 'Page number of results to return'); 39 | $this->setHelp(<<search:files command allows you to search for files matching a given query 41 | 42 | If the `--highlight` option is specified, the matching query terms will be marked up in the results so that clients may 43 | replace them with appropriate highlighting markers (e.g. ). 44 | 45 | The UTF-8 markers used are: 46 | - start: "\xEE\x80\x80"; # U+E000 (private-use) 47 | - end : "\xEE\x80\x81"; # U+E001 (private-use) 48 | 49 | For more information about the related API method, check out the official documentation: 50 | https://api.slack.com/methods/search.files 51 | EOT 52 | ); 53 | } 54 | 55 | /** 56 | * @return SearchFilesPayload 57 | */ 58 | protected function createPayload() 59 | { 60 | $payload = new SearchFilesPayload(); 61 | $payload->setQuery($this->input->getArgument('query')); 62 | $payload->setSort($this->input->getOption('sort')); 63 | $payload->setSortDir($this->input->getOption('sort-dir')); 64 | $payload->setPage($this->input->getOption('page')); 65 | $payload->setCount($this->input->getOption('count')); 66 | $payload->setHighlight($this->input->getOption('highlight')); 67 | 68 | return $payload; 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | * 74 | * @param SearchFilesPayloadResponse $payloadResponse 75 | */ 76 | protected function handleResponse($payloadResponse) 77 | { 78 | if ($payloadResponse->isOk()) { 79 | $total = 0; 80 | if ($fileSearchResult = $payloadResponse->getResult()) { 81 | $total += $fileSearchResult->getTotal(); 82 | } 83 | 84 | $this->writeComment(sprintf('Got %d results...', $total)); 85 | 86 | if ($total > 0) { 87 | $this->writeComment('Listing files...'); 88 | if ($fileSearchResult->getTotal() > 1) { 89 | $this->renderTable($fileSearchResult->getMatches()); 90 | } else { 91 | $this->writeComment('No files matched the query'); 92 | } 93 | } 94 | } else { 95 | $this->writeError(sprintf('Failed to search. %s', lcfirst($payloadResponse->getErrorExplanation()))); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/SearchMessagesCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\SearchMessagesPayload; 15 | use CL\Slack\Payload\SearchMessagesPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | use Symfony\Component\Console\Input\InputOption; 18 | 19 | /** 20 | * @author Cas Leentfaar 21 | */ 22 | class SearchMessagesCommand extends AbstractApiCommand 23 | { 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | protected function configure() 28 | { 29 | parent::configure(); 30 | 31 | $this->setName('search:messages'); 32 | $this->setDescription('Searches messages and files within your Slack team'); 33 | $this->addArgument('query', InputArgument::REQUIRED, 'Search query. May contains booleans, etc.'); 34 | $this->addOption('sort', null, InputOption::VALUE_REQUIRED, 'Return matches sorted by either score or timestamp'); 35 | $this->addOption('sort-dir', null, InputOption::VALUE_REQUIRED, 'Change sort direction to ascending (asc) or descending (desc)'); 36 | $this->addOption('highlight', null, InputOption::VALUE_REQUIRED, 'Pass a value of 1 to enable query highlight markers'); 37 | $this->addOption('count', 'c', InputOption::VALUE_REQUIRED, 'Number of items to return per page'); 38 | $this->addOption('page', 'p', InputOption::VALUE_REQUIRED, 'Page number of results to return'); 39 | $this->setHelp(<<search:messages command allows you to search for messages matching a given query 41 | 42 | If the `--highlight` option is specified, the matching query terms will be marked up in the results so that clients may 43 | replace them with appropriate highlighting markers (e.g. ). 44 | 45 | The UTF-8 markers used are: 46 | - start: "\xEE\x80\x80"; # U+E000 (private-use) 47 | - end : "\xEE\x80\x81"; # U+E001 (private-use) 48 | 49 | For more information about the related API method, check out the official documentation: 50 | https://api.slack.com/methods/search.messages 51 | EOT 52 | ); 53 | } 54 | 55 | /** 56 | * @return SearchMessagesPayload 57 | */ 58 | protected function createPayload() 59 | { 60 | $payload = new SearchMessagesPayload(); 61 | $payload->setQuery($this->input->getArgument('query')); 62 | $payload->setSort($this->input->getOption('sort')); 63 | $payload->setSortDir($this->input->getOption('sort-dir')); 64 | $payload->setPage($this->input->getOption('page')); 65 | $payload->setCount($this->input->getOption('count')); 66 | $payload->setHighlight($this->input->getOption('highlight')); 67 | 68 | return $payload; 69 | } 70 | 71 | /** 72 | * {@inheritdoc} 73 | * 74 | * @param SearchMessagesPayloadResponse $payloadResponse 75 | */ 76 | protected function handleResponse($payloadResponse) 77 | { 78 | if ($payloadResponse->isOk()) { 79 | $total = 0; 80 | if ($messageSearchResult = $payloadResponse->getResult()) { 81 | $total += $messageSearchResult->getTotal(); 82 | } 83 | 84 | $this->writeComment(sprintf('Got %d results...', $total)); 85 | 86 | if ($total > 0) { 87 | $this->writeComment('Listing messages...'); 88 | if ($messageSearchResult->getTotal() > 1) { 89 | $this->renderTable($messageSearchResult->getMatches()); 90 | } else { 91 | $this->writeComment('No messages matched the query'); 92 | } 93 | } 94 | } else { 95 | $this->writeError(sprintf('Failed to search. %s', lcfirst($payloadResponse->getErrorExplanation()))); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/SelfUpdateCommand.php: -------------------------------------------------------------------------------- 1 | setName('self:update'); 23 | $this->setDescription('Updates slack.phar to the latest version'); 24 | $this->setAliases(['self.update']); 25 | } 26 | 27 | /** 28 | * {@inheritdoc} 29 | */ 30 | protected function execute(InputInterface $input, OutputInterface $output) 31 | { 32 | $currentVersion = $this->getApplication()->getVersion(); 33 | $manager = new Manager(Manifest::loadFile(self::MANIFEST_FILE)); 34 | $lockMajor = false; 35 | $allowPreRelease = false; 36 | 37 | if (substr($currentVersion, 0, 1) == 0) { 38 | $allowPreRelease = true; 39 | } 40 | 41 | if ($manager->update($currentVersion, $lockMajor, $allowPreRelease)) { 42 | $newVersion = $this->getNewVersion($currentVersion, $manager, $lockMajor, $allowPreRelease); 43 | 44 | $this->output->writeln(sprintf( 45 | 'Updated Slack CLI from %s to %s', 46 | $currentVersion, 47 | $newVersion 48 | )); 49 | } else { 50 | $this->output->writeln(sprintf( 51 | 'You are already using the latest version (%s)', 52 | $currentVersion 53 | )); 54 | } 55 | } 56 | 57 | /** 58 | * @param string $currentVersion 59 | * @param Manager $manager 60 | * @param bool $lockMajor 61 | * @param bool $allowPreRelease 62 | * 63 | * @return string 64 | */ 65 | private function getNewVersion($currentVersion, Manager $manager, $lockMajor = false, $allowPreRelease = false) 66 | { 67 | $newVersionObject = $manager->getManifest()->findRecent( 68 | Parser::toVersion($currentVersion), 69 | $lockMajor, 70 | $allowPreRelease 71 | )->getVersion(); 72 | 73 | $newVersion = sprintf( 74 | '%s.%s', 75 | $newVersionObject->getMajor(), 76 | implode('.', array_filter([ 77 | $newVersionObject->getMinor(), 78 | $newVersionObject->getPatch(), 79 | ])) 80 | ); 81 | 82 | return $newVersion; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/StarsListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\StarsListPayload; 15 | use CL\Slack\Payload\StarsListPayloadResponse; 16 | use Symfony\Component\Console\Input\InputOption; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class StarsListCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('stars:list'); 31 | $this->setDescription('Returns a list of all the items starred by a user'); 32 | $this->addOption('user-id', null, InputOption::VALUE_REQUIRED, 'Show stars by this user. Defaults to the token\'s user.'); 33 | $this->setHelp(<<stars:list returns a list of all the items starred by a user. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/stars.list 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return StarsListPayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new StarsListPayload(); 48 | $payload->setUserId($this->input->getOption('user-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param StarsListPayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | $stars = $payloadResponse->getItems(); 62 | $this->output->writeln(sprintf('Received %d starred items...', count($stars))); 63 | if (!empty($stars)) { 64 | $this->renderTable($stars, null); 65 | $this->writeOk('Finished listing starred items'); 66 | } else { 67 | $this->writeComment('No starred items to list'); 68 | } 69 | } else { 70 | $this->writeError(sprintf( 71 | 'Failed to list starred items: %s', 72 | lcfirst($payloadResponse->getErrorExplanation()) 73 | )); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/UsersInfoCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\UsersInfoPayload; 15 | use CL\Slack\Payload\UsersInfoPayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class UsersInfoCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('users:info'); 31 | $this->setDescription('Returns information about a team member'); 32 | $this->addArgument('user-id', InputArgument::REQUIRED, 'User to get info on'); 33 | $this->setHelp(<<users.info command returns information about a team member. 35 | 36 | For more information about the related API method, check out the official documentation: 37 | https://api.slack.com/methods/users.info 38 | EOT 39 | ); 40 | } 41 | 42 | /** 43 | * @return UsersInfoPayload 44 | */ 45 | protected function createPayload() 46 | { 47 | $payload = new UsersInfoPayload(); 48 | $payload->setUserId($this->input->getArgument('user-id')); 49 | 50 | return $payload; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | * 56 | * @param UsersInfoPayloadResponse $payloadResponse 57 | */ 58 | protected function handleResponse($payloadResponse) 59 | { 60 | if ($payloadResponse->isOk()) { 61 | $this->renderKeyValueTable($payloadResponse->getUser()); 62 | } else { 63 | $this->writeError(sprintf('Failed to fetch information about the user: %s', lcfirst($payloadResponse->getErrorExplanation()))); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/UsersListCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\UsersListPayload; 15 | use CL\Slack\Payload\UsersListPayloadResponse; 16 | 17 | /** 18 | * @author Cas Leentfaar 19 | */ 20 | class UsersListCommand extends AbstractApiCommand 21 | { 22 | /** 23 | * {@inheritDoc} 24 | */ 25 | protected function configure() 26 | { 27 | parent::configure(); 28 | 29 | $this->setName('users:list'); 30 | $this->setDescription('Returns a list of all users in the team (including deleted/deactivated users)'); 31 | $this->setHelp(<<users:list command returns a list of all users in the team. This includes deleted/deactivated users. 33 | 34 | For more information about the related API method, check out the official documentation: 35 | https://api.slack.com/methods/users.list 36 | EOT 37 | ); 38 | } 39 | 40 | /** 41 | * @return UsersListPayload 42 | */ 43 | protected function createPayload() 44 | { 45 | $payload = new UsersListPayload(); 46 | 47 | return $payload; 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | * 53 | * @param UsersListPayloadResponse $payloadResponse 54 | */ 55 | protected function handleResponse($payloadResponse) 56 | { 57 | if ($payloadResponse->isOk()) { 58 | $users = $payloadResponse->getUsers(); 59 | $this->output->writeln(sprintf('Received %d users...', count($users))); 60 | if (!empty($users)) { 61 | $this->renderTable($users, null); 62 | $this->writeOk('Successfully listed users'); 63 | } else { 64 | $this->writeError('No users seem to be assigned to your team... this is strange...'); 65 | } 66 | } else { 67 | $this->writeError(sprintf('Failed to list users: %s', lcfirst($payloadResponse->getErrorExplanation()))); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/UsersSetActiveCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license setactivermation, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\UsersSetActivePayload; 15 | use CL\Slack\Payload\UsersSetActivePayloadResponse; 16 | 17 | /** 18 | * @author Cas Leentfaar 19 | */ 20 | class UsersSetActiveCommand extends AbstractApiCommand 21 | { 22 | /** 23 | * {@inheritDoc} 24 | */ 25 | protected function configure() 26 | { 27 | parent::configure(); 28 | 29 | $this->setName('users:set-active'); 30 | $this->setDescription('Lets the slack messaging server know that the token\'s user is currently active'); 31 | $this->setHelp(<<users:set-active command lets the slack messaging server know that the token's 33 | user is currently active. Consult the presence documentation for more details (see link below). 34 | 35 | For more information about the related API method, check out the official documentation: 36 | https://api.slack.com/methods/users.setActive 37 | EOT 38 | ); 39 | } 40 | 41 | /** 42 | * @return UsersSetActivePayload 43 | */ 44 | protected function createPayload() 45 | { 46 | $payload = new UsersSetActivePayload(); 47 | 48 | return $payload; 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | * 54 | * @param UsersSetActivePayloadResponse $payloadResponse 55 | */ 56 | protected function handleResponse($payloadResponse) 57 | { 58 | if ($payloadResponse->isOk()) { 59 | $this->writeOk('Successfully informed Slack of the token user\'s active status'); 60 | } else { 61 | $this->writeError(sprintf( 62 | 'Failed to set the user to active: %s', 63 | lcfirst($payloadResponse->getErrorExplanation()) 64 | )); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Command/UsersSetPresenceCommand.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Command; 13 | 14 | use CL\Slack\Payload\UsersSetPresencePayload; 15 | use CL\Slack\Payload\UsersSetPresencePayloadResponse; 16 | use Symfony\Component\Console\Input\InputArgument; 17 | 18 | /** 19 | * @author Cas Leentfaar 20 | */ 21 | class UsersSetPresenceCommand extends AbstractApiCommand 22 | { 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | protected function configure() 27 | { 28 | parent::configure(); 29 | 30 | $this->setName('users:set-presence'); 31 | $this->setDescription('Override the token user\'s presence value'); 32 | $this->addArgument('presence', InputArgument::REQUIRED, 'Either "active" or "away"'); 33 | $this->setHelp(<<users:set-presence command lets you manually override the token user's presence value. 35 | Consult the presence documentation for more details. 36 | 37 | For more information about the related API method, check out the official documentation: 38 | https://api.slack.com/methods/presence.set 39 | EOT 40 | ); 41 | } 42 | 43 | /** 44 | * @return UsersSetPresencePayload 45 | */ 46 | protected function createPayload() 47 | { 48 | $payload = new UsersSetPresencePayload(); 49 | $payload->setPresence($this->input->getArgument('presence')); 50 | 51 | return $payload; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | * 57 | * @param UsersSetPresencePayloadResponse $payloadResponse 58 | */ 59 | protected function handleResponse($payloadResponse) 60 | { 61 | if ($payloadResponse->isOk()) { 62 | $this->writeOk('Successfully changed presence!'); 63 | } else { 64 | $this->writeError(sprintf('Failed to change presence. %s', lcfirst($payloadResponse->getErrorExplanation()))); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Config/Config.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Config; 13 | 14 | /** 15 | * @author Jordi Boggiano 16 | * @author Cas Leentfaar 17 | */ 18 | class Config 19 | { 20 | public static $defaultConfig = [ 21 | 'default_token' => null, 22 | ]; 23 | 24 | private $config; 25 | private $configSource; 26 | private $useEnvironment; 27 | 28 | /** 29 | * @param boolean $useEnvironment Use SLACK_CLI_ environment variables to replace config settings 30 | */ 31 | public function __construct($useEnvironment = true) 32 | { 33 | // load defaults 34 | $this->config = static::$defaultConfig; 35 | $this->useEnvironment = (bool) $useEnvironment; 36 | } 37 | 38 | /** 39 | * @param $source 40 | */ 41 | public function setConfigSource($source) 42 | { 43 | $this->configSource = $source; 44 | } 45 | 46 | /** 47 | * @return mixed 48 | */ 49 | public function getConfigSource() 50 | { 51 | return $this->configSource; 52 | } 53 | 54 | /** 55 | * Merges new config values with the existing ones (overriding) 56 | * 57 | * @param array $config 58 | */ 59 | public function merge($config) 60 | { 61 | // override defaults with given config 62 | if (!empty($config['config']) && is_array($config['config'])) { 63 | foreach ($config['config'] as $key => $val) { 64 | $this->config[$key] = $val; 65 | } 66 | } 67 | } 68 | 69 | /** 70 | * Returns a setting 71 | * 72 | * @param string $key 73 | * 74 | * @throws \RuntimeException 75 | * 76 | * @return mixed 77 | */ 78 | public function get($key) 79 | { 80 | switch ($key) { 81 | case 'home': 82 | return rtrim($this->process($this->config[$key]), '/\\'); 83 | default: 84 | if (!isset($this->config[$key])) { 85 | return; 86 | } 87 | 88 | return $this->process($this->config[$key]); 89 | } 90 | } 91 | 92 | /** 93 | * @return array 94 | */ 95 | public function all() 96 | { 97 | $all = []; 98 | foreach (array_keys($this->config) as $key) { 99 | $all['config'][$key] = $this->get($key); 100 | } 101 | 102 | return $all; 103 | } 104 | 105 | /** 106 | * @return array 107 | */ 108 | public function raw() 109 | { 110 | return [ 111 | 'config' => $this->config, 112 | ]; 113 | } 114 | 115 | /** 116 | * Checks whether a setting exists 117 | * 118 | * @param string $key 119 | * 120 | * @return bool 121 | */ 122 | public function has($key) 123 | { 124 | return array_key_exists($key, $this->config); 125 | } 126 | 127 | /** 128 | * Replaces {$refs} inside a config string 129 | * 130 | * @param string $value a config string that can contain {$refs-to-other-config} 131 | * 132 | * @return string 133 | */ 134 | private function process($value) 135 | { 136 | $config = $this; 137 | 138 | if (!is_string($value)) { 139 | return $value; 140 | } 141 | 142 | return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config) { 143 | return $config->get($match[1]); 144 | }, $value); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Config/ConfigFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Config; 13 | 14 | use Composer\Config\JsonConfigSource; 15 | use Composer\Json\JsonFile; 16 | 17 | /** 18 | * @author Ryan Weaver 19 | * @author Jordi Boggiano 20 | * @author Igor Wiedler 21 | * @author Nils Adermann 22 | * @author Cas Leentfaar 23 | */ 24 | class ConfigFactory 25 | { 26 | /** 27 | * @return string 28 | * 29 | * @throws \RuntimeException 30 | */ 31 | public static function getHomeDir() 32 | { 33 | $home = getenv('SLACK_CLI_HOME'); 34 | if (!$home) { 35 | if (defined('PHP_WINDOWS_VERSION_MAJOR')) { 36 | if (!getenv('APPDATA')) { 37 | throw new \RuntimeException('The APPDATA or SLACK_CLI_HOME environment variable must be set for Slack CLI to run correctly'); 38 | } 39 | $home = strtr(getenv('APPDATA'), '\\', '/') . '/SlackCli'; 40 | } else { 41 | if (!getenv('HOME')) { 42 | throw new \RuntimeException('The HOME or SLACK_CLI_HOME environment variable must be set for Slack CLI to run correctly'); 43 | } 44 | $home = rtrim(getenv('HOME'), '/') . '/.slack-cli'; 45 | } 46 | } 47 | 48 | return $home; 49 | } 50 | 51 | /** 52 | * @param string $path 53 | * 54 | * @return Config 55 | */ 56 | public static function createConfig($path) 57 | { 58 | $config = new Config(); 59 | 60 | // load global config 61 | $file = new JsonFile($path); 62 | if ($file->exists()) { 63 | $config->merge($file->read()); 64 | } 65 | 66 | $config->setConfigSource(new JsonConfigSource($file)); 67 | 68 | return $config; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Console/Application.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace CL\SlackCli\Console; 13 | 14 | use Symfony\Component\Console\Application as BaseApplication; 15 | use Symfony\Component\Console\Input\InputOption; 16 | 17 | /** 18 | * @author Cas Leentfaar 19 | */ 20 | class Application extends BaseApplication 21 | { 22 | /** 23 | * @var array 24 | */ 25 | private $availableEnvironments = [ 26 | 'prod', 27 | 'test-success', // mocks a successful response 28 | 'test-failure', // mocks a failed response 29 | ]; 30 | 31 | /** 32 | * @var string 33 | */ 34 | private $defaultEnvironment = 'prod'; 35 | 36 | /** 37 | * Constructor. 38 | */ 39 | public function __construct() 40 | { 41 | error_reporting(-1); 42 | 43 | parent::__construct('Slack CLI', $this->getReplacedVersion()); 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | public function getLongVersion() 50 | { 51 | return sprintf('%s by Cas Leentfaar', parent::getLongVersion()); 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function getDefaultInputDefinition() 58 | { 59 | $parentDefinition = parent::getDefaultInputDefinition(); 60 | $parentDefinition->addOption(new InputOption( 61 | '--env', 62 | 'e', 63 | InputOption::VALUE_REQUIRED, 64 | sprintf('The environment to run the Slack CLI under (%s)', implode('|', $this->availableEnvironments)), 65 | $this->defaultEnvironment 66 | )); 67 | 68 | return $parentDefinition; 69 | } 70 | 71 | /** 72 | * @return null|string 73 | */ 74 | private function getReplacedVersion() 75 | { 76 | $version = '@git-version@'; 77 | if ($version === '@' . 'git-version@') { 78 | return 'UNKNOWN'; 79 | } 80 | 81 | return $version; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Resources/doc/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Coding standards 4 | 5 | Your PRs must adhere to the [Symfony2 Coding Standards](http://symfony.com/doc/current/contributing/code/standards.html). 6 | The easiest way to apply to these conventions is to install [PHP_CodeSniffer](http://pear.php.net/package/PHP_CodeSniffer) 7 | and the [Opensky Symfony2 Coding Standard](https://github.com/opensky/Symfony2-coding-standard). 8 | 9 | You may be interested in [PHP Coding Standards Fixer](https://github.com/fabpot/PHP-CS-Fixer). 10 | 11 | **Happy coding** ! 12 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Resources/doc/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Step 1) Downloading the Slack CLI Executable 4 | 5 | There are in short, two ways to install the Slack CLI: 6 | - [Locally](#locally); as part of your project, or; 7 | - [Globally](#globally); as a system-wide executable 8 | 9 | Windows Users should follow steps [here](#windows-users). 10 | 11 | ### Locally 12 | 13 | Installing Slack CLI locally is a matter of just running the installer in your 14 | project directory: 15 | 16 | ```sh 17 | curl -sS http://cleentfaar.github.io/slack-cli/installer | php 18 | ``` 19 | 20 | > **Note:** If the above fails for some reason, you can download the installer 21 | > with `php` instead: 22 | 23 | ```sh 24 | php -r "readfile('http://cleentfaar.github.io/slack-cli/installer');" | php 25 | ``` 26 | 27 | The installer will just check a few PHP settings and then download the latest `slack.phar` 28 | to your working directory. This file is the Slack CLI binary. It is a PHAR (PHP 29 | archive), which is an archive format for PHP which can be run on the command 30 | line, amongst other things. 31 | 32 | You can install Slack CLI to a specific directory by using the `--install-dir` 33 | option and providing a target directory (it can be an absolute or relative path): 34 | 35 | ```sh 36 | curl -sS http://cleentfaar.github.io/slack-cli/installer | php -- --install-dir=bin 37 | ``` 38 | 39 | ### Globally 40 | 41 | You can place this file anywhere you wish. If you put it in your `PATH`, 42 | you can access it globally. On unixy systems you can even make it 43 | executable and invoke it without `php`. 44 | 45 | You can run these commands to easily access `slack` from anywhere on your system: 46 | 47 | ```sh 48 | curl -sS http://cleentfaar.github.io/slack-cli/installer | php 49 | mv slack.phar /usr/local/bin/slack 50 | ``` 51 | 52 | > **Note:** If the above fails due to permissions, run the `mv` line 53 | > again with sudo. 54 | 55 | Then, just run `slack` in order to run Slack CLI instead of `php slack.phar`. 56 | 57 | ### Windows users 58 | 59 | Change to a directory on your `PATH` and run the install snippet to download 60 | slack.phar: 61 | 62 | ```sh 63 | C:\Users\username>cd C:\bin 64 | C:\bin>php -r "readfile('http://cleentfaar.github.io/slack-cli/installer');" | php 65 | ``` 66 | 67 | Create a new `slack.bat` file alongside `slack.phar`: 68 | 69 | ```sh 70 | C:\bin>echo @php "%~dp0slack.phar" %*>slack.bat 71 | ``` 72 | 73 | Close your current terminal. Test usage with a new terminal: 74 | 75 | ```sh 76 | C:\Users\username>slack -V 77 | Slack CLI version 0.14.1 78 | ``` 79 | 80 | ## Step 2) (Optional) Configure the API token to use by default 81 | 82 | All API commands require you to supply the API token using the `--token` option. 83 | However, if you are planning on using the same token you can easily configure the application to use a token set before-hand: 84 | 85 | ```sh 86 | $ slack.phar config:set default_token your-token-here 87 | ``` 88 | 89 | If you do not have an API token yet, you should generate one on the Slack API website (you need to be logged in first): [https://api.slack.com/web#authentication](https://api.slack.com/web#authentication) 90 | 91 | 92 | # Ready? 93 | 94 | Let's start up this puppy! Check out the [usage documentation](https://github.com/cleentfaar/slack-cli/blob/master/src/CL/SlackCli/Resources/doc/usage.md)! 95 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/AbstractApiCommandTest.php: -------------------------------------------------------------------------------- 1 | 'testing-token', 21 | '--env' => 'test-success', 22 | '--verbose' => 3, 23 | ]); 24 | } 25 | 26 | protected function getDefaultFailureInput() 27 | { 28 | return array_merge(parent::getDefaultFailureInput(), [ 29 | '--token' => 'testing-token', 30 | '--env' => 'test-failure', 31 | '--verbose' => 3, 32 | ]); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ApiTestCommandTest.php: -------------------------------------------------------------------------------- 1 | assertExecutionSucceedsWith( 13 | [], 14 | 'Slack API seems to have responded correctly' 15 | ); 16 | 17 | $this->assertExecutionSucceedsWith([ 18 | '--arguments' => [ 19 | 'foo:bar', 20 | ], 21 | ], 'Slack API seems to have responded correctly'); 22 | $this->assertExecutionSucceedsWith([ 23 | '--arguments' => [ 24 | 'foo:bar', 25 | ], 26 | '--error' => 'some expected error', 27 | ], 'Slack API seems to have responded correctly'); 28 | 29 | $this->assertExecutionFailsWith([], 'Slack API did not respond correctly (no error expected)'); 30 | } 31 | 32 | /** 33 | * @return AbstractCommand 34 | */ 35 | protected function createCommand() 36 | { 37 | return new ApiTestCommand(); 38 | } 39 | 40 | /** 41 | * @return string 42 | */ 43 | protected function getExpectedName() 44 | { 45 | return 'api:test'; 46 | } 47 | 48 | /** 49 | * @return array 50 | */ 51 | protected function getExpectedArguments() 52 | { 53 | return []; 54 | } 55 | 56 | /** 57 | * @return array 58 | */ 59 | protected function getExpectedOptions() 60 | { 61 | return [ 62 | 'arguments', 63 | 'error', 64 | ]; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/AuthTestCommandTest.php: -------------------------------------------------------------------------------- 1 | assertExecutionSucceedsWith([], 'Successfully authenticated by the Slack API'); 13 | $this->assertExecutionFailsWith([], 'Failed to be authenticated by the Slack API'); 14 | } 15 | 16 | /** 17 | * @return AbstractCommand 18 | */ 19 | protected function createCommand() 20 | { 21 | return new AuthTestCommand(); 22 | } 23 | 24 | /** 25 | * @return string 26 | */ 27 | protected function getExpectedName() 28 | { 29 | return 'auth:test'; 30 | } 31 | 32 | /** 33 | * @return array 34 | */ 35 | protected function getExpectedArguments() 36 | { 37 | return []; 38 | } 39 | 40 | /** 41 | * @return array 42 | */ 43 | protected function getExpectedOptions() 44 | { 45 | return []; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsArchiveCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | ]; 14 | 15 | $this->assertExecutionSucceedsWith($args, 'Successfully archived channel'); 16 | $this->assertExecutionFailsWith($args, 'Failed to archive channel'); 17 | } 18 | 19 | protected function createCommand() 20 | { 21 | return new ChannelsArchiveCommand(); 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | protected function getExpectedName() 28 | { 29 | return 'channels:archive'; 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | protected function getExpectedArguments() 36 | { 37 | return [ 38 | 'channel-id', 39 | ]; 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | protected function getExpectedOptions() 46 | { 47 | return []; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsCreateCommandTest.php: -------------------------------------------------------------------------------- 1 | 'My new channel', 13 | ]; 14 | 15 | $this->assertExecutionSucceedsWith($args, 'Successfully created channel'); 16 | $this->assertExecutionFailsWith($args, 'Failed to create channel'); 17 | } 18 | 19 | protected function createCommand() 20 | { 21 | return new ChannelsCreateCommand(); 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | protected function getExpectedName() 28 | { 29 | return 'channels:create'; 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | protected function getExpectedArguments() 36 | { 37 | return [ 38 | 'name', 39 | ]; 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | protected function getExpectedOptions() 46 | { 47 | return []; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsHistoryCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | '--oldest' => '2014-01-01', 14 | '--latest' => '2015-01-01', 15 | '--count' => 123, 16 | ]; 17 | 18 | $this->assertExecutionSucceedsWith($args, [ 19 | 'Successfully retrieved history', 20 | '+----------+---------+-----------+-----------+--------------+', 21 | '| ts | type | user | username | text |', 22 | '+----------+---------+-----------+-----------+--------------+', 23 | '| 12345678 | message | U1234567! | acme_user | Hello world! |', 24 | '+----------+---------+-----------+-----------+--------------+', 25 | ]); 26 | 27 | $this->assertExecutionFailsWith($args, 'Failed to retrieve history for this channel'); 28 | } 29 | 30 | protected function createCommand() 31 | { 32 | return new ChannelsHistoryCommand(); 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | protected function getExpectedName() 39 | { 40 | return 'channels:history'; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | protected function getExpectedArguments() 47 | { 48 | return [ 49 | 'channel-id', 50 | ]; 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | protected function getExpectedOptions() 57 | { 58 | return [ 59 | 'latest', 60 | 'oldest', 61 | 'count', 62 | ]; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsInfoCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | ]; 14 | 15 | $this->assertExecutionSucceedsWith($args, [ 16 | 'Successfully retrieved information about the channel', 17 | 'C1234567', 18 | 'acme_channel', 19 | '1970-05-23T21:21:18+0000', 20 | 'U1234567', 21 | '{"ts":"12345678.12345678","type":"message","channel":{"id":"C1234567","name":"#foo"},"user":"U1234567","username":"Acme","text":"Hello world!","attachments":[]}', 22 | '12345678.12345678', 23 | '["U1234567"]', 24 | '{"value":"Discuss secret plans that no-one else should know","type":"text","creator":"U024BE7LH","last_set":"2013-02-13T19:13:24+0000"}', 25 | '{"value":"Discuss secret plans that no-one else should know","type":"text","creator":"U024BE7LH","last_set":"2013-02-13T19:13:24+0000"}', 26 | ]); 27 | 28 | $this->assertExecutionFailsWith($args, 'Failed to retrieve information about the channel'); 29 | } 30 | 31 | protected function createCommand() 32 | { 33 | return new ChannelsInfoCommand(); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | protected function getExpectedName() 40 | { 41 | return 'channels:info'; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | protected function getExpectedArguments() 48 | { 49 | return [ 50 | 'channel-id', 51 | ]; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function getExpectedOptions() 58 | { 59 | return []; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsInviteCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | 'user-id' => 'U1234567', 14 | ]; 15 | 16 | $this->assertExecutionSucceedsWith($args, [ 17 | 'Successfully invited user to the channel', 18 | 'Channel used:', 19 | 'C1234567', 20 | 'acme_channel', 21 | '1970-05-23T21:21:18+0000', 22 | 'U1234567', 23 | '{"ts":"12345678.12345678","type":"message","channel":{"id":"C1234567","name":"#foo"},"user":"U1234567","username":"Acme","text":"Hello world!","attachments":[]}', 24 | '12345678.12345678', 25 | '["U1234567"]', 26 | '{"value":"Discuss secret plans that no-one else should know","type":"text","creator":"U024BE7LH","last_set":"2013-02-13T19:13:24+0000"}', 27 | '{"value":"Discuss secret plans that no-one else should know","type":"text","creator":"U024BE7LH","last_set":"2013-02-13T19:13:24+0000"}', 28 | ]); 29 | 30 | $this->assertExecutionFailsWith($args, 'Failed to invite user to this channel'); 31 | } 32 | 33 | protected function createCommand() 34 | { 35 | return new ChannelsInviteCommand(); 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | protected function getExpectedName() 42 | { 43 | return 'channels:invite'; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | protected function getExpectedArguments() 50 | { 51 | return [ 52 | 'channel-id', 53 | 'user-id', 54 | ]; 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | protected function getExpectedOptions() 61 | { 62 | return []; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsJoinCommandTest.php: -------------------------------------------------------------------------------- 1 | 'Acme Channel', 13 | ]; 14 | 15 | $this->assertExecutionSucceedsWith($args, [ 16 | 'You are already in this channel', 17 | 'C1234567', 18 | 'acme_channel', 19 | '1970-05-23T21:21:18+0000', 20 | 'U1234567', 21 | '{"ts":"12345678.12345678","type":"message","channel":{"id":"C1234567","name":"#foo"},"user":"U1234567","username":"Acme","text":"Hello world!","attachments":[]}', 22 | '12345678.12345678', 23 | '["U1234567"]', 24 | '{"value":"Discuss secret plans that no-one else should know","type":"text","creator":"U024BE7LH","last_set":"2013-02-13T19:13:24+0000"}', 25 | '{"value":"Discuss secret plans that no-one else should know","type":"text","creator":"U024BE7LH","last_set":"2013-02-13T19:13:24+0000"}', 26 | ]); 27 | 28 | $this->assertExecutionFailsWith($args, 'Failed to join channel'); 29 | } 30 | 31 | protected function createCommand() 32 | { 33 | return new ChannelsJoinCommand(); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | protected function getExpectedName() 40 | { 41 | return 'channels:join'; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | protected function getExpectedArguments() 48 | { 49 | return [ 50 | 'channel', 51 | ]; 52 | } 53 | 54 | /** 55 | * {@inheritdoc} 56 | */ 57 | protected function getExpectedOptions() 58 | { 59 | return []; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsKickCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | 'user-id' => 'U1234567', 14 | ]; 15 | 16 | $this->assertExecutionSucceedsWith($args, 'Successfully kicked user from the channel'); 17 | $this->assertExecutionFailsWith($args, 'Failed to kick user from the channel'); 18 | } 19 | 20 | protected function createCommand() 21 | { 22 | return new ChannelsKickCommand(); 23 | } 24 | 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | protected function getExpectedName() 29 | { 30 | return 'channels:kick'; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | protected function getExpectedArguments() 37 | { 38 | return [ 39 | 'channel-id', 40 | 'user-id', 41 | ]; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | protected function getExpectedOptions() 48 | { 49 | return []; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsLeaveCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | ]; 14 | 15 | $this->assertExecutionSucceedsWith($args, 'Could not leave channel; not in channel'); 16 | $this->assertExecutionFailsWith($args, 'Failed to leave channel'); 17 | } 18 | 19 | protected function createCommand() 20 | { 21 | return new ChannelsLeaveCommand(); 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | protected function getExpectedName() 28 | { 29 | return 'channels:leave'; 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | protected function getExpectedArguments() 36 | { 37 | return [ 38 | 'channel-id', 39 | ]; 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | protected function getExpectedOptions() 46 | { 47 | return []; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsListCommandTest.php: -------------------------------------------------------------------------------- 1 | assertExecutionSucceedsWith([], [ 13 | 'Received 1 channels...', 14 | 'C1234567', 15 | 'acme_channel', 16 | '1970-05-23T21:21:18+0000', 17 | 'U1234567', 18 | '{"ts":"12345678.12345678","type":"message","channel":{"id":"C1234567","name":"#foo"},"user":"U1234567","username":"Acme","text":"Hello world!","attachments":[]}', 19 | '12345678.12345678', 20 | '["U1234567"]', 21 | 'Discuss secret plans that no-one else should know | Discuss secret plans that no-one else should know', 22 | ]); 23 | 24 | $this->assertExecutionFailsWith([], 'Failed to list channels'); 25 | } 26 | 27 | /** 28 | * @return AbstractCommand 29 | */ 30 | protected function createCommand() 31 | { 32 | return new ChannelsListCommand(); 33 | } 34 | 35 | /** 36 | * @return string 37 | */ 38 | protected function getExpectedName() 39 | { 40 | return 'channels:list'; 41 | } 42 | 43 | /** 44 | * @return array 45 | */ 46 | protected function getExpectedArguments() 47 | { 48 | return []; 49 | } 50 | 51 | /** 52 | * @return array 53 | */ 54 | protected function getExpectedOptions() 55 | { 56 | return [ 57 | 'exclude-archived', 58 | ]; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsMarkCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | 'timestamp' => '12345678.12345678', 14 | ]; 15 | 16 | $this->assertExecutionSucceedsWith($args, 'Successfully moved the read cursor'); 17 | $this->assertExecutionFailsWith($args, 'Failed to move the read cursor in the channel'); 18 | } 19 | 20 | protected function createCommand() 21 | { 22 | return new ChannelsMarkCommand(); 23 | } 24 | 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | protected function getExpectedName() 29 | { 30 | return 'channels:mark'; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | protected function getExpectedArguments() 37 | { 38 | return [ 39 | 'channel-id', 40 | 'timestamp', 41 | ]; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | protected function getExpectedOptions() 48 | { 49 | return []; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsRenameCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | 'name' => 'New name', 14 | ]; 15 | 16 | $this->assertExecutionSucceedsWith($args, [ 17 | 'Successfully renamed channel!', 18 | 'Renamed channel:', 19 | 'C1234567', 20 | 'acme_channel', 21 | '1970-05-23T21:21:18+0000', 22 | 'U1234567', 23 | '{"ts":"12345678.12345678","type":"message","channel":{"id":"C1234567","name":"#foo"},"user":"U1234567","username":"Acme","text":"Hello world!","attachments":[]}', 24 | '12345678.12345678', 25 | '["U1234567"]', 26 | '{"value":"Discuss secret plans that no-one else should know","type":"text","creator":"U024BE7LH","last_set":"2013-02-13T19:13:24+0000"}', 27 | '{"value":"Discuss secret plans that no-one else should know","type":"text","creator":"U024BE7LH","last_set":"2013-02-13T19:13:24+0000"}', 28 | ]); 29 | 30 | $this->assertExecutionFailsWith($args, 'Failed to rename channel'); 31 | } 32 | 33 | protected function createCommand() 34 | { 35 | return new ChannelsRenameCommand(); 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | protected function getExpectedName() 42 | { 43 | return 'channels:rename'; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | protected function getExpectedArguments() 50 | { 51 | return [ 52 | 'channel-id', 53 | 'name', 54 | ]; 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | protected function getExpectedOptions() 61 | { 62 | return []; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsSetPurposeCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | 'purpose' => 'New purpose', 14 | ]; 15 | 16 | $this->assertExecutionSucceedsWith($args, 'Successfully changed purpose of channel to: "new_purpose"'); 17 | $this->assertExecutionFailsWith($args, 'Failed to change purpose of channel'); 18 | } 19 | 20 | protected function createCommand() 21 | { 22 | return new ChannelsSetPurposeCommand(); 23 | } 24 | 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | protected function getExpectedName() 29 | { 30 | return 'channels:set-purpose'; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | protected function getExpectedArguments() 37 | { 38 | return [ 39 | 'channel-id', 40 | 'purpose', 41 | ]; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | protected function getExpectedOptions() 48 | { 49 | return []; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsSetTopicCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | 'topic' => 'New topic', 14 | ]; 15 | 16 | $this->assertExecutionSucceedsWith($args, 'Successfully changed topic of channel to: "new_topic"'); 17 | $this->assertExecutionFailsWith($args, 'Failed to change topic of channel'); 18 | } 19 | 20 | protected function createCommand() 21 | { 22 | return new ChannelsSetTopicCommand(); 23 | } 24 | 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | protected function getExpectedName() 29 | { 30 | return 'channels:set-topic'; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | protected function getExpectedArguments() 37 | { 38 | return [ 39 | 'channel-id', 40 | 'topic', 41 | ]; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | protected function getExpectedOptions() 48 | { 49 | return []; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChannelsUnarchiveCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | ]; 14 | 15 | $this->assertExecutionSucceedsWith($args, 'Successfully un-archived channel'); 16 | $this->assertExecutionFailsWith($args, 'Failed to un-archive channel'); 17 | } 18 | 19 | protected function createCommand() 20 | { 21 | return new ChannelsUnarchiveCommand(); 22 | } 23 | 24 | /** 25 | * {@inheritdoc} 26 | */ 27 | protected function getExpectedName() 28 | { 29 | return 'channels:unarchive'; 30 | } 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | protected function getExpectedArguments() 36 | { 37 | return [ 38 | 'channel-id', 39 | ]; 40 | } 41 | 42 | /** 43 | * {@inheritdoc} 44 | */ 45 | protected function getExpectedOptions() 46 | { 47 | return []; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChatDeleteCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | 'timestamp' => '12345678.12345678', 14 | ]; 15 | 16 | $this->assertExecutionSucceedsWith($args, 'Successfully deleted message'); 17 | $this->assertExecutionFailsWith($args, 'Failed to delete message'); 18 | } 19 | 20 | protected function createCommand() 21 | { 22 | return new ChatDeleteCommand(); 23 | } 24 | 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | protected function getExpectedName() 29 | { 30 | return 'chat:delete'; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | protected function getExpectedArguments() 37 | { 38 | return [ 39 | 'channel-id', 40 | 'timestamp', 41 | ]; 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | protected function getExpectedOptions() 48 | { 49 | return []; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChatPostMessageCommandTest.php: -------------------------------------------------------------------------------- 1 | '#foobar', 13 | 'text' => 'Hello world!', 14 | ]; 15 | 16 | $this->assertExecutionSucceedsWith($args, [ 17 | 'Successfully sent message to Slack', 18 | 'Channel ID: C1234567', 19 | 'Timestamp: 12345678.12345678', 20 | ]); 21 | 22 | $this->assertExecutionFailsWith($args, 'Failed to send message to Slack'); 23 | } 24 | 25 | protected function createCommand() 26 | { 27 | return new ChatPostMessageCommand(); 28 | } 29 | 30 | /** 31 | * {@inheritdoc} 32 | */ 33 | protected function getExpectedName() 34 | { 35 | return 'chat:post-message'; 36 | } 37 | 38 | /** 39 | * {@inheritdoc} 40 | */ 41 | protected function getExpectedAliases() 42 | { 43 | return [ 44 | 'chat.postMessage', 45 | ]; 46 | } 47 | 48 | /** 49 | * {@inheritdoc} 50 | */ 51 | protected function getExpectedArguments() 52 | { 53 | return [ 54 | 'channel', 55 | 'text', 56 | ]; 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | protected function getExpectedOptions() 63 | { 64 | return [ 65 | 'icon-emoji', 66 | 'icon-url', 67 | 'link-names', 68 | 'parse', 69 | 'unfurl-links', 70 | 'unfurl-media', 71 | 'username', 72 | ]; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ChatUpdateCommandTest.php: -------------------------------------------------------------------------------- 1 | 'C1234567', 13 | 'timestamp' => '12345678.12345678', 14 | 'text' => 'New text of the message', 15 | ]; 16 | 17 | $this->assertExecutionSucceedsWith($args, 'Successfully updated message'); 18 | $this->assertExecutionFailsWith($args, 'Failed to update message'); 19 | } 20 | 21 | protected function createCommand() 22 | { 23 | return new ChatUpdateCommand(); 24 | } 25 | 26 | /** 27 | * {@inheritdoc} 28 | */ 29 | protected function getExpectedName() 30 | { 31 | return 'chat:update'; 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | */ 37 | protected function getExpectedArguments() 38 | { 39 | return [ 40 | 'channel-id', 41 | 'timestamp', 42 | 'text', 43 | ]; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | protected function getExpectedOptions() 50 | { 51 | return []; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ConfigEditCommandTest.php: -------------------------------------------------------------------------------- 1 | assertExecutionSucceedsWith([ 14 | ], sprintf('Editing `%s` using `mock-editor`...', $this->getConfigurationPath())); 15 | } 16 | 17 | /** 18 | * @return ConfigEditCommand 19 | */ 20 | protected function createCommand() 21 | { 22 | return new ConfigEditCommand(); 23 | } 24 | 25 | /** 26 | * @return string 27 | */ 28 | protected function getExpectedName() 29 | { 30 | return 'config:edit'; 31 | } 32 | 33 | /** 34 | * @return array 35 | */ 36 | protected function getExpectedArguments() 37 | { 38 | return []; 39 | } 40 | 41 | /** 42 | * @return array 43 | */ 44 | protected function getExpectedOptions() 45 | { 46 | return []; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ConfigGetCommandTest.php: -------------------------------------------------------------------------------- 1 | assertExecutionSucceedsWith([ 13 | 'setting' => 'default_token', 14 | ], 'Value of `default_token` is NULL'); 15 | 16 | $this->assertExecutionFailsWith([ 17 | 'setting' => 'unknown_setting', 18 | ], 'There is no setting with that name in the configuration: `unknown_setting`'); 19 | } 20 | 21 | /** 22 | * @return ConfigSetCommand 23 | */ 24 | protected function createCommand() 25 | { 26 | return new ConfigGetCommand(); 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | protected function getExpectedName() 33 | { 34 | return 'config:get'; 35 | } 36 | 37 | /** 38 | * @return array 39 | */ 40 | protected function getExpectedArguments() 41 | { 42 | return [ 43 | 'setting', 44 | ]; 45 | } 46 | 47 | /** 48 | * @return array 49 | */ 50 | protected function getExpectedOptions() 51 | { 52 | return []; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ConfigListCommandTest.php: -------------------------------------------------------------------------------- 1 | assertExecutionSucceedsWith([], [ 13 | '+---------------+-------+', 14 | '| Key | Value |', 15 | '+---------------+-------+', 16 | '| default_token | |', 17 | '+---------------+-------+', 18 | ]); 19 | } 20 | 21 | /** 22 | * @return ConfigSetCommand 23 | */ 24 | protected function createCommand() 25 | { 26 | return new ConfigListCommand(); 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | protected function getExpectedName() 33 | { 34 | return 'config:list'; 35 | } 36 | 37 | /** 38 | * @return array 39 | */ 40 | protected function getExpectedArguments() 41 | { 42 | return []; 43 | } 44 | 45 | /** 46 | * @return array 47 | */ 48 | protected function getExpectedOptions() 49 | { 50 | return []; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ConfigSetCommandTest.php: -------------------------------------------------------------------------------- 1 | assertExecutionSucceedsWith([ 12 | 'setting' => 'default_token', 13 | 'value' => 'fake-token', 14 | ], 'Successfully changed value of `default_token` to `fake-token`'); 15 | 16 | $this->assertExecutionFailsWith([ 17 | 'setting' => 'unknown_setting', 18 | 'value' => 'some-value', 19 | ], 'There is no setting with that name in the configuration: `unknown_setting`'); 20 | } 21 | 22 | /** 23 | * @return ConfigSetCommand 24 | */ 25 | protected function createCommand() 26 | { 27 | return new ConfigSetCommand(); 28 | } 29 | 30 | /** 31 | * @return string 32 | */ 33 | protected function getExpectedName() 34 | { 35 | return 'config:set'; 36 | } 37 | 38 | /** 39 | * @return array 40 | */ 41 | protected function getExpectedArguments() 42 | { 43 | return [ 44 | 'setting', 45 | 'value', 46 | ]; 47 | } 48 | 49 | /** 50 | * @return array 51 | */ 52 | protected function getExpectedOptions() 53 | { 54 | return []; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/CL/SlackCli/Tests/Command/ConfigUnsetCommandTest.php: -------------------------------------------------------------------------------- 1 | assertExecutionSucceedsWith([ 13 | 'setting' => 'default_token', 14 | ], 'Setting with name `default_token` has been removed from the configuration'); 15 | 16 | $this->assertExecutionSucceedsWith([ 17 | 'setting' => 'unknown_setting', 18 | ], 'No changes made; there is no setting defined with the name `unknown_setting`'); 19 | } 20 | 21 | /** 22 | * @return ConfigSetCommand 23 | */ 24 | protected function createCommand() 25 | { 26 | return new ConfigUnsetCommand(); 27 | } 28 | 29 | /** 30 | * @return string 31 | */ 32 | protected function getExpectedName() 33 | { 34 | return 'config:unset'; 35 | } 36 | 37 | /** 38 | * @return array 39 | */ 40 | protected function getExpectedArguments() 41 | { 42 | return [ 43 | 'setting', 44 | ]; 45 | } 46 | 47 | /** 48 | * @return array 49 | */ 50 | protected function getExpectedOptions() 51 | { 52 | return []; 53 | } 54 | } 55 | --------------------------------------------------------------------------------