antenna-openclaw-plugin 1.2.17 → 1.2.18
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/index.ts +76 -0
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -1211,6 +1211,82 @@ export default function register(api: any) {
|
|
|
1211
1211
|
logger.warn("Antenna: failed to start realtime subscription, falling back to poll only:", err.message);
|
|
1212
1212
|
}
|
|
1213
1213
|
|
|
1214
|
+
// ── Supabase Realtime: event participant notifications ──────
|
|
1215
|
+
try {
|
|
1216
|
+
const epCfg = getConfig(api);
|
|
1217
|
+
const epSb = getSupabase(epCfg);
|
|
1218
|
+
epSb
|
|
1219
|
+
.channel('antenna-event-notify')
|
|
1220
|
+
.on('postgres_changes',
|
|
1221
|
+
{ event: 'INSERT', schema: 'public', table: 'event_participants' },
|
|
1222
|
+
async (payload: any) => {
|
|
1223
|
+
try {
|
|
1224
|
+
// New participant joined (pending) → notify creator
|
|
1225
|
+
if (payload.new?.status !== 'pending') return;
|
|
1226
|
+
const eventId = payload.new?.event_id;
|
|
1227
|
+
const applicantDeviceId = payload.new?.device_id;
|
|
1228
|
+
if (!eventId || !applicantDeviceId) return;
|
|
1229
|
+
|
|
1230
|
+
// Get event info via RPC
|
|
1231
|
+
const { data: event } = await epSb.rpc('get_event_by_id', { p_event_id: eventId });
|
|
1232
|
+
if (!event?.found || !event?.notify_on_join || !event?.created_by) return;
|
|
1233
|
+
|
|
1234
|
+
// Get applicant profile
|
|
1235
|
+
const { data: applicant } = await epSb.rpc('get_profile', { p_device_id: applicantDeviceId });
|
|
1236
|
+
const aName = applicant?.display_name || '某人';
|
|
1237
|
+
const aEmoji = applicant?.emoji || '👤';
|
|
1238
|
+
|
|
1239
|
+
const parts = event.created_by.split(':');
|
|
1240
|
+
if (parts.length < 2) return;
|
|
1241
|
+
notifyUser(parts[0], parts.slice(1).join(':'),
|
|
1242
|
+
`[Antenna] 📩 ${aEmoji} ${aName} 申请加入你的活动「${event.name}」\n\n用 antenna_event_scan --code ${event.code} 查看申请者名片并审批。`,
|
|
1243
|
+
logger);
|
|
1244
|
+
} catch (err: any) {
|
|
1245
|
+
logger.warn('Antenna: event participant INSERT handler error:', err.message);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
)
|
|
1249
|
+
.on('postgres_changes',
|
|
1250
|
+
{ event: 'UPDATE', schema: 'public', table: 'event_participants' },
|
|
1251
|
+
async (payload: any) => {
|
|
1252
|
+
try {
|
|
1253
|
+
// Status changed → notify the participant
|
|
1254
|
+
const oldStatus = payload.old?.status;
|
|
1255
|
+
const newStatus = payload.new?.status;
|
|
1256
|
+
if (!oldStatus || oldStatus === newStatus) return;
|
|
1257
|
+
if (newStatus !== 'active' && newStatus !== 'rejected') return;
|
|
1258
|
+
|
|
1259
|
+
const participantDeviceId = payload.new?.device_id;
|
|
1260
|
+
const eventId = payload.new?.event_id;
|
|
1261
|
+
if (!participantDeviceId || !eventId) return;
|
|
1262
|
+
|
|
1263
|
+
const { data: event } = await epSb.rpc('get_event_by_id', { p_event_id: eventId });
|
|
1264
|
+
const eventName = event?.name || '活动';
|
|
1265
|
+
|
|
1266
|
+
const parts = participantDeviceId.split(':');
|
|
1267
|
+
if (parts.length < 2) return;
|
|
1268
|
+
|
|
1269
|
+
if (newStatus === 'active') {
|
|
1270
|
+
notifyUser(parts[0], parts.slice(1).join(':'),
|
|
1271
|
+
`[Antenna] ✅ 你的申请已通过!欢迎加入「${eventName}」\n\n用 antenna_event_scan --code ${event?.code} 查看其他参与者。`,
|
|
1272
|
+
logger);
|
|
1273
|
+
} else if (newStatus === 'rejected') {
|
|
1274
|
+
notifyUser(parts[0], parts.slice(1).join(':'),
|
|
1275
|
+
`[Antenna] ❌ 你的申请未通过「${eventName}」的审核。`,
|
|
1276
|
+
logger);
|
|
1277
|
+
}
|
|
1278
|
+
} catch (err: any) {
|
|
1279
|
+
logger.warn('Antenna: event participant UPDATE handler error:', err.message);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
)
|
|
1283
|
+
.subscribe((status: string) => {
|
|
1284
|
+
logger.info(`Antenna: event participant realtime status: ${status}`);
|
|
1285
|
+
});
|
|
1286
|
+
} catch (err: any) {
|
|
1287
|
+
logger.warn('Antenna: failed to start event participant realtime:', err.message);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1214
1290
|
// ── Poll fallback: catch anything Realtime missed ───────────
|
|
1215
1291
|
_pollTimer = setInterval(async () => {
|
|
1216
1292
|
try {
|