Added in HTTP interactive messages and Controller

This commit is contained in:
Deon George 2022-02-24 09:02:29 +11:00
parent dbd355555b
commit 29d3591125
9 changed files with 128 additions and 49 deletions

View File

@ -0,0 +1,45 @@
<?php
namespace Slack\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Slack\Client\Payload;
use Slack\Message;
use Slack\Interactive\Factory as InteractiveMessageFactory;
use App\Http\Controllers\Controller;
class InteractiveMessageController extends Controller
{
private const LOGKEY = 'CIM';
/**
* Fire slack event
*
* @param Request $request
* @return \Illuminate\Http\Response|\Laravel\Lumen\Http\ResponseFactory
*/
public function fire(Request $request)
{
$event = InteractiveMessageFactory::make(new Payload(json_decode($request->payload,TRUE),TRUE));
Log::debug(sprintf('%s:Firing Event [%s] and responding [%s]',static::LOGKEY,get_class($event),$event->respondNow));
if ($event->respondNow) {
if (! method_exists($event,'respond')) {
Log::alert(sprintf('%s:Cant respond to Event [%s], no respond method',static::LOGKEY,get_class($event)));
} else {
$result = $event->respond();
return (($result instanceof Message) AND $result->isEmpty()) ? NULL : $result;
}
} else {
event($event);
Log::info(sprintf('%s:Dispatched Event [%s]',static::LOGKEY,get_class($event)));
return response('IM Event Processed',200);
}
}
}

View File

@ -2,16 +2,16 @@
namespace Slack\Http\Controllers;
use App\Http\Controllers\Controller;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redirect;
use Slack\Jobs\TeamUpdate;
use Slack\Models\{Enterprise,Team,Token,User};
use App\Http\Controllers\Controller;
class SlackAppController extends Controller
{
protected const LOGKEY = 'CSA';

View File

@ -7,8 +7,8 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Slack\Client\Payload;
use Slack\Event\Factory as EventFactory;
use Slack\Interactive\Factory as InteractiveFactory;
use App\Slack\Interactive\Factory as InteractiveFactory;
use App\Slack\Options\Factory as OptionsFactory;
class CheckRequest
@ -51,7 +51,7 @@ class CheckRequest
break;
case 'api/imsg':
$event = InteractiveFactory::make($request);
$event = InteractiveFactory::make(new Payload(json_decode($request->payload,TRUE),TRUE));
break;
default:

View File

@ -8,6 +8,8 @@ use Slack\Base as SlackBase;
abstract class Base extends SlackBase
{
// Does the event respond with a reply to the HTTP request, or via a post with a trigger
// Child class should have a respond() function.
// (There should be a local implementation of the child class should respondNow = TRUE)
public $respondNow = FALSE;
// When retrieving multiple action values, this is the index we are retrieving.
@ -61,4 +63,4 @@ abstract class Base extends SlackBase
if ($key == 'index')
$this->{$key} = $value;
}
}
}

View File

@ -60,9 +60,6 @@ class BlockActions extends Base
public function __get($key)
{
switch ($key) {
case 'actions':
return object_get($this->_data,$key);
case 'action_id':
return object_get(Arr::get(object_get($this->_data,'actions'),$this->index),$key);
@ -73,9 +70,15 @@ class BlockActions extends Base
case 'action_value':
return $this->action('value');
case 'actions':
return object_get($this->_data,$key);
case 'callback_id':
return object_get($this->_data,'view.callback_id');
case 'channel_id':
return object_get($this->_data,'channel.id') ?: Channel::findOrFail($this->action('value'))->channel_id;
case 'keys':
return collect(object_get($this->_data,'view.blocks'))->pluck('accessory.action_id');
@ -83,9 +86,6 @@ class BlockActions extends Base
case 'message_ts':
return object_get($this->_data,'message.ts');
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');
@ -166,4 +166,20 @@ 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;
}
}

View File

