refactor: replace old bot code with Matrix infra configs and scripts
- Remove obsolete Python bot (Wordle, commands, callbacks, welcome) - Add hookshot/ — all 11 webhook transformation functions + deploy.sh - Add cinny/ — config.json and dev-update.sh (nightly dev branch build) - Add landing/ — matrix.lotusguild.org landing page HTML - Add systemd/ — livekit-server, draupnir, cinny cron unit files - Add draupnir/ — production config (access token redacted) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
11
hookshot/bazarr.js
Normal file
11
hookshot/bazarr.js
Normal file
@@ -0,0 +1,11 @@
|
||||
var title = data.title || 'Bazarr';
|
||||
var msg = data.message || data.body || '';
|
||||
var type = (data.type || 'info').toLowerCase();
|
||||
var emoji = type === 'success' ? '✅' : (type === 'warning' ? '⚠️' : (type === 'failure' ? '❌' : '📝'));
|
||||
var lines = [emoji + ' ' + title];
|
||||
var htmlParts = ['<b>' + emoji + ' ' + title + '</b>'];
|
||||
if (msg) {
|
||||
var msgLines = msg.split(/\r?\n/).filter(function(l){ return l.trim(); });
|
||||
for (var i = 0; i < msgLines.length; i++) { lines.push(msgLines[i]); htmlParts.push(msgLines[i]); }
|
||||
}
|
||||
result = { version: 'v2', plain: lines.join('\n'), html: htmlParts.join('<br>'), msgtype: 'm.notice' };
|
||||
54
hookshot/deploy.sh
Normal file
54
hookshot/deploy.sh
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
# Deploy hookshot transformation functions to Matrix room state.
|
||||
# Each .js file in this directory maps to a webhook by the same name (case-sensitive).
|
||||
#
|
||||
# Usage:
|
||||
# ./deploy.sh # deploy all hooks
|
||||
# ./deploy.sh proxmox.js # deploy one hook
|
||||
#
|
||||
# Requirements:
|
||||
# MATRIX_TOKEN - access token with power level >= 50 in the target room
|
||||
# MATRIX_SERVER - homeserver URL (default: https://matrix.lotusguild.org)
|
||||
# MATRIX_ROOM - room ID where hooks are registered
|
||||
|
||||
MATRIX_SERVER="${MATRIX_SERVER:-https://matrix.lotusguild.org}"
|
||||
MATRIX_ROOM="${MATRIX_ROOM:-!GttT4QYd1wlGlkHU3qTmq_P3gbyYKKeSSN6R7TPcJHg}"
|
||||
|
||||
if [ -z "$MATRIX_TOKEN" ]; then
|
||||
echo "Error: MATRIX_TOKEN is not set." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
deploy_hook() {
|
||||
local file="$1"
|
||||
local filename="$(basename "$file" .js)"
|
||||
# Capitalize first letter to match state_key (e.g. proxmox -> Proxmox)
|
||||
local state_key="$(echo "$filename" | sed 's/\b\(.\)/\u\1/g' | sed 's/-\(.\)/\u\1/g')"
|
||||
local fn="$(cat "$file")"
|
||||
local encoded_room="$(python3 -c "import urllib.parse; print(urllib.parse.quote('$MATRIX_ROOM'))")"
|
||||
local encoded_key="$(python3 -c "import urllib.parse; print(urllib.parse.quote('$state_key'))")"
|
||||
|
||||
local response
|
||||
response=$(curl -sf -X PUT \
|
||||
"$MATRIX_SERVER/_matrix/client/v3/rooms/$encoded_room/state/uk.half-shot.matrix-hookshot.generic.hook/$encoded_key" \
|
||||
-H "Authorization: Bearer $MATRIX_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data-binary "$(python3 -c "import json; print(json.dumps({'name': '$state_key', 'transformationFunction': open('$file').read()}))")" \
|
||||
2>&1)
|
||||
|
||||
if echo "$response" | python3 -c "import json,sys; d=json.load(sys.stdin); exit(0 if 'event_id' in d else 1)" 2>/dev/null; then
|
||||
echo "✓ $state_key"
|
||||
else
|
||||
echo "✗ $state_key: $response"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
deploy_hook "$DIR/$1"
|
||||
else
|
||||
for f in "$DIR"/*.js; do
|
||||
deploy_hook "$f"
|
||||
done
|
||||
fi
|
||||
32
hookshot/grafana.js
Normal file
32
hookshot/grafana.js
Normal file
@@ -0,0 +1,32 @@
|
||||
var status = data.status || 'unknown';
|
||||
var emoji = status === 'firing' ? '🔴' : (status === 'resolved' ? '🟢' : '🟡');
|
||||
var title = data.title || ('[' + status.toUpperCase() + '] Grafana Alert');
|
||||
var alerts = data.alerts || [];
|
||||
var lines = [emoji + ' ' + title];
|
||||
var htmlParts = ['<b>' + emoji + ' ' + title + '</b>'];
|
||||
for (var i = 0; i < alerts.length && i < 5; i++) {
|
||||
var a = alerts[i];
|
||||
var labels = a.labels || {};
|
||||
var ann = a.annotations || {};
|
||||
var name = labels.alertname || '';
|
||||
var summary = ann.summary || ann.description || '';
|
||||
var instance = labels.instance || labels.job || '';
|
||||
var severity = labels.severity || '';
|
||||
var aStatus = a.status || '';
|
||||
var genURL = a.generatorURL || '';
|
||||
var aEmoji = aStatus === 'resolved' ? '🟢' : '🔴';
|
||||
if (alerts.length > 1) {
|
||||
var alertLine = aEmoji + ' ' + (name || 'Alert') + (severity ? ' [' + severity + ']' : '') + (instance ? ' \u2014 ' + instance : '') + (summary ? ': ' + summary : '');
|
||||
lines.push(alertLine);
|
||||
htmlParts.push(alertLine + (genURL ? ' <a href="' + genURL + '">\u2197</a>' : ''));
|
||||
} else {
|
||||
if (name && name !== title) { lines.push('Alert: ' + name); htmlParts.push('Alert: ' + name); }
|
||||
if (severity) { lines.push('Severity: ' + severity); htmlParts.push('Severity: ' + severity); }
|
||||
if (instance) { lines.push('Instance: ' + instance); htmlParts.push('Instance: ' + instance); }
|
||||
if (summary) { lines.push(summary); htmlParts.push(summary); }
|
||||
if (genURL) { lines.push('View: ' + genURL); htmlParts.push('<a href="' + genURL + '">View in Grafana</a>'); }
|
||||
}
|
||||
}
|
||||
if (alerts.length === 0 && data.message) { lines.push(data.message); htmlParts.push(data.message); }
|
||||
if (alerts.length > 5) { var more = '(+' + (alerts.length - 5) + ' more alerts)'; lines.push(more); htmlParts.push('<i>' + more + '</i>'); }
|
||||
result = { version: 'v2', plain: lines.join('\n'), html: htmlParts.join('<br>'), msgtype: 'm.notice' };
|
||||
37
hookshot/lidarr.js
Normal file
37
hookshot/lidarr.js
Normal file
@@ -0,0 +1,37 @@
|
||||
var ev = data.eventType || 'Unknown';
|
||||
if (ev === 'Test') {
|
||||
result = { version: 'v2', plain: '🧪 Lidarr: Connection test successful', msgtype: 'm.notice' };
|
||||
} else {
|
||||
var artist = (data.artist && data.artist.name) || 'Unknown Artist';
|
||||
var albums = data.albums || (data.album ? [data.album] : []);
|
||||
var albumStr = albums.map(function(a){ return a.title || ''; }).filter(Boolean).join(', ');
|
||||
var quality = (data.release && data.release.quality) || (data.trackFiles && data.trackFiles[0] && data.trackFiles[0].quality) || '';
|
||||
var releaseGroup = (data.release && data.release.releaseGroup) || '';
|
||||
var client = data.downloadClient || '';
|
||||
var upgrade = data.isUpgrade ? ' \u2191upgrade' : '';
|
||||
var healthMsg = data.message || '';
|
||||
var healthWiki = data.wikiUrl || '';
|
||||
var prevVer = data.previousVersion || '';
|
||||
var newVer = data.newVersion || '';
|
||||
var emojiMap = { 'Grab':'📥','Download':'✅','Rename':'✏️','ArtistAdd':'➕','ArtistDelete':'🗑️','AlbumAdd':'➕','AlbumDelete':'🗑️','TrackFileDelete':'🗑️','HealthIssue':'⚠️','HealthRestored':'💚','ApplicationUpdate':'🔄' };
|
||||
var emoji = emojiMap[ev] || '🎵';
|
||||
var plain, html;
|
||||
if (ev === 'HealthIssue' || ev === 'HealthRestored') {
|
||||
plain = emoji + ' Lidarr ' + ev + ': ' + healthMsg + (healthWiki ? '\n' + healthWiki : '');
|
||||
html = '<b>' + emoji + ' Lidarr ' + ev + '</b>: ' + healthMsg + (healthWiki ? '<br><a href="' + healthWiki + '">Wiki</a>' : '');
|
||||
} else if (ev === 'ApplicationUpdate') {
|
||||
plain = emoji + ' Lidarr updated: ' + prevVer + ' \u2192 ' + newVer;
|
||||
html = '<b>' + emoji + ' Lidarr updated</b>: ' + prevVer + ' \u2192 ' + newVer;
|
||||
} else if (ev === 'ArtistAdd' || ev === 'ArtistDelete') {
|
||||
plain = emoji + ' Lidarr ' + ev + ': ' + artist;
|
||||
html = '<b>' + emoji + ' Lidarr ' + ev + '</b>: ' + artist;
|
||||
} else {
|
||||
var albumPart = albumStr ? ' \u2014 ' + albumStr : '';
|
||||
var qualPart = quality ? ' [' + quality + ']' : '';
|
||||
var groupPart = releaseGroup ? ' {' + releaseGroup + '}' : '';
|
||||
var clientPart = client ? ' via ' + client : '';
|
||||
plain = emoji + ' Lidarr ' + ev + ': ' + artist + albumPart + qualPart + groupPart + upgrade + clientPart;
|
||||
html = '<b>' + emoji + ' Lidarr ' + ev + '</b>: ' + artist + (albumStr ? ' \u2014 <i>' + albumStr + '</i>' : '') + qualPart + groupPart + upgrade + clientPart;
|
||||
}
|
||||
result = { version: 'v2', plain: plain, html: html, msgtype: 'm.notice' };
|
||||
}
|
||||
21
hookshot/owncast.js
Normal file
21
hookshot/owncast.js
Normal file
@@ -0,0 +1,21 @@
|
||||
var evtype = data.type || 'EVENT';
|
||||
var ed = data.eventData || {};
|
||||
var streamName = ed.name || ed.streamerName || '';
|
||||
var title = ed.streamTitle || ed.title || '';
|
||||
var viewers = ed.viewerCount !== undefined ? String(ed.viewerCount) : (ed.viewers !== undefined ? String(ed.viewers) : '');
|
||||
var url = ed.externalURL || ed.url || ed.serverURL || '';
|
||||
var chatUser = (ed.user && (ed.user.displayName || ed.user.username)) || '';
|
||||
var chatMsg = ed.body || '';
|
||||
var emoji, label;
|
||||
if (evtype === 'STREAM_STARTED') { emoji = '🔴'; label = 'Now Live'; }
|
||||
else if (evtype === 'STREAM_STOPPED') { emoji = '⚫'; label = 'Stream Ended'; }
|
||||
else if (evtype === 'USER_JOINED') { emoji = '👤'; label = 'Viewer Joined'; }
|
||||
else if (evtype === 'CHAT') { emoji = '💬'; label = 'Chat'; }
|
||||
else { emoji = '📡'; label = evtype.replace(/_/g, ' '); }
|
||||
var lines = [emoji + ' ' + label + (streamName ? ' \u2014 ' + streamName : '')];
|
||||
var htmlParts = ['<b>' + emoji + ' ' + label + '</b>' + (streamName ? ': ' + streamName : '')];
|
||||
if (title) { lines.push(title); htmlParts.push('<i>' + title + '</i>'); }
|
||||
if (viewers) { lines.push(viewers + ' viewers'); htmlParts.push(viewers + ' viewers'); }
|
||||
if (chatUser && chatMsg) { lines.push(chatUser + ': ' + chatMsg); htmlParts.push('<b>' + chatUser + '</b>: ' + chatMsg); }
|
||||
if (url && evtype === 'STREAM_STARTED') { lines.push(url); htmlParts.push('<a href="' + url + '">' + url + '</a>'); }
|
||||
result = { version: 'v2', plain: lines.join('\n'), html: htmlParts.join('<br>'), msgtype: 'm.notice' };
|
||||
18
hookshot/proxmox.js
Normal file
18
hookshot/proxmox.js
Normal file
@@ -0,0 +1,18 @@
|
||||
var embed = (data.embeds && data.embeds[0]) || {};
|
||||
var title = embed.title || 'Proxmox Notification';
|
||||
var description = embed.description || '';
|
||||
var fields = embed.fields || [];
|
||||
var fieldMap = {};
|
||||
fields.forEach(function(f) { fieldMap[f.name] = f.value; });
|
||||
var severity = (fieldMap['Severity'] || 'info').toLowerCase();
|
||||
var node = fieldMap['Node'] || '';
|
||||
var type = fieldMap['Type'] || '';
|
||||
var vmid = fieldMap['VM/CT ID'] || '';
|
||||
var emoji = severity === 'error' ? '🔴' : (severity === 'warning' ? '🟡' : 'ℹ️');
|
||||
var lines = [emoji + ' ' + title];
|
||||
var htmlParts = ['<b>' + emoji + ' ' + title + '</b>'];
|
||||
if (node) { lines.push('\uD83D\uDDA5\uFE0F Node: ' + node); htmlParts.push('\uD83D\uDDA5\uFE0F Node: <b>' + node + '</b>'); }
|
||||
if (type) { lines.push('\uD83D\uDCCB Type: ' + type); htmlParts.push('\uD83D\uDCCB Type: ' + type); }
|
||||
if (vmid && vmid !== 'N/A') { lines.push('\uD83D\uDD32 VM/CT: ' + vmid); htmlParts.push('\uD83D\uDD32 VM/CT: ' + vmid); }
|
||||
if (description) { lines.push(description); htmlParts.push(description); }
|
||||
result = { version: 'v2', plain: lines.join('\n'), html: htmlParts.join('<br>'), msgtype: 'm.notice' };
|
||||
35
hookshot/radarr.js
Normal file
35
hookshot/radarr.js
Normal file
@@ -0,0 +1,35 @@
|
||||
var ev = data.eventType || 'Unknown';
|
||||
if (ev === 'Test') {
|
||||
result = { version: 'v2', plain: '🧪 Radarr: Connection test successful', msgtype: 'm.notice' };
|
||||
} else {
|
||||
var m = data.movie || {};
|
||||
var movie = m.title ? m.title + (m.year ? ' (' + m.year + ')' : '') : 'Unknown Movie';
|
||||
var quality = (data.release && data.release.quality) || (data.movieFile && data.movieFile.quality) || '';
|
||||
var releaseGroup = (data.release && data.release.releaseGroup) || (data.movieFile && data.movieFile.releaseGroup) || '';
|
||||
var client = data.downloadClient || '';
|
||||
var upgrade = data.isUpgrade ? ' \u2191upgrade' : '';
|
||||
var healthMsg = data.message || '';
|
||||
var healthWiki = data.wikiUrl || '';
|
||||
var prevVer = data.previousVersion || '';
|
||||
var newVer = data.newVersion || '';
|
||||
var emojiMap = { 'Grab':'📥','Download':'✅','Rename':'✏️','MovieAdded':'➕','MovieDelete':'🗑️','MovieFileDelete':'🗑️','HealthIssue':'⚠️','HealthRestored':'💚','ApplicationUpdate':'🔄','ManualInteractionRequired':'🔔' };
|
||||
var emoji = emojiMap[ev] || '🎬';
|
||||
var plain, html;
|
||||
if (ev === 'HealthIssue' || ev === 'HealthRestored') {
|
||||
plain = emoji + ' Radarr ' + ev + ': ' + healthMsg + (healthWiki ? '\n' + healthWiki : '');
|
||||
html = '<b>' + emoji + ' Radarr ' + ev + '</b>: ' + healthMsg + (healthWiki ? '<br><a href="' + healthWiki + '">Wiki</a>' : '');
|
||||
} else if (ev === 'ApplicationUpdate') {
|
||||
plain = emoji + ' Radarr updated: ' + prevVer + ' \u2192 ' + newVer;
|
||||
html = '<b>' + emoji + ' Radarr updated</b>: ' + prevVer + ' \u2192 ' + newVer;
|
||||
} else if (ev === 'MovieAdded' || ev === 'MovieDelete') {
|
||||
plain = emoji + ' Radarr ' + ev + ': ' + movie;
|
||||
html = '<b>' + emoji + ' Radarr ' + ev + '</b>: ' + movie;
|
||||
} else {
|
||||
var qualPart = quality ? ' [' + quality + ']' : '';
|
||||
var groupPart = releaseGroup ? ' {' + releaseGroup + '}' : '';
|
||||
var clientPart = client ? ' via ' + client : '';
|
||||
plain = emoji + ' Radarr ' + ev + ': ' + movie + qualPart + groupPart + upgrade + clientPart;
|
||||
html = '<b>' + emoji + ' Radarr ' + ev + '</b>: ' + movie + qualPart + groupPart + upgrade + clientPart;
|
||||
}
|
||||
result = { version: 'v2', plain: plain, html: html, msgtype: 'm.notice' };
|
||||
}
|
||||
37
hookshot/readarr.js
Normal file
37
hookshot/readarr.js
Normal file
@@ -0,0 +1,37 @@
|
||||
var ev = data.eventType || 'Unknown';
|
||||
if (ev === 'Test') {
|
||||
result = { version: 'v2', plain: '🧪 Readarr: Connection test successful', msgtype: 'm.notice' };
|
||||
} else {
|
||||
var author = (data.author && data.author.name) || 'Unknown Author';
|
||||
var books = data.books || (data.book ? [data.book] : []);
|
||||
var bookStr = books.map(function(b){ return b.title || ''; }).filter(Boolean).join(', ');
|
||||
var quality = (data.release && data.release.quality) || (data.bookFile && data.bookFile.quality) || '';
|
||||
var releaseGroup = (data.release && data.release.releaseGroup) || (data.bookFile && data.bookFile.releaseGroup) || '';
|
||||
var client = data.downloadClient || '';
|
||||
var upgrade = data.isUpgrade ? ' \u2191upgrade' : '';
|
||||
var healthMsg = data.message || '';
|
||||
var healthWiki = data.wikiUrl || '';
|
||||
var prevVer = data.previousVersion || '';
|
||||
var newVer = data.newVersion || '';
|
||||
var emojiMap = { 'Grab':'📥','Download':'✅','Rename':'✏️','AuthorAdd':'➕','AuthorDelete':'🗑️','BookAdd':'➕','BookDelete':'🗑️','BookFileDelete':'🗑️','HealthIssue':'⚠️','HealthRestored':'💚','ApplicationUpdate':'🔄' };
|
||||
var emoji = emojiMap[ev] || '📚';
|
||||
var plain, html;
|
||||
if (ev === 'HealthIssue' || ev === 'HealthRestored') {
|
||||
plain = emoji + ' Readarr ' + ev + ': ' + healthMsg + (healthWiki ? '\n' + healthWiki : '');
|
||||
html = '<b>' + emoji + ' Readarr ' + ev + '</b>: ' + healthMsg + (healthWiki ? '<br><a href="' + healthWiki + '">Wiki</a>' : '');
|
||||
} else if (ev === 'ApplicationUpdate') {
|
||||
plain = emoji + ' Readarr updated: ' + prevVer + ' \u2192 ' + newVer;
|
||||
html = '<b>' + emoji + ' Readarr updated</b>: ' + prevVer + ' \u2192 ' + newVer;
|
||||
} else if (ev === 'AuthorAdd' || ev === 'AuthorDelete') {
|
||||
plain = emoji + ' Readarr ' + ev + ': ' + author;
|
||||
html = '<b>' + emoji + ' Readarr ' + ev + '</b>: ' + author;
|
||||
} else {
|
||||
var titlePart = bookStr ? bookStr + ' by ' + author : author;
|
||||
var qualPart = quality ? ' [' + quality + ']' : '';
|
||||
var groupPart = releaseGroup ? ' {' + releaseGroup + '}' : '';
|
||||
var clientPart = client ? ' via ' + client : '';
|
||||
plain = emoji + ' Readarr ' + ev + ': ' + titlePart + qualPart + groupPart + upgrade + clientPart;
|
||||
html = '<b>' + emoji + ' Readarr ' + ev + '</b>: ' + (bookStr ? '<i>' + bookStr + '</i> by ' + author : author) + qualPart + groupPart + upgrade + clientPart;
|
||||
}
|
||||
result = { version: 'v2', plain: plain, html: html, msgtype: 'm.notice' };
|
||||
}
|
||||
29
hookshot/seerr.js
Normal file
29
hookshot/seerr.js
Normal file
@@ -0,0 +1,29 @@
|
||||
var evtype = data.notification_type || data.event || 'Notification';
|
||||
var subject = data.subject || evtype;
|
||||
var message = data.message || '';
|
||||
var media = data.media || {};
|
||||
var request = data.request || {};
|
||||
var issue = data.issue || {};
|
||||
var comment = data.comment || {};
|
||||
var user = request.requestedBy_username || request.requestedBy_email || (data.account && data.account.username) || '';
|
||||
var mt = media.media_type || '';
|
||||
var status4k = media.status4k || 0;
|
||||
var typeEmoji = mt === 'movie' ? '🎬' : (mt === 'tv' ? '📺' : '📋');
|
||||
var statusEmoji;
|
||||
if (evtype.indexOf('PENDING') >= 0) statusEmoji = '🟡';
|
||||
else if (evtype.indexOf('APPROVED') >= 0 || evtype.indexOf('AVAILABLE') >= 0) statusEmoji = '✅';
|
||||
else if (evtype.indexOf('DECLINED') >= 0 || evtype.indexOf('FAILED') >= 0) statusEmoji = '❌';
|
||||
else if (evtype.indexOf('ISSUE') >= 0) statusEmoji = '⚠️';
|
||||
else if (evtype.indexOf('COMMENT') >= 0) statusEmoji = '💬';
|
||||
else statusEmoji = typeEmoji;
|
||||
var lines = [statusEmoji + ' ' + subject];
|
||||
var htmlParts = ['<b>' + statusEmoji + ' ' + subject + '</b>'];
|
||||
if (user) { lines.push('Requested by: ' + user); htmlParts.push('Requested by: ' + user); }
|
||||
if (message && message !== subject) { lines.push(message); htmlParts.push(message); }
|
||||
if (status4k) { lines.push('4K request'); htmlParts.push('4K request'); }
|
||||
if (issue.issue_type) {
|
||||
var issueLine = 'Issue: ' + issue.issue_type + (issue.message ? ' \u2014 ' + issue.message : '');
|
||||
lines.push(issueLine); htmlParts.push(issueLine);
|
||||
}
|
||||
if (comment.message) { lines.push('Comment: ' + comment.message); htmlParts.push('Comment: ' + comment.message); }
|
||||
result = { version: 'v2', plain: lines.join('\n'), html: htmlParts.join('<br>'), msgtype: 'm.notice' };
|
||||
41
hookshot/sonarr.js
Normal file
41
hookshot/sonarr.js
Normal file
@@ -0,0 +1,41 @@
|
||||
var ev = data.eventType || 'Unknown';
|
||||
if (ev === 'Test') {
|
||||
result = { version: 'v2', plain: '🧪 Sonarr: Connection test successful', msgtype: 'm.notice' };
|
||||
} else {
|
||||
var series = (data.series && data.series.title) || 'Unknown Series';
|
||||
var network = (data.series && data.series.network) || '';
|
||||
var eps = data.episodes || [];
|
||||
var epStrs = eps.map(function(ep) {
|
||||
var s = 'S' + ('0'+(ep.seasonNumber||0)).slice(-2) + 'E' + ('0'+(ep.episodeNumber||0)).slice(-2);
|
||||
return ep.title ? s + ' \u2013 ' + ep.title : s;
|
||||
});
|
||||
var quality = (data.release && data.release.quality) || (data.episodeFile && data.episodeFile.quality) || '';
|
||||
var releaseGroup = (data.release && data.release.releaseGroup) || (data.episodeFile && data.episodeFile.releaseGroup) || '';
|
||||
var client = data.downloadClient || '';
|
||||
var upgrade = data.isUpgrade ? ' \u2191upgrade' : '';
|
||||
var healthMsg = data.message || '';
|
||||
var healthWiki = data.wikiUrl || '';
|
||||
var prevVer = data.previousVersion || '';
|
||||
var newVer = data.newVersion || '';
|
||||
var emojiMap = { 'Grab':'📥','Download':'✅','Rename':'✏️','SeriesAdd':'➕','SeriesDelete':'🗑️','EpisodeFileDelete':'🗑️','HealthIssue':'⚠️','HealthRestored':'💚','ApplicationUpdate':'🔄','ManualInteractionRequired':'🔔' };
|
||||
var emoji = emojiMap[ev] || '📺';
|
||||
var plain, html;
|
||||
if (ev === 'HealthIssue' || ev === 'HealthRestored') {
|
||||
plain = emoji + ' Sonarr ' + ev + ': ' + healthMsg + (healthWiki ? '\n' + healthWiki : '');
|
||||
html = '<b>' + emoji + ' Sonarr ' + ev + '</b>: ' + healthMsg + (healthWiki ? '<br><a href="' + healthWiki + '">Wiki</a>' : '');
|
||||
} else if (ev === 'ApplicationUpdate') {
|
||||
plain = emoji + ' Sonarr updated: ' + prevVer + ' \u2192 ' + newVer;
|
||||
html = '<b>' + emoji + ' Sonarr updated</b>: ' + prevVer + ' \u2192 ' + newVer;
|
||||
} else if (ev === 'SeriesAdd' || ev === 'SeriesDelete' || ev === 'Rename') {
|
||||
plain = emoji + ' Sonarr ' + ev + ': ' + series + (network ? ' (' + network + ')' : '');
|
||||
html = '<b>' + emoji + ' Sonarr ' + ev + '</b>: ' + series + (network ? ' (' + network + ')' : '');
|
||||
} else {
|
||||
var epPart = epStrs.length ? ' \u2014 ' + epStrs.join(', ') : '';
|
||||
var qualPart = quality ? ' [' + quality + ']' : '';
|
||||
var groupPart = releaseGroup ? ' {' + releaseGroup + '}' : '';
|
||||
var clientPart = client ? ' via ' + client : '';
|
||||
plain = emoji + ' Sonarr ' + ev + ': ' + series + epPart + qualPart + groupPart + upgrade + clientPart;
|
||||
html = '<b>' + emoji + ' Sonarr ' + ev + '</b>: ' + series + (epStrs.length ? ' \u2014 <i>' + epStrs.join(', ') + '</i>' : '') + qualPart + groupPart + upgrade + clientPart;
|
||||
}
|
||||
result = { version: 'v2', plain: plain, html: html, msgtype: 'm.notice' };
|
||||
}
|
||||
31
hookshot/tinker-tickets.js
Normal file
31
hookshot/tinker-tickets.js
Normal file
@@ -0,0 +1,31 @@
|
||||
var id = data.ticket_id || '?';
|
||||
var title = data.title || 'Untitled';
|
||||
var priority = parseInt(data.priority) || 4;
|
||||
var category = data.category || 'General';
|
||||
var type = data.type || 'Issue';
|
||||
var source = data.source || '';
|
||||
var url = data.url || '';
|
||||
var trigger = data.trigger || 'manual';
|
||||
var notifyUsers = data.notify_users || [];
|
||||
var priorityEmojis = ['', '🔴', '🟠', '🔵', '🟢', '⚫'];
|
||||
var priorityLabels = ['', 'P1 Critical', 'P2 High', 'P3 Medium', 'P4 Low', 'P5 Info'];
|
||||
var emoji = (priority >= 1 && priority <= 5) ? priorityEmojis[priority] : '⚫';
|
||||
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 + ']';
|
||||
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 plain = emoji + ' New Ticket #' + id + ': ' + title + '\n' + meta + (url ? '\n' + url : '') + mentionPlain;
|
||||
var html = '<b>' + emoji + ' <a href="' + url + '">#' + id + '</a>: ' + title + '</b><br>' + meta + mentionHtml;
|
||||
result = { version: 'v2', plain: plain, html: html, msgtype: 'm.text' };
|
||||
18
hookshot/uptime-kuma.js
Normal file
18
hookshot/uptime-kuma.js
Normal file
@@ -0,0 +1,18 @@
|
||||
var monitor = data.monitor || {};
|
||||
var hb = data.heartbeat || {};
|
||||
var name = monitor.name || monitor.url || 'Monitor';
|
||||
var url = monitor.url || '';
|
||||
var status = hb.status;
|
||||
var emoji = status === 1 ? '🟢' : (status === 0 ? '🔴' : '🟡');
|
||||
var state = status === 1 ? 'UP' : (status === 0 ? 'DOWN' : 'Unknown');
|
||||
var reason = hb.msg || '';
|
||||
var ping = (hb.ping !== undefined && hb.ping !== null) ? hb.ping + 'ms' : '';
|
||||
var duration = hb.duration ? hb.duration + 's' : '';
|
||||
if (reason === 'OK' || reason === '200 - OK' || reason === '200') reason = '';
|
||||
var lines = [emoji + ' ' + name + ' is ' + state];
|
||||
var htmlParts = ['<b>' + emoji + ' ' + name + ' is ' + state + '</b>'];
|
||||
if (url) { lines.push(url); htmlParts.push('<a href="' + url + '">' + url + '</a>'); }
|
||||
if (reason) { lines.push('Reason: ' + reason); htmlParts.push('Reason: ' + reason); }
|
||||
if (ping && status === 1) { lines.push('Ping: ' + ping); htmlParts.push('Ping: ' + ping); }
|
||||
if (duration && status === 0) { lines.push('Down for: ' + duration); htmlParts.push('Down for: ' + duration); }
|
||||
result = { version: 'v2', plain: lines.join('\n'), html: htmlParts.join('<br>'), msgtype: 'm.notice' };
|
||||
Reference in New Issue
Block a user