Skip to content

Commit

Permalink
[FEATURE] Private Messaging Feature
Browse files Browse the repository at this point in the history
Resolves: #9
  • Loading branch information
NeoBlack committed Feb 19, 2016
1 parent 686e41c commit 2bf516c
Show file tree
Hide file tree
Showing 109 changed files with 1,776 additions and 21,269 deletions.
165 changes: 89 additions & 76 deletions Classes/Commands/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,23 @@
*/
namespace T3Bot\Commands;

use /** @noinspection PhpInternalEntityUsedInspection */
Doctrine\DBAL\Configuration;
use /** @noinspection PhpInternalEntityUsedInspection */ Doctrine\DBAL\Configuration;
use Doctrine\DBAL\DriverManager;
use Slack\Message\Attachment;
use Slack\Payload;
use Slack\RealTimeClient;
use T3Bot\Slack\Message;
use T3Bot\Traits\ForgerTrait;
use T3Bot\Traits\GerritTrait;
use T3Bot\Traits\SlackTrait;

/**
* Class AbstractCommand.
*/
abstract class AbstractCommand
{
use SlackTrait, ForgerTrait, GerritTrait;

const PROJECT_PHASE_DEVELOPMENT = 'development';
const PROJECT_PHASE_STABILISATION = 'stabilisation';
const PROJECT_PHASE_SOFT_FREEZE = 'soft_freeze';
Expand Down Expand Up @@ -88,46 +92,92 @@ public function process()
}

