Перейти к содержанию

Вебхуки

Вебхук публикует сообщения в один канал под собственными именем и аватаром. Его URL содержит ID и токен, а для публикации достаточно токена, так что скрипт деплоя или задача мониторинга могут отправлять сообщения без бота.

import asyncio
import os

import bostie
from bostie import Embed, color, ui


async def announce(url: str, version: str) -> None:
    async with bostie.WebhookClient(url) as webhook:
        message = await webhook.execute(
            embeds=[Embed(title=f"Deploying {version}", color=color.YELLOW)],
            username="Deploy bot",
            avatar_url="https://example.com/deploy.png",
        )
        await webhook.edit_message(
            message.id,
            embeds=[Embed(title=f"Deployed {version}", color=color.GREEN)],
        )
        await webhook.execute(
            components=[ui.text(f"Release notes for {version} are out.")],
            thread_name=f"Release {version}",
            with_components=True,
        )


def announce_from_a_script(url: str) -> None:
    webhook = bostie.SyncWebhookClient(url)
    message = webhook.execute("The nightly backup is running.")
    webhook.edit_message(message.id, content="The nightly backup finished.")


if __name__ == "__main__":
    asyncio.run(announce(os.environ["WEBHOOK_URL"], "2.0"))

WebhookClient(url) извлекает ID и токен из URL вебхука и вызывает ValueError для всего остального. Используйте его внутри async with, который открывает и закрывает его HTTP-клиент. У SyncWebhookClient(url) те же методы для кода без цикла событий; каждый вызов запускает собственный цикл.

Метод Что делает
execute(content, **parts) публикует сообщение и возвращает его, когда Discord его сохранил
edit_message(message_id, **parts) изменяет сообщение, отправленное вебхуком; непереданная часть остаётся, None её очищает
fetch_message(message_id), delete_message(message_id) получает или удаляет одно сообщение
fetch(), edit(name=..., avatar=...), delete() сам вебхук
execute_slack(payload), execute_github(payload) публикуют полезную нагрузку в форматах, которые принимают эндпоинты Discord, совместимые со Slack и GitHub

execute принимает части сообщения, а также:

  • username и avatar_url, которые показываются вместо собственных имени и аватара вебхука для этого сообщения;
  • thread_id, чтобы опубликовать сообщение в ветке канала; методы сообщений тоже его принимают;
  • thread_name, чтобы начать ветку в форуме или медиаканале, вместе с applied_tags;
  • with_components=True, нужный для компонентов в вебхуке, которым не владеет ни одно приложение.

Клиенты принимают api_url, http_settings и allowed_mentions, как и бот; по умолчанию вебхук может пинговать пользователей и роли, но не @everyone.

Если Discord отвечает 404 Unknown Webhook, вебхук удалён. Тогда bostie отвечает на каждый последующий запрос к нему тем же 404, не отправляя его, так что мёртвый вебхук не расходует лимит недействительных запросов.

Управление вебхуками через бота

bot.rest.webhooks создаёт и перечисляет вебхуки канала или сервера, для чего нужно право «Управлять вебхуками», а также содержит методы с токеном:

  • create(channel_id, name=..., avatar=File(...)) возвращает Webhook, чей url можно передать в WebhookClient.
  • list(channel_id), list_guild(guild_id), fetch(webhook_id), edit(webhook_id, ...) и delete(webhook_id) работают с токеном бота.
  • execute(webhook_id, token, ...) и остальные методы _with_token и методы сообщений — это то, что вызывает WebhookClient.

Событие WebhooksUpdate сообщает, что вебхуки канала изменились. Сообщение, отправленное вебхуком, приходит как WebhookMessage, у которого author — это PartialUser, а webhook_id задан.