PHP code example of helgesverre / slack-bolt

1. Go to this page and download the library: Download helgesverre/slack-bolt library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

helgesverre / slack-bolt example snippets


use Thunder\Bolt\Attributes\Event;
use Thunder\Bolt\Payloads\Events\AppMention;
use Thunder\Bolt\Reply;

final readonly class GreetMention
{
    #[Event('app_mention')]
    public function __invoke(AppMention $event, Reply $reply): void
    {
        $reply->inThread("Hello <@{$event->userId}>!");
    }
}

use Thunder\Bolt\Attributes\SlashCommand;
use Thunder\Bolt\Responses\CommandResponse;

final readonly class Ping
{
    #[SlashCommand('/ping')]
    public function __invoke(): CommandResponse
    {
        return CommandResponse::ephemeral('Pong.');
    }
}

use Thunder\Bolt\Payloads\Events\AppMention;
use Thunder\Bolt\Reply;
use Thunder\Bolt\Responses\CommandResponse;

$app
    ->event('app_mention', static function (AppMention $event, Reply $reply): void {
        $reply->inThread("Hello <@{$event->userId}>.");
    })
    ->command('/ping', static fn (): CommandResponse => CommandResponse::ephemeral('Pong.'));

use Thunder\Bolt\BlockKit\{Actions, Button, Section};
use Thunder\Bolt\Messages\Message;

$message = Message::blocks(
    Section::markdown('*Deployment ready*'),
    Actions::make(
        Button::make('Approve', 'approve_deployment')->primary(),
    ),
)->fallbackText('Deployment ready for approval.');

$reply->inChannel($message);

use Thunder\Bolt\BlockKit\{Input, PlainTextInput};
use Thunder\Bolt\Views\Modal;

$modal = Modal::make('Approve deployment',
    Input::make('Reason', PlainTextInput::make('reason')->multiline())
        ->id('reason'),
)->callbackId('approve_deployment')->submit('Approve');

use Thunder\Bolt\Responses\ShortcutResponse;
use Thunder\Bolt\WebApi\Requests\ViewRequest;

$client->views()->open(ViewRequest::open($shortcut->triggerId, $modal));

return ShortcutResponse::empty();

use Thunder\Bolt\BlockKit\Section;
use Thunder\Bolt\Views\Home;
use Thunder\Bolt\WebApi\Requests\ViewRequest;

$home = Home::make(
    Section::markdown('*Workspace dashboard*'),
    Section::markdown('No pending approvals.'),
);

$client->views()->publish(ViewRequest::publish('U123', $home));

use Thunder\Bolt\BlockKit\{RichText, RichTextMessageMention, RichTextSection, RichTextTag, RichTextText};

$status = RichText::make(RichTextSection::make(
    RichTextTag::make('In progress')->blue(),
    RichTextText::make(' '),
    RichTextMessageMention::for('C123', '1700000000.000001'),
));

use Thunder\Bolt\Attributes\Action as OnAction;
use Thunder\Bolt\Reply;
use Thunder\Bolt\Responses\ActionResponse;

final readonly class ApproveDeployment
{
    #[OnAction('approve_deployment')]
    public function __invoke(Reply $reply): ActionResponse
    {
        $reply->replaceOriginal('Deployment approved.');

        return ActionResponse::empty();
    }
}

use Thunder\Bolt\Attributes\View as OnView;
use Thunder\Bolt\Payloads\View;
use Thunder\Bolt\Responses\ViewResponse;

final readonly class ValidateApproval
{
    #[OnView('approve_deployment')]
    public function __invoke(View $view): ViewResponse
    {
        $reason = $view->value('reason', 'reason');
        if (!is_string($reason) || trim($reason) === '') {
            return ViewResponse::errors(['reason' => 'Enter a reason.']);
        }

        return ViewResponse::empty();
    }
}

use Thunder\Bolt\Attributes\Options as LoadOptions;
use Thunder\Bolt\BlockKit\Option;
use Thunder\Bolt\Payloads\Options;
use Thunder\Bolt\Responses\OptionsResponse;

