@xquik/tweetclaw 1.6.18 → 1.6.20
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/dist/request.js +65 -2
- package/dist/request.js.map +1 -1
- package/dist/tools/tweetclaw.js +23 -13
- package/dist/tools/tweetclaw.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/src/request.ts +74 -4
- package/src/tools/tweetclaw.ts +23 -13
package/dist/request.js
CHANGED
|
@@ -6,6 +6,7 @@ const BEARER_PREFIX = 'Bearer ';
|
|
|
6
6
|
const API_KEY_PREFIX = 'xq_';
|
|
7
7
|
const API_V1_PREFIX = '/api/v1/';
|
|
8
8
|
const SUPPORT_TICKETS_PREFIX = '/api/v1/support/tickets';
|
|
9
|
+
const MAX_SAFE_ERROR_CODE_LENGTH = 80;
|
|
9
10
|
function buildAuthHeader(credential) {
|
|
10
11
|
if (credential.startsWith(API_KEY_PREFIX)) {
|
|
11
12
|
return { [API_KEY_HEADER]: credential };
|
|
@@ -84,6 +85,68 @@ function validateRequestPath(method, path) {
|
|
|
84
85
|
throw new Error('Agent-prohibited endpoint. Account connection and re-authentication must be done through the Xquik dashboard at dashboard.xquik.com, not through the agent.');
|
|
85
86
|
}
|
|
86
87
|
}
|
|
88
|
+
async function readResponseJson(response) {
|
|
89
|
+
try {
|
|
90
|
+
return await response.json();
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function isAsciiLetter(character) {
|
|
97
|
+
const lower = character.toLowerCase();
|
|
98
|
+
return lower >= 'a' && lower <= 'z';
|
|
99
|
+
}
|
|
100
|
+
function isAsciiDigit(character) {
|
|
101
|
+
return character >= '0' && character <= '9';
|
|
102
|
+
}
|
|
103
|
+
function isSafeErrorCodeCharacter(character) {
|
|
104
|
+
return isAsciiLetter(character)
|
|
105
|
+
|| isAsciiDigit(character)
|
|
106
|
+
|| character === '_'
|
|
107
|
+
|| character === '.'
|
|
108
|
+
|| character === ':'
|
|
109
|
+
|| character === '-';
|
|
110
|
+
}
|
|
111
|
+
function isSafeErrorCode(value) {
|
|
112
|
+
if (value.length === 0
|
|
113
|
+
|| value.length > MAX_SAFE_ERROR_CODE_LENGTH
|
|
114
|
+
|| !isAsciiLetter(value.slice(0, 1))) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
for (const character of value) {
|
|
118
|
+
if (!isSafeErrorCodeCharacter(character)) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
function stringErrorCode(value) {
|
|
125
|
+
if (typeof value !== 'object' || value === null) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
if ('error' in value && typeof value.error === 'string') {
|
|
129
|
+
return value.error;
|
|
130
|
+
}
|
|
131
|
+
if ('code' in value && typeof value.code === 'string') {
|
|
132
|
+
return value.code;
|
|
133
|
+
}
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
function safeErrorCode(value) {
|
|
137
|
+
const code = stringErrorCode(value);
|
|
138
|
+
return code !== undefined && isSafeErrorCode(code) ? code : undefined;
|
|
139
|
+
}
|
|
140
|
+
function formatApiError(response, payload) {
|
|
141
|
+
const status = response.statusText.length > 0
|
|
142
|
+
? `${String(response.status)} ${response.statusText}`
|
|
143
|
+
: String(response.status);
|
|
144
|
+
const code = safeErrorCode(payload);
|
|
145
|
+
if (code === undefined) {
|
|
146
|
+
return `API request failed: ${status}`;
|
|
147
|
+
}
|
|
148
|
+
return `API request failed: ${status} (${code})`;
|
|
149
|
+
}
|
|
87
150
|
function createProxiedRequest(baseUrl, credential, fetchFunction = fetch) {
|
|
88
151
|
return async (path, options) => {
|
|
89
152
|
const method = options?.method ?? 'GET';
|
|
@@ -95,9 +158,9 @@ function createProxiedRequest(baseUrl, credential, fetchFunction = fetch) {
|
|
|
95
158
|
method,
|
|
96
159
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
97
160
|
});
|
|
98
|
-
const json = await response
|
|
161
|
+
const json = await readResponseJson(response);
|
|
99
162
|
if (!response.ok) {
|
|
100
|
-
throw new Error(
|
|
163
|
+
throw new Error(formatApiError(response, json));
|
|
101
164
|
}
|
|
102
165
|
return json;
|
|
103
166
|
};
|
package/dist/request.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,MAAM,mBAAmB,GAAG,cAAc,CAAC;AAC3C,MAAM,cAAc,GAAG,WAAW,CAAC;AACnC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAC7C,MAAM,aAAa,GAAG,SAAS,CAAC;AAChC,MAAM,cAAc,GAAG,KAAK,CAAC;AAC7B,MAAM,aAAa,GAAG,UAAU,CAAC;AACjC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/tweetclaw.js
CHANGED
|
@@ -40,19 +40,29 @@ async function handleTweetclaw(options) {
|
|
|
40
40
|
try {
|
|
41
41
|
const requestInfo = resolveCatalogRequest(params, { mppMode });
|
|
42
42
|
const request = createProxiedRequest(baseUrl, credential, fetchFunction);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
43
|
+
let rejectTimeout = (reason) => {
|
|
44
|
+
throw reason;
|
|
45
|
+
};
|
|
46
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
47
|
+
rejectTimeout = reject;
|
|
48
|
+
});
|
|
49
|
+
const timeoutId = setTimeout(() => {
|
|
50
|
+
rejectTimeout(new Error(`Execution timed out after ${String(timeoutMs / MS_PER_SECOND)}s`));
|
|
51
|
+
}, timeoutMs);
|
|
52
|
+
try {
|
|
53
|
+
const result = await Promise.race([
|
|
54
|
+
request(requestInfo.path, {
|
|
55
|
+
...(requestInfo.body === undefined ? {} : { body: requestInfo.body }),
|
|
56
|
+
method: requestInfo.method,
|
|
57
|
+
...(requestInfo.query === undefined ? {} : { query: requestInfo.query }),
|
|
58
|
+
}),
|
|
59
|
+
timeoutPromise,
|
|
60
|
+
]);
|
|
61
|
+
return successResult(result);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
clearTimeout(timeoutId);
|
|
65
|
+
}
|
|
56
66
|
}
|
|
57
67
|
catch (error) {
|
|
58
68
|
return errorResult(error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tweetclaw.js","sourceRoot":"","sources":["../../src/tools/tweetclaw.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGzD,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+B1B,CAAC;AAEH,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,MAAM,aAAa,GAAG,IAAI,CAAC;AAW3B,KAAK,UAAU,eAAe,CAAC,OAAmC;IAChE,MAAM,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,OAAO,GAAG,KAAK,EACf,MAAM,EACN,SAAS,GAAG,oBAAoB,GACjC,GAAG,OAAO,CAAC;IAEZ,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,qBAAqB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAoB,oBAAoB,CAAC,OAAO,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QAC1F,
|
|
1
|
+
{"version":3,"file":"tweetclaw.js","sourceRoot":"","sources":["../../src/tools/tweetclaw.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGzD,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+B1B,CAAC;AAEH,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,MAAM,aAAa,GAAG,IAAI,CAAC;AAW3B,KAAK,UAAU,eAAe,CAAC,OAAmC;IAChE,MAAM,EACJ,OAAO,EACP,UAAU,EACV,aAAa,EACb,OAAO,GAAG,KAAK,EACf,MAAM,EACN,SAAS,GAAG,oBAAoB,GACjC,GAAG,OAAO,CAAC;IAEZ,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,qBAAqB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAoB,oBAAoB,CAAC,OAAO,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QAC1F,IAAI,aAAa,GAA4B,CAAC,MAAM,EAAE,EAAE;YACtD,MAAM,MAAM,CAAC;QACf,CAAC,CAAC;QACF,MAAM,cAAc,GAAG,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;YAC7D,aAAa,GAAG,MAAM,CAAC;QACzB,CAAC,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,aAAa,CAAC,IAAI,KAAK,CAAC,6BAA6B,MAAM,CAAC,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9F,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,IAAI,CAAC;YACH,MAAM,MAAM,GAAY,MAAM,OAAO,CAAC,IAAI,CAAC;gBACzC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE;oBACxB,GAAG,CAAC,WAAW,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;oBACrE,MAAM,EAAE,WAAW,CAAC,MAAM;oBAC1B,GAAG,CAAC,WAAW,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC;iBACzE,CAAC;gBACF,cAAc;aACf,CAAC,CAAC;YAEH,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,SAAS,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,aAAa,EAAE,CAAC"}
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xquik/tweetclaw",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.20",
|
|
4
4
|
"description": "Post tweets, reply, like, retweet, follow, DM & more from OpenClaw through structured Xquik endpoints.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"install": {
|
|
34
34
|
"defaultChoice": "npm",
|
|
35
|
-
"npmSpec": "@xquik/tweetclaw@1.6.
|
|
35
|
+
"npmSpec": "@xquik/tweetclaw@1.6.20",
|
|
36
36
|
"minHostVersion": ">=2026.5.4"
|
|
37
37
|
}
|
|
38
38
|
},
|
package/src/request.ts
CHANGED
|
@@ -8,6 +8,7 @@ const BEARER_PREFIX = 'Bearer ';
|
|
|
8
8
|
const API_KEY_PREFIX = 'xq_';
|
|
9
9
|
const API_V1_PREFIX = '/api/v1/';
|
|
10
10
|
const SUPPORT_TICKETS_PREFIX = '/api/v1/support/tickets';
|
|
11
|
+
const MAX_SAFE_ERROR_CODE_LENGTH = 80;
|
|
11
12
|
|
|
12
13
|
function buildAuthHeader(credential: string): Record<string, string> {
|
|
13
14
|
if (credential.startsWith(API_KEY_PREFIX)) {
|
|
@@ -103,6 +104,77 @@ function validateRequestPath(method: string, path: string): void {
|
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
async function readResponseJson(response: Response): Promise<unknown> {
|
|
108
|
+
try {
|
|
109
|
+
return await response.json();
|
|
110
|
+
} catch {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isAsciiLetter(character: string): boolean {
|
|
116
|
+
const lower = character.toLowerCase();
|
|
117
|
+
return lower >= 'a' && lower <= 'z';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function isAsciiDigit(character: string): boolean {
|
|
121
|
+
return character >= '0' && character <= '9';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function isSafeErrorCodeCharacter(character: string): boolean {
|
|
125
|
+
return isAsciiLetter(character)
|
|
126
|
+
|| isAsciiDigit(character)
|
|
127
|
+
|| character === '_'
|
|
128
|
+
|| character === '.'
|
|
129
|
+
|| character === ':'
|
|
130
|
+
|| character === '-';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function isSafeErrorCode(value: string): boolean {
|
|
134
|
+
if (
|
|
135
|
+
value.length === 0
|
|
136
|
+
|| value.length > MAX_SAFE_ERROR_CODE_LENGTH
|
|
137
|
+
|| !isAsciiLetter(value.slice(0, 1))
|
|
138
|
+
) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
for (const character of value) {
|
|
142
|
+
if (!isSafeErrorCodeCharacter(character)) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function stringErrorCode(value: unknown): string | undefined {
|
|
150
|
+
if (typeof value !== 'object' || value === null) {
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
if ('error' in value && typeof value.error === 'string') {
|
|
154
|
+
return value.error;
|
|
155
|
+
}
|
|
156
|
+
if ('code' in value && typeof value.code === 'string') {
|
|
157
|
+
return value.code;
|
|
158
|
+
}
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function safeErrorCode(value: unknown): string | undefined {
|
|
163
|
+
const code = stringErrorCode(value);
|
|
164
|
+
return code !== undefined && isSafeErrorCode(code) ? code : undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function formatApiError(response: Response, payload: unknown): string {
|
|
168
|
+
const status = response.statusText.length > 0
|
|
169
|
+
? `${String(response.status)} ${response.statusText}`
|
|
170
|
+
: String(response.status);
|
|
171
|
+
const code = safeErrorCode(payload);
|
|
172
|
+
if (code === undefined) {
|
|
173
|
+
return `API request failed: ${status}`;
|
|
174
|
+
}
|
|
175
|
+
return `API request failed: ${status} (${code})`;
|
|
176
|
+
}
|
|
177
|
+
|
|
106
178
|
function createProxiedRequest(
|
|
107
179
|
baseUrl: string,
|
|
108
180
|
credential: string,
|
|
@@ -118,11 +190,9 @@ function createProxiedRequest(
|
|
|
118
190
|
method,
|
|
119
191
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
120
192
|
});
|
|
121
|
-
const json: unknown = await response
|
|
193
|
+
const json: unknown = await readResponseJson(response);
|
|
122
194
|
if (!response.ok) {
|
|
123
|
-
throw new Error(
|
|
124
|
-
`API request failed: ${String(response.status)} ${response.statusText} - ${JSON.stringify(json)}`,
|
|
125
|
-
);
|
|
195
|
+
throw new Error(formatApiError(response, json));
|
|
126
196
|
}
|
|
127
197
|
return json;
|
|
128
198
|
};
|
package/src/tools/tweetclaw.ts
CHANGED
|
@@ -61,20 +61,30 @@ async function handleTweetclaw(options: Readonly<TweetclawOptions>): Promise<Too
|
|
|
61
61
|
try {
|
|
62
62
|
const requestInfo = resolveCatalogRequest(params, { mppMode });
|
|
63
63
|
const request: RequestFunction = createProxiedRequest(baseUrl, credential, fetchFunction);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}, timeoutMs);
|
|
74
|
-
}),
|
|
75
|
-
]);
|
|
64
|
+
let rejectTimeout: (reason: Error) => void = (reason) => {
|
|
65
|
+
throw reason;
|
|
66
|
+
};
|
|
67
|
+
const timeoutPromise = new Promise<never>((_resolve, reject) => {
|
|
68
|
+
rejectTimeout = reject;
|
|
69
|
+
});
|
|
70
|
+
const timeoutId = setTimeout(() => {
|
|
71
|
+
rejectTimeout(new Error(`Execution timed out after ${String(timeoutMs / MS_PER_SECOND)}s`));
|
|
72
|
+
}, timeoutMs);
|
|
76
73
|
|
|
77
|
-
|
|
74
|
+
try {
|
|
75
|
+
const result: unknown = await Promise.race([
|
|
76
|
+
request(requestInfo.path, {
|
|
77
|
+
...(requestInfo.body === undefined ? {} : { body: requestInfo.body }),
|
|
78
|
+
method: requestInfo.method,
|
|
79
|
+
...(requestInfo.query === undefined ? {} : { query: requestInfo.query }),
|
|
80
|
+
}),
|
|
81
|
+
timeoutPromise,
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
return successResult(result);
|
|
85
|
+
} finally {
|
|
86
|
+
clearTimeout(timeoutId);
|
|
87
|
+
}
|
|
78
88
|
} catch (error: unknown) {
|
|
79
89
|
return errorResult(error);
|
|
80
90
|
}
|