@zlr_236/popo 0.0.4 → 0.0.6

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zlr_236/popo",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "type": "module",
5
5
  "description": "OpenClaw POPO channel plugin",
6
6
  "license": "MIT",
package/src/bot.ts CHANGED
@@ -27,7 +27,7 @@ export type PopoMessageEvent = {
27
27
  from: string; // Sender email
28
28
  sessionId: string; // P2P=email, group=groupId
29
29
  notify: string; // Message content
30
- msgType?: string; // text, image, file, etc.
30
+ msgType?: string | number; // text, image, file, etc.
31
31
  fileId?: string; // File message ID
32
32
  timestamp?: number;
33
33
  groupId?: string;
@@ -51,7 +51,10 @@ export type PopoActionEvent = {
51
51
  };
52
52
  };
53
53
 
54
- function parseMessageContent(notify: string, msgType?: string): string {
54
+ function parseMessageContent(
55
+ notify: string,
56
+ msgType?: string | number,
57
+ ): string {
55
58
  if (msgType === "text" || !msgType) {
56
59
  return notify;
57
60
  }
@@ -62,15 +65,19 @@ function parseMessageContent(notify: string, msgType?: string): string {
62
65
  /**
63
66
  * Infer placeholder text based on message type.
64
67
  */
65
- function inferPlaceholder(msgType?: string): string {
68
+ function inferPlaceholder(msgType?: string | number): string {
66
69
  switch (msgType) {
67
70
  case "image":
71
+ case 171:
68
72
  return "<media:image>";
69
73
  case "file":
74
+ case 171:
70
75
  return "<media:document>";
71
76
  case "audio":
77
+ case 171:
72
78
  return "<media:audio>";
73
79
  case "video":
80
+ case 142:
74
81
  return "<media:video>";
75
82
  default:
76
83
  return "";
@@ -88,17 +95,10 @@ async function resolvePopoMediaList(params: {
88
95
  }): Promise<PopoMediaInfo[]> {
89
96
  const { cfg, event, maxBytes, log } = params;
90
97
  const { msgType, fileId, fileInfo } = event.eventData;
91
- // Write urlResult to res.txt
92
- const __filename = fileURLToPath(import.meta.url);
93
- const __dirname = dirname(__filename);
94
- const resFilePath = join(__dirname, "res.txt");
95
- await fs.writeFile(
96
- resFilePath,
97
- JSON.stringify(event.eventData, null, 2),
98
- "utf-8",
99
- );
98
+ log?.(`popo: resolvePopoMediaList: ${JSON.stringify(event)}`);
99
+
100
100
  // Only process media message types
101
- const mediaTypes = ["image", "file", "audio", "video", 171];
101
+ const mediaTypes = ["image", "file", "audio", "video", 171, 142];
102
102
  if (
103
103
  !msgType ||
104
104
  !mediaTypes.includes(msgType) ||
@@ -117,15 +117,19 @@ async function resolvePopoMediaList(params: {
117
117
  fileId: fileId || fileInfo?.fileId,
118
118
  });
119
119
 
120
- // Write urlResult to res.txt
121
- const __filename = fileURLToPath(import.meta.url);
122
- const __dirname = dirname(__filename);
123
- const resFilePath = join(__dirname, "res.txt");
124
- await fs.writeFile(
125
- resFilePath,
126
- JSON.stringify(urlResult, null, 2),
127
- "utf-8",
128
- );
120
+ try {
121
+ // Write urlResult to res.txt
122
+ const __filename = fileURLToPath(import.meta.url);
123
+ const __dirname = dirname(__filename);
124
+ const resFilePath = join(__dirname, "res.txt");
125
+ await fs.writeFile(
126
+ resFilePath,
127
+ JSON.stringify(urlResult, null, 2),
128
+ "utf-8",
129
+ );
130
+ } catch (e) {
131
+ log?.(`popo: DEBUG failed to write event data: ${String(e)}`);
132
+ }
129
133
 
130
134
  if (!urlResult.success || !urlResult.downloadUrl) {
131
135
  throw new Error(urlResult.error || "Failed to get download URL");
@@ -209,7 +213,7 @@ export function parsePopoMessageEvent(
209
213
  chatType: isGroup ? "group" : "p2p",
210
214
  content,
211
215
  contentType: eventData.msgType ?? "text",
212
- fileId: eventData.fileId,
216
+ fileId: eventData.fileId || eventData.fileInfo?.fileId,
213
217
  };
214
218
  }
215
219
 
@@ -228,7 +232,7 @@ export async function handlePopoMessage(params: {
228
232
  const isGroup = ctx.chatType === "group";
229
233
 
230
234
  log(
231
- `popo: received message from ${ctx.senderEmail} in ${ctx.sessionId} (${ctx.chatType})`,
235
+ `popo: received message from ${ctx.senderEmail} in ${ctx.sessionId} (${ctx.chatType}) ${JSON.stringify(event)}`,
232
236
  );
233
237
 
234
238
  const historyLimit = Math.max(
package/src/monitor.ts CHANGED
@@ -1,6 +1,13 @@
1
1
  import http from "http";
2
- import { registerPluginHttpRoute, normalizePluginHttpPath } from "openclaw/plugin-sdk";
3
- import type { ClawdbotConfig, RuntimeEnv, HistoryEntry } from "openclaw/plugin-sdk";
2
+ import {
3
+ registerPluginHttpRoute,
4
+ normalizePluginHttpPath,
5
+ } from "openclaw/plugin-sdk";
6
+ import type {
7
+ ClawdbotConfig,
8
+ RuntimeEnv,
9
+ HistoryEntry,
10
+ } from "openclaw/plugin-sdk";
4
11
  import type { PopoConfig } from "./types.js";
5
12
  import { resolvePopoCredentials } from "./accounts.js";
6
13
  import { verifySignature, decryptMessage, encryptMessage } from "./crypto.js";
@@ -24,7 +31,9 @@ function readRequestBody(req: http.IncomingMessage): Promise<string> {
24
31
  });
25
32
  }
26
33
 
27
- export async function monitorPopoProvider(opts: MonitorPopoOpts = {}): Promise<void> {
34
+ export async function monitorPopoProvider(
35
+ opts: MonitorPopoOpts = {},
36
+ ): Promise<void> {
28
37
  const cfg = opts.config;
29
38
  if (!cfg) {
30
39
  throw new Error("Config is required for POPO monitor");
@@ -33,7 +42,9 @@ export async function monitorPopoProvider(opts: MonitorPopoOpts = {}): Promise<v
33
42
  const popoCfg = cfg.channels?.popo as PopoConfig | undefined;
34
43
  const creds = resolvePopoCredentials(popoCfg);
35
44
  if (!creds) {
36
- throw new Error("POPO credentials not configured (appKey, appSecret required)");
45
+ throw new Error(
46
+ "POPO credentials not configured (appKey, appSecret required)",
47
+ );
37
48
  }
38
49
 
39
50
  const log = opts.runtime?.log ?? console.log;
@@ -50,7 +61,8 @@ export async function monitorPopoProvider(opts: MonitorPopoOpts = {}): Promise<v
50
61
  const chatHistories = new Map<string, HistoryEntry[]>();
51
62
 
52
63
  // Normalize path
53
- const normalizedPath = normalizePluginHttpPath(webhookPath, "/popo/events") ?? "/popo/events";
64
+ const normalizedPath =
65
+ normalizePluginHttpPath(webhookPath, "/popo/events") ?? "/popo/events";
54
66
 
55
67
  // Register HTTP route to gateway
56
68
  const unregisterHttp = registerPluginHttpRoute({
@@ -79,7 +91,9 @@ export async function monitorPopoProvider(opts: MonitorPopoOpts = {}): Promise<v
79
91
  const timestamp = url.searchParams.get("timestamp");
80
92
  const signature = url.searchParams.get("signature");
81
93
 
82
- log(`popo: URL validation attempt - nonce=${nonce}, timestamp=${timestamp}, signature=${signature}`);
94
+ log(
95
+ `popo: URL validation attempt - nonce=${nonce}, timestamp=${timestamp}, signature=${signature}`,
96
+ );
83
97
 
84
98
  if (nonce && timestamp && signature && creds.token) {
85
99
  const valid = verifySignature({
@@ -141,6 +155,31 @@ export async function monitorPopoProvider(opts: MonitorPopoOpts = {}): Promise<v
141
155
  }
142
156
 
143
157
  const event = eventData as { eventType?: string };
158
+ // Debug: write ALL events before any filtering
159
+ try {
160
+ const fsDebug = await import("node:fs/promises");
161
+ const debugPath =
162
+ "/home/node/.openclaw/workspace/popo_raw_event.json";
163
+ await fsDebug.writeFile(
164
+ debugPath,
165
+ JSON.stringify(
166
+ {
167
+ ts: new Date().toISOString(),
168
+ eventType: event.eventType,
169
+ eventData,
170
+ },
171
+ null,
172
+ 2,
173
+ ),
174
+ "utf-8",
175
+ );
176
+ log(`popo: DEBUG wrote raw event to ${debugPath}`);
177
+ } catch (e) {
178
+ log(`popo: DEBUG write failed: ${String(e)}`);
179
+ }
180
+ log(
181
+ `popo: DEBUG eventType=${event.eventType} eventData=${JSON.stringify(eventData).slice(0, 500)}`,
182
+ );
144
183
 
145
184
  // Handle valid_url event
146
185
  if (event.eventType === "valid_url") {
@@ -148,7 +187,10 @@ export async function monitorPopoProvider(opts: MonitorPopoOpts = {}): Promise<v
148
187
  const response = { eventType: "valid_url" };
149
188
 
150
189
  if (creds.aesKey) {
151
- const encrypted = encryptMessage(JSON.stringify(response), creds.aesKey);
190
+ const encrypted = encryptMessage(
191
+ JSON.stringify(response),
192
+ creds.aesKey,
193
+ );
152
194
  res.writeHead(200, { "Content-Type": "application/json" });
153
195
  res.end(JSON.stringify({ encrypt: encrypted }));
154
196
  } else {
@@ -186,7 +228,10 @@ export async function monitorPopoProvider(opts: MonitorPopoOpts = {}): Promise<v
186
228
  // Return success response
187
229
  const successResponse = { success: true };
188
230
  if (creds.aesKey) {
189
- const encrypted = encryptMessage(JSON.stringify(successResponse), creds.aesKey);
231
+ const encrypted = encryptMessage(
232
+ JSON.stringify(successResponse),
233
+ creds.aesKey,
234
+ );
190
235
  res.writeHead(200, { "Content-Type": "application/json" });
191
236
  res.end(JSON.stringify({ encrypt: encrypted }));
192
237
  } else {
package/src/types.ts CHANGED
@@ -19,7 +19,7 @@ export type PopoMessageContext = {
19
19
  senderName?: string;
20
20
  chatType: "p2p" | "group";
21
21
  content: string;
22
- contentType: string;
22
+ contentType: string | number;
23
23
  fileId?: string;
24
24
  };
25
25