lansenger-cli 1.0.4 → 1.1.1
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/commands/chat.js +4 -4
- package/dist/commands/media.js +6 -6
- package/dist/commands/oauth.js +126 -0
- package/dist/main.js +35 -1
- package/package.json +3 -3
package/dist/commands/chat.js
CHANGED
|
@@ -4,8 +4,8 @@ exports.registerChatCommands = registerChatCommands;
|
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
function splitMonths(startUs, endUs) {
|
|
6
6
|
const results = [];
|
|
7
|
-
const startDt = startUs ? new Date(startUs /
|
|
8
|
-
const endDt = new Date(endUs /
|
|
7
|
+
const startDt = startUs ? new Date(startUs / 1000) : new Date(2020, 0, 1);
|
|
8
|
+
const endDt = new Date(endUs / 1000);
|
|
9
9
|
let year = startDt.getFullYear();
|
|
10
10
|
let month = startDt.getMonth();
|
|
11
11
|
while (new Date(year, month, 1) <= endDt) {
|
|
@@ -64,7 +64,7 @@ function registerChatCommands(program) {
|
|
|
64
64
|
.option("--staff-id <staffId>", "Private chat partner staffId", "")
|
|
65
65
|
.option("--group-id <groupId>", "Group openId", "")
|
|
66
66
|
.option("-s, --size <size>", "Per-page count (max 100)", "100")
|
|
67
|
-
.option("--
|
|
67
|
+
.option("--cursor <cursor>", "Deep pagination cursor, first call: 0", "0")
|
|
68
68
|
.option("--start <start>", "Start time in microseconds", "0")
|
|
69
69
|
.option("--end <end>", "End time in microseconds", "0")
|
|
70
70
|
.option("--sender-id <senderId>", "Filter by sender staffId", "")
|
|
@@ -78,7 +78,7 @@ function registerChatCommands(program) {
|
|
|
78
78
|
staff_id: opts.staffId || undefined,
|
|
79
79
|
group_id: opts.groupId || undefined,
|
|
80
80
|
page_size: parseInt(opts.size),
|
|
81
|
-
base_version: opts.
|
|
81
|
+
base_version: opts.cursor,
|
|
82
82
|
start_time: parseInt(opts.start),
|
|
83
83
|
end_time: parseInt(opts.end),
|
|
84
84
|
sender_id: opts.senderId || undefined,
|
package/dist/commands/media.js
CHANGED
|
@@ -24,16 +24,16 @@ function registerMediaCommands(program) {
|
|
|
24
24
|
.description("Upload media for app/bot usage (4.5.4 API)")
|
|
25
25
|
.argument("<filePath>", "Local file path to upload")
|
|
26
26
|
.option("-t, --media-type <type>", "file, video, image, audio (4.5.4 app/bot)", "file")
|
|
27
|
-
.option("--width <width>", "Width for video/image"
|
|
28
|
-
.option("--height <height>", "Height for video/image"
|
|
29
|
-
.option("--duration <duration>", "Duration in seconds for video/audio"
|
|
27
|
+
.option("--width <width>", "Width for video/image")
|
|
28
|
+
.option("--height <height>", "Height for video/image")
|
|
29
|
+
.option("--duration <duration>", "Duration in seconds for video/audio")
|
|
30
30
|
.action(async (filePath, opts) => {
|
|
31
31
|
const client = (0, utils_1.getClient)();
|
|
32
32
|
const result = await client.uploadAppMediaFile(filePath, {
|
|
33
33
|
media_type: opts.mediaType,
|
|
34
|
-
width: parseInt(opts.width)
|
|
35
|
-
height: parseInt(opts.height)
|
|
36
|
-
duration: parseInt(opts.duration)
|
|
34
|
+
width: opts.width ? parseInt(opts.width) : undefined,
|
|
35
|
+
height: opts.height ? parseInt(opts.height) : undefined,
|
|
36
|
+
duration: opts.duration ? parseInt(opts.duration) : undefined,
|
|
37
37
|
});
|
|
38
38
|
(0, utils_1.checkError)(result);
|
|
39
39
|
(0, utils_1.outputResult)(result);
|
package/dist/commands/oauth.js
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.registerOauthCommands = registerOauthCommands;
|
|
37
|
+
const http = __importStar(require("http"));
|
|
4
38
|
const lansenger_sdk_ts_1 = require("lansenger-sdk-ts");
|
|
5
39
|
const utils_1 = require("../utils");
|
|
6
40
|
function registerOauthCommands(program) {
|
|
@@ -80,4 +114,96 @@ function registerOauthCommands(program) {
|
|
|
80
114
|
const valid = lansenger_sdk_ts_1.LansengerClient.validateCallbackState(callbackState, expectedState);
|
|
81
115
|
(0, utils_1.outputResult)({ valid });
|
|
82
116
|
});
|
|
117
|
+
cmd
|
|
118
|
+
.command("local-callback")
|
|
119
|
+
.description("Start a local HTTP server to capture OAuth2 callback and optionally exchange the code")
|
|
120
|
+
.option("-p, --port <port>", "Local HTTP server port", "8765")
|
|
121
|
+
.option("-s, --scope <scope>", "OAuth2 scope", "basic_userinfor")
|
|
122
|
+
.option("--state <state>", "CSRF state (auto-generated if empty)", "")
|
|
123
|
+
.option("-E, --exchange", "Auto-exchange code for userToken", true)
|
|
124
|
+
.option("--no-exchange", "Do not auto-exchange code")
|
|
125
|
+
.option("-t, --timeout <timeout>", "Max wait seconds for callback", "120")
|
|
126
|
+
.action(async (opts) => {
|
|
127
|
+
const port = parseInt(opts.port);
|
|
128
|
+
const scope = opts.scope;
|
|
129
|
+
const state = opts.state || undefined;
|
|
130
|
+
const autoExchange = opts.exchange !== false;
|
|
131
|
+
const timeout = parseInt(opts.timeout);
|
|
132
|
+
const redirectUri = `http://localhost:${port}`;
|
|
133
|
+
const client = (0, utils_1.getClient)();
|
|
134
|
+
const authUrl = client.buildAuthorizeUrl(redirectUri, { scope, state });
|
|
135
|
+
if (utils_1.jsonOutput) {
|
|
136
|
+
console.log(JSON.stringify({ authorize_url: authUrl, redirect_uri: redirectUri, port }, null, 2));
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.log(`Authorize URL:\n${authUrl}`);
|
|
140
|
+
console.log(`\nWaiting for callback on port ${port}... (timeout: ${timeout}s)`);
|
|
141
|
+
console.log("Open the URL above in a browser, authorize, then wait.");
|
|
142
|
+
}
|
|
143
|
+
const callbackResult = { value: null };
|
|
144
|
+
const server = http.createServer((req, res) => {
|
|
145
|
+
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
146
|
+
const code = url.searchParams.get("code") || "";
|
|
147
|
+
const receivedState = url.searchParams.get("state") || "";
|
|
148
|
+
const error = url.searchParams.get("error") || "";
|
|
149
|
+
if (error) {
|
|
150
|
+
res.writeHead(400);
|
|
151
|
+
res.end(`OAuth2 error: ${error}`);
|
|
152
|
+
callbackResult.value = { error };
|
|
153
|
+
}
|
|
154
|
+
else if (code) {
|
|
155
|
+
res.writeHead(200);
|
|
156
|
+
res.end("Authorization successful. You can close this tab.");
|
|
157
|
+
callbackResult.value = { code, state: receivedState };
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
res.writeHead(400);
|
|
161
|
+
res.end("Missing code parameter.");
|
|
162
|
+
callbackResult.value = { error: "missing_code" };
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
server.timeout = 1000;
|
|
166
|
+
const startTime = Date.now();
|
|
167
|
+
while (callbackResult.value === null && (Date.now() - startTime) < timeout * 1000) {
|
|
168
|
+
await new Promise((resolve) => {
|
|
169
|
+
server.once("request", () => resolve());
|
|
170
|
+
const timer = setTimeout(resolve, 1000);
|
|
171
|
+
timer.unref();
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
server.close();
|
|
175
|
+
if (callbackResult.value === null) {
|
|
176
|
+
console.error(`Timeout: no callback received within ${timeout}s`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
const result = callbackResult.value;
|
|
180
|
+
if (result.error) {
|
|
181
|
+
console.error(`OAuth2 error: ${result.error}`);
|
|
182
|
+
process.exit(1);
|
|
183
|
+
}
|
|
184
|
+
const code = result.code || "";
|
|
185
|
+
const receivedState = result.state || "";
|
|
186
|
+
if (!utils_1.jsonOutput) {
|
|
187
|
+
console.log(`Received code: ${code}`);
|
|
188
|
+
console.log(`Received state: ${receivedState}`);
|
|
189
|
+
}
|
|
190
|
+
if (autoExchange) {
|
|
191
|
+
const exchangeResult = await client.exchangeCode(code, { redirect_uri: redirectUri });
|
|
192
|
+
(0, utils_1.checkError)(exchangeResult);
|
|
193
|
+
if (exchangeResult.success && exchangeResult.user_token) {
|
|
194
|
+
const store = (0, utils_1.getStore)();
|
|
195
|
+
store.saveUserToken(exchangeResult.user_token, exchangeResult.refresh_token || "", exchangeResult.expires_in || 0);
|
|
196
|
+
}
|
|
197
|
+
(0, utils_1.outputResult)(exchangeResult);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
if (utils_1.jsonOutput) {
|
|
201
|
+
console.log(JSON.stringify({ code, state: receivedState }, null, 2));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.log(`\nUse this code to exchange manually:`);
|
|
205
|
+
console.log(` lansenger oauth exchange-code ${code} --redirect-uri ${redirectUri}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
83
209
|
}
|
package/dist/main.js
CHANGED
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
3
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
37
|
const commander_1 = require("commander");
|
|
5
38
|
const utils_1 = require("./utils");
|
|
39
|
+
const pkg = __importStar(require("../package.json"));
|
|
6
40
|
const config_1 = require("./commands/config");
|
|
7
41
|
const message_1 = require("./commands/message");
|
|
8
42
|
const staff_1 = require("./commands/staff");
|
|
@@ -20,7 +54,7 @@ const program = new commander_1.Command();
|
|
|
20
54
|
program
|
|
21
55
|
.name("lansenger")
|
|
22
56
|
.description("CLI for Lansenger (蓝信) — send messages, manage groups, staff, departments, calendars, todos, and more")
|
|
23
|
-
.version(
|
|
57
|
+
.version(pkg.version)
|
|
24
58
|
.option("-j, --json", "Output as JSON", false)
|
|
25
59
|
.option("-P, --profile <profile>", "Credential profile", "default")
|
|
26
60
|
.hook("preAction", () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lansenger-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "CLI for Lansenger (蓝信) — send messages, manage groups, staff, departments, calendars, todos, and more",
|
|
5
5
|
"main": "dist/main.js",
|
|
6
6
|
"bin": {
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"lint": "tsc --noEmit"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"commander": "^12.0.0",
|
|
23
22
|
"cli-table3": "^0.6.0",
|
|
24
|
-
"
|
|
23
|
+
"commander": "^12.0.0",
|
|
24
|
+
"lansenger-sdk-ts": "^1.1.0",
|
|
25
25
|
"node-fetch": "^2.7.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|