Enhancements
This commit is contained in:
parent
9d66b5ed91
commit
4533b1d0ed
@ -55,7 +55,7 @@ class API
|
||||
{
|
||||
$this->_token = $o->token;
|
||||
|
||||
Log::debug(sprintf('%s:Slack API with token [%s]',static::LOGKEY,$this->_token->token_hidden),['m'=>__METHOD__]);
|
||||
Log::debug(sprintf('%s:Slack API with token [%s]',static::LOGKEY,$this->_token ? $this->_token->token_hidden : NULL),['m'=>__METHOD__]);
|
||||
}
|
||||
|
||||
public function authTest(): Test
|
||||
|
@ -19,9 +19,9 @@ abstract class Base
|
||||
|
||||
public const signature_version = 'v0';
|
||||
|
||||
public function __construct(Request $request)
|
||||
public function __construct(array $request)
|
||||
{
|
||||
$this->_data = json_decode(json_encode($request->all()));
|
||||
$this->_data = json_decode(json_encode($request));
|
||||
|
||||
if (get_class($this) == self::class)
|
||||
Log::debug(sprintf('SB-:Received from Slack [%s]',get_class($this)),['m'=>__METHOD__]);
|
||||
@ -50,6 +50,7 @@ abstract class Base
|
||||
|
||||
if (! $o->exists and $create) {
|
||||
$o->team_id = $this->team()->id;
|
||||
$o->active = FALSE;
|
||||
$o->save();
|
||||
}
|
||||
|
||||
|
@ -18,87 +18,13 @@ class BlockKit implements \JsonSerializable
|
||||
$this->_data = collect();
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return $this->_data->count();
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a BlockKit Button
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $value
|
||||
* @param string|null $action_id
|
||||
* @return \Illuminate\Support\Collection
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function button(string $label,string $value,string $action_id=NULL): Collection
|
||||
{
|
||||
$x = collect();
|
||||
$x->put('type','button');
|
||||
$x->put('text',$this->text($label,'plain_text'));
|
||||
$x->put('value',$value);
|
||||
|
||||
if ($action_id)
|
||||
$x->put('action_id',$action_id);
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param int $minlength
|
||||
* @param string $placeholder
|
||||
* @param bool $multiline
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function input(string $label,string $action,int $minlength,string $placeholder='',bool $multiline=FALSE,string $hint='',string $initial='')
|
||||
{
|
||||
$this->_data->put('type','input');
|
||||
$this->_data->put('element',[
|
||||
'type'=>'plain_text_input',
|
||||
'action_id'=>$action,
|
||||
'placeholder'=>$this->text($placeholder ?: ' ','plain_text'),
|
||||
'multiline'=>$multiline,
|
||||
'min_length'=>$minlength,
|
||||
'initial_value'=>$initial,
|
||||
]);
|
||||
$this->_data->put('label',[
|
||||
'type'=>'plain_text',
|
||||
'text'=>$label,
|
||||
'emoji'=>true,
|
||||
]);
|
||||
$this->_data->put('optional',$minlength ? FALSE : TRUE);
|
||||
|
||||
if ($hint)
|
||||
$this->_data->put('hint',$this->text($hint,'plain_text'));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BlockKit Text item
|
||||
*
|
||||
* @param string $text
|
||||
* @param string $type
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function text(string $text,string $type='mrkdwn'): array
|
||||
{
|
||||
// Quick Validation
|
||||
if (! in_array($type,['mrkdwn','plain_text']))
|
||||
throw new \Exception('Invalid text type: '.$type);
|
||||
|
||||
return [
|
||||
'type'=>$type,
|
||||
'text'=>$text,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,256 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Slack\BlockKit;
|
||||
|
||||
/**
|
||||
* Class Blockkit Block
|
||||
* Represents a Block used in Blockkit
|
||||
*
|
||||
* @package Slack\Blockkit
|
||||
*/
|
||||
class Block extends BlockKit
|
||||
{
|
||||
/**
|
||||
* Add Actions Block
|
||||
*
|
||||
* @param Collection $elements
|
||||
* @return $this
|
||||
*/
|
||||
public function addAction(Collection $elements): self
|
||||
{
|
||||
// Initialise
|
||||
$this->_data = collect();
|
||||
|
||||
$this->_data->put('type','actions');
|
||||
$this->_data->put('elements',$elements);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A context block
|
||||
*
|
||||
* @param Collection $elements
|
||||
* @return $this
|
||||
*/
|
||||
public function addContext(Collection $elements): self
|
||||
{
|
||||
// Initialise
|
||||
$this->_data = collect();
|
||||
|
||||
$this->_data->put('type','context');
|
||||
$this->_data->put('elements',$elements);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a bock divider
|
||||
*/
|
||||
public function addDivider(): self
|
||||
{
|
||||
$this->_data->put('type','divider');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a block header
|
||||
*
|
||||
* @param string $text
|
||||
* @param string $type
|
||||
* @return Block
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addHeader(string $text,string $type='plain_text'): self
|
||||
{
|
||||
$this->_data->put('type','header');
|
||||
$this->_data->put('text',$this->text($text,$type));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a multiselect that queries back to the server for values
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addMultiSelectInput(string $label,string $action): self
|
||||
{
|
||||
$this->_data->put('type','section');
|
||||
$this->_data->put('text',$this->text('mrkdwn',$label));
|
||||
$this->_data->put('accessory',[
|
||||
'action_id'=>$action,
|
||||
'type'=>'multi_external_select',
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param Collection $options
|
||||
* @param Collection|null $selected
|
||||
* @param int|null $maximum
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addMultiSelectStaticInput(string $label,string $action,Collection $options,Collection $selected=NULL,int $maximum=NULL): self
|
||||
{
|
||||
$this->_data->put('type','section');
|
||||
$this->_data->put('text',$this->text($label,'mrkdwn'));
|
||||
|
||||
$x = collect();
|
||||
$x->put('action_id',$action);
|
||||
$x->put('type','multi_static_select');
|
||||
$x->put('options',$options->transform(function ($item) {
|
||||
return ['text'=>$this->text($item->name,'plain_text'),'value'=>(string)$item->id];
|
||||
}));
|
||||
|
||||
if ($selected and $selected->count())
|
||||
$x->put('initial_options',$selected->transform(function ($item) {
|
||||
return ['text'=>$this->text($item->name,'plain_text'),'value'=>(string)$item->id];
|
||||
}));
|
||||
|
||||
if ($maximum)
|
||||
$x->put('max_selected_items',$maximum);
|
||||
|
||||
$this->_data->put('accessory',$x);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $options
|
||||
* @param string $action
|
||||
* @return Collection
|
||||
*/
|
||||
public function addOverflow(Collection $options,string $action): Collection
|
||||
{
|
||||
return collect([
|
||||
'type'=>'overflow',
|
||||
'options'=>$options,
|
||||
'action_id'=>$action,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A section block
|
||||
*
|
||||
* @param string $text
|
||||
* @param string $type
|
||||
* @param Collection|null $accessories
|
||||
* @param string|null $block_id
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addSection(string $text,string $type='mrkdwn',Collection $accessories=NULL,string $block_id=NULL): self
|
||||
{
|
||||
// Initialise
|
||||
$this->_data = collect();
|
||||
|
||||
$this->_data->put('type','section');
|
||||
$this->_data->put('text',$this->text($text,$type));
|
||||
|
||||
if ($block_id)
|
||||
$this->_data->put('block_id',$block_id);
|
||||
|
||||
if ($accessories AND $accessories->count())
|
||||
$this->_data->put('accessory',$accessories);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param Collection $options
|
||||
* @param string|null $default
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addSelect(string $label,string $action,Collection $options,string $default=NULL): self
|
||||
{
|
||||
$this->_data->put('type','section');
|
||||
$this->_data->put('text',$this->text($label,'mrkdwn'));
|
||||
|
||||
// Accessories
|
||||
$x = collect();
|
||||
$x->put('action_id',$action);
|
||||
$x->put('type','static_select');
|
||||
$x->put('options',$options->map(function ($item) {
|
||||
if (is_array($item))
|
||||
$item = (object)$item;
|
||||
|
||||
return [
|
||||
'text'=>[
|
||||
'type'=>'plain_text',
|
||||
'text'=>(string)$item->name,
|
||||
],
|
||||
'value'=>(string)($item->value ?: $item->id)
|
||||
];
|
||||
}));
|
||||
|
||||
if ($default) {
|
||||
$choice = $options->filter(function($item) use ($default) {
|
||||
if (is_array($item))
|
||||
$item = (object)$item;
|
||||
|
||||
return ($item->value == $default) ? $item : NULL;
|
||||
})->filter()->pop();
|
||||
|
||||
if ($choice) {
|
||||
$x->put('initial_option',[
|
||||
'text'=>$this->text($choice['name'],'plain_text'),
|
||||
'value'=>(string)$choice['value']
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_data->put('accessory',$x);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a single-line input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param string $placeholder
|
||||
* @param int $minlength
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addSingleLineInput(string $label,string $action,string $placeholder='',int $minlength=5,string $hint='',string $initial=''): self
|
||||
{
|
||||
return $this->input($label,$action,$minlength,$placeholder,FALSE,$hint,$initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a multi-line input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param string $placeholder
|
||||
* @param int $minlength
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function addMultiLineInput(string $label,string $action,string $placeholder='',int $minlength=20,string $hint='',string $initial=''): self
|
||||
{
|
||||
return $this->input($label,$action,$minlength,$placeholder,TRUE,$hint,$initial);
|
||||
}
|
||||
|
||||
}
|
@ -3,9 +3,11 @@
|
||||
namespace Slack\Blockkit;
|
||||
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Blocks\TextEmoji;
|
||||
|
||||
/**
|
||||
* This class creates a slack actions used in BlockKit Actions
|
||||
* @todo Still needed?
|
||||
*/
|
||||
class BlockAction extends BlockKit
|
||||
{
|
||||
@ -18,15 +20,16 @@ class BlockAction extends BlockKit
|
||||
* @param string $style
|
||||
* @return BlockAction
|
||||
* @throws \Exception
|
||||
* @deprecated Move to Blocks/Button?
|
||||
*/
|
||||
public function addButton(string $text,string $action,string $value,string $style=''): self
|
||||
public function addButton(TextEmoji $text,string $action,string $value,string $style=''): self
|
||||
{
|
||||
if ($style AND ! in_array($style,['primary','danger']))
|
||||
abort('Invalid style: '.$style);
|
||||
|
||||
$this->_data->put('type','button');
|
||||
$this->_data->put('action_id',$action);
|
||||
$this->_data->put('text',$this->text($text,'plain_text'));
|
||||
$this->_data->put('text',$text);
|
||||
$this->_data->put('value',$value);
|
||||
|
||||
if ($style)
|
||||
|
341
src/Blockkit/Blocks.php
Normal file
341
src/Blockkit/Blocks.php
Normal file
@ -0,0 +1,341 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Exceptions\SlackException;
|
||||
use Slack\Blockkit\Blocks\{Button,Text,TextEmoji};
|
||||
|
||||
/**
|
||||
* Class Blockkit Block
|
||||
* Represents a list of Blockit blocks
|
||||
*
|
||||
* @package Slack\Blockkit
|
||||
*/
|
||||
class Blocks extends BlockKit
|
||||
{
|
||||
/**
|
||||
* Actions
|
||||
*
|
||||
* @param array $items
|
||||
* @return Blocks
|
||||
*/
|
||||
private function actions(array $items): self
|
||||
{
|
||||
$this->_data->push(array_merge(['type'=>'actions'],$items));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add actions block
|
||||
*
|
||||
* @param Collection $elements
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addActionElements(Collection $elements): self
|
||||
{
|
||||
$this->actions(['elements'=>$elements]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add context items
|
||||
*
|
||||
* @param Collection $items
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addContextElements(Collection $items): self
|
||||
{
|
||||
return $this->context(['elements'=>$items]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a bock divider
|
||||
*
|
||||
* @returns Blocks
|
||||
*/
|
||||
public function addDivider(): self
|
||||
{
|
||||
$this->_data->push(['type'=>'divider']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a block header
|
||||
*
|
||||
* @param string $text
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addHeader(string $text): self
|
||||
{
|
||||
$this->_data->push(['type'=>'header','text'=>TextEmoji::item($text,TRUE)]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $options
|
||||
* @param string $action_id
|
||||
* @return Collection
|
||||
* @todo To Check
|
||||
*/
|
||||
public function addOverflow(Collection $options,string $action_id): Collection
|
||||
{
|
||||
return collect([
|
||||
'type'=>'overflow',
|
||||
'options'=>$options,
|
||||
'action_id'=>$action_id,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section with accessories
|
||||
*
|
||||
* @param Text $text
|
||||
* @param Button $accessory
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addSectionAccessoryButton(Text $text,Button $accessory): self
|
||||
{
|
||||
return $this->section([
|
||||
'text'=>$text,
|
||||
'accessory'=>$accessory,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Text $label
|
||||
* @param string $action
|
||||
* @param Collection $options
|
||||
* @param string|null $default
|
||||
* @return Blocks
|
||||
* @deprecated
|
||||
* @todo Look at addSectionAccessory
|
||||
*/
|
||||
public function addSelect(Text $label,string $action,Collection $options,string $default=NULL): self
|
||||
{
|
||||
$this->_data->put('type','section');
|
||||
$this->_data->put('text',$label);
|
||||
|
||||
// Accessories
|
||||
$x = collect();
|
||||
$x->put('action_id',$action);
|
||||
$x->put('type','static_select');
|
||||
$x->put('options',$options->map(function ($item) {
|
||||
if (is_array($item))
|
||||
$item = (object)$item;
|
||||
|
||||
return [
|
||||
'text'=>[
|
||||
'type'=>'plain_text',
|
||||
'text'=>(string)$item->name,
|
||||
],
|
||||
'value'=>(string)($item->value ?: $item->id)
|
||||
];
|
||||
}));
|
||||
|
||||
if ($default) {
|
||||
$choice = $options->filter(function($item) use ($default) {
|
||||
if (is_array($item))
|
||||
$item = (object)$item;
|
||||
|
||||
return ($item->value == $default) ? $item : NULL;
|
||||
})->filter()->pop();
|
||||
|
||||
if ($choice) {
|
||||
$x->put('initial_option',[
|
||||
'text'=>TextEmoji::item($choice['name']),
|
||||
'value'=>(string)$choice['value']
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->_data->put('accessory',$x);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section with fields
|
||||
* @param Collection $items
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addSectionFields(Collection $items): self
|
||||
{
|
||||
return $this->section(['fields'=>$items]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a multiselect that queries back to the server for values
|
||||
*
|
||||
* @param Text $label
|
||||
* @param string $action
|
||||
* @return Blocks
|
||||
* @todo To Change - and rename addSectionMultiSelectInput()
|
||||
* @deprecated
|
||||
*/
|
||||
public function addMultiSelectInput(Text $label,string $action): self
|
||||
{
|
||||
$this->_data->put('type','section');
|
||||
$this->_data->put('text',$label);
|
||||
$this->_data->put('accessory',[
|
||||
'action_id'=>$action,
|
||||
'type'=>'multi_external_select',
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section with a multi select list
|
||||
*
|
||||
* @param Text $label
|
||||
* @param string $action
|
||||
* @param Collection $options
|
||||
* @param Collection|null $selected
|
||||
* @param int|null $maximum
|
||||
* @return Blocks
|
||||
* @throws \Exception
|
||||
* @note Slack only allows 100 items
|
||||
*/
|
||||
public function addSectionMultiSelectStaticInput(Text $label,string $action,Collection $options,Collection $selected=NULL,int $maximum=NULL): self
|
||||
{
|
||||
if ($options->count() > 100)
|
||||
throw new SlackException('Selection list cannot have more than 100 items.');
|
||||
|
||||
$x = collect();
|
||||
$x->put('action_id',$action);
|
||||
$x->put('type','multi_static_select');
|
||||
$x->put('options',$options->transform(function ($item) {
|
||||
return ['text'=>TextEmoji::item($item->name),'value'=>(string)$item->id];
|
||||
}));
|
||||
|
||||
if ($selected and $selected->count())
|
||||
$x->put('initial_options',$selected->transform(function ($item) {
|
||||
return ['text'=>TextEmoji::item($item->name),'value'=>(string)$item->id];
|
||||
}));
|
||||
|
||||
if ($maximum)
|
||||
$x->put('max_selected_items',$maximum);
|
||||
|
||||
return $this->section([
|
||||
'text' => $label,
|
||||
'accessory' => $x
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a section with just text
|
||||
*
|
||||
* @param Text $text
|
||||
* @return Blocks
|
||||
*/
|
||||
public function addSectionText(Text $text): self
|
||||
{
|
||||
return $this->section(['text'=>$text]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A context block
|
||||
*
|
||||
* @param array $items
|
||||
* @return Blocks
|
||||
*/
|
||||
private function context(array $items): self
|
||||
{
|
||||
$this->_data->push(array_merge(['type'=>'context'],$items));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param int $minlength
|
||||
* @param string $placeholder
|
||||
* @param bool $multiline
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
* @deprecated - to optimize
|
||||
*/
|
||||
protected function input(string $label,string $action,int $minlength,string $placeholder='',bool $multiline=FALSE,string $hint='',string $initial='')
|
||||
{
|
||||
$this->_data->put('type','input');
|
||||
$this->_data->put('element',[
|
||||
'type'=>'plain_text_input',
|
||||
'action_id'=>$action,
|
||||
'placeholder'=>$this->text($placeholder ?: ' ','plain_text'),
|
||||
'multiline'=>$multiline,
|
||||
'min_length'=>$minlength,
|
||||
'initial_value'=>$initial,
|
||||
]);
|
||||
$this->_data->put('label',[
|
||||
'type'=>'plain_text',
|
||||
'text'=>$label,
|
||||
'emoji'=>true,
|
||||
]);
|
||||
$this->_data->put('optional',$minlength ? FALSE : TRUE);
|
||||
|
||||
if ($hint)
|
||||
$this->_data->put('hint',$this->text($hint,'plain_text'));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A section block
|
||||
*
|
||||
* @param array $items
|
||||
* @return Blocks
|
||||
*/
|
||||
private function section(array $items): self
|
||||
{
|
||||
$this->_data->push(array_merge(['type'=>'section'],$items));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a single-line input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param string $placeholder
|
||||
* @param int $minlength
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return Blocks
|
||||
* @throws \Exception
|
||||
* @deprecated - to optimize
|
||||
*/
|
||||
public function addSingleLineInput(string $label,string $action,string $placeholder='',int $minlength=5,string $hint='',string $initial=''): self
|
||||
{
|
||||
return $this->input($label,$action,$minlength,$placeholder,FALSE,$hint,$initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a multi-line input dialog
|
||||
*
|
||||
* @param string $label
|
||||
* @param string $action
|
||||
* @param string $placeholder
|
||||
* @param int $minlength
|
||||
* @param string $hint
|
||||
* @param string $initial
|
||||
* @return Blocks
|
||||
* @throws \Exception
|
||||
* @deprecated - to optimize
|
||||
*/
|
||||
public function addMultiLineInput(string $label,string $action,string $placeholder='',int $minlength=20,string $hint='',string $initial=''): self
|
||||
{
|
||||
return $this->input($label,$action,$minlength,$placeholder,TRUE,$hint,$initial);
|
||||
}
|
||||
}
|
30
src/Blockkit/Blocks/Button.php
Normal file
30
src/Blockkit/Blocks/Button.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
final class Button
|
||||
{
|
||||
public string $type;
|
||||
public TextEmoji $text;
|
||||
public string $value;
|
||||
public string $url;
|
||||
public string $action_id;
|
||||
public string $style;
|
||||
|
||||
public function __construct(TextEmoji $text,string $value,string $action_id,string $url=NULL,string $style=NULL)
|
||||
{
|
||||
$this->type = 'button';
|
||||
$this->text = $text;
|
||||
$this->value = $value ?: '-';
|
||||
$this->action_id = $action_id;
|
||||
if ($url)
|
||||
$this->url = $url;
|
||||
if ($style)
|
||||
$this->style = $style;
|
||||
}
|
||||
|
||||
public static function item(TextEmoji $text,string $value,string $action_id,string $url=NULL,string $style=NULL): self
|
||||
{
|
||||
return new self($text,$value,$action_id,$url,$style);
|
||||
}
|
||||
}
|
24
src/Blockkit/Blocks/Input.php
Normal file
24
src/Blockkit/Blocks/Input.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
use Slack\Blockkit\Input\Element;
|
||||
|
||||
final class Input
|
||||
{
|
||||
public string $type;
|
||||
public Element $element;
|
||||
public TextEmoji $label;
|
||||
|
||||
public function __construct(Element $element,TextEmoji $label)
|
||||
{
|
||||
$this->type = 'input';
|
||||
$this->element = $element;
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
public static function item(Element $element,TextEmoji $label): self
|
||||
{
|
||||
return new self($element,$label);
|
||||
}
|
||||
}
|
20
src/Blockkit/Blocks/Text.php
Normal file
20
src/Blockkit/Blocks/Text.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
final class Text
|
||||
{
|
||||
public string $type;
|
||||
public string $text;
|
||||
|
||||
public function __construct(string $text,string $type='mrkdwn')
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
public static function item(string $text,string $type='mrkdwn'): self
|
||||
{
|
||||
return new self($text,$type);
|
||||
}
|
||||
}
|
22
src/Blockkit/Blocks/TextEmoji.php
Normal file
22
src/Blockkit/Blocks/TextEmoji.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Blocks;
|
||||
|
||||
final class TextEmoji
|
||||
{
|
||||
public bool $emoji;
|
||||
public string $text;
|
||||
public string $type;
|
||||
|
||||
public function __construct(string $text,bool $emoji=TRUE)
|
||||
{
|
||||
$this->emoji = $emoji;
|
||||
$this->text = $text;
|
||||
$this->type = 'plain_text';
|
||||
}
|
||||
|
||||
public static function item(string $text,bool $emoji=TRUE): self
|
||||
{
|
||||
return new self($text,$emoji);
|
||||
}
|
||||
}
|
22
src/Blockkit/Input/Element.php
Normal file
22
src/Blockkit/Input/Element.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Blockkit\Input;
|
||||
|
||||
final class Element
|
||||
{
|
||||
public string $type;
|
||||
public string $action_id;
|
||||
public bool $multiline;
|
||||
|
||||
public function __construct(string $type,string $action_id,bool $multiline=FALSE)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->action_id = $action_id;
|
||||
$this->multiline = $multiline;
|
||||
}
|
||||
|
||||
public static function item(string $type,string $action_id,bool $multiline=FALSE): self
|
||||
{
|
||||
return new self($type,$action_id,$multiline);
|
||||
}
|
||||
}
|
@ -2,40 +2,36 @@
|
||||
|
||||
namespace Slack\Blockkit;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\Blocks\TextEmoji;
|
||||
|
||||
/**
|
||||
* This class creates a slack Modal Response
|
||||
*/
|
||||
class Modal extends BlockKit
|
||||
{
|
||||
protected $blocks;
|
||||
private $action = NULL;
|
||||
|
||||
public function __construct(string $title)
|
||||
public function __construct(TextEmoji $title)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->blocks = collect();
|
||||
|
||||
$this->_data->put('type','modal');
|
||||
$this->_data->put('title',$this->text(Str::limit($title,24),'plain_text'));
|
||||
$this->_data->put('title',$title);
|
||||
}
|
||||
|
||||
/*
|
||||
public function action(string $action)
|
||||
{
|
||||
$this->action = $action;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* The data that will be returned when converted to JSON.
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
if ($this->blocks->count())
|
||||
$this->_data->put('blocks',$this->blocks);
|
||||
|
||||
switch ($this->action) {
|
||||
case 'clear':
|
||||
return ['response_action'=>'clear'];
|
||||
@ -51,23 +47,24 @@ class Modal extends BlockKit
|
||||
/**
|
||||
* Add a block to the modal
|
||||
*
|
||||
* @param Block $block
|
||||
* @param Blocks $blocks
|
||||
* @return $this
|
||||
*/
|
||||
public function addBlock(Block $block): self
|
||||
public function setBlocks(Blocks $blocks): self
|
||||
{
|
||||
$this->blocks->push($block);
|
||||
$this->_data->put('blocks',$blocks);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function callback(string $id): self
|
||||
public function setCallback(string $id): self
|
||||
{
|
||||
$this->_data->put('callback_id',$id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/*
|
||||
public function close(string $text='Cancel'): self
|
||||
{
|
||||
$this->_data->put('close',
|
||||
@ -112,4 +109,5 @@ class Modal extends BlockKit
|
||||
|
||||
return $this;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
20
src/Channels/SlackBotChannel.php
Normal file
20
src/Channels/SlackBotChannel.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Channels;
|
||||
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class SlackBotChannel
|
||||
{
|
||||
public function send($notifiable,Notification $notification)
|
||||
{
|
||||
if (! $co = $notifiable->routeNotificationFor('slackapp',$notification)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$o = $notification->toSlack($notifiable);
|
||||
$o->setChannel($co);
|
||||
|
||||
return $o->post();
|
||||
}
|
||||
}
|
@ -60,9 +60,9 @@ abstract class API
|
||||
* @param array $args An associative array of arguments to pass to the
|
||||
* method call.
|
||||
* @param bool $multipart Whether to send as a multipart request. Default to false
|
||||
* @param bool $callDeferred Wether to call the API asynchronous or not.
|
||||
* @param bool $callDeferred Whether to call the API asynchronous or not.
|
||||
*
|
||||
* @return \React\Promise\PromiseInterface A promise for an API response.
|
||||
* @return PromiseInterface A promise for an API response.
|
||||
*/
|
||||
public function apiCall(string $method,array $args=[],bool $multipart=FALSE,bool $callDeferred=TRUE): PromiseInterface
|
||||
{
|
||||
@ -84,7 +84,6 @@ abstract class API
|
||||
]
|
||||
]);
|
||||
|
||||
//dump(['m'=>__METHOD__,'l'=>__LINE__,'promise'=>$promise]);
|
||||
// Add requests to the event loop to be handled at a later date.
|
||||
if ($callDeferred) {
|
||||
$this->loop->futureTick(function () use ($promise) {
|
||||
|
@ -11,11 +11,15 @@ use Illuminate\Support\Facades\Log;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\Promise\Deferred;
|
||||
use React\Promise;
|
||||
use Slack\Command\Factory;
|
||||
|
||||
class SocketMode extends API
|
||||
{
|
||||
use EventEmitterTrait;
|
||||
|
||||
private const LOGKEY = 'ASM';
|
||||
|
||||
private bool $debug_reconnect = FALSE;
|
||||
private bool $connected;
|
||||
private WebSocket $websocket;
|
||||
|
||||
@ -37,7 +41,7 @@ class SocketMode extends API
|
||||
*
|
||||
* @return \React\Promise\PromiseInterface
|
||||
*/
|
||||
public function connect()
|
||||
public function connect(): Promise\PromiseInterface
|
||||
{
|
||||
$deferred = new Deferred;
|
||||
|
||||
@ -81,9 +85,9 @@ class SocketMode extends API
|
||||
|
||||
// initiate the websocket connection
|
||||
// write PHPWS things to the existing logger
|
||||
$this->websocket = new WebSocket($response['url'].'&debug_reconnects=true', $this->loop, $this->logger);
|
||||
$this->websocket = new WebSocket($response['url'].($this->debug_reconnect ? '&debug_reconnects=true' : ''),$this->loop,$this->logger);
|
||||
$this->websocket->on('message', function ($message) {
|
||||
Log::debug('Calling onMessage for',['m'=>serialize($message)]);
|
||||
Log::debug(sprintf('%s:- Calling onMessage ...',self::LOGKEY),['m'=>__METHOD__]);
|
||||
$this->onMessage($message);
|
||||
});
|
||||
|
||||
@ -124,6 +128,8 @@ class SocketMode extends API
|
||||
|
||||
$this->websocket->close();
|
||||
$this->connected = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,22 +145,36 @@ class SocketMode extends API
|
||||
/**
|
||||
* Handles incoming websocket messages, parses them, and emits them as remote events.
|
||||
*
|
||||
* @param WebSocketMessageInterface $messageRaw A websocket message.
|
||||
* @param WebSocketMessageInterface $message
|
||||
*/
|
||||
private function onMessage(WebSocketMessageInterface $message)
|
||||
{
|
||||
Log::debug('+ Start',['m'=>__METHOD__]);
|
||||
Log::debug(sprintf('%s:+ Start',self::LOGKEY),['m'=>__METHOD__]);
|
||||
|
||||
// parse the message and get the event name
|
||||
$payload = Payload::fromJson($message->getData());
|
||||
$emitted = FALSE;
|
||||
|
||||
if (isset($payload['type'])) {
|
||||
$this->emit('_internal_message', [$payload['type'], $payload]);
|
||||
|
||||
switch ($payload['type']) {
|
||||
case 'hello':
|
||||
$this->connected = TRUE;
|
||||
break;
|
||||
|
||||
case 'disconnect':
|
||||
Log::debug(sprintf('%s:- Disconnect Received, Re-Connecting...',self::LOGKEY),['m'=>__METHOD__]);
|
||||
$this->disconnect();
|
||||
$this->connect();
|
||||
break;
|
||||
|
||||
// We got an event, we'll handle it later in SlackSocketClient::class (after ACKing it).
|
||||
case 'events_api':
|
||||
case 'interactive':
|
||||
case 'slash_commands':
|
||||
break;
|
||||
|
||||
/*
|
||||
case 'team_rename':
|
||||
$this->team->data['name'] = $payload['name'];
|
||||
@ -235,18 +255,46 @@ class SocketMode extends API
|
||||
$this->users[$user->getId()] = $user;
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
Log::debug(sprintf('Unhandled type [%s]',$payload['type']),['m'=>__METHOD__,'p'=>$payload]);
|
||||
}
|
||||
|
||||
// emit an event with the attached json
|
||||
$this->emit($payload['type'], [$payload]);
|
||||
default:
|
||||
Log::debug(sprintf('%s:- Unhandled type [%s]',self::LOGKEY,$payload['type']),['m'=>__METHOD__,'p'=>$payload]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($payload['envelope_id'])) {
|
||||
if (isset($payload['accepts_response_payload']) && $payload['accepts_response_payload']) {
|
||||
switch ($payload['type']) {
|
||||
case 'slash_commands':
|
||||
$command = Factory::make($payload);
|
||||
|
||||
if (! method_exists($command,'respond')) {
|
||||
Log::alert(sprintf('%s:! Cant respond to Command [%s], no respond method',static::LOGKEY,get_class($command)),['m'=>__METHOD__]);
|
||||
abort(500,'No respond method() for '.get_class($command));
|
||||
}
|
||||
|
||||
$response = ($x=$command->respond())->isEmpty() ? NULL : $x;
|
||||
|
||||
$this->websocket->send(json_encode(['envelope_id'=>$payload['envelope_id'],'payload'=>$response]));
|
||||
$emitted = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::debug(sprintf('%s:- Unhandled type [%s] for accepts_response_payload',self::LOGKEY,$payload['type']),['m'=>__METHOD__]);
|
||||
$this->websocket->send(json_encode(['envelope_id'=>$payload['envelope_id']]));
|
||||
}
|
||||
|
||||
} else {
|
||||
// @acknowledge the event
|
||||
$this->websocket->send(json_encode(['envelope_id'=>$payload['envelope_id']]));
|
||||
Log::debug(sprintf('Responded to event [%s] for (%s)',$payload['envelope_id'],$payload['type']),['m'=>__METHOD__]);
|
||||
}
|
||||
|
||||
Log::debug(sprintf('%s:- Responded to event [%s] for (%s)',self::LOGKEY,$payload['envelope_id'],$payload['type']),['m'=>__METHOD__]);
|
||||
}
|
||||
|
||||
// If we havent already handled the event, we'll emit it to be handled upstream
|
||||
if (isset($payload['type']) && ! $emitted) {
|
||||
// emit an event with the attached json
|
||||
$this->emit($payload['type'],[$payload]);
|
||||
}
|
||||
|
||||
if (! isset($payload['type']) || $payload['type'] == 'pong') {
|
||||
@ -269,6 +317,6 @@ class SocketMode extends API
|
||||
}
|
||||
}
|
||||
|
||||
Log::debug('= End',['m'=>__METHOD__]);
|
||||
Log::debug(sprintf('%s:= End',self::LOGKEY),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
|
@ -2,16 +2,17 @@
|
||||
|
||||
namespace Slack\Command;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Base as SlackBase;
|
||||
use Slack\Blockkit\Blocks;
|
||||
use Slack\Message;
|
||||
|
||||
abstract class Base extends SlackBase
|
||||
{
|
||||
public function __construct(Request $request)
|
||||
public function __construct(array $request)
|
||||
{
|
||||
Log::info(sprintf('SCb:Slack SLASHCOMMAND Initialised [%s]',get_class($this)),['m'=>__METHOD__]);
|
||||
parent::_construct($request);
|
||||
parent::__construct($request);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,4 +52,20 @@ abstract class Base extends SlackBase
|
||||
return object_get($this->_data,'trigger_id');
|
||||
}
|
||||
}
|
||||
|
||||
protected function bot_in_channel(): ?Message
|
||||
{
|
||||
$o = new Message;
|
||||
|
||||
if (! $this->channel() || ! $this->channel()->active) {
|
||||
$blocks = new Blocks;
|
||||
|
||||
$blocks->addHeader(':robot_face: Bot not in this channel');
|
||||
$blocks->addSectionText(Blocks\Text::item(sprintf('Please add %s to this channel and try this again.',$this->team()->bot->name ?: 'the BOT')));
|
||||
|
||||
$o->setAttachments((new Message\Attachments())->setBlocks($blocks)->setColor('#ff0000'));
|
||||
}
|
||||
|
||||
return $o->isEmpty() ? NULL : $o;
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
namespace Slack\Command;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Client\Payload;
|
||||
|
||||
class Factory {
|
||||
private const LOGKEY = 'SCf';
|
||||
@ -14,39 +14,32 @@ class Factory {
|
||||
* @var array event type to event class mapping
|
||||
*/
|
||||
public const map = [
|
||||
'ask'=>Watson::class,
|
||||
'ate'=>Ask::class,
|
||||
'help'=>Help::class,
|
||||
'goto'=>Link::class,
|
||||
'leaders'=>Leaders::class,
|
||||
'products'=>Products::class,
|
||||
'review'=>Review::class,
|
||||
'wc'=>WatsonCollection::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns new event instance
|
||||
*
|
||||
* @param string $type
|
||||
* @param Request $request
|
||||
* @param array $request
|
||||
* @return Base
|
||||
*/
|
||||
public static function create(string $type,Request $request)
|
||||
public static function create(string $type,array $request): Base
|
||||
{
|
||||
$class = Arr::get(self::map,$type,Unknown::class);
|
||||
$class = Arr::get(config('slack.commands',self::map),$type,Unknown::class);
|
||||
Log::debug(sprintf('%s:Working out Slash Command Class for [%s] as [%s]',static::LOGKEY,$type,$class),['m'=>__METHOD__]);
|
||||
|
||||
if (App::environment() == 'dev')
|
||||
file_put_contents('/tmp/command.'.$type,print_r(json_decode(json_encode($request->all())),TRUE));
|
||||
if (App::environment() == 'local')
|
||||
file_put_contents('/tmp/command.'.$type,print_r(json_decode(json_encode($request)),TRUE));
|
||||
|
||||
return new $class($request);
|
||||
}
|
||||
|
||||
public static function make(Request $request): Base
|
||||
public static function make(Payload $request): Base
|
||||
{
|
||||
$data = json_decode(json_encode($request->all()));
|
||||
$command = preg_replace('/^([a-z]+)(\s?.*)/','$1',$data->text);
|
||||
$data = json_decode(json_encode($request->getData()));
|
||||
$command = preg_replace('/^([a-z]+)(\s?.*)/','$1',$data->payload->text);
|
||||
|
||||
return self::create($command ?: 'help',$request);
|
||||
return self::create($command ?: 'help',Arr::get($request->getData(),'payload'));
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
namespace Slack\Command;
|
||||
|
||||
use Slack\Message;
|
||||
use Slack\Message\Attachment;
|
||||
use Slack\Message\Attachments;
|
||||
|
||||
class Help extends Base
|
||||
{
|
||||
@ -13,12 +13,12 @@ class Help extends Base
|
||||
{
|
||||
$o = new Message;
|
||||
|
||||
$o->setText('Hi, I am the a *NEW* Bot');
|
||||
$o->setText('Hi, I am a *NEW* Bot');
|
||||
|
||||
// Version
|
||||
$a = new Attachment;
|
||||
$a->addField('Version',config('app.version'),TRUE);
|
||||
$o->addAttachment($a);
|
||||
$a = new Attachments;
|
||||
$a->addField('Version',config('app.version','unknown'),TRUE);
|
||||
$o->setAttachments($a);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ use Slack\Message;
|
||||
*/
|
||||
final class Unknown extends Base
|
||||
{
|
||||
public function __construct(Request $request)
|
||||
public function __construct(array $request)
|
||||
{
|
||||
Log::notice(sprintf('SCU:UNKNOWN Slack Interaction Option received [%s]',get_class($this)),['m'=>__METHOD__]);
|
||||
|
||||
|
@ -6,6 +6,9 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use React\EventLoop\Loop;
|
||||
use Slack\Client\SocketMode;
|
||||
use Slack\Command\Factory as SlackCommandFactory;
|
||||
use Slack\Event\Factory as SlackEventFactory;
|
||||
use Slack\Interactive\Factory as SlackInteractiveFactory;
|
||||
|
||||
class SlackSocketClient extends Command
|
||||
{
|
||||
@ -47,12 +50,20 @@ class SlackSocketClient extends Command
|
||||
$client = new SocketMode($loop);
|
||||
$client->setToken(config('slack.socket_token'));
|
||||
|
||||
$client->on('events_api', function ($data) use ($client) {
|
||||
dump(['data'=>$data]);
|
||||
$client->on('events_api',function ($data) {
|
||||
event(SlackEventFactory::make($data));
|
||||
});
|
||||
|
||||
$client->on('interactive',function ($data) {
|
||||
event(SlackInteractiveFactory::make($data));
|
||||
});
|
||||
|
||||
$client->on('slash_command',function ($data) {
|
||||
event(SlackCommandFactory::make($data));
|
||||
});
|
||||
|
||||
$client->connect()->then(function () {
|
||||
Log::debug(sprintf('%s: Connected to slack.',self::LOGKEY));
|
||||
Log::debug(sprintf('%s:- Connected to slack.',self::LOGKEY));
|
||||
});
|
||||
|
||||
$loop->run();
|
||||
|
@ -8,7 +8,7 @@ use Slack\Base as SlackBase;
|
||||
|
||||
abstract class Base extends SlackBase
|
||||
{
|
||||
public function __construct(Request $request)
|
||||
public function __construct(array $request)
|
||||
{
|
||||
Log::info(sprintf('SEb:Slack Event Initialised [%s]',get_class($this)),['m'=>__METHOD__]);
|
||||
|
||||
|
@ -6,6 +6,7 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Client\Payload;
|
||||
|
||||
class Factory {
|
||||
private const LOGKEY = 'SEf';
|
||||
@ -28,21 +29,21 @@ class Factory {
|
||||
* Returns new event instance
|
||||
*
|
||||
* @param string $type
|
||||
* @param Request $request
|
||||
* @param array $request
|
||||
* @return Base
|
||||
*/
|
||||
public static function create(string $type,Request $request)
|
||||
public static function create(string $type,array $request): Base
|
||||
{
|
||||
$class = Arr::get(self::map,$type,Unknown::class);
|
||||
Log::debug(sprintf('%s:Working out Event Class for [%s] as [%s]',static::LOGKEY,$type,$class),['m'=>__METHOD__]);
|
||||
|
||||
if (App::environment() == 'dev')
|
||||
file_put_contents('/tmp/event.'.$type,print_r($request->all(),TRUE));
|
||||
if (App::environment() == 'local')
|
||||
file_put_contents('/tmp/event.'.$type,print_r($request,TRUE));
|
||||
|
||||
return new $class($request);
|
||||
}
|
||||
|
||||
public static function make(Request $request): Base
|
||||
public static function make(Payload $request): Base
|
||||
{
|
||||
// During the life of the event, this method is called twice - once during Middleware processing, and finally by the Controller.
|
||||
static $o = NULL;
|
||||
@ -50,7 +51,7 @@ class Factory {
|
||||
|
||||
if (! $o OR ($or != $request)) {
|
||||
$or = $request;
|
||||
$o = self::create($request->input('event.type'),$request);
|
||||
$o = self::create(Arr::get($request->getData(),'payload.event.type'),Arr::get($request->getData(),'payload'));
|
||||
}
|
||||
|
||||
return $o;
|
||||
|
@ -12,10 +12,10 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
class Unknown extends Base
|
||||
{
|
||||
public function __construct(Request $request)
|
||||
public function __construct(array $request)
|
||||
{
|
||||
Log::notice(sprintf('SEU:UNKNOWN Slack Event received [%s]',get_class($this)),['m'=>__METHOD__]);
|
||||
|
||||
parent::__contruct($request);
|
||||
parent::__construct($request);
|
||||
}
|
||||
}
|
||||
|
@ -16,25 +16,6 @@ class SlackAppController extends Controller
|
||||
{
|
||||
private const LOGKEY = 'CSA';
|
||||
|
||||
protected static $scopes = [
|
||||
/*
|
||||
'channels:history',
|
||||
'channels:read',
|
||||
'chat:write',
|
||||
'chat:write.customize',
|
||||
'groups:history',
|
||||
'groups:read',
|
||||
'im:history',
|
||||
'im:read',
|
||||
'im:write',
|
||||
'team:read',
|
||||
*/
|
||||
];
|
||||
|
||||
protected static $user_scopes = [
|
||||
//'pins.write',
|
||||
];
|
||||
|
||||
private const slack_authorise_url = 'https://slack.com/oauth/v2/authorize';
|
||||
private const slack_oauth_url = 'https://slack.com/api/oauth.v2.access';
|
||||
private const slack_button = 'https://platform.slack-edge.com/img/add_to_slack.png';
|
||||
@ -173,9 +154,15 @@ class SlackAppController extends Controller
|
||||
$so->admin_id = $uo->id;
|
||||
$so->save();
|
||||
|
||||
return sprintf('All set up! Head back to your slack instance <strong>%s</strong>."',$so->description);
|
||||
return sprintf('All set up! Head back to your slack instance <strong>%s</strong>.',$so->description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define our parameters to install this Slack Integration
|
||||
*
|
||||
* @note The configuration file should include a list of scopes that this application needs
|
||||
* @return array
|
||||
*/
|
||||
private function parameters(): array
|
||||
{
|
||||
return [
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace Slack\Interactive;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Base as SlackBase;
|
||||
|
||||
@ -14,12 +13,12 @@ abstract class Base extends SlackBase
|
||||
// When retrieving multiple action values, this is the index we are retrieving.
|
||||
protected $index = 0;
|
||||
|
||||
public function __construct(Request $request)
|
||||
public function __construct(array $request)
|
||||
{
|
||||
Log::info(sprintf('SIb:Slack INTERACTIVE MESSAGE Initialised [%s]',get_class($this)),['m'=>__METHOD__]);
|
||||
|
||||
// Our data is in a payload value
|
||||
$this->_data = json_decode($request->input('payload'));
|
||||
parent::__construct($request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,25 +60,24 @@ class BlockActions extends Base
|
||||
public function __get($key)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'callback_id':
|
||||
return object_get($this->_data,'view.callback_id');
|
||||
case 'actions':
|
||||
return object_get($this->_data,$key);
|
||||
|
||||
case 'action_id':
|
||||
return object_get(Arr::get(object_get($this->_data,'actions'),$this->index),$key);
|
||||
|
||||
// An event can have more than 1 action, each action can have 1 value.
|
||||
case 'action_id':
|
||||
case 'action_key':
|
||||
return $this->action('action');
|
||||
|
||||
case 'action_value':
|
||||
return $this->action('value');
|
||||
|
||||
case 'value':
|
||||
switch (Arr::get(object_get($this->_data,'actions'),$this->index)->type) {
|
||||
case 'external_select':
|
||||
case 'overflow':
|
||||
case 'static_select':
|
||||
return object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'selected_option.value');
|
||||
default:
|
||||
return object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'value');
|
||||
}
|
||||
case 'callback_id':
|
||||
return object_get($this->_data,'view.callback_id');
|
||||
|
||||
case 'keys':
|
||||
return collect(object_get($this->_data,'view.blocks'))->pluck('accessory.action_id');
|
||||
|
||||
// For Block Actions that are messages
|
||||
case 'message_ts':
|
||||
@ -87,16 +86,41 @@ class BlockActions extends Base
|
||||
case 'channel_id':
|
||||
return object_get($this->_data,'channel.id') ?: Channel::findOrFail($this->action('value'))->channel_id;
|
||||
|
||||
case 'team_id': // view.team_id represent workspace publishing view
|
||||
return object_get($this->_data,'user.team_id');
|
||||
|
||||
case 'view_id':
|
||||
return object_get($this->_data,'view.id');
|
||||
|
||||
case 'actions':
|
||||
return object_get($this->_data,$key);
|
||||
case 'value':
|
||||
switch (Arr::get(object_get($this->_data,'actions'),$this->index)->type) {
|
||||
case 'external_select':
|
||||
case 'overflow':
|
||||
case 'static_select':
|
||||
return object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'selected_option.value');
|
||||
case 'multi_static_select':
|
||||
return object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'selected_options.value');
|
||||
default:
|
||||
return object_get(Arr::get(object_get($this->_data,'actions'),$this->index),$key);
|
||||
}
|
||||
|
||||
// For some reason this object is not making sense, and while we should be getting team.id or even view.team_id, the actual team appears to be in user.team_id
|
||||
// @todo Currently working with Slack to understand this behaviour
|
||||
case 'team_id': // view.team_id represent workspace publishing view
|
||||
return object_get($this->_data,'user.team_id');
|
||||
case 'values':
|
||||
switch (Arr::get(object_get($this->_data,'actions'),$this->index)->type) {
|
||||
// @todo To Check
|
||||
case 'external_select':
|
||||
// @todo To Check
|
||||
case 'overflow':
|
||||
// @todo To Check
|
||||
case 'static_select':
|
||||
return count(object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'selected_option'));
|
||||
case 'multi_static_select':
|
||||
return collect(object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'selected_options'))->pluck('value');
|
||||
default:
|
||||
return count(object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'value'));
|
||||
}
|
||||
|
||||
case 'value_count':
|
||||
return count($this->values);
|
||||
|
||||
default:
|
||||
return parent::__get($key);
|
||||
@ -116,16 +140,16 @@ class BlockActions extends Base
|
||||
$value = NULL;
|
||||
|
||||
// We only take the action up to the pipe symbol
|
||||
$action_id = object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'action_id');
|
||||
$action_key = object_get(Arr::get(object_get($this->_data,'actions'),$this->index),'action_id');
|
||||
|
||||
if (preg_match($regex,$action_id)) {
|
||||
$action = preg_replace($regex,'$1',$action_id);
|
||||
$value = preg_replace($regex,'$2',$action_id);
|
||||
if (preg_match($regex,$action_key)) {
|
||||
$action = preg_replace($regex,'$1',$action_key);
|
||||
$value = preg_replace($regex,'$2',$action_key);
|
||||
}
|
||||
|
||||
switch ($key) {
|
||||
case 'action':
|
||||
return $action ?: $action_id;
|
||||
return $action ?: $action_key;
|
||||
case 'value':
|
||||
return $value;
|
||||
}
|
||||
@ -142,20 +166,4 @@ class BlockActions extends Base
|
||||
{
|
||||
return object_get($this->_data,'message') ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the selected options from a block action actions array
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function selected_options(): Collection
|
||||
{
|
||||
$result = collect();
|
||||
|
||||
foreach (Arr::get(object_get($this->_data,'actions'),'0')->selected_options as $option) {
|
||||
$result->push($option->value);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Client\Payload;
|
||||
|
||||
class Factory {
|
||||
private const LOGKEY = 'SIF';
|
||||
@ -25,30 +26,29 @@ class Factory {
|
||||
* Returns new event instance
|
||||
*
|
||||
* @param string $type
|
||||
* @param Request $request
|
||||
* @param array $request
|
||||
* @return Base
|
||||
*/
|
||||
public static function create(string $type,Request $request)
|
||||
public static function create(string $type,array $request): Base
|
||||
{
|
||||
$class = Arr::get(self::map,$type,Unknown::class);
|
||||
Log::debug(sprintf('%s:Working out Interactive Message Event Class for [%s] as [%s]',static::LOGKEY,$type,$class),['m'=>__METHOD__]);
|
||||
|
||||
if (App::environment() == 'dev')
|
||||
file_put_contents('/tmp/interactive.'.$type,print_r(json_decode($request->input('payload')),TRUE));
|
||||
if (App::environment() == 'local')
|
||||
file_put_contents('/tmp/interactive.'.$type,print_r($request,TRUE));
|
||||
|
||||
return new $class($request);
|
||||
}
|
||||
|
||||
public static function make(Request $request): Base
|
||||
public static function make(Payload $request): Base
|
||||
{
|
||||
// During the life of the event, this method is called twice - once during Middleware processing, and finally by the Controller.
|
||||
static $o = NULL;
|
||||
static $or = NULL;
|
||||
|
||||
if (! $o OR ($or != $request)) {
|
||||
$data = json_decode($request->input('payload'));
|
||||
$or = $request;
|
||||
$o = self::create($data->type,$request);
|
||||
$o = self::create(Arr::get($request->getData(),'payload.type'),Arr::get($request->getData(),'payload'));
|
||||
}
|
||||
|
||||
return $o;
|
||||
|
@ -12,7 +12,7 @@ use Illuminate\Support\Facades\Log;
|
||||
*/
|
||||
class Unknown extends Base
|
||||
{
|
||||
public function __construct(Request $request)
|
||||
public function __construct(array $request)
|
||||
{
|
||||
Log::notice(sprintf('SIU:UNKNOWN Slack Interaction Option received [%s]',get_class($this)),['m'=>__METHOD__]);
|
||||
|
||||
|
30
src/Listeners/AppHomeOpenedListener.php
Normal file
30
src/Listeners/AppHomeOpenedListener.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use App\Jobs\SlackHomeTabUpdate;
|
||||
use Slack\Event\AppHomeOpened;
|
||||
|
||||
class AppHomeOpenedListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LAH';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param AppHomeOpened $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(AppHomeOpened $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:App Home Page open for [%s] in team [%s]',self::LOGKEY,$event->user_id,$event->team_id),['m'=>__METHOD__]);
|
||||
|
||||
dispatch((new SlackHomeTabUpdate($event))->onQueue('high'));
|
||||
}
|
||||
}
|
85
src/Listeners/BlockActionListener.php
Normal file
85
src/Listeners/BlockActionListener.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Jobs\DeleteChat;
|
||||
use Slack\Interactive\BlockActions;
|
||||
|
||||
class BlockActionListener
|
||||
{
|
||||
protected const LOGKEY = 'LBA';
|
||||
|
||||
// Block actions arent queued, since slack expects a response to the request
|
||||
//public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param BlockActions $event
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function handle(BlockActions $event): void
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Block Action for Callback [%s] User [%s] in [%s]',self::LOGKEY,$event->callback_id,$event->user_id,$event->team_id),['m'=>__METHOD__]);
|
||||
|
||||
switch ($event->callback_id) {
|
||||
// Messages that generate a block action dont have a callback ID
|
||||
case NULL:
|
||||
Log::debug(sprintf('%s:Callback NULL [%s] (%s)',self::LOGKEY,$event->isMessage(),$event->action_id),['m'=>__METHOD__]);
|
||||
|
||||
$this->messageEvent($event);
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::notice(sprintf('%s:Unhandled CALLBACK [%s]',self::LOGKEY,$event->callback_id),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Events from messages
|
||||
*
|
||||
* @param BlockActions $event
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function messageEvent(BlockActions $event): void
|
||||
{
|
||||
Log::info(sprintf('%s:[%s] has [%d] actions',self::LOGKEY,$event->callback_id,count($event->actions)),['m'=>__METHOD__]);
|
||||
|
||||
foreach ($event->actions as $id => $action) {
|
||||
$event->index = $id;
|
||||
|
||||
Log::debug(sprintf('%s:Action [%s]',self::LOGKEY,$event->action_id),['m'=>__METHOD__]);
|
||||
switch ($event->action_id) {
|
||||
case 'self_destruct':
|
||||
// Queue the delete of the message
|
||||
dispatch((new DeleteChat($event->user(),$event->message_ts))->onQueue('low'));
|
||||
|
||||
// @todo If this message is on integrations messages channel, which is not the user_id() - need to use the user's integration direct channel ID
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::notice(sprintf('%s:Unhandled ACTION [%s]',self::LOGKEY,$event->action_id),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store data coming in from a block action dialog
|
||||
*
|
||||
* @param BlockActions $event
|
||||
*/
|
||||
protected function store(BlockActions $event): void
|
||||
{
|
||||
foreach ($event->actions as $id => $action) {
|
||||
$event->index = $id;
|
||||
|
||||
switch ($event->action_id) {
|
||||
default:
|
||||
Log::notice(sprintf('%s:Unhandled ACTION [%s]',static::LOGKEY,$event->action_id),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
src/Listeners/ChannelJoinListener.php
Normal file
38
src/Listeners/ChannelJoinListener.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Event\MemberJoinedChannel;
|
||||
|
||||
class ChannelJoinListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LCJ';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param MemberJoinedChannel $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(MemberJoinedChannel $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:User [%s] joined Channel [%s]',self::LOGKEY,$event->invited,$event->channel_id),['m'=>__METHOD__]);
|
||||
|
||||
if ($event->team()->bot->user_id == $event->invited) {
|
||||
$o = $event->channel(TRUE);
|
||||
$o->active = TRUE;
|
||||
$o->save();
|
||||
|
||||
Log::debug(sprintf('%s:BOT [%s] Joined Channel [%s]',self::LOGKEY,$event->invited,$event->channel_id),['m'=>__METHOD__]);
|
||||
|
||||
} else {
|
||||
Log::debug(sprintf('%s:Wasnt the BOT who joined Channel [%s]',self::LOGKEY,$event->channel_id),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
}
|
34
src/Listeners/ChannelLeftListener.php
Normal file
34
src/Listeners/ChannelLeftListener.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Event\{Base,ChannelLeft,GroupLeft};
|
||||
|
||||
class ChannelLeftListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LCL';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param Base $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Base $event)
|
||||
{
|
||||
if (! $event instanceof ChannelLeft AND ! $event instanceof GroupLeft)
|
||||
abort(500,'Wrong class calling this listener? '.get_class($event));
|
||||
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Bot Left Channel [%s]',self::LOGKEY,$event->channel_id),['m'=>__METHOD__,'c'=>$event->channel_id]);
|
||||
|
||||
$o = $event->channel(TRUE);
|
||||
$o->active = FALSE;
|
||||
$o->save();
|
||||
}
|
||||
}
|
32
src/Listeners/InteractiveMessageListener.php
Normal file
32
src/Listeners/InteractiveMessageListener.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Interactive\InteractiveMessage;
|
||||
|
||||
class InteractiveMessageListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LIM';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param InteractiveMessage $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(InteractiveMessage $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Interactive Message for Callback [%s] User [%s] in [%s]',self::LOGKEY,$event->callback_id,$event->user_id,$event->team_id),['m'=>__METHOD__]);
|
||||
|
||||
switch ($event->callback_id) {
|
||||
default:
|
||||
Log::notice(sprintf('%s:Unhandled CALLBACK [%s]',self::LOGKEY,$event->callback_id),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
}
|
38
src/Listeners/MessageListener.php
Normal file
38
src/Listeners/MessageListener.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Event\Message;
|
||||
|
||||
class MessageListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LM-';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param Message $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Message $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Message event [%s] - subtype [%s]',self::LOGKEY,$event->ts,$event->type),['m'=>__METHOD__]);
|
||||
|
||||
switch ($event->type) {
|
||||
case 'channel_join': // Handled by another event (member_joined_channel - needs to be defined in Event Subscriptions)
|
||||
case 'group_join': // Handled by another event (member_joined_channel - needs to be defined in Event Subscriptions)
|
||||
case 'message_changed':
|
||||
Log::debug(sprintf('%s:Ignoring message subtype [%s]',self::LOGKEY,$event->type),['m'=>__METHOD__]);
|
||||
break;
|
||||
|
||||
default:
|
||||
Log::notice(sprintf('%s:Unhandled TYPE [%s]',self::LOGKEY,$event->type),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
}
|
29
src/Listeners/PinAddedListener.php
Normal file
29
src/Listeners/PinAddedListener.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Event\PinAdded;
|
||||
|
||||
class PinAddedListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LPA';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param PinAdded $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(PinAdded $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Pin Added to message [%s] in [%s]',self::LOGKEY,$event->ts,$event->channel_id),['m'=>__METHOD__]);
|
||||
|
||||
Log::notice(sprintf('%s:Ignoring Pin Add on [%s]',static::LOGKEY,$event->ts),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
29
src/Listeners/PinRemovedListener.php
Normal file
29
src/Listeners/PinRemovedListener.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Event\PinRemoved;
|
||||
|
||||
class PinRemovedListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LPR';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param PinRemoved $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(PinRemoved $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Pin Removed from message [%s] in [%s]',self::LOGKEY,$event->ts,$event->channel_id),['m'=>__METHOD__]);
|
||||
|
||||
Log::debug(sprintf('%s:Ignoring Pin Remove on [%s]',static::LOGKEY,$event->ts),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
29
src/Listeners/ReactionAddedListener.php
Normal file
29
src/Listeners/ReactionAddedListener.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Event\ReactionAdded;
|
||||
|
||||
class ReactionAddedListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LRA';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param ReactionAdded $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(ReactionAdded $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Reaction [%s] added to message in [%s]',self::LOGKEY,$event->reaction,$event->team_id),['m'=>__METHOD__]);
|
||||
|
||||
Log::debug(sprintf('%s:Ignoring Reaction Add [%s] on [%s]',static::LOGKEY,$event->reaction,$event->ts),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
54
src/Listeners/ShortcutListener.php
Normal file
54
src/Listeners/ShortcutListener.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Blockkit\Blocks;
|
||||
use Slack\Blockkit\Modal;
|
||||
use Slack\Interactive\Shortcut;
|
||||
use Slack\Message;
|
||||
|
||||
class ShortcutListener //implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LSC';
|
||||
|
||||
// Block actions arent queued, since slack expects a response to the request
|
||||
//public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param Shortcut $event
|
||||
* @return void
|
||||
* @todo To Test
|
||||
*/
|
||||
public function handle(Shortcut $event): Message
|
||||
{
|
||||
if (! $event->channel() || ! $event->channel()->active) {
|
||||
$modal = new Modal(Blocks\TextEmoji::item(config('app.name')));
|
||||
$blocks = new Blocks;
|
||||
|
||||
$blocks->addHeader(':robot_face: Bot not in this channel');
|
||||
$blocks->addSectionText(Blocks\Text::item('Please add the BOT to this channel and try this again.'));
|
||||
|
||||
$modal->setBlocks($blocks);
|
||||
|
||||
try {
|
||||
$event->team()->slackAPI()->viewOpen($event->trigger_id,json_encode($modal));
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error(sprintf('%s:Got an error posting view to slack: %s',static::LOGKEY,$e->getMessage()),['m'=>__METHOD__]);
|
||||
}
|
||||
|
||||
return (new Message)->blank();
|
||||
}
|
||||
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Shortcut [%s] triggered for: [%s]',self::LOGKEY,$event->callback_id,$event->team_id),['m'=>__METHOD__]);
|
||||
|
||||
switch ($event->callback_id) {
|
||||
default:
|
||||
Log::notice(sprintf('%s:Unhandled CALLBACK [%s]',self::LOGKEY,$event->callback_id),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
}
|
32
src/Listeners/ViewClosedListener.php
Normal file
32
src/Listeners/ViewClosedListener.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Interactive\ViewClosed;
|
||||
|
||||
class ViewClosedListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LVC';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param ViewClosed $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(ViewClosed $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:Block Action for Callback [%s] User [%s] in [%s]',self::LOGKEY,$event->callback_id,$event->user_id,$event->team_id),['m'=>__METHOD__]);
|
||||
|
||||
switch ($event->callback_id) {
|
||||
default:
|
||||
Log::notice(sprintf('%s:Unhandled CALLBACK [%s]',self::LOGKEY,$event->callback_id),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
}
|
32
src/Listeners/ViewSubmissionListener.php
Normal file
32
src/Listeners/ViewSubmissionListener.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Slack\Listeners;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
use Slack\Interactive\ViewSubmission;
|
||||
|
||||
class ViewSubmissionListener implements ShouldQueue
|
||||
{
|
||||
private const LOGKEY = 'LVC';
|
||||
|
||||
public $queue = 'high';
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param ViewSubmission $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle(ViewSubmission $event)
|
||||
{
|
||||
// Do some magic with event data
|
||||
Log::info(sprintf('%s:View Submission for Callback [%s] User [%s] in [%s]',self::LOGKEY,$event->callback_id,$event->user_id,$event->team_id),['m'=>__METHOD__]);
|
||||
|
||||
switch ($event->callback_id) {
|
||||
default:
|
||||
Log::notice(sprintf('%s:Unhandled CALLBACK [%s]',self::LOGKEY,$event->callback_id),['m'=>__METHOD__]);
|
||||
}
|
||||
}
|
||||
}
|
144
src/Message.php
144
src/Message.php
@ -6,11 +6,11 @@ use Carbon\Carbon;
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Slack\Jobs\DeleteChat;
|
||||
use Slack\Models\{Channel,User};
|
||||
use Slack\Blockkit\Block;
|
||||
use Slack\Blockkit\Blocks;
|
||||
use Slack\Exceptions\SlackException;
|
||||
use Slack\Message\Attachment;
|
||||
use Slack\Jobs\DeleteChat;
|
||||
use Slack\Message\Attachments;
|
||||
use Slack\Models\{Channel,User};
|
||||
use Slack\Response\Generic;
|
||||
|
||||
/**
|
||||
@ -20,19 +20,20 @@ class Message implements \JsonSerializable
|
||||
{
|
||||
protected const LOGKEY = 'SM-';
|
||||
|
||||
private $o;
|
||||
private $attachments;
|
||||
private $blocks;
|
||||
private Model $o;
|
||||
private Blocks $blocks;
|
||||
|
||||
/**
|
||||
* Message constructor.
|
||||
*
|
||||
* @param Model|null $o Who the message will be to - Channel or User
|
||||
* @throws SlackException
|
||||
*/
|
||||
public function __construct(Model $o=NULL)
|
||||
{
|
||||
$this->_data = collect();
|
||||
|
||||
if ($o) {
|
||||
// Message is to a channel
|
||||
if ($o instanceof Channel) {
|
||||
$this->setChannel($o);
|
||||
@ -40,35 +41,27 @@ class Message implements \JsonSerializable
|
||||
// Message is to a user
|
||||
} elseif ($o instanceof User) {
|
||||
$this->setUser($o);
|
||||
|
||||
} else {
|
||||
throw new SlackException('Model not handled: '.get_class($o));
|
||||
}
|
||||
|
||||
$this->o = $o;
|
||||
$this->attachments = collect();
|
||||
$this->blocks = collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attachment to a message
|
||||
*
|
||||
* @param Attachment $attachment
|
||||
* @return Message
|
||||
*/
|
||||
public function addAttachment(Attachment $attachment): self
|
||||
{
|
||||
$this->attachments->push($attachment);
|
||||
|
||||
return $this;
|
||||
$this->blocks = new Blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a block to the message
|
||||
*
|
||||
* @param BlockKit $block
|
||||
* @return $this
|
||||
* @param Blocks $blocks
|
||||
* @return Message
|
||||
* @todo to test
|
||||
*/
|
||||
public function addBlock(BlockKit $block): self
|
||||
public function addBlock(Blocks $blocks): self
|
||||
{
|
||||
$this->blocks->push($block);
|
||||
$this->blocks = $blocks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -76,11 +69,12 @@ class Message implements \JsonSerializable
|
||||
/**
|
||||
* Empty the message
|
||||
*
|
||||
* @return $this
|
||||
* @return Message
|
||||
*/
|
||||
public function blank(): self
|
||||
{
|
||||
$this->_data = collect();
|
||||
$this->blocks = new Blocks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -117,15 +111,8 @@ class Message implements \JsonSerializable
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
if ($this->blocks->count()) {
|
||||
if ($this->_data->has('text'))
|
||||
throw new \Exception('Messages cannot have text and blocks!');
|
||||
|
||||
if ($this->blocks->count())
|
||||
$this->_data->put('blocks',$this->blocks);
|
||||
}
|
||||
|
||||
if ($this->attachments->count())
|
||||
$this->_data->put('attachments',$this->attachments);
|
||||
|
||||
// For interactive messages that generate a dialog, we need to return NULL
|
||||
return $this->_data->count() ? $this->_data : NULL;
|
||||
@ -143,6 +130,9 @@ class Message implements \JsonSerializable
|
||||
if ($this->_data->has('ephemeral'))
|
||||
abort('500','Cannot post ephemeral messages.');
|
||||
|
||||
if ($this->blocks->count() && $this->_data->get('attachments'))
|
||||
throw new SlackException('Message cannot have blocks and attachments.');
|
||||
|
||||
$api = $this->o->team->slackAPI();
|
||||
$response = $this->_data->has('ts') ? $api->updateMessage($this) : $api->postMessage($this);
|
||||
|
||||
@ -156,18 +146,33 @@ class Message implements \JsonSerializable
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function replace(bool $replace=TRUE): self
|
||||
public function setReplace(bool $replace=TRUE): self
|
||||
{
|
||||
$this->_data['replace_original'] = $replace ? 'true' : 'false';
|
||||
$this->_data->put('replace_original',$replace ? 'true' : 'false');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* To slack from rendering URLs in the message
|
||||
*
|
||||
* @param bool $unfurl
|
||||
* @return $this
|
||||
*/
|
||||
public function setUnfurlLinks(bool $unfurl): self
|
||||
{
|
||||
$this->_data->put('unfurl_links',$unfurl ? 'true' : 'false');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a message to slack using the respond_url
|
||||
* @note This URL can only be used 5 times in 30 minutes
|
||||
*
|
||||
* @note This URL can only be used 5 times in 30 minutes
|
||||
* @param string $url
|
||||
* @return string
|
||||
* @throws SlackException
|
||||
*/
|
||||
public function respond(string $url)
|
||||
{
|
||||
@ -212,23 +217,53 @@ class Message implements \JsonSerializable
|
||||
*/
|
||||
public function selfdestruct(Carbon $time): Generic
|
||||
{
|
||||
$this->addBlock(
|
||||
(new Block)->addContext(
|
||||
$this->blocks->addContextElements(
|
||||
collect()
|
||||
->push((new BlockKit)->text(sprintf('This message will self destruct in %s...',$time->diffForHumans(Carbon::now(),['syntax' => CarbonInterface::DIFF_RELATIVE_TO_NOW]))))));
|
||||
->push(Blocks\Text::item(sprintf('This message will self destruct in %s...',$time->diffForHumans(Carbon::now(),['syntax' => CarbonInterface::DIFF_RELATIVE_TO_NOW])))));
|
||||
|
||||
return $this->post($time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attachment to a message
|
||||
*
|
||||
* @param Attachment $attachments
|
||||
* @return Message
|
||||
*/
|
||||
public function setAttachments(Attachments $attachments): self
|
||||
{
|
||||
$this->_data->put('attachments',[$attachments]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add blocks to the message
|
||||
*
|
||||
* @param Blocks $blocks
|
||||
* @return Message
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setBlocks(Blocks $blocks): self
|
||||
{
|
||||
if ($this->blocks->count())
|
||||
throw new \Exception('Blocks already defined');
|
||||
|
||||
$this->blocks = $blocks;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set our channel
|
||||
*
|
||||
* @param Channel $o
|
||||
* @return Message
|
||||
*/
|
||||
public function setChannel(Channel $o)
|
||||
public function setChannel(Channel $o): self
|
||||
{
|
||||
$this->_data['channel'] = $o->channel_id;
|
||||
$this->_data->put('channel',$o->channel_id);
|
||||
$this->o = $o;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -237,7 +272,7 @@ class Message implements \JsonSerializable
|
||||
* Set the icon next to the message
|
||||
*
|
||||
* @param string $icon
|
||||
* @return $this
|
||||
* @return Message
|
||||
* @deprecated
|
||||
*/
|
||||
public function setIcon(string $icon): self
|
||||
@ -255,7 +290,7 @@ class Message implements \JsonSerializable
|
||||
*/
|
||||
public function setOptionGroup(array $array): void
|
||||
{
|
||||
$this->_data = collect();
|
||||
$this->_data = collect(); // @todo Why are clearing our data?
|
||||
$this->_data->put('option_groups',$array);
|
||||
}
|
||||
|
||||
@ -263,7 +298,7 @@ class Message implements \JsonSerializable
|
||||
* Message text
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @return Message
|
||||
*/
|
||||
public function setText(string $string): self
|
||||
{
|
||||
@ -272,6 +307,12 @@ class Message implements \JsonSerializable
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timestamp, used when replacing messages
|
||||
*
|
||||
* @param string $string
|
||||
* @return Message
|
||||
*/
|
||||
public function setTS(string $string): self
|
||||
{
|
||||
$this->_data->put('ts',$string);
|
||||
@ -279,6 +320,12 @@ class Message implements \JsonSerializable
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the thread timestamp, used when adding a threaded response
|
||||
*
|
||||
* @param string $string
|
||||
* @return Message
|
||||
*/
|
||||
public function setThreadTS(string $string): self
|
||||
{
|
||||
$this->_data->put('thread_ts',$string);
|
||||
@ -292,16 +339,17 @@ class Message implements \JsonSerializable
|
||||
* @param User $o
|
||||
* @return Message
|
||||
*/
|
||||
public function setUser(User $o)
|
||||
public function setUser(User $o): self
|
||||
{
|
||||
$this->_data['channel'] = $o->user_id;
|
||||
$this->_data->put('channel',$o->user_id);
|
||||
$this->o = $o;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUserName(string $user)
|
||||
public function setUserName(string $user): self
|
||||
{
|
||||
$this->_data['username'] = $user;
|
||||
$this->_data->put('username',$user);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace Slack\Message;
|
||||
|
||||
use Slack\BlockKit;
|
||||
use Slack\Blockkit\BlockAction;
|
||||
use Slack\Blockkit\Blocks;
|
||||
|
||||
/**
|
||||
* Class MessageAttachment - Slack Message Attachments
|
||||
@ -11,23 +12,27 @@ use Slack\Blockkit\BlockAction;
|
||||
*
|
||||
* @package Slack\Message
|
||||
*/
|
||||
class Attachment implements \JsonSerializable
|
||||
class Attachments implements \JsonSerializable
|
||||
{
|
||||
private $_data;
|
||||
private $actions;
|
||||
private $blocks;
|
||||
//private $blocks;
|
||||
private $blockactions;
|
||||
|
||||
// @todo To rework
|
||||
public function __construct()
|
||||
{
|
||||
$this->actions = collect();
|
||||
$this->blocks = collect();
|
||||
//$this->blocks = collect();
|
||||
$this->blockactions = collect();
|
||||
$this->_data = collect();
|
||||
}
|
||||
|
||||
// @todo To rework
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
/*
|
||||
if ($this->actions->count() AND ! $this->_data->has('callback_id'))
|
||||
abort(500,'Actions without a callback ID');
|
||||
|
||||
@ -47,15 +52,16 @@ class Attachment implements \JsonSerializable
|
||||
|
||||
if ($this->blocks->count())
|
||||
$this->_data->put('blocks',$this->blocks);
|
||||
*/
|
||||
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attachment to a message
|
||||
*
|
||||
* @param AttachmentAction $action
|
||||
* @return Attachment
|
||||
* @todo To rework
|
||||
*/
|
||||
public function addAction(AttachmentAction $action): self
|
||||
{
|
||||
@ -69,6 +75,7 @@ class Attachment implements \JsonSerializable
|
||||
*
|
||||
* @param BlockKit $block
|
||||
* @return Attachment
|
||||
* @deprecated
|
||||
*/
|
||||
public function addBlock(BlockKit $block): self
|
||||
{
|
||||
@ -82,6 +89,7 @@ class Attachment implements \JsonSerializable
|
||||
*
|
||||
* @param BlockAction $action
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function addBlockAction(BlockAction $action): self
|
||||
{
|
||||
@ -90,6 +98,8 @@ class Attachment implements \JsonSerializable
|
||||
return $this;
|
||||
}
|
||||
|
||||
//* @todo To rework
|
||||
|
||||
public function addField(string $title,string $value,bool $short): self
|
||||
{
|
||||
if (! $this->_data->has('fields'))
|
||||
@ -103,12 +113,12 @@ class Attachment implements \JsonSerializable
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set where markdown should be parsed by slack
|
||||
*
|
||||
* @param array $array
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function markdownIn(array $array): self
|
||||
{
|
||||
@ -123,6 +133,7 @@ class Attachment implements \JsonSerializable
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setCallbackID(string $string): self
|
||||
{
|
||||
@ -131,11 +142,25 @@ class Attachment implements \JsonSerializable
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a blocks to the message attachment
|
||||
*
|
||||
* @param Blocks $blocks
|
||||
* @return self
|
||||
*/
|
||||
public function setBlocks(Blocks $blocks): self
|
||||
{
|
||||
$this->_data->put('blocks',$blocks);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the attachment color (on the left of the attachment)
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setColor(string $string): self
|
||||
{
|
||||
@ -149,6 +174,7 @@ class Attachment implements \JsonSerializable
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setFooter(string $string): self
|
||||
{
|
||||
@ -162,6 +188,7 @@ class Attachment implements \JsonSerializable
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setPretext(string $string): self
|
||||
{
|
||||
@ -175,6 +202,7 @@ class Attachment implements \JsonSerializable
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setText(string $string): self
|
||||
{
|
||||
@ -188,6 +216,7 @@ class Attachment implements \JsonSerializable
|
||||
*
|
||||
* @param string $string
|
||||
* @return $this
|
||||
* @todo To rework
|
||||
*/
|
||||
public function setTitle(string $string): self
|
||||
{
|
@ -53,4 +53,18 @@ class Channel extends Model
|
||||
{
|
||||
return preg_match('/^D/',$this->channel_id) OR $this->name == 'directmessage';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a slack URL to the timestamp
|
||||
*
|
||||
* @param string $ts
|
||||
* @return string
|
||||
*/
|
||||
public function url(string $ts): string
|
||||
{
|
||||
if (! $this->team->url)
|
||||
return '';
|
||||
|
||||
return sprintf('https://%s/archives/%s/p%s',$this->team->url,$this->channel_id,str_replace('.','',$ts));
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,15 @@ class Team extends Model
|
||||
return implode('-',$attrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the team's slack URL
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlAttribute(): string
|
||||
{
|
||||
return $this->team_name ? sprintf('%s.slack.com',$this->team_name) : '';
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,11 @@
|
||||
|
||||
namespace Slack\Providers;
|
||||
|
||||
use Illuminate\Notifications\ChannelManager;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Slack\API;
|
||||
use Slack\Channels\SlackBotChannel;
|
||||
use Slack\Console\Commands\SlackSocketClient;
|
||||
|
||||
class SlackServiceProvider extends ServiceProvider
|
||||
@ -35,5 +39,11 @@ class SlackServiceProvider extends ServiceProvider
|
||||
$this->mergeConfigFrom(__DIR__.'/../config/slack.php','slack');
|
||||
|
||||
$this->loadRoutesFrom(realpath(__DIR__ .'/../routes.php'));
|
||||
|
||||
Notification::resolved(function (ChannelManager $service) {
|
||||
$service->extend('slackapp', function ($app) {
|
||||
return new SlackBotChannel($app->make(API::class));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ class SlackIntegration extends Migration
|
||||
$table->timestamps();
|
||||
|
||||
$table->string('team_id', 45)->unique();
|
||||
$table->string('name')->nullable();
|
||||
$table->string('team_name')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->boolean('active');
|
||||
|
||||
@ -62,8 +62,8 @@ class SlackIntegration extends Migration
|
||||
$table->string('name')->nullable();
|
||||
$table->boolean('active');
|
||||
|
||||
$table->integer('enterprise_id')->nullable()->unsigned();
|
||||
$table->foreign('enterprise_id')->references('id')->on('slack_enterprises');
|
||||
$table->integer('team_id')->nullable()->unsigned();
|
||||
$table->foreign('team_id')->references('id')->on('slack_teams');
|
||||
});
|
||||
|
||||
Schema::table('slack_users', function (Blueprint $table) {
|
||||
|
Loading…
Reference in New Issue
Block a user