@falkenslab/moodle-driver 0.0.0-stage → 0.4.0
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 -0
- package/README.md +131 -2
- package/dist/areas/activities/build.d.ts +98 -0
- package/dist/areas/activities/build.js +248 -0
- package/dist/areas/activities/build.js.map +1 -0
- package/dist/areas/activities/content.d.ts +53 -0
- package/dist/areas/activities/content.js +113 -0
- package/dist/areas/activities/content.js.map +1 -0
- package/dist/areas/assignments/grader.d.ts +68 -0
- package/dist/areas/assignments/grader.js +169 -0
- package/dist/areas/assignments/grader.js.map +1 -0
- package/dist/areas/assignments/grading.d.ts +86 -0
- package/dist/areas/assignments/grading.js +162 -0
- package/dist/areas/assignments/grading.js.map +1 -0
- package/dist/areas/assignments/student.d.ts +57 -0
- package/dist/areas/assignments/student.js +115 -0
- package/dist/areas/assignments/student.js.map +1 -0
- package/dist/areas/calendar/calendar.d.ts +43 -0
- package/dist/areas/calendar/calendar.js +84 -0
- package/dist/areas/calendar/calendar.js.map +1 -0
- package/dist/areas/completion/completion.d.ts +50 -0
- package/dist/areas/completion/completion.js +112 -0
- package/dist/areas/completion/completion.js.map +1 -0
- package/dist/areas/courses/list.d.ts +59 -0
- package/dist/areas/courses/list.js +74 -0
- package/dist/areas/courses/list.js.map +1 -0
- package/dist/areas/courses/overview.d.ts +83 -0
- package/dist/areas/courses/overview.js +137 -0
- package/dist/areas/courses/overview.js.map +1 -0
- package/dist/areas/courses/state.d.ts +51 -0
- package/dist/areas/courses/state.js +45 -0
- package/dist/areas/courses/state.js.map +1 -0
- package/dist/areas/courses/structure.d.ts +89 -0
- package/dist/areas/courses/structure.js +104 -0
- package/dist/areas/courses/structure.js.map +1 -0
- package/dist/areas/forums/discussions.d.ts +57 -0
- package/dist/areas/forums/discussions.js +119 -0
- package/dist/areas/forums/discussions.js.map +1 -0
- package/dist/areas/forums/posts.d.ts +83 -0
- package/dist/areas/forums/posts.js +114 -0
- package/dist/areas/forums/posts.js.map +1 -0
- package/dist/areas/grades/gradebook.d.ts +104 -0
- package/dist/areas/grades/gradebook.js +250 -0
- package/dist/areas/grades/gradebook.js.map +1 -0
- package/dist/areas/grades/user-report.d.ts +26 -0
- package/dist/areas/grades/user-report.js +71 -0
- package/dist/areas/grades/user-report.js.map +1 -0
- package/dist/areas/h5p/h5p.d.ts +33 -0
- package/dist/areas/h5p/h5p.js +104 -0
- package/dist/areas/h5p/h5p.js.map +1 -0
- package/dist/areas/lessons/lessons.d.ts +60 -0
- package/dist/areas/lessons/lessons.js +145 -0
- package/dist/areas/lessons/lessons.js.map +1 -0
- package/dist/areas/messages/messages.d.ts +68 -0
- package/dist/areas/messages/messages.js +84 -0
- package/dist/areas/messages/messages.js.map +1 -0
- package/dist/areas/participants/participants.d.ts +57 -0
- package/dist/areas/participants/participants.js +135 -0
- package/dist/areas/participants/participants.js.map +1 -0
- package/dist/areas/questions/banks.d.ts +83 -0
- package/dist/areas/questions/banks.js +239 -0
- package/dist/areas/questions/banks.js.map +1 -0
- package/dist/areas/quizzes/attempts.d.ts +123 -0
- package/dist/areas/quizzes/attempts.js +300 -0
- package/dist/areas/quizzes/attempts.js.map +1 -0
- package/dist/areas/quizzes/results.d.ts +36 -0
- package/dist/areas/quizzes/results.js +93 -0
- package/dist/areas/quizzes/results.js.map +1 -0
- package/dist/areas/quizzes/structure.d.ts +42 -0
- package/dist/areas/quizzes/structure.js +100 -0
- package/dist/areas/quizzes/structure.js.map +1 -0
- package/dist/areas/scorm/scorm.d.ts +60 -0
- package/dist/areas/scorm/scorm.js +171 -0
- package/dist/areas/scorm/scorm.js.map +1 -0
- package/dist/areas/site/info.d.ts +25 -0
- package/dist/areas/site/info.js +45 -0
- package/dist/areas/site/info.js.map +1 -0
- package/dist/areas/site/users.d.ts +56 -0
- package/dist/areas/site/users.js +89 -0
- package/dist/areas/site/users.js.map +1 -0
- package/dist/areas/surveys/choice.d.ts +38 -0
- package/dist/areas/surveys/choice.js +105 -0
- package/dist/areas/surveys/choice.js.map +1 -0
- package/dist/areas/surveys/surveys.d.ts +51 -0
- package/dist/areas/surveys/surveys.js +201 -0
- package/dist/areas/surveys/surveys.js.map +1 -0
- package/dist/browser/chromium.d.ts +15 -0
- package/dist/browser/chromium.js +53 -0
- package/dist/browser/chromium.js.map +1 -0
- package/dist/browser/cookies.d.ts +11 -0
- package/dist/browser/cookies.js +31 -0
- package/dist/browser/cookies.js.map +1 -0
- package/dist/browser/manager.d.ts +57 -0
- package/dist/browser/manager.js +177 -0
- package/dist/browser/manager.js.map +1 -0
- package/dist/browser.d.ts +53 -0
- package/dist/browser.js +167 -0
- package/dist/browser.js.map +1 -0
- package/dist/categories.d.ts +28 -0
- package/dist/categories.js +225 -0
- package/dist/categories.js.map +1 -0
- package/dist/chromiumInstaller.d.ts +15 -0
- package/dist/chromiumInstaller.js +52 -0
- package/dist/chromiumInstaller.js.map +1 -0
- package/dist/cli/args.d.ts +33 -0
- package/dist/cli/args.js +194 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/commands.generated.d.ts +4 -0
- package/dist/cli/commands.generated.js +2217 -0
- package/dist/cli/commands.generated.js.map +1 -0
- package/dist/cli/config.d.ts +46 -0
- package/dist/cli/config.js +107 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +19 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/output.d.ts +4 -0
- package/dist/cli/output.js +71 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/run.d.ts +15 -0
- package/dist/cli/run.js +194 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/spec.d.ts +42 -0
- package/dist/cli/spec.js +4 -0
- package/dist/cli/spec.js.map +1 -0
- package/dist/client.d.ts +224 -0
- package/dist/client.js +182 -0
- package/dist/client.js.map +1 -0
- package/dist/core/ajax.d.ts +25 -0
- package/dist/core/ajax.js +85 -0
- package/dist/core/ajax.js.map +1 -0
- package/dist/core/editor.d.ts +18 -0
- package/dist/core/editor.js +51 -0
- package/dist/core/editor.js.map +1 -0
- package/dist/core/errors.d.ts +12 -0
- package/dist/core/errors.js +10 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/files.d.ts +16 -0
- package/dist/core/files.js +58 -0
- package/dist/core/files.js.map +1 -0
- package/dist/core/forms.d.ts +45 -0
- package/dist/core/forms.js +200 -0
- package/dist/core/forms.js.map +1 -0
- package/dist/core/http.d.ts +18 -0
- package/dist/core/http.js +22 -0
- package/dist/core/http.js.map +1 -0
- package/dist/core/inPage.d.ts +8 -0
- package/dist/core/inPage.js +10 -0
- package/dist/core/inPage.js.map +1 -0
- package/dist/core/login.d.ts +40 -0
- package/dist/core/login.js +83 -0
- package/dist/core/login.js.map +1 -0
- package/dist/core/pace.d.ts +4 -0
- package/dist/core/pace.js +21 -0
- package/dist/core/pace.js.map +1 -0
- package/dist/core/session.d.ts +55 -0
- package/dist/core/session.js +157 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/site.d.ts +8 -0
- package/dist/core/site.js +36 -0
- package/dist/core/site.js.map +1 -0
- package/dist/core/text.d.ts +21 -0
- package/dist/core/text.js +113 -0
- package/dist/core/text.js.map +1 -0
- package/dist/home.d.ts +19 -0
- package/dist/home.js +54 -0
- package/dist/home.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/internals.d.ts +11 -0
- package/dist/internals.js +15 -0
- package/dist/internals.js.map +1 -0
- package/dist/moodle/activities.d.ts +94 -0
- package/dist/moodle/activities.js +240 -0
- package/dist/moodle/activities.js.map +1 -0
- package/dist/moodle/ajax.d.ts +22 -0
- package/dist/moodle/ajax.js +91 -0
- package/dist/moodle/ajax.js.map +1 -0
- package/dist/moodle/assign.d.ts +65 -0
- package/dist/moodle/assign.js +162 -0
- package/dist/moodle/assign.js.map +1 -0
- package/dist/moodle/calendar.d.ts +41 -0
- package/dist/moodle/calendar.js +80 -0
- package/dist/moodle/calendar.js.map +1 -0
- package/dist/moodle/choice.d.ts +33 -0
- package/dist/moodle/choice.js +100 -0
- package/dist/moodle/choice.js.map +1 -0
- package/dist/moodle/completion.d.ts +48 -0
- package/dist/moodle/completion.js +108 -0
- package/dist/moodle/completion.js.map +1 -0
- package/dist/moodle/content.d.ts +43 -0
- package/dist/moodle/content.js +105 -0
- package/dist/moodle/content.js.map +1 -0
- package/dist/moodle/course.d.ts +51 -0
- package/dist/moodle/course.js +45 -0
- package/dist/moodle/course.js.map +1 -0
- package/dist/moodle/courses.d.ts +57 -0
- package/dist/moodle/courses.js +70 -0
- package/dist/moodle/courses.js.map +1 -0
- package/dist/moodle/editor.d.ts +18 -0
- package/dist/moodle/editor.js +50 -0
- package/dist/moodle/editor.js.map +1 -0
- package/dist/moodle/files.d.ts +16 -0
- package/dist/moodle/files.js +57 -0
- package/dist/moodle/files.js.map +1 -0
- package/dist/moodle/forms.d.ts +44 -0
- package/dist/moodle/forms.js +199 -0
- package/dist/moodle/forms.js.map +1 -0
- package/dist/moodle/forum.d.ts +55 -0
- package/dist/moodle/forum.js +115 -0
- package/dist/moodle/forum.js.map +1 -0
- package/dist/moodle/forumPosts.d.ts +83 -0
- package/dist/moodle/forumPosts.js +113 -0
- package/dist/moodle/forumPosts.js.map +1 -0
- package/dist/moodle/gradebook.d.ts +102 -0
- package/dist/moodle/gradebook.js +246 -0
- package/dist/moodle/gradebook.js.map +1 -0
- package/dist/moodle/grades.d.ts +24 -0
- package/dist/moodle/grades.js +67 -0
- package/dist/moodle/grades.js.map +1 -0
- package/dist/moodle/grading.d.ts +92 -0
- package/dist/moodle/grading.js +161 -0
- package/dist/moodle/grading.js.map +1 -0
- package/dist/moodle/h5p.d.ts +31 -0
- package/dist/moodle/h5p.js +100 -0
- package/dist/moodle/h5p.js.map +1 -0
- package/dist/moodle/inPage.d.ts +8 -0
- package/dist/moodle/inPage.js +10 -0
- package/dist/moodle/inPage.js.map +1 -0
- package/dist/moodle/lesson.d.ts +57 -0
- package/dist/moodle/lesson.js +140 -0
- package/dist/moodle/lesson.js.map +1 -0
- package/dist/moodle/login.d.ts +37 -0
- package/dist/moodle/login.js +77 -0
- package/dist/moodle/login.js.map +1 -0
- package/dist/moodle/messages.d.ts +66 -0
- package/dist/moodle/messages.js +80 -0
- package/dist/moodle/messages.js.map +1 -0
- package/dist/moodle/overview.d.ts +83 -0
- package/dist/moodle/overview.js +137 -0
- package/dist/moodle/overview.js.map +1 -0
- package/dist/moodle/pace.d.ts +4 -0
- package/dist/moodle/pace.js +19 -0
- package/dist/moodle/pace.js.map +1 -0
- package/dist/moodle/participants.d.ts +55 -0
- package/dist/moodle/participants.js +131 -0
- package/dist/moodle/participants.js.map +1 -0
- package/dist/moodle/questionBank.d.ts +81 -0
- package/dist/moodle/questionBank.js +235 -0
- package/dist/moodle/questionBank.js.map +1 -0
- package/dist/moodle/quiz.d.ts +117 -0
- package/dist/moodle/quiz.js +291 -0
- package/dist/moodle/quiz.js.map +1 -0
- package/dist/moodle/quizResults.d.ts +36 -0
- package/dist/moodle/quizResults.js +93 -0
- package/dist/moodle/quizResults.js.map +1 -0
- package/dist/moodle/quizStructure.d.ts +42 -0
- package/dist/moodle/quizStructure.js +100 -0
- package/dist/moodle/quizStructure.js.map +1 -0
- package/dist/moodle/session.d.ts +39 -0
- package/dist/moodle/session.js +99 -0
- package/dist/moodle/session.js.map +1 -0
- package/dist/moodle/site.d.ts +8 -0
- package/dist/moodle/site.js +36 -0
- package/dist/moodle/site.js.map +1 -0
- package/dist/moodle/siteInfo.d.ts +25 -0
- package/dist/moodle/siteInfo.js +45 -0
- package/dist/moodle/siteInfo.js.map +1 -0
- package/dist/moodle/structure.d.ts +94 -0
- package/dist/moodle/structure.js +103 -0
- package/dist/moodle/structure.js.map +1 -0
- package/dist/moodle/submission.d.ts +48 -0
- package/dist/moodle/submission.js +109 -0
- package/dist/moodle/submission.js.map +1 -0
- package/dist/moodle/survey.d.ts +47 -0
- package/dist/moodle/survey.js +197 -0
- package/dist/moodle/survey.js.map +1 -0
- package/dist/moodle/text.d.ts +21 -0
- package/dist/moodle/text.js +113 -0
- package/dist/moodle/text.js.map +1 -0
- package/dist/moodle/user.d.ts +54 -0
- package/dist/moodle/user.js +78 -0
- package/dist/moodle/user.js.map +1 -0
- package/dist/options.d.ts +30 -0
- package/dist/options.js +35 -0
- package/dist/options.js.map +1 -0
- package/dist/sessionCookies.d.ts +11 -0
- package/dist/sessionCookies.js +31 -0
- package/dist/sessionCookies.js.map +1 -0
- package/dist/testing/fakeMoodle.d.ts +55 -0
- package/dist/testing/fakeMoodle.js +103 -0
- package/dist/testing/fakeMoodle.js.map +1 -0
- package/dist/testing/gradingPanel.d.ts +6 -0
- package/dist/testing/gradingPanel.js +22 -0
- package/dist/testing/gradingPanel.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.js +18 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +78 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submission.js","sourceRoot":"","sources":["../../src/moodle/submission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { BrowserContext, Page } from "playwright-core";
|
|
2
|
+
/** The two survey modules: the questionnaire plugin (mod_questionnaire) and Moodle's feedback. */
|
|
3
|
+
export type SurveyType = "questionnaire" | "feedback";
|
|
4
|
+
export declare class SurveyError extends Error {
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
/** One field of a survey question, by its form name. */
|
|
8
|
+
export interface SurveyField {
|
|
9
|
+
name: string;
|
|
10
|
+
kind: "choice" | "checkbox" | "text" | "select";
|
|
11
|
+
label?: string;
|
|
12
|
+
options?: {
|
|
13
|
+
value: string;
|
|
14
|
+
label: string;
|
|
15
|
+
}[];
|
|
16
|
+
value?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface SurveyQuestion {
|
|
19
|
+
page: number;
|
|
20
|
+
number?: string;
|
|
21
|
+
text: string;
|
|
22
|
+
required: boolean;
|
|
23
|
+
fields: SurveyField[];
|
|
24
|
+
}
|
|
25
|
+
/** The questions on a survey page, with their fields read from the form (names, options, labels). */
|
|
26
|
+
export declare function readSurveyPage(page: Page, type: SurveyType, pageNumber: number): Promise<SurveyQuestion[]>;
|
|
27
|
+
/** Which survey module an activity is, from the page each module answers with its own view (body id). */
|
|
28
|
+
export declare function surveyType(context: BrowserContext, siteUrl: string, cmid: number): Promise<SurveyType>;
|
|
29
|
+
/** A survey (questionnaire or feedback): whether it can be answered, its intro and messages, and its questions page by page. Its module is found when not given. */
|
|
30
|
+
export declare function getSurvey(context: BrowserContext, siteUrl: string, cmid: number, type?: SurveyType): Promise<{
|
|
31
|
+
questions: SurveyQuestion[];
|
|
32
|
+
canAnswer: boolean;
|
|
33
|
+
intro: string;
|
|
34
|
+
messages: string[];
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Fills the survey page by page with `responses` (field name → value) and submits it on the last
|
|
38
|
+
* page. Every name is checked against the form first, so nothing is sent with a wrong one.
|
|
39
|
+
*/
|
|
40
|
+
export declare function submitSurvey(context: BrowserContext, siteUrl: string, cmid: number, type: SurveyType, responses: Record<string, string>): Promise<{
|
|
41
|
+
messages: string[];
|
|
42
|
+
}>;
|
|
43
|
+
export declare function submitSurvey(context: BrowserContext, siteUrl: string, cmid: number, responses: Record<string, string>, options?: {
|
|
44
|
+
type?: SurveyType;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
messages: string[];
|
|
47
|
+
}>;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { setFields } from "./forms.js";
|
|
2
|
+
import { inPage } from "./inPage.js";
|
|
3
|
+
import { openSitePage } from "./session.js";
|
|
4
|
+
export class SurveyError extends Error {
|
|
5
|
+
name = "SurveyError";
|
|
6
|
+
}
|
|
7
|
+
/** Where each module keeps its form, its questions, their text and their "required" mark. */
|
|
8
|
+
const LAYOUT = {
|
|
9
|
+
questionnaire: { form: "#phpesp_response", question: "fieldset.qn-container", text: ".qn-question", required: "img.req", number: ".qn-number", next: "next", finish: "submit" },
|
|
10
|
+
feedback: { form: "form.feedback_form", question: ".feedback_itemlist", text: ".col-form-label", required: ".col-form-label .text-danger", number: ".itemnr", next: "gonextpage", finish: "savevalues" },
|
|
11
|
+
};
|
|
12
|
+
/** The questions on a survey page, with their fields read from the form (names, options, labels). */
|
|
13
|
+
export function readSurveyPage(page, type, pageNumber) {
|
|
14
|
+
return inPage(page, ({ layout, pageNumber }) => {
|
|
15
|
+
const doc = globalThis.document;
|
|
16
|
+
// Text as shown, without what only screen readers get.
|
|
17
|
+
const text = (el) => {
|
|
18
|
+
if (!el)
|
|
19
|
+
return "";
|
|
20
|
+
const copy = el.cloneNode(true);
|
|
21
|
+
for (const hidden of Array.from(copy.querySelectorAll(".accesshide, .visually-hidden, .sr-only, input")))
|
|
22
|
+
hidden.remove();
|
|
23
|
+
doc.body.appendChild(copy);
|
|
24
|
+
const shown = copy.innerText ?? "";
|
|
25
|
+
copy.remove();
|
|
26
|
+
return shown.replace(/\s+/g, " ").trim();
|
|
27
|
+
};
|
|
28
|
+
// An option's label: its own <label for>, the label around it, or (a rating row) nothing.
|
|
29
|
+
const labelOf = (input) => {
|
|
30
|
+
const own = input.id ? doc.querySelector(`label[for="${input.id}"]:not(.accesshide)`) : null;
|
|
31
|
+
const around = input.closest("label");
|
|
32
|
+
return text(own ?? around) || undefined;
|
|
33
|
+
};
|
|
34
|
+
const form = doc.querySelector(layout.form);
|
|
35
|
+
if (!form)
|
|
36
|
+
return [];
|
|
37
|
+
return Array.from(form.querySelectorAll(layout.question)).map((question) => {
|
|
38
|
+
const fields = [];
|
|
39
|
+
for (const input of Array.from(question.querySelectorAll("input:not([type=hidden]), select, textarea"))) {
|
|
40
|
+
if (!input.name)
|
|
41
|
+
continue;
|
|
42
|
+
if (input.type === "radio") {
|
|
43
|
+
let field = fields.find((f) => f.name === input.name);
|
|
44
|
+
if (!field) {
|
|
45
|
+
// A rating row's item is the row's first cell.
|
|
46
|
+
const row = input.closest("tr.raterow");
|
|
47
|
+
field = { name: input.name, kind: "choice", options: [], ...(row ? { label: text(row.querySelector("td")) } : {}) };
|
|
48
|
+
fields.push(field);
|
|
49
|
+
}
|
|
50
|
+
const label = labelOf(input);
|
|
51
|
+
field.options.push({ value: input.value, label: label && !label.includes(",") ? label : input.value === "-999" ? "(no answer)" : (label ?? input.value) });
|
|
52
|
+
if (input.checked)
|
|
53
|
+
field.value = input.value;
|
|
54
|
+
}
|
|
55
|
+
else if (input.type === "checkbox") {
|
|
56
|
+
fields.push({ name: input.name, kind: "checkbox", label: labelOf(input), value: input.checked ? "1" : "0" });
|
|
57
|
+
}
|
|
58
|
+
else if (input.tagName === "SELECT") {
|
|
59
|
+
const options = Array.from(input.options);
|
|
60
|
+
fields.push({ name: input.name, kind: "select", options: options.map((o) => ({ value: o.value, label: o.text.trim() })), value: options.find((o) => o.selected)?.value });
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
fields.push({ name: input.name, kind: "text", ...(input.value ? { value: input.value } : {}) });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
page: pageNumber,
|
|
68
|
+
number: text(question.querySelector(layout.number)) || undefined,
|
|
69
|
+
text: text(question.querySelector(layout.text)),
|
|
70
|
+
required: question.querySelector(layout.required) !== null,
|
|
71
|
+
fields,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
}, { layout: LAYOUT[type], pageNumber });
|
|
75
|
+
}
|
|
76
|
+
/** Whether the person can answer now, and the survey's page message (completed, closed…). */
|
|
77
|
+
async function surveyStatus(context, siteUrl, cmid, type) {
|
|
78
|
+
const page = await openSitePage(context, siteUrl, `mod/${type}/view.php?id=${cmid}`);
|
|
79
|
+
try {
|
|
80
|
+
if ((await page.locator(`body#page-mod-${type}-view`).count()) === 0)
|
|
81
|
+
throw new SurveyError(`Activity ${cmid} isn't a ${type} you can open. Take its id and module from the course structure.`);
|
|
82
|
+
return await page.evaluate(() => {
|
|
83
|
+
const doc = globalThis.document;
|
|
84
|
+
return {
|
|
85
|
+
canAnswer: doc.querySelector('#region-main a[href*="complete.php"]') !== null,
|
|
86
|
+
intro: (doc.querySelector(".activity-description, #intro")?.innerText ?? "").trim(),
|
|
87
|
+
messages: Array.from(doc.querySelectorAll("#region-main .alert, #region-main .notifymessage, #region-main .complete, #region-main .generalbox p"))
|
|
88
|
+
.map((e) => e.innerText.replace(/\s+/g, " ").trim())
|
|
89
|
+
.filter(Boolean)
|
|
90
|
+
.slice(0, 6),
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
await page.close().catch(() => undefined);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Every page of the survey's form: feedback pages through `gopage`, questionnaire sections through `sec`. */
|
|
99
|
+
async function readAllPages(context, siteUrl, cmid, type) {
|
|
100
|
+
const layout = LAYOUT[type];
|
|
101
|
+
const questions = [];
|
|
102
|
+
const page = await openSitePage(context, siteUrl, `mod/${type}/complete.php?id=${cmid}`);
|
|
103
|
+
try {
|
|
104
|
+
for (let p = 0; p < 50; p++) {
|
|
105
|
+
if (p > 0) {
|
|
106
|
+
const next = type === "feedback" ? `mod/feedback/complete.php?id=${cmid}&gopage=${p}` : `mod/questionnaire/complete.php?id=${cmid}&sec=${p + 1}`;
|
|
107
|
+
await page.goto(new URL(next, siteUrl).href, { waitUntil: "domcontentloaded" });
|
|
108
|
+
}
|
|
109
|
+
const found = await readSurveyPage(page, type, p);
|
|
110
|
+
if (found.length === 0)
|
|
111
|
+
break;
|
|
112
|
+
questions.push(...found);
|
|
113
|
+
if ((await page.locator(`${layout.form} [name="${layout.next}"]`).count()) === 0)
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
return questions;
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
await page.close().catch(() => undefined);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// A course module's module never changes: one look per survey and site, for the process.
|
|
123
|
+
const surveyTypes = new Map();
|
|
124
|
+
/** Which survey module an activity is, from the page each module answers with its own view (body id). */
|
|
125
|
+
export async function surveyType(context, siteUrl, cmid) {
|
|
126
|
+
const key = `${siteUrl}|${cmid}`;
|
|
127
|
+
const known = surveyTypes.get(key);
|
|
128
|
+
if (known)
|
|
129
|
+
return known;
|
|
130
|
+
for (const type of ["questionnaire", "feedback"]) {
|
|
131
|
+
const page = await openSitePage(context, siteUrl, `mod/${type}/view.php?id=${cmid}`, { follow: false });
|
|
132
|
+
try {
|
|
133
|
+
if ((await page.locator(`body#page-mod-${type}-view`).count()) > 0) {
|
|
134
|
+
surveyTypes.set(key, type);
|
|
135
|
+
return type;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
await page.close().catch(() => undefined);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
throw new SurveyError(`Activity ${cmid} isn't a questionnaire or a feedback activity you can open. Take its id and module from the course structure.`);
|
|
143
|
+
}
|
|
144
|
+
/** A survey (questionnaire or feedback): whether it can be answered, its intro and messages, and its questions page by page. Its module is found when not given. */
|
|
145
|
+
export async function getSurvey(context, siteUrl, cmid, type) {
|
|
146
|
+
type ??= await surveyType(context, siteUrl, cmid);
|
|
147
|
+
const status = await surveyStatus(context, siteUrl, cmid, type);
|
|
148
|
+
return { ...status, questions: status.canAnswer ? await readAllPages(context, siteUrl, cmid, type) : [] };
|
|
149
|
+
}
|
|
150
|
+
export async function submitSurvey(context, siteUrl, cmid, typeOrResponses, responsesOrOptions) {
|
|
151
|
+
// (cmid, type, responses), as before 0.2, or (cmid, responses, { type }), the module found when not given.
|
|
152
|
+
const responses = (typeof typeOrResponses === "string" ? responsesOrOptions : typeOrResponses);
|
|
153
|
+
const type = typeof typeOrResponses === "string" ? typeOrResponses : (responsesOrOptions?.type ?? (await surveyType(context, siteUrl, cmid)));
|
|
154
|
+
const layout = LAYOUT[type];
|
|
155
|
+
const status = await surveyStatus(context, siteUrl, cmid, type);
|
|
156
|
+
if (!status.canAnswer)
|
|
157
|
+
throw new SurveyError(`You can't answer ${type} ${cmid} now: ${status.messages.join(" ") || "it's completed, closed or not open yet"}.`);
|
|
158
|
+
const known = new Set((await readAllPages(context, siteUrl, cmid, type)).flatMap((q) => q.fields.map((f) => f.name)));
|
|
159
|
+
const unknown = Object.keys(responses).filter((name) => !known.has(name));
|
|
160
|
+
if (unknown.length > 0)
|
|
161
|
+
throw new SurveyError(`The survey has no field ${unknown.join(", ")}: take the names from the survey's questions.`);
|
|
162
|
+
const page = await openSitePage(context, siteUrl, `mod/${type}/complete.php?id=${cmid}`);
|
|
163
|
+
try {
|
|
164
|
+
for (let p = 0; p < 50; p++) {
|
|
165
|
+
const here = new Set((await readSurveyPage(page, type, p)).flatMap((q) => q.fields.map((f) => f.name)));
|
|
166
|
+
const values = Object.fromEntries(Object.entries(responses).filter(([name]) => here.has(name)));
|
|
167
|
+
await setFields(page, values, layout.form);
|
|
168
|
+
const last = (await page.locator(`${layout.form} [name="${layout.next}"]`).count()) === 0;
|
|
169
|
+
const [response] = await Promise.all([page.waitForNavigation({ waitUntil: "domcontentloaded" }), page.click(`${layout.form} [name="${last ? layout.finish : layout.next}"]`)]);
|
|
170
|
+
if (response && response.status() >= 500) {
|
|
171
|
+
throw new SurveyError(`The site answered ${response.status()} ${last ? "on submitting" : "on the way"}; it may or may not have recorded the answers. Read the survey again before trying again.`);
|
|
172
|
+
}
|
|
173
|
+
// Moodle sends the page back when something's missing or wrong.
|
|
174
|
+
const problems = await page.evaluate((form) => {
|
|
175
|
+
const doc = globalThis.document;
|
|
176
|
+
const messages = Array.from(doc.querySelectorAll(`${form} [id^="id_error_"], #region-main .alert-danger`)).map((e) => {
|
|
177
|
+
// Without the notification's close button ("Dismiss this notification").
|
|
178
|
+
const copy = e.cloneNode(true);
|
|
179
|
+
for (const button of Array.from(copy.querySelectorAll("button, .close, .visually-hidden")))
|
|
180
|
+
button.remove();
|
|
181
|
+
const text = (copy.innerText ?? e.innerText).replace(/\s+/g, " ").trim();
|
|
182
|
+
return text ? `${e.id ? e.id.replace("id_error_", "") + ": " : ""}${text}` : "";
|
|
183
|
+
});
|
|
184
|
+
return [...new Set(messages.filter(Boolean))];
|
|
185
|
+
}, layout.form);
|
|
186
|
+
if (problems.length > 0)
|
|
187
|
+
throw new SurveyError(`Moodle didn't accept the answers on page ${p + 1}: ${problems.join("; ")}`);
|
|
188
|
+
if (last)
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
await page.close().catch(() => undefined);
|
|
194
|
+
}
|
|
195
|
+
return { messages: (await surveyStatus(context, siteUrl, cmid, type)).messages };
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=survey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"survey.js","sourceRoot":"","sources":["../../src/moodle/survey.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Page } from "playwright-core";
|
|
2
|
+
/** Moodle formats names for HTML (`format_string`): plain text for the client. */
|
|
3
|
+
export declare function decodeEntities(text: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* The text of the elements matching `selector` in `page`, one string each: paragraphs, line breaks
|
|
6
|
+
* and list items kept, scripts and styles left out. Runs in the page with no named functions inside
|
|
7
|
+
* (see the conventions on page.evaluate).
|
|
8
|
+
*/
|
|
9
|
+
export declare function readTexts(page: Page, selector: string): Promise<string[]>;
|
|
10
|
+
/** A video, audio or player found in a page's content. */
|
|
11
|
+
export interface MediaItem {
|
|
12
|
+
kind: "video" | "audio" | "youtube" | "vimeo" | "embed";
|
|
13
|
+
url: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The media in the elements matching `selector`: `<video>`/`<audio>` and their sources, players in
|
|
18
|
+
* iframes, video.js's `data-setup` sources (Moodle's media filter turns a YouTube link into one), and
|
|
19
|
+
* plain links to media. YouTube URLs come back as `watch?v=` links. Read in the page.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readMedia(page: Page, selector: string): Promise<MediaItem[]>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { inPage } from "./inPage.js";
|
|
2
|
+
/** Moodle formats names for HTML (`format_string`): plain text for the client. */
|
|
3
|
+
export function decodeEntities(text) {
|
|
4
|
+
return text.replace(/&(#x[0-9a-f]+|#\d+|amp|lt|gt|quot|apos|nbsp);/gi, (entity, code) => {
|
|
5
|
+
const lower = code.toLowerCase();
|
|
6
|
+
if (lower.startsWith("#x"))
|
|
7
|
+
return String.fromCodePoint(parseInt(lower.slice(2), 16));
|
|
8
|
+
if (lower.startsWith("#"))
|
|
9
|
+
return String.fromCodePoint(parseInt(lower.slice(1), 10));
|
|
10
|
+
return { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: " " }[lower] ?? entity;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The text of the elements matching `selector` in `page`, one string each: paragraphs, line breaks
|
|
15
|
+
* and list items kept, scripts and styles left out. Runs in the page with no named functions inside
|
|
16
|
+
* (see the conventions on page.evaluate).
|
|
17
|
+
*/
|
|
18
|
+
export function readTexts(page, selector) {
|
|
19
|
+
return page.evaluate((selector) => {
|
|
20
|
+
const doc = globalThis;
|
|
21
|
+
const BLOCKS = new Set(["P", "DIV", "LI", "UL", "OL", "TR", "TABLE", "PRE", "BLOCKQUOTE", "SECTION", "ARTICLE", "H1", "H2", "H3", "H4", "H5", "H6"]);
|
|
22
|
+
return Array.from(doc.document.querySelectorAll(selector)).map((root) => {
|
|
23
|
+
let raw = "";
|
|
24
|
+
const stack = [root];
|
|
25
|
+
while (stack.length > 0) {
|
|
26
|
+
const item = stack.pop();
|
|
27
|
+
if (typeof item === "string")
|
|
28
|
+
raw += item;
|
|
29
|
+
else if (item.nodeType === 3)
|
|
30
|
+
raw += (item.textContent ?? "").replace(/\s+/g, " ");
|
|
31
|
+
else if (item.nodeType !== 1 || item.nodeName === "SCRIPT" || item.nodeName === "STYLE")
|
|
32
|
+
continue;
|
|
33
|
+
else if (item.nodeName === "BR")
|
|
34
|
+
raw += "\n";
|
|
35
|
+
else if (item.nodeName === "PRE")
|
|
36
|
+
raw += `\n${item.textContent ?? ""}\n`;
|
|
37
|
+
else {
|
|
38
|
+
const isBlock = BLOCKS.has(item.nodeName);
|
|
39
|
+
raw += item.nodeName === "LI" ? "\n- " : isBlock ? "\n" : "";
|
|
40
|
+
// A list item ends where the next one starts: no blank line between items.
|
|
41
|
+
stack.push(isBlock && item.nodeName !== "LI" ? "\n" : "", ...Array.from(item.childNodes).reverse());
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return raw
|
|
45
|
+
.replace(/[ \t]+\n/g, "\n")
|
|
46
|
+
.replace(/\n[ \t]+/g, "\n")
|
|
47
|
+
.replace(/\n- +/g, "\n- ")
|
|
48
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
49
|
+
.trim();
|
|
50
|
+
});
|
|
51
|
+
}, selector);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The media in the elements matching `selector`: `<video>`/`<audio>` and their sources, players in
|
|
55
|
+
* iframes, video.js's `data-setup` sources (Moodle's media filter turns a YouTube link into one), and
|
|
56
|
+
* plain links to media. YouTube URLs come back as `watch?v=` links. Read in the page.
|
|
57
|
+
*/
|
|
58
|
+
export function readMedia(page, selector) {
|
|
59
|
+
return inPage(page, (selector) => {
|
|
60
|
+
const roots = Array.from(globalThis.document.querySelectorAll(selector));
|
|
61
|
+
const found = new Map();
|
|
62
|
+
const add = (raw, tag, title) => {
|
|
63
|
+
if (!raw || raw.startsWith("blob:") || raw.startsWith("data:"))
|
|
64
|
+
return;
|
|
65
|
+
let url;
|
|
66
|
+
try {
|
|
67
|
+
url = new URL(raw, globalThis.location.href);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const youtube = /(?:youtube(?:-nocookie)?\.com\/(?:embed\/|watch\?v=|shorts\/)|youtu\.be\/)([\w-]{6,})/.exec(url.href)?.[1];
|
|
73
|
+
let kind;
|
|
74
|
+
let href = url.href;
|
|
75
|
+
if (youtube) {
|
|
76
|
+
kind = "youtube";
|
|
77
|
+
href = `https://www.youtube.com/watch?v=${youtube}`;
|
|
78
|
+
}
|
|
79
|
+
else if (/vimeo\.com\//.test(url.href))
|
|
80
|
+
kind = "vimeo";
|
|
81
|
+
else if (tag === "AUDIO" || /\.(mp3|ogg|oga|wav|m4a|aac)(\?|$)/i.test(url.pathname))
|
|
82
|
+
kind = "audio";
|
|
83
|
+
else if (tag === "VIDEO" || /\.(mp4|webm|m4v|mov|ogv|m3u8)(\?|$)/i.test(url.pathname))
|
|
84
|
+
kind = "video";
|
|
85
|
+
else if (tag === "IFRAME")
|
|
86
|
+
kind = "embed";
|
|
87
|
+
else
|
|
88
|
+
return;
|
|
89
|
+
if (!found.has(href))
|
|
90
|
+
found.set(href, { kind, url: href, ...(title ? { title } : {}) });
|
|
91
|
+
};
|
|
92
|
+
for (const root of roots) {
|
|
93
|
+
for (const el of Array.from(root.querySelectorAll("video, audio, source, iframe, a[href]"))) {
|
|
94
|
+
const media = el.tagName === "SOURCE" ? "VIDEO" : el.tagName;
|
|
95
|
+
add(el.getAttribute("src") ?? el.getAttribute("href"), media, el.getAttribute("title"));
|
|
96
|
+
for (const attribute of ["data-setup-lazy", "data-setup"]) {
|
|
97
|
+
const setup = el.getAttribute(attribute);
|
|
98
|
+
if (!setup)
|
|
99
|
+
continue;
|
|
100
|
+
try {
|
|
101
|
+
for (const source of JSON.parse(setup).sources ?? [])
|
|
102
|
+
add(source.src, "VIDEO", el.getAttribute("title"));
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Not JSON: nothing to read.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return Array.from(found.values());
|
|
111
|
+
}, selector);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/moodle/text.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { BrowserContext } from "playwright-core";
|
|
2
|
+
/** A user as `core_user_get_users_by_field` returns it (Moodle 5.2), the fields read. */
|
|
3
|
+
export interface MoodleUser {
|
|
4
|
+
id: number;
|
|
5
|
+
username?: string;
|
|
6
|
+
fullname: string;
|
|
7
|
+
email?: string;
|
|
8
|
+
firstaccess?: number;
|
|
9
|
+
lastaccess?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function userById(context: BrowserContext, siteUrl: string, userId: number): Promise<MoodleUser | undefined>;
|
|
12
|
+
/** The site's name, from its public settings; `undefined` where the mobile app support is off. */
|
|
13
|
+
export declare function siteName(context: BrowserContext, siteUrl: string): Promise<string | undefined>;
|
|
14
|
+
/** A user's roles in a course, from their profile there: role links carry the role id in any language. */
|
|
15
|
+
export declare function courseRoles(context: BrowserContext, siteUrl: string, userId: number, courseId: number): Promise<{
|
|
16
|
+
id: number;
|
|
17
|
+
name: string;
|
|
18
|
+
}[]>;
|
|
19
|
+
/**
|
|
20
|
+
* What the person can do in a course, asked of read-only services that need the capability: the
|
|
21
|
+
* activity types they can add (none without `moodle/course:manageactivities`) and the grader
|
|
22
|
+
* report's users (`nopermissions` without `gradereport/grader:view`). Nothing is changed.
|
|
23
|
+
*/
|
|
24
|
+
export declare function courseAbilities(context: BrowserContext, siteUrl: string, courseId: number, sectionId: number): Promise<{
|
|
25
|
+
canEdit: boolean;
|
|
26
|
+
canGrade: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
export interface Me {
|
|
29
|
+
userId: number;
|
|
30
|
+
username?: string;
|
|
31
|
+
fullName: string;
|
|
32
|
+
email?: string;
|
|
33
|
+
/** The interface language in use. */
|
|
34
|
+
language: string;
|
|
35
|
+
timeZone: string;
|
|
36
|
+
firstAccess?: string;
|
|
37
|
+
lastAccess?: string;
|
|
38
|
+
site: {
|
|
39
|
+
name?: string;
|
|
40
|
+
url: string;
|
|
41
|
+
};
|
|
42
|
+
/** With a course: the person's roles there and what they can do. */
|
|
43
|
+
course?: {
|
|
44
|
+
id: number;
|
|
45
|
+
roles: {
|
|
46
|
+
id: number;
|
|
47
|
+
name: string;
|
|
48
|
+
}[];
|
|
49
|
+
canEdit: boolean;
|
|
50
|
+
canGrade: boolean;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** Who the logged-in person is; with `courseId`, also their roles and abilities in that course. */
|
|
54
|
+
export declare function whoAmI(context: BrowserContext, siteUrl: string, courseId?: number): Promise<Me>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { MoodleServiceError, callService, readPageConfig } from "./ajax.js";
|
|
2
|
+
import { courseState } from "./course.js";
|
|
3
|
+
import { isoDate } from "./courses.js";
|
|
4
|
+
import { openSitePage } from "./session.js";
|
|
5
|
+
export async function userById(context, siteUrl, userId) {
|
|
6
|
+
const users = await callService(context, siteUrl, "core_user_get_users_by_field", { field: "id", values: [String(userId)] });
|
|
7
|
+
return users[0];
|
|
8
|
+
}
|
|
9
|
+
/** The site's name, from its public settings; `undefined` where the mobile app support is off. */
|
|
10
|
+
export async function siteName(context, siteUrl) {
|
|
11
|
+
try {
|
|
12
|
+
return (await callService(context, siteUrl, "tool_mobile_get_public_config", {})).sitename;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** A user's roles in a course, from their profile there: role links carry the role id in any language. */
|
|
19
|
+
export async function courseRoles(context, siteUrl, userId, courseId) {
|
|
20
|
+
const page = await openSitePage(context, siteUrl, `user/view.php?id=${userId}&course=${courseId}`);
|
|
21
|
+
try {
|
|
22
|
+
return await page.evaluate(() => {
|
|
23
|
+
const links = globalThis.document.querySelectorAll('#region-main a[href*="/user/index.php"][href*="roleid="]');
|
|
24
|
+
const roles = new Map();
|
|
25
|
+
for (const link of Array.from(links)) {
|
|
26
|
+
const id = Number(new URL(link.href).searchParams.get("roleid"));
|
|
27
|
+
if (id > 0)
|
|
28
|
+
roles.set(id, (link.textContent ?? "").trim());
|
|
29
|
+
}
|
|
30
|
+
return Array.from(roles, ([id, name]) => ({ id, name }));
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
await page.close().catch(() => undefined);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* What the person can do in a course, asked of read-only services that need the capability: the
|
|
39
|
+
* activity types they can add (none without `moodle/course:manageactivities`) and the grader
|
|
40
|
+
* report's users (`nopermissions` without `gradereport/grader:view`). Nothing is changed.
|
|
41
|
+
*/
|
|
42
|
+
export async function courseAbilities(context, siteUrl, courseId, sectionId) {
|
|
43
|
+
const items = await callService(context, siteUrl, "core_courseformat_get_section_content_items", { courseid: courseId, sectionid: sectionId });
|
|
44
|
+
let canGrade = true;
|
|
45
|
+
try {
|
|
46
|
+
await callService(context, siteUrl, "gradereport_grader_get_users_in_report", { courseid: courseId });
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (!(error instanceof MoodleServiceError && error.errorcode === "nopermissions"))
|
|
50
|
+
throw error;
|
|
51
|
+
canGrade = false;
|
|
52
|
+
}
|
|
53
|
+
return { canEdit: items.content_items.length > 0, canGrade };
|
|
54
|
+
}
|
|
55
|
+
/** Who the logged-in person is; with `courseId`, also their roles and abilities in that course. */
|
|
56
|
+
export async function whoAmI(context, siteUrl, courseId) {
|
|
57
|
+
const cfg = await readPageConfig(context, siteUrl);
|
|
58
|
+
const user = await userById(context, siteUrl, cfg.userId);
|
|
59
|
+
const me = {
|
|
60
|
+
userId: cfg.userId,
|
|
61
|
+
username: user?.username,
|
|
62
|
+
fullName: user?.fullname ?? "",
|
|
63
|
+
email: user?.email,
|
|
64
|
+
language: cfg.language,
|
|
65
|
+
timeZone: cfg.timeZone,
|
|
66
|
+
firstAccess: isoDate(user?.firstaccess),
|
|
67
|
+
lastAccess: isoDate(user?.lastaccess),
|
|
68
|
+
site: { name: await siteName(context, siteUrl), url: siteUrl },
|
|
69
|
+
};
|
|
70
|
+
if (courseId !== undefined) {
|
|
71
|
+
// The course's state checks that it exists and the person can see it, and gives a section.
|
|
72
|
+
const state = await courseState(context, siteUrl, courseId);
|
|
73
|
+
const abilities = await courseAbilities(context, siteUrl, courseId, Number(state.section[0]?.id ?? 0));
|
|
74
|
+
me.course = { id: courseId, roles: await courseRoles(context, siteUrl, cfg.userId, courseId), ...abilities };
|
|
75
|
+
}
|
|
76
|
+
return me;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/moodle/user.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { MoodleError } from "./core/errors.js";
|
|
2
|
+
/** Installed browsers tried in this order when no channel is chosen (ADR-001). */
|
|
3
|
+
export declare const SYSTEM_CHANNELS: readonly ["msedge", "chrome"];
|
|
4
|
+
/** Every channel: the system browsers, and Playwright's Chromium (downloaded when missing). */
|
|
5
|
+
export declare const CHANNELS: readonly ["msedge", "chrome", "chromium"];
|
|
6
|
+
export type Channel = (typeof CHANNELS)[number];
|
|
7
|
+
/** How student actions view and do things: through the real pages at a person's pace, or fast (ADR-005). */
|
|
8
|
+
export declare const TRAILS: readonly ["realistic", "fast"];
|
|
9
|
+
export type Trail = (typeof TRAILS)[number];
|
|
10
|
+
/**
|
|
11
|
+
* The browser's options. The driver reads them each time it launches, so a program may change them
|
|
12
|
+
* between launches (a `configure` in an MCP server) on the same object.
|
|
13
|
+
*/
|
|
14
|
+
export interface BrowserOptions {
|
|
15
|
+
/** The persistent profile folder where the person logs in (ADR-002). */
|
|
16
|
+
profileDir: string;
|
|
17
|
+
/** One channel, or undefined for Edge, then Chrome, then (with `downloadBrowser`) Chromium. */
|
|
18
|
+
channel?: Channel;
|
|
19
|
+
/** Without a window, unless a window is asked for (logging in) or shown on demand. */
|
|
20
|
+
headless: boolean;
|
|
21
|
+
/** Download Playwright's Chromium when no installed browser works. */
|
|
22
|
+
downloadBrowser: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** A site URL that isn't one. */
|
|
25
|
+
export declare class MoodleUrlError extends MoodleError {
|
|
26
|
+
name: string;
|
|
27
|
+
constructor(message: string);
|
|
28
|
+
}
|
|
29
|
+
/** A Moodle site's base URL, normalized: http(s), no query or fragment, a trailing slash. */
|
|
30
|
+
export declare function parseSiteUrl(value: string): string;
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { MoodleError } from "./core/errors.js";
|
|
2
|
+
// What a program using the driver chooses: the browser, its profile, the site, how student actions
|
|
3
|
+
// look in Moodle's logs. Plain values: the driver reads no environment or arguments of its own.
|
|
4
|
+
/** Installed browsers tried in this order when no channel is chosen (ADR-001). */
|
|
5
|
+
export const SYSTEM_CHANNELS = ["msedge", "chrome"];
|
|
6
|
+
/** Every channel: the system browsers, and Playwright's Chromium (downloaded when missing). */
|
|
7
|
+
export const CHANNELS = [...SYSTEM_CHANNELS, "chromium"];
|
|
8
|
+
/** How student actions view and do things: through the real pages at a person's pace, or fast (ADR-005). */
|
|
9
|
+
export const TRAILS = ["realistic", "fast"];
|
|
10
|
+
/** A site URL that isn't one. */
|
|
11
|
+
export class MoodleUrlError extends MoodleError {
|
|
12
|
+
name = "MoodleUrlError";
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message, "moodle-url");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** A Moodle site's base URL, normalized: http(s), no query or fragment, a trailing slash. */
|
|
18
|
+
export function parseSiteUrl(value) {
|
|
19
|
+
let url;
|
|
20
|
+
try {
|
|
21
|
+
url = new URL(value.trim());
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
throw new MoodleUrlError(`The Moodle URL isn't a valid URL: "${value}".`);
|
|
25
|
+
}
|
|
26
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
27
|
+
throw new MoodleUrlError(`The Moodle URL must be http or https, not "${value}".`);
|
|
28
|
+
}
|
|
29
|
+
url.search = "";
|
|
30
|
+
url.hash = "";
|
|
31
|
+
if (!url.pathname.endsWith("/"))
|
|
32
|
+
url.pathname += "/";
|
|
33
|
+
return url.href;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=options.js.map
|