n8n-nodes-pronote 0.2.1 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -29,3 +29,5 @@ See `agent-tools/pronoteTools.ts` for a thin wrapper you can drop into LLM agent
|
|
|
29
29
|
1) Run **PRONOTE Auth Helper** with operation “Prepare Mobile Validation” and your instance URL. It returns a `deviceUUID` and the `InfoMobileApp.json` URL.
|
|
30
30
|
2) Open that URL in a browser, approve the device in your CAS portal (e.g., Lycée Connecté). Capture the returned `login` and `mdp` (token).
|
|
31
31
|
3) Run **PRONOTE Auth Helper** with operation “Validate Mobile Token”, providing the `instanceUrl`, `login`, `mdp`, and the same `deviceUUID`. The node outputs a verified token plus user details—use these in the PRONOTE credentials.
|
|
32
|
+
|
|
33
|
+
> Use `mobileToken` (mdp) + `deviceUUID` in the PRONOTE credentials. The `sessionToken` returned is short‑lived; nodes will re-login with the mobile token on each run.
|
|
@@ -178,7 +178,8 @@ class PronoteAuthHelper {
|
|
|
178
178
|
instanceUrl: auth.url,
|
|
179
179
|
deviceUUID: auth.deviceUUID,
|
|
180
180
|
username: auth.username,
|
|
181
|
-
|
|
181
|
+
mobileToken: token,
|
|
182
|
+
sessionToken: auth.token,
|
|
182
183
|
kind: auth.kind,
|
|
183
184
|
userDisplayName: auth.session.user.name,
|
|
184
185
|
establishment: auth.session.user.resources[0]?.establishmentName,
|
|
@@ -209,7 +210,7 @@ class PronoteAuthHelper {
|
|
|
209
210
|
instanceUrl: auth.url,
|
|
210
211
|
deviceUUID: auth.deviceUUID,
|
|
211
212
|
username: auth.username,
|
|
212
|
-
|
|
213
|
+
sessionToken: auth.token,
|
|
213
214
|
kind: auth.kind,
|
|
214
215
|
userDisplayName: auth.session.user.name,
|
|
215
216
|
establishment: auth.session.user.resources[0]?.establishmentName,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type INodeType, type INodeTypeDescription, type
|
|
1
|
+
import { type INodeType, type INodeTypeDescription, type IExecuteFunctions, type INodeExecutionData } from "n8n-workflow";
|
|
2
2
|
export declare class PronoteTool implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
|
-
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
5
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PronoteTool = void 0;
|
|
4
|
-
const tools_1 = require("@langchain/core/tools");
|
|
5
|
-
const zod_1 = require("zod");
|
|
6
4
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
7
5
|
const pawnoteClient_1 = require("../../shared/pawnoteClient");
|
|
8
6
|
const GenericFunctions_1 = require("./GenericFunctions");
|
|
@@ -15,13 +13,14 @@ class PronoteTool {
|
|
|
15
13
|
group: ["transform"],
|
|
16
14
|
version: 1,
|
|
17
15
|
description: "Expose PRONOTE timetable, tasks, and grades to AI Agents",
|
|
18
|
-
subtitle: "={{ $parameter[\"
|
|
16
|
+
subtitle: "={{ $parameter[\"action\"] || \"PRONOTE\" }}",
|
|
19
17
|
defaults: {
|
|
20
18
|
name: "PRONOTE Tool",
|
|
21
19
|
},
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
usableAsTool: true,
|
|
21
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
22
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
23
|
+
outputNames: ["Result"],
|
|
25
24
|
credentials: [
|
|
26
25
|
{
|
|
27
26
|
name: "pronoteApi",
|
|
@@ -30,104 +29,138 @@ class PronoteTool {
|
|
|
30
29
|
],
|
|
31
30
|
properties: [
|
|
32
31
|
{
|
|
33
|
-
displayName: "
|
|
34
|
-
name: "
|
|
32
|
+
displayName: "Action",
|
|
33
|
+
name: "action",
|
|
34
|
+
type: "options",
|
|
35
|
+
default: "timetable",
|
|
36
|
+
options: [
|
|
37
|
+
{ name: "Timetable", value: "timetable" },
|
|
38
|
+
{ name: "Tasks", value: "tasks" },
|
|
39
|
+
{ name: "Grades", value: "grades" },
|
|
40
|
+
{ name: "Grade Periods", value: "gradePeriods" },
|
|
41
|
+
],
|
|
42
|
+
description: "What to retrieve from PRONOTE",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
displayName: "Reference Date",
|
|
46
|
+
name: "referenceDate",
|
|
47
|
+
type: "string",
|
|
48
|
+
default: "",
|
|
49
|
+
placeholder: "2024-09-01",
|
|
50
|
+
description: "ISO date used to pick the PRONOTE week for timetable/tasks. Defaults to today.",
|
|
51
|
+
displayOptions: {
|
|
52
|
+
show: {
|
|
53
|
+
action: ["timetable", "tasks"],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
displayName: "Only Pending Tasks",
|
|
59
|
+
name: "onlyPendingTasks",
|
|
60
|
+
type: "boolean",
|
|
61
|
+
default: false,
|
|
62
|
+
description: "Filter out tasks already marked done",
|
|
63
|
+
displayOptions: {
|
|
64
|
+
show: {
|
|
65
|
+
action: ["tasks"],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
displayName: "Period Name or ID",
|
|
71
|
+
name: "periodName",
|
|
35
72
|
type: "string",
|
|
36
|
-
default: "
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
73
|
+
default: "",
|
|
74
|
+
description: "Grade period to fetch (name or ID). Leave empty to use the first available period.",
|
|
75
|
+
displayOptions: {
|
|
76
|
+
show: {
|
|
77
|
+
action: ["grades"],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
displayName: "Include Individual Grades",
|
|
83
|
+
name: "includeGrades",
|
|
84
|
+
type: "boolean",
|
|
85
|
+
default: true,
|
|
86
|
+
description: "If false, only averages and subjects are returned",
|
|
87
|
+
displayOptions: {
|
|
88
|
+
show: {
|
|
89
|
+
action: ["grades"],
|
|
90
|
+
},
|
|
42
91
|
},
|
|
43
92
|
},
|
|
44
93
|
],
|
|
45
94
|
};
|
|
46
95
|
}
|
|
47
|
-
async
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
.enum(["timetable", "tasks", "grades", "gradePeriods"])
|
|
60
|
-
.describe("What to retrieve from PRONOTE."),
|
|
61
|
-
referenceDate: zod_1.z
|
|
62
|
-
.string()
|
|
63
|
-
.optional()
|
|
64
|
-
.describe("ISO date (e.g. 2024-09-01). Used for timetable and tasks to select the week; defaults to today."),
|
|
65
|
-
periodName: zod_1.z
|
|
66
|
-
.string()
|
|
67
|
-
.optional()
|
|
68
|
-
.describe("Grade period name or ID. Used when action=grades."),
|
|
69
|
-
onlyPendingTasks: zod_1.z
|
|
70
|
-
.boolean()
|
|
71
|
-
.optional()
|
|
72
|
-
.describe("When action=tasks, if true only return undone tasks."),
|
|
73
|
-
includeGrades: zod_1.z
|
|
74
|
-
.boolean()
|
|
75
|
-
.optional()
|
|
76
|
-
.describe("When action=grades, if false only averages are returned."),
|
|
77
|
-
}),
|
|
78
|
-
func: async (input) => {
|
|
79
|
-
const safeStringify = (data) => JSON.stringify(data, null, 2);
|
|
80
|
-
switch (input.action) {
|
|
81
|
-
case "timetable": {
|
|
82
|
-
const referenceDate = (0, GenericFunctions_1.resolveReferenceDate)(input.referenceDate);
|
|
83
|
-
const timetable = await (0, pawnoteClient_1.fetchTimetable)(session, referenceDate);
|
|
84
|
-
return safeStringify(timetable);
|
|
85
|
-
}
|
|
86
|
-
case "tasks": {
|
|
87
|
-
const referenceDate = (0, GenericFunctions_1.resolveReferenceDate)(input.referenceDate);
|
|
88
|
-
const assignments = await (0, pawnoteClient_1.fetchAssignments)(session, referenceDate);
|
|
89
|
-
const filtered = input.onlyPendingTasks
|
|
90
|
-
? assignments.filter((a) => !a.isDone)
|
|
91
|
-
: assignments;
|
|
92
|
-
return safeStringify(filtered);
|
|
93
|
-
}
|
|
94
|
-
case "gradePeriods": {
|
|
95
|
-
const periods = await (0, pawnoteClient_1.fetchGradePeriods)(session);
|
|
96
|
-
return safeStringify(periods);
|
|
97
|
-
}
|
|
98
|
-
case "grades": {
|
|
99
|
-
const includeGrades = input.includeGrades !== false;
|
|
100
|
-
const overview = await (0, pawnoteClient_1.fetchGrades)(session, input.periodName);
|
|
101
|
-
if (!includeGrades) {
|
|
102
|
-
return safeStringify({
|
|
103
|
-
period: overview.period,
|
|
104
|
-
studentOverall: overview.studentOverall,
|
|
105
|
-
classAverage: overview.classAverage,
|
|
106
|
-
subjects: overview.subjects.map((subject) => ({
|
|
107
|
-
id: subject.id,
|
|
108
|
-
name: subject.name,
|
|
109
|
-
studentAverage: subject.studentAverage,
|
|
110
|
-
classAverage: subject.classAverage,
|
|
111
|
-
maximum: subject.maximum,
|
|
112
|
-
minimum: subject.minimum,
|
|
113
|
-
outOf: subject.outOf,
|
|
114
|
-
})),
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
return safeStringify(overview);
|
|
118
|
-
}
|
|
119
|
-
default:
|
|
120
|
-
throw new Error(`Unsupported action: ${input["action"]}`);
|
|
96
|
+
async execute() {
|
|
97
|
+
const items = this.getInputData();
|
|
98
|
+
const returnData = [];
|
|
99
|
+
const auth = await (0, GenericFunctions_1.getPronoteAuth)(this);
|
|
100
|
+
const action = this.getNodeParameter("action", 0);
|
|
101
|
+
for (let i = 0; i < items.length; i++) {
|
|
102
|
+
try {
|
|
103
|
+
if (action === "timetable") {
|
|
104
|
+
const referenceDate = (0, GenericFunctions_1.resolveReferenceDate)(this.getNodeParameter("referenceDate", i));
|
|
105
|
+
const timetable = await (0, pawnoteClient_1.fetchTimetable)(auth.session, referenceDate);
|
|
106
|
+
for (const day of timetable) {
|
|
107
|
+
returnData.push({ json: day, pairedItem: { item: i } });
|
|
121
108
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (action === "tasks") {
|
|
112
|
+
const referenceDate = (0, GenericFunctions_1.resolveReferenceDate)(this.getNodeParameter("referenceDate", i));
|
|
113
|
+
const onlyPending = this.getNodeParameter("onlyPendingTasks", i);
|
|
114
|
+
const assignments = await (0, pawnoteClient_1.fetchAssignments)(auth.session, referenceDate);
|
|
115
|
+
for (const assignment of assignments) {
|
|
116
|
+
if (onlyPending && assignment.isDone)
|
|
117
|
+
continue;
|
|
118
|
+
returnData.push({ json: assignment, pairedItem: { item: i } });
|
|
119
|
+
}
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (action === "gradePeriods") {
|
|
123
|
+
const periods = await (0, pawnoteClient_1.fetchGradePeriods)(auth.session);
|
|
124
|
+
for (const period of periods) {
|
|
125
|
+
returnData.push({ json: period, pairedItem: { item: i } });
|
|
126
|
+
}
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (action === "grades") {
|
|
130
|
+
const periodName = this.getNodeParameter("periodName", i).trim() || undefined;
|
|
131
|
+
const includeGrades = this.getNodeParameter("includeGrades", i);
|
|
132
|
+
const overview = await (0, pawnoteClient_1.fetchGrades)(auth.session, periodName);
|
|
133
|
+
if (!includeGrades) {
|
|
134
|
+
returnData.push({
|
|
135
|
+
json: {
|
|
136
|
+
period: overview.period,
|
|
137
|
+
studentOverall: overview.studentOverall,
|
|
138
|
+
classAverage: overview.classAverage,
|
|
139
|
+
subjects: overview.subjects.map((subject) => ({
|
|
140
|
+
id: subject.id,
|
|
141
|
+
name: subject.name,
|
|
142
|
+
studentAverage: subject.studentAverage,
|
|
143
|
+
classAverage: subject.classAverage,
|
|
144
|
+
maximum: subject.maximum,
|
|
145
|
+
minimum: subject.minimum,
|
|
146
|
+
outOf: subject.outOf,
|
|
147
|
+
})),
|
|
148
|
+
},
|
|
149
|
+
pairedItem: { item: i },
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
returnData.push({ json: overview, pairedItem: { item: i } });
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
throw new Error(`Unsupported action ${action}`);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i });
|
|
161
|
+
}
|
|
130
162
|
}
|
|
163
|
+
return [returnData];
|
|
131
164
|
}
|
|
132
165
|
}
|
|
133
166
|
exports.PronoteTool = PronoteTool;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-pronote",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "n8n custom nodes and agent utilities to talk to PRONOTE via the Pawnote library.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/nodes/Pronote/Pronote.node.js",
|
|
@@ -14,9 +14,7 @@
|
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"
|
|
18
|
-
"pawnote": "^1.6.2",
|
|
19
|
-
"zod": "^3.23.8"
|
|
17
|
+
"pawnote": "^1.6.2"
|
|
20
18
|
},
|
|
21
19
|
"peerDependencies": {
|
|
22
20
|
"n8n-core": "^1.0.0",
|