@shenhh/popo 0.1.8 → 0.1.10
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/accounts.ts +1 -1
- package/src/auth.ts +20 -20
- package/src/client.ts +6 -6
- package/src/config-schema.ts +1 -1
- package/src/media.ts +24 -18
- package/src/outbound.ts +11 -1
- package/src/send.ts +24 -15
package/package.json
CHANGED
package/src/accounts.ts
CHANGED
|
@@ -17,7 +17,7 @@ export function resolvePopoCredentials(cfg?: PopoConfig): {
|
|
|
17
17
|
appSecret,
|
|
18
18
|
token: cfg?.token?.trim() || undefined,
|
|
19
19
|
aesKey: cfg?.aesKey?.trim() || undefined,
|
|
20
|
-
server: cfg?.server ?? "https://open.popo.netease.com
|
|
20
|
+
server: cfg?.server ?? "https://open.popo.netease.com",
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
|
package/src/auth.ts
CHANGED
|
@@ -54,7 +54,7 @@ async function fetchNewToken(cfg: PopoConfig): Promise<PopoToken> {
|
|
|
54
54
|
throw new Error("POPO credentials not configured");
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const response = await fetch(`${creds.server}/
|
|
57
|
+
const response = await fetch(`${creds.server}/open-apis/robots/v1/token`, {
|
|
58
58
|
method: "POST",
|
|
59
59
|
headers: {
|
|
60
60
|
"Content-Type": "application/json",
|
|
@@ -70,9 +70,9 @@ async function fetchNewToken(cfg: PopoConfig): Promise<PopoToken> {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const data = (await response.json()) as {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
errcode?: number;
|
|
74
|
+
errmsg?: string;
|
|
75
|
+
data?: {
|
|
76
76
|
accessToken: string;
|
|
77
77
|
accessExpiredAt: number;
|
|
78
78
|
refreshToken: string;
|
|
@@ -80,15 +80,15 @@ async function fetchNewToken(cfg: PopoConfig): Promise<PopoToken> {
|
|
|
80
80
|
};
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
if (data.
|
|
84
|
-
throw new Error(`POPO token request failed: ${data.
|
|
83
|
+
if (data.errcode !== 0 || !data.data) {
|
|
84
|
+
throw new Error(`POPO token request failed: ${data.errmsg || "unknown error"}`);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
return {
|
|
88
|
-
accessToken: data.
|
|
89
|
-
accessExpiredAt: data.
|
|
90
|
-
refreshToken: data.
|
|
91
|
-
refreshExpiredAt: data.
|
|
88
|
+
accessToken: data.data.accessToken,
|
|
89
|
+
accessExpiredAt: data.data.accessExpiredAt,
|
|
90
|
+
refreshToken: data.data.refreshToken,
|
|
91
|
+
refreshExpiredAt: data.data.refreshExpiredAt,
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -104,7 +104,7 @@ export async function refreshAccessToken(
|
|
|
104
104
|
throw new Error("POPO credentials not configured");
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
const response = await fetch(`${creds.server}/
|
|
107
|
+
const response = await fetch(`${creds.server}/open-apis/robots/v1/token/refresh`, {
|
|
108
108
|
method: "POST",
|
|
109
109
|
headers: {
|
|
110
110
|
"Content-Type": "application/json",
|
|
@@ -120,9 +120,9 @@ export async function refreshAccessToken(
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
const data = (await response.json()) as {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
errcode?: number;
|
|
124
|
+
errmsg?: string;
|
|
125
|
+
data?: {
|
|
126
126
|
accessToken: string;
|
|
127
127
|
accessExpiredAt: number;
|
|
128
128
|
refreshToken: string;
|
|
@@ -130,15 +130,15 @@ export async function refreshAccessToken(
|
|
|
130
130
|
};
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
-
if (data.
|
|
134
|
-
throw new Error(`POPO token refresh failed: ${data.
|
|
133
|
+
if (data.errcode !== 0 || !data.data) {
|
|
134
|
+
throw new Error(`POPO token refresh failed: ${data.errmsg || "unknown error"}`);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
return {
|
|
138
|
-
accessToken: data.
|
|
139
|
-
accessExpiredAt: data.
|
|
140
|
-
refreshToken: data.
|
|
141
|
-
refreshExpiredAt: data.
|
|
138
|
+
accessToken: data.data.accessToken,
|
|
139
|
+
accessExpiredAt: data.data.accessExpiredAt,
|
|
140
|
+
refreshToken: data.data.refreshToken,
|
|
141
|
+
refreshExpiredAt: data.data.refreshExpiredAt,
|
|
142
142
|
};
|
|
143
143
|
}
|
|
144
144
|
|
package/src/client.ts
CHANGED
|
@@ -3,9 +3,9 @@ import { resolvePopoCredentials } from "./accounts.js";
|
|
|
3
3
|
import { getAccessToken } from "./auth.js";
|
|
4
4
|
|
|
5
5
|
export type PopoApiResponse<T = unknown> = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
errcode: number;
|
|
7
|
+
errmsg: string;
|
|
8
|
+
data?: T;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -27,7 +27,7 @@ export async function popoRequest<T = unknown>(params: {
|
|
|
27
27
|
const url = `${creds.server}${path}`;
|
|
28
28
|
|
|
29
29
|
const headers: Record<string, string> = {
|
|
30
|
-
|
|
30
|
+
"Open-Access-Token": accessToken,
|
|
31
31
|
"Content-Type": "application/json",
|
|
32
32
|
};
|
|
33
33
|
|
|
@@ -64,7 +64,7 @@ export async function popoUploadRequest<T = unknown>(params: {
|
|
|
64
64
|
const response = await fetch(url, {
|
|
65
65
|
method: "POST",
|
|
66
66
|
headers: {
|
|
67
|
-
|
|
67
|
+
"Open-Access-Token": accessToken,
|
|
68
68
|
// Don't set Content-Type for FormData - fetch will set it with boundary
|
|
69
69
|
},
|
|
70
70
|
body: formData,
|
|
@@ -96,7 +96,7 @@ export async function popoDownloadRequest(params: {
|
|
|
96
96
|
const response = await fetch(url, {
|
|
97
97
|
method: "GET",
|
|
98
98
|
headers: {
|
|
99
|
-
|
|
99
|
+
"Open-Access-Token": accessToken,
|
|
100
100
|
},
|
|
101
101
|
});
|
|
102
102
|
|
package/src/config-schema.ts
CHANGED
|
@@ -46,7 +46,7 @@ export const PopoConfigSchema = z
|
|
|
46
46
|
server: z
|
|
47
47
|
.string()
|
|
48
48
|
.optional()
|
|
49
|
-
.default("https://open.popo.netease.com
|
|
49
|
+
.default("https://open.popo.netease.com"),
|
|
50
50
|
webhookPath: z.string().optional().default("/popo/events"),
|
|
51
51
|
webhookPort: z.number().int().positive().optional(),
|
|
52
52
|
dmPolicy: DmPolicySchema.optional().default("pairing"),
|
package/src/media.ts
CHANGED
|
@@ -67,19 +67,19 @@ export async function uploadFilePopo(params: {
|
|
|
67
67
|
const blob = new Blob([fileBuffer as unknown as ArrayBuffer], { type: fileType || "application/octet-stream" });
|
|
68
68
|
formData.append("file", blob, fileName);
|
|
69
69
|
|
|
70
|
-
const response = await popoUploadRequest<{
|
|
70
|
+
const response = await popoUploadRequest<{ fileKey: string; fileName: string }>({
|
|
71
71
|
cfg: popoCfg,
|
|
72
|
-
path: "/im/file/upload",
|
|
72
|
+
path: "/open-apis/robots/v1/im/file/upload",
|
|
73
73
|
formData,
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
if (response.
|
|
77
|
-
throw new Error(`POPO file upload failed: ${response.
|
|
76
|
+
if (response.errcode !== 0 || !response.data) {
|
|
77
|
+
throw new Error(`POPO file upload failed: ${response.errmsg || "unknown error"}`);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
return {
|
|
81
|
-
fileId: response.
|
|
82
|
-
fileName: response.
|
|
81
|
+
fileId: response.data.fileKey,
|
|
82
|
+
fileName: response.data.fileName,
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
85
|
|
|
@@ -147,23 +147,26 @@ export async function sendImagePopo(params: {
|
|
|
147
147
|
const receiverType = detectReceiverType(receiver);
|
|
148
148
|
const receiverKey = receiverType === "email" ? "receiver" : "groupId";
|
|
149
149
|
|
|
150
|
-
const response = await popoRequest<{
|
|
150
|
+
const response = await popoRequest<{ msgInfo?: Record<string, string> }>({
|
|
151
151
|
cfg: popoCfg,
|
|
152
152
|
method: "POST",
|
|
153
|
-
path: "/im/send-msg",
|
|
153
|
+
path: "/open-apis/robots/v1/im/send-msg",
|
|
154
154
|
body: {
|
|
155
155
|
[receiverKey]: receiver,
|
|
156
156
|
msgType: "image",
|
|
157
|
-
message: { fileId },
|
|
157
|
+
message: { fileKey: fileId },
|
|
158
158
|
},
|
|
159
159
|
});
|
|
160
160
|
|
|
161
|
-
if (response.
|
|
162
|
-
throw new Error(`POPO image send failed: ${response.
|
|
161
|
+
if (response.errcode !== 0) {
|
|
162
|
+
throw new Error(`POPO image send failed: ${response.errmsg || `errcode ${response.errcode}`}`);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
const msgInfo = response.data?.msgInfo ?? {};
|
|
166
|
+
const messageId = msgInfo[receiver];
|
|
167
|
+
|
|
165
168
|
return {
|
|
166
|
-
messageId
|
|
169
|
+
messageId,
|
|
167
170
|
sessionId: receiver,
|
|
168
171
|
};
|
|
169
172
|
}
|
|
@@ -190,23 +193,26 @@ export async function sendFilePopo(params: {
|
|
|
190
193
|
const receiverType = detectReceiverType(receiver);
|
|
191
194
|
const receiverKey = receiverType === "email" ? "receiver" : "groupId";
|
|
192
195
|
|
|
193
|
-
const response = await popoRequest<{
|
|
196
|
+
const response = await popoRequest<{ msgInfo?: Record<string, string> }>({
|
|
194
197
|
cfg: popoCfg,
|
|
195
198
|
method: "POST",
|
|
196
|
-
path: "/im/send-msg",
|
|
199
|
+
path: "/open-apis/robots/v1/im/send-msg",
|
|
197
200
|
body: {
|
|
198
201
|
[receiverKey]: receiver,
|
|
199
202
|
msgType: "file",
|
|
200
|
-
message: { fileId },
|
|
203
|
+
message: { fileKey: fileId },
|
|
201
204
|
},
|
|
202
205
|
});
|
|
203
206
|
|
|
204
|
-
if (response.
|
|
205
|
-
throw new Error(`POPO file send failed: ${response.
|
|
207
|
+
if (response.errcode !== 0) {
|
|
208
|
+
throw new Error(`POPO file send failed: ${response.errmsg || `errcode ${response.errcode}`}`);
|
|
206
209
|
}
|
|
207
210
|
|
|
211
|
+
const msgInfo = response.data?.msgInfo ?? {};
|
|
212
|
+
const messageId = msgInfo[receiver];
|
|
213
|
+
|
|
208
214
|
return {
|
|
209
|
-
messageId
|
|
215
|
+
messageId,
|
|
210
216
|
sessionId: receiver,
|
|
211
217
|
};
|
|
212
218
|
}
|
package/src/outbound.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChannelOutboundAdapter } from "openclaw/plugin-sdk";
|
|
2
2
|
import { getPopoRuntime } from "./runtime.js";
|
|
3
|
-
import { sendMessagePopo } from "./send.js";
|
|
3
|
+
import { sendMessagePopo, sendCardPopo } from "./send.js";
|
|
4
4
|
import { sendMediaPopo } from "./media.js";
|
|
5
5
|
|
|
6
6
|
export const popoOutbound: ChannelOutboundAdapter = {
|
|
@@ -37,4 +37,14 @@ export const popoOutbound: ChannelOutboundAdapter = {
|
|
|
37
37
|
const result = await sendMessagePopo({ cfg, to, text: text ?? "" });
|
|
38
38
|
return { channel: "popo", ...result };
|
|
39
39
|
},
|
|
40
|
+
|
|
41
|
+
sendCard: async ({ cfg, to, card }) => {
|
|
42
|
+
const { templateUuid, instanceUuid, publicVariableMap } = card as {
|
|
43
|
+
templateUuid: string;
|
|
44
|
+
instanceUuid: string;
|
|
45
|
+
publicVariableMap?: Record<string, unknown>;
|
|
46
|
+
};
|
|
47
|
+
const result = await sendCardPopo({ cfg, to, templateUuid, instanceUuid, publicVariableMap });
|
|
48
|
+
return { channel: "popo", ...result };
|
|
49
|
+
},
|
|
40
50
|
};
|
package/src/send.ts
CHANGED
|
@@ -40,10 +40,10 @@ export async function sendMessagePopo(params: SendPopoMessageParams): Promise<Po
|
|
|
40
40
|
message.isAtAll = true;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const response = await popoRequest<{
|
|
43
|
+
const response = await popoRequest<{ msgInfo?: Record<string, string> }>({
|
|
44
44
|
cfg: popoCfg,
|
|
45
45
|
method: "POST",
|
|
46
|
-
path: "/im/send-msg",
|
|
46
|
+
path: "/open-apis/robots/v1/im/send-msg",
|
|
47
47
|
body: {
|
|
48
48
|
[receiverKey]: receiver,
|
|
49
49
|
msgType: "text",
|
|
@@ -51,12 +51,15 @@ export async function sendMessagePopo(params: SendPopoMessageParams): Promise<Po
|
|
|
51
51
|
},
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
if (response.
|
|
55
|
-
throw new Error(`POPO send failed: ${response.
|
|
54
|
+
if (response.errcode !== 0) {
|
|
55
|
+
throw new Error(`POPO send failed: ${response.errmsg || `errcode ${response.errcode}`}`);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
const msgInfo = response.data?.msgInfo ?? {};
|
|
59
|
+
const messageId = msgInfo[receiver];
|
|
60
|
+
|
|
58
61
|
return {
|
|
59
|
-
messageId
|
|
62
|
+
messageId,
|
|
60
63
|
sessionId: receiver,
|
|
61
64
|
};
|
|
62
65
|
}
|
|
@@ -85,10 +88,10 @@ export async function sendRichTextPopo(params: SendPopoRichTextParams): Promise<
|
|
|
85
88
|
const receiverType = detectReceiverType(receiver);
|
|
86
89
|
const receiverKey = receiverType === "email" ? "receiver" : "groupId";
|
|
87
90
|
|
|
88
|
-
const response = await popoRequest<{
|
|
91
|
+
const response = await popoRequest<{ msgInfo?: Record<string, string> }>({
|
|
89
92
|
cfg: popoCfg,
|
|
90
93
|
method: "POST",
|
|
91
|
-
path: "/im/send-msg",
|
|
94
|
+
path: "/open-apis/robots/v1/im/send-msg",
|
|
92
95
|
body: {
|
|
93
96
|
[receiverKey]: receiver,
|
|
94
97
|
msgType: "rich_text",
|
|
@@ -96,12 +99,15 @@ export async function sendRichTextPopo(params: SendPopoRichTextParams): Promise<
|
|
|
96
99
|
},
|
|
97
100
|
});
|
|
98
101
|
|
|
99
|
-
if (response.
|
|
100
|
-
throw new Error(`POPO rich text send failed: ${response.
|
|
102
|
+
if (response.errcode !== 0) {
|
|
103
|
+
throw new Error(`POPO rich text send failed: ${response.errmsg || `errcode ${response.errcode}`}`);
|
|
101
104
|
}
|
|
102
105
|
|
|
106
|
+
const msgInfo = response.data?.msgInfo ?? {};
|
|
107
|
+
const messageId = msgInfo[receiver];
|
|
108
|
+
|
|
103
109
|
return {
|
|
104
|
-
messageId
|
|
110
|
+
messageId,
|
|
105
111
|
sessionId: receiver,
|
|
106
112
|
};
|
|
107
113
|
}
|
|
@@ -132,10 +138,10 @@ export async function sendCardPopo(params: SendPopoCardParams): Promise<PopoSend
|
|
|
132
138
|
const receiverType = detectReceiverType(receiver);
|
|
133
139
|
const receiverKey = receiverType === "email" ? "receiver" : "groupId";
|
|
134
140
|
|
|
135
|
-
const response = await popoRequest<{
|
|
141
|
+
const response = await popoRequest<{ msgInfo?: Record<string, string> }>({
|
|
136
142
|
cfg: popoCfg,
|
|
137
143
|
method: "POST",
|
|
138
|
-
path: "/im/send-msg",
|
|
144
|
+
path: "/open-apis/robots/v1/im/send-msg",
|
|
139
145
|
body: {
|
|
140
146
|
[receiverKey]: receiver,
|
|
141
147
|
msgType: "card",
|
|
@@ -147,12 +153,15 @@ export async function sendCardPopo(params: SendPopoCardParams): Promise<PopoSend
|
|
|
147
153
|
},
|
|
148
154
|
});
|
|
149
155
|
|
|
150
|
-
if (response.
|
|
151
|
-
throw new Error(`POPO card send failed: ${response.
|
|
156
|
+
if (response.errcode !== 0) {
|
|
157
|
+
throw new Error(`POPO card send failed: ${response.errmsg || `errcode ${response.errcode}`}`);
|
|
152
158
|
}
|
|
153
159
|
|
|
160
|
+
const msgInfo = response.data?.msgInfo ?? {};
|
|
161
|
+
const messageId = msgInfo[receiver];
|
|
162
|
+
|
|
154
163
|
return {
|
|
155
|
-
messageId
|
|
164
|
+
messageId,
|
|
156
165
|
sessionId: receiver,
|
|
157
166
|
};
|
|
158
167
|
}
|