@mo7yw4ng/openape 1.0.1 → 1.0.3
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/README.md +8 -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 +260 -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 +226 -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 +522 -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 +335 -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 +251 -0
- package/esm/src/lib/moodle.d.ts.map +1 -0
- package/esm/src/lib/moodle.js +833 -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 +272 -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 +37 -0
- package/esm/src/lib/utils.d.ts.map +1 -0
- package/esm/src/lib/utils.js +82 -0
- package/package.json +4 -4
- 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 +2 -1
- package/script/src/commands/auth.d.ts.map +1 -0
- package/script/src/commands/auth.js +52 -24
- 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 -316
- 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 +283 -178
- 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 +127 -120
- package/script/src/index.d.ts +1 -0
- package/script/src/index.d.ts.map +1 -0
- package/script/src/index.js +5 -5
- 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 +72 -55
- package/script/src/lib/moodle.d.ts.map +1 -0
- package/script/src/lib/moodle.js +275 -350
- 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 +11 -0
- package/script/src/lib/types.d.ts.map +1 -0
- package/script/src/lib/utils.d.ts +32 -0
- package/script/src/lib/utils.d.ts.map +1 -0
- package/script/src/lib/utils.js +93 -13
- package/skills/openape/SKILL.md +6 -26
|
@@ -5,3 +5,4 @@ import type { AppConfig, Logger, SessionInfo } from "./types.js";
|
|
|
5
5
|
* The sesskey is required for all AJAX calls.
|
|
6
6
|
*/
|
|
7
7
|
export declare function extractSessionInfo(page: Page, config: AppConfig, log: Logger, wsToken?: string): Promise<SessionInfo>;
|
|
8
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -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"}
|
|
@@ -1,30 +1,6 @@
|
|
|
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 (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.extractSessionInfo =
|
|
27
|
-
const dntShim = __importStar(require("../../_dnt.shims.js"));
|
|
3
|
+
exports.extractSessionInfo = extractSessionInfo;
|
|
28
4
|
/**
|
|
29
5
|
* Extract Moodle sesskey from the current page.
|
|
30
6
|
* The sesskey is required for all AJAX calls.
|
|
@@ -38,9 +14,8 @@ async function extractSessionInfo(page, config, log, wsToken) {
|
|
|
38
14
|
});
|
|
39
15
|
}
|
|
40
16
|
// Try extracting sesskey from M.cfg (Moodle's JS config object)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
17
|
+
// Use string to avoid dnt transforming globalThis/window to dntShim
|
|
18
|
+
let sesskey = await page.evaluate("() => self.M?.cfg?.sesskey ?? null");
|
|
44
19
|
// Fallback: extract from a hidden input
|
|
45
20
|
if (!sesskey) {
|
|
46
21
|
sesskey = await page.evaluate(() => {
|
|
@@ -68,4 +43,3 @@ async function extractSessionInfo(page, config, log, wsToken) {
|
|
|
68
43
|
}
|
|
69
44
|
return sessionInfo;
|
|
70
45
|
}
|
|
71
|
-
exports.extractSessionInfo = extractSessionInfo;
|
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
import type { Page } from "playwright-core";
|
|
2
2
|
import type { AppConfig, Logger } from "./types.js";
|
|
3
3
|
/**
|
|
4
|
-
* Get the
|
|
5
|
-
* E.g., .auth/storage-state.json -> .auth/
|
|
4
|
+
* Get the session metadata file path from the auth state path.
|
|
5
|
+
* E.g., .auth/storage-state.json -> .auth/session-meta.json
|
|
6
6
|
*/
|
|
7
|
-
export declare function
|
|
7
|
+
export declare function getSessionMetaPath(authStatePath: string): string;
|
|
8
8
|
/**
|
|
9
|
-
* Load
|
|
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.
|
|
10
20
|
*/
|
|
11
21
|
export declare function loadWsToken(authStatePath: string): string | null;
|
|
12
22
|
/**
|
|
13
|
-
* Save WS token to
|
|
23
|
+
* Save WS token to metadata.
|
|
14
24
|
*/
|
|
15
25
|
export declare function saveWsToken(authStatePath: string, token: string): void;
|
|
16
26
|
/**
|
|
@@ -25,3 +35,4 @@ export declare function saveWsToken(authStatePath: string, token: string): void;
|
|
|
25
35
|
* @throws Error if token acquisition fails
|
|
26
36
|
*/
|
|
27
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"}
|
package/script/src/lib/token.js
CHANGED
|
@@ -3,60 +3,96 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
exports.getSessionMetaPath = getSessionMetaPath;
|
|
7
|
+
exports.loadSesskey = loadSesskey;
|
|
8
|
+
exports.saveSesskey = saveSesskey;
|
|
9
|
+
exports.loadWsToken = loadWsToken;
|
|
10
|
+
exports.saveWsToken = saveWsToken;
|
|
11
|
+
exports.acquireWsToken = acquireWsToken;
|
|
12
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
14
|
/**
|
|
10
|
-
* Get the
|
|
11
|
-
* E.g., .auth/storage-state.json -> .auth/
|
|
15
|
+
* Get the session metadata file path from the auth state path.
|
|
16
|
+
* E.g., .auth/storage-state.json -> .auth/session-meta.json
|
|
12
17
|
*/
|
|
13
|
-
function
|
|
14
|
-
const dir =
|
|
15
|
-
return
|
|
18
|
+
function getSessionMetaPath(authStatePath) {
|
|
19
|
+
const dir = node_path_1.default.dirname(authStatePath);
|
|
20
|
+
return node_path_1.default.join(dir, "session-meta.json");
|
|
16
21
|
}
|
|
17
|
-
exports.getWsTokenPath = getWsTokenPath;
|
|
18
22
|
/**
|
|
19
|
-
* Load
|
|
23
|
+
* Load session metadata from file.
|
|
20
24
|
*/
|
|
21
|
-
function
|
|
22
|
-
const
|
|
25
|
+
function loadSessionMeta(authStatePath) {
|
|
26
|
+
const metaPath = getSessionMetaPath(authStatePath);
|
|
23
27
|
try {
|
|
24
|
-
if (
|
|
25
|
-
const content =
|
|
26
|
-
|
|
27
|
-
// Check if token is not too old (Moodle tokens typically expire after some time)
|
|
28
|
-
if (data.token && data.timestamp) {
|
|
29
|
-
const age = Date.now() - data.timestamp;
|
|
30
|
-
// Consider token valid if less than 24 hours old
|
|
31
|
-
if (age < 24 * 60 * 60 * 1000) {
|
|
32
|
-
return data.token;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
28
|
+
if (node_fs_1.default.existsSync(metaPath)) {
|
|
29
|
+
const content = node_fs_1.default.readFileSync(metaPath, "utf8");
|
|
30
|
+
return JSON.parse(content);
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
33
|
catch {
|
|
38
|
-
// Ignore errors,
|
|
34
|
+
// Ignore errors, return empty meta
|
|
39
35
|
}
|
|
40
|
-
return
|
|
36
|
+
return {};
|
|
41
37
|
}
|
|
42
|
-
exports.loadWsToken = loadWsToken;
|
|
43
38
|
/**
|
|
44
|
-
* Save
|
|
39
|
+
* Save session metadata to file.
|
|
45
40
|
*/
|
|
46
|
-
function
|
|
47
|
-
const
|
|
41
|
+
function saveSessionMeta(authStatePath, meta) {
|
|
42
|
+
const metaPath = getSessionMetaPath(authStatePath);
|
|
48
43
|
try {
|
|
49
|
-
|
|
50
|
-
token,
|
|
51
|
-
timestamp: Date.now(),
|
|
52
|
-
};
|
|
53
|
-
fs_1.default.writeFileSync(tokenPath, JSON.stringify(data, null, 2));
|
|
44
|
+
node_fs_1.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
54
45
|
}
|
|
55
46
|
catch {
|
|
56
47
|
// Ignore save errors
|
|
57
48
|
}
|
|
58
49
|
}
|
|
59
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Load sesskey from metadata if it exists and is valid.
|
|
52
|
+
* Sesskey is typically valid for 6 hours.
|
|
53
|
+
*/
|
|
54
|
+
function loadSesskey(authStatePath) {
|
|
55
|
+
const meta = loadSessionMeta(authStatePath);
|
|
56
|
+
if (meta.sesskey && meta.sesskeyTimestamp) {
|
|
57
|
+
const age = Date.now() - meta.sesskeyTimestamp;
|
|
58
|
+
if (age < 6 * 60 * 60 * 1000) {
|
|
59
|
+
return meta.sesskey;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Save sesskey to metadata.
|
|
66
|
+
*/
|
|
67
|
+
function saveSesskey(authStatePath, sesskey) {
|
|
68
|
+
const meta = loadSessionMeta(authStatePath);
|
|
69
|
+
meta.sesskey = sesskey;
|
|
70
|
+
meta.sesskeyTimestamp = Date.now();
|
|
71
|
+
saveSessionMeta(authStatePath, meta);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Load WS token from metadata if it exists and is valid.
|
|
75
|
+
* WS token is valid for 24 hours.
|
|
76
|
+
*/
|
|
77
|
+
function loadWsToken(authStatePath) {
|
|
78
|
+
const meta = loadSessionMeta(authStatePath);
|
|
79
|
+
if (meta.wsToken && meta.wsTokenTimestamp) {
|
|
80
|
+
const age = Date.now() - meta.wsTokenTimestamp;
|
|
81
|
+
if (age < 24 * 60 * 60 * 1000) {
|
|
82
|
+
return meta.wsToken;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Save WS token to metadata.
|
|
89
|
+
*/
|
|
90
|
+
function saveWsToken(authStatePath, token) {
|
|
91
|
+
const meta = loadSessionMeta(authStatePath);
|
|
92
|
+
meta.wsToken = token;
|
|
93
|
+
meta.wsTokenTimestamp = Date.now();
|
|
94
|
+
saveSessionMeta(authStatePath, meta);
|
|
95
|
+
}
|
|
60
96
|
/**
|
|
61
97
|
* Extract and decode the Web Service Token from moodlemobile:// URL
|
|
62
98
|
* Format: moodlemobile://token=BASE64_DATA
|
|
@@ -151,4 +187,3 @@ async function acquireWsToken(page, config, log) {
|
|
|
151
187
|
throw error;
|
|
152
188
|
}
|
|
153
189
|
}
|
|
154
|
-
exports.acquireWsToken = acquireWsToken;
|
|
@@ -35,6 +35,7 @@ export interface SuperVideoModule {
|
|
|
35
35
|
cmid: string;
|
|
36
36
|
name: string;
|
|
37
37
|
url: string;
|
|
38
|
+
instance?: number;
|
|
38
39
|
isComplete: boolean;
|
|
39
40
|
}
|
|
40
41
|
export interface VideoActivity {
|
|
@@ -78,12 +79,21 @@ export interface ForumDiscussion {
|
|
|
78
79
|
name: string;
|
|
79
80
|
firstPostId: number;
|
|
80
81
|
userId: number;
|
|
82
|
+
userFullName: string;
|
|
81
83
|
groupId?: number;
|
|
82
84
|
timedue?: number;
|
|
83
85
|
timeModified: number;
|
|
86
|
+
timeStart?: number;
|
|
87
|
+
timeEnd?: number;
|
|
84
88
|
userModified?: number;
|
|
89
|
+
userModifiedFullName?: string;
|
|
85
90
|
postCount?: number;
|
|
86
91
|
unread?: boolean;
|
|
92
|
+
subject?: string;
|
|
93
|
+
message?: string;
|
|
94
|
+
pinned?: boolean;
|
|
95
|
+
locked?: boolean;
|
|
96
|
+
starred?: boolean;
|
|
87
97
|
}
|
|
88
98
|
export interface AnnouncementPost {
|
|
89
99
|
id: number;
|
|
@@ -259,3 +269,4 @@ export interface CommandOptions {
|
|
|
259
269
|
headed?: boolean;
|
|
260
270
|
dryRun?: boolean;
|
|
261
271
|
}
|
|
272
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/src/lib/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,37 @@
|
|
|
1
|
+
import type { OutputFormat } from "./types.js";
|
|
1
2
|
/**
|
|
2
3
|
* Returns the base directory for config/storage resolving.
|
|
3
4
|
* Handles both Deno (raw/compiled) and Node.js (npx).
|
|
4
5
|
*/
|
|
5
6
|
export declare function getBaseDir(): string;
|
|
7
|
+
/**
|
|
8
|
+
* Strip HTML tags from a string.
|
|
9
|
+
* Preserves text content while removing all HTML markup.
|
|
10
|
+
*/
|
|
11
|
+
export declare function stripHtmlTags(html: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Extract clean course name from Moodle fullname.
|
|
14
|
+
* Removes mlang tags, course codes, and instructor info.
|
|
15
|
+
* Example: "{mlang zh-tw}1142爵士樂賞析(遠距)-楊曊恩..." -> "爵士樂賞析"
|
|
16
|
+
*/
|
|
17
|
+
export declare function extractCourseName(fullname: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Get output format from command options (global or local).
|
|
20
|
+
* Defaults to "json" if not specified.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getOutputFormat(command: {
|
|
23
|
+
optsWithGlobals(): {
|
|
24
|
+
output?: OutputFormat;
|
|
25
|
+
};
|
|
26
|
+
}): OutputFormat;
|
|
27
|
+
/**
|
|
28
|
+
* Determine if logs should be silenced based on output format and verbosity.
|
|
29
|
+
* JSON output without verbose flag silences logs.
|
|
30
|
+
*/
|
|
31
|
+
export declare function shouldSilenceLogs(outputFormat: OutputFormat, verbose?: boolean): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Sanitize filename by removing invalid characters and limiting length.
|
|
34
|
+
* Replaces invalid characters with underscores and limits to maxLength.
|
|
35
|
+
*/
|
|
36
|
+
export declare function sanitizeFilename(name: string, maxLength?: number): string;
|
|
37
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/src/lib/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAcnC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAelD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IAAE,eAAe,IAAI;QAAE,MAAM,CAAC,EAAE,YAAY,CAAA;KAAE,CAAA;CAAE,GAAG,YAAY,CAGvG;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAExF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,CAK9E"}
|
package/script/src/lib/utils.js
CHANGED
|
@@ -15,17 +15,32 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
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
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.getBaseDir =
|
|
36
|
+
exports.getBaseDir = getBaseDir;
|
|
37
|
+
exports.stripHtmlTags = stripHtmlTags;
|
|
38
|
+
exports.extractCourseName = extractCourseName;
|
|
39
|
+
exports.getOutputFormat = getOutputFormat;
|
|
40
|
+
exports.shouldSilenceLogs = shouldSilenceLogs;
|
|
41
|
+
exports.sanitizeFilename = sanitizeFilename;
|
|
27
42
|
const dntShim = __importStar(require("../../_dnt.shims.js"));
|
|
28
|
-
const
|
|
43
|
+
const node_path_1 = require("node:path");
|
|
29
44
|
/**
|
|
30
45
|
* Returns the base directory for config/storage resolving.
|
|
31
46
|
* Handles both Deno (raw/compiled) and Node.js (npx).
|
|
@@ -33,11 +48,76 @@ const path_1 = require("path");
|
|
|
33
48
|
function getBaseDir() {
|
|
34
49
|
// @ts-ignore - Deno global is available in Deno
|
|
35
50
|
if (typeof dntShim.Deno !== "undefined" && typeof dntShim.Deno.execPath === "function") {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
51
|
+
try {
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
const exeDir = (0, node_path_1.dirname)(dntShim.Deno.execPath());
|
|
54
|
+
return exeDir.includes("deno") ? process.cwd() : exeDir;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Deno shim (dnt) or Deno not installed
|
|
58
|
+
return process.cwd();
|
|
59
|
+
}
|
|
39
60
|
}
|
|
40
61
|
// Node.js or dnt runtime
|
|
41
62
|
return process.cwd();
|
|
42
63
|
}
|
|
43
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Strip HTML tags from a string.
|
|
66
|
+
* Preserves text content while removing all HTML markup.
|
|
67
|
+
*/
|
|
68
|
+
function stripHtmlTags(html) {
|
|
69
|
+
if (!html)
|
|
70
|
+
return "";
|
|
71
|
+
// Remove HTML tags
|
|
72
|
+
return html.replace(/<[^>]*>/g, "")
|
|
73
|
+
// Replace HTML entities with their characters
|
|
74
|
+
.replace(/ /g, " ")
|
|
75
|
+
.replace(/&/g, "&")
|
|
76
|
+
.replace(/</g, "<")
|
|
77
|
+
.replace(/>/g, ">")
|
|
78
|
+
.replace(/"/g, '"')
|
|
79
|
+
.replace(/'/g, "'")
|
|
80
|
+
.replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(parseInt(dec, 10)))
|
|
81
|
+
// Clean up excessive whitespace
|
|
82
|
+
.replace(/\s+/g, " ")
|
|
83
|
+
.trim();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Extract clean course name from Moodle fullname.
|
|
87
|
+
* Removes mlang tags, course codes, and instructor info.
|
|
88
|
+
* Example: "{mlang zh-tw}1142爵士樂賞析(遠距)-楊曊恩..." -> "爵士樂賞析"
|
|
89
|
+
*/
|
|
90
|
+
function extractCourseName(fullname) {
|
|
91
|
+
if (!fullname)
|
|
92
|
+
return "";
|
|
93
|
+
// Remove {mlang ...} tags
|
|
94
|
+
let cleaned = fullname.replace(/\{mlang[^}]*\}/g, "");
|
|
95
|
+
// Match: 4+ digits + course name (until (, -, or [)
|
|
96
|
+
const match = cleaned.match(/\d{4,}([^([-]+)/);
|
|
97
|
+
return match ? match[1].trim() : fullname;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get output format from command options (global or local).
|
|
101
|
+
* Defaults to "json" if not specified.
|
|
102
|
+
*/
|
|
103
|
+
function getOutputFormat(command) {
|
|
104
|
+
const opts = command.optsWithGlobals();
|
|
105
|
+
return opts.output || "json";
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Determine if logs should be silenced based on output format and verbosity.
|
|
109
|
+
* JSON output without verbose flag silences logs.
|
|
110
|
+
*/
|
|
111
|
+
function shouldSilenceLogs(outputFormat, verbose) {
|
|
112
|
+
return outputFormat === "json" && !verbose;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Sanitize filename by removing invalid characters and limiting length.
|
|
116
|
+
* Replaces invalid characters with underscores and limits to maxLength.
|
|
117
|
+
*/
|
|
118
|
+
function sanitizeFilename(name, maxLength = 200) {
|
|
119
|
+
return name
|
|
120
|
+
.replace(/[<>:"/\\|?*]/g, "_")
|
|
121
|
+
.replace(/\s+/g, "_")
|
|
122
|
+
.substring(0, maxLength);
|
|
123
|
+
}
|
package/skills/openape/SKILL.md
CHANGED
|
@@ -9,39 +9,29 @@ Use the `openape` command to access CYCU iLearning (Moodle) platform. OpenApe pr
|
|
|
9
9
|
|
|
10
10
|
## Setup
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
If `openape` is not installed:
|
|
13
13
|
```bash
|
|
14
14
|
npm install -g @mo7yw4ng/openape
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Or run without installing:
|
|
18
|
-
```bash
|
|
19
|
-
npx @mo7yw4ng/openape --help
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Or install via Deno/JSR:
|
|
23
|
-
```bash
|
|
24
|
-
deno install -A -g -n openape jsr:@openape/openape
|
|
25
|
-
```
|
|
26
|
-
|
|
27
17
|
If not authenticated, run:
|
|
28
18
|
```bash
|
|
29
19
|
openape login
|
|
30
20
|
```
|
|
31
|
-
A browser will open for Microsoft OAuth SSO. Complete MFA login manually
|
|
21
|
+
A browser will open for Microsoft OAuth SSO. Complete MFA login manually.
|
|
32
22
|
|
|
33
23
|
Session is saved to `.auth/storage-state.json` and persists between runs. If session expires, run `openape login` again.
|
|
34
24
|
|
|
35
25
|
## Discovering Commands
|
|
36
26
|
|
|
37
|
-
Every command supports `--help` for full option details
|
|
27
|
+
**Every command supports `--help` for full option details:**
|
|
38
28
|
```bash
|
|
39
29
|
openape --help
|
|
40
30
|
openape courses --help
|
|
41
31
|
openape videos complete --help
|
|
42
32
|
```
|
|
43
33
|
|
|
44
|
-
Add `--output json` to any command for machine-readable output. Use `--output csv` for spreadsheet format, `--output table` for human-readable tables
|
|
34
|
+
Add `--output json` to any command for machine-readable output. Use `--output csv` for spreadsheet format, `--output table` for human-readable tables.
|
|
45
35
|
|
|
46
36
|
## Course Commands
|
|
47
37
|
|
|
@@ -94,18 +84,10 @@ openape videos list <course-id> --incomplete-only
|
|
|
94
84
|
# Complete all incomplete videos in a course
|
|
95
85
|
openape videos complete <course-id>
|
|
96
86
|
|
|
97
|
-
# Dry-run: discover videos without completing
|
|
98
|
-
openape videos complete <course-id> --dry-run
|
|
99
|
-
|
|
100
87
|
# Complete all incomplete videos across all courses
|
|
101
88
|
openape videos complete-all
|
|
102
|
-
|
|
103
|
-
# Dry-run all courses
|
|
104
|
-
openape videos complete-all --dry-run
|
|
105
89
|
```
|
|
106
90
|
|
|
107
|
-
**Note:** Video completion forges SuperVideo progress AJAX calls to simulate watching the entire video. The server accepts the progress but completion status may take time to update in the course state.
|
|
108
|
-
|
|
109
91
|
### Downloading videos
|
|
110
92
|
|
|
111
93
|
```bash
|
|
@@ -305,6 +287,7 @@ openape courses syllabus <course-id>
|
|
|
305
287
|
**Review discussions:** Catch up on forum activity.
|
|
306
288
|
```bash
|
|
307
289
|
openape forums list --level in_progress
|
|
290
|
+
openape forums list-all
|
|
308
291
|
openape forums discussions <forum-id>
|
|
309
292
|
openape forums posts <discussion-id>
|
|
310
293
|
```
|
|
@@ -323,9 +306,6 @@ openape materials download-all --level in_progress
|
|
|
323
306
|
|
|
324
307
|
## Tips
|
|
325
308
|
|
|
326
|
-
- Use `--dry-run` with `videos complete` to preview what will be completed
|
|
327
309
|
- Use `--level in_progress` (default) to focus on active courses
|
|
328
310
|
- Use `--output json` for scripting and automation
|
|
329
|
-
- Use `--output table` for human-readable output
|
|
330
|
-
- Session persists after login, no need to re-authenticate
|
|
331
|
-
- WS API mode is used by default for faster performance; browser mode is fallback
|
|
311
|
+
- Use `--output table` for human-readable output
|