-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbreakout-to-article.js
More file actions
69 lines (57 loc) · 2.25 KB
/
breakout-to-article.js
File metadata and controls
69 lines (57 loc) · 2.25 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
/**
* Breakout Monitor → Article Bridge
* Watches breakout_alerts.json and generates articles from new alerts
*/
const fs = require('fs');
const path = require('path');
const { writeArticle, publishArticle, tweetArticle, slugify, isAlreadyWritten } = require('./news-pipeline');
const ALERTS_FILE = '/root/.openclaw/data/memory/breakout_alerts.json';
const POLL_INTERVAL = 30000; // 30s
let lastSeenCount = 0;
let watchInterval;
function loadAlerts() {
try {
if (!fs.existsSync(ALERTS_FILE)) return [];
const data = JSON.parse(fs.readFileSync(ALERTS_FILE, 'utf8'));
return Array.isArray(data) ? data : [];
} catch (e) {
return [];
}
}
async function checkForNewAlerts() {
const alerts = loadAlerts();
if (alerts.length <= lastSeenCount) {
lastSeenCount = alerts.length; // handle file shrinks
return;
}
const newAlerts = alerts.slice(lastSeenCount);
lastSeenCount = alerts.length;
console.log(`[BREAKOUT] ${newAlerts.length} new alert(s)`);
for (const alert of newAlerts) {
try {
const sym = alert.symbol || alert.name || 'unknown';
const slug = slugify(`breakout-${sym}-${Date.now()}`);
if (isAlreadyWritten(slug)) continue;
const mcapStr = alert.mcap ? `$${(alert.mcap / 1e6).toFixed(1)}M mcap` : '';
const volStr = alert.volume ? `$${(alert.volume / 1e6).toFixed(1)}M vol` : '';
const topic = `${alert.name || sym} ($${sym}) breakout detected — ${[mcapStr, volStr].filter(Boolean).join(', ')}. ${alert.narrative || ''} ${alert.alert_type || ''}`.trim();
const article = await writeArticle(topic, 'TRENCH NEWS', alert, slug);
if (article) {
const published = await publishArticle(article);
if (published) await tweetArticle(article);
}
} catch (e) {
console.error(`[BREAKOUT] Error processing alert:`, e.message);
}
}
}
function startBreakoutWatcher() {
// Initialize count from existing file
lastSeenCount = loadAlerts().length;
console.log(`[BREAKOUT] watcher started — ${lastSeenCount} existing alerts, polling every 30s`);
watchInterval = setInterval(checkForNewAlerts, POLL_INTERVAL);
}
function stopBreakoutWatcher() {
if (watchInterval) clearInterval(watchInterval);
}
module.exports = { startBreakoutWatcher, stopBreakoutWatcher };