Files
zulip/tools/generate-integration-docs-screenshot
Puneeth Chaganti 4d2ce607c9 tools: Add script to trigger webhook notification using fixtures.
When creating a webhook integration or creating a new one, it is a pain to
create or update the screenshots in the documentation. This commit adds a
tool that can trigger a sample notification for the webhook using a fixture,
that is likely already written for the tests.

Currently, the developer needs to take a screenshot manually, but this could
be automated using puppeteer or something like that.

Also, the tool does not support webhooks with basic auth, and only supports
webhooks that use json fixtures. These can be fixed in subsequent commits.
2020-04-16 19:25:13 -07:00

111 lines
3.7 KiB
Python
Executable File

#!/usr/bin/env python3
"""Create or update a webhook integration screenshot using a test fixture."""
# check for the venv
from lib import sanity_check
sanity_check.check_venv(__file__)
import os
import sys
TOOLS_DIR = os.path.abspath(os.path.dirname(__file__))
ROOT_DIR = os.path.dirname(TOOLS_DIR)
sys.path.insert(0, ROOT_DIR)
from scripts.lib.setup_path import setup_path
setup_path()
os.environ["DJANGO_SETTINGS_MODULE"] = "zproject.settings"
import django
django.setup()
import argparse
from typing import Any, Dict
import requests
import ujson
from zerver.models import UserProfile, get_user_by_delivery_email, get_realm
from zerver.lib.actions import do_create_user, notify_created_bot
from zerver.lib.upload import upload_avatar_image
from zerver.lib.actions import do_change_avatar_fields
from zerver.lib.integrations import WebhookIntegration, INTEGRATIONS, split_fixture_path
from zerver.lib.webhooks.common import get_fixture_http_headers
from setup.generate_zulip_bots_static_files import create_png_from_svg
def create_integration_bot(integration_name: str) -> UserProfile:
realm = get_realm('zulip')
owner = get_user_by_delivery_email("iago@zulip.com", realm)
bot_email = "{}-bot@example.com".format(integration_name)
bot_name = "{} Bot".format(integration_name.capitalize())
try:
bot = UserProfile.objects.get(email=bot_email)
except UserProfile.DoesNotExist:
bot = do_create_user(
email=bot_email,
password="123",
realm=owner.realm,
full_name=bot_name,
short_name=bot_name,
bot_type=UserProfile.INCOMING_WEBHOOK_BOT,
bot_owner=owner,
)
notify_created_bot(bot)
if integration.logo_url is None:
return bot
logo_relative_path = integration.logo_url[len(realm.uri) + 1:]
logo_path = os.path.join(ROOT_DIR, logo_relative_path)
if logo_path.endswith(".svg"):
logo_path = create_png_from_svg(logo_path)
with open(logo_path, "rb") as f:
upload_avatar_image(f, owner, bot)
do_change_avatar_fields(bot, UserProfile.AVATAR_FROM_USER)
return bot
def get_integration(integration_name: str) -> WebhookIntegration:
integration = INTEGRATIONS[integration_name]
assert isinstance(integration, WebhookIntegration), "Not a WebhookIntegration"
return integration
def get_requests_headers(integration_name: str, fixture_name: str) -> Dict[str, Any]:
headers = get_fixture_http_headers(integration_name, fixture_name)
def fix_name(header: str) -> str:
header = header if not header.startswith('HTTP_') else header[len('HTTP_'):]
return header.replace('_', '-')
return {fix_name(k): v for k, v in headers.items()}
def webhook_json_fixture(path: str) -> str:
path = os.path.abspath(path)
if not (os.path.exists(path) and path.endswith('.json') and 'webhooks' in path):
raise ValueError('Not a valid webhook JSON fixture')
return path
parser = argparse.ArgumentParser()
parser.add_argument('fixture', type=webhook_json_fixture, help='Path to the fixture to use')
options = parser.parse_args()
integration_name, fixture_name = split_fixture_path(options.fixture)
integration = get_integration(integration_name)
bot = create_integration_bot(integration.name)
assert isinstance(bot.bot_owner, UserProfile)
url = "{}/{}?api_key={}&stream=devel".format(
bot.bot_owner.realm.uri, integration.url, bot.api_key
)
with open(options.fixture) as f:
data = ujson.load(f)
headers = get_requests_headers(integration_name, fixture_name)
response = requests.post(url, json=data, headers=headers)
if response.status_code == 200:
print('Triggered {} webhook'.format(integration.name))
else:
print(response.json())