twindex-openclaw-plugin 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/index.ts +15 -2
- package/src/poll-service.ts +31 -16
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -94,12 +94,23 @@ export default function register(api: any) {
|
|
|
94
94
|
description:
|
|
95
95
|
"How often to deliver updates. realtime = every 5 min, periodic = every hour, daily = once per day.",
|
|
96
96
|
},
|
|
97
|
+
chat_target: {
|
|
98
|
+
type: "string",
|
|
99
|
+
description:
|
|
100
|
+
"Delivery target. For Telegram, this is the chat ID. For Slack, the channel ID.",
|
|
101
|
+
},
|
|
102
|
+
chat_channel: {
|
|
103
|
+
type: "string",
|
|
104
|
+
enum: ["telegram", "slack"],
|
|
105
|
+
description:
|
|
106
|
+
"Delivery channel. Defaults to telegram.",
|
|
107
|
+
},
|
|
97
108
|
},
|
|
98
|
-
required: ["artists", "frequency"],
|
|
109
|
+
required: ["artists", "frequency", "chat_target"],
|
|
99
110
|
},
|
|
100
111
|
async execute(
|
|
101
112
|
_id: string,
|
|
102
|
-
params: { artists: string[]; frequency: string },
|
|
113
|
+
params: { artists: string[]; frequency: string; chat_target: string; chat_channel?: string },
|
|
103
114
|
) {
|
|
104
115
|
try {
|
|
105
116
|
const config = cfg();
|
|
@@ -118,6 +129,8 @@ export default function register(api: any) {
|
|
|
118
129
|
apiKey,
|
|
119
130
|
artists: params.artists,
|
|
120
131
|
frequency: params.frequency,
|
|
132
|
+
chatTarget: params.chat_target,
|
|
133
|
+
chatChannel: params.chat_channel ?? "telegram",
|
|
121
134
|
});
|
|
122
135
|
|
|
123
136
|
const results: string[] = [];
|
package/src/poll-service.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Polling notification service — replaces SSE for frameworks that can't hold
|
|
2
2
|
// persistent connections (like OpenClaw plugins).
|
|
3
3
|
// Polls GET /api/v1/notifications at configurable intervals, delivers via
|
|
4
|
-
// `openclaw
|
|
4
|
+
// `openclaw message send` CLI, marks read after confirmed delivery.
|
|
5
5
|
|
|
6
6
|
import { execFile } from "child_process";
|
|
7
7
|
import * as twindex from "./client.js";
|
|
@@ -12,21 +12,16 @@ const FREQUENCY_MS: Record<string, number> = {
|
|
|
12
12
|
daily: 24 * 60 * 60 * 1000, // 24 hours
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
function
|
|
15
|
+
function sendMessage(
|
|
16
|
+
message: string,
|
|
17
|
+
channel: string,
|
|
18
|
+
target: string,
|
|
19
|
+
): Promise<boolean> {
|
|
16
20
|
return new Promise((resolve) => {
|
|
17
21
|
execFile(
|
|
18
22
|
"openclaw",
|
|
19
|
-
[
|
|
20
|
-
|
|
21
|
-
"--session-id",
|
|
22
|
-
"twindex-push",
|
|
23
|
-
"--deliver",
|
|
24
|
-
"--channel",
|
|
25
|
-
"last",
|
|
26
|
-
"-m",
|
|
27
|
-
message,
|
|
28
|
-
],
|
|
29
|
-
{ timeout: 120_000 },
|
|
23
|
+
["message", "send", "--channel", channel, "--target", target, "-m", message],
|
|
24
|
+
{ timeout: 30_000 },
|
|
30
25
|
(err) => resolve(!err),
|
|
31
26
|
);
|
|
32
27
|
});
|
|
@@ -45,6 +40,14 @@ export function createNotificationService(api: any) {
|
|
|
45
40
|
return api.config?.plugins?.entries?.twindex?.config?.frequency ?? "periodic";
|
|
46
41
|
}
|
|
47
42
|
|
|
43
|
+
function getChatTarget(): string | undefined {
|
|
44
|
+
return api.config?.plugins?.entries?.twindex?.config?.chatTarget;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getChatChannel(): string {
|
|
48
|
+
return api.config?.plugins?.entries?.twindex?.config?.chatChannel ?? "telegram";
|
|
49
|
+
}
|
|
50
|
+
|
|
48
51
|
const logger = api.logger;
|
|
49
52
|
|
|
50
53
|
async function poll() {
|
|
@@ -55,6 +58,13 @@ export function createNotificationService(api: any) {
|
|
|
55
58
|
const apiKey = getApiKey();
|
|
56
59
|
if (!apiKey) return;
|
|
57
60
|
|
|
61
|
+
const target = getChatTarget();
|
|
62
|
+
if (!target) {
|
|
63
|
+
logger?.warn?.("Twindex: no chatTarget configured — skipping delivery");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const channel = getChatChannel();
|
|
67
|
+
|
|
58
68
|
const notifications = await twindex.getNotifications(apiKey);
|
|
59
69
|
if (!notifications || notifications.length === 0) return;
|
|
60
70
|
|
|
@@ -69,7 +79,7 @@ export function createNotificationService(api: any) {
|
|
|
69
79
|
`New Twindex update for ${notif.brand} (${notif.event_type}): ${notif.summary}\n` +
|
|
70
80
|
"Share this with the user naturally. If they seem busy, keep it brief.";
|
|
71
81
|
|
|
72
|
-
const delivered = await
|
|
82
|
+
const delivered = await sendMessage(message, channel, target);
|
|
73
83
|
if (delivered) {
|
|
74
84
|
try {
|
|
75
85
|
await twindex.markRead(apiKey, [notif.id]);
|
|
@@ -77,7 +87,7 @@ export function createNotificationService(api: any) {
|
|
|
77
87
|
// Non-fatal — delivered but read status will catch up
|
|
78
88
|
}
|
|
79
89
|
} else {
|
|
80
|
-
logger?.warn?.("Twindex:
|
|
90
|
+
logger?.warn?.("Twindex: message delivery failed, will retry next poll");
|
|
81
91
|
break; // Don't pile up failed deliveries
|
|
82
92
|
}
|
|
83
93
|
}
|
|
@@ -92,7 +102,12 @@ export function createNotificationService(api: any) {
|
|
|
92
102
|
id: "twindex-notifications",
|
|
93
103
|
|
|
94
104
|
start() {
|
|
95
|
-
|
|
105
|
+
// Clear any stale timer from a previous gateway reload
|
|
106
|
+
if (timer) {
|
|
107
|
+
clearInterval(timer);
|
|
108
|
+
timer = null;
|
|
109
|
+
}
|
|
110
|
+
|
|
96
111
|
const apiKey = getApiKey();
|
|
97
112
|
if (!apiKey) {
|
|
98
113
|
logger?.info?.("Twindex: no API key — poll service waiting for setup");
|