forked from scrapinghub/spidermon
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add discord integration (scrapinghub#348)
* Add Discord integration Co-authored-by: Ana Paula Gomes <[email protected]> Co-authored-by: Ana Paula Gomes <[email protected]> Co-authored-by: Roy <[email protected]>
- Loading branch information
1 parent
a5d32c8
commit 3539ee4
Showing
17 changed files
with
371 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
Discord action | ||
=============== | ||
|
||
This action allows you to send custom messages to a `Discord`_ channel | ||
using a bot when your monitor suites finish their execution. | ||
|
||
To use this action you need to provide the `Discord webhook URL`_ in your ``settings.py`` file as follows: | ||
|
||
.. code-block:: python | ||
# settings.py | ||
SPIDERMON_DISCORD_WEBHOOK_URL = "<DISCORD_WEBHOOK_URL>" | ||
A notification will look like the following: | ||
|
||
.. image:: /_static/discord_notification.png | ||
:scale: 50 % | ||
:alt: Discord Notification | ||
|
||
Follow :ref:`these steps <configuring-discord-bot>` to configure your Discord bot. | ||
|
||
The following settings are the minimum needed to make this action work: | ||
|
||
SPIDERMON_DISCORD_WEBHOOK_URL | ||
----------------------------- | ||
|
||
`Webhook URL` of your bot. | ||
|
||
.. warning:: | ||
|
||
Be careful when using bot webhooks URL in Spidermon. Do not publish them in public code repositories. | ||
|
||
Other settings available: | ||
|
||
.. _SPIDERMON_DISCORD_FAKE: | ||
|
||
_SPIDERMON_DISCORD_FAKE | ||
----------------------- | ||
|
||
Default: ``False`` | ||
|
||
If set `True`, the Discord message content will be in the logs but nothing will be sent. | ||
|
||
.. _SPIDERMON_DISCORD_MESSAGE: | ||
|
||
SPIDERMON_DISCORD_MESSAGE | ||
------------------------- | ||
|
||
The message to be sent, it supports Jinja2 template formatting. | ||
|
||
.. _SPIDERMON_DISCORD_MESSAGE_TEMPLATE: | ||
|
||
SPIDERMON_DISCORD_MESSAGE_TEMPLATE | ||
---------------------------------- | ||
|
||
Path to a Jinja2 template file to format messages sent by the Discord Action. | ||
|
||
.. _`Discord`: https://discord.com/ | ||
.. _`Discord webhook URL`: https://discord.com/developers/docs/resources/webhook |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
.. _configuring-discord-bot: | ||
|
||
How do I configure a Discord bot for Spidermon? | ||
=============================================== | ||
|
||
What are bots? | ||
-------------- | ||
|
||
A bot is a type of Discord user designed to interact with users via conversation. | ||
|
||
To work with :doc:`Discord Actions </actions/discord-action>`, | ||
you will need a Discord webhook which would send notifications to Discord from Spidermon. | ||
|
||
Steps | ||
----- | ||
|
||
#. Create a Discord webhook <https://discord.com/developers/docs/resources/webhook>`_. | ||
|
||
#. Once your webhook is created, you will receive its URL. This is what we use for ``SPIDERMON_DISCORD_WEBHOOK_URL``. | ||
|
||
#. Add your Discord bot credential to your Scrapy project's settings. That's it. | ||
|
||
.. code-block:: python | ||
# settings.py | ||
SPIDERMON_DISCORD_WEBHOOK_URL = "DISCORD_WEBHOOK_URL" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from __future__ import absolute_import | ||
|
||
import logging | ||
|
||
import requests | ||
from spidermon.contrib.actions.templates import ActionWithTemplates | ||
from spidermon.exceptions import NotConfigured | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class DiscordMessageManager: | ||
sender_token = None | ||
|
||
def __init__(self, webhook_url, fake=False): | ||
if not webhook_url: | ||
raise NotConfigured("You must provide a discord webhook URL.") | ||
self.webhook_url = webhook_url | ||
self.fake = fake | ||
|
||
def send_message(self, text): | ||
if self.fake: | ||
logger.info(text) | ||
return | ||
|
||
body = {"content": text} | ||
response = requests.post(self.webhook_url, json=body) | ||
response.raise_for_status() | ||
|
||
if not response.ok: | ||
logger.error( | ||
f"Failed to send message. Discord API error: {response.reason}" | ||
) | ||
|
||
|
||
class SendDiscordMessage(ActionWithTemplates): | ||
webhook_url = None | ||
message = None | ||
message_template = "discord/default/message.jinja" | ||
fake = False | ||
|
||
def __init__( | ||
self, | ||
webhook_url=None, | ||
message=None, | ||
message_template=None, | ||
fake=None, | ||
): | ||
super(SendDiscordMessage, self).__init__() | ||
|
||
self.fake = fake or self.fake | ||
self.manager = DiscordMessageManager( | ||
webhook_url or self.webhook_url, fake=self.fake | ||
) | ||
self.message = message or self.message | ||
self.message_template = message_template or self.message_template | ||
|
||
@classmethod | ||
def from_crawler_kwargs(cls, crawler): | ||
return { | ||
"webhook_url": crawler.settings.get("SPIDERMON_DISCORD_WEBHOOK_URL"), | ||
"message": crawler.settings.get("SPIDERMON_DISCORD_MESSAGE"), | ||
"message_template": crawler.settings.get( | ||
"SPIDERMON_DISCORD_MESSAGE_TEMPLATE" | ||
), | ||
"fake": crawler.settings.getbool("SPIDERMON_DISCORD_FAKE"), | ||
} | ||
|
||
def run_action(self): | ||
self.manager.send_message(self.get_message()) | ||
|
||
def get_message(self): | ||
if self.message: | ||
return self.render_text_template(self.message) | ||
else: | ||
return self.render_template(self.message_template) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
from __future__ import absolute_import | ||
|
||
from . import SendDiscordMessage | ||
|
||
|
||
class SendDiscordMessageSpiderStarted(SendDiscordMessage): | ||
message_template = "discord/spider/notifier/start/message.jinja" | ||
|
||
|
||
class SendDiscordMessageSpiderFinished(SendDiscordMessage): | ||
message_template = "discord/spider/notifier/finish/message.jinja" | ||
include_ok_messages = False | ||
include_error_messages = True | ||
|
||
def __init__( | ||
self, include_ok_messages=None, include_error_messages=None, *args, **kwargs | ||
): | ||
super(SendDiscordMessageSpiderFinished, self).__init__(*args, **kwargs) | ||
self.include_ok_messages = include_ok_messages or self.include_ok_messages | ||
self.include_error_messages = ( | ||
include_error_messages or self.include_error_messages | ||
) | ||
|
||
@classmethod | ||
def from_crawler_kwargs(cls, crawler): | ||
kwargs = super(SendDiscordMessageSpiderFinished, cls).from_crawler_kwargs( | ||
crawler | ||
) | ||
kwargs.update( | ||
{ | ||
"include_ok_messages": crawler.settings.get( | ||
"SPIDERMON_DISCORD_NOTIFIER_INCLUDE_OK_MESSAGES" | ||
), | ||
"include_error_messages": crawler.settings.get( | ||
"SPIDERMON_DISCORD_NOTIFIER_INCLUDE_ERROR_MESSAGES" | ||
), | ||
} | ||
) | ||
return kwargs | ||
|
||
def get_template_context(self): | ||
context = super(SendDiscordMessageSpiderFinished, self).get_template_context() | ||
context.update( | ||
{ | ||
"include_ok_messages": self.include_ok_messages, | ||
"include_error_messages": self.include_error_messages, | ||
} | ||
) | ||
return context | ||
|
||
|
||
class SendDiscordMessageSpiderRunning(SendDiscordMessageSpiderFinished): | ||
message_template = "discord/spider/notifier/periodic/message.jinja" |
1 change: 1 addition & 0 deletions
1
spidermon/contrib/actions/discord/templates/discord/default/message.jinja
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This is the default message... |
16 changes: 16 additions & 0 deletions
16
spidermon/contrib/actions/discord/templates/discord/spider/notifier/finish/message.jinja
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{% import 'discord/spider/notifier/macros.jinja' as renderer with context %} | ||
{% if monitors_failed %} | ||
{{ "💀" }} "`{{ renderer.render_spider_name() }}`" spider finished with errors! {{ renderer.render_url() }} _(errors={{ result.monitors_failed_results|length }})_ {{ "\n" }} | ||
{% else %} | ||
{{ "🎉"}} "`{{ renderer.render_spider_name() }}`" spider finished! {{ renderer.render_url() }} {{ "\n" }} | ||
{% endif %} | ||
{%- if include_ok_messages and monitors_passed -%} | ||
``` | ||
{{ renderer.render_passed() -}} | ||
``` | ||
{% endif %} | ||
{%- if include_error_messages and monitors_failed -%} | ||
``` | ||
{{ renderer.render_failed() -}} | ||
``` | ||
{% endif %} |
19 changes: 19 additions & 0 deletions
19
spidermon/contrib/actions/discord/templates/discord/spider/notifier/macros.jinja
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{% macro render_result(emoji, result) %} | ||
{{ emoji }} {{ result.monitor.name }} | ||
{% endmacro %} | ||
|
||
{% macro render_results(emoji, results) %} | ||
{% for result in results %} {{- render_result(emoji, result) -}} {% endfor %} | ||
{% endmacro %} | ||
|
||
{% macro render_passed() %} | ||
{{- render_results("✔️", result.monitors_passed_results) -}} | ||
{% endmacro %} | ||
|
||
{% macro render_failed() %} | ||
{{ render_results("❌", result.monitors_failed_results) }} | ||
{% endmacro %} | ||
|
||
{% macro render_job_url() %}{% if data.job %} / [view job in Scrapy Cloud](https://app.scrapinghub.com/p/{{ data.job.key }}){% endif %}{% endmacro %} | ||
{% macro render_url() %}{{ render_job_url() }}{% endmacro %} | ||
{% macro render_spider_name() %}{% if data.spider %}{{ data.spider.name }}{% elif data.job %}{{ data.job.metadata['spider'] }}{% else %}??{% endif %}{% endmacro %} |
12 changes: 12 additions & 0 deletions
12
spidermon/contrib/actions/discord/templates/discord/spider/notifier/periodic/message.jinja
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{% import 'discord/spider/notifier/macros.jinja' as renderer with context %} | ||
{{ "💀" }} "`{{ renderer.render_spider_name() }}`" Detected errors on running spider!{{ renderer.render_job_url() }} _(errors={{ result.monitors_failed_results|length }})_ {{ "\n\n" }} | ||
{%- if include_ok_messages and monitors_passed -%} | ||
``` | ||
{{ renderer.render_passed() -}} | ||
``` | ||
{% endif %} | ||
{%- if include_error_messages and monitors_failed -%} | ||
``` | ||
{{ renderer.render_failed() -}} | ||
``` | ||
{% endif %} |
2 changes: 2 additions & 0 deletions
2
spidermon/contrib/actions/discord/templates/discord/spider/notifier/start/message.jinja
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
{% import 'discord/spider/notifier/macros.jinja' as renderer with context %} | ||
{{ "🕒" }} "`{{ renderer.render_spider_name() }}`" *spider started!* {{ renderer.render_job_url() }} |
Oops, something went wrong.