/**
* @param \T3Bot\Slack\Message|string $response
* @param \T3Bot\Slack\Message|string $messageToSent
* @param string $user
*/
public function sendResponse($response)
public function sendResponse($messageToSent, $user = null)
{
if ($response instanceof Message) {
$data['unfurl_links'] = false;
$data['unfurl_media'] = false;
$data['parse'] = 'none';
$data['text'] = $response->getText();
$data['channel'] = $this->payload->getData()['channel'];
$attachments = $response->getAttachments();
if (count($attachments)) {
$data['attachments'] = array();
}
/** @var \T3Bot\Slack\Message\Attachment $attachment */
foreach ($attachments as $attachment) {
$data['attachments'][] = Attachment::fromData([
'title' => $attachment->getTitle(),
'title_link' => $attachment->getTitleLink(),
'text' => $attachment->getText(),
'fallback' => $attachment->getFallback(),
'color' => $attachment->getColor(),
'pretext' => $attachment->getPretext(),
'author_name' => $attachment->getAuthorName(),
'author_icon' => $attachment->getAuthorIcon(),
'author_link' => $attachment->getAuthorLink(),
'image_url' => $attachment->getImageUrl(),
'thumb_url' => $attachment->getThumbUrl(),
]);
if ($user !== null) {
$this->client->apiCall('im.open', ['user' => $user])
->then(function (Payload $response) use ($messageToSent) {
$channel = $response->getData()['channel']['id'];
if ($messageToSent instanceof Message) {
$data['unfurl_links'] = false;
$data['unfurl_media'] = false;
$data['parse'] = 'none';
$data['text'] = $messageToSent->getText();
$data['channel'] = $channel;
$attachments = $messageToSent->getAttachments();
if (count($attachments)) {
$data['attachments'] = array();
}
/** @var \T3Bot\Slack\Message\Attachment $attachment */
foreach ($attachments as $attachment) {
$data['attachments'][] = Attachment::fromData([
'title' => $attachment->getTitle(),
'title_link' => $attachment->getTitleLink(),
'text' => $attachment->getText(),
'fallback' => $attachment->getFallback(),
'color' => $attachment->getColor(),
'pretext' => $attachment->getPretext(),
'author_name' => $attachment->getAuthorName(),
'author_icon' => $attachment->getAuthorIcon(),
'author_link' => $attachment->getAuthorLink(),
'image_url' => $attachment->getImageUrl(),
'thumb_url' => $attachment->getThumbUrl(),
]);
}
$message = new \Slack\Message\Message($this->client, $data);
$this->client->postMessage($message);
} elseif (is_string($messageToSent)) {
$data['unfurl_links'] = false;
$data['unfurl_media'] = false;
$data['parse'] = 'none';
$data['text'] = $messageToSent;
$data['channel'] = $channel;
$data['as_user'] = true;
$this->client->apiCall('chat.postMessage', $data);
}
});
} else {
$channel = $this->payload->getData()['channel'];
if ($messageToSent instanceof Message) {
$data['unfurl_links'] = false;
$data['unfurl_media'] = false;
$data['parse'] = 'none';
$data['text'] = $messageToSent->getText();
$data['channel'] = $channel;
$attachments = $messageToSent->getAttachments();
if (count($attachments)) {
$data['attachments'] = array();
}
/** @var \T3Bot\Slack\Message\Attachment $attachment */
foreach ($attachments as $attachment) {
$data['attachments'][] = Attachment::fromData([
'title' => $attachment->getTitle(),
'title_link' => $attachment->getTitleLink(),
'text' => $attachment->getText(),
'fallback' => $attachment->getFallback(),
'color' => $attachment->getColor(),
'pretext' => $attachment->getPretext(),
'author_name' => $attachment->getAuthorName(),
'author_icon' => $attachment->getAuthorIcon(),
'author_link' => $attachment->getAuthorLink(),
'image_url' => $attachment->getImageUrl(),
'thumb_url' => $attachment->getThumbUrl(),
]);
}
$message = new \Slack\Message\Message($this->client, $data);
$this->client->postMessage($message);
} elseif (is_string($messageToSent)) {
$data['unfurl_links'] = false;
$data['unfurl_media'] = false;
$data['parse'] = 'none';
$data['text'] = $messageToSent;
$data['channel'] = $channel;
$data['as_user'] = true;
$this->client->apiCall('chat.postMessage', $data);
}
$message = new \Slack\Message\Message($this->client, $data);
$this->client->postMessage($message);
} elseif (is_string($response)) {
$data['unfurl_links'] = false;
$data['unfurl_media'] = false;
$data['parse'] = 'none';
$data['text'] = $response;
$data['channel'] = $this->payload->getData()['channel'];
$data['as_user'] = true;
$this->client->apiCall('chat.postMessage', $data);
}
}

Expand Down Expand Up @@ -198,43 +248,6 @@ protected function buildReviewMessage($item)
return $message;
}

/**
* build a review line.
*
* @param object $item the review item
*
* @return string
*/
protected function buildReviewLine($item)
{
return $this->bold($item->subject) . ' <https://review.typo3.org/' . $item->_number
. '|Review #' . $item->_number . ' now>';
}

/**
* make text bold.
*
* @param $string
*
* @return string
*/
protected function bold($string)
{
return '*'.$string.'*';
}

/**
* make text italic.
*
* @param $string
*
* @return string
*/
protected function italic($string)
{
return '_'.$string.'_';
}

/**
* @return \Doctrine\DBAL\Connection
* @throws \Doctrine\DBAL\DBALException
Expand Down
22 changes: 0 additions & 22 deletions Classes/Commands/ForgeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,6 @@ class ForgeCommand extends AbstractCommand
'show [Issue-ID]' => 'shows the issue by given [Issue-ID]'
];

/**
* @param $item
*
* @return string
*/
protected function buildIssueMessage($item)
{
$created = substr($item->created_on, 0, 19);
$updated = substr($item->updated_on, 0, 19);
$text = $this->bold('[' . $item->tracker->name . '] ' . $item->subject)
. ' by ' . $this->italic($item->author->name) . "\n";
$text .= 'Project: '.$this->bold($item->project->name);
if (!empty($item->category->name)) {
$text .= ' | Category: '.$this->bold($item->category->name);
}
$text .= ' | Status: '.$this->bold($item->status->name)."\n";
$text .= ':calendar: Created: '.$this->bold($created).' | Last update: '.$this->bold($updated)."\n";
$text .= '<https://forge.typo3.org/issues/'.$item->id.'|:arrow_right: View on Forge>';

return $text;
}

/**
* process show.
*
Expand Down
125 changes: 125 additions & 0 deletions Classes/Commands/TellCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php
/**
* T3Bot.
*
* @author Frank Nägler <frank.naegler@typo3.org>
*
* @link http://www.t3bot.de
* @link http://wiki.typo3.org/T3Bot
*/
namespace T3Bot\Commands;

/**
* Class TellCommand.
*/
class TellCommand extends AbstractCommand
{
const PRESENCE_ACTIVE = 'active';
const PRESENCE_AWAY = 'away';

/**
* @var string
*/
protected $commandName = 'tell';

/**
* @var array
*/
protected $helpCommands = [
'help' => 'shows this help',
'tell [@to-user] about review:[Gerrit-ID]' => 'tell the target user about the given review',
'tell [@to-user] about forge:[Issue-ID]' => 'tell the target user about the given forge issue',
'tell [@to-user] [your message]' => 'tell the target user your message',
];

/**
* @return bool|string
*/
public function process()
{
$message = $this->payload->getData()['text'];
$this->params = array_map('trim', explode(' ', $message));
$result = false;
if ($this->params[0] === 'tell') {
$result = $this->processTell();
}
return $result;
}

/**
* @param string $user
* @param string $presence
*/
public function processPresenceChange($user, $presence)
{
if ($presence === self::PRESENCE_ACTIVE) {
$notifications = $this->getDatabaseConnection()
->fetchAll(
'SELECT * FROM notifications WHERE to_user = ? AND delivered = ?',
[$user, '0000-00-00 00:00:00']
);
foreach ($notifications as $notification) {
if (strpos($notification['message'], 'review:') === 0) {
$parts = explode(':', $notification['message']);
$refId = trim($parts[1]);
$result = $this->queryGerrit('change:' . $refId);
$msg = '*Hi <@' . $user . '>, <@' . $notification['from_user'] . '>'
. ' ask you to look at this patch:*';
foreach ($result as $item) {
if ($item->_number == $refId) {
$message = $this->buildReviewMessage($item);
$message->setText($msg);
$this->sendResponse($message, $user);
}
}
} elseif (strpos($notification['message'], 'forge:') === 0) {
$parts = explode(':', $notification['message']);
$issueNumber = (int)trim($parts[1]);
$result = $this->queryForge("issues/{$issueNumber}");
if ($result) {
$msg = '*Hi <@' . $user . '>, <@' . $notification['from_user'] . '>'
. ' ask you to look at this issue:*';
$this->sendResponse($msg . "\n" . $this->buildIssueMessage($result->issue), $user);
}
} else {
$msg = '*Hi <@' . $user . '>, here is a message from <@' . $notification['from_user'] . '>'
. ' for you:*';
$this->sendResponse($msg . "\n" . $notification['message'], $user);
}
$now = new \DateTime();
$now->setTimestamp(time());
$this->getDatabaseConnection()->update(
'notifications',
['delivered' => $now],
['id' => $notification['id']],
['datetime']
);
}
}
}

/**
* @return string
*/
protected function processTell()
{
$params = $this->params;
array_shift($params);
$toUser = array_shift($params);
$toUser = str_replace('<', '', $toUser);
$toUser = str_replace('>', '', $toUser);
$toUser = str_replace('@', '', $toUser);
if ($params[0] === 'about'
&& (strpos($params[1], 'review:') !== false || strpos($params[1], 'forge:') !== false)) {
$message = $params[1];
} else {
$message = implode(' ', $params);
}
$this->getDatabaseConnection()->insert('notifications', [
'from_user' => $this->payload->getData()['user'],
'to_user' => $toUser,
'message' => $message
]);
return 'OK, I will tell <@' . $toUser . '> about your message';
}
}
13 changes: 11 additions & 2 deletions Classes/Slack/CommandResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,18 @@ public function resolveCommand()
if (class_exists($commandClass)) {
return new $commandClass($this->payload, $this->client);
}

$parts = explode(' ', $message);
$command = ucfirst(strtolower($parts[0]));
$commandClass = '\\T3Bot\\Commands\\' . $command . 'Command';
if (class_exists($commandClass)) {
return new $commandClass($this->payload, $this->client);
}

$resultCommand = false;
if (strpos($message, 'botty') !== false || strpos($message, $GLOBALS['config']['slack']['botId']) !== false) {
return new BottyCommand($this->payload, $this->client);
$resultCommand = new BottyCommand($this->payload, $this->client);
}
return false;
return $resultCommand;
}
}
Loading

0 comments on commit 2bf516c

Please sign in to comment.