@mo7yw4ng/openape 1.0.4 → 1.0.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/esm/deno.js +1 -1
- package/esm/src/commands/announcements.js +3 -3
- package/esm/src/commands/auth.d.ts.map +1 -1
- package/esm/src/commands/auth.js +24 -14
- package/esm/src/commands/calendar.js +3 -3
- package/esm/src/commands/courses.js +3 -3
- package/esm/src/commands/forums.js +3 -3
- package/esm/src/commands/grades.js +3 -3
- package/esm/src/commands/materials.d.ts.map +1 -1
- package/esm/src/commands/materials.js +114 -191
- package/esm/src/commands/quizzes.d.ts.map +1 -1
- package/esm/src/commands/quizzes.js +33 -22
- package/esm/src/commands/videos.js +5 -5
- package/esm/src/lib/auth.js +2 -2
- package/esm/src/lib/logger.d.ts +1 -1
- package/esm/src/lib/logger.d.ts.map +1 -1
- package/esm/src/lib/logger.js +7 -4
- package/esm/src/lib/moodle.d.ts +4 -0
- package/esm/src/lib/moodle.d.ts.map +1 -1
- package/esm/src/lib/moodle.js +19 -2
- package/package.json +1 -1
- package/script/deno.js +1 -1
- package/script/src/commands/announcements.js +3 -3
- package/script/src/commands/auth.d.ts.map +1 -1
- package/script/src/commands/auth.js +24 -14
- package/script/src/commands/calendar.js +3 -3
- package/script/src/commands/courses.js +3 -3
- package/script/src/commands/forums.js +3 -3
- package/script/src/commands/grades.js +3 -3
- package/script/src/commands/materials.d.ts.map +1 -1
- package/script/src/commands/materials.js +111 -188
- package/script/src/commands/quizzes.d.ts.map +1 -1
- package/script/src/commands/quizzes.js +32 -21
- package/script/src/commands/videos.js +5 -5
- package/script/src/lib/auth.js +2 -2
- package/script/src/lib/logger.d.ts +1 -1
- package/script/src/lib/logger.d.ts.map +1 -1
- package/script/src/lib/logger.js +7 -4
- package/script/src/lib/moodle.d.ts +4 -0
- package/script/src/lib/moodle.d.ts.map +1 -1
- package/script/src/lib/moodle.js +20 -2
- package/skills/openape/SKILL.md +4 -2
|
@@ -6,76 +6,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.registerMaterialsCommand = registerMaterialsCommand;
|
|
7
7
|
const utils_js_1 = require("../lib/utils.js");
|
|
8
8
|
const moodle_js_1 = require("../lib/moodle.js");
|
|
9
|
-
const logger_js_1 = require("../lib/logger.js");
|
|
10
9
|
const auth_js_1 = require("../lib/auth.js");
|
|
11
|
-
const session_js_1 = require("../lib/session.js");
|
|
12
|
-
const auth_js_2 = require("../lib/auth.js");
|
|
13
10
|
const index_js_1 = require("../index.js");
|
|
14
11
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
12
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
16
13
|
function registerMaterialsCommand(program) {
|
|
17
14
|
const materialsCmd = program.command("materials");
|
|
18
15
|
materialsCmd.description("Material/resource operations");
|
|
19
|
-
// Helper
|
|
20
|
-
async function
|
|
21
|
-
const opts = command?.optsWithGlobals ? command.optsWithGlobals() : options;
|
|
22
|
-
const outputFormat = (0, utils_js_1.getOutputFormat)(command || { optsWithGlobals: () => ({ output: "json" }) });
|
|
23
|
-
const silent = outputFormat === "json" && !opts.verbose;
|
|
24
|
-
const log = (0, logger_js_1.createLogger)(opts.verbose, silent);
|
|
25
|
-
const sessionPath = (0, utils_js_1.getSessionPath)();
|
|
26
|
-
if (!node_fs_1.default.existsSync(sessionPath)) {
|
|
27
|
-
log.error("未找到登入 session。請先執行 'openape auth login' 進行登入。");
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
const config = {
|
|
31
|
-
username: "",
|
|
32
|
-
password: "",
|
|
33
|
-
courseUrl: "",
|
|
34
|
-
moodleBaseUrl: "https://ilearning.cycu.edu.tw",
|
|
35
|
-
headless: !options.headed,
|
|
36
|
-
slowMo: 0,
|
|
37
|
-
authStatePath: sessionPath,
|
|
38
|
-
ollamaBaseUrl: "",
|
|
39
|
-
};
|
|
40
|
-
log.info("啟動瀏覽器...");
|
|
41
|
-
const { browser, context, page } = await (0, auth_js_1.launchAuthenticated)(config, log);
|
|
42
|
-
try {
|
|
43
|
-
const session = await (0, session_js_1.extractSessionInfo)(page, config, log);
|
|
44
|
-
return { log, page, session, browser, context };
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
await context.close();
|
|
48
|
-
await browser.close();
|
|
49
|
-
throw err;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// Helper to download a single resource
|
|
53
|
-
async function downloadResource(page, resource, outputDir, log) {
|
|
16
|
+
// Helper to download a single resource via HTTP (no browser needed)
|
|
17
|
+
async function downloadResourceHttp(resource, outputDir, log, token) {
|
|
54
18
|
try {
|
|
55
19
|
// Only download resource type (skip url)
|
|
56
20
|
if (resource.modType !== "resource") {
|
|
57
21
|
log.debug(` Skipping ${resource.modType}: ${resource.name}`);
|
|
58
22
|
return null;
|
|
59
23
|
}
|
|
60
|
-
// Create course directory
|
|
61
24
|
const courseDir = node_path_1.default.join(outputDir, (0, utils_js_1.sanitizeFilename)(resource.course_name));
|
|
62
25
|
await node_fs_1.default.promises.mkdir(courseDir, { recursive: true });
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
await page.goto(resource.url, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
66
|
-
// Try to find download link on the page
|
|
67
|
-
const downloadLinks = await page.$$eval('a[href*="forcedownload=1"]', (links) => links.map((a) => a.href));
|
|
68
|
-
if (downloadLinks.length === 0) {
|
|
69
|
-
log.warn(` No download link found for: ${resource.name}`);
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
// Download the first available file
|
|
73
|
-
const downloadUrl = downloadLinks[0];
|
|
74
|
-
// Extract filename from URL or use resource name
|
|
75
|
-
const urlObj = new URL(downloadUrl);
|
|
76
|
-
const filenameParam = urlObj.searchParams.get("filename");
|
|
77
|
-
let filename = filenameParam || (0, utils_js_1.sanitizeFilename)(resource.name);
|
|
78
|
-
// Add extension if missing
|
|
26
|
+
// Build filename
|
|
27
|
+
let filename = (0, utils_js_1.sanitizeFilename)(resource.name);
|
|
79
28
|
if (resource.mimetype && !node_path_1.default.extname(filename)) {
|
|
80
29
|
const extMap = {
|
|
81
30
|
"application/pdf": ".pdf",
|
|
@@ -94,27 +43,54 @@ function registerMaterialsCommand(program) {
|
|
|
94
43
|
}
|
|
95
44
|
}
|
|
96
45
|
const outputPath = node_path_1.default.join(courseDir, filename);
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
46
|
+
// Skip if already exists
|
|
47
|
+
if (node_fs_1.default.existsSync(outputPath)) {
|
|
48
|
+
log.debug(` Skipping (exists): ${filename}`);
|
|
49
|
+
const stats = await node_fs_1.default.promises.stat(outputPath);
|
|
50
|
+
return { filename, path: outputPath, size: stats.size, course_id: resource.course_id, course_name: resource.course_name };
|
|
51
|
+
}
|
|
52
|
+
// Download via HTTP with WS token
|
|
53
|
+
const separator = resource.url.includes("?") ? "&" : "?";
|
|
54
|
+
const downloadUrl = `${resource.url}${separator}token=${token}`;
|
|
55
|
+
log.debug(` Downloading: ${resource.name}`);
|
|
56
|
+
const response = await fetch(downloadUrl);
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
log.warn(` Failed to download ${resource.name}: HTTP ${response.status}`);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
62
|
+
const data = new Uint8Array(arrayBuffer);
|
|
63
|
+
await node_fs_1.default.promises.writeFile(outputPath, data);
|
|
64
|
+
log.success(` Downloaded: ${filename} (${(0, utils_js_1.formatFileSize)(data.byteLength, 1)} KB)`);
|
|
65
|
+
return { filename, path: outputPath, size: data.byteLength, course_id: resource.course_id, course_name: resource.course_name };
|
|
112
66
|
}
|
|
113
67
|
catch (err) {
|
|
114
68
|
log.warn(` Failed to download ${resource.name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
115
69
|
return null;
|
|
116
70
|
}
|
|
117
71
|
}
|
|
72
|
+
// Helper to build material list from API resources
|
|
73
|
+
function buildMaterialsList(courses, apiResources) {
|
|
74
|
+
const courseMap = new Map(courses.map(c => [c.id, c]));
|
|
75
|
+
const materials = [];
|
|
76
|
+
for (const resource of apiResources) {
|
|
77
|
+
const course = courseMap.get(resource.courseId);
|
|
78
|
+
if (course) {
|
|
79
|
+
materials.push({
|
|
80
|
+
course_id: resource.courseId,
|
|
81
|
+
course_name: course.fullname,
|
|
82
|
+
cmid: resource.cmid,
|
|
83
|
+
name: resource.name,
|
|
84
|
+
url: resource.url,
|
|
85
|
+
modType: resource.modType,
|
|
86
|
+
mimetype: resource.mimetype,
|
|
87
|
+
filesize: resource.filesize,
|
|
88
|
+
modified: resource.modified,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return materials;
|
|
93
|
+
}
|
|
118
94
|
materialsCmd
|
|
119
95
|
.command("list-all")
|
|
120
96
|
.description("List all materials/resources across all courses")
|
|
@@ -180,150 +156,97 @@ function registerMaterialsCommand(program) {
|
|
|
180
156
|
});
|
|
181
157
|
materialsCmd
|
|
182
158
|
.command("download")
|
|
183
|
-
.description("Download all materials from a specific course
|
|
159
|
+
.description("Download all materials from a specific course")
|
|
184
160
|
.argument("<course-id>", "Course ID")
|
|
185
161
|
.option("--output-dir <path>", "Output directory", "./downloads")
|
|
186
162
|
.action(async (courseId, options, command) => {
|
|
187
|
-
const
|
|
188
|
-
if (!
|
|
163
|
+
const apiContext = await (0, auth_js_1.createApiContext)(options, command);
|
|
164
|
+
if (!apiContext) {
|
|
189
165
|
process.exitCode = 1;
|
|
190
166
|
return;
|
|
191
167
|
}
|
|
192
|
-
const { log,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
name: a.textContent?.trim() || "",
|
|
209
|
-
}));
|
|
210
|
-
});
|
|
211
|
-
for (const link of resourceLinks) {
|
|
212
|
-
const cmidMatch = link.url.match(/id=(\d+)/);
|
|
213
|
-
if (cmidMatch) {
|
|
214
|
-
materials.push({
|
|
215
|
-
course_id: course.id,
|
|
216
|
-
course_name: course.fullname,
|
|
217
|
-
cmid: cmidMatch[1],
|
|
218
|
-
name: link.name,
|
|
219
|
-
url: link.url,
|
|
220
|
-
modType: "resource",
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
log.info(`Found ${materials.length} materials in course: ${course.fullname}`);
|
|
225
|
-
const downloadedFiles = [];
|
|
226
|
-
for (const material of materials) {
|
|
227
|
-
const result = await downloadResource(page, material, options.outputDir, log);
|
|
228
|
-
if (result) {
|
|
229
|
-
downloadedFiles.push(result);
|
|
230
|
-
}
|
|
168
|
+
const { log, session } = apiContext;
|
|
169
|
+
const courses = await (0, moodle_js_1.getEnrolledCoursesApi)(session);
|
|
170
|
+
const course = courses.find((c) => c.id === parseInt(courseId, 10));
|
|
171
|
+
if (!course) {
|
|
172
|
+
log.error(`Course not found: ${courseId}`);
|
|
173
|
+
process.exitCode = 1;
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const apiResources = await (0, moodle_js_1.getResourcesByCoursesApi)(session, [course.id]);
|
|
177
|
+
const materials = buildMaterialsList(courses, apiResources);
|
|
178
|
+
log.info(`Found ${materials.length} materials in course: ${course.fullname}`);
|
|
179
|
+
const downloadedFiles = [];
|
|
180
|
+
for (const material of materials) {
|
|
181
|
+
const result = await downloadResourceHttp(material, options.outputDir, log, session.wsToken);
|
|
182
|
+
if (result) {
|
|
183
|
+
downloadedFiles.push(result);
|
|
231
184
|
}
|
|
232
|
-
|
|
185
|
+
}
|
|
186
|
+
const output = {
|
|
187
|
+
status: "success",
|
|
188
|
+
timestamp: new Date().toISOString(),
|
|
189
|
+
downloaded_files: downloadedFiles.map(f => ({
|
|
190
|
+
filename: f.filename,
|
|
191
|
+
path: f.path,
|
|
192
|
+
size: f.size,
|
|
193
|
+
course_id: f.course_id,
|
|
194
|
+
course_name: f.course_name,
|
|
195
|
+
})),
|
|
196
|
+
summary: {
|
|
233
197
|
total_materials: materials.length,
|
|
234
198
|
downloaded: downloadedFiles.length,
|
|
235
199
|
skipped: materials.length - downloadedFiles.length,
|
|
236
200
|
total_size: downloadedFiles.reduce((sum, f) => sum + f.size, 0),
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
timestamp: new Date().toISOString(),
|
|
241
|
-
downloaded_files: downloadedFiles.map(f => ({
|
|
242
|
-
filename: f.filename,
|
|
243
|
-
path: f.path,
|
|
244
|
-
size: f.size,
|
|
245
|
-
course_id: f.course_id,
|
|
246
|
-
course_name: f.course_name,
|
|
247
|
-
})),
|
|
248
|
-
summary,
|
|
249
|
-
};
|
|
250
|
-
console.log(JSON.stringify(output));
|
|
251
|
-
}
|
|
252
|
-
finally {
|
|
253
|
-
await (0, auth_js_2.closeBrowserSafely)(browser, browserContext);
|
|
254
|
-
}
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
console.log(JSON.stringify(output));
|
|
255
204
|
});
|
|
256
205
|
materialsCmd
|
|
257
206
|
.command("download-all")
|
|
258
|
-
.description("Download all materials from all courses
|
|
207
|
+
.description("Download all materials from all courses")
|
|
259
208
|
.option("--output-dir <path>", "Output directory", "./downloads")
|
|
260
209
|
.option("--level <type>", "Course level: in_progress (default) | all", "in_progress")
|
|
261
210
|
.action(async (options, command) => {
|
|
262
|
-
const
|
|
263
|
-
if (!
|
|
211
|
+
const apiContext = await (0, auth_js_1.createApiContext)(options, command);
|
|
212
|
+
if (!apiContext) {
|
|
264
213
|
process.exitCode = 1;
|
|
265
214
|
return;
|
|
266
215
|
}
|
|
267
|
-
const { log,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
});
|
|
281
|
-
for (const link of resourceLinks) {
|
|
282
|
-
const cmidMatch = link.url.match(/id=(\d+)/);
|
|
283
|
-
if (cmidMatch) {
|
|
284
|
-
allMaterials.push({
|
|
285
|
-
course_id: course.id,
|
|
286
|
-
course_name: course.fullname,
|
|
287
|
-
cmid: cmidMatch[1],
|
|
288
|
-
name: link.name,
|
|
289
|
-
url: link.url,
|
|
290
|
-
modType: "resource",
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
log.info(`Found ${allMaterials.length} materials across ${courses.length} courses`);
|
|
296
|
-
const downloadedFiles = [];
|
|
297
|
-
for (const material of allMaterials) {
|
|
298
|
-
const result = await downloadResource(page, material, options.outputDir, log);
|
|
299
|
-
if (result) {
|
|
300
|
-
downloadedFiles.push(result);
|
|
301
|
-
}
|
|
216
|
+
const { log, session } = apiContext;
|
|
217
|
+
const classification = options.level === "all" ? undefined : "inprogress";
|
|
218
|
+
const courses = await (0, moodle_js_1.getEnrolledCoursesApi)(session, { classification });
|
|
219
|
+
log.info(`Scanning ${courses.length} courses for materials...`);
|
|
220
|
+
const courseIds = courses.map((c) => c.id);
|
|
221
|
+
const apiResources = await (0, moodle_js_1.getResourcesByCoursesApi)(session, courseIds);
|
|
222
|
+
const allMaterials = buildMaterialsList(courses, apiResources);
|
|
223
|
+
log.info(`Found ${allMaterials.length} materials across ${courses.length} courses`);
|
|
224
|
+
const downloadedFiles = [];
|
|
225
|
+
for (const material of allMaterials) {
|
|
226
|
+
const result = await downloadResourceHttp(material, options.outputDir, log, session.wsToken);
|
|
227
|
+
if (result) {
|
|
228
|
+
downloadedFiles.push(result);
|
|
302
229
|
}
|
|
303
|
-
|
|
230
|
+
}
|
|
231
|
+
const output = {
|
|
232
|
+
status: "success",
|
|
233
|
+
timestamp: new Date().toISOString(),
|
|
234
|
+
downloaded_files: downloadedFiles.map(f => ({
|
|
235
|
+
filename: f.filename,
|
|
236
|
+
path: f.path,
|
|
237
|
+
size: f.size,
|
|
238
|
+
course_id: f.course_id,
|
|
239
|
+
course_name: f.course_name,
|
|
240
|
+
})),
|
|
241
|
+
summary: {
|
|
304
242
|
total_courses: courses.length,
|
|
305
243
|
total_materials: allMaterials.length,
|
|
306
244
|
downloaded: downloadedFiles.length,
|
|
307
245
|
skipped: allMaterials.length - downloadedFiles.length,
|
|
308
246
|
total_size: downloadedFiles.reduce((sum, f) => sum + f.size, 0),
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
timestamp: new Date().toISOString(),
|
|
313
|
-
downloaded_files: downloadedFiles.map(f => ({
|
|
314
|
-
filename: f.filename,
|
|
315
|
-
path: f.path,
|
|
316
|
-
size: f.size,
|
|
317
|
-
course_id: f.course_id,
|
|
318
|
-
course_name: f.course_name,
|
|
319
|
-
})),
|
|
320
|
-
summary,
|
|
321
|
-
};
|
|
322
|
-
console.log(JSON.stringify(output));
|
|
323
|
-
}
|
|
324
|
-
finally {
|
|
325
|
-
await (0, auth_js_2.closeBrowserSafely)(browser, browserContext);
|
|
326
|
-
}
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
console.log(JSON.stringify(output));
|
|
327
250
|
});
|
|
328
251
|
materialsCmd
|
|
329
252
|
.command("complete")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quizzes.d.ts","sourceRoot":"","sources":["../../../src/src/commands/quizzes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"quizzes.d.ts","sourceRoot":"","sources":["../../../src/src/commands/quizzes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyEpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAoQ7D"}
|
|
@@ -47,6 +47,21 @@ function parseSavedAnswer(html) {
|
|
|
47
47
|
return textMatch[1];
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
|
+
function parseQuizQuestions(questions) {
|
|
51
|
+
return Object.values(questions).map((q) => {
|
|
52
|
+
const parsed = parseQuestionHtml(q.html ?? "");
|
|
53
|
+
const savedAnswer = parseSavedAnswer(q.html ?? "");
|
|
54
|
+
return {
|
|
55
|
+
slot: q.slot,
|
|
56
|
+
type: q.type,
|
|
57
|
+
status: q.status,
|
|
58
|
+
stateclass: q.stateclass,
|
|
59
|
+
savedAnswer,
|
|
60
|
+
question: parsed.text,
|
|
61
|
+
options: parsed.options,
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
}
|
|
50
65
|
function registerQuizzesCommand(program) {
|
|
51
66
|
const quizzesCmd = program.command("quizzes");
|
|
52
67
|
quizzesCmd.description("Quiz operations");
|
|
@@ -59,19 +74,19 @@ function registerQuizzesCommand(program) {
|
|
|
59
74
|
const opts = command?.optsWithGlobals ? command.optsWithGlobals() : options;
|
|
60
75
|
const outputFormat = getOutputFormat(command || { optsWithGlobals: () => ({ output: "json" }) });
|
|
61
76
|
const silent = outputFormat === "json" && !opts.verbose;
|
|
62
|
-
const log = (0, logger_js_1.createLogger)(opts.verbose, silent);
|
|
77
|
+
const log = (0, logger_js_1.createLogger)(opts.verbose, silent, outputFormat);
|
|
63
78
|
const baseDir = (0, utils_js_1.getBaseDir)();
|
|
64
79
|
const sessionPath = node_path_1.default.resolve(baseDir, ".auth", "storage-state.json");
|
|
65
80
|
// Check if session exists
|
|
66
81
|
if (!node_fs_1.default.existsSync(sessionPath)) {
|
|
67
|
-
log.error("未找到登入 session。請先執行 'openape
|
|
82
|
+
log.error("未找到登入 session。請先執行 'openape login' 進行登入。");
|
|
68
83
|
log.info(`Session 預期位置: ${sessionPath}`);
|
|
69
84
|
return null;
|
|
70
85
|
}
|
|
71
86
|
// Try to load WS token
|
|
72
87
|
const wsToken = (0, token_js_1.loadWsToken)(sessionPath);
|
|
73
88
|
if (!wsToken) {
|
|
74
|
-
log.error("未找到 WS token。請先執行 'openape
|
|
89
|
+
log.error("未找到 WS token。請先執行 'openape login' 進行登入。");
|
|
75
90
|
return null;
|
|
76
91
|
}
|
|
77
92
|
return {
|
|
@@ -160,8 +175,12 @@ function registerQuizzesCommand(program) {
|
|
|
160
175
|
}
|
|
161
176
|
try {
|
|
162
177
|
const result = await (0, moodle_js_1.startQuizAttemptApi)(apiContext.session, quizCmid);
|
|
178
|
+
apiContext.log.success(`Quiz attempt ${result.attempt.attemptid} started.`);
|
|
179
|
+
const attemptId = result.attempt.attemptid;
|
|
180
|
+
const data = await (0, moodle_js_1.getAllQuizAttemptDataApi)(apiContext.session, attemptId);
|
|
181
|
+
const questions = parseQuizQuestions(data.questions);
|
|
163
182
|
const outputData = [{
|
|
164
|
-
attemptId
|
|
183
|
+
attemptId,
|
|
165
184
|
quizId: result.attempt.quizid,
|
|
166
185
|
state: result.attempt.state,
|
|
167
186
|
timeStart: (0, utils_js_1.formatTimestamp)(result.attempt.timestart),
|
|
@@ -169,8 +188,9 @@ function registerQuizzesCommand(program) {
|
|
|
169
188
|
? (0, utils_js_1.formatTimestamp)(result.attempt.timefinish)
|
|
170
189
|
: null,
|
|
171
190
|
isPreview: result.attempt.preview,
|
|
191
|
+
totalQuestions: questions.length,
|
|
192
|
+
questions,
|
|
172
193
|
}];
|
|
173
|
-
apiContext.log.success(`Quiz attempt ${result.attempt.attemptid} started.`);
|
|
174
194
|
(0, index_js_1.formatAndOutput)(outputData, output, apiContext.log);
|
|
175
195
|
}
|
|
176
196
|
catch (error) {
|
|
@@ -182,7 +202,7 @@ function registerQuizzesCommand(program) {
|
|
|
182
202
|
.command("info")
|
|
183
203
|
.description("Get quiz attempt data and questions")
|
|
184
204
|
.argument("<attempt-id>", "Quiz attempt ID")
|
|
185
|
-
.option("--page <number>", "Page number", "
|
|
205
|
+
.option("--page <number>", "Page number (-1 for all pages)", "-1")
|
|
186
206
|
.option("--output <format>", "Output format: json|csv|table|silent")
|
|
187
207
|
.action(async (attemptId, options, command) => {
|
|
188
208
|
const output = getOutputFormat(command);
|
|
@@ -192,20 +212,11 @@ function registerQuizzesCommand(program) {
|
|
|
192
212
|
return;
|
|
193
213
|
}
|
|
194
214
|
try {
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
number: q.questionnumber ?? q.slot,
|
|
201
|
-
type: q.type,
|
|
202
|
-
status: q.status,
|
|
203
|
-
stateclass: q.stateclass,
|
|
204
|
-
savedAnswer,
|
|
205
|
-
question: parsed.text,
|
|
206
|
-
options: parsed.options,
|
|
207
|
-
};
|
|
208
|
-
});
|
|
215
|
+
const pageNumber = parseInt(options.page);
|
|
216
|
+
const data = pageNumber === -1
|
|
217
|
+
? await (0, moodle_js_1.getAllQuizAttemptDataApi)(apiContext.session, parseInt(attemptId))
|
|
218
|
+
: await (0, moodle_js_1.getQuizAttemptDataApi)(apiContext.session, parseInt(attemptId), pageNumber);
|
|
219
|
+
const questions = parseQuizQuestions(data.questions);
|
|
209
220
|
const outputData = [{
|
|
210
221
|
attemptId: data.attempt.attemptid,
|
|
211
222
|
quizId: data.attempt.quizid,
|
|
@@ -246,7 +257,7 @@ function registerQuizzesCommand(program) {
|
|
|
246
257
|
}
|
|
247
258
|
try {
|
|
248
259
|
// Get attempt data to find uniqueid and sequencecheck values
|
|
249
|
-
const attemptData = await (0, moodle_js_1.
|
|
260
|
+
const attemptData = await (0, moodle_js_1.getAllQuizAttemptDataApi)(apiContext.session, parseInt(attemptId));
|
|
250
261
|
const uniqueId = attemptData.attempt.uniqueid ?? attemptData.attempt.attemptid;
|
|
251
262
|
const sequenceChecks = new Map();
|
|
252
263
|
for (const q of Object.values(attemptData.questions)) {
|
|
@@ -23,19 +23,19 @@ function registerVideosCommand(program) {
|
|
|
23
23
|
// Don't silence logs for commands that don't have explicit output format control
|
|
24
24
|
const outputFormat = command && command.optsWithGlobals ? (0, utils_js_1.getOutputFormat)(command) : "table";
|
|
25
25
|
const silent = outputFormat === "json" && !opts.verbose;
|
|
26
|
-
const log = (0, logger_js_1.createLogger)(opts.verbose, silent);
|
|
26
|
+
const log = (0, logger_js_1.createLogger)(opts.verbose, silent, outputFormat);
|
|
27
27
|
const baseDir = (0, utils_js_1.getBaseDir)();
|
|
28
28
|
const sessionPath = node_path_1.default.resolve(baseDir, ".auth", "storage-state.json");
|
|
29
29
|
// Check if session exists
|
|
30
30
|
if (!node_fs_1.default.existsSync(sessionPath)) {
|
|
31
|
-
|
|
31
|
+
console.error("未找到登入 session。請先執行 'openape login' 進行登入。");
|
|
32
32
|
log.info(`Session 預期位置: ${sessionPath}`);
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
35
|
// Try to load WS token
|
|
36
36
|
const wsToken = (0, token_js_1.loadWsToken)(sessionPath);
|
|
37
37
|
if (!wsToken) {
|
|
38
|
-
|
|
38
|
+
console.error("未找到 WS token。請先執行 'openape login' 進行登入。");
|
|
39
39
|
return null;
|
|
40
40
|
}
|
|
41
41
|
return {
|
|
@@ -51,11 +51,11 @@ function registerVideosCommand(program) {
|
|
|
51
51
|
const opts = command?.optsWithGlobals ? command.optsWithGlobals() : options;
|
|
52
52
|
const outputFormat = (0, utils_js_1.getOutputFormat)(command || { optsWithGlobals: () => ({ output: "json" }) });
|
|
53
53
|
const silent = outputFormat === "json" && !opts.verbose;
|
|
54
|
-
const log = (0, logger_js_1.createLogger)(opts.verbose, silent);
|
|
54
|
+
const log = (0, logger_js_1.createLogger)(opts.verbose, silent, outputFormat);
|
|
55
55
|
const baseDir = (0, utils_js_1.getBaseDir)();
|
|
56
56
|
const sessionPath = node_path_1.default.resolve(baseDir, ".auth", "storage-state.json");
|
|
57
57
|
if (!node_fs_1.default.existsSync(sessionPath)) {
|
|
58
|
-
|
|
58
|
+
console.error("未找到登入 session。請先執行 'openape login' 進行登入。");
|
|
59
59
|
return null;
|
|
60
60
|
}
|
|
61
61
|
const config = {
|
package/script/src/lib/auth.js
CHANGED
|
@@ -251,12 +251,12 @@ async function createApiContext(options, command) {
|
|
|
251
251
|
const opts = command?.optsWithGlobals ? command.optsWithGlobals() : options;
|
|
252
252
|
const outputFormat = command ? getOutputFormat(command) : "json";
|
|
253
253
|
const silent = outputFormat === "json" && !opts.verbose;
|
|
254
|
-
const log = createLogger(opts.verbose, silent);
|
|
254
|
+
const log = createLogger(opts.verbose, silent, outputFormat);
|
|
255
255
|
const sessionPath = getSessionPath();
|
|
256
256
|
// Try to load WS token
|
|
257
257
|
const wsToken = loadWsToken(sessionPath);
|
|
258
258
|
if (!wsToken) {
|
|
259
|
-
|
|
259
|
+
console.error("未找到 WS token。請先執行 'openape login' 進行登入。");
|
|
260
260
|
return null;
|
|
261
261
|
}
|
|
262
262
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAOzC,wBAAgB,YAAY,CAAC,OAAO,UAAQ,EAAE,MAAM,UAAQ,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/src/lib/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAOzC,wBAAgB,YAAY,CAAC,OAAO,UAAQ,EAAE,MAAM,UAAQ,EAAE,YAAY,GAAE,MAAe,GAAG,MAAM,CAwBnG"}
|
package/script/src/lib/logger.js
CHANGED
|
@@ -3,14 +3,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createLogger = createLogger;
|
|
4
4
|
const NO_COLOR = !!process.env.NO_COLOR;
|
|
5
5
|
const c = (code, text) => NO_COLOR ? text : `\x1b[${code}m${text}\x1b[0m`;
|
|
6
|
-
function createLogger(verbose = false, silent = false) {
|
|
6
|
+
function createLogger(verbose = false, silent = false, outputFormat = "json") {
|
|
7
|
+
const jsonError = outputFormat === "json";
|
|
8
|
+
const errorFn = jsonError
|
|
9
|
+
? (msg) => console.error(JSON.stringify({ error: msg }))
|
|
10
|
+
: (msg) => console.error(c("31", "[ERR]") + ` ${msg}`);
|
|
7
11
|
if (silent) {
|
|
8
|
-
// Silent logger - no output at all
|
|
9
12
|
return {
|
|
10
13
|
info: (_msg) => { },
|
|
11
14
|
success: (_msg) => { },
|
|
12
15
|
warn: (_msg) => { },
|
|
13
|
-
error:
|
|
16
|
+
error: errorFn,
|
|
14
17
|
debug: (_msg) => { },
|
|
15
18
|
};
|
|
16
19
|
}
|
|
@@ -18,7 +21,7 @@ function createLogger(verbose = false, silent = false) {
|
|
|
18
21
|
info: (msg) => console.error(c("36", "[INFO]") + ` ${msg}`),
|
|
19
22
|
success: (msg) => console.error(c("32", "[OK]") + ` ${msg}`),
|
|
20
23
|
warn: (msg) => console.error(c("33", "[WARN]") + ` ${msg}`),
|
|
21
|
-
error:
|
|
24
|
+
error: errorFn,
|
|
22
25
|
debug: (msg) => {
|
|
23
26
|
if (verbose)
|
|
24
27
|
console.error(c("90", "[DBG]") + ` ${msg}`);
|
|
@@ -269,6 +269,10 @@ export declare function startQuizAttemptApi(session: {
|
|
|
269
269
|
/**
|
|
270
270
|
* Get quiz attempt data including questions via pure WS API.
|
|
271
271
|
*/
|
|
272
|
+
export declare function getAllQuizAttemptDataApi(session: {
|
|
273
|
+
wsToken: string;
|
|
274
|
+
moodleBaseUrl: string;
|
|
275
|
+
}, attemptId: number): Promise<QuizAttemptData>;
|
|
272
276
|
export declare function getQuizAttemptDataApi(session: {
|
|
273
277
|
wsToken: string;
|
|
274
278
|
moodleBaseUrl: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"moodle.d.ts","sourceRoot":"","sources":["../../../src/src/lib/moodle.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"moodle.d.ts","sourceRoot":"","sources":["../../../src/src/lib/moodle.ts"],"names":[],"mappings":"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"}
|