-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdigest.js
More file actions
121 lines (108 loc) · 4.38 KB
/
digest.js
File metadata and controls
121 lines (108 loc) · 4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// digest.js — in-memory ring buffer of recent GitHub events
// Stores the last MAX_ENTRIES events. Consumed by /digest.
// Resets on bot restart (no persistence needed — this is a live feed helper).
"use strict";
const MAX_ENTRIES = 50;
/** @type {DigestEntry[]} */
const _ring = [];
/**
* @typedef {Object} DigestEntry
* @property {string} eventType
* @property {string} summary — human-readable one-liner
* @property {string|null} url — link to the GitHub object
* @property {string|null} actor — GitHub username
* @property {string|null} repo — full_name e.g. "owner/repo"
* @property {Date} timestamp
* @property {'sent'|'dropped'|'ignored'} outcome
*/
/**
* Push a new event into the ring buffer.
* @param {string} eventType
* @param {object} payload Raw webhook payload
* @param {'sent'|'dropped'|'ignored'} outcome
*/
function push(eventType, payload, outcome) {
const entry = {
eventType,
outcome,
timestamp: new Date(),
actor: payload?.sender?.login || null,
repo: payload?.repository?.full_name || null,
summary: _summarise(eventType, payload),
url: _url(eventType, payload),
};
_ring.push(entry);
if (_ring.length > MAX_ENTRIES) _ring.shift();
}
/**
* Return the most recent `limit` entries, newest last.
* @param {number} [limit=10]
* @returns {DigestEntry[]}
*/
function recent(limit = 10) {
return _ring.slice(-Math.min(limit, MAX_ENTRIES));
}
/** Total entries currently in the ring. */
function size() { return _ring.length; }
// ─── Internal helpers ─────────────────────────────────────────────────────────
function _clip(str, max = 55) {
if (!str) return "";
const s = str.replace(/\r?\n/g, " ").trim();
return s.length > max ? s.slice(0, max - 1) + "…" : s;
}
function _summarise(type, p) {
try {
const who = p?.sender?.login || "someone";
switch (type) {
case "push":
return `${who} pushed ${p.commits?.length ?? 0} commit(s) to \`${p.ref?.replace("refs/heads/","")}\``;
case "pull_request":
return `${who} ${p.action} PR #${p.pull_request?.number}: ${_clip(p.pull_request?.title)}`;
case "issues":
return `${who} ${p.action} issue #${p.issue?.number}: ${_clip(p.issue?.title)}`;
case "issue_comment":
return `${who} commented on #${p.issue?.number}: ${_clip(p.comment?.body)}`;
case "pull_request_review":
return `${who} reviewed PR #${p.pull_request?.number} (${p.review?.state})`;
case "release":
return `${who} ${p.action} release ${p.release?.tag_name}`;
case "star":
return `${who} ${p.action === "created" ? "⭐ starred" : "unstarred"} the repo (${p.repository?.stargazers_count} total)`;
case "fork":
return `${who} 🍴 forked → ${p.forkee?.full_name}`;
case "create":
return `${who} created ${p.ref_type} \`${p.ref}\``;
case "delete":
return `${who} deleted ${p.ref_type} \`${p.ref}\``;
case "workflow_run":
return `Workflow "${p.workflow_run?.name}" ${p.workflow_run?.conclusion || p.action} on \`${p.workflow_run?.head_branch}\``;
case "check_run":
return `Check "${p.check_run?.name}" → ${p.check_run?.conclusion || p.action}`;
case "deployment_status":
return `Deploy to \`${p.deployment?.environment}\` → ${p.deployment_status?.state}`;
default:
return `${type}${p?.action ? ` (${p.action})` : ""}`;
}
} catch {
return type;
}
}
function _url(type, p) {
try {
switch (type) {
case "push": return p?.compare || p?.repository?.html_url;
case "pull_request": return p?.pull_request?.html_url;
case "issues": return p?.issue?.html_url;
case "issue_comment": return p?.comment?.html_url;
case "pull_request_review": return p?.review?.html_url;
case "release": return p?.release?.html_url;
case "workflow_run": return p?.workflow_run?.html_url;
case "check_run": return p?.check_run?.html_url;
case "deployment_status": return p?.deployment_status?.target_url || p?.repository?.html_url;
default: return p?.repository?.html_url || null;
}
} catch {
return null;
}
}
module.exports = { push, recent, size };