@mo7yw4ng/openape 1.0.0 → 1.0.2
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/LICENSE +21 -21
- package/README.md +15 -5
- package/esm/_dnt.polyfills.d.ts +83 -6
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +127 -1
- package/esm/_dnt.shims.d.ts +1 -0
- package/esm/_dnt.shims.d.ts.map +1 -0
- package/esm/deno.d.ts +2 -0
- package/esm/deno.d.ts.map +1 -0
- package/esm/deno.js +2 -1
- package/esm/src/commands/announcements.d.ts +3 -0
- package/esm/src/commands/announcements.d.ts.map +1 -0
- package/esm/src/commands/announcements.js +135 -0
- package/esm/src/commands/auth.d.ts +3 -0
- package/esm/src/commands/auth.d.ts.map +1 -0
- package/esm/src/commands/auth.js +264 -0
- package/esm/src/commands/calendar.d.ts +3 -0
- package/esm/src/commands/calendar.d.ts.map +1 -0
- package/esm/src/commands/calendar.js +180 -0
- package/esm/src/commands/courses.d.ts +3 -0
- package/esm/src/commands/courses.d.ts.map +1 -0
- package/esm/src/commands/courses.js +348 -0
- package/esm/src/commands/forums.d.ts +3 -0
- package/esm/src/commands/forums.d.ts.map +1 -0
- package/esm/src/commands/forums.js +231 -0
- package/esm/src/commands/grades.d.ts +3 -0
- package/esm/src/commands/grades.d.ts.map +1 -0
- package/esm/src/commands/grades.js +121 -0
- package/esm/src/commands/materials.d.ts +3 -0
- package/esm/src/commands/materials.d.ts.map +1 -0
- package/esm/src/commands/materials.js +362 -0
- package/esm/src/commands/quizzes.d.ts +3 -0
- package/esm/src/commands/quizzes.d.ts.map +1 -0
- package/esm/src/commands/quizzes.js +160 -0
- package/esm/src/commands/skills.d.ts +3 -0
- package/esm/src/commands/skills.d.ts.map +1 -0
- package/esm/src/commands/skills.js +110 -0
- package/esm/src/commands/videos.d.ts +3 -0
- package/esm/src/commands/videos.d.ts.map +1 -0
- package/esm/src/commands/videos.js +302 -0
- package/esm/src/index.d.ts +27 -0
- package/esm/src/index.d.ts.map +1 -0
- package/esm/src/index.js +149 -0
- package/esm/src/lib/auth.d.ts +25 -0
- package/esm/src/lib/auth.d.ts.map +1 -0
- package/esm/src/lib/auth.js +194 -0
- package/esm/src/lib/config.d.ts +6 -0
- package/esm/src/lib/config.d.ts.map +1 -0
- package/esm/src/lib/config.js +36 -0
- package/esm/src/lib/logger.d.ts +3 -0
- package/esm/src/lib/logger.d.ts.map +1 -0
- package/esm/src/lib/logger.js +24 -0
- package/esm/src/lib/moodle.d.ts +205 -0
- package/esm/src/lib/moodle.d.ts.map +1 -0
- package/esm/src/lib/moodle.js +690 -0
- package/esm/src/lib/session.d.ts +8 -0
- package/esm/src/lib/session.d.ts.map +1 -0
- package/esm/src/lib/session.js +42 -0
- package/esm/src/lib/token.d.ts +38 -0
- package/esm/src/lib/token.d.ts.map +1 -0
- package/esm/src/lib/token.js +178 -0
- package/esm/src/lib/types.d.ts +271 -0
- package/esm/src/lib/types.d.ts.map +1 -0
- package/esm/src/lib/types.js +1 -0
- package/esm/src/lib/utils.d.ts +17 -0
- package/esm/src/lib/utils.d.ts.map +1 -0
- package/esm/src/lib/utils.js +51 -0
- package/package.json +7 -3
- package/script/_dnt.polyfills.d.ts +83 -6
- package/script/_dnt.polyfills.d.ts.map +1 -0
- package/script/_dnt.polyfills.js +128 -0
- package/script/_dnt.shims.d.ts +1 -0
- package/script/_dnt.shims.d.ts.map +1 -0
- package/script/deno.d.ts +2 -0
- package/script/deno.d.ts.map +1 -0
- package/script/deno.js +2 -1
- package/script/src/commands/announcements.d.ts +1 -0
- package/script/src/commands/announcements.d.ts.map +1 -0
- package/script/src/commands/announcements.js +75 -222
- package/script/src/commands/auth.d.ts +1 -0
- package/script/src/commands/auth.d.ts.map +1 -0
- package/script/src/commands/auth.js +49 -17
- package/script/src/commands/calendar.d.ts +1 -0
- package/script/src/commands/calendar.d.ts.map +1 -0
- package/script/src/commands/calendar.js +112 -301
- package/script/src/commands/courses.d.ts +1 -0
- package/script/src/commands/courses.d.ts.map +1 -0
- package/script/src/commands/courses.js +43 -173
- package/script/src/commands/forums.d.ts +1 -0
- package/script/src/commands/forums.d.ts.map +1 -0
- package/script/src/commands/forums.js +145 -311
- package/script/src/commands/grades.d.ts +1 -0
- package/script/src/commands/grades.d.ts.map +1 -0
- package/script/src/commands/grades.js +62 -194
- package/script/src/commands/materials.d.ts +1 -0
- package/script/src/commands/materials.d.ts.map +1 -0
- package/script/src/commands/materials.js +111 -166
- package/script/src/commands/quizzes.d.ts +1 -0
- package/script/src/commands/quizzes.d.ts.map +1 -0
- package/script/src/commands/quizzes.js +40 -102
- package/script/src/commands/skills.d.ts +1 -0
- package/script/src/commands/skills.d.ts.map +1 -0
- package/script/src/commands/skills.js +17 -18
- package/script/src/commands/videos.d.ts +1 -0
- package/script/src/commands/videos.d.ts.map +1 -0
- package/script/src/commands/videos.js +26 -52
- package/script/src/index.d.ts +1 -0
- package/script/src/index.d.ts.map +1 -0
- package/script/src/index.js +4 -4
- package/script/src/lib/auth.d.ts +1 -0
- package/script/src/lib/auth.d.ts.map +1 -0
- package/script/src/lib/auth.js +9 -10
- package/script/src/lib/config.d.ts +1 -0
- package/script/src/lib/config.d.ts.map +1 -0
- package/script/src/lib/config.js +6 -7
- package/script/src/lib/logger.d.ts +1 -0
- package/script/src/lib/logger.d.ts.map +1 -0
- package/script/src/lib/logger.js +1 -2
- package/script/src/lib/moodle.d.ts +25 -54
- package/script/src/lib/moodle.d.ts.map +1 -0
- package/script/src/lib/moodle.js +103 -324
- package/script/src/lib/session.d.ts +1 -0
- package/script/src/lib/session.d.ts.map +1 -0
- package/script/src/lib/session.js +3 -29
- package/script/src/lib/token.d.ts +16 -5
- package/script/src/lib/token.d.ts.map +1 -0
- package/script/src/lib/token.js +71 -36
- package/script/src/lib/types.d.ts +10 -0
- package/script/src/lib/types.d.ts.map +1 -0
- package/script/src/lib/utils.d.ts +12 -0
- package/script/src/lib/utils.d.ts.map +1 -0
- package/script/src/lib/utils.js +57 -11
- package/skills/openape/SKILL.md +331 -328
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/src/lib/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEjE;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CA6CtB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract Moodle sesskey from the current page.
|
|
3
|
+
* The sesskey is required for all AJAX calls.
|
|
4
|
+
*/
|
|
5
|
+
export async function extractSessionInfo(page, config, log, wsToken) {
|
|
6
|
+
// Ensure we're on a Moodle page
|
|
7
|
+
const url = page.url();
|
|
8
|
+
if (!url.includes(config.moodleBaseUrl.replace("https://", ""))) {
|
|
9
|
+
await page.goto(`${config.moodleBaseUrl}/my/`, {
|
|
10
|
+
waitUntil: "domcontentloaded",
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
// Try extracting sesskey from M.cfg (Moodle's JS config object)
|
|
14
|
+
// Use string to avoid dnt transforming globalThis/window to dntShim
|
|
15
|
+
let sesskey = await page.evaluate("() => self.M?.cfg?.sesskey ?? null");
|
|
16
|
+
// Fallback: extract from a hidden input
|
|
17
|
+
if (!sesskey) {
|
|
18
|
+
sesskey = await page.evaluate(() => {
|
|
19
|
+
const el = document.querySelector('input[name="sesskey"]');
|
|
20
|
+
return el?.value ?? null;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Fallback: regex on page source
|
|
24
|
+
if (!sesskey) {
|
|
25
|
+
const content = await page.content();
|
|
26
|
+
const match = content.match(/"sesskey"\s*:\s*"([a-zA-Z0-9]+)"/);
|
|
27
|
+
sesskey = match?.[1] ?? null;
|
|
28
|
+
}
|
|
29
|
+
if (!sesskey) {
|
|
30
|
+
throw new Error("Failed to extract sesskey from Moodle page.");
|
|
31
|
+
}
|
|
32
|
+
log.debug(`Extracted sesskey: ${sesskey}`);
|
|
33
|
+
const sessionInfo = {
|
|
34
|
+
sesskey,
|
|
35
|
+
moodleBaseUrl: config.moodleBaseUrl,
|
|
36
|
+
};
|
|
37
|
+
if (wsToken) {
|
|
38
|
+
sessionInfo.wsToken = wsToken;
|
|
39
|
+
log.debug("Web Service Token included in session");
|
|
40
|
+
}
|
|
41
|
+
return sessionInfo;
|
|
42
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Page } from "playwright-core";
|
|
2
|
+
import type { AppConfig, Logger } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Get the session metadata file path from the auth state path.
|
|
5
|
+
* E.g., .auth/storage-state.json -> .auth/session-meta.json
|
|
6
|
+
*/
|
|
7
|
+
export declare function getSessionMetaPath(authStatePath: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Load sesskey from metadata if it exists and is valid.
|
|
10
|
+
* Sesskey is typically valid for 6 hours.
|
|
11
|
+
*/
|
|
12
|
+
export declare function loadSesskey(authStatePath: string): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Save sesskey to metadata.
|
|
15
|
+
*/
|
|
16
|
+
export declare function saveSesskey(authStatePath: string, sesskey: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Load WS token from metadata if it exists and is valid.
|
|
19
|
+
* WS token is valid for 24 hours.
|
|
20
|
+
*/
|
|
21
|
+
export declare function loadWsToken(authStatePath: string): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Save WS token to metadata.
|
|
24
|
+
*/
|
|
25
|
+
export declare function saveWsToken(authStatePath: string, token: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Acquire Moodle Web Service Token via mobile app launch endpoint.
|
|
28
|
+
*
|
|
29
|
+
* Process:
|
|
30
|
+
* 1. Visit admin/tool/mobile/launch.php with service=moodle_mobile_app
|
|
31
|
+
* 2. Server redirects to moodlemobile://token=BASE64_DATA (which causes ERR_ABORTED)
|
|
32
|
+
* 3. We catch the redirect from the response and extract the token
|
|
33
|
+
*
|
|
34
|
+
* @returns The Web Service Token for Moodle API calls
|
|
35
|
+
* @throws Error if token acquisition fails
|
|
36
|
+
*/
|
|
37
|
+
export declare function acquireWsToken(page: Page, config: AppConfig, log: Logger): Promise<string>;
|
|
38
|
+
//# sourceMappingURL=token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/src/lib/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAWpD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAGhE;AA8BD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAShE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAKxE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAShE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAKtE;AAuBD;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAsEjB"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Get the session metadata file path from the auth state path.
|
|
5
|
+
* E.g., .auth/storage-state.json -> .auth/session-meta.json
|
|
6
|
+
*/
|
|
7
|
+
export function getSessionMetaPath(authStatePath) {
|
|
8
|
+
const dir = path.dirname(authStatePath);
|
|
9
|
+
return path.join(dir, "session-meta.json");
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Load session metadata from file.
|
|
13
|
+
*/
|
|
14
|
+
function loadSessionMeta(authStatePath) {
|
|
15
|
+
const metaPath = getSessionMetaPath(authStatePath);
|
|
16
|
+
try {
|
|
17
|
+
if (fs.existsSync(metaPath)) {
|
|
18
|
+
const content = fs.readFileSync(metaPath, "utf8");
|
|
19
|
+
return JSON.parse(content);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Ignore errors, return empty meta
|
|
24
|
+
}
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Save session metadata to file.
|
|
29
|
+
*/
|
|
30
|
+
function saveSessionMeta(authStatePath, meta) {
|
|
31
|
+
const metaPath = getSessionMetaPath(authStatePath);
|
|
32
|
+
try {
|
|
33
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Ignore save errors
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Load sesskey from metadata if it exists and is valid.
|
|
41
|
+
* Sesskey is typically valid for 6 hours.
|
|
42
|
+
*/
|
|
43
|
+
export function loadSesskey(authStatePath) {
|
|
44
|
+
const meta = loadSessionMeta(authStatePath);
|
|
45
|
+
if (meta.sesskey && meta.sesskeyTimestamp) {
|
|
46
|
+
const age = Date.now() - meta.sesskeyTimestamp;
|
|
47
|
+
if (age < 6 * 60 * 60 * 1000) {
|
|
48
|
+
return meta.sesskey;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Save sesskey to metadata.
|
|
55
|
+
*/
|
|
56
|
+
export function saveSesskey(authStatePath, sesskey) {
|
|
57
|
+
const meta = loadSessionMeta(authStatePath);
|
|
58
|
+
meta.sesskey = sesskey;
|
|
59
|
+
meta.sesskeyTimestamp = Date.now();
|
|
60
|
+
saveSessionMeta(authStatePath, meta);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Load WS token from metadata if it exists and is valid.
|
|
64
|
+
* WS token is valid for 24 hours.
|
|
65
|
+
*/
|
|
66
|
+
export function loadWsToken(authStatePath) {
|
|
67
|
+
const meta = loadSessionMeta(authStatePath);
|
|
68
|
+
if (meta.wsToken && meta.wsTokenTimestamp) {
|
|
69
|
+
const age = Date.now() - meta.wsTokenTimestamp;
|
|
70
|
+
if (age < 24 * 60 * 60 * 1000) {
|
|
71
|
+
return meta.wsToken;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Save WS token to metadata.
|
|
78
|
+
*/
|
|
79
|
+
export function saveWsToken(authStatePath, token) {
|
|
80
|
+
const meta = loadSessionMeta(authStatePath);
|
|
81
|
+
meta.wsToken = token;
|
|
82
|
+
meta.wsTokenTimestamp = Date.now();
|
|
83
|
+
saveSessionMeta(authStatePath, meta);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Extract and decode the Web Service Token from moodlemobile:// URL
|
|
87
|
+
* Format: moodlemobile://token=BASE64_DATA
|
|
88
|
+
* Decoded: token:::site_url:::other_params
|
|
89
|
+
*/
|
|
90
|
+
function extractTokenFromCustomScheme(url) {
|
|
91
|
+
try {
|
|
92
|
+
const match = url.match(/token=([A-Za-z0-9+/=]+)/);
|
|
93
|
+
if (!match)
|
|
94
|
+
return null;
|
|
95
|
+
// Base64 decode the token data
|
|
96
|
+
const decoded = atob(match[1]);
|
|
97
|
+
const parts = decoded.split(":::");
|
|
98
|
+
// The second part (index 1) is the actual WS token
|
|
99
|
+
return parts.length >= 2 ? parts[1] : null;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Acquire Moodle Web Service Token via mobile app launch endpoint.
|
|
107
|
+
*
|
|
108
|
+
* Process:
|
|
109
|
+
* 1. Visit admin/tool/mobile/launch.php with service=moodle_mobile_app
|
|
110
|
+
* 2. Server redirects to moodlemobile://token=BASE64_DATA (which causes ERR_ABORTED)
|
|
111
|
+
* 3. We catch the redirect from the response and extract the token
|
|
112
|
+
*
|
|
113
|
+
* @returns The Web Service Token for Moodle API calls
|
|
114
|
+
* @throws Error if token acquisition fails
|
|
115
|
+
*/
|
|
116
|
+
export async function acquireWsToken(page, config, log) {
|
|
117
|
+
log.info("Acquiring Moodle Web Service Token...");
|
|
118
|
+
// Generate random UUID for passport parameter
|
|
119
|
+
const passport = crypto.randomUUID();
|
|
120
|
+
const launchUrl = `${config.moodleBaseUrl}/admin/tool/mobile/launch.php?service=moodle_mobile_app&passport=${passport}`;
|
|
121
|
+
log.debug(`Token acquisition URL: ${launchUrl}`);
|
|
122
|
+
// Set up response listener to catch the redirect
|
|
123
|
+
let tokenFound = false;
|
|
124
|
+
const tokenPromise = new Promise((resolve, reject) => {
|
|
125
|
+
const timeout = setTimeout(() => {
|
|
126
|
+
if (!tokenFound) {
|
|
127
|
+
page.off("response", responseHandler);
|
|
128
|
+
reject(new Error("Token acquisition timed out - no redirect received"));
|
|
129
|
+
}
|
|
130
|
+
}, 15000);
|
|
131
|
+
const responseHandler = async (response) => {
|
|
132
|
+
try {
|
|
133
|
+
const status = response.status();
|
|
134
|
+
const headers = response.headers();
|
|
135
|
+
// Check for redirect to custom scheme
|
|
136
|
+
const location = headers["location"] || headers["Location"];
|
|
137
|
+
if (location && location.startsWith("moodlemobile://")) {
|
|
138
|
+
clearTimeout(timeout);
|
|
139
|
+
tokenFound = true;
|
|
140
|
+
page.off("response", responseHandler);
|
|
141
|
+
const token = extractTokenFromCustomScheme(location);
|
|
142
|
+
if (token) {
|
|
143
|
+
resolve(token);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
reject(new Error("Failed to extract token from custom scheme URL"));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
// Ignore errors in response handler
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
page.on("response", responseHandler);
|
|
155
|
+
});
|
|
156
|
+
try {
|
|
157
|
+
// Navigate to the launch endpoint - expect it to fail with ERR_ABORTED
|
|
158
|
+
// because the browser can't handle moodlemobile:// scheme
|
|
159
|
+
await page.goto(launchUrl, {
|
|
160
|
+
waitUntil: "domcontentloaded",
|
|
161
|
+
timeout: 10000,
|
|
162
|
+
}).catch(() => {
|
|
163
|
+
// Expected: navigation will fail due to custom scheme redirect
|
|
164
|
+
// The token should have been captured by our response handler
|
|
165
|
+
log.debug("Navigation failed as expected (custom scheme redirect)");
|
|
166
|
+
});
|
|
167
|
+
// Wait for the intercepted token
|
|
168
|
+
const token = await tokenPromise;
|
|
169
|
+
log.success("Web Service Token acquired successfully");
|
|
170
|
+
log.debug(`Token (first 10 chars): ${token.substring(0, 10)}...`);
|
|
171
|
+
return token;
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
175
|
+
log.warn(`Failed to acquire WS Token: ${message}`);
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import type { Page } from "playwright-core";
|
|
2
|
+
export interface AppConfig {
|
|
3
|
+
courseUrl: string;
|
|
4
|
+
moodleBaseUrl: string;
|
|
5
|
+
headless: boolean;
|
|
6
|
+
slowMo: number;
|
|
7
|
+
authStatePath: string;
|
|
8
|
+
ollamaModel?: string;
|
|
9
|
+
ollamaBaseUrl: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SessionInfo {
|
|
12
|
+
sesskey: string;
|
|
13
|
+
moodleBaseUrl: string;
|
|
14
|
+
wsToken?: string;
|
|
15
|
+
wsTokenExpires?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface Logger {
|
|
18
|
+
info: (msg: string) => void;
|
|
19
|
+
success: (msg: string) => void;
|
|
20
|
+
warn: (msg: string) => void;
|
|
21
|
+
error: (msg: string) => void;
|
|
22
|
+
debug: (msg: string) => void;
|
|
23
|
+
}
|
|
24
|
+
export interface EnrolledCourse {
|
|
25
|
+
id: number;
|
|
26
|
+
fullname: string;
|
|
27
|
+
shortname: string;
|
|
28
|
+
idnumber?: string;
|
|
29
|
+
category?: string;
|
|
30
|
+
progress?: number;
|
|
31
|
+
startdate?: number;
|
|
32
|
+
enddate?: number;
|
|
33
|
+
}
|
|
34
|
+
export interface SuperVideoModule {
|
|
35
|
+
cmid: string;
|
|
36
|
+
name: string;
|
|
37
|
+
url: string;
|
|
38
|
+
isComplete: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface VideoActivity {
|
|
41
|
+
name: string;
|
|
42
|
+
url: string;
|
|
43
|
+
viewId: number;
|
|
44
|
+
duration: number;
|
|
45
|
+
existingPercent: number;
|
|
46
|
+
}
|
|
47
|
+
export interface QuizModule {
|
|
48
|
+
cmid: string;
|
|
49
|
+
name: string;
|
|
50
|
+
url: string;
|
|
51
|
+
isComplete: boolean;
|
|
52
|
+
timeOpen?: number;
|
|
53
|
+
timeClose?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface ForumModule {
|
|
56
|
+
cmid: string;
|
|
57
|
+
forumId: number;
|
|
58
|
+
name: string;
|
|
59
|
+
url: string;
|
|
60
|
+
courseId: number;
|
|
61
|
+
forumType: string;
|
|
62
|
+
}
|
|
63
|
+
export interface ForumPost {
|
|
64
|
+
id: number;
|
|
65
|
+
subject: string;
|
|
66
|
+
author: string;
|
|
67
|
+
authorId?: number;
|
|
68
|
+
created: number;
|
|
69
|
+
modified: number;
|
|
70
|
+
message: string;
|
|
71
|
+
discussionId: number;
|
|
72
|
+
replies?: ForumPost[];
|
|
73
|
+
unread?: boolean;
|
|
74
|
+
}
|
|
75
|
+
export interface ForumDiscussion {
|
|
76
|
+
id: number;
|
|
77
|
+
forumId: number;
|
|
78
|
+
name: string;
|
|
79
|
+
firstPostId: number;
|
|
80
|
+
userId: number;
|
|
81
|
+
userFullName: string;
|
|
82
|
+
groupId?: number;
|
|
83
|
+
timedue?: number;
|
|
84
|
+
timeModified: number;
|
|
85
|
+
timeStart?: number;
|
|
86
|
+
timeEnd?: number;
|
|
87
|
+
userModified?: number;
|
|
88
|
+
userModifiedFullName?: string;
|
|
89
|
+
postCount?: number;
|
|
90
|
+
unread?: boolean;
|
|
91
|
+
subject?: string;
|
|
92
|
+
message?: string;
|
|
93
|
+
pinned?: boolean;
|
|
94
|
+
locked?: boolean;
|
|
95
|
+
starred?: boolean;
|
|
96
|
+
}
|
|
97
|
+
export interface AnnouncementPost {
|
|
98
|
+
id: number;
|
|
99
|
+
subject: string;
|
|
100
|
+
content: string;
|
|
101
|
+
author: string;
|
|
102
|
+
authorId?: number;
|
|
103
|
+
courseId: number;
|
|
104
|
+
createdAt: number;
|
|
105
|
+
modifiedAt?: number;
|
|
106
|
+
attachments?: AnnouncementAttachment[];
|
|
107
|
+
unread?: boolean;
|
|
108
|
+
}
|
|
109
|
+
export interface AnnouncementAttachment {
|
|
110
|
+
filename: string;
|
|
111
|
+
url: string;
|
|
112
|
+
filesize: number;
|
|
113
|
+
mimetype: string;
|
|
114
|
+
}
|
|
115
|
+
export interface ResourceModule {
|
|
116
|
+
cmid: string;
|
|
117
|
+
name: string;
|
|
118
|
+
url: string;
|
|
119
|
+
courseId: number;
|
|
120
|
+
modType: string;
|
|
121
|
+
mimetype?: string;
|
|
122
|
+
filesize?: number;
|
|
123
|
+
modified?: number;
|
|
124
|
+
}
|
|
125
|
+
export interface FolderContents {
|
|
126
|
+
files: ResourceFile[];
|
|
127
|
+
folders: FolderInfo[];
|
|
128
|
+
}
|
|
129
|
+
export interface ResourceFile {
|
|
130
|
+
filename: string;
|
|
131
|
+
url: string;
|
|
132
|
+
filesize: number;
|
|
133
|
+
mimetype: string;
|
|
134
|
+
modified: number;
|
|
135
|
+
path?: string;
|
|
136
|
+
}
|
|
137
|
+
export interface FolderInfo {
|
|
138
|
+
name: string;
|
|
139
|
+
id: number;
|
|
140
|
+
path: string;
|
|
141
|
+
}
|
|
142
|
+
export interface AssignmentModule {
|
|
143
|
+
cmid: string;
|
|
144
|
+
name: string;
|
|
145
|
+
url: string;
|
|
146
|
+
courseId: number;
|
|
147
|
+
duedate?: number;
|
|
148
|
+
cutoffdate?: number;
|
|
149
|
+
allowSubmissionsFromDate?: number;
|
|
150
|
+
gradingduedate?: number;
|
|
151
|
+
submissionStatus?: string;
|
|
152
|
+
grade?: GradeInfo;
|
|
153
|
+
lateSubmission?: boolean;
|
|
154
|
+
extensionduedate?: number;
|
|
155
|
+
}
|
|
156
|
+
export interface AssignmentSubmission {
|
|
157
|
+
id: number;
|
|
158
|
+
assignmentId: number;
|
|
159
|
+
userId: number;
|
|
160
|
+
timemodified: number;
|
|
161
|
+
status: string;
|
|
162
|
+
files?: SubmissionFile[];
|
|
163
|
+
grade?: GradeInfo;
|
|
164
|
+
feedback?: string;
|
|
165
|
+
}
|
|
166
|
+
export interface SubmissionFile {
|
|
167
|
+
filename: string;
|
|
168
|
+
url: string;
|
|
169
|
+
filesize: number;
|
|
170
|
+
mimetype: string;
|
|
171
|
+
timemodified: number;
|
|
172
|
+
}
|
|
173
|
+
export interface GradeInfo {
|
|
174
|
+
grade: string;
|
|
175
|
+
gradeFormatted: string;
|
|
176
|
+
grader?: string;
|
|
177
|
+
timedue?: number;
|
|
178
|
+
timemodified?: number;
|
|
179
|
+
}
|
|
180
|
+
export interface CourseGrade {
|
|
181
|
+
courseId: number;
|
|
182
|
+
courseName: string;
|
|
183
|
+
grade?: string;
|
|
184
|
+
gradeFormatted?: string;
|
|
185
|
+
rank?: number;
|
|
186
|
+
totalUsers?: number;
|
|
187
|
+
items?: GradeItem[];
|
|
188
|
+
}
|
|
189
|
+
export interface GradeItem {
|
|
190
|
+
id: number;
|
|
191
|
+
name: string;
|
|
192
|
+
grade?: string;
|
|
193
|
+
gradeFormatted?: string;
|
|
194
|
+
range?: string;
|
|
195
|
+
percentage?: number;
|
|
196
|
+
weight?: number;
|
|
197
|
+
feedback?: string;
|
|
198
|
+
graded?: boolean;
|
|
199
|
+
}
|
|
200
|
+
export interface CalendarEvent {
|
|
201
|
+
id: number;
|
|
202
|
+
name: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
format: number;
|
|
205
|
+
courseid?: number;
|
|
206
|
+
categoryid?: number;
|
|
207
|
+
groupid?: number;
|
|
208
|
+
userid?: number;
|
|
209
|
+
moduleid?: number;
|
|
210
|
+
modulename?: string;
|
|
211
|
+
instance?: number;
|
|
212
|
+
eventtype: string;
|
|
213
|
+
timestart: number;
|
|
214
|
+
timeduration?: number;
|
|
215
|
+
timedue?: number;
|
|
216
|
+
visible?: number;
|
|
217
|
+
location?: string;
|
|
218
|
+
}
|
|
219
|
+
export interface QuestionParsing {
|
|
220
|
+
id: string;
|
|
221
|
+
text: string;
|
|
222
|
+
options: {
|
|
223
|
+
value: string;
|
|
224
|
+
text: string;
|
|
225
|
+
}[];
|
|
226
|
+
type: "radio" | "checkbox";
|
|
227
|
+
}
|
|
228
|
+
export interface QuestionAnswer {
|
|
229
|
+
questionId: string;
|
|
230
|
+
reasoning: string;
|
|
231
|
+
answerValues: string[];
|
|
232
|
+
}
|
|
233
|
+
export type OutputFormat = "json" | "csv" | "table" | "silent";
|
|
234
|
+
export interface OutputOptions {
|
|
235
|
+
format: OutputFormat;
|
|
236
|
+
fields?: string[];
|
|
237
|
+
pretty?: boolean;
|
|
238
|
+
}
|
|
239
|
+
export interface ProgressPayload {
|
|
240
|
+
view_id: number;
|
|
241
|
+
currenttime: number;
|
|
242
|
+
duration: number;
|
|
243
|
+
percent: number;
|
|
244
|
+
mapa: string;
|
|
245
|
+
}
|
|
246
|
+
export interface AjaxResponse {
|
|
247
|
+
error: boolean;
|
|
248
|
+
data?: {
|
|
249
|
+
success?: boolean;
|
|
250
|
+
exec?: string;
|
|
251
|
+
};
|
|
252
|
+
exception?: {
|
|
253
|
+
message: string;
|
|
254
|
+
errorcode: string;
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
export interface CommandContext {
|
|
258
|
+
page: Page;
|
|
259
|
+
session: SessionInfo;
|
|
260
|
+
config: AppConfig;
|
|
261
|
+
log: Logger;
|
|
262
|
+
}
|
|
263
|
+
export interface CommandOptions {
|
|
264
|
+
output?: OutputFormat;
|
|
265
|
+
courseUrl?: string;
|
|
266
|
+
courseId?: number;
|
|
267
|
+
verbose?: boolean;
|
|
268
|
+
headed?: boolean;
|
|
269
|
+
dryRun?: boolean;
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAID,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAID,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAID,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3C,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAID,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAID,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,SAAS,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACpD;AAID,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,SAAS,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the base directory for config/storage resolving.
|
|
3
|
+
* Handles both Deno (raw/compiled) and Node.js (npx).
|
|
4
|
+
*/
|
|
5
|
+
export declare function getBaseDir(): string;
|
|
6
|
+
/**
|
|
7
|
+
* Strip HTML tags from a string.
|
|
8
|
+
* Preserves text content while removing all HTML markup.
|
|
9
|
+
*/
|
|
10
|
+
export declare function stripHtmlTags(html: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Extract clean course name from Moodle fullname.
|
|
13
|
+
* Removes mlang tags, course codes, and instructor info.
|
|
14
|
+
* Example: "{mlang zh-tw}1142爵士樂賞析(遠距)-楊曊恩..." -> "爵士樂賞析"
|
|
15
|
+
*/
|
|
16
|
+
export declare function extractCourseName(fullname: string): string;
|
|
17
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/src/lib/utils.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CASnC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAelD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO1D"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Returns the base directory for config/storage resolving.
|
|
5
|
+
* Handles both Deno (raw/compiled) and Node.js (npx).
|
|
6
|
+
*/
|
|
7
|
+
export function getBaseDir() {
|
|
8
|
+
// @ts-ignore - Deno global is available in Deno
|
|
9
|
+
if (typeof dntShim.Deno !== "undefined" && typeof dntShim.Deno.execPath === "function") {
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const exeDir = dirname(dntShim.Deno.execPath());
|
|
12
|
+
return exeDir.includes("deno") ? process.cwd() : exeDir;
|
|
13
|
+
}
|
|
14
|
+
// Node.js or dnt runtime
|
|
15
|
+
return process.cwd();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Strip HTML tags from a string.
|
|
19
|
+
* Preserves text content while removing all HTML markup.
|
|
20
|
+
*/
|
|
21
|
+
export function stripHtmlTags(html) {
|
|
22
|
+
if (!html)
|
|
23
|
+
return "";
|
|
24
|
+
// Remove HTML tags
|
|
25
|
+
return html.replace(/<[^>]*>/g, "")
|
|
26
|
+
// Replace HTML entities with their characters
|
|
27
|
+
.replace(/ /g, " ")
|
|
28
|
+
.replace(/&/g, "&")
|
|
29
|
+
.replace(/</g, "<")
|
|
30
|
+
.replace(/>/g, ">")
|
|
31
|
+
.replace(/"/g, '"')
|
|
32
|
+
.replace(/'/g, "'")
|
|
33
|
+
.replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(parseInt(dec, 10)))
|
|
34
|
+
// Clean up excessive whitespace
|
|
35
|
+
.replace(/\s+/g, " ")
|
|
36
|
+
.trim();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Extract clean course name from Moodle fullname.
|
|
40
|
+
* Removes mlang tags, course codes, and instructor info.
|
|
41
|
+
* Example: "{mlang zh-tw}1142爵士樂賞析(遠距)-楊曊恩..." -> "爵士樂賞析"
|
|
42
|
+
*/
|
|
43
|
+
export function extractCourseName(fullname) {
|
|
44
|
+
if (!fullname)
|
|
45
|
+
return "";
|
|
46
|
+
// Remove {mlang ...} tags
|
|
47
|
+
let cleaned = fullname.replace(/\{mlang[^}]*\}/g, "");
|
|
48
|
+
// Match: 4+ digits + course name (until (, -, or [)
|
|
49
|
+
const match = cleaned.match(/\d{4,}([^([-]+)/);
|
|
50
|
+
return match ? match[1].trim() : fullname;
|
|
51
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mo7yw4ng/openape",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "CLI tool for CYCU i-Learning platform",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ilearning",
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
],
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "
|
|
15
|
+
"url": "https://github.com/MO7YW4NG/openape"
|
|
16
16
|
},
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"bugs": {
|
|
19
19
|
"url": "https://github.com/mo7yw4ng/openape/issues"
|
|
20
20
|
},
|
|
21
|
+
"scripts": {},
|
|
21
22
|
"bin": {
|
|
22
23
|
"openape": "./script/src/index.js"
|
|
23
24
|
},
|
|
@@ -25,10 +26,13 @@
|
|
|
25
26
|
"node": ">=18.0.0"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
29
|
+
"commander": "^12.1.0",
|
|
30
|
+
"node-html-parser": "^6.1.13",
|
|
31
|
+
"playwright-core": "^1.48.0",
|
|
28
32
|
"@deno/shim-deno": "~0.18.0"
|
|
29
33
|
},
|
|
30
34
|
"devDependencies": {
|
|
31
35
|
"@types/node": "^20.9.0"
|
|
32
36
|
},
|
|
33
|
-
"_generatedBy": "dnt@
|
|
37
|
+
"_generatedBy": "dnt@dev"
|
|
34
38
|
}
|