фикс заявок с гцупом
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
43607bf9d0
commit
585cc374ed
2 changed files with 26 additions and 8 deletions
|
|
@ -56,7 +56,10 @@ def _build_full_text(
|
||||||
result += "\n\n🆕 *Новое:*\n" + "\n".join(newest)
|
result += "\n\n🆕 *Новое:*\n" + "\n".join(newest)
|
||||||
|
|
||||||
if responsible:
|
if responsible:
|
||||||
names = ", ".join(r["user_name"] for r in responsible)
|
names = ", ".join(
|
||||||
|
formatter.escape_markdown(r["user_name"]) or r["user_name"]
|
||||||
|
for r in responsible
|
||||||
|
)
|
||||||
result += _RESP_SEP + f"\n🙋 В работе: {names}"
|
result += _RESP_SEP + f"\n🙋 В работе: {names}"
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,15 @@ def _shorten_name(name: str | None) -> str | None:
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def escape_markdown(text: str | None) -> str | None:
|
||||||
|
"""Escape user-provided text for Telegram legacy Markdown parse mode."""
|
||||||
|
if text is None:
|
||||||
|
return None
|
||||||
|
escaped = str(text).replace("\\", "\\\\")
|
||||||
|
for ch in ("_", "*", "`", "["):
|
||||||
|
escaped = escaped.replace(ch, f"\\{ch}")
|
||||||
|
return escaped
|
||||||
|
|
||||||
def _strip_quote(text: str) -> tuple[str, bool]:
|
def _strip_quote(text: str) -> tuple[str, bool]:
|
||||||
"""Убирает блоки цитирования. Возвращает (cleaned_text, had_quote)."""
|
"""Убирает блоки цитирования. Возвращает (cleaned_text, had_quote)."""
|
||||||
cleaned, n = _QUOTE_RE.subn("", text)
|
cleaned, n = _QUOTE_RE.subn("", text)
|
||||||
|
|
@ -146,6 +155,7 @@ def _parse_single_event(event: dict, username: str = "") -> ParsedEvent | None:
|
||||||
etype = event.get("type")
|
etype = event.get("type")
|
||||||
blockname = event.get("blockname", "")
|
blockname = event.get("blockname", "")
|
||||||
short_user = _shorten_name(username) or "Неизвестный"
|
short_user = _shorten_name(username) or "Неизвестный"
|
||||||
|
short_user = escape_markdown(short_user) or short_user
|
||||||
|
|
||||||
# ── Комментарии ──────────────────────────────────────────────────────────
|
# ── Комментарии ──────────────────────────────────────────────────────────
|
||||||
if etype in (50, 55):
|
if etype in (50, 55):
|
||||||
|
|
@ -155,6 +165,7 @@ def _parse_single_event(event: dict, username: str = "") -> ParsedEvent | None:
|
||||||
text, had_quote = _strip_quote(text)
|
text, had_quote = _strip_quote(text)
|
||||||
if not text:
|
if not text:
|
||||||
return None
|
return None
|
||||||
|
text = escape_markdown(text) or ""
|
||||||
prefix = "Ответ на прошлое: " if had_quote else ""
|
prefix = "Ответ на прошлое: " if had_quote else ""
|
||||||
lock = " 🔒" if etype == 55 else ""
|
lock = " 🔒" if etype == 55 else ""
|
||||||
return ParsedEvent("comment", f"*{short_user}*{lock}: {prefix}{text}")
|
return ParsedEvent("comment", f"*{short_user}*{lock}: {prefix}{text}")
|
||||||
|
|
@ -187,8 +198,8 @@ def _parse_single_event(event: dict, username: str = "") -> ParsedEvent | None:
|
||||||
if entity_data:
|
if entity_data:
|
||||||
val_new = entity_data.get("valuenew") or {}
|
val_new = entity_data.get("valuenew") or {}
|
||||||
val_old = entity_data.get("valueold")
|
val_old = entity_data.get("valueold")
|
||||||
new_str = _extract_name(val_new, blockname)
|
new_str = escape_markdown(_extract_name(val_new, blockname))
|
||||||
old_str = _extract_name(val_old, blockname) if val_old else None
|
old_str = escape_markdown(_extract_name(val_old, blockname)) if val_old else None
|
||||||
if not new_str and not old_str:
|
if not new_str and not old_str:
|
||||||
return None
|
return None
|
||||||
if new_str and old_str:
|
if new_str and old_str:
|
||||||
|
|
@ -205,11 +216,14 @@ def _parse_single_event(event: dict, username: str = "") -> ParsedEvent | None:
|
||||||
if isinstance(attach, dict):
|
if isinstance(attach, dict):
|
||||||
fname = attach.get("Name", "")
|
fname = attach.get("Name", "")
|
||||||
uploader = _shorten_name(attach.get("UploadedBy", "").strip() or None) or "?"
|
uploader = _shorten_name(attach.get("UploadedBy", "").strip() or None) or "?"
|
||||||
|
fname = escape_markdown(fname) or ""
|
||||||
|
uploader = escape_markdown(uploader) or "?"
|
||||||
return ParsedEvent("change", f"• 📎 {uploader} прикрепил: {fname}")
|
return ParsedEvent("change", f"• 📎 {uploader} прикрепил: {fname}")
|
||||||
m = _FILE_EXT_RE.search(str_val.strip())
|
m = _FILE_EXT_RE.search(str_val.strip())
|
||||||
ext = m.group(1).upper() if m else "файл"
|
ext = m.group(1).upper() if m else "файл"
|
||||||
return ParsedEvent("change", f"• 📎 Добавлен файл .{ext}")
|
return ParsedEvent("change", f"• 📎 Добавлен файл .{ext}")
|
||||||
truncated = str_val[:80] + ("…" if len(str_val) > 80 else "")
|
truncated = str_val[:80] + ("…" if len(str_val) > 80 else "")
|
||||||
|
truncated = escape_markdown(truncated) or ""
|
||||||
return ParsedEvent("change", f"• {label}: *{truncated}*")
|
return ParsedEvent("change", f"• {label}: *{truncated}*")
|
||||||
|
|
||||||
# ── Событие без значения ──────────────────────────────────────────────────
|
# ── Событие без значения ──────────────────────────────────────────────────
|
||||||
|
|
@ -230,6 +244,7 @@ def get_description_event(fields: dict) -> str | None:
|
||||||
if not description:
|
if not description:
|
||||||
return None
|
return None
|
||||||
truncated = description[:100] + ('…' if len(description) > 100 else '')
|
truncated = description[:100] + ('…' if len(description) > 100 else '')
|
||||||
|
truncated = escape_markdown(truncated) or ""
|
||||||
return f"📝 {truncated}"
|
return f"📝 {truncated}"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -374,12 +389,12 @@ def format_notification(payload: dict) -> str:
|
||||||
op_type = payload.get("Event", {}).get("OperationType", "")
|
op_type = payload.get("Event", {}).get("OperationType", "")
|
||||||
fields = payload.get("Fields", {})
|
fields = payload.get("Fields", {})
|
||||||
number = fields.get("Number", "?")
|
number = fields.get("Number", "?")
|
||||||
name = _scalar(fields.get("name")) or "—"
|
name = escape_markdown(_scalar(fields.get("name")) or "—") or "-"
|
||||||
applicant = get_initiator(fields)
|
applicant = escape_markdown(get_initiator(fields))
|
||||||
executors = get_all_executors(fields)
|
executors = [escape_markdown(x) or "" for x in get_all_executors(fields)]
|
||||||
obj_name = get_object_name(fields)
|
obj_name = escape_markdown(get_object_name(fields))
|
||||||
to_flag = is_to(fields)
|
to_flag = is_to(fields)
|
||||||
status = _resolve_field(fields, "status", "statuses")
|
status = escape_markdown(_resolve_field(fields, "status", "statuses"))
|
||||||
|
|
||||||
header = f"🆕 *Новая #{number}*" if op_type == "Created" \
|
header = f"🆕 *Новая #{number}*" if op_type == "Created" \
|
||||||
else f"🔄 *#{number} обновлена*"
|
else f"🔄 *#{number} обновлена*"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue