mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 21:43:21 +00:00
clubhouse: Strengthen types using WildValue.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
committed by
Tim Abbott
parent
573d264759
commit
d5a8e040da
@@ -1,5 +1,5 @@
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import Any, Callable, Dict, Generator, List, Optional
|
from typing import Callable, Dict, Iterable, Iterator, List, Optional
|
||||||
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
|
||||||
@@ -7,6 +7,16 @@ from zerver.decorator import webhook_view
|
|||||||
from zerver.lib.exceptions import UnsupportedWebhookEventType
|
from zerver.lib.exceptions import UnsupportedWebhookEventType
|
||||||
from zerver.lib.request import REQ, has_request_variables
|
from zerver.lib.request import REQ, has_request_variables
|
||||||
from zerver.lib.response import json_success
|
from zerver.lib.response import json_success
|
||||||
|
from zerver.lib.validator import (
|
||||||
|
WildValue,
|
||||||
|
check_bool,
|
||||||
|
check_int,
|
||||||
|
check_list,
|
||||||
|
check_none_or,
|
||||||
|
check_string,
|
||||||
|
check_string_or_int,
|
||||||
|
to_wild_value,
|
||||||
|
)
|
||||||
from zerver.lib.webhooks.common import check_send_webhook_message
|
from zerver.lib.webhooks.common import check_send_webhook_message
|
||||||
from zerver.models import UserProfile
|
from zerver.models import UserProfile
|
||||||
|
|
||||||
@@ -66,7 +76,7 @@ STORY_UPDATE_BATCH_CHANGED_SUB_TEMPLATE = "{entity_type} **{old}** to **{new}**"
|
|||||||
STORY_UPDATE_BATCH_ADD_REMOVE_TEMPLATE = "{operation} with {entity}"
|
STORY_UPDATE_BATCH_ADD_REMOVE_TEMPLATE = "{operation} with {entity}"
|
||||||
|
|
||||||
|
|
||||||
def get_action_with_primary_id(payload: Dict[str, Any]) -> Dict[str, Any]:
|
def get_action_with_primary_id(payload: WildValue) -> WildValue:
|
||||||
for action in payload["actions"]:
|
for action in payload["actions"]:
|
||||||
if payload["primary_id"] == action["id"]:
|
if payload["primary_id"] == action["id"]:
|
||||||
action_with_primary_id = action
|
action_with_primary_id = action
|
||||||
@@ -74,109 +84,121 @@ def get_action_with_primary_id(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|||||||
return action_with_primary_id
|
return action_with_primary_id
|
||||||
|
|
||||||
|
|
||||||
def get_event(payload: Dict[str, Any], action: Dict[str, Any]) -> Optional[str]:
|
def get_event(payload: WildValue, action: WildValue) -> Optional[str]:
|
||||||
event = "{}_{}".format(action["entity_type"], action["action"])
|
event = "{}_{}".format(
|
||||||
|
action["entity_type"].tame(check_string), action["action"].tame(check_string)
|
||||||
|
)
|
||||||
|
|
||||||
# We only consider the change to be a batch update only if there are multiple stories (thus there is no primary_id)
|
# We only consider the change to be a batch update only if there are multiple stories (thus there is no primary_id)
|
||||||
if event == "story_update" and payload.get("primary_id") is None:
|
if event == "story_update" and "primary_id" not in payload:
|
||||||
return "{}_{}".format(event, "batch")
|
return "{}_{}".format(event, "batch")
|
||||||
|
|
||||||
if event in IGNORED_EVENTS:
|
if event in IGNORED_EVENTS:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
changes = action.get("changes")
|
if "changes" in action:
|
||||||
if changes is not None:
|
changes = action["changes"]
|
||||||
if changes.get("description") is not None:
|
if "description" in changes:
|
||||||
event = "{}_{}".format(event, "description")
|
event = "{}_{}".format(event, "description")
|
||||||
elif changes.get("state") is not None:
|
elif "state" in changes:
|
||||||
event = "{}_{}".format(event, "state")
|
event = "{}_{}".format(event, "state")
|
||||||
elif changes.get("workflow_state_id") is not None:
|
elif "workflow_state_id" in changes:
|
||||||
event = "{}_{}".format(event, "state")
|
event = "{}_{}".format(event, "state")
|
||||||
elif changes.get("name") is not None:
|
elif "name" in changes:
|
||||||
event = "{}_{}".format(event, "name")
|
event = "{}_{}".format(event, "name")
|
||||||
elif changes.get("archived") is not None:
|
elif "archived" in changes:
|
||||||
event = "{}_{}".format(event, "archived")
|
event = "{}_{}".format(event, "archived")
|
||||||
elif changes.get("complete") is not None:
|
elif "complete" in changes:
|
||||||
event = "{}_{}".format(event, "complete")
|
event = "{}_{}".format(event, "complete")
|
||||||
elif changes.get("epic_id") is not None:
|
elif "epic_id" in changes:
|
||||||
event = "{}_{}".format(event, "epic")
|
event = "{}_{}".format(event, "epic")
|
||||||
elif changes.get("estimate") is not None:
|
elif "estimate" in changes:
|
||||||
event = "{}_{}".format(event, "estimate")
|
event = "{}_{}".format(event, "estimate")
|
||||||
elif changes.get("file_ids") is not None:
|
elif "file_ids" in changes:
|
||||||
event = "{}_{}".format(event, "attachment")
|
event = "{}_{}".format(event, "attachment")
|
||||||
elif changes.get("label_ids") is not None:
|
elif "label_ids" in changes:
|
||||||
event = "{}_{}".format(event, "label")
|
event = "{}_{}".format(event, "label")
|
||||||
elif changes.get("project_id") is not None:
|
elif "project_id" in changes:
|
||||||
event = "{}_{}".format(event, "project")
|
event = "{}_{}".format(event, "project")
|
||||||
elif changes.get("story_type") is not None:
|
elif "story_type" in changes:
|
||||||
event = "{}_{}".format(event, "type")
|
event = "{}_{}".format(event, "type")
|
||||||
elif changes.get("owner_ids") is not None:
|
elif "owner_ids" in changes:
|
||||||
event = "{}_{}".format(event, "owner")
|
event = "{}_{}".format(event, "owner")
|
||||||
|
|
||||||
return event
|
return event
|
||||||
|
|
||||||
|
|
||||||
def get_topic_function_based_on_type(payload: Dict[str, Any], action: Dict[str, Any]) -> Any:
|
def get_topic_function_based_on_type(
|
||||||
entity_type = action["entity_type"]
|
payload: WildValue, action: WildValue
|
||||||
|
) -> Optional[Callable[[WildValue, WildValue], Optional[str]]]:
|
||||||
|
entity_type = action["entity_type"].tame(check_string)
|
||||||
return EVENT_TOPIC_FUNCTION_MAPPER.get(entity_type)
|
return EVENT_TOPIC_FUNCTION_MAPPER.get(entity_type)
|
||||||
|
|
||||||
|
|
||||||
def get_delete_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_delete_body(payload: WildValue, action: WildValue) -> str:
|
||||||
return DELETE_TEMPLATE.format(**action)
|
return DELETE_TEMPLATE.format(
|
||||||
|
entity_type=action["entity_type"].tame(check_string),
|
||||||
|
name=action["name"].tame(check_string),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_story_create_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_story_create_body(payload: WildValue, action: WildValue) -> str:
|
||||||
if action.get("epic_id") is None:
|
if "epic_id" not in action:
|
||||||
message = "New story [{name}]({app_url}) of type **{story_type}** was created."
|
message = "New story [{name}]({app_url}) of type **{story_type}** was created."
|
||||||
kwargs = action
|
kwargs = {
|
||||||
|
"name": action["name"].tame(check_string),
|
||||||
|
"app_url": action["app_url"].tame(check_string),
|
||||||
|
"story_type": action["story_type"].tame(check_string),
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
message = "New story [{name}]({app_url}) was created and added to the epic **{epic_name}**."
|
message = "New story [{name}]({app_url}) was created and added to the epic **{epic_name}**."
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"name": action["name"],
|
"name": action["name"].tame(check_string),
|
||||||
"app_url": action["app_url"],
|
"app_url": action["app_url"].tame(check_string),
|
||||||
}
|
}
|
||||||
epic_id = action["epic_id"]
|
epic_id = action["epic_id"].tame(check_int)
|
||||||
refs = payload["references"]
|
refs = payload["references"]
|
||||||
for ref in refs:
|
for ref in refs:
|
||||||
if ref["id"] == epic_id:
|
if ref["id"].tame(check_string_or_int) == epic_id:
|
||||||
kwargs["epic_name"] = ref["name"]
|
kwargs["epic_name"] = ref["name"].tame(check_string)
|
||||||
|
|
||||||
return message.format(**kwargs)
|
return message.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_epic_create_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_epic_create_body(payload: WildValue, action: WildValue) -> str:
|
||||||
message = "New epic **{name}**({state}) was created."
|
message = "New epic **{name}**({state}) was created."
|
||||||
return message.format(**action)
|
return message.format(
|
||||||
|
name=action["name"].tame(check_string),
|
||||||
|
state=action["state"].tame(check_string),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_comment_added_body(payload: Dict[str, Any], action: Dict[str, Any], entity: str) -> str:
|
def get_comment_added_body(payload: WildValue, action: WildValue, entity: str) -> str:
|
||||||
actions = payload["actions"]
|
actions = payload["actions"]
|
||||||
kwargs = {"entity": entity}
|
kwargs = {"entity": entity}
|
||||||
for action in actions:
|
for action in actions:
|
||||||
if action["id"] == payload["primary_id"]:
|
if action["id"] == payload["primary_id"]:
|
||||||
kwargs["text"] = action["text"]
|
kwargs["text"] = action["text"].tame(check_string)
|
||||||
elif action["entity_type"] == entity:
|
elif action["entity_type"] == entity:
|
||||||
name_template = get_name_template(entity).format(
|
name_template = get_name_template(entity).format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action.get("app_url"),
|
app_url=action.get("app_url").tame(check_none_or(check_string)),
|
||||||
)
|
)
|
||||||
kwargs["name_template"] = name_template
|
kwargs["name_template"] = name_template
|
||||||
|
|
||||||
return COMMENT_ADDED_TEMPLATE.format(**kwargs)
|
return COMMENT_ADDED_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_update_description_body(
|
def get_update_description_body(payload: WildValue, action: WildValue, entity: str) -> str:
|
||||||
payload: Dict[str, Any], action: Dict[str, Any], entity: str
|
|
||||||
) -> str:
|
|
||||||
desc = action["changes"]["description"]
|
desc = action["changes"]["description"]
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"entity": entity,
|
"entity": entity,
|
||||||
"new": desc["new"],
|
"new": desc["new"].tame(check_string),
|
||||||
"old": desc["old"],
|
"old": desc["old"].tame(check_string),
|
||||||
"name_template": get_name_template(entity).format(
|
"name_template": get_name_template(entity).format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action.get("app_url"),
|
app_url=action.get("app_url").tame(check_none_or(check_string)),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,58 +212,60 @@ def get_update_description_body(
|
|||||||
return body
|
return body
|
||||||
|
|
||||||
|
|
||||||
def get_epic_update_state_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_epic_update_state_body(payload: WildValue, action: WildValue) -> str:
|
||||||
state = action["changes"]["state"]
|
state = action["changes"]["state"]
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"entity": "epic",
|
"entity": "epic",
|
||||||
"new": state["new"],
|
"new": state["new"].tame(check_string),
|
||||||
"old": state["old"],
|
"old": state["old"].tame(check_string),
|
||||||
"name_template": EPIC_NAME_TEMPLATE.format(name=action["name"]),
|
"name_template": EPIC_NAME_TEMPLATE.format(
|
||||||
|
name=action["name"].tame(check_string),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATE_CHANGED_TEMPLATE.format(**kwargs)
|
return STATE_CHANGED_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_update_state_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_story_update_state_body(payload: WildValue, action: WildValue) -> str:
|
||||||
workflow_state_id = action["changes"]["workflow_state_id"]
|
workflow_state_id = action["changes"]["workflow_state_id"]
|
||||||
references = payload["references"]
|
references = payload["references"]
|
||||||
|
|
||||||
state = {}
|
state = {}
|
||||||
for ref in references:
|
for ref in references:
|
||||||
if ref["id"] == workflow_state_id["new"]:
|
if ref["id"].tame(check_string_or_int) == workflow_state_id["new"].tame(check_int):
|
||||||
state["new"] = ref["name"]
|
state["new"] = ref["name"].tame(check_string)
|
||||||
if ref["id"] == workflow_state_id["old"]:
|
if ref["id"].tame(check_string_or_int) == workflow_state_id["old"].tame(check_int):
|
||||||
state["old"] = ref["name"]
|
state["old"] = ref["name"].tame(check_string)
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"entity": "story",
|
"entity": "story",
|
||||||
"new": state["new"],
|
"new": state["new"],
|
||||||
"old": state["old"],
|
"old": state["old"],
|
||||||
"name_template": STORY_NAME_TEMPLATE.format(
|
"name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action.get("app_url"),
|
app_url=action.get("app_url").tame(check_none_or(check_string)),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATE_CHANGED_TEMPLATE.format(**kwargs)
|
return STATE_CHANGED_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_update_name_body(payload: Dict[str, Any], action: Dict[str, Any], entity: str) -> str:
|
def get_update_name_body(payload: WildValue, action: WildValue, entity: str) -> str:
|
||||||
name = action["changes"]["name"]
|
name = action["changes"]["name"]
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"entity": entity,
|
"entity": entity,
|
||||||
"new": name["new"],
|
"new": name["new"].tame(check_string),
|
||||||
"old": name["old"],
|
"old": name["old"].tame(check_string),
|
||||||
"name_template": get_name_template(entity).format(
|
"name_template": get_name_template(entity).format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action.get("app_url"),
|
app_url=action.get("app_url").tame(check_none_or(check_string)),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
return NAME_CHANGED_TEMPLATE.format(**kwargs)
|
return NAME_CHANGED_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_update_archived_body(payload: Dict[str, Any], action: Dict[str, Any], entity: str) -> str:
|
def get_update_archived_body(payload: WildValue, action: WildValue, entity: str) -> str:
|
||||||
archived = action["changes"]["archived"]
|
archived = action["changes"]["archived"]
|
||||||
if archived["new"]:
|
if archived["new"]:
|
||||||
operation = "archived"
|
operation = "archived"
|
||||||
@@ -251,8 +275,8 @@ def get_update_archived_body(payload: Dict[str, Any], action: Dict[str, Any], en
|
|||||||
kwargs = {
|
kwargs = {
|
||||||
"entity": entity,
|
"entity": entity,
|
||||||
"name_template": get_name_template(entity).format(
|
"name_template": get_name_template(entity).format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action.get("app_url"),
|
app_url=action.get("app_url").tame(check_none_or(check_string)),
|
||||||
),
|
),
|
||||||
"operation": operation,
|
"operation": operation,
|
||||||
}
|
}
|
||||||
@@ -260,58 +284,63 @@ def get_update_archived_body(payload: Dict[str, Any], action: Dict[str, Any], en
|
|||||||
return ARCHIVED_TEMPLATE.format(**kwargs)
|
return ARCHIVED_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_task_body(payload: Dict[str, Any], action: Dict[str, Any], operation: str) -> str:
|
def get_story_task_body(payload: WildValue, action: WildValue, operation: str) -> str:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"task_description": action["description"],
|
"task_description": action["description"].tame(check_string),
|
||||||
"operation": operation,
|
"operation": operation,
|
||||||
}
|
}
|
||||||
|
|
||||||
for a in payload["actions"]:
|
for a in payload["actions"]:
|
||||||
if a["entity_type"] == "story":
|
if a["entity_type"].tame(check_string) == "story":
|
||||||
kwargs["name_template"] = STORY_NAME_TEMPLATE.format(
|
kwargs["name_template"] = STORY_NAME_TEMPLATE.format(
|
||||||
name=a["name"],
|
name=a["name"].tame(check_string),
|
||||||
app_url=a["app_url"],
|
app_url=a["app_url"].tame(check_string),
|
||||||
)
|
)
|
||||||
|
|
||||||
return STORY_TASK_TEMPLATE.format(**kwargs)
|
return STORY_TASK_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_task_completed_body(payload: Dict[str, Any], action: Dict[str, Any]) -> Optional[str]:
|
def get_story_task_completed_body(payload: WildValue, action: WildValue) -> Optional[str]:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"task_description": action["description"],
|
"task_description": action["description"].tame(check_string),
|
||||||
}
|
}
|
||||||
|
|
||||||
story_id = action["story_id"]
|
story_id = action["story_id"].tame(check_int)
|
||||||
for ref in payload["references"]:
|
for ref in payload["references"]:
|
||||||
if ref["id"] == story_id:
|
if ref["id"].tame(check_string_or_int) == story_id:
|
||||||
kwargs["name_template"] = STORY_NAME_TEMPLATE.format(
|
kwargs["name_template"] = STORY_NAME_TEMPLATE.format(
|
||||||
name=ref["name"],
|
name=ref["name"].tame(check_string),
|
||||||
app_url=ref["app_url"],
|
app_url=ref["app_url"].tame(check_string),
|
||||||
)
|
)
|
||||||
|
|
||||||
if action["changes"]["complete"]["new"]:
|
if action["changes"]["complete"]["new"].tame(check_bool):
|
||||||
return STORY_TASK_COMPLETED_TEMPLATE.format(**kwargs)
|
return STORY_TASK_COMPLETED_TEMPLATE.format(**kwargs)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_story_update_epic_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_story_update_epic_body(payload: WildValue, action: WildValue) -> str:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"story_name_template": STORY_NAME_TEMPLATE.format(
|
"story_name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action["app_url"],
|
app_url=action["app_url"].tame(check_string),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
new_id = action["changes"]["epic_id"].get("new")
|
epic_id = action["changes"]["epic_id"]
|
||||||
old_id = action["changes"]["epic_id"].get("old")
|
new_id = epic_id.get("new").tame(check_none_or(check_int))
|
||||||
|
old_id = epic_id.get("old").tame(check_none_or(check_int))
|
||||||
|
|
||||||
for ref in payload["references"]:
|
for ref in payload["references"]:
|
||||||
if ref["id"] == new_id:
|
if ref["id"].tame(check_string_or_int) == new_id:
|
||||||
kwargs["new_epic_name_template"] = EPIC_NAME_TEMPLATE.format(name=ref["name"])
|
kwargs["new_epic_name_template"] = EPIC_NAME_TEMPLATE.format(
|
||||||
|
name=ref["name"].tame(check_string),
|
||||||
|
)
|
||||||
|
|
||||||
if ref["id"] == old_id:
|
if ref["id"].tame(check_string_or_int) == old_id:
|
||||||
kwargs["old_epic_name_template"] = EPIC_NAME_TEMPLATE.format(name=ref["name"])
|
kwargs["old_epic_name_template"] = EPIC_NAME_TEMPLATE.format(
|
||||||
|
name=ref["name"].tame(check_string),
|
||||||
|
)
|
||||||
|
|
||||||
if new_id and old_id:
|
if new_id and old_id:
|
||||||
return STORY_EPIC_CHANGED_TEMPLATE.format(**kwargs)
|
return STORY_EPIC_CHANGED_TEMPLATE.format(**kwargs)
|
||||||
@@ -325,16 +354,17 @@ def get_story_update_epic_body(payload: Dict[str, Any], action: Dict[str, Any])
|
|||||||
return STORY_ADDED_REMOVED_EPIC_TEMPLATE.format(**kwargs)
|
return STORY_ADDED_REMOVED_EPIC_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_update_estimate_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_story_update_estimate_body(payload: WildValue, action: WildValue) -> str:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"story_name_template": STORY_NAME_TEMPLATE.format(
|
"story_name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action["app_url"],
|
app_url=action["app_url"].tame(check_string),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
new = action["changes"]["estimate"].get("new")
|
estimate = action["changes"]["estimate"]
|
||||||
if new:
|
if "new" in estimate:
|
||||||
|
new = estimate["new"].tame(check_int)
|
||||||
kwargs["estimate"] = f"{new} points"
|
kwargs["estimate"] = f"{new} points"
|
||||||
else:
|
else:
|
||||||
kwargs["estimate"] = "*Unestimated*"
|
kwargs["estimate"] = "*Unestimated*"
|
||||||
@@ -342,45 +372,51 @@ def get_story_update_estimate_body(payload: Dict[str, Any], action: Dict[str, An
|
|||||||
return STORY_ESTIMATE_TEMPLATE.format(**kwargs)
|
return STORY_ESTIMATE_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_reference_by_id(payload: Dict[str, Any], ref_id: int) -> Dict[str, Any]:
|
def get_reference_by_id(payload: WildValue, ref_id: Optional[int]) -> Optional[WildValue]:
|
||||||
ref: Dict[str, Any] = {}
|
ref = None
|
||||||
for reference in payload["references"]:
|
for reference in payload["references"]:
|
||||||
if reference["id"] == ref_id:
|
if reference["id"].tame(check_string_or_int) == ref_id:
|
||||||
ref = reference
|
ref = reference
|
||||||
|
|
||||||
return ref
|
return ref
|
||||||
|
|
||||||
|
|
||||||
def get_secondary_actions_with_param(
|
def get_secondary_actions_with_param(
|
||||||
payload: Dict[str, Any], entity: str, changed_attr: str
|
payload: WildValue, entity: str, changed_attr: str
|
||||||
) -> Generator[Dict[str, Any], None, None]:
|
) -> Iterator[WildValue]:
|
||||||
# This function is a generator for secondary actions that have the required changed attributes,
|
# This function is a generator for secondary actions that have the required changed attributes,
|
||||||
# i.e.: "story" that has "pull-request_ids" changed.
|
# i.e.: "story" that has "pull-request_ids" changed.
|
||||||
for action in payload["actions"]:
|
for action in payload["actions"]:
|
||||||
if action["entity_type"] == entity and action["changes"].get(changed_attr) is not None:
|
if action["entity_type"].tame(check_string) == entity and changed_attr in action["changes"]:
|
||||||
yield action
|
yield action
|
||||||
|
|
||||||
|
|
||||||
def get_story_create_github_entity_body(
|
def get_story_create_github_entity_body(payload: WildValue, action: WildValue, entity: str) -> str:
|
||||||
payload: Dict[str, Any], action: Dict[str, Any], entity: str
|
pull_request_action: WildValue = get_action_with_primary_id(payload)
|
||||||
) -> str:
|
|
||||||
pull_request_action: Dict[str, Any] = get_action_with_primary_id(payload)
|
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"name_template": STORY_NAME_TEMPLATE.format(**action),
|
"name_template": STORY_NAME_TEMPLATE.format(
|
||||||
"name": pull_request_action.get("number")
|
name=action["name"].tame(check_string),
|
||||||
|
app_url=action["app_url"].tame(check_string),
|
||||||
|
),
|
||||||
|
"name": pull_request_action["number"].tame(check_int)
|
||||||
if entity == "pull-request" or entity == "pull-request-comment"
|
if entity == "pull-request" or entity == "pull-request-comment"
|
||||||
else pull_request_action.get("name"),
|
else pull_request_action["name"].tame(check_string),
|
||||||
"url": pull_request_action["url"],
|
"url": pull_request_action["url"].tame(check_string),
|
||||||
"workflow_state_template": "",
|
"workflow_state_template": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sometimes the workflow state of the story will not be changed when linking to a PR.
|
# Sometimes the workflow state of the story will not be changed when linking to a PR.
|
||||||
if action["changes"].get("workflow_state_id") is not None:
|
if "workflow_state_id" in action["changes"]:
|
||||||
new_state_id = action["changes"]["workflow_state_id"]["new"]
|
workflow_state_id = action["changes"]["workflow_state_id"]
|
||||||
old_state_id = action["changes"]["workflow_state_id"]["old"]
|
new_state_id = workflow_state_id["new"].tame(check_int)
|
||||||
new_state = get_reference_by_id(payload, new_state_id)["name"]
|
old_state_id = workflow_state_id["old"].tame(check_int)
|
||||||
old_state = get_reference_by_id(payload, old_state_id)["name"]
|
new_reference = get_reference_by_id(payload, new_state_id)
|
||||||
|
assert new_reference is not None
|
||||||
|
new_state = new_reference["name"].tame(check_string)
|
||||||
|
old_reference = get_reference_by_id(payload, old_state_id)
|
||||||
|
assert old_reference is not None
|
||||||
|
old_state = old_reference["name"].tame(check_string)
|
||||||
kwargs["workflow_state_template"] = TRAILING_WORKFLOW_STATE_CHANGE_TEMPLATE.format(
|
kwargs["workflow_state_template"] = TRAILING_WORKFLOW_STATE_CHANGE_TEMPLATE.format(
|
||||||
new=new_state, old=old_state
|
new=new_state, old=old_state
|
||||||
)
|
)
|
||||||
@@ -394,34 +430,33 @@ def get_story_create_github_entity_body(
|
|||||||
return template.format(**kwargs)
|
return template.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_update_attachment_body(
|
def get_story_update_attachment_body(payload: WildValue, action: WildValue) -> Optional[str]:
|
||||||
payload: Dict[str, Any], action: Dict[str, Any]
|
|
||||||
) -> Optional[str]:
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"name_template": STORY_NAME_TEMPLATE.format(
|
"name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action["app_url"],
|
app_url=action["app_url"].tame(check_string),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
file_ids_added = action["changes"]["file_ids"].get("adds")
|
file_ids = action["changes"]["file_ids"]
|
||||||
|
|
||||||
# If this is a payload for when an attachment is removed, ignore it
|
# If this is a payload for when an attachment is removed, ignore it
|
||||||
if not file_ids_added:
|
if "adds" not in file_ids:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
file_ids_added = file_ids["adds"].tame(check_list(check_int))
|
||||||
file_id = file_ids_added[0]
|
file_id = file_ids_added[0]
|
||||||
for ref in payload["references"]:
|
for ref in payload["references"]:
|
||||||
if ref["id"] == file_id:
|
if ref["id"].tame(check_string_or_int) == file_id:
|
||||||
kwargs.update(
|
kwargs.update(
|
||||||
type=ref["entity_type"],
|
type=ref["entity_type"].tame(check_string),
|
||||||
file_name=ref["name"],
|
file_name=ref["name"].tame(check_string),
|
||||||
)
|
)
|
||||||
|
|
||||||
return FILE_ATTACHMENT_TEMPLATE.format(**kwargs)
|
return FILE_ATTACHMENT_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_joined_label_list(
|
def get_story_joined_label_list(
|
||||||
payload: Dict[str, Any], action: Dict[str, Any], label_ids_added: List[int]
|
payload: WildValue, action: WildValue, label_ids_added: List[int]
|
||||||
) -> str:
|
) -> str:
|
||||||
labels = []
|
labels = []
|
||||||
|
|
||||||
@@ -429,30 +464,32 @@ def get_story_joined_label_list(
|
|||||||
label_name = ""
|
label_name = ""
|
||||||
|
|
||||||
for action in payload["actions"]:
|
for action in payload["actions"]:
|
||||||
if action.get("id") == label_id:
|
if action["id"].tame(check_int) == label_id:
|
||||||
label_name = action.get("name", "")
|
label_name = action.get("name", "").tame(check_string)
|
||||||
|
|
||||||
if label_name == "":
|
if label_name == "":
|
||||||
label_name = get_reference_by_id(payload, label_id).get("name", "")
|
reference = get_reference_by_id(payload, label_id)
|
||||||
|
label_name = "" if reference is None else reference["name"].tame(check_string)
|
||||||
|
|
||||||
labels.append(LABEL_TEMPLATE.format(name=label_name))
|
labels.append(LABEL_TEMPLATE.format(name=label_name))
|
||||||
|
|
||||||
return ", ".join(labels)
|
return ", ".join(labels)
|
||||||
|
|
||||||
|
|
||||||
def get_story_label_body(payload: Dict[str, Any], action: Dict[str, Any]) -> Optional[str]:
|
def get_story_label_body(payload: WildValue, action: WildValue) -> Optional[str]:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"name_template": STORY_NAME_TEMPLATE.format(
|
"name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action["app_url"],
|
app_url=action["app_url"].tame(check_string),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
label_ids_added = action["changes"]["label_ids"].get("adds")
|
label_ids = action["changes"]["label_ids"]
|
||||||
|
|
||||||
# If this is a payload for when no label is added, ignore it
|
# If this is a payload for when no label is added, ignore it
|
||||||
if not label_ids_added:
|
if "adds" not in label_ids:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
label_ids_added = label_ids["adds"].tame(check_list(check_int))
|
||||||
kwargs.update(labels=get_story_joined_label_list(payload, action, label_ids_added))
|
kwargs.update(labels=get_story_joined_label_list(payload, action, label_ids_added))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -462,58 +499,60 @@ def get_story_label_body(payload: Dict[str, Any], action: Dict[str, Any]) -> Opt
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_story_update_project_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_story_update_project_body(payload: WildValue, action: WildValue) -> str:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"name_template": STORY_NAME_TEMPLATE.format(
|
"name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action["app_url"],
|
app_url=action["app_url"].tame(check_string),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
new_project_id = action["changes"]["project_id"]["new"]
|
project_id = action["changes"]["project_id"]
|
||||||
old_project_id = action["changes"]["project_id"]["old"]
|
new_project_id = project_id["new"].tame(check_int)
|
||||||
|
old_project_id = project_id["old"].tame(check_int)
|
||||||
for ref in payload["references"]:
|
for ref in payload["references"]:
|
||||||
if ref["id"] == new_project_id:
|
if ref["id"].tame(check_string_or_int) == new_project_id:
|
||||||
kwargs.update(new=ref["name"])
|
kwargs.update(new=ref["name"].tame(check_string))
|
||||||
if ref["id"] == old_project_id:
|
if ref["id"].tame(check_string_or_int) == old_project_id:
|
||||||
kwargs.update(old=ref["name"])
|
kwargs.update(old=ref["name"].tame(check_string))
|
||||||
|
|
||||||
return STORY_UPDATE_PROJECT_TEMPLATE.format(**kwargs)
|
return STORY_UPDATE_PROJECT_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_update_type_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_story_update_type_body(payload: WildValue, action: WildValue) -> str:
|
||||||
|
story_type = action["changes"]["story_type"]
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"name_template": STORY_NAME_TEMPLATE.format(
|
"name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action["app_url"],
|
app_url=action["app_url"].tame(check_string),
|
||||||
),
|
),
|
||||||
"new_type": action["changes"]["story_type"]["new"],
|
"new_type": story_type["new"].tame(check_string),
|
||||||
"old_type": action["changes"]["story_type"]["old"],
|
"old_type": story_type["old"].tame(check_string),
|
||||||
}
|
}
|
||||||
|
|
||||||
return STORY_UPDATE_TYPE_TEMPLATE.format(**kwargs)
|
return STORY_UPDATE_TYPE_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_update_owner_body(payload: Dict[str, Any], action: Dict[str, Any]) -> str:
|
def get_story_update_owner_body(payload: WildValue, action: WildValue) -> str:
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"name_template": STORY_NAME_TEMPLATE.format(
|
"name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action["app_url"],
|
app_url=action["app_url"].tame(check_string),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
return STORY_UPDATE_OWNER_TEMPLATE.format(**kwargs)
|
return STORY_UPDATE_OWNER_TEMPLATE.format(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
def get_story_update_batch_body(payload: Dict[str, Any], action: Dict[str, Any]) -> Optional[str]:
|
def get_story_update_batch_body(payload: WildValue, action: WildValue) -> Optional[str]:
|
||||||
# When the user selects one or more stories with the checkbox, they can perform
|
# When the user selects one or more stories with the checkbox, they can perform
|
||||||
# a batch update on multiple stories while changing multiple attribtues at the
|
# a batch update on multiple stories while changing multiple attribtues at the
|
||||||
# same time.
|
# same time.
|
||||||
changes = action["changes"]
|
changes = action["changes"]
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"name_template": STORY_NAME_TEMPLATE.format(
|
"name_template": STORY_NAME_TEMPLATE.format(
|
||||||
name=action["name"],
|
name=action["name"].tame(check_string),
|
||||||
app_url=action["app_url"],
|
app_url=action["app_url"].tame(check_string),
|
||||||
),
|
),
|
||||||
"workflow_state_template": "",
|
"workflow_state_template": "",
|
||||||
}
|
}
|
||||||
@@ -524,20 +563,34 @@ def get_story_update_batch_body(payload: Dict[str, Any], action: Dict[str, Any])
|
|||||||
move_sub_templates = []
|
move_sub_templates = []
|
||||||
if "epic_id" in changes:
|
if "epic_id" in changes:
|
||||||
last_change = "epic"
|
last_change = "epic"
|
||||||
|
epic_id = changes["epic_id"]
|
||||||
|
old_reference = get_reference_by_id(
|
||||||
|
payload, epic_id.get("old").tame(check_none_or(check_int))
|
||||||
|
)
|
||||||
|
new_reference = get_reference_by_id(
|
||||||
|
payload, epic_id.get("new").tame(check_none_or(check_int))
|
||||||
|
)
|
||||||
move_sub_templates.append(
|
move_sub_templates.append(
|
||||||
STORY_UPDATE_BATCH_CHANGED_SUB_TEMPLATE.format(
|
STORY_UPDATE_BATCH_CHANGED_SUB_TEMPLATE.format(
|
||||||
entity_type="Epic",
|
entity_type="Epic",
|
||||||
old=get_reference_by_id(payload, changes["epic_id"].get("old")).get("name"),
|
old=None if old_reference is None else old_reference["name"].tame(check_string),
|
||||||
new=get_reference_by_id(payload, changes["epic_id"].get("new")).get("name"),
|
new=None if new_reference is None else new_reference["name"].tame(check_string),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if "project_id" in changes:
|
if "project_id" in changes:
|
||||||
last_change = "project"
|
last_change = "project"
|
||||||
|
project_id = changes["project_id"]
|
||||||
|
old_reference = get_reference_by_id(
|
||||||
|
payload, project_id.get("old").tame(check_none_or(check_int))
|
||||||
|
)
|
||||||
|
new_reference = get_reference_by_id(
|
||||||
|
payload, project_id.get("new").tame(check_none_or(check_int))
|
||||||
|
)
|
||||||
move_sub_templates.append(
|
move_sub_templates.append(
|
||||||
STORY_UPDATE_BATCH_CHANGED_SUB_TEMPLATE.format(
|
STORY_UPDATE_BATCH_CHANGED_SUB_TEMPLATE.format(
|
||||||
entity_type="Project",
|
entity_type="Project",
|
||||||
old=get_reference_by_id(payload, changes["project_id"].get("old")).get("name"),
|
old=None if old_reference is None else old_reference["name"].tame(check_string),
|
||||||
new=get_reference_by_id(payload, changes["project_id"].get("new")).get("name"),
|
new=None if new_reference is None else new_reference["name"].tame(check_string),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if len(move_sub_templates) > 0:
|
if len(move_sub_templates) > 0:
|
||||||
@@ -550,42 +603,47 @@ def get_story_update_batch_body(payload: Dict[str, Any], action: Dict[str, Any])
|
|||||||
|
|
||||||
if "story_type" in changes:
|
if "story_type" in changes:
|
||||||
last_change = "type"
|
last_change = "type"
|
||||||
|
story_type = changes["story_type"]
|
||||||
templates.append(
|
templates.append(
|
||||||
STORY_UPDATE_BATCH_CHANGED_TEMPLATE.format(
|
STORY_UPDATE_BATCH_CHANGED_TEMPLATE.format(
|
||||||
operation="{} changed".format("was" if len(templates) == 0 else "and"),
|
operation="{} changed".format("was" if len(templates) == 0 else "and"),
|
||||||
sub_templates=STORY_UPDATE_BATCH_CHANGED_SUB_TEMPLATE.format(
|
sub_templates=STORY_UPDATE_BATCH_CHANGED_SUB_TEMPLATE.format(
|
||||||
entity_type="type",
|
entity_type="type",
|
||||||
old=changes["story_type"].get("old"),
|
old=story_type.get("old").tame(check_none_or(check_string)),
|
||||||
new=changes["story_type"].get("new"),
|
new=story_type.get("new").tame(check_none_or(check_string)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if "label_ids" in changes:
|
if "label_ids" in changes:
|
||||||
label_ids_added = changes["label_ids"].get("adds")
|
label_ids = changes["label_ids"]
|
||||||
# If this is a payload for when no label is added, ignore it
|
# If this is a payload for when no label is added, ignore it
|
||||||
if label_ids_added is not None:
|
if "adds" in label_ids:
|
||||||
|
label_ids_added = label_ids["adds"].tame(check_list(check_int))
|
||||||
last_change = "label"
|
last_change = "label"
|
||||||
labels = get_story_joined_label_list(payload, action, label_ids_added)
|
labels = get_story_joined_label_list(payload, action, label_ids_added)
|
||||||
templates.append(
|
templates.append(
|
||||||
STORY_UPDATE_BATCH_ADD_REMOVE_TEMPLATE.format(
|
STORY_UPDATE_BATCH_ADD_REMOVE_TEMPLATE.format(
|
||||||
operation="{} added".format("was" if len(templates) == 0 else "and"),
|
operation="{} added".format("was" if len(templates) == 0 else "and"),
|
||||||
entity="the new label{plural} {labels}".format(
|
entity="the new label{plural} {labels}".format(
|
||||||
plural="s" if len(changes["label_ids"]) > 1 else "", labels=labels
|
plural="s" if len(label_ids) > 1 else "", labels=labels
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if "workflow_state_id" in changes:
|
if "workflow_state_id" in changes:
|
||||||
last_change = "state"
|
last_change = "state"
|
||||||
|
workflow_state_id = changes["workflow_state_id"]
|
||||||
|
old_reference = get_reference_by_id(
|
||||||
|
payload, workflow_state_id.get("old").tame(check_none_or(check_int))
|
||||||
|
)
|
||||||
|
new_reference = get_reference_by_id(
|
||||||
|
payload, workflow_state_id.get("new").tame(check_none_or(check_int))
|
||||||
|
)
|
||||||
kwargs.update(
|
kwargs.update(
|
||||||
workflow_state_template=TRAILING_WORKFLOW_STATE_CHANGE_TEMPLATE.format(
|
workflow_state_template=TRAILING_WORKFLOW_STATE_CHANGE_TEMPLATE.format(
|
||||||
old=get_reference_by_id(payload, changes["workflow_state_id"].get("old")).get(
|
old=None if old_reference is None else old_reference["name"].tame(check_string),
|
||||||
"name"
|
new=None if new_reference is None else new_reference["name"].tame(check_string),
|
||||||
),
|
|
||||||
new=get_reference_by_id(payload, changes["workflow_state_id"].get("new")).get(
|
|
||||||
"name"
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -604,19 +662,19 @@ def get_story_update_batch_body(payload: Dict[str, Any], action: Dict[str, Any])
|
|||||||
|
|
||||||
|
|
||||||
def get_entity_name(
|
def get_entity_name(
|
||||||
payload: Dict[str, Any], action: Dict[str, Any], entity: Optional[str] = None
|
payload: WildValue, action: WildValue, entity: Optional[str] = None
|
||||||
) -> Optional[str]:
|
) -> Optional[str]:
|
||||||
name = action.get("name")
|
name = action["name"].tame(check_string) if "name" in action else None
|
||||||
|
|
||||||
if name is None or action["entity_type"] == "branch":
|
if name is None or action["entity_type"] == "branch":
|
||||||
for action in payload["actions"]:
|
for action in payload["actions"]:
|
||||||
if action["entity_type"] == entity:
|
if action["entity_type"].tame(check_string) == entity:
|
||||||
name = action["name"]
|
name = action["name"].tame(check_string)
|
||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
for ref in payload["references"]:
|
for ref in payload["references"]:
|
||||||
if ref["entity_type"] == entity:
|
if ref["entity_type"].tame(check_string) == entity:
|
||||||
name = ref["name"]
|
name = ref["name"].tame(check_string)
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
@@ -630,8 +688,8 @@ def get_name_template(entity: str) -> str:
|
|||||||
def send_stream_messages_for_actions(
|
def send_stream_messages_for_actions(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
user_profile: UserProfile,
|
user_profile: UserProfile,
|
||||||
payload: Dict[str, Any],
|
payload: WildValue,
|
||||||
action: Dict[str, Any],
|
action: WildValue,
|
||||||
event: str,
|
event: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
body_func = EVENT_BODY_FUNCTION_MAPPER.get(event)
|
body_func = EVENT_BODY_FUNCTION_MAPPER.get(event)
|
||||||
@@ -646,7 +704,7 @@ def send_stream_messages_for_actions(
|
|||||||
check_send_webhook_message(request, user_profile, topic, body, event)
|
check_send_webhook_message(request, user_profile, topic, body, event)
|
||||||
|
|
||||||
|
|
||||||
EVENT_BODY_FUNCTION_MAPPER: Dict[str, Callable[[Dict[str, Any], Dict[str, Any]], Optional[str]]] = {
|
EVENT_BODY_FUNCTION_MAPPER: Dict[str, Callable[[WildValue, WildValue], Optional[str]]] = {
|
||||||
"story_update_archived": partial(get_update_archived_body, entity="story"),
|
"story_update_archived": partial(get_update_archived_body, entity="story"),
|
||||||
"epic_update_archived": partial(get_update_archived_body, entity="epic"),
|
"epic_update_archived": partial(get_update_archived_body, entity="epic"),
|
||||||
"story_create": get_story_create_body,
|
"story_create": get_story_create_body,
|
||||||
@@ -681,7 +739,7 @@ EVENT_BODY_FUNCTION_MAPPER: Dict[str, Callable[[Dict[str, Any], Dict[str, Any]],
|
|||||||
|
|
||||||
ALL_EVENT_TYPES = list(EVENT_BODY_FUNCTION_MAPPER.keys())
|
ALL_EVENT_TYPES = list(EVENT_BODY_FUNCTION_MAPPER.keys())
|
||||||
|
|
||||||
EVENT_TOPIC_FUNCTION_MAPPER = {
|
EVENT_TOPIC_FUNCTION_MAPPER: Dict[str, Callable[[WildValue, WildValue], Optional[str]]] = {
|
||||||
"story": partial(get_entity_name, entity="story"),
|
"story": partial(get_entity_name, entity="story"),
|
||||||
"pull-request": partial(get_entity_name, entity="story"),
|
"pull-request": partial(get_entity_name, entity="story"),
|
||||||
"branch": partial(get_entity_name, entity="story"),
|
"branch": partial(get_entity_name, entity="story"),
|
||||||
@@ -695,9 +753,7 @@ IGNORED_EVENTS = {
|
|||||||
"story-comment_update",
|
"story-comment_update",
|
||||||
}
|
}
|
||||||
|
|
||||||
EVENTS_SECONDARY_ACTIONS_FUNCTION_MAPPER: Dict[
|
EVENTS_SECONDARY_ACTIONS_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], Iterator[WildValue]]] = {
|
||||||
str, Callable[[Dict[str, Any]], Generator[Dict[str, Any], None, None]]
|
|
||||||
] = {
|
|
||||||
"pull-request_create": partial(
|
"pull-request_create": partial(
|
||||||
get_secondary_actions_with_param, entity="story", changed_attr="pull_request_ids"
|
get_secondary_actions_with_param, entity="story", changed_attr="pull_request_ids"
|
||||||
),
|
),
|
||||||
@@ -715,19 +771,19 @@ EVENTS_SECONDARY_ACTIONS_FUNCTION_MAPPER: Dict[
|
|||||||
def api_clubhouse_webhook(
|
def api_clubhouse_webhook(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
user_profile: UserProfile,
|
user_profile: UserProfile,
|
||||||
payload: Optional[Dict[str, Any]] = REQ(argument_type="body"),
|
payload: WildValue = REQ(argument_type="body", converter=to_wild_value),
|
||||||
) -> HttpResponse:
|
) -> HttpResponse:
|
||||||
|
|
||||||
# Clubhouse has a tendency to send empty POST requests to
|
# Clubhouse has a tendency to send empty POST requests to
|
||||||
# third-party endpoints. It is unclear as to which event type
|
# third-party endpoints. It is unclear as to which event type
|
||||||
# such requests correspond to. So, it is best to ignore such
|
# such requests correspond to. So, it is best to ignore such
|
||||||
# requests for now.
|
# requests for now.
|
||||||
if payload is None:
|
if payload.value is None:
|
||||||
return json_success(request)
|
return json_success(request)
|
||||||
|
|
||||||
if payload.get("primary_id") is not None:
|
if "primary_id" in payload:
|
||||||
action = get_action_with_primary_id(payload)
|
action = get_action_with_primary_id(payload)
|
||||||
primary_actions = [action]
|
primary_actions: Iterable[WildValue] = [action]
|
||||||
else:
|
else:
|
||||||
primary_actions = payload["actions"]
|
primary_actions = payload["actions"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user