Lint / Shell (shellcheck) (push) Successful in 11s
Lint / JS (eslint) (push) Successful in 12s
Lint / Landing page is rendered (matrix (push) Successful in 5s
Lint / No secrets in webhook configs (push) Successful in 5s
Lint / Python (ruff) (push) Successful in 7s
Lint / Secret scan (gitleaks) (push) Successful in 6s
Lint / Shell (shellcheck) (pull_request) Successful in 10s
Lint / JS (eslint) (pull_request) Successful in 9s
Lint / No secrets in webhook configs (pull_request) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 43s
Lint / Landing page is rendered (matrix (pull_request) Successful in 4s
Lint / Python (ruff) (pull_request) Successful in 7s
Lint / Secret scan (gitleaks) (pull_request) Successful in 6s
Lint / Python deps (pip-audit) (pull_request) Successful in 39s
Synapse 1.164 turns on MSC4210 by default: the legacy push rules that
pinged when a user ID or display name appeared in the body are removed, so
a message only notifies the users listed in m.mentions.
- hookshot/tinker-tickets.js deliberately pings assignees/watchers
(notify_users) with matrix.to links; those pings would stop. Return
mentions: { user_ids: notifyUsers } (hookshot 7.3.2 v2 transforms
support it).
- matrixbot: send_html takes optional mention_user_ids; !roast mentions the
target when given as a full Matrix ID. Winner announcements stay without
a ping (the player is already in the room).
No @room is sent anywhere. Lotus Chat already sends m.mentions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
90 lines
4.1 KiB
JavaScript
90 lines
4.1 KiB
JavaScript
// Tinker Tickets hookshot transform — handles all event types emitted by NotificationHelper
|
|
// result must be assigned without var/let/const (QuickJS sandbox)
|
|
|
|
var event = data.event || 'ticket_created';
|
|
var id = data.ticket_id || '?';
|
|
var title = data.title || 'Untitled';
|
|
var url = data.url || '';
|
|
var notifyUsers = data.notify_users || [];
|
|
|
|
var priorityEmojis = ['', '\ud83d\udd34', '\ud83d\udfe0', '\ud83d\udd35', '\ud83d\udfe2', '\u26ab'];
|
|
var priorityLabels = ['', 'P1 Critical', 'P2 High', 'P3 Medium', 'P4 Low', 'P5 Info'];
|
|
|
|
// Build mention strings
|
|
var mentionPlain = '';
|
|
var mentionHtml = '';
|
|
if (notifyUsers.length > 0) {
|
|
var pParts = [], hParts = [];
|
|
for (var i = 0; i < notifyUsers.length; i++) {
|
|
var uid = notifyUsers[i];
|
|
var disp = uid.replace(/^@/, '').split(':')[0];
|
|
pParts.push(uid);
|
|
hParts.push('<a href="https://matrix.to/#/' + uid + '">' + disp + '</a>');
|
|
}
|
|
mentionPlain = '\n' + pParts.join(' ');
|
|
mentionHtml = '<br>' + hParts.join(' ');
|
|
}
|
|
|
|
var ticketLink = url ? ('<a href="' + url + '">#' + id + '</a>') : ('#' + id);
|
|
|
|
var plain, html;
|
|
|
|
if (event === 'ticket_created') {
|
|
var priority = parseInt(data.priority) || 4;
|
|
var category = data.category || 'General';
|
|
var type = data.type || 'Issue';
|
|
var source = data.source || '';
|
|
var trigger = data.trigger || 'manual';
|
|
var emoji = (priority >= 1 && priority <= 5) ? priorityEmojis[priority] : '\u26ab';
|
|
var pLabel = (priority >= 1 && priority <= 5) ? priorityLabels[priority] : 'P' + priority;
|
|
var tLabel = trigger === 'automated' ? 'Automated' : 'Manual';
|
|
var meta = pLabel + ' \u00b7 ' + category + ' \u00b7 ' + type + (source ? ' \u00b7 ' + source : '') + ' [' + tLabel + ']';
|
|
|
|
plain = emoji + ' New Ticket #' + id + ': ' + title + '\n' + meta + (url ? '\n' + url : '') + mentionPlain;
|
|
html = '<b>' + emoji + ' ' + ticketLink + ': ' + title + '</b><br>' + meta + mentionHtml;
|
|
|
|
} else if (event === 'status_changed') {
|
|
var oldStatus = data.old_status || '?';
|
|
var newStatus = data.new_status || '?';
|
|
var changedBy = data.changed_by ? (' by ' + data.changed_by) : '';
|
|
|
|
plain = '\ud83d\udd04 Status changed' + changedBy + ': ' + oldStatus + ' \u2192 ' + newStatus + '\n#' + id + ': ' + title + (url ? '\n' + url : '') + mentionPlain;
|
|
html = '\ud83d\udd04 Status changed' + changedBy + ': <b>' + oldStatus + ' \u2192 ' + newStatus + '</b><br>' + ticketLink + ': ' + title + mentionHtml;
|
|
|
|
} else if (event === 'comment_added') {
|
|
var author = data.author || 'Someone';
|
|
var preview = data.preview || '';
|
|
|
|
plain = '\ud83d\udcac ' + author + ' commented on #' + id + ': ' + title + (preview ? '\n"' + preview + '"' : '') + (url ? '\n' + url : '') + mentionPlain;
|
|
html = '\ud83d\udcac <b>' + author + '</b> commented on ' + ticketLink + ': ' + title + (preview ? '<br><i>"' + preview + '"</i>' : '') + mentionHtml;
|
|
|
|
} else if (event === 'mention') {
|
|
var author = data.author || 'Someone';
|
|
var preview = data.preview || '';
|
|
|
|
plain = '\ud83d\udce3 ' + author + ' mentioned you in #' + id + ': ' + title + (preview ? '\n"' + preview + '"' : '') + (url ? '\n' + url : '') + mentionPlain;
|
|
html = '\ud83d\udce3 <b>' + author + '</b> mentioned you in ' + ticketLink + ': ' + title + (preview ? '<br><i>"' + preview + '"</i>' : '') + mentionHtml;
|
|
|
|
} else if (event === 'assigned') {
|
|
var assignee = data.assignee || 'someone';
|
|
var changedBy = data.changed_by ? (' by ' + data.changed_by) : '';
|
|
|
|
plain = '\ud83d\udc64 Ticket #' + id + ' assigned to ' + assignee + changedBy + ': ' + title + (url ? '\n' + url : '') + mentionPlain;
|
|
html = '\ud83d\udc64 ' + ticketLink + ' assigned to <b>' + assignee + '</b>' + changedBy + ': ' + title + mentionHtml;
|
|
|
|
} else {
|
|
plain = '[tinker-tickets] event: ' + event + ' ticket #' + id;
|
|
html = '[tinker-tickets] event: <code>' + event + '</code> ticket #' + id;
|
|
}
|
|
|
|
// Explicit mentions (m.mentions): from Synapse 1.164 the legacy push rules
|
|
// that pinged on a user ID or display name in the body are off by default
|
|
// (MSC4210), so the people to notify must be listed here.
|
|
result = {
|
|
version: 'v2',
|
|
plain: plain,
|
|
html: html,
|
|
msgtype: 'm.text',
|
|
mentions: { user_ids: notifyUsers }
|
|
};
|