slack slackbot

Creating a slackbot to manage VPS’s in openstack – Part 2

Alright, so a little recap from part 1: Ive used a wrapper for a PHP slackbot, made the SSH2 extension available for my PHP 7 setup and now we are going to work on combining these various things. Read the part 1 here: https://devrant.com/creating-a-slackbot-to-manage-vpss-in-openstack-part-1/

Creating the slackbot in PHP

So, when taking the wrapper from here: https://github.com/jclg/php-slack-bot we can actually start working with it.

When I started I just created a single new file. You should make a class and autoload this, but for “testing and lazy purposes” I skipped this part.

require 'vendor/autoload.php';

use PhpSlackBot\Bot;

// Custom command
class FixCommand extends \PhpSlackBot\Command\BaseCommand {

}
$bot = new Bot();
$bot->setToken('slacktoken-here');
$bot->loadCommand(new FixCommand());
$bot->run();

So this is the first setup. Basically we require the wrapper, and init the bot. Setting our slack token for our team, and registering our “command”. With the run function we are actually running the bot. It will listen to the channel(s) and you can start processing on commands / messages being sent in the channel.

Retrieving commands and arguments from slack

So the next part is to actually do something when you talk to the bot. I have set my bot’s name to “simon”.  In slack I want to type  “simon help”, and simon should return things regarding the help command.

Starting with a function to retrieve the arguments:


private function getArgs( $message ) {
	$this->args = array();
	if ( isset( $message['text'] ) ) {
		$this->args = array_values( array_filter( explode( ' ', $message['text'] ) ) );
	}
	$commandName = $this->getName();
	// Remove args which are before the command name
	$finalArgs = array();
	$remove    = true;
	foreach ( $this->args as $arg ) {
		if ( $commandName == $arg ) {
			$remove = false;
		}
		if ( ! $remove ) {
			$finalArgs[] = $arg;
		}
	}
	
	return $finalArgs;
}

The next part is fairly easy, I just made a switch on the commands. First I made sure that “simon” was the first argument passed before actually doing something. Otherwise I would run the function linked to the command:


if ( $this->args[0] !== 'simon' ) {
	return false;
}

switch ( $this->args[1] ) {
	case
	"help":
		$this->help();
		break;
	case "find":
		$this->find();
		break;
	case "lookup":
		$this->find();
		break;
	case "restart":
		$this->command( "restart" );
		break;
	case "status":
		$this->command( "status" );
		break;
	case "cloud":
		$this->cloud();
		break;
	default:
		$this->badArg();
}

Using PHP SSH2

So, based on some commands, I want to execute a command on a remote VPS. Therefor we start with SSH2. Just start with the basic configuration:


public $ssh_host = '111.222.333.444';
private $ssh_port = 22;
private $ssh_auth_user = 'user';
private $ssh_auth_pub = '/user/.ssh/id_rsa.pub';
private $ssh_auth_priv = '/user/.ssh/id_rsa';
private $ssh_auth_pass;
private $connection;

Our connect function is pretty simple:


    public function connect() {
        if (!($this->connection = ssh2_connect($this->ssh_host, $this->ssh_port))) {
            throw new Exception('Cannot connect to server');
        }

        if (!ssh2_auth_pubkey_file($this->connection, $this->ssh_auth_user, $this->ssh_auth_pub, $this->ssh_auth_priv, $this->ssh_auth_pass)) {
            throw new Exception('Autentication rejected by server');
        }
    }

And next is our “execute” function, that will actually send our command to the VPS:


    public function exec($cmd) {
        if (!($stream = ssh2_exec($this->connection, $cmd))) {
            throw new Exception('SSH command failed');
        }
        stream_set_blocking($stream, true);
        $data = "";
        while ($buf = fread($stream, 4096)) {
            $data .= $buf;
        }
        fclose($stream);
        return $data;
    }

In the next part I will explain how we can execute commands via a tower to our VPS and return the output back to slack!

part 1
This page
Next part!

Leave a Reply

Your email address will not be published. Required fields are marked *