2017-09-22 18:30:18 +02:00
|
|
|
import os
|
2024-07-12 02:30:25 +02:00
|
|
|
from collections.abc import Callable, Sequence
|
2020-06-13 03:34:01 +02:00
|
|
|
from dataclasses import dataclass, field
|
2024-07-12 02:30:25 +02:00
|
|
|
from typing import Any, TypeAlias
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2019-07-17 01:52:30 +02:00
|
|
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
2024-09-25 00:25:45 +02:00
|
|
|
from django.http import HttpRequest, HttpResponseBase
|
|
|
|
from django.urls import URLPattern, path
|
2016-10-27 14:52:33 +02:00
|
|
|
from django.utils.module_loading import import_string
|
2022-08-05 00:07:27 +02:00
|
|
|
from django.utils.translation import gettext_lazy
|
2024-09-25 00:25:45 +02:00
|
|
|
from django.views.decorators.csrf import csrf_exempt
|
2022-09-19 21:43:34 +02:00
|
|
|
from django_stubs_ext import StrPromise
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2019-07-17 02:29:08 +02:00
|
|
|
from zerver.lib.storage import static_path
|
2024-09-20 11:41:30 +02:00
|
|
|
from zerver.lib.validator import check_bool, check_string
|
|
|
|
from zerver.lib.webhooks.common import WebhookConfigOption
|
2017-04-05 07:34:02 +02:00
|
|
|
|
2016-08-04 21:13:25 +02:00
|
|
|
"""This module declares all of the (documented) integrations available
|
|
|
|
in the Zulip server. The Integration class is used as part of
|
2023-03-23 03:47:14 +01:00
|
|
|
generating the documentation on the /integrations/ page, while the
|
2016-08-04 21:13:25 +02:00
|
|
|
WebhookIntegration class is also used to generate the URLs in
|
|
|
|
`zproject/urls.py` for webhook integrations.
|
|
|
|
|
|
|
|
To add a new non-webhook integration, add code to the INTEGRATIONS
|
|
|
|
dictionary below.
|
|
|
|
|
|
|
|
To add a new webhook integration, declare a WebhookIntegration in the
|
|
|
|
WEBHOOK_INTEGRATIONS list below (it will be automatically added to
|
|
|
|
INTEGRATIONS).
|
|
|
|
|
2022-09-08 13:33:36 +02:00
|
|
|
To add a new integration category, add to either the CATEGORIES or
|
|
|
|
META_CATEGORY dicts below. The META_CATEGORY dict is for categories
|
|
|
|
that do not describe types of tools (e.g., bots or frameworks).
|
2017-07-05 22:07:46 +02:00
|
|
|
|
2016-08-04 21:13:25 +02:00
|
|
|
Over time, we expect this registry to grow additional convenience
|
|
|
|
features for writing and configuring integrations efficiently.
|
|
|
|
"""
|
2016-07-25 22:12:12 +02:00
|
|
|
|
2024-09-20 11:41:30 +02:00
|
|
|
OptionValidator: TypeAlias = Callable[[str, str], str | bool | None]
|
2022-06-01 00:34:34 +02:00
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
META_CATEGORY: dict[str, StrPromise] = {
|
2021-04-16 00:57:30 +02:00
|
|
|
"meta-integration": gettext_lazy("Integration frameworks"),
|
2022-09-08 13:33:36 +02:00
|
|
|
"bots": gettext_lazy("Interactive bots"),
|
|
|
|
}
|
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
CATEGORIES: dict[str, StrPromise] = {
|
2022-09-08 13:33:36 +02:00
|
|
|
**META_CATEGORY,
|
2021-04-16 00:57:30 +02:00
|
|
|
"continuous-integration": gettext_lazy("Continuous integration"),
|
|
|
|
"customer-support": gettext_lazy("Customer support"),
|
|
|
|
"deployment": gettext_lazy("Deployment"),
|
2021-03-28 00:11:00 +01:00
|
|
|
"entertainment": gettext_lazy("Entertainment"),
|
2021-04-16 00:57:30 +02:00
|
|
|
"communication": gettext_lazy("Communication"),
|
|
|
|
"financial": gettext_lazy("Financial"),
|
2022-09-08 13:33:36 +02:00
|
|
|
"hr": gettext_lazy("Human resources"),
|
2021-04-16 00:57:30 +02:00
|
|
|
"marketing": gettext_lazy("Marketing"),
|
|
|
|
"misc": gettext_lazy("Miscellaneous"),
|
2022-09-08 13:33:36 +02:00
|
|
|
"monitoring": gettext_lazy("Monitoring"),
|
2021-04-16 00:57:30 +02:00
|
|
|
"project-management": gettext_lazy("Project management"),
|
|
|
|
"productivity": gettext_lazy("Productivity"),
|
|
|
|
"version-control": gettext_lazy("Version control"),
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
}
|
2017-07-05 22:07:46 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:37:41 +01:00
|
|
|
class Integration:
|
2021-02-12 08:20:45 +01:00
|
|
|
DEFAULT_LOGO_STATIC_PATH_PNG = "images/integrations/logos/{name}.png"
|
|
|
|
DEFAULT_LOGO_STATIC_PATH_SVG = "images/integrations/logos/{name}.svg"
|
|
|
|
DEFAULT_BOT_AVATAR_PATH = "images/integrations/bot_avatars/{name}.png"
|
2016-07-25 22:12:12 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
name: str,
|
|
|
|
client_name: str,
|
2024-07-12 02:30:17 +02:00
|
|
|
categories: list[str],
|
2024-07-12 02:30:23 +02:00
|
|
|
logo: str | None = None,
|
|
|
|
secondary_line_text: str | None = None,
|
|
|
|
display_name: str | None = None,
|
|
|
|
doc: str | None = None,
|
|
|
|
stream_name: str | None = None,
|
2021-02-12 08:19:30 +01:00
|
|
|
legacy: bool = False,
|
2024-09-20 11:41:30 +02:00
|
|
|
config_options: Sequence[WebhookConfigOption] = [],
|
2021-02-12 08:19:30 +01:00
|
|
|
) -> None:
|
2016-07-25 22:12:12 +02:00
|
|
|
self.name = name
|
|
|
|
self.client_name = client_name
|
|
|
|
self.secondary_line_text = secondary_line_text
|
2017-07-21 03:22:09 +02:00
|
|
|
self.legacy = legacy
|
2016-11-26 00:25:05 +01:00
|
|
|
self.doc = doc
|
2016-07-25 22:12:12 +02:00
|
|
|
|
2019-08-17 13:17:07 +02:00
|
|
|
# Note: Currently only incoming webhook type bots use this list for
|
|
|
|
# defining how the bot's BotConfigData should be. Embedded bots follow
|
|
|
|
# a different approach.
|
|
|
|
self.config_options = config_options
|
|
|
|
|
2017-07-05 22:07:46 +02:00
|
|
|
for category in categories:
|
|
|
|
if category not in CATEGORIES:
|
|
|
|
raise KeyError( # nocoverage
|
2021-02-12 08:20:45 +01:00
|
|
|
"INTEGRATIONS: "
|
2021-02-12 08:19:30 +01:00
|
|
|
+ name
|
2021-02-12 08:20:45 +01:00
|
|
|
+ " - category '"
|
2021-02-12 08:19:30 +01:00
|
|
|
+ category
|
2021-02-12 08:20:45 +01:00
|
|
|
+ "' is not a key in CATEGORIES.",
|
2017-07-05 22:07:46 +02:00
|
|
|
)
|
2022-10-30 02:30:03 +02:00
|
|
|
self.categories = [CATEGORIES[c] for c in categories]
|
2017-07-05 22:07:46 +02:00
|
|
|
|
2020-05-15 09:43:39 +02:00
|
|
|
self.logo_path = logo if logo is not None else self.get_logo_path()
|
2022-07-23 00:33:09 +02:00
|
|
|
# TODO: Enforce that all integrations have logo_url with an assertion.
|
2020-05-15 09:43:39 +02:00
|
|
|
self.logo_url = self.get_logo_url()
|
2016-07-25 22:12:12 +02:00
|
|
|
|
|
|
|
if display_name is None:
|
|
|
|
display_name = name.title()
|
|
|
|
self.display_name = display_name
|
|
|
|
|
2017-06-12 23:25:30 +02:00
|
|
|
if stream_name is None:
|
|
|
|
stream_name = self.name
|
|
|
|
self.stream_name = stream_name
|
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def is_enabled(self) -> bool:
|
2016-07-25 22:12:12 +02:00
|
|
|
return True
|
|
|
|
|
2024-07-12 02:30:23 +02:00
|
|
|
def get_logo_path(self) -> str | None:
|
2019-07-17 01:52:30 +02:00
|
|
|
logo_file_path_svg = self.DEFAULT_LOGO_STATIC_PATH_SVG.format(name=self.name)
|
|
|
|
logo_file_path_png = self.DEFAULT_LOGO_STATIC_PATH_PNG.format(name=self.name)
|
2019-07-17 02:29:08 +02:00
|
|
|
if os.path.isfile(static_path(logo_file_path_svg)):
|
2020-04-21 15:10:56 +02:00
|
|
|
return logo_file_path_svg
|
2019-07-17 02:29:08 +02:00
|
|
|
elif os.path.isfile(static_path(logo_file_path_png)):
|
2020-04-21 15:10:56 +02:00
|
|
|
return logo_file_path_png
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
2024-07-12 02:30:23 +02:00
|
|
|
def get_bot_avatar_path(self) -> str | None:
|
2020-05-15 09:45:06 +02:00
|
|
|
if self.logo_path is not None:
|
|
|
|
name = os.path.splitext(os.path.basename(self.logo_path))[0]
|
|
|
|
return self.DEFAULT_BOT_AVATAR_PATH.format(name=name)
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
2024-07-12 02:30:23 +02:00
|
|
|
def get_logo_url(self) -> str | None:
|
2020-05-15 09:43:39 +02:00
|
|
|
if self.logo_path is not None:
|
|
|
|
return staticfiles_storage.url(self.logo_path)
|
2017-10-17 19:39:01 +02:00
|
|
|
|
|
|
|
return None
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-09-17 02:28:59 +02:00
|
|
|
class BotIntegration(Integration):
|
2021-02-12 08:20:45 +01:00
|
|
|
DEFAULT_LOGO_STATIC_PATH_PNG = "generated/bots/{name}/logo.png"
|
|
|
|
DEFAULT_LOGO_STATIC_PATH_SVG = "generated/bots/{name}/logo.svg"
|
|
|
|
ZULIP_LOGO_STATIC_PATH_PNG = "images/logo/zulip-icon-128x128.png"
|
|
|
|
DEFAULT_DOC_PATH = "{name}/doc.md"
|
2017-09-17 02:28:59 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
name: str,
|
2024-07-12 02:30:17 +02:00
|
|
|
categories: list[str],
|
2024-07-12 02:30:23 +02:00
|
|
|
logo: str | None = None,
|
|
|
|
secondary_line_text: str | None = None,
|
|
|
|
display_name: str | None = None,
|
|
|
|
doc: str | None = None,
|
2021-02-12 08:19:30 +01:00
|
|
|
) -> None:
|
2017-10-27 08:28:23 +02:00
|
|
|
super().__init__(
|
2017-09-17 02:28:59 +02:00
|
|
|
name,
|
|
|
|
client_name=name,
|
|
|
|
categories=categories,
|
|
|
|
secondary_line_text=secondary_line_text,
|
|
|
|
)
|
|
|
|
|
|
|
|
if logo is None:
|
2019-07-17 01:52:30 +02:00
|
|
|
self.logo_url = self.get_logo_url()
|
|
|
|
if self.logo_url is None:
|
2017-09-17 02:28:59 +02:00
|
|
|
# TODO: Add a test for this by initializing one in a test.
|
2019-07-17 01:52:30 +02:00
|
|
|
logo = staticfiles_storage.url(self.ZULIP_LOGO_STATIC_PATH_PNG) # nocoverage
|
|
|
|
else:
|
|
|
|
self.logo_url = staticfiles_storage.url(logo)
|
2017-09-17 02:28:59 +02:00
|
|
|
|
|
|
|
if display_name is None:
|
2020-06-09 00:25:09 +02:00
|
|
|
display_name = f"{name.title()} Bot" # nocoverage
|
2017-09-17 02:28:59 +02:00
|
|
|
else:
|
2020-06-09 00:25:09 +02:00
|
|
|
display_name = f"{display_name} Bot"
|
2017-09-17 02:28:59 +02:00
|
|
|
self.display_name = display_name
|
|
|
|
|
|
|
|
if doc is None:
|
|
|
|
doc = self.DEFAULT_DOC_PATH.format(name=name)
|
|
|
|
self.doc = doc
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2016-07-25 22:12:12 +02:00
|
|
|
class WebhookIntegration(Integration):
|
2021-02-12 08:20:45 +01:00
|
|
|
DEFAULT_FUNCTION_PATH = "zerver.webhooks.{name}.view.api_{name}_webhook"
|
|
|
|
DEFAULT_URL = "api/v1/external/{name}"
|
|
|
|
DEFAULT_CLIENT_NAME = "Zulip{name}Webhook"
|
|
|
|
DEFAULT_DOC_PATH = "{name}/doc.{ext}"
|
2016-07-25 22:12:12 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
name: str,
|
2024-07-12 02:30:17 +02:00
|
|
|
categories: list[str],
|
2024-07-12 02:30:23 +02:00
|
|
|
client_name: str | None = None,
|
|
|
|
logo: str | None = None,
|
|
|
|
secondary_line_text: str | None = None,
|
|
|
|
function: str | None = None,
|
|
|
|
url: str | None = None,
|
|
|
|
display_name: str | None = None,
|
|
|
|
doc: str | None = None,
|
|
|
|
stream_name: str | None = None,
|
2021-02-12 08:19:30 +01:00
|
|
|
legacy: bool = False,
|
2024-09-20 11:41:30 +02:00
|
|
|
config_options: Sequence[WebhookConfigOption] = [],
|
2024-07-12 02:30:23 +02:00
|
|
|
dir_name: str | None = None,
|
2021-02-12 08:19:30 +01:00
|
|
|
) -> None:
|
2016-07-25 22:12:12 +02:00
|
|
|
if client_name is None:
|
|
|
|
client_name = self.DEFAULT_CLIENT_NAME.format(name=name.title())
|
2017-10-27 08:28:23 +02:00
|
|
|
super().__init__(
|
2017-06-13 16:08:07 +02:00
|
|
|
name,
|
|
|
|
client_name,
|
2017-07-05 22:07:46 +02:00
|
|
|
categories,
|
2017-06-13 16:08:07 +02:00
|
|
|
logo=logo,
|
|
|
|
secondary_line_text=secondary_line_text,
|
|
|
|
display_name=display_name,
|
2017-07-21 03:22:09 +02:00
|
|
|
stream_name=stream_name,
|
2019-08-17 13:17:07 +02:00
|
|
|
legacy=legacy,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
config_options=config_options,
|
2017-06-13 16:08:07 +02:00
|
|
|
)
|
2016-07-25 22:12:12 +02:00
|
|
|
|
|
|
|
if function is None:
|
|
|
|
function = self.DEFAULT_FUNCTION_PATH.format(name=name)
|
2024-09-25 00:25:45 +02:00
|
|
|
self.function_name = function
|
2016-07-25 22:12:12 +02:00
|
|
|
|
|
|
|
if url is None:
|
|
|
|
url = self.DEFAULT_URL.format(name=name)
|
|
|
|
self.url = url
|
|
|
|
|
2016-11-26 00:25:05 +01:00
|
|
|
if doc is None:
|
2021-02-12 08:20:45 +01:00
|
|
|
doc = self.DEFAULT_DOC_PATH.format(name=name, ext="md")
|
2016-11-26 00:25:05 +01:00
|
|
|
self.doc = doc
|
|
|
|
|
2023-12-20 00:43:09 +01:00
|
|
|
if dir_name is None:
|
|
|
|
dir_name = self.name
|
|
|
|
self.dir_name = dir_name
|
|
|
|
|
2024-09-25 00:25:45 +02:00
|
|
|
def get_function(self) -> Callable[[HttpRequest], HttpResponseBase]:
|
|
|
|
return import_string(self.function_name)
|
|
|
|
|
|
|
|
@csrf_exempt
|
|
|
|
def view(self, request: HttpRequest) -> HttpResponseBase:
|
|
|
|
# Lazily load the real view function to improve startup performance.
|
|
|
|
function = self.get_function()
|
|
|
|
assert function.csrf_exempt # type: ignore[attr-defined] # ensure the above @csrf_exempt is justified
|
|
|
|
return function(request)
|
|
|
|
|
2016-07-25 22:12:12 +02:00
|
|
|
@property
|
2024-09-25 00:25:45 +02:00
|
|
|
def url_object(self) -> URLPattern:
|
|
|
|
return path(self.url, self.view)
|
2016-07-25 22:12:12 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
def split_fixture_path(path: str) -> tuple[str, str]:
|
2020-04-09 19:33:49 +02:00
|
|
|
path, fixture_name = os.path.split(path)
|
|
|
|
fixture_name, _ = os.path.splitext(fixture_name)
|
|
|
|
integration_name = os.path.split(os.path.dirname(path))[-1]
|
|
|
|
return integration_name, fixture_name
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2020-06-11 21:44:23 +02:00
|
|
|
@dataclass
|
2021-03-29 15:02:37 +02:00
|
|
|
class BaseScreenshotConfig:
|
2020-06-11 21:44:23 +02:00
|
|
|
fixture_name: str
|
2021-02-12 08:20:45 +01:00
|
|
|
image_name: str = "001.png"
|
2024-07-12 02:30:23 +02:00
|
|
|
image_dir: str | None = None
|
|
|
|
bot_name: str | None = None
|
2021-03-29 15:02:37 +02:00
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class ScreenshotConfig(BaseScreenshotConfig):
|
2020-06-11 21:44:23 +02:00
|
|
|
payload_as_query_param: bool = False
|
2021-02-12 08:20:45 +01:00
|
|
|
payload_param_name: str = "payload"
|
2024-07-12 02:30:17 +02:00
|
|
|
extra_params: dict[str, str] = field(default_factory=dict)
|
2020-06-11 21:44:23 +02:00
|
|
|
use_basic_auth: bool = False
|
2024-07-12 02:30:17 +02:00
|
|
|
custom_headers: dict[str, str] = field(default_factory=dict)
|
2020-04-26 08:35:53 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
|
|
|
def get_fixture_and_image_paths(
|
2021-03-29 15:02:37 +02:00
|
|
|
integration: Integration, screenshot_config: BaseScreenshotConfig
|
2024-07-12 02:30:17 +02:00
|
|
|
) -> tuple[str, str]:
|
2021-03-29 15:02:37 +02:00
|
|
|
if isinstance(integration, WebhookIntegration):
|
2023-12-20 00:43:09 +01:00
|
|
|
fixture_dir = os.path.join("zerver", "webhooks", integration.dir_name, "fixtures")
|
2021-03-29 15:02:37 +02:00
|
|
|
else:
|
|
|
|
fixture_dir = os.path.join("zerver", "integration_fixtures", integration.name)
|
2020-04-26 08:35:53 +02:00
|
|
|
fixture_path = os.path.join(fixture_dir, screenshot_config.fixture_name)
|
|
|
|
image_dir = screenshot_config.image_dir or integration.name
|
|
|
|
image_name = screenshot_config.image_name
|
2021-02-12 08:20:45 +01:00
|
|
|
image_path = os.path.join("static/images/integrations", image_dir, image_name)
|
2020-04-26 08:35:53 +02:00
|
|
|
return fixture_path, image_path
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-15 23:01:12 +01:00
|
|
|
class HubotIntegration(Integration):
|
2016-11-23 18:58:59 +01:00
|
|
|
GIT_URL_TEMPLATE = "https://github.com/hubot-scripts/hubot-{}"
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
name: str,
|
2024-07-12 02:30:17 +02:00
|
|
|
categories: list[str],
|
2024-07-12 02:30:23 +02:00
|
|
|
display_name: str | None = None,
|
|
|
|
logo: str | None = None,
|
|
|
|
logo_alt: str | None = None,
|
|
|
|
git_url: str | None = None,
|
2021-02-12 08:19:30 +01:00
|
|
|
legacy: bool = False,
|
|
|
|
) -> None:
|
2016-11-23 18:58:59 +01:00
|
|
|
if logo_alt is None:
|
2020-06-09 00:25:09 +02:00
|
|
|
logo_alt = f"{name.title()} logo"
|
2016-11-23 18:58:59 +01:00
|
|
|
self.logo_alt = logo_alt
|
|
|
|
|
|
|
|
if git_url is None:
|
|
|
|
git_url = self.GIT_URL_TEMPLATE.format(name)
|
2017-10-07 12:30:49 +02:00
|
|
|
self.hubot_docs_url = git_url
|
|
|
|
|
2017-10-27 08:28:23 +02:00
|
|
|
super().__init__(
|
2021-02-12 08:19:30 +01:00
|
|
|
name,
|
|
|
|
name,
|
|
|
|
categories,
|
|
|
|
logo=logo,
|
|
|
|
display_name=display_name,
|
2021-02-12 08:20:45 +01:00
|
|
|
doc="zerver/integrations/hubot_common.md",
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
legacy=legacy,
|
2017-06-13 16:08:07 +02:00
|
|
|
)
|
2016-11-23 18:58:59 +01:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-07-21 17:52:56 +02:00
|
|
|
class EmbeddedBotIntegration(Integration):
|
2021-02-12 08:19:30 +01:00
|
|
|
"""
|
2017-07-21 17:52:56 +02:00
|
|
|
This class acts as a registry for bots verified as safe
|
|
|
|
and valid such that these are capable of being deployed on the server.
|
2021-02-12 08:19:30 +01:00
|
|
|
"""
|
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
DEFAULT_CLIENT_NAME = "Zulip{name}EmbeddedBot"
|
2017-07-21 17:52:56 +02:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def __init__(self, name: str, *args: Any, **kwargs: Any) -> None:
|
2017-07-21 17:52:56 +02:00
|
|
|
assert kwargs.get("client_name") is None
|
|
|
|
client_name = self.DEFAULT_CLIENT_NAME.format(name=name.title())
|
2021-02-12 08:19:30 +01:00
|
|
|
super().__init__(name, client_name, *args, **kwargs)
|
|
|
|
|
2017-07-21 17:52:56 +02:00
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
EMBEDDED_BOTS: list[EmbeddedBotIntegration] = [
|
2021-02-12 08:20:45 +01:00
|
|
|
EmbeddedBotIntegration("converter", []),
|
|
|
|
EmbeddedBotIntegration("encrypt", []),
|
|
|
|
EmbeddedBotIntegration("helloworld", []),
|
|
|
|
EmbeddedBotIntegration("virtual_fs", []),
|
|
|
|
EmbeddedBotIntegration("giphy", []),
|
|
|
|
EmbeddedBotIntegration("followup", []),
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
]
|
2017-07-21 17:52:56 +02:00
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
WEBHOOK_INTEGRATIONS: list[WebhookIntegration] = [
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("airbrake", ["monitoring"]),
|
2024-10-09 00:02:24 +02:00
|
|
|
WebhookIntegration("airbyte", ["monitoring"]),
|
2020-02-07 10:04:22 +01:00
|
|
|
WebhookIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"alertmanager",
|
|
|
|
["monitoring"],
|
|
|
|
display_name="Prometheus Alertmanager",
|
|
|
|
logo="images/integrations/logos/prometheus.svg",
|
|
|
|
),
|
|
|
|
WebhookIntegration("ansibletower", ["deployment"], display_name="Ansible Tower"),
|
|
|
|
WebhookIntegration("appfollow", ["customer-support"], display_name="AppFollow"),
|
|
|
|
WebhookIntegration("appveyor", ["continuous-integration"], display_name="AppVeyor"),
|
2022-07-17 13:28:15 +02:00
|
|
|
WebhookIntegration("azuredevops", ["version-control"], display_name="AzureDevOps"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("beanstalk", ["version-control"], stream_name="commits"),
|
|
|
|
WebhookIntegration("basecamp", ["project-management"]),
|
|
|
|
WebhookIntegration("beeminder", ["misc"], display_name="Beeminder"),
|
2019-03-03 17:44:33 +01:00
|
|
|
WebhookIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"bitbucket3",
|
|
|
|
["version-control"],
|
|
|
|
logo="images/integrations/logos/bitbucket.svg",
|
|
|
|
display_name="Bitbucket Server",
|
|
|
|
stream_name="bitbucket",
|
2019-03-03 17:44:33 +01:00
|
|
|
),
|
2017-06-12 23:25:30 +02:00
|
|
|
WebhookIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"bitbucket2",
|
|
|
|
["version-control"],
|
|
|
|
logo="images/integrations/logos/bitbucket.svg",
|
|
|
|
display_name="Bitbucket",
|
|
|
|
stream_name="bitbucket",
|
2017-06-12 23:25:30 +02:00
|
|
|
),
|
2017-06-12 23:48:16 +02:00
|
|
|
WebhookIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"bitbucket",
|
|
|
|
["version-control"],
|
|
|
|
display_name="Bitbucket",
|
|
|
|
secondary_line_text="(Enterprise)",
|
|
|
|
stream_name="commits",
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
legacy=True,
|
2017-06-12 23:48:16 +02:00
|
|
|
),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("buildbot", ["continuous-integration"], display_name="Buildbot"),
|
2021-12-16 21:34:08 +01:00
|
|
|
WebhookIntegration("canarytoken", ["monitoring"], display_name="Thinkst Canarytokens"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("circleci", ["continuous-integration"], display_name="CircleCI"),
|
|
|
|
WebhookIntegration("clubhouse", ["project-management"]),
|
|
|
|
WebhookIntegration("codeship", ["continuous-integration", "deployment"]),
|
|
|
|
WebhookIntegration("crashlytics", ["monitoring"]),
|
|
|
|
WebhookIntegration("dialogflow", ["customer-support"], display_name="Dialogflow"),
|
|
|
|
WebhookIntegration("delighted", ["customer-support", "marketing"], display_name="Delighted"),
|
2017-06-13 00:34:47 +02:00
|
|
|
WebhookIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"deskdotcom",
|
|
|
|
["customer-support"],
|
|
|
|
logo="images/integrations/logos/deskcom.png",
|
|
|
|
display_name="Desk.com",
|
|
|
|
stream_name="desk",
|
|
|
|
),
|
|
|
|
WebhookIntegration("dropbox", ["productivity"], display_name="Dropbox"),
|
|
|
|
WebhookIntegration("errbit", ["monitoring"], display_name="Errbit"),
|
|
|
|
WebhookIntegration("flock", ["customer-support"], display_name="Flock"),
|
|
|
|
WebhookIntegration("freshdesk", ["customer-support"]),
|
2021-04-15 23:39:16 +02:00
|
|
|
WebhookIntegration("freshping", ["monitoring"], display_name="Freshping"),
|
2021-04-13 02:22:41 +02:00
|
|
|
WebhookIntegration(
|
|
|
|
"freshstatus", ["monitoring", "customer-support"], display_name="Freshstatus"
|
|
|
|
),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("front", ["customer-support"], display_name="Front"),
|
|
|
|
WebhookIntegration("gitea", ["version-control"], stream_name="commits"),
|
2019-04-26 01:16:38 +02:00
|
|
|
WebhookIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"github",
|
|
|
|
["version-control"],
|
|
|
|
display_name="GitHub",
|
|
|
|
logo="images/integrations/logos/github.svg",
|
|
|
|
function="zerver.webhooks.github.view.api_github_webhook",
|
|
|
|
stream_name="github",
|
2024-09-20 11:41:30 +02:00
|
|
|
config_options=[
|
|
|
|
WebhookConfigOption(
|
|
|
|
name="branches",
|
|
|
|
description="Filter by branches (comma-separated list)",
|
|
|
|
validator=check_string,
|
|
|
|
),
|
|
|
|
WebhookConfigOption(
|
|
|
|
name="ignore_private_repositories",
|
|
|
|
description="Exclude notifications from private repositories",
|
|
|
|
validator=check_bool,
|
|
|
|
),
|
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
),
|
2023-12-20 00:43:09 +01:00
|
|
|
WebhookIntegration(
|
|
|
|
"githubsponsors",
|
|
|
|
["financial"],
|
|
|
|
display_name="GitHub Sponsors",
|
|
|
|
logo="images/integrations/logos/github.svg",
|
|
|
|
dir_name="github",
|
|
|
|
function="zerver.webhooks.github.view.api_github_webhook",
|
|
|
|
doc="github/githubsponsors.md",
|
|
|
|
stream_name="github",
|
|
|
|
),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("gitlab", ["version-control"], display_name="GitLab"),
|
|
|
|
WebhookIntegration("gocd", ["continuous-integration"], display_name="GoCD"),
|
|
|
|
WebhookIntegration("gogs", ["version-control"], stream_name="commits"),
|
|
|
|
WebhookIntegration("gosquared", ["marketing"], display_name="GoSquared"),
|
|
|
|
WebhookIntegration("grafana", ["monitoring"], display_name="Grafana"),
|
|
|
|
WebhookIntegration("greenhouse", ["hr"], display_name="Greenhouse"),
|
|
|
|
WebhookIntegration("groove", ["customer-support"], display_name="Groove"),
|
|
|
|
WebhookIntegration("harbor", ["deployment", "productivity"], display_name="Harbor"),
|
|
|
|
WebhookIntegration("hellosign", ["productivity", "hr"], display_name="HelloSign"),
|
|
|
|
WebhookIntegration("helloworld", ["misc"], display_name="Hello World"),
|
|
|
|
WebhookIntegration("heroku", ["deployment"], display_name="Heroku"),
|
|
|
|
WebhookIntegration("homeassistant", ["misc"], display_name="Home Assistant"),
|
2017-07-05 22:07:46 +02:00
|
|
|
WebhookIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"ifttt",
|
|
|
|
["meta-integration"],
|
|
|
|
function="zerver.webhooks.ifttt.view.api_iftt_app_webhook",
|
|
|
|
display_name="IFTTT",
|
|
|
|
),
|
|
|
|
WebhookIntegration("insping", ["monitoring"], display_name="Insping"),
|
|
|
|
WebhookIntegration("intercom", ["customer-support"], display_name="Intercom"),
|
2021-05-10 07:02:14 +02:00
|
|
|
WebhookIntegration("jira", ["project-management"], display_name="Jira"),
|
2020-10-21 20:56:33 +02:00
|
|
|
WebhookIntegration("jotform", ["misc"], display_name="Jotform"),
|
2021-05-10 07:02:14 +02:00
|
|
|
WebhookIntegration("json", ["misc"], display_name="JSON formatter"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("librato", ["monitoring"]),
|
2021-03-28 00:11:00 +01:00
|
|
|
WebhookIntegration("lidarr", ["entertainment"]),
|
2023-04-12 20:34:01 +02:00
|
|
|
WebhookIntegration("linear", ["project-management"], display_name="Linear"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("mention", ["marketing"], display_name="Mention"),
|
|
|
|
WebhookIntegration("netlify", ["continuous-integration", "deployment"], display_name="Netlify"),
|
|
|
|
WebhookIntegration("newrelic", ["monitoring"], display_name="New Relic"),
|
2024-08-02 15:58:41 +02:00
|
|
|
WebhookIntegration("opencollective", ["financial"], display_name="Open Collective"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("opsgenie", ["meta-integration", "monitoring"]),
|
|
|
|
WebhookIntegration("pagerduty", ["monitoring"], display_name="PagerDuty"),
|
|
|
|
WebhookIntegration("papertrail", ["monitoring"]),
|
2024-01-17 22:56:18 +01:00
|
|
|
WebhookIntegration("patreon", ["financial"], display_name="Patreon"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("pingdom", ["monitoring"]),
|
|
|
|
WebhookIntegration("pivotal", ["project-management"], display_name="Pivotal Tracker"),
|
2021-03-27 18:40:42 +01:00
|
|
|
WebhookIntegration("radarr", ["entertainment"], display_name="Radarr"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("raygun", ["monitoring"], display_name="Raygun"),
|
2021-12-17 05:12:13 +01:00
|
|
|
WebhookIntegration("reviewboard", ["version-control"], display_name="Review Board"),
|
2022-07-09 12:23:36 +02:00
|
|
|
WebhookIntegration("rhodecode", ["version-control"], display_name="RhodeCode"),
|
2023-04-07 19:13:21 +02:00
|
|
|
WebhookIntegration("rundeck", ["deployment"], display_name="Rundeck"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("semaphore", ["continuous-integration", "deployment"]),
|
|
|
|
WebhookIntegration("sentry", ["monitoring"]),
|
2020-02-12 23:48:55 +01:00
|
|
|
WebhookIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"slack_incoming",
|
|
|
|
["communication", "meta-integration"],
|
2020-02-12 23:48:55 +01:00
|
|
|
display_name="Slack-compatible webhook",
|
2021-02-12 08:20:45 +01:00
|
|
|
logo="images/integrations/logos/slack.svg",
|
|
|
|
),
|
|
|
|
WebhookIntegration("slack", ["communication"]),
|
2021-03-10 03:47:04 +01:00
|
|
|
WebhookIntegration("sonarqube", ["continuous-integration"], display_name="SonarQube"),
|
2021-03-27 03:56:36 +01:00
|
|
|
WebhookIntegration("sonarr", ["entertainment"], display_name="Sonarr"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("splunk", ["monitoring"], display_name="Splunk"),
|
|
|
|
WebhookIntegration("statuspage", ["customer-support"], display_name="Statuspage"),
|
|
|
|
WebhookIntegration("stripe", ["financial"], display_name="Stripe"),
|
|
|
|
WebhookIntegration("taiga", ["project-management"]),
|
|
|
|
WebhookIntegration("teamcity", ["continuous-integration"]),
|
|
|
|
WebhookIntegration("thinkst", ["monitoring"]),
|
|
|
|
WebhookIntegration("transifex", ["misc"]),
|
|
|
|
WebhookIntegration("travis", ["continuous-integration"], display_name="Travis CI"),
|
|
|
|
WebhookIntegration("trello", ["project-management"]),
|
|
|
|
WebhookIntegration("updown", ["monitoring"]),
|
2021-12-17 05:14:58 +01:00
|
|
|
WebhookIntegration("uptimerobot", ["monitoring"], display_name="UptimeRobot"),
|
2019-11-14 13:21:38 +01:00
|
|
|
WebhookIntegration("wekan", ["productivity"], display_name="Wekan"),
|
2021-02-12 08:20:45 +01:00
|
|
|
WebhookIntegration("wordpress", ["marketing"], display_name="WordPress"),
|
|
|
|
WebhookIntegration("zapier", ["meta-integration"]),
|
|
|
|
WebhookIntegration("zendesk", ["customer-support"]),
|
|
|
|
WebhookIntegration("zabbix", ["monitoring"], display_name="Zabbix"),
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
]
|
2016-07-25 22:12:12 +02:00
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
INTEGRATIONS: dict[str, Integration] = {
|
2021-02-12 08:20:45 +01:00
|
|
|
"asana": Integration(
|
|
|
|
"asana", "asana", ["project-management"], doc="zerver/integrations/asana.md"
|
|
|
|
),
|
2021-04-14 12:30:54 +02:00
|
|
|
"big-blue-button": Integration(
|
|
|
|
"big-blue-button",
|
|
|
|
"big-blue-button",
|
|
|
|
["communication"],
|
|
|
|
logo="images/integrations/logos/bigbluebutton.svg",
|
2021-07-06 00:23:51 +02:00
|
|
|
display_name="BigBlueButton",
|
2021-04-14 12:30:54 +02:00
|
|
|
doc="zerver/integrations/big-blue-button.md",
|
|
|
|
),
|
2021-02-12 08:20:45 +01:00
|
|
|
"capistrano": Integration(
|
|
|
|
"capistrano",
|
|
|
|
"capistrano",
|
|
|
|
["deployment"],
|
|
|
|
display_name="Capistrano",
|
|
|
|
doc="zerver/integrations/capistrano.md",
|
|
|
|
),
|
|
|
|
"codebase": Integration(
|
|
|
|
"codebase", "codebase", ["version-control"], doc="zerver/integrations/codebase.md"
|
|
|
|
),
|
|
|
|
"discourse": Integration(
|
|
|
|
"discourse", "discourse", ["communication"], doc="zerver/integrations/discourse.md"
|
|
|
|
),
|
|
|
|
"email": Integration("email", "email", ["communication"], doc="zerver/integrations/email.md"),
|
|
|
|
"errbot": Integration(
|
|
|
|
"errbot", "errbot", ["meta-integration", "bots"], doc="zerver/integrations/errbot.md"
|
|
|
|
),
|
2021-03-19 13:21:18 +01:00
|
|
|
"giphy": Integration(
|
|
|
|
"giphy",
|
|
|
|
"giphy",
|
|
|
|
display_name="GIPHY",
|
|
|
|
categories=["misc"],
|
|
|
|
doc="zerver/integrations/giphy.md",
|
2022-07-16 20:26:26 +02:00
|
|
|
logo="images/integrations/giphy/GIPHY_big_logo.png",
|
2021-03-19 13:21:18 +01:00
|
|
|
),
|
2021-02-12 08:20:45 +01:00
|
|
|
"git": Integration(
|
|
|
|
"git", "git", ["version-control"], stream_name="commits", doc="zerver/integrations/git.md"
|
|
|
|
),
|
2021-04-15 20:52:23 +02:00
|
|
|
"github-actions": Integration(
|
|
|
|
"github-actions",
|
|
|
|
"github-actions",
|
|
|
|
["continuous-integration"],
|
|
|
|
display_name="GitHub Actions",
|
|
|
|
doc="zerver/integrations/github-actions.md",
|
|
|
|
),
|
2021-02-12 08:20:45 +01:00
|
|
|
"google-calendar": Integration(
|
|
|
|
"google-calendar",
|
|
|
|
"google-calendar",
|
|
|
|
["productivity"],
|
|
|
|
display_name="Google Calendar",
|
|
|
|
doc="zerver/integrations/google-calendar.md",
|
|
|
|
),
|
|
|
|
"hubot": Integration(
|
|
|
|
"hubot", "hubot", ["meta-integration", "bots"], doc="zerver/integrations/hubot.md"
|
|
|
|
),
|
|
|
|
"irc": Integration(
|
|
|
|
"irc", "irc", ["communication"], display_name="IRC", doc="zerver/integrations/irc.md"
|
|
|
|
),
|
|
|
|
"jenkins": Integration(
|
|
|
|
"jenkins",
|
|
|
|
"jenkins",
|
|
|
|
["continuous-integration"],
|
|
|
|
secondary_line_text="(or Hudson)",
|
|
|
|
doc="zerver/integrations/jenkins.md",
|
|
|
|
),
|
|
|
|
"jira-plugin": Integration(
|
|
|
|
"jira-plugin",
|
|
|
|
"jira-plugin",
|
|
|
|
["project-management"],
|
|
|
|
logo="images/integrations/logos/jira.svg",
|
|
|
|
secondary_line_text="(locally installed)",
|
2021-05-10 07:02:14 +02:00
|
|
|
display_name="Jira",
|
2021-02-12 08:20:45 +01:00
|
|
|
doc="zerver/integrations/jira-plugin.md",
|
|
|
|
stream_name="jira",
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
legacy=True,
|
2016-07-25 22:12:12 +02:00
|
|
|
),
|
2021-04-14 12:07:16 +02:00
|
|
|
"jitsi": Integration(
|
|
|
|
"jitsi",
|
|
|
|
"jitsi",
|
|
|
|
["communication"],
|
|
|
|
logo="images/integrations/logos/jitsi.svg",
|
|
|
|
display_name="Jitsi Meet",
|
|
|
|
doc="zerver/integrations/jitsi.md",
|
|
|
|
),
|
2023-01-13 00:41:05 +01:00
|
|
|
"mastodon": Integration(
|
|
|
|
"mastodon",
|
|
|
|
"mastodon",
|
|
|
|
["communication"],
|
|
|
|
display_name="Mastodon",
|
|
|
|
doc="zerver/integrations/mastodon.md",
|
|
|
|
),
|
2021-02-12 08:20:45 +01:00
|
|
|
"matrix": Integration(
|
|
|
|
"matrix", "matrix", ["communication"], doc="zerver/integrations/matrix.md"
|
|
|
|
),
|
|
|
|
"mercurial": Integration(
|
|
|
|
"mercurial",
|
|
|
|
"mercurial",
|
|
|
|
["version-control"],
|
|
|
|
display_name="Mercurial (hg)",
|
|
|
|
doc="zerver/integrations/mercurial.md",
|
|
|
|
stream_name="commits",
|
|
|
|
),
|
|
|
|
"nagios": Integration("nagios", "nagios", ["monitoring"], doc="zerver/integrations/nagios.md"),
|
2023-05-02 09:44:46 +02:00
|
|
|
"notion": Integration(
|
|
|
|
"notion", "notion", ["productivity"], doc="zerver/integrations/notion.md"
|
|
|
|
),
|
2021-02-12 08:20:45 +01:00
|
|
|
"openshift": Integration(
|
|
|
|
"openshift",
|
|
|
|
"openshift",
|
|
|
|
["deployment"],
|
|
|
|
display_name="OpenShift",
|
|
|
|
doc="zerver/integrations/openshift.md",
|
|
|
|
stream_name="deployments",
|
|
|
|
),
|
|
|
|
"perforce": Integration(
|
|
|
|
"perforce", "perforce", ["version-control"], doc="zerver/integrations/perforce.md"
|
|
|
|
),
|
|
|
|
"phabricator": Integration(
|
|
|
|
"phabricator", "phabricator", ["version-control"], doc="zerver/integrations/phabricator.md"
|
|
|
|
),
|
|
|
|
"puppet": Integration("puppet", "puppet", ["deployment"], doc="zerver/integrations/puppet.md"),
|
|
|
|
"redmine": Integration(
|
|
|
|
"redmine", "redmine", ["project-management"], doc="zerver/integrations/redmine.md"
|
|
|
|
),
|
|
|
|
"rss": Integration(
|
|
|
|
"rss", "rss", ["communication"], display_name="RSS", doc="zerver/integrations/rss.md"
|
|
|
|
),
|
|
|
|
"svn": Integration("svn", "svn", ["version-control"], doc="zerver/integrations/svn.md"),
|
|
|
|
"trac": Integration("trac", "trac", ["project-management"], doc="zerver/integrations/trac.md"),
|
|
|
|
"twitter": Integration(
|
|
|
|
"twitter",
|
|
|
|
"twitter",
|
|
|
|
["customer-support", "marketing"],
|
2021-02-12 08:19:30 +01:00
|
|
|
# _ needed to get around adblock plus
|
2021-02-12 08:20:45 +01:00
|
|
|
logo="images/integrations/logos/twitte_r.svg",
|
|
|
|
doc="zerver/integrations/twitter.md",
|
2021-02-12 08:19:30 +01:00
|
|
|
),
|
2021-04-14 12:23:36 +02:00
|
|
|
"zoom": Integration(
|
|
|
|
"zoom",
|
|
|
|
"zoom",
|
|
|
|
["communication"],
|
|
|
|
logo="images/integrations/logos/zoom.svg",
|
|
|
|
display_name="Zoom",
|
|
|
|
doc="zerver/integrations/zoom.md",
|
|
|
|
),
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
}
|
2016-07-25 22:12:12 +02:00
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
BOT_INTEGRATIONS: list[BotIntegration] = [
|
2021-02-12 08:20:45 +01:00
|
|
|
BotIntegration("github_detail", ["version-control", "bots"], display_name="GitHub Detail"),
|
2021-02-12 08:19:30 +01:00
|
|
|
BotIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"xkcd", ["bots", "misc"], display_name="xkcd", logo="images/integrations/logos/xkcd.png"
|
2021-02-12 08:19:30 +01:00
|
|
|
),
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
]
|
2017-09-17 02:28:59 +02:00
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
HUBOT_INTEGRATIONS: list[HubotIntegration] = [
|
2021-02-12 08:19:30 +01:00
|
|
|
HubotIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"assembla",
|
|
|
|
["version-control", "project-management"],
|
|
|
|
display_name="Assembla",
|
|
|
|
logo_alt="Assembla",
|
|
|
|
),
|
|
|
|
HubotIntegration("bonusly", ["hr"]),
|
|
|
|
HubotIntegration("chartbeat", ["marketing"], display_name="Chartbeat"),
|
|
|
|
HubotIntegration("darksky", ["misc"], display_name="Dark Sky", logo_alt="Dark Sky logo"),
|
2021-02-12 08:19:30 +01:00
|
|
|
HubotIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"instagram",
|
|
|
|
["misc"],
|
|
|
|
display_name="Instagram",
|
2021-02-12 08:19:30 +01:00
|
|
|
# _ needed to get around adblock plus
|
2021-02-12 08:20:45 +01:00
|
|
|
logo="images/integrations/logos/instagra_m.svg",
|
2021-02-12 08:19:30 +01:00
|
|
|
),
|
2021-12-17 05:08:35 +01:00
|
|
|
HubotIntegration("mailchimp", ["communication", "marketing"], display_name="Mailchimp"),
|
2021-02-12 08:19:30 +01:00
|
|
|
HubotIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"google-translate",
|
|
|
|
["misc"],
|
2021-02-12 08:19:30 +01:00
|
|
|
display_name="Google Translate",
|
2021-02-12 08:20:45 +01:00
|
|
|
logo_alt="Google Translate logo",
|
2021-02-12 08:19:30 +01:00
|
|
|
),
|
|
|
|
HubotIntegration(
|
2021-02-12 08:20:45 +01:00
|
|
|
"youtube",
|
|
|
|
["misc"],
|
|
|
|
display_name="YouTube",
|
2021-02-12 08:19:30 +01:00
|
|
|
# _ needed to get around adblock plus
|
2021-02-12 08:20:45 +01:00
|
|
|
logo="images/integrations/logos/youtub_e.svg",
|
2021-02-12 08:19:30 +01:00
|
|
|
),
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
]
|
2017-10-07 12:30:49 +02:00
|
|
|
|
|
|
|
for hubot_integration in HUBOT_INTEGRATIONS:
|
|
|
|
INTEGRATIONS[hubot_integration.name] = hubot_integration
|
|
|
|
|
|
|
|
for webhook_integration in WEBHOOK_INTEGRATIONS:
|
|
|
|
INTEGRATIONS[webhook_integration.name] = webhook_integration
|
2017-09-17 02:28:59 +02:00
|
|
|
|
|
|
|
for bot_integration in BOT_INTEGRATIONS:
|
|
|
|
INTEGRATIONS[bot_integration.name] = bot_integration
|
2020-04-26 10:35:13 +02:00
|
|
|
|
|
|
|
# Add integrations that don't have automated screenshots here
|
|
|
|
NO_SCREENSHOT_WEBHOOKS = {
|
2021-02-12 08:20:45 +01:00
|
|
|
"beeminder", # FIXME: fixture's goal.losedate needs to be modified dynamically
|
|
|
|
"ifttt", # Docs don't have a screenshot
|
|
|
|
"slack_incoming", # Docs don't have a screenshot
|
|
|
|
"zapier", # Docs don't have a screenshot
|
2020-04-26 10:35:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-12 02:30:17 +02:00
|
|
|
DOC_SCREENSHOT_CONFIG: dict[str, list[BaseScreenshotConfig]] = {
|
2021-02-12 08:20:45 +01:00
|
|
|
"airbrake": [ScreenshotConfig("error_message.json")],
|
2024-10-09 00:02:24 +02:00
|
|
|
"airbyte": [ScreenshotConfig("airbyte_job_payload_success.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"alertmanager": [
|
|
|
|
ScreenshotConfig("alert.json", extra_params={"name": "topic", "desc": "description"})
|
2021-02-12 08:19:30 +01:00
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
"ansibletower": [ScreenshotConfig("job_successful_multiple_hosts.json")],
|
|
|
|
"appfollow": [ScreenshotConfig("review.json")],
|
|
|
|
"appveyor": [ScreenshotConfig("appveyor_build_success.json")],
|
2022-07-17 13:28:15 +02:00
|
|
|
"azuredevops": [ScreenshotConfig("code_push.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"basecamp": [ScreenshotConfig("doc_active.json")],
|
|
|
|
"beanstalk": [
|
|
|
|
ScreenshotConfig("git_multiple.json", use_basic_auth=True, payload_as_query_param=True)
|
2021-02-12 08:19:30 +01:00
|
|
|
],
|
2020-04-26 10:35:13 +02:00
|
|
|
# 'beeminder': [ScreenshotConfig('derail_worried.json')],
|
2021-02-12 08:20:45 +01:00
|
|
|
"bitbucket": [
|
|
|
|
ScreenshotConfig("push.json", "002.png", use_basic_auth=True, payload_as_query_param=True)
|
2021-02-12 08:19:30 +01:00
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
"bitbucket2": [
|
|
|
|
ScreenshotConfig("issue_created.json", "003.png", "bitbucket", bot_name="Bitbucket Bot")
|
2021-02-12 08:19:30 +01:00
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
"bitbucket3": [
|
2021-02-12 08:19:30 +01:00
|
|
|
ScreenshotConfig(
|
2021-02-12 08:20:45 +01:00
|
|
|
"repo_push_update_single_branch.json",
|
|
|
|
"004.png",
|
|
|
|
"bitbucket",
|
|
|
|
bot_name="Bitbucket Server Bot",
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
"buildbot": [ScreenshotConfig("started.json")],
|
|
|
|
"canarytoken": [ScreenshotConfig("canarytoken_real.json")],
|
|
|
|
"circleci": [
|
2023-07-15 01:59:41 +02:00
|
|
|
ScreenshotConfig("bitbucket_job_completed.json", image_name="001.png"),
|
|
|
|
ScreenshotConfig("github_job_completed.json", image_name="002.png"),
|
2021-02-12 08:19:30 +01:00
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
"clubhouse": [ScreenshotConfig("story_create.json")],
|
|
|
|
"codeship": [ScreenshotConfig("error_build.json")],
|
|
|
|
"crashlytics": [ScreenshotConfig("issue_message.json")],
|
|
|
|
"delighted": [ScreenshotConfig("survey_response_updated_promoter.json")],
|
|
|
|
"deskdotcom": [ScreenshotConfig("static_text.txt", "009.png", "desk", use_basic_auth=True)],
|
|
|
|
"dialogflow": [ScreenshotConfig("weather_app.json", extra_params={"email": "iago@zulip.com"})],
|
|
|
|
"dropbox": [ScreenshotConfig("file_updated.json")],
|
|
|
|
"errbit": [ScreenshotConfig("error_message.json")],
|
|
|
|
"flock": [ScreenshotConfig("messages.json")],
|
|
|
|
"freshdesk": [
|
|
|
|
ScreenshotConfig("ticket_created.json", image_name="004.png", use_basic_auth=True)
|
2021-02-12 08:19:30 +01:00
|
|
|
],
|
2021-04-15 23:39:16 +02:00
|
|
|
"freshping": [ScreenshotConfig("freshping_check_unreachable.json")],
|
2021-04-13 02:22:41 +02:00
|
|
|
"freshstatus": [ScreenshotConfig("freshstatus_incident_open.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"front": [ScreenshotConfig("inbound_message.json")],
|
|
|
|
"gitea": [ScreenshotConfig("pull_request__merged.json")],
|
|
|
|
"github": [ScreenshotConfig("push__1_commit.json")],
|
2023-12-20 00:43:09 +01:00
|
|
|
"githubsponsors": [ScreenshotConfig("created.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"gitlab": [ScreenshotConfig("push_hook__push_local_branch_without_commits.json")],
|
2024-01-30 02:11:11 +01:00
|
|
|
"gocd": [ScreenshotConfig("pipeline_with_mixed_job_result.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"gogs": [ScreenshotConfig("pull_request__opened.json")],
|
|
|
|
"gosquared": [ScreenshotConfig("traffic_spike.json", image_name="000.png")],
|
2024-02-29 19:10:12 +01:00
|
|
|
"grafana": [ScreenshotConfig("alert_values_v11.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"greenhouse": [ScreenshotConfig("candidate_stage_change.json", image_name="000.png")],
|
|
|
|
"groove": [ScreenshotConfig("ticket_started.json")],
|
|
|
|
"harbor": [ScreenshotConfig("scanning_completed.json")],
|
|
|
|
"hellosign": [
|
2021-02-12 08:19:30 +01:00
|
|
|
ScreenshotConfig(
|
2021-02-12 08:20:45 +01:00
|
|
|
"signatures_signed_by_one_signatory.json",
|
2021-02-12 08:19:30 +01:00
|
|
|
payload_as_query_param=True,
|
2021-02-12 08:20:45 +01:00
|
|
|
payload_param_name="json",
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
"helloworld": [ScreenshotConfig("hello.json")],
|
|
|
|
"heroku": [ScreenshotConfig("deploy.txt")],
|
|
|
|
"homeassistant": [ScreenshotConfig("reqwithtitle.json", image_name="003.png")],
|
|
|
|
"insping": [ScreenshotConfig("website_state_available.json")],
|
|
|
|
"intercom": [ScreenshotConfig("conversation_admin_replied.json")],
|
|
|
|
"jira": [ScreenshotConfig("created_v1.json")],
|
2020-10-21 20:56:33 +02:00
|
|
|
"jotform": [ScreenshotConfig("response.json")],
|
2021-04-09 03:50:04 +02:00
|
|
|
"json": [ScreenshotConfig("json_github_push__1_commit.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"librato": [ScreenshotConfig("three_conditions_alert.json", payload_as_query_param=True)],
|
2023-07-15 01:59:41 +02:00
|
|
|
"lidarr": [ScreenshotConfig("lidarr_album_grabbed.json")],
|
2023-04-12 20:34:01 +02:00
|
|
|
"linear": [ScreenshotConfig("issue_create_complex.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"mention": [ScreenshotConfig("webfeeds.json")],
|
2021-03-29 23:04:31 +02:00
|
|
|
"nagios": [BaseScreenshotConfig("service_notify.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"netlify": [ScreenshotConfig("deploy_building.json")],
|
2021-03-29 21:08:05 +02:00
|
|
|
"newrelic": [
|
2023-07-15 01:59:41 +02:00
|
|
|
ScreenshotConfig("incident_active_new.json", "001.png"),
|
|
|
|
ScreenshotConfig("incident_acknowledged_new.json", "002.png"),
|
|
|
|
ScreenshotConfig("incident_closed_new.json", "003.png"),
|
2021-03-29 21:08:05 +02:00
|
|
|
],
|
2021-06-25 00:55:44 +02:00
|
|
|
"opencollective": [ScreenshotConfig("one_time_donation.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"opsgenie": [ScreenshotConfig("addrecipient.json", image_name="000.png")],
|
|
|
|
"pagerduty": [ScreenshotConfig("trigger_v2.json")],
|
|
|
|
"papertrail": [ScreenshotConfig("short_post.json", payload_as_query_param=True)],
|
2024-01-17 22:56:18 +01:00
|
|
|
"patreon": [ScreenshotConfig("members_pledge_create.json")],
|
2024-08-02 15:26:51 +02:00
|
|
|
"pingdom": [ScreenshotConfig("http_up_to_down.json", image_name="001.png")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"pivotal": [ScreenshotConfig("v5_type_changed.json")],
|
2021-03-27 18:40:42 +01:00
|
|
|
"radarr": [ScreenshotConfig("radarr_movie_grabbed.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"raygun": [ScreenshotConfig("new_error.json")],
|
|
|
|
"reviewboard": [ScreenshotConfig("review_request_published.json")],
|
2022-07-09 12:23:36 +02:00
|
|
|
"rhodecode": [ScreenshotConfig("push.json")],
|
2023-04-07 19:13:21 +02:00
|
|
|
"rundeck": [ScreenshotConfig("start.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"semaphore": [ScreenshotConfig("pull_request.json")],
|
|
|
|
"sentry": [
|
|
|
|
ScreenshotConfig("event_for_exception_python.json"),
|
|
|
|
ScreenshotConfig("issue_assigned_to_team.json", "002.png"),
|
2021-02-12 08:19:30 +01:00
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
"slack": [ScreenshotConfig("message_info.txt")],
|
2021-03-10 03:47:04 +01:00
|
|
|
"sonarqube": [ScreenshotConfig("error.json")],
|
2021-03-27 03:56:36 +01:00
|
|
|
"sonarr": [ScreenshotConfig("sonarr_episode_grabbed.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"splunk": [ScreenshotConfig("search_one_result.json")],
|
|
|
|
"statuspage": [ScreenshotConfig("incident_created.json")],
|
|
|
|
"stripe": [ScreenshotConfig("charge_succeeded__card.json")],
|
|
|
|
"taiga": [ScreenshotConfig("userstory_changed_status.json")],
|
|
|
|
"teamcity": [ScreenshotConfig("success.json"), ScreenshotConfig("personal.json", "002.png")],
|
|
|
|
"thinkst": [ScreenshotConfig("canary_consolidated_port_scan.json")],
|
|
|
|
"transifex": [
|
2021-02-12 08:19:30 +01:00
|
|
|
ScreenshotConfig(
|
2021-02-12 08:20:45 +01:00
|
|
|
"",
|
2021-02-12 08:19:30 +01:00
|
|
|
extra_params={
|
2021-02-12 08:20:45 +01:00
|
|
|
"project": "Zulip Mobile",
|
|
|
|
"language": "en",
|
|
|
|
"resource": "file",
|
|
|
|
"reviewed": "100",
|
2021-02-12 08:19:30 +01:00
|
|
|
},
|
|
|
|
)
|
|
|
|
],
|
2021-02-12 08:20:45 +01:00
|
|
|
"travis": [ScreenshotConfig("build.json", payload_as_query_param=True)],
|
|
|
|
"trello": [ScreenshotConfig("adding_comment_to_card.json")],
|
|
|
|
"updown": [ScreenshotConfig("check_multiple_events.json")],
|
2020-02-17 23:46:15 +01:00
|
|
|
"uptimerobot": [ScreenshotConfig("uptimerobot_monitor_up.json")],
|
2019-11-14 13:21:38 +01:00
|
|
|
"wekan": [ScreenshotConfig("add_comment.json")],
|
2021-02-12 08:20:45 +01:00
|
|
|
"wordpress": [ScreenshotConfig("publish_post.txt", "wordpress_post_created.png")],
|
|
|
|
"zabbix": [ScreenshotConfig("zabbix_alert.json")],
|
|
|
|
"zendesk": [
|
2021-02-12 08:19:30 +01:00
|
|
|
ScreenshotConfig(
|
2021-02-12 08:20:45 +01:00
|
|
|
"",
|
|
|
|
"007.png",
|
2021-02-12 08:19:30 +01:00
|
|
|
use_basic_auth=True,
|
|
|
|
extra_params={
|
2021-02-12 08:20:45 +01:00
|
|
|
"ticket_title": "Test ticket",
|
|
|
|
"ticket_id": "4",
|
2021-05-10 07:02:14 +02:00
|
|
|
"message": "Test message",
|
2021-02-12 08:19:30 +01:00
|
|
|
},
|
|
|
|
)
|
|
|
|
],
|
2020-04-26 10:35:13 +02:00
|
|
|
}
|
2023-08-07 12:25:33 +02:00
|
|
|
|
|
|
|
|
2024-07-12 02:30:23 +02:00
|
|
|
def get_all_event_types_for_integration(integration: Integration) -> list[str] | None:
|
2023-08-07 12:25:33 +02:00
|
|
|
integration = INTEGRATIONS[integration.name]
|
2023-12-20 00:43:09 +01:00
|
|
|
if isinstance(integration, WebhookIntegration):
|
|
|
|
if integration.name == "githubsponsors":
|
|
|
|
return import_string("zerver.webhooks.github.view.SPONSORS_EVENT_TYPES")
|
2024-09-25 00:25:45 +02:00
|
|
|
function = integration.get_function()
|
|
|
|
if hasattr(function, "_all_event_types"):
|
|
|
|
return function._all_event_types
|
2023-08-07 12:25:33 +02:00
|
|
|
return None
|