Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webhooks "send" based on book or shelf #5009

Open
1 task done
tritanium73 opened this issue May 14, 2024 · 1 comment
Open
1 task done

Webhooks "send" based on book or shelf #5009

tritanium73 opened this issue May 14, 2024 · 1 comment

Comments

@tritanium73
Copy link

Describe the feature you'd like

It would be great if you could send webhooks based on the source:

Book 1 -> webhook target a
Book 2 -> webhook target b

or

Shelf x

  • Book 3
  • Book 4

to webhook target c

Describe the benefits this would bring to existing BookStack users

This would allow us to notify our MS Teams channels in a more granular manner so that only certain books go to certain MS Teams channels

Can the goal of this request already be achieved via other means?

Not really, because when I create the webhook I unfortunately can't specify a source that the webhook end should refer to

Have you searched for an existing open/closed issue?

  • I have searched for existing issues and none cover my fundamental request

How long have you been using BookStack?

3 months to 1 year

Additional context

No response

@DanielGordonIT
Copy link

I'd suggest the theme system, but I don't think the webhook event covers it:

public function __construct(Webhook $webhook, string $event, Loggable|string $detail)
{
    $this->webhook = $webhook;
    $this->initiator = user();
    $this->initiatedTime = time();

    $themeResponse = Theme::dispatch(ThemeEvents::WEBHOOK_CALL_BEFORE, $event, $this->webhook, $detail, $this->initiator, $this->initiatedTime);
    $this->webhookData =  $themeResponse ?? WebhookFormatter::getDefault($event, $this->webhook, $detail, $this->initiator, $this->initiatedTime)->format();
}

As far as I can tell, it can't change the webhook's data, only change the data that gets sent. It would be weird if you could change endpoints in place. The only other option would be to make a different webhook for each channel you want, and then set the output to empty if the event is for a book you don't care about for that endpoint:

<?php

use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Models\Webhook;
use BookStack\Activity\Tools\WebhookFormatter;
use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;

function selectiveFormat(array $defaultWebhookData): array
{
    $book_id = $defaultWebhookData['related_item']['book_id'];
    $webhook_name = $defaultWebhookData['webhook_name']
    if ( !(
        ($book_id == 1 && $webhook_name == "Team 1 Webhook") ||
        ($book_id == 2 && $webhook_name == "Team 2 Webhook") ||
        ($book_id == 3 && $webhook_name == "Team 3 Webhook") ||
        ($book_id == 4 && $webhook_name == "Team 4 Webhook")
    )
    ) {
        // If it's a teams webhook, but the name and book ID don't match, then just return nothing and cause a 400 error.
        return [];
    }
    return null;

}

Theme::listen(ThemeEvents::WEBHOOK_CALL_BEFORE, function (
    string $event,
    Webhook $webhook,
    string|Loggable $detail,
    User $initiator,
    int $initTime,
) {
    if (str_starts_with($webhook->endpoint, 'https://teams.webhook.whatever')) {
        $defaultData = WebhookFormatter::getDefault($event, $webhook, $detail, $initiator, $initTime);
        return selectiveFormat($defaultData->format());
    }

    // Otherwise return null to leave the webhook data alone
    return null;
});

This will return [] when a book ID and webhook name according to your manual specifications don't match, but will return the normal value when they do.

The main problem with this is that it scales pretty badly with each team added - if you have 5 teams, that's 5 events firing and 5 webhooks trying to send data per action the webhook is listening to.

This is pretty heavily adapted from this page where Dan Brown went over formatting webhooks differently for Pushover.

(Disclaimer: I haven't tested this code due to time constraints on my end, so there might be some issues with how it grabs the data from the webhook for the webhook name and book ID, but that should be easy enough to debug)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants