mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	webhooks: Use partial with positional arguments.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							04638ffaee
						
					
				
				
					commit
					6fef5c3e46
				
			@@ -312,11 +312,11 @@ def get_issue_commented_body(request: HttpRequest, payload: WildValue, include_t
 | 
				
			|||||||
    action = "[commented]({}) on".format(
 | 
					    action = "[commented]({}) on".format(
 | 
				
			||||||
        payload["comment"]["links"]["html"]["href"].tame(check_string)
 | 
					        payload["comment"]["links"]["html"]["href"].tame(check_string)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    return get_issue_action_body(request, payload, action, include_title)
 | 
					    return get_issue_action_body(action, request, payload, include_title)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_issue_action_body(
 | 
					def get_issue_action_body(
 | 
				
			||||||
    request: HttpRequest, payload: WildValue, action: str, include_title: bool
 | 
					    action: str, request: HttpRequest, payload: WildValue, include_title: bool
 | 
				
			||||||
) -> str:
 | 
					) -> str:
 | 
				
			||||||
    issue = payload["issue"]
 | 
					    issue = payload["issue"]
 | 
				
			||||||
    assignee = None
 | 
					    assignee = None
 | 
				
			||||||
@@ -338,7 +338,7 @@ def get_issue_action_body(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_pull_request_action_body(
 | 
					def get_pull_request_action_body(
 | 
				
			||||||
    request: HttpRequest, payload: WildValue, action: str, include_title: bool
 | 
					    action: str, request: HttpRequest, payload: WildValue, include_title: bool
 | 
				
			||||||
) -> str:
 | 
					) -> str:
 | 
				
			||||||
    pull_request = payload["pullrequest"]
 | 
					    pull_request = payload["pullrequest"]
 | 
				
			||||||
    target_branch = None
 | 
					    target_branch = None
 | 
				
			||||||
@@ -359,7 +359,7 @@ def get_pull_request_action_body(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_pull_request_created_or_updated_body(
 | 
					def get_pull_request_created_or_updated_body(
 | 
				
			||||||
    request: HttpRequest, payload: WildValue, action: str, include_title: bool
 | 
					    action: str, request: HttpRequest, payload: WildValue, include_title: bool
 | 
				
			||||||
) -> str:
 | 
					) -> str:
 | 
				
			||||||
    pull_request = payload["pullrequest"]
 | 
					    pull_request = payload["pullrequest"]
 | 
				
			||||||
    assignee = None
 | 
					    assignee = None
 | 
				
			||||||
@@ -399,9 +399,9 @@ def get_pull_request_comment_created_action_body(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_pull_request_deleted_or_updated_comment_action_body(
 | 
					def get_pull_request_deleted_or_updated_comment_action_body(
 | 
				
			||||||
 | 
					    action: str,
 | 
				
			||||||
    request: HttpRequest,
 | 
					    request: HttpRequest,
 | 
				
			||||||
    payload: WildValue,
 | 
					    payload: WildValue,
 | 
				
			||||||
    action: str,
 | 
					 | 
				
			||||||
    include_title: bool,
 | 
					    include_title: bool,
 | 
				
			||||||
) -> str:
 | 
					) -> str:
 | 
				
			||||||
    action = "{} a [comment]({})".format(
 | 
					    action = "{} a [comment]({})".format(
 | 
				
			||||||
@@ -538,21 +538,21 @@ GET_SINGLE_MESSAGE_BODY_DEPENDING_ON_TYPE_MAPPER: Dict[str, BodyGetter] = {
 | 
				
			|||||||
    "fork": get_fork_body,
 | 
					    "fork": get_fork_body,
 | 
				
			||||||
    "commit_comment": get_commit_comment_body,
 | 
					    "commit_comment": get_commit_comment_body,
 | 
				
			||||||
    "change_commit_status": get_commit_status_changed_body,
 | 
					    "change_commit_status": get_commit_status_changed_body,
 | 
				
			||||||
    "issue_updated": partial(get_issue_action_body, action="updated"),
 | 
					    "issue_updated": partial(get_issue_action_body, "updated"),
 | 
				
			||||||
    "issue_created": partial(get_issue_action_body, action="created"),
 | 
					    "issue_created": partial(get_issue_action_body, "created"),
 | 
				
			||||||
    "issue_commented": get_issue_commented_body,
 | 
					    "issue_commented": get_issue_commented_body,
 | 
				
			||||||
    "pull_request_created": partial(get_pull_request_created_or_updated_body, action="created"),
 | 
					    "pull_request_created": partial(get_pull_request_created_or_updated_body, "created"),
 | 
				
			||||||
    "pull_request_updated": partial(get_pull_request_created_or_updated_body, action="updated"),
 | 
					    "pull_request_updated": partial(get_pull_request_created_or_updated_body, "updated"),
 | 
				
			||||||
    "pull_request_approved": partial(get_pull_request_action_body, action="approved"),
 | 
					    "pull_request_approved": partial(get_pull_request_action_body, "approved"),
 | 
				
			||||||
    "pull_request_unapproved": partial(get_pull_request_action_body, action="unapproved"),
 | 
					    "pull_request_unapproved": partial(get_pull_request_action_body, "unapproved"),
 | 
				
			||||||
    "pull_request_fulfilled": partial(get_pull_request_action_body, action="merged"),
 | 
					    "pull_request_fulfilled": partial(get_pull_request_action_body, "merged"),
 | 
				
			||||||
    "pull_request_rejected": partial(get_pull_request_action_body, action="rejected"),
 | 
					    "pull_request_rejected": partial(get_pull_request_action_body, "rejected"),
 | 
				
			||||||
    "pull_request_comment_created": get_pull_request_comment_created_action_body,
 | 
					    "pull_request_comment_created": get_pull_request_comment_created_action_body,
 | 
				
			||||||
    "pull_request_comment_updated": partial(
 | 
					    "pull_request_comment_updated": partial(
 | 
				
			||||||
        get_pull_request_deleted_or_updated_comment_action_body, action="updated"
 | 
					        get_pull_request_deleted_or_updated_comment_action_body, "updated"
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    "pull_request_comment_deleted": partial(
 | 
					    "pull_request_comment_deleted": partial(
 | 
				
			||||||
        get_pull_request_deleted_or_updated_comment_action_body, action="deleted"
 | 
					        get_pull_request_deleted_or_updated_comment_action_body, "deleted"
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    "repo:updated": get_repo_updated_body,
 | 
					    "repo:updated": get_repo_updated_body,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,8 +84,8 @@ def ping_handler(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def repo_comment_handler(
 | 
					def repo_comment_handler(
 | 
				
			||||||
    payload: WildValue,
 | 
					 | 
				
			||||||
    action: str,
 | 
					    action: str,
 | 
				
			||||||
 | 
					    payload: WildValue,
 | 
				
			||||||
    branches: Optional[str],
 | 
					    branches: Optional[str],
 | 
				
			||||||
    include_title: Optional[str],
 | 
					    include_title: Optional[str],
 | 
				
			||||||
) -> List[Dict[str, str]]:
 | 
					) -> List[Dict[str, str]]:
 | 
				
			||||||
@@ -336,8 +336,8 @@ def get_pr_reassigned_body(payload: WildValue, include_title: Optional[str]) ->
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pr_handler(
 | 
					def pr_handler(
 | 
				
			||||||
    payload: WildValue,
 | 
					 | 
				
			||||||
    action: str,
 | 
					    action: str,
 | 
				
			||||||
 | 
					    payload: WildValue,
 | 
				
			||||||
    branches: Optional[str],
 | 
					    branches: Optional[str],
 | 
				
			||||||
    include_title: Optional[str],
 | 
					    include_title: Optional[str],
 | 
				
			||||||
) -> List[Dict[str, str]]:
 | 
					) -> List[Dict[str, str]]:
 | 
				
			||||||
@@ -363,8 +363,8 @@ def pr_handler(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pr_comment_handler(
 | 
					def pr_comment_handler(
 | 
				
			||||||
    payload: WildValue,
 | 
					 | 
				
			||||||
    action: str,
 | 
					    action: str,
 | 
				
			||||||
 | 
					    payload: WildValue,
 | 
				
			||||||
    branches: Optional[str],
 | 
					    branches: Optional[str],
 | 
				
			||||||
    include_title: Optional[str],
 | 
					    include_title: Optional[str],
 | 
				
			||||||
) -> List[Dict[str, str]]:
 | 
					) -> List[Dict[str, str]]:
 | 
				
			||||||
@@ -398,24 +398,24 @@ class EventHandler(Protocol):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
EVENT_HANDLER_MAP: Dict[str, EventHandler] = {
 | 
					EVENT_HANDLER_MAP: Dict[str, EventHandler] = {
 | 
				
			||||||
    "diagnostics:ping": ping_handler,
 | 
					    "diagnostics:ping": ping_handler,
 | 
				
			||||||
    "repo:comment:added": partial(repo_comment_handler, action="commented"),
 | 
					    "repo:comment:added": partial(repo_comment_handler, "commented"),
 | 
				
			||||||
    "repo:comment:edited": partial(repo_comment_handler, action="edited their comment"),
 | 
					    "repo:comment:edited": partial(repo_comment_handler, "edited their comment"),
 | 
				
			||||||
    "repo:comment:deleted": partial(repo_comment_handler, action="deleted their comment"),
 | 
					    "repo:comment:deleted": partial(repo_comment_handler, "deleted their comment"),
 | 
				
			||||||
    "repo:forked": repo_forked_handler,
 | 
					    "repo:forked": repo_forked_handler,
 | 
				
			||||||
    "repo:modified": repo_modified_handler,
 | 
					    "repo:modified": repo_modified_handler,
 | 
				
			||||||
    "repo:refs_changed": repo_push_handler,
 | 
					    "repo:refs_changed": repo_push_handler,
 | 
				
			||||||
    "pr:comment:added": partial(pr_comment_handler, action="commented on"),
 | 
					    "pr:comment:added": partial(pr_comment_handler, "commented on"),
 | 
				
			||||||
    "pr:comment:edited": partial(pr_comment_handler, action="edited their comment on"),
 | 
					    "pr:comment:edited": partial(pr_comment_handler, "edited their comment on"),
 | 
				
			||||||
    "pr:comment:deleted": partial(pr_comment_handler, action="deleted their comment on"),
 | 
					    "pr:comment:deleted": partial(pr_comment_handler, "deleted their comment on"),
 | 
				
			||||||
    "pr:declined": partial(pr_handler, action="declined"),
 | 
					    "pr:declined": partial(pr_handler, "declined"),
 | 
				
			||||||
    "pr:deleted": partial(pr_handler, action="deleted"),
 | 
					    "pr:deleted": partial(pr_handler, "deleted"),
 | 
				
			||||||
    "pr:merged": partial(pr_handler, action="merged"),
 | 
					    "pr:merged": partial(pr_handler, "merged"),
 | 
				
			||||||
    "pr:modified": partial(pr_handler, action="modified"),
 | 
					    "pr:modified": partial(pr_handler, "modified"),
 | 
				
			||||||
    "pr:opened": partial(pr_handler, action="opened"),
 | 
					    "pr:opened": partial(pr_handler, "opened"),
 | 
				
			||||||
    "pr:reviewer:approved": partial(pr_handler, action="approved"),
 | 
					    "pr:reviewer:approved": partial(pr_handler, "approved"),
 | 
				
			||||||
    "pr:reviewer:needs_work": partial(pr_handler, action="needs_work"),
 | 
					    "pr:reviewer:needs_work": partial(pr_handler, "needs_work"),
 | 
				
			||||||
    "pr:reviewer:updated": partial(pr_handler, action="reviewers_updated"),
 | 
					    "pr:reviewer:updated": partial(pr_handler, "reviewers_updated"),
 | 
				
			||||||
    "pr:reviewer:unapproved": partial(pr_handler, action="unapproved"),
 | 
					    "pr:reviewer:unapproved": partial(pr_handler, "unapproved"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ALL_EVENT_TYPES = list(EVENT_HANDLER_MAP.keys())
 | 
					ALL_EVENT_TYPES = list(EVENT_HANDLER_MAP.keys())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,7 +172,7 @@ def get_epic_create_body(payload: WildValue, action: WildValue) -> str:
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_comment_added_body(payload: WildValue, action: WildValue, entity: str) -> str:
 | 
					def get_comment_added_body(entity: str, payload: WildValue, action: WildValue) -> str:
 | 
				
			||||||
    actions = payload["actions"]
 | 
					    actions = payload["actions"]
 | 
				
			||||||
    kwargs = {"entity": entity}
 | 
					    kwargs = {"entity": entity}
 | 
				
			||||||
    for action in actions:
 | 
					    for action in actions:
 | 
				
			||||||
@@ -188,7 +188,7 @@ def get_comment_added_body(payload: WildValue, action: WildValue, entity: str) -
 | 
				
			|||||||
    return COMMENT_ADDED_TEMPLATE.format(**kwargs)
 | 
					    return COMMENT_ADDED_TEMPLATE.format(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_update_description_body(payload: WildValue, action: WildValue, entity: str) -> str:
 | 
					def get_update_description_body(entity: str, payload: WildValue, action: WildValue) -> str:
 | 
				
			||||||
    desc = action["changes"]["description"]
 | 
					    desc = action["changes"]["description"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kwargs = {
 | 
					    kwargs = {
 | 
				
			||||||
@@ -249,7 +249,7 @@ def get_story_update_state_body(payload: WildValue, action: WildValue) -> str:
 | 
				
			|||||||
    return STATE_CHANGED_TEMPLATE.format(**kwargs)
 | 
					    return STATE_CHANGED_TEMPLATE.format(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_update_name_body(payload: WildValue, action: WildValue, entity: str) -> str:
 | 
					def get_update_name_body(entity: str, payload: WildValue, action: WildValue) -> str:
 | 
				
			||||||
    name = action["changes"]["name"]
 | 
					    name = action["changes"]["name"]
 | 
				
			||||||
    kwargs = {
 | 
					    kwargs = {
 | 
				
			||||||
        "entity": entity,
 | 
					        "entity": entity,
 | 
				
			||||||
@@ -264,7 +264,7 @@ def get_update_name_body(payload: WildValue, action: WildValue, entity: str) ->
 | 
				
			|||||||
    return NAME_CHANGED_TEMPLATE.format(**kwargs)
 | 
					    return NAME_CHANGED_TEMPLATE.format(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_update_archived_body(payload: WildValue, action: WildValue, entity: str) -> str:
 | 
					def get_update_archived_body(entity: str, payload: WildValue, action: WildValue) -> str:
 | 
				
			||||||
    archived = action["changes"]["archived"]
 | 
					    archived = action["changes"]["archived"]
 | 
				
			||||||
    if archived["new"]:
 | 
					    if archived["new"]:
 | 
				
			||||||
        operation = "archived"
 | 
					        operation = "archived"
 | 
				
			||||||
@@ -283,7 +283,7 @@ def get_update_archived_body(payload: WildValue, action: WildValue, entity: str)
 | 
				
			|||||||
    return ARCHIVED_TEMPLATE.format(**kwargs)
 | 
					    return ARCHIVED_TEMPLATE.format(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_story_task_body(payload: WildValue, action: WildValue, operation: str) -> str:
 | 
					def get_story_task_body(operation: str, payload: WildValue, action: WildValue) -> str:
 | 
				
			||||||
    kwargs = {
 | 
					    kwargs = {
 | 
				
			||||||
        "task_description": action["description"].tame(check_string),
 | 
					        "task_description": action["description"].tame(check_string),
 | 
				
			||||||
        "operation": operation,
 | 
					        "operation": operation,
 | 
				
			||||||
@@ -381,7 +381,7 @@ def get_reference_by_id(payload: WildValue, ref_id: Optional[int]) -> Optional[W
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_secondary_actions_with_param(
 | 
					def get_secondary_actions_with_param(
 | 
				
			||||||
    payload: WildValue, entity: str, changed_attr: str
 | 
					    entity: str, changed_attr: str, payload: WildValue
 | 
				
			||||||
) -> Iterator[WildValue]:
 | 
					) -> 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.
 | 
				
			||||||
@@ -390,7 +390,7 @@ def get_secondary_actions_with_param(
 | 
				
			|||||||
            yield action
 | 
					            yield action
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_story_create_github_entity_body(payload: WildValue, action: WildValue, entity: str) -> str:
 | 
					def get_story_create_github_entity_body(entity: str, payload: WildValue, action: WildValue) -> str:
 | 
				
			||||||
    pull_request_action: WildValue = get_action_with_primary_id(payload)
 | 
					    pull_request_action: WildValue = get_action_with_primary_id(payload)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kwargs = {
 | 
					    kwargs = {
 | 
				
			||||||
@@ -662,9 +662,7 @@ def get_story_update_batch_body(payload: WildValue, action: WildValue) -> Option
 | 
				
			|||||||
    return STORY_UPDATE_BATCH_TEMPLATE.format(**kwargs)
 | 
					    return STORY_UPDATE_BATCH_TEMPLATE.format(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_entity_name(
 | 
					def get_entity_name(entity: str, payload: WildValue, action: WildValue) -> Optional[str]:
 | 
				
			||||||
    payload: WildValue, action: WildValue, entity: Optional[str] = None
 | 
					 | 
				
			||||||
) -> Optional[str]:
 | 
					 | 
				
			||||||
    name = action["name"].tame(check_string) if "name" in action else None
 | 
					    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":
 | 
				
			||||||
@@ -706,18 +704,16 @@ def send_stream_messages_for_actions(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EVENT_BODY_FUNCTION_MAPPER: Dict[str, Callable[[WildValue, WildValue], 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, "story"),
 | 
				
			||||||
    "epic_update_archived": partial(get_update_archived_body, entity="epic"),
 | 
					    "epic_update_archived": partial(get_update_archived_body, "epic"),
 | 
				
			||||||
    "story_create": get_story_create_body,
 | 
					    "story_create": get_story_create_body,
 | 
				
			||||||
    "pull-request_create": partial(get_story_create_github_entity_body, entity="pull-request"),
 | 
					    "pull-request_create": partial(get_story_create_github_entity_body, "pull-request"),
 | 
				
			||||||
    "pull-request_comment": partial(
 | 
					    "pull-request_comment": partial(get_story_create_github_entity_body, "pull-request-comment"),
 | 
				
			||||||
        get_story_create_github_entity_body, entity="pull-request-comment"
 | 
					    "branch_create": partial(get_story_create_github_entity_body, "branch"),
 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    "branch_create": partial(get_story_create_github_entity_body, entity="branch"),
 | 
					 | 
				
			||||||
    "story_delete": get_delete_body,
 | 
					    "story_delete": get_delete_body,
 | 
				
			||||||
    "epic_delete": get_delete_body,
 | 
					    "epic_delete": get_delete_body,
 | 
				
			||||||
    "story-task_create": partial(get_story_task_body, operation="added to"),
 | 
					    "story-task_create": partial(get_story_task_body, "added to"),
 | 
				
			||||||
    "story-task_delete": partial(get_story_task_body, operation="removed from"),
 | 
					    "story-task_delete": partial(get_story_task_body, "removed from"),
 | 
				
			||||||
    "story-task_update_complete": get_story_task_completed_body,
 | 
					    "story-task_update_complete": get_story_task_completed_body,
 | 
				
			||||||
    "story_update_epic": get_story_update_epic_body,
 | 
					    "story_update_epic": get_story_update_epic_body,
 | 
				
			||||||
    "story_update_estimate": get_story_update_estimate_body,
 | 
					    "story_update_estimate": get_story_update_estimate_body,
 | 
				
			||||||
@@ -727,27 +723,27 @@ EVENT_BODY_FUNCTION_MAPPER: Dict[str, Callable[[WildValue, WildValue], Optional[
 | 
				
			|||||||
    "story_update_project": get_story_update_project_body,
 | 
					    "story_update_project": get_story_update_project_body,
 | 
				
			||||||
    "story_update_type": get_story_update_type_body,
 | 
					    "story_update_type": get_story_update_type_body,
 | 
				
			||||||
    "epic_create": get_epic_create_body,
 | 
					    "epic_create": get_epic_create_body,
 | 
				
			||||||
    "epic-comment_create": partial(get_comment_added_body, entity="epic"),
 | 
					    "epic-comment_create": partial(get_comment_added_body, "epic"),
 | 
				
			||||||
    "story-comment_create": partial(get_comment_added_body, entity="story"),
 | 
					    "story-comment_create": partial(get_comment_added_body, "story"),
 | 
				
			||||||
    "epic_update_description": partial(get_update_description_body, entity="epic"),
 | 
					    "epic_update_description": partial(get_update_description_body, "epic"),
 | 
				
			||||||
    "story_update_description": partial(get_update_description_body, entity="story"),
 | 
					    "story_update_description": partial(get_update_description_body, "story"),
 | 
				
			||||||
    "epic_update_state": get_epic_update_state_body,
 | 
					    "epic_update_state": get_epic_update_state_body,
 | 
				
			||||||
    "story_update_state": get_story_update_state_body,
 | 
					    "story_update_state": get_story_update_state_body,
 | 
				
			||||||
    "epic_update_name": partial(get_update_name_body, entity="epic"),
 | 
					    "epic_update_name": partial(get_update_name_body, "epic"),
 | 
				
			||||||
    "story_update_name": partial(get_update_name_body, entity="story"),
 | 
					    "story_update_name": partial(get_update_name_body, "story"),
 | 
				
			||||||
    "story_update_batch": get_story_update_batch_body,
 | 
					    "story_update_batch": get_story_update_batch_body,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ALL_EVENT_TYPES = list(EVENT_BODY_FUNCTION_MAPPER.keys())
 | 
					ALL_EVENT_TYPES = list(EVENT_BODY_FUNCTION_MAPPER.keys())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EVENT_TOPIC_FUNCTION_MAPPER: Dict[str, Callable[[WildValue, WildValue], Optional[str]]] = {
 | 
					EVENT_TOPIC_FUNCTION_MAPPER: Dict[str, Callable[[WildValue, WildValue], Optional[str]]] = {
 | 
				
			||||||
    "story": partial(get_entity_name, entity="story"),
 | 
					    "story": partial(get_entity_name, "story"),
 | 
				
			||||||
    "pull-request": partial(get_entity_name, entity="story"),
 | 
					    "pull-request": partial(get_entity_name, "story"),
 | 
				
			||||||
    "branch": partial(get_entity_name, entity="story"),
 | 
					    "branch": partial(get_entity_name, "story"),
 | 
				
			||||||
    "story-comment": partial(get_entity_name, entity="story"),
 | 
					    "story-comment": partial(get_entity_name, "story"),
 | 
				
			||||||
    "story-task": partial(get_entity_name, entity="story"),
 | 
					    "story-task": partial(get_entity_name, "story"),
 | 
				
			||||||
    "epic": partial(get_entity_name, entity="epic"),
 | 
					    "epic": partial(get_entity_name, "epic"),
 | 
				
			||||||
    "epic-comment": partial(get_entity_name, entity="epic"),
 | 
					    "epic-comment": partial(get_entity_name, "epic"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
IGNORED_EVENTS = {
 | 
					IGNORED_EVENTS = {
 | 
				
			||||||
@@ -755,15 +751,9 @@ IGNORED_EVENTS = {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EVENTS_SECONDARY_ACTIONS_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], Iterator[WildValue]]] = {
 | 
					EVENTS_SECONDARY_ACTIONS_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], Iterator[WildValue]]] = {
 | 
				
			||||||
    "pull-request_create": partial(
 | 
					    "pull-request_create": partial(get_secondary_actions_with_param, "story", "pull_request_ids"),
 | 
				
			||||||
        get_secondary_actions_with_param, entity="story", changed_attr="pull_request_ids"
 | 
					    "branch_create": partial(get_secondary_actions_with_param, "story", "branch_ids"),
 | 
				
			||||||
    ),
 | 
					    "pull-request_comment": partial(get_secondary_actions_with_param, "story", "pull_request_ids"),
 | 
				
			||||||
    "branch_create": partial(
 | 
					 | 
				
			||||||
        get_secondary_actions_with_param, entity="story", changed_attr="branch_ids"
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    "pull-request_comment": partial(
 | 
					 | 
				
			||||||
        get_secondary_actions_with_param, entity="story", changed_attr="pull_request_ids"
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -251,7 +251,7 @@ def get_change_deployment_status_body(helper: Helper) -> str:
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_create_or_delete_body(helper: Helper, action: str) -> str:
 | 
					def get_create_or_delete_body(action: str, helper: Helper) -> str:
 | 
				
			||||||
    payload = helper.payload
 | 
					    payload = helper.payload
 | 
				
			||||||
    ref_type = payload["ref_type"].tame(check_string)
 | 
					    ref_type = payload["ref_type"].tame(check_string)
 | 
				
			||||||
    return "{} {} {} {}.".format(
 | 
					    return "{} {} {} {}.".format(
 | 
				
			||||||
@@ -814,9 +814,9 @@ def get_topic_based_on_type(payload: WildValue, event: str) -> str:
 | 
				
			|||||||
EVENT_FUNCTION_MAPPER: Dict[str, Callable[[Helper], str]] = {
 | 
					EVENT_FUNCTION_MAPPER: Dict[str, Callable[[Helper], str]] = {
 | 
				
			||||||
    "commit_comment": get_commit_comment_body,
 | 
					    "commit_comment": get_commit_comment_body,
 | 
				
			||||||
    "closed_pull_request": get_closed_pull_request_body,
 | 
					    "closed_pull_request": get_closed_pull_request_body,
 | 
				
			||||||
    "create": partial(get_create_or_delete_body, action="created"),
 | 
					    "create": partial(get_create_or_delete_body, "created"),
 | 
				
			||||||
    "check_run": get_check_run_body,
 | 
					    "check_run": get_check_run_body,
 | 
				
			||||||
    "delete": partial(get_create_or_delete_body, action="deleted"),
 | 
					    "delete": partial(get_create_or_delete_body, "deleted"),
 | 
				
			||||||
    "deployment": get_deployment_body,
 | 
					    "deployment": get_deployment_body,
 | 
				
			||||||
    "deployment_status": get_change_deployment_status_body,
 | 
					    "deployment_status": get_change_deployment_status_body,
 | 
				
			||||||
    "discussion": get_discussion_body,
 | 
					    "discussion": get_discussion_body,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -109,7 +109,7 @@ def get_issue_created_event_body(payload: WildValue, include_title: bool) -> str
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_issue_event_body(payload: WildValue, action: str, include_title: bool) -> str:
 | 
					def get_issue_event_body(action: str, payload: WildValue, include_title: bool) -> str:
 | 
				
			||||||
    return get_issue_event_message(
 | 
					    return get_issue_event_message(
 | 
				
			||||||
        user_name=get_issue_user_name(payload),
 | 
					        user_name=get_issue_user_name(payload),
 | 
				
			||||||
        action=action,
 | 
					        action=action,
 | 
				
			||||||
@@ -122,19 +122,19 @@ def get_issue_event_body(payload: WildValue, action: str, include_title: bool) -
 | 
				
			|||||||
def get_merge_request_updated_event_body(payload: WildValue, include_title: bool) -> str:
 | 
					def get_merge_request_updated_event_body(payload: WildValue, include_title: bool) -> str:
 | 
				
			||||||
    if payload["object_attributes"].get("oldrev"):
 | 
					    if payload["object_attributes"].get("oldrev"):
 | 
				
			||||||
        return get_merge_request_event_body(
 | 
					        return get_merge_request_event_body(
 | 
				
			||||||
            payload,
 | 
					 | 
				
			||||||
            "added commit(s) to",
 | 
					            "added commit(s) to",
 | 
				
			||||||
 | 
					            payload,
 | 
				
			||||||
            include_title=include_title,
 | 
					            include_title=include_title,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return get_merge_request_open_or_updated_body(
 | 
					    return get_merge_request_open_or_updated_body(
 | 
				
			||||||
        payload,
 | 
					 | 
				
			||||||
        "updated",
 | 
					        "updated",
 | 
				
			||||||
 | 
					        payload,
 | 
				
			||||||
        include_title=include_title,
 | 
					        include_title=include_title,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_merge_request_event_body(payload: WildValue, action: str, include_title: bool) -> str:
 | 
					def get_merge_request_event_body(action: str, payload: WildValue, include_title: bool) -> str:
 | 
				
			||||||
    pull_request = payload["object_attributes"]
 | 
					    pull_request = payload["object_attributes"]
 | 
				
			||||||
    target_branch = None
 | 
					    target_branch = None
 | 
				
			||||||
    base_branch = None
 | 
					    base_branch = None
 | 
				
			||||||
@@ -155,7 +155,7 @@ def get_merge_request_event_body(payload: WildValue, action: str, include_title:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_merge_request_open_or_updated_body(
 | 
					def get_merge_request_open_or_updated_body(
 | 
				
			||||||
    payload: WildValue, action: str, include_title: bool
 | 
					    action: str, payload: WildValue, include_title: bool
 | 
				
			||||||
) -> str:
 | 
					) -> str:
 | 
				
			||||||
    pull_request = payload["object_attributes"]
 | 
					    pull_request = payload["object_attributes"]
 | 
				
			||||||
    return get_pull_request_event_message(
 | 
					    return get_pull_request_event_message(
 | 
				
			||||||
@@ -272,7 +272,7 @@ def get_commented_snippet_event_body(payload: WildValue, include_title: bool) ->
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_wiki_page_event_body(payload: WildValue, action: str, include_title: bool) -> str:
 | 
					def get_wiki_page_event_body(action: str, payload: WildValue, include_title: bool) -> str:
 | 
				
			||||||
    return '{} {} [wiki page "{}"]({}).'.format(
 | 
					    return '{} {} [wiki page "{}"]({}).'.format(
 | 
				
			||||||
        get_issue_user_name(payload),
 | 
					        get_issue_user_name(payload),
 | 
				
			||||||
        action,
 | 
					        action,
 | 
				
			||||||
@@ -387,27 +387,27 @@ EVENT_FUNCTION_MAPPER: Dict[str, EventFunction] = {
 | 
				
			|||||||
    "Tag Push Hook": get_tag_push_event_body,
 | 
					    "Tag Push Hook": get_tag_push_event_body,
 | 
				
			||||||
    "Test Hook": get_test_event_body,
 | 
					    "Test Hook": get_test_event_body,
 | 
				
			||||||
    "Issue Hook open": get_issue_created_event_body,
 | 
					    "Issue Hook open": get_issue_created_event_body,
 | 
				
			||||||
    "Issue Hook close": partial(get_issue_event_body, action="closed"),
 | 
					    "Issue Hook close": partial(get_issue_event_body, "closed"),
 | 
				
			||||||
    "Issue Hook reopen": partial(get_issue_event_body, action="reopened"),
 | 
					    "Issue Hook reopen": partial(get_issue_event_body, "reopened"),
 | 
				
			||||||
    "Issue Hook update": partial(get_issue_event_body, action="updated"),
 | 
					    "Issue Hook update": partial(get_issue_event_body, "updated"),
 | 
				
			||||||
    "Confidential Issue Hook open": get_issue_created_event_body,
 | 
					    "Confidential Issue Hook open": get_issue_created_event_body,
 | 
				
			||||||
    "Confidential Issue Hook close": partial(get_issue_event_body, action="closed"),
 | 
					    "Confidential Issue Hook close": partial(get_issue_event_body, "closed"),
 | 
				
			||||||
    "Confidential Issue Hook reopen": partial(get_issue_event_body, action="reopened"),
 | 
					    "Confidential Issue Hook reopen": partial(get_issue_event_body, "reopened"),
 | 
				
			||||||
    "Confidential Issue Hook update": partial(get_issue_event_body, action="updated"),
 | 
					    "Confidential Issue Hook update": partial(get_issue_event_body, "updated"),
 | 
				
			||||||
    "Note Hook Commit": get_commented_commit_event_body,
 | 
					    "Note Hook Commit": get_commented_commit_event_body,
 | 
				
			||||||
    "Note Hook MergeRequest": get_commented_merge_request_event_body,
 | 
					    "Note Hook MergeRequest": get_commented_merge_request_event_body,
 | 
				
			||||||
    "Note Hook Issue": get_commented_issue_event_body,
 | 
					    "Note Hook Issue": get_commented_issue_event_body,
 | 
				
			||||||
    "Confidential Note Hook Issue": get_commented_issue_event_body,
 | 
					    "Confidential Note Hook Issue": get_commented_issue_event_body,
 | 
				
			||||||
    "Note Hook Snippet": get_commented_snippet_event_body,
 | 
					    "Note Hook Snippet": get_commented_snippet_event_body,
 | 
				
			||||||
    "Merge Request Hook approved": partial(get_merge_request_event_body, action="approved"),
 | 
					    "Merge Request Hook approved": partial(get_merge_request_event_body, "approved"),
 | 
				
			||||||
    "Merge Request Hook unapproved": partial(get_merge_request_event_body, action="unapproved"),
 | 
					    "Merge Request Hook unapproved": partial(get_merge_request_event_body, "unapproved"),
 | 
				
			||||||
    "Merge Request Hook open": partial(get_merge_request_open_or_updated_body, action="created"),
 | 
					    "Merge Request Hook open": partial(get_merge_request_open_or_updated_body, "created"),
 | 
				
			||||||
    "Merge Request Hook update": get_merge_request_updated_event_body,
 | 
					    "Merge Request Hook update": get_merge_request_updated_event_body,
 | 
				
			||||||
    "Merge Request Hook merge": partial(get_merge_request_event_body, action="merged"),
 | 
					    "Merge Request Hook merge": partial(get_merge_request_event_body, "merged"),
 | 
				
			||||||
    "Merge Request Hook close": partial(get_merge_request_event_body, action="closed"),
 | 
					    "Merge Request Hook close": partial(get_merge_request_event_body, "closed"),
 | 
				
			||||||
    "Merge Request Hook reopen": partial(get_merge_request_event_body, action="reopened"),
 | 
					    "Merge Request Hook reopen": partial(get_merge_request_event_body, "reopened"),
 | 
				
			||||||
    "Wiki Page Hook create": partial(get_wiki_page_event_body, action="created"),
 | 
					    "Wiki Page Hook create": partial(get_wiki_page_event_body, "created"),
 | 
				
			||||||
    "Wiki Page Hook update": partial(get_wiki_page_event_body, action="updated"),
 | 
					    "Wiki Page Hook update": partial(get_wiki_page_event_body, "updated"),
 | 
				
			||||||
    "Job Hook": get_build_hook_event_body,
 | 
					    "Job Hook": get_build_hook_event_body,
 | 
				
			||||||
    "Build Hook": get_build_hook_event_body,
 | 
					    "Build Hook": get_build_hook_event_body,
 | 
				
			||||||
    "Pipeline Hook": get_pipeline_event_body,
 | 
					    "Pipeline Hook": get_pipeline_event_body,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,7 +70,7 @@ def ticket_assigned_body(payload: WildValue) -> Optional[str]:
 | 
				
			|||||||
        return None
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def replied_body(payload: WildValue, actor: str, action: str) -> str:
 | 
					def replied_body(actor: str, action: str, payload: WildValue) -> str:
 | 
				
			||||||
    actor_url = "http://api.groovehq.com/v1/{}/".format(actor + "s")
 | 
					    actor_url = "http://api.groovehq.com/v1/{}/".format(actor + "s")
 | 
				
			||||||
    actor = payload["links"]["author"]["href"].tame(check_url).split(actor_url)[1]
 | 
					    actor = payload["links"]["author"]["href"].tame(check_url).split(actor_url)[1]
 | 
				
			||||||
    number = (
 | 
					    number = (
 | 
				
			||||||
@@ -93,9 +93,9 @@ def replied_body(payload: WildValue, actor: str, action: str) -> str:
 | 
				
			|||||||
EVENTS_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], Optional[str]]] = {
 | 
					EVENTS_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], Optional[str]]] = {
 | 
				
			||||||
    "ticket_started": ticket_started_body,
 | 
					    "ticket_started": ticket_started_body,
 | 
				
			||||||
    "ticket_assigned": ticket_assigned_body,
 | 
					    "ticket_assigned": ticket_assigned_body,
 | 
				
			||||||
    "agent_replied": partial(replied_body, actor="agent", action="replied to"),
 | 
					    "agent_replied": partial(replied_body, "agent", "replied to"),
 | 
				
			||||||
    "customer_replied": partial(replied_body, actor="customer", action="replied to"),
 | 
					    "customer_replied": partial(replied_body, "customer", "replied to"),
 | 
				
			||||||
    "note_added": partial(replied_body, actor="agent", action="left a note on"),
 | 
					    "note_added": partial(replied_body, "agent", "left a note on"),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ALL_EVENT_TYPES = list(EVENTS_FUNCTION_MAPPER.keys())
 | 
					ALL_EVENT_TYPES = list(EVENTS_FUNCTION_MAPPER.keys())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,8 +173,8 @@ def get_conversation_admin_assigned_message(payload: WildValue) -> Tuple[str, st
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_conversation_admin_message(
 | 
					def get_conversation_admin_message(
 | 
				
			||||||
    payload: WildValue,
 | 
					 | 
				
			||||||
    action: str,
 | 
					    action: str,
 | 
				
			||||||
 | 
					    payload: WildValue,
 | 
				
			||||||
) -> Tuple[str, str]:
 | 
					) -> Tuple[str, str]:
 | 
				
			||||||
    assignee = payload["data"]["item"]["assignee"]
 | 
					    assignee = payload["data"]["item"]["assignee"]
 | 
				
			||||||
    user = payload["data"]["item"]["user"]
 | 
					    user = payload["data"]["item"]["user"]
 | 
				
			||||||
@@ -187,8 +187,8 @@ def get_conversation_admin_message(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_conversation_admin_reply_message(
 | 
					def get_conversation_admin_reply_message(
 | 
				
			||||||
    payload: WildValue,
 | 
					 | 
				
			||||||
    action: str,
 | 
					    action: str,
 | 
				
			||||||
 | 
					    payload: WildValue,
 | 
				
			||||||
) -> Tuple[str, str]:
 | 
					) -> Tuple[str, str]:
 | 
				
			||||||
    assignee = payload["data"]["item"]["assignee"]
 | 
					    assignee = payload["data"]["item"]["assignee"]
 | 
				
			||||||
    user = payload["data"]["item"]["user"]
 | 
					    user = payload["data"]["item"]["user"]
 | 
				
			||||||
@@ -270,8 +270,8 @@ def get_user_email_updated_message(payload: WildValue) -> Tuple[str, str]:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_user_tagged_message(
 | 
					def get_user_tagged_message(
 | 
				
			||||||
    payload: WildValue,
 | 
					 | 
				
			||||||
    action: str,
 | 
					    action: str,
 | 
				
			||||||
 | 
					    payload: WildValue,
 | 
				
			||||||
) -> Tuple[str, str]:
 | 
					) -> Tuple[str, str]:
 | 
				
			||||||
    user = payload["data"]["item"]["user"]
 | 
					    user = payload["data"]["item"]["user"]
 | 
				
			||||||
    tag = payload["data"]["item"]["tag"]
 | 
					    tag = payload["data"]["item"]["tag"]
 | 
				
			||||||
@@ -298,16 +298,12 @@ EVENT_TO_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], Tuple[str, str]]] = {
 | 
				
			|||||||
    "contact.tag.created": get_contact_tag_created_message,
 | 
					    "contact.tag.created": get_contact_tag_created_message,
 | 
				
			||||||
    "contact.tag.deleted": get_contact_tag_deleted_message,
 | 
					    "contact.tag.deleted": get_contact_tag_deleted_message,
 | 
				
			||||||
    "conversation.admin.assigned": get_conversation_admin_assigned_message,
 | 
					    "conversation.admin.assigned": get_conversation_admin_assigned_message,
 | 
				
			||||||
    "conversation.admin.closed": partial(get_conversation_admin_message, action="closed"),
 | 
					    "conversation.admin.closed": partial(get_conversation_admin_message, "closed"),
 | 
				
			||||||
    "conversation.admin.opened": partial(get_conversation_admin_message, action="opened"),
 | 
					    "conversation.admin.opened": partial(get_conversation_admin_message, "opened"),
 | 
				
			||||||
    "conversation.admin.snoozed": partial(get_conversation_admin_message, action="snoozed"),
 | 
					    "conversation.admin.snoozed": partial(get_conversation_admin_message, "snoozed"),
 | 
				
			||||||
    "conversation.admin.unsnoozed": partial(get_conversation_admin_message, action="unsnoozed"),
 | 
					    "conversation.admin.unsnoozed": partial(get_conversation_admin_message, "unsnoozed"),
 | 
				
			||||||
    "conversation.admin.replied": partial(
 | 
					    "conversation.admin.replied": partial(get_conversation_admin_reply_message, "replied to"),
 | 
				
			||||||
        get_conversation_admin_reply_message, action="replied to"
 | 
					    "conversation.admin.noted": partial(get_conversation_admin_reply_message, "added a note to"),
 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    "conversation.admin.noted": partial(
 | 
					 | 
				
			||||||
        get_conversation_admin_reply_message, action="added a note to"
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    "conversation.admin.single.created": get_conversation_admin_single_created_message,
 | 
					    "conversation.admin.single.created": get_conversation_admin_single_created_message,
 | 
				
			||||||
    "conversation.user.created": get_conversation_user_created_message,
 | 
					    "conversation.user.created": get_conversation_user_created_message,
 | 
				
			||||||
    "conversation.user.replied": get_conversation_user_replied_message,
 | 
					    "conversation.user.replied": get_conversation_user_replied_message,
 | 
				
			||||||
@@ -315,8 +311,8 @@ EVENT_TO_FUNCTION_MAPPER: Dict[str, Callable[[WildValue], Tuple[str, str]]] = {
 | 
				
			|||||||
    "user.created": get_user_created_message,
 | 
					    "user.created": get_user_created_message,
 | 
				
			||||||
    "user.deleted": get_user_deleted_message,
 | 
					    "user.deleted": get_user_deleted_message,
 | 
				
			||||||
    "user.email.updated": get_user_email_updated_message,
 | 
					    "user.email.updated": get_user_email_updated_message,
 | 
				
			||||||
    "user.tag.created": partial(get_user_tagged_message, action="added to"),
 | 
					    "user.tag.created": partial(get_user_tagged_message, "added to"),
 | 
				
			||||||
    "user.tag.deleted": partial(get_user_tagged_message, action="removed from"),
 | 
					    "user.tag.deleted": partial(get_user_tagged_message, "removed from"),
 | 
				
			||||||
    "user.unsubscribed": get_user_unsubscribed_message,
 | 
					    "user.unsubscribed": get_user_unsubscribed_message,
 | 
				
			||||||
    # Note that we do not have a payload for visitor.signed_up
 | 
					    # Note that we do not have a payload for visitor.signed_up
 | 
				
			||||||
    # but it should be identical to contact.signed_up
 | 
					    # but it should be identical to contact.signed_up
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user