final readonly class SearchAssignees
{
    #[LoadOptions('search_assignees')]
    public function __invoke(Options $request): OptionsResponse
    {
        // Use $request->value to search your application's people directory.
        return OptionsResponse::options(
            Option::text('Ada', 'ada'),
            Option::text('Linus', 'linus'),
        );
    }
}

use Thunder\Bolt\Messages\Message;
use Thunder\Bolt\WebApi\Requests\ChatPostMessage;

$result = $client->chat()->postMessage(
    new ChatPostMessage('C123', Message::text('Hello from PHP')),
);

$messageTimestamp = $result->ts;

use Thunder\Bolt\BlockKit\Section;
use Thunder\Bolt\Messages\Message;
use Thunder\Bolt\Views\Modal;
use Thunder\Bolt\WebApi\Requests\{ChatPostEphemeral, ChatUpdate, ViewRequest};

$client->views()->open(ViewRequest::open(
    $action->triggerId,
    Modal::make('Deployment', Section::text('Ready for review.'))->close('Close'),
));
$client->chat()->update(new ChatUpdate('C123', $messageTimestamp, Message::text('Complete.')));
$client->chat()->postEphemeral(new ChatPostEphemeral('C123', 'U123', 'Saved for you.'));

$client->chat()->postMessage([
    'channel' => 'C123',
    'text' => 'A forward-compatible payload.',
]);

$client->admin()->conversations()->archive(['channel_id' => 'C123']);

foreach ($client->paginate('conversations.list', ['limit' => 100]) as $page) {
    foreach ($page->get('channels', []) as $channel) {
        // Process this page; stop iteration to avoid fetching more pages.
    }
}

use Thunder\Bolt\WebApi\Uploads\Upload;

$client->upload(
    Upload::path('report.pdf')
        ->title('Monthly report')
        ->toChannel('C123')
        ->comment('The report is ready.'),
);

use Thunder\Bolt\WebApi\RetryPolicy;

$background = $client->retrying(
    RetryPolicy::rateLimits(maxRetries: 3, maxTotalWait: 60),
);

$result = $background->conversations()->list(['limit' => 100]);

use Closure;
use Thunder\Bolt\Invocation\Delivery;
use Thunder\Bolt\Middleware\Middleware;

final readonly class RequestContext implements Middleware
{
    public function handle(Delivery $delivery, Closure $next): mixed
    {
        $delivery->context->set('request_id', bin2hex(random_bytes(8)));

        return $next($delivery);
    }
}

$app->use(new RequestContext());

use Thunder\Bolt\Middleware\MessageFilter;
use Thunder\Bolt\Payloads\Events\Message;
use Thunder\Bolt\Reply;

$app->message('', MessageFilter::directMention(),
    static function (Message $message, Reply $reply): void {
        $reply->inThread('You mentioned me.');
    },
);

use Thunder\Bolt\Errors\{ErrorHandling, FailureContext};

$app->onError(static function (FailureContext $failure): ErrorHandling {
    error_log(json_encode($failure->summary(), JSON_THROW_ON_ERROR));

    return ErrorHandling::Handled;
});

use Thunder\Bolt\Attributes\Event;
use Thunder\Bolt\Authorization\Authorization;
use Thunder\Bolt\Reply;

final readonly class InstallationGreeting
{
    #[Event('app_mention')]
    public function __invoke(Authorization $authorization, Reply $reply): void
    {
        $reply->inThread('Hello workspace '.$authorization->teamId);
    }
}

use Thunder\Bolt\Attributes\Event;
use Thunder\Bolt\Conversation\ThreadContext;
use Thunder\Bolt\Payloads\Events\AppMention;

final readonly class CountMentions
{
    #[Event('app_mention')]
    public function __invoke(AppMention $event, ThreadContext $thread): void
    {
        $thread->update(static fn (mixed $state): array => [
            'mentions' => ($state['mentions'] ?? 0) + 1,
        ]);
    }
}

use Tempest\CommandBus\CommandHandler;
use Thunder\Bolt\Attributes\Event;
use Thunder\Bolt\Jobs;
use Thunder\Bolt\Jobs\{Job, JobExecution};
use Thunder\Bolt\Payloads\Events\AppMention;
use Thunder\Bolt\Reply;

final readonly class PublishNote implements Job
{
    public function __construct(public string $text) {}
}

final readonly class QueueNote
{
    #[Event('app_mention')]
    public function __invoke(AppMention $event, Jobs $jobs): void
    {
        $jobs->dispatch(new PublishNote($event->text));
    }
}

final readonly class PublishNoteHandler
{
    public function __construct(private Reply $reply, private JobExecution $execution) {}

    #[CommandHandler]
    public function handle(PublishNote $job): void
    {
        $this->execution->checkpoint();
        $this->reply->inThread($job->text);
    }
}

use App\Listeners\WorkspaceAssistant;
use Thunder\Bolt\Assistant;

return Assistant::make()
    ->threadStarted([WorkspaceAssistant::class, 'started'])
    ->userMessage([WorkspaceAssistant::class, 'message']);

use Thunder\Bolt\Assistant\{SuggestedPrompt, Thread};
use Thunder\Bolt\Payloads\Events\AssistantThreadStarted;

final readonly class WorkspaceAssistant
{
    public function started(AssistantThreadStarted $event, Thread $thread): void
    {
        $thread->saveContext();
        $thread->say('What are we working on?');
        $thread->setSuggestedPrompts([
            new SuggestedPrompt('Explain a change', 'Explain the latest change.'),
        ]);
    }

    public function message(Thread $thread): void
    {
        $thread->say('Message received. Add your application logic here.');
    }
}

use Thunder\Bolt\Assistant\AgentSessionStatus;

$stream = $thread->sayStream();
foreach ($textFragments as $fragment) {
    $stream->append($fragment);
}
$stream->finish(AgentSessionStatus::Suspended);

use Thunder\Bolt\Assistant\Streaming\{TaskStatus, TaskUpdate};

$task = TaskUpdate::make('search', 'Read the reference');
$stream = $thread->sayStream();
$stream->chunks([$task])->append('Checking the API.');
$stream->chunks([$task->status(TaskStatus::Complete)->output('Reference found.')]);
$stream->append('Here is what it supports.')->stop();

use App\Listeners\WorkspaceAgent;
use Thunder\Bolt\Assistant;

return Assistant::forAgentView()
    ->opened([WorkspaceAgent::class, 'opened'])
    ->appContextChanged([WorkspaceAgent::class, 'contextChanged'])
    ->userMessage([WorkspaceAgent::class, 'message']);

use Thunder\Bolt\Attributes\{FromInputs, SlackFunction};
use Thunder\Bolt\Functions\Execution;

final readonly class FormatInputs
{
    public function __construct(public string $message, public bool $uppercase = false) {}
}

final readonly class FormatMessage
{
    #[SlackFunction('format_message')]
    public function __invoke(#[FromInputs] FormatInputs $inputs, Execution $execution): void
    {
        $text = $inputs->uppercase ? mb_strtoupper($inputs->message) : $inputs->message;
        $execution->complete(['message' => $text]);
    }
}

use Thunder\Bolt\Messages\Message;
use Thunder\Bolt\WorkObjects\{Entity, EntityField, ExternalReference};

$task = Entity::task(
    new ExternalReference('TASK-42', 'task'),
    'https://example.com/tasks/42',
    'Ship the PHP integration',
)->field('status', EntityField::status('In progress', 'blue'))->comments(0);

$client->chat()->postMessage([
    'channel' => 'C123',
    ...Message::text('Ready for review')->entities($task)->toArray(),
]);

use App\Listeners\GreetOnMention;
use Thunder\Bolt\Testing\BoltTest;

$bolt = BoltTest::make()->listeners(GreetOnMention::class);

$bolt->mention('hello', user: 'U123', channel: 'C123')
    ->assertAcknowledged()
    ->assertThreadReply('Hello <@U123>!')
    ->assertNoJobsQueued();
sh
php bolt doctor
php bolt auth:verify
php bolt serve
# Or: php bolt socket:serve --verify-token
sh
php bolt jobs:work