@ -15,11 +15,11 @@ class Factory {
* @var array event type to event class mapping
*/
public const map = [
'block_actions'=>BlockActions::class,
'interactive_message'=>InteractiveMessage::class,
'shortcut'=>Shortcut::class,
'view_closed'=>ViewClosed::class,
'view_submission'=>ViewSubmission::class,
'block_actions' => BlockActions::class,
//'interactive_message' => InteractiveMessage::class,
'shortcut' => Shortcut::class,
'view_closed' => ViewClosed::class,
//'view_submission' => ViewSubmission::class,
];
/**
@ -31,7 +31,7 @@ class Factory {
*/
public static function create(string $type,array $request): Base
{
$class = Arr::get(self::map,$type,Unknown::class);
$class = Arr::get(config('slack.interactive',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() == 'local')
@ -53,4 +53,4 @@ class Factory {
return $o;
}
}
}

View File

@ -57,7 +57,7 @@ use Slack\Message;
*/
class InteractiveMessage extends Base
{
private const LOGKEY = 'IIM';
protected const LOGKEY = 'IIM';
// Does the event respond with a reply to the HTTP request, or via a post with a trigger
public $respondNow = TRUE;
@ -90,6 +90,11 @@ class InteractiveMessage extends Base
}
}
/**
* This method should be overridden by a local implementation
*
* @return Message
*/
public function respond(): Message
{
Log::info(sprintf('%s:Interactive Message - Callback [%s] Name [%s] Type [%s]',static::LOGKEY,$this->callback_id,$this->name,$this->type),['m'=>__METHOD__]);
@ -112,7 +117,7 @@ class InteractiveMessage extends Base
switch ($action) {
default:
Log::notice(sprintf('%s:Unhandled ACTION [%s]',static::LOGKEY,$action),['m'=>__METHOD__]);
return (new Message)->setText('That didnt work, I didnt know what to do with your button - you might like to tell '.$this->team()->owner->slack_user);
return (new Message)->text('That didnt work, I didnt know what to do with your button - you might like to tell '.$this->team()->owner->slack_user);
}
}
}

View File

@ -5,6 +5,7 @@ namespace Slack\Interactive;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Slack\Message;
use Slack\Models\Team;
use Slack\Blockkit\Modal;
@ -15,7 +16,7 @@ use Slack\Blockkit\Modal;
*/
class ViewSubmission extends Base
{
private const LOGKEY = 'IVS';
protected const LOGKEY = 'IVS';
// View Submissions must respond with via a trigger or inline
public $respondNow = TRUE;
@ -37,33 +38,11 @@ class ViewSubmission extends Base
}
}
private function blocks(): Collection
{
$result = collect();
foreach (object_get($this->_data,'view.blocks',[]) as $id=>$block) {
switch (object_get($block,'type')) {
case 'input':
$result->put($block->element->action_id,$block->block_id);
break;
case 'section':
$result->put($block->block_id,$id);
break;
}
}
return $result;
}
public function value(string $block_id): ?string
{
$key = Arr::get($this->blocks(),$block_id);
// Return the state value, or the original block value
return object_get($this->_data,'view.state.values.'.$key.'.'.$block_id.'.value') ?: object_get(Arr::get(object_get($this->_data,'view.blocks'),$key),'text.text','');
}
/**
* This method should be overridden by a local implementation
*
* @return Message
*/
public function respond(): Modal
{
// Do some magic with event data
@ -90,4 +69,31 @@ class ViewSubmission extends Base
return new Modal(new Team);
}
protected function blocks(): Collection
{
$result = collect();
foreach (object_get($this->_data,'view.blocks',[]) as $id=>$block) {
switch (object_get($block,'type')) {
case 'input':
$result->put($block->element->action_id,$block->block_id);
break;
case 'section':
$result->put($block->block_id,$id);
break;
}
}
return $result;
}
public function value(string $block_id): ?string
{
$key = Arr::get($this->blocks(),$block_id);
// Return the state value, or the original block value
return object_get($this->_data,'view.state.values.'.$key.'.'.$block_id.'.value') ?: object_get(Arr::get(object_get($this->_data,'view.blocks'),$key),'text.text','');
}
}

View File

@ -28,4 +28,9 @@ app('router')
'uses' => 'EventsController@fire',
'as' => 'event',
]);
$router->post('imsg', [
'uses' => 'InteractiveMessageController@fire',
'as' => 'imsg',
]);
});