2020-06-13 03:34:01 +02:00
|
|
|
from typing import Any, Mapping, Optional, Tuple
|
2017-11-16 00:43:10 +01:00
|
|
|
|
2020-08-19 22:26:38 +02:00
|
|
|
from zerver.lib.exceptions import UnsupportedWebhookEventType
|
2016-05-05 07:06:41 +02:00
|
|
|
|
|
|
|
SUPPORTED_CARD_ACTIONS = [
|
2020-04-09 21:51:58 +02:00
|
|
|
'updateCard',
|
|
|
|
'createCard',
|
|
|
|
'addLabelToCard',
|
|
|
|
'removeLabelFromCard',
|
|
|
|
'addMemberToCard',
|
|
|
|
'removeMemberFromCard',
|
|
|
|
'addAttachmentToCard',
|
|
|
|
'addChecklistToCard',
|
|
|
|
'commentCard',
|
|
|
|
'updateCheckItemStateOnCard',
|
2016-05-05 07:06:41 +02:00
|
|
|
]
|
|
|
|
|
2019-02-21 23:16:09 +01:00
|
|
|
IGNORED_CARD_ACTIONS = [
|
2020-09-03 16:00:59 +02:00
|
|
|
"copyCard",
|
2020-08-20 18:06:30 +02:00
|
|
|
"createCheckItem",
|
|
|
|
"updateCheckItem",
|
|
|
|
"updateList",
|
2019-02-21 23:16:09 +01:00
|
|
|
]
|
|
|
|
|
2020-04-09 21:51:58 +02:00
|
|
|
CREATE = 'createCard'
|
|
|
|
CHANGE_LIST = 'changeList'
|
|
|
|
CHANGE_NAME = 'changeName'
|
|
|
|
SET_DESC = 'setDesc'
|
|
|
|
CHANGE_DESC = 'changeDesc'
|
|
|
|
REMOVE_DESC = 'removeDesc'
|
|
|
|
ARCHIVE = 'archiveCard'
|
|
|
|
REOPEN = 'reopenCard'
|
|
|
|
SET_DUE_DATE = 'setDueDate'
|
|
|
|
CHANGE_DUE_DATE = 'changeDueDate'
|
|
|
|
REMOVE_DUE_DATE = 'removeDueDate'
|
|
|
|
ADD_LABEL = 'addLabelToCard'
|
|
|
|
REMOVE_LABEL = 'removeLabelFromCard'
|
|
|
|
ADD_MEMBER = 'addMemberToCard'
|
|
|
|
REMOVE_MEMBER = 'removeMemberFromCard'
|
|
|
|
ADD_ATTACHMENT = 'addAttachmentToCard'
|
|
|
|
ADD_CHECKLIST = 'addChecklistToCard'
|
|
|
|
COMMENT = 'commentCard'
|
|
|
|
UPDATE_CHECK_ITEM_STATE = 'updateCheckItemStateOnCard'
|
|
|
|
|
|
|
|
TRELLO_CARD_URL_TEMPLATE = '[{card_name}]({card_url})'
|
2016-05-05 07:06:41 +02:00
|
|
|
|
|
|
|
ACTIONS_TO_MESSAGE_MAPPER = {
|
2020-04-09 21:51:58 +02:00
|
|
|
CREATE: 'created {card_url_template}.',
|
|
|
|
CHANGE_LIST: 'moved {card_url_template} from {old_list} to {new_list}.',
|
|
|
|
CHANGE_NAME: 'renamed the card from "{old_name}" to {card_url_template}.',
|
|
|
|
SET_DESC: 'set description for {card_url_template} to:\n~~~ quote\n{desc}\n~~~\n',
|
|
|
|
CHANGE_DESC: ('changed description for {card_url_template} from\n' +
|
2017-10-27 02:36:54 +02:00
|
|
|
'~~~ quote\n{old_desc}\n~~~\nto\n~~~ quote\n{desc}\n~~~\n'),
|
2020-04-09 21:51:58 +02:00
|
|
|
REMOVE_DESC: 'removed description from {card_url_template}.',
|
|
|
|
ARCHIVE: 'archived {card_url_template}.',
|
|
|
|
REOPEN: 'reopened {card_url_template}.',
|
|
|
|
SET_DUE_DATE: 'set due date for {card_url_template} to {due_date}.',
|
|
|
|
CHANGE_DUE_DATE: 'changed due date for {card_url_template} from {old_due_date} to {due_date}.',
|
|
|
|
REMOVE_DUE_DATE: 'removed the due date from {card_url_template}.',
|
|
|
|
ADD_LABEL: 'added a {color} label with \"{text}\" to {card_url_template}.',
|
|
|
|
REMOVE_LABEL: 'removed a {color} label with \"{text}\" from {card_url_template}.',
|
|
|
|
ADD_MEMBER: 'added {member_name} to {card_url_template}.',
|
|
|
|
REMOVE_MEMBER: 'removed {member_name} from {card_url_template}.',
|
|
|
|
ADD_ATTACHMENT: 'added [{attachment_name}]({attachment_url}) to {card_url_template}.',
|
|
|
|
ADD_CHECKLIST: 'added the {checklist_name} checklist to {card_url_template}.',
|
|
|
|
COMMENT: 'commented on {card_url_template}:\n~~~ quote\n{text}\n~~~\n',
|
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
|
|
|
UPDATE_CHECK_ITEM_STATE: '{action} **{item_name}** in **{checklist_name}** ({card_url_template}).',
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|
|
|
|
|
2017-11-04 07:47:46 +01:00
|
|
|
def prettify_date(date_string: str) -> str:
|
2017-02-26 09:10:14 +01:00
|
|
|
return date_string.replace('T', ' ').replace('.000', '').replace('Z', ' UTC')
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def process_card_action(payload: Mapping[str, Any], action_type: str) -> Optional[Tuple[str, str]]:
|
2017-08-06 08:31:36 +02:00
|
|
|
proper_action = get_proper_action(payload, action_type)
|
|
|
|
if proper_action is not None:
|
|
|
|
return get_subject(payload), get_body(payload, proper_action)
|
2017-07-27 06:33:57 +02:00
|
|
|
return None
|
2016-05-05 07:06:41 +02:00
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_proper_action(payload: Mapping[str, Any], action_type: str) -> Optional[str]:
|
2016-05-05 07:06:41 +02:00
|
|
|
if action_type == 'updateCard':
|
|
|
|
data = get_action_data(payload)
|
2017-05-24 23:03:06 +02:00
|
|
|
old_data = data['old']
|
|
|
|
card_data = data['card']
|
2016-05-05 07:06:41 +02:00
|
|
|
if data.get('listBefore'):
|
|
|
|
return CHANGE_LIST
|
2017-05-24 23:03:06 +02:00
|
|
|
if old_data.get('name'):
|
2016-05-05 07:06:41 +02:00
|
|
|
return CHANGE_NAME
|
2017-07-04 19:24:59 +02:00
|
|
|
if old_data.get('desc') == "":
|
|
|
|
return SET_DESC
|
|
|
|
if old_data.get('desc'):
|
|
|
|
if card_data.get('desc') == "":
|
|
|
|
return REMOVE_DESC
|
|
|
|
else:
|
|
|
|
return CHANGE_DESC
|
2017-05-24 23:03:06 +02:00
|
|
|
if old_data.get('due', False) is None:
|
2016-05-05 07:06:41 +02:00
|
|
|
return SET_DUE_DATE
|
2017-05-24 23:03:06 +02:00
|
|
|
if old_data.get('due'):
|
|
|
|
if card_data.get('due', False) is None:
|
2016-05-05 07:06:41 +02:00
|
|
|
return REMOVE_DUE_DATE
|
|
|
|
else:
|
|
|
|
return CHANGE_DUE_DATE
|
2017-05-24 23:03:06 +02:00
|
|
|
if old_data.get('closed') is False and card_data.get('closed'):
|
2016-05-05 07:06:41 +02:00
|
|
|
return ARCHIVE
|
2017-05-24 23:03:06 +02:00
|
|
|
if old_data.get('closed') and card_data.get('closed') is False:
|
2016-05-05 07:06:41 +02:00
|
|
|
return REOPEN
|
2020-08-22 14:33:01 +02:00
|
|
|
# We don't support events for when a card is moved up or down
|
|
|
|
# within a single list (pos), or when the cover changes (cover).
|
|
|
|
# We also don't know if "dueComplete" is just a new name for "due".
|
2020-08-21 14:12:49 +02:00
|
|
|
ignored_fields = [
|
|
|
|
"cover",
|
2020-08-22 14:33:01 +02:00
|
|
|
"dueComplete",
|
2020-08-21 14:12:49 +02:00
|
|
|
"idAttachmentCover",
|
|
|
|
"pos",
|
|
|
|
]
|
|
|
|
for field in ignored_fields:
|
|
|
|
if old_data.get(field):
|
|
|
|
return None
|
2020-08-20 00:50:06 +02:00
|
|
|
raise UnsupportedWebhookEventType(action_type)
|
2016-05-05 07:06:41 +02:00
|
|
|
|
|
|
|
return action_type
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_subject(payload: Mapping[str, Any]) -> str:
|
2017-09-24 01:07:17 +02:00
|
|
|
return get_action_data(payload)['board'].get('name')
|
2016-05-05 07:06:41 +02:00
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2017-05-24 23:03:06 +02:00
|
|
|
message_body = ACTIONS_TO_FILL_BODY_MAPPER[action_type](payload, action_type)
|
|
|
|
creator = payload['action']['memberCreator'].get('fullName')
|
2020-06-09 00:25:09 +02:00
|
|
|
return f'{creator} {message_body}'
|
2016-05-05 07:06:41 +02:00
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_added_checklist_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
data = {
|
2017-05-24 23:03:06 +02:00
|
|
|
'checklist_name': get_action_data(payload)['checklist'].get('name'),
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2019-02-22 00:00:06 +01:00
|
|
|
def get_update_check_item_body(payload: Mapping[str, Any], action_type: str) -> str:
|
|
|
|
action = get_action_data(payload)
|
|
|
|
state = action['checkItem']['state']
|
|
|
|
data = {
|
|
|
|
'action': 'checked' if state == 'complete' else 'unchecked',
|
|
|
|
'checklist_name': action['checklist'].get('name'),
|
|
|
|
'item_name': action['checkItem'].get('name'),
|
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_added_attachment_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
data = {
|
2017-05-24 23:03:06 +02:00
|
|
|
'attachment_url': get_action_data(payload)['attachment'].get('url'),
|
|
|
|
'attachment_name': get_action_data(payload)['attachment'].get('name'),
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_updated_card_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
data = {
|
|
|
|
'card_name': get_card_name(payload),
|
2017-05-24 23:03:06 +02:00
|
|
|
'old_list': get_action_data(payload)['listBefore'].get('name'),
|
|
|
|
'new_list': get_action_data(payload)['listAfter'].get('name'),
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_renamed_card_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2017-05-24 23:03:06 +02:00
|
|
|
|
2016-05-05 07:06:41 +02:00
|
|
|
data = {
|
2017-05-24 23:03:06 +02:00
|
|
|
'old_name': get_action_data(payload)['old'].get('name'),
|
|
|
|
'new_name': get_action_data(payload)['old'].get('name'),
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_added_label_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
data = {
|
|
|
|
'color': get_action_data(payload).get('value'),
|
|
|
|
'text': get_action_data(payload).get('text'),
|
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_managed_member_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
data = {
|
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
|
|
|
'member_name': payload['action']['member'].get('fullName'),
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_comment_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2017-07-04 18:58:49 +02:00
|
|
|
data = {
|
|
|
|
'text': get_action_data(payload)['text'],
|
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_managed_due_date_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
data = {
|
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
|
|
|
'due_date': prettify_date(get_action_data(payload)['card'].get('due')),
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_changed_due_date_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
data = {
|
2017-05-24 23:03:06 +02:00
|
|
|
'due_date': prettify_date(get_action_data(payload)['card'].get('due')),
|
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
|
|
|
'old_due_date': prettify_date(get_action_data(payload)['old'].get('due')),
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_managed_desc_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2017-07-04 19:24:59 +02:00
|
|
|
data = {
|
2020-07-29 02:58:19 +02:00
|
|
|
'desc': get_action_data(payload)['card']['desc'],
|
2017-07-04 19:24:59 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_changed_desc_body(payload: Mapping[str, Any], action_type: str) -> str:
|
2017-07-04 19:24:59 +02:00
|
|
|
data = {
|
2020-07-29 02:58:19 +02:00
|
|
|
'desc': get_action_data(payload)['card']['desc'],
|
|
|
|
'old_desc': get_action_data(payload)['old']['desc'],
|
2017-07-04 19:24:59 +02:00
|
|
|
}
|
|
|
|
return fill_appropriate_message_content(payload, action_type, data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_body_by_action_type_without_data(payload: Mapping[str, Any], action_type: str) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
return fill_appropriate_message_content(payload, action_type)
|
|
|
|
|
2017-11-04 07:47:46 +01:00
|
|
|
def fill_appropriate_message_content(payload: Mapping[str, Any],
|
2018-05-10 19:34:01 +02:00
|
|
|
action_type: str,
|
2020-06-13 03:34:01 +02:00
|
|
|
data: Mapping[str, Any] = {}) -> str:
|
|
|
|
data = dict(data)
|
|
|
|
if 'card_url_template' not in data:
|
|
|
|
data['card_url_template'] = get_filled_card_url_template(payload)
|
2016-05-05 07:06:41 +02:00
|
|
|
message_body = get_message_body(action_type)
|
|
|
|
return message_body.format(**data)
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_filled_card_url_template(payload: Mapping[str, Any]) -> str:
|
2016-05-05 07:06:41 +02:00
|
|
|
return TRELLO_CARD_URL_TEMPLATE.format(card_name=get_card_name(payload), card_url=get_card_url(payload))
|
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_card_url(payload: Mapping[str, Any]) -> str:
|
2020-04-09 21:51:58 +02:00
|
|
|
return 'https://trello.com/c/{}'.format(get_action_data(payload)['card'].get('shortLink'))
|
2016-05-05 07:06:41 +02:00
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_message_body(action_type: str) -> str:
|
2017-05-24 23:03:06 +02:00
|
|
|
return ACTIONS_TO_MESSAGE_MAPPER[action_type]
|
2016-05-05 07:06:41 +02:00
|
|
|
|
2018-05-10 19:34:01 +02:00
|
|
|
def get_card_name(payload: Mapping[str, Any]) -> str:
|
2017-05-24 23:03:06 +02:00
|
|
|
return get_action_data(payload)['card'].get('name')
|
2016-05-05 07:06:41 +02:00
|
|
|
|
2017-11-04 07:47:46 +01:00
|
|
|
def get_action_data(payload: Mapping[str, Any]) -> Mapping[str, Any]:
|
2017-05-24 23:03:06 +02:00
|
|
|
return payload['action'].get('data')
|
2016-05-05 07:06:41 +02:00
|
|
|
|
|
|
|
ACTIONS_TO_FILL_BODY_MAPPER = {
|
|
|
|
CREATE: get_body_by_action_type_without_data,
|
|
|
|
CHANGE_LIST: get_updated_card_body,
|
|
|
|
CHANGE_NAME: get_renamed_card_body,
|
2017-07-04 19:24:59 +02:00
|
|
|
SET_DESC: get_managed_desc_body,
|
|
|
|
CHANGE_DESC: get_changed_desc_body,
|
|
|
|
REMOVE_DESC: get_body_by_action_type_without_data,
|
2016-05-05 07:06:41 +02:00
|
|
|
ARCHIVE: get_body_by_action_type_without_data,
|
|
|
|
REOPEN: get_body_by_action_type_without_data,
|
|
|
|
SET_DUE_DATE: get_managed_due_date_body,
|
|
|
|
CHANGE_DUE_DATE: get_changed_due_date_body,
|
|
|
|
REMOVE_DUE_DATE: get_body_by_action_type_without_data,
|
|
|
|
ADD_LABEL: get_added_label_body,
|
|
|
|
REMOVE_LABEL: get_added_label_body,
|
|
|
|
ADD_MEMBER: get_managed_member_body,
|
|
|
|
REMOVE_MEMBER: get_managed_member_body,
|
|
|
|
ADD_ATTACHMENT: get_added_attachment_body,
|
|
|
|
ADD_CHECKLIST: get_added_checklist_body,
|
2017-07-04 18:58:49 +02:00
|
|
|
COMMENT: get_comment_body,
|
2019-02-22 00:00:06 +01:00
|
|
|
UPDATE_CHECK_ITEM_STATE: get_update_check_item_body,
|
2016-05-05 07:06:41 +02:00
|
|
|
}
|