@a2hmarket/a2hmarket 1.3.3 โ 1.3.5
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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/oss.ts +2 -0
- package/src/pending-welcome.ts +95 -28
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/src/oss.ts
CHANGED
|
@@ -26,6 +26,8 @@ const MIME_MAP: Record<string, string> = {
|
|
|
26
26
|
".txt": "text/plain", ".csv": "text/csv", ".md": "text/markdown",
|
|
27
27
|
// archives
|
|
28
28
|
".zip": "application/zip", ".tar": "application/x-tar", ".gz": "application/gzip",
|
|
29
|
+
// audio
|
|
30
|
+
".mp3": "audio/mpeg",
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
const PROFILE_QR_MIME: Record<string, string> = {
|
package/src/pending-welcome.ts
CHANGED
|
@@ -49,32 +49,93 @@ export function deletePendingWelcome(): void {
|
|
|
49
49
|
|
|
50
50
|
const WELCOME_TITLE = "๐ A2H Market ๆไปถๅทฒๅฐฑ็ปช";
|
|
51
51
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
52
|
+
const AUTH_API_URL = "https://web.a2hmarket.ai";
|
|
53
|
+
const LOGIN_URL = "https://a2hmarket.ai";
|
|
54
|
+
|
|
55
|
+
async function generateAuthUrl(): Promise<string | null> {
|
|
56
|
+
try {
|
|
57
|
+
const { networkInterfaces } = await import("node:os");
|
|
58
|
+
const { createHash, randomBytes } = await import("node:crypto");
|
|
59
|
+
|
|
60
|
+
let mac = "00:00:00:00:00:00";
|
|
61
|
+
const ifaces = networkInterfaces();
|
|
62
|
+
for (const name of Object.keys(ifaces)) {
|
|
63
|
+
for (const iface of ifaces[name] ?? []) {
|
|
64
|
+
if (!iface.internal && iface.mac && iface.mac !== "00:00:00:00:00:00") {
|
|
65
|
+
mac = iface.mac;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (mac !== "00:00:00:00:00:00") break;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const timestamp = String(Math.floor(Date.now() / 1000));
|
|
73
|
+
try {
|
|
74
|
+
const formData = new URLSearchParams({ timestamp, mac });
|
|
75
|
+
const resp = await fetch(`${AUTH_API_URL}/v1/auth/init-login`, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
78
|
+
body: formData.toString(),
|
|
79
|
+
});
|
|
80
|
+
const data = (await resp.json()) as { code?: string; url?: string };
|
|
81
|
+
if (data.url) return data.url;
|
|
82
|
+
} catch {
|
|
83
|
+
// fallback to local generation
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const randomHex = randomBytes(32).toString("hex");
|
|
87
|
+
const macClean = mac.replace(/:/g, "");
|
|
88
|
+
const raw = `${randomHex}_${timestamp}_${macClean}`;
|
|
89
|
+
const code = createHash("md5").update(raw).digest("hex");
|
|
90
|
+
return `${LOGIN_URL}/authcode?code=${code}`;
|
|
91
|
+
} catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function buildFeishuElements(authUrl: string | null) {
|
|
97
|
+
const elements = [
|
|
98
|
+
{
|
|
99
|
+
tag: "markdown" as const,
|
|
100
|
+
content:
|
|
101
|
+
"ๆๆฏไฝ ็ **A2H Market** AI ๅฉๆ๏ผๅฏไปฅๅธฎไฝ ๏ผ\n" +
|
|
102
|
+
"๐ฆ ๅๅธๅๅใๆต่งๅธๅบ\n" +
|
|
103
|
+
"๐ฌ ่ชๅจไธๅ
ถไป Agent ่ฐๅคๅๅ\n" +
|
|
104
|
+
"๐ ็ฎก็่ฎขๅใๅค็ๆฏไป",
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
if (authUrl) {
|
|
108
|
+
elements.push({
|
|
109
|
+
tag: "markdown" as const,
|
|
110
|
+
content: `---\n๐ **[็นๅป่ฟ้ๅฎๆๆๆ็ปๅฝ](${authUrl})**`,
|
|
111
|
+
});
|
|
112
|
+
} else {
|
|
113
|
+
elements.push({
|
|
114
|
+
tag: "markdown" as const,
|
|
115
|
+
content: '---\n๐ ้ฆๆฌกไฝฟ็จ่ฏทๅ้ **"็ปๅฝ A2H Market"** ๅฎๆๆๆ',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return elements;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function buildWelcomeText(authUrl: string | null): string {
|
|
122
|
+
const lines = [
|
|
123
|
+
`**${WELCOME_TITLE}**`,
|
|
124
|
+
"",
|
|
125
|
+
"ๆๆฏไฝ ็ A2H Market AI ๅฉๆ๏ผๅฏไปฅๅธฎไฝ ๏ผ",
|
|
126
|
+
"๐ฆ ๅๅธๅๅใๆต่งๅธๅบ",
|
|
127
|
+
"๐ฌ ่ชๅจไธๅ
ถไป Agent ่ฐๅคๅๅ",
|
|
128
|
+
"๐ ็ฎก็่ฎขๅใๅค็ๆฏไป",
|
|
129
|
+
"",
|
|
130
|
+
"---",
|
|
131
|
+
];
|
|
132
|
+
if (authUrl) {
|
|
133
|
+
lines.push(`๐ ็นๅปๅฎๆๆๆ็ปๅฝ: ${authUrl}`);
|
|
134
|
+
} else {
|
|
135
|
+
lines.push('๐ ้ฆๆฌกไฝฟ็จ่ฏทๅ้ "็ปๅฝ A2H Market" ๅฎๆๆๆ');
|
|
136
|
+
}
|
|
137
|
+
return lines.join("\n");
|
|
138
|
+
}
|
|
78
139
|
|
|
79
140
|
// โโ Send Welcome โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
80
141
|
|
|
@@ -92,6 +153,12 @@ export async function sendWelcome(
|
|
|
92
153
|
channelCfg: Record<string, unknown>,
|
|
93
154
|
log: WelcomeLog,
|
|
94
155
|
): Promise<boolean> {
|
|
156
|
+
// Generate auth URL (best-effort, falls back to text prompt)
|
|
157
|
+
const authUrl = await generateAuthUrl();
|
|
158
|
+
if (authUrl) {
|
|
159
|
+
log.info(`welcome: auth url generated`);
|
|
160
|
+
}
|
|
161
|
+
|
|
95
162
|
if (pending.channel === "feishu") {
|
|
96
163
|
if (!channelCfg.appId || !channelCfg.appSecret) {
|
|
97
164
|
log.warn("welcome: feishu channel credentials not configured, skipped");
|
|
@@ -104,7 +171,7 @@ export async function sendWelcome(
|
|
|
104
171
|
target: pending.target,
|
|
105
172
|
title: WELCOME_TITLE,
|
|
106
173
|
titleColor: "green",
|
|
107
|
-
elements:
|
|
174
|
+
elements: buildFeishuElements(authUrl),
|
|
108
175
|
});
|
|
109
176
|
return true;
|
|
110
177
|
}
|
|
@@ -137,7 +204,7 @@ export async function sendWelcome(
|
|
|
137
204
|
const resp = await fetch(`https://discord.com/api/v10/channels/${channelId}/messages`, {
|
|
138
205
|
method: "POST",
|
|
139
206
|
headers,
|
|
140
|
-
body: JSON.stringify({ content:
|
|
207
|
+
body: JSON.stringify({ content: buildWelcomeText(authUrl) }),
|
|
141
208
|
});
|
|
142
209
|
if (!resp.ok) {
|
|
143
210
|
const data = (await resp.json()) as { message?: string };
|