@wilm-ai/wilma-cli 1.1.0 → 1.2.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/README.md +13 -1
- package/dist/index.js +97 -5
- package/package.json +11 -10
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -26,7 +26,19 @@ Combines today's and tomorrow's schedule, upcoming exams, recent homework, news,
|
|
|
26
26
|
|
|
27
27
|
### Schedule
|
|
28
28
|
```bash
|
|
29
|
-
wilma schedule list [--when today|tomorrow|week] [--student <id|name>] [--all-students] [--json]
|
|
29
|
+
wilma schedule list [--when today|tomorrow|week] [--date YYYY-MM-DD] [--weekday mon|tue|wed|thu|fri|sat|sun] [--student <id|name>] [--all-students] [--json]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Examples:
|
|
33
|
+
```bash
|
|
34
|
+
# Specific day by date
|
|
35
|
+
wilma schedule list --date 2026-02-25 --student "Stella" --json
|
|
36
|
+
|
|
37
|
+
# Next Thursday (also accepts Finnish short forms like to/ke/pe)
|
|
38
|
+
wilma schedule list --weekday thu --student "Stella" --json
|
|
39
|
+
|
|
40
|
+
# Tomorrow
|
|
41
|
+
wilma schedule list --when tomorrow --student "Stella" --json
|
|
30
42
|
```
|
|
31
43
|
|
|
32
44
|
### Homework
|
package/dist/index.js
CHANGED
|
@@ -518,6 +518,8 @@ async function handleCommand(args, config) {
|
|
|
518
518
|
});
|
|
519
519
|
await outputSchedule(perStudentClient, {
|
|
520
520
|
when: flags.when ?? "week",
|
|
521
|
+
date: flags.date,
|
|
522
|
+
weekday: flags.weekday,
|
|
521
523
|
json: flags.json,
|
|
522
524
|
label: studentInfo?.name ?? undefined,
|
|
523
525
|
});
|
|
@@ -591,7 +593,7 @@ async function handleCommand(args, config) {
|
|
|
591
593
|
function printUsage() {
|
|
592
594
|
console.log("Usage:");
|
|
593
595
|
console.log(" wilma summary [--days 7] [--student <id|name>] [--all-students] [--json]");
|
|
594
|
-
console.log(" wilma schedule list [--when today|tomorrow|week] [--student <id|name>] [--all-students] [--json]");
|
|
596
|
+
console.log(" wilma schedule list [--when today|tomorrow|week] [--date YYYY-MM-DD] [--weekday mon|tue|wed|thu|fri|sat|sun] [--student <id|name>] [--all-students] [--json]");
|
|
595
597
|
console.log(" wilma homework list [--limit 10] [--student <id|name>] [--all-students] [--json]");
|
|
596
598
|
console.log(" wilma exams list [--limit 20] [--student <id|name>] [--all-students] [--json]");
|
|
597
599
|
console.log(" wilma grades list [--limit 20] [--student <id|name>] [--all-students] [--json]");
|
|
@@ -683,6 +685,16 @@ function parseArgs(args) {
|
|
|
683
685
|
i += 2;
|
|
684
686
|
continue;
|
|
685
687
|
}
|
|
688
|
+
if (arg === "--date") {
|
|
689
|
+
flags.date = rest[i + 1];
|
|
690
|
+
i += 2;
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
if (arg === "--weekday") {
|
|
694
|
+
flags.weekday = rest[i + 1];
|
|
695
|
+
i += 2;
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
686
698
|
if (!flags.id && !arg.startsWith("--")) {
|
|
687
699
|
flags.id = arg;
|
|
688
700
|
i += 1;
|
|
@@ -704,6 +716,71 @@ function parseReadId(raw, entity) {
|
|
|
704
716
|
}
|
|
705
717
|
return id;
|
|
706
718
|
}
|
|
719
|
+
function parseIsoDateOrExit(raw) {
|
|
720
|
+
const value = (raw ?? "").trim();
|
|
721
|
+
// Accept YYYY-MM-DD only.
|
|
722
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
723
|
+
console.error(`Invalid date "${raw}". Expected YYYY-MM-DD.`);
|
|
724
|
+
process.exit(1);
|
|
725
|
+
}
|
|
726
|
+
// Validate date is real.
|
|
727
|
+
const d = new Date(value + "T12:00:00Z");
|
|
728
|
+
if (Number.isNaN(d.getTime())) {
|
|
729
|
+
console.error(`Invalid date "${raw}". Expected a real calendar date.`);
|
|
730
|
+
process.exit(1);
|
|
731
|
+
}
|
|
732
|
+
const iso = d.toISOString().slice(0, 10);
|
|
733
|
+
if (iso !== value) {
|
|
734
|
+
console.error(`Invalid date "${raw}". Expected a real calendar date.`);
|
|
735
|
+
process.exit(1);
|
|
736
|
+
}
|
|
737
|
+
return value;
|
|
738
|
+
}
|
|
739
|
+
function normalizeWeekdayOrExit(raw) {
|
|
740
|
+
const v = (raw ?? "").trim().toLowerCase();
|
|
741
|
+
const map = {
|
|
742
|
+
sun: 0,
|
|
743
|
+
su: 0,
|
|
744
|
+
sunday: 0,
|
|
745
|
+
mon: 1,
|
|
746
|
+
ma: 1,
|
|
747
|
+
monday: 1,
|
|
748
|
+
tue: 2,
|
|
749
|
+
ti: 2,
|
|
750
|
+
tuesday: 2,
|
|
751
|
+
wed: 3,
|
|
752
|
+
ke: 3,
|
|
753
|
+
wednesday: 3,
|
|
754
|
+
thu: 4,
|
|
755
|
+
to: 4,
|
|
756
|
+
thursday: 4,
|
|
757
|
+
fri: 5,
|
|
758
|
+
pe: 5,
|
|
759
|
+
friday: 5,
|
|
760
|
+
sat: 6,
|
|
761
|
+
la: 6,
|
|
762
|
+
saturday: 6,
|
|
763
|
+
};
|
|
764
|
+
const day = map[v];
|
|
765
|
+
if (day === undefined) {
|
|
766
|
+
console.error(`Invalid weekday "${raw}". Use mon|tue|wed|thu|fri|sat|sun (also accepts fi: ma|ti|ke|to|pe|la|su).`);
|
|
767
|
+
process.exit(1);
|
|
768
|
+
}
|
|
769
|
+
return day;
|
|
770
|
+
}
|
|
771
|
+
function nextDateForWeekday(rawWeekday) {
|
|
772
|
+
const target = normalizeWeekdayOrExit(rawWeekday);
|
|
773
|
+
const now = new Date();
|
|
774
|
+
// Use local time.
|
|
775
|
+
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 12, 0, 0);
|
|
776
|
+
const current = today.getDay();
|
|
777
|
+
let delta = (target - current + 7) % 7;
|
|
778
|
+
// If you ask for e.g. "thu" on a Saturday, you'll get next Thursday.
|
|
779
|
+
// If you ask for today's weekday, you'll get today.
|
|
780
|
+
const d = new Date(today);
|
|
781
|
+
d.setDate(d.getDate() + delta);
|
|
782
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
783
|
+
}
|
|
707
784
|
async function readPackageVersion() {
|
|
708
785
|
const pkgPath = resolve(dirname(new URL(import.meta.url).pathname), "..", "package.json");
|
|
709
786
|
const raw = await readFile(pkgPath, "utf-8");
|
|
@@ -894,7 +971,19 @@ async function outputSchedule(client, opts) {
|
|
|
894
971
|
const when = opts.when || "week";
|
|
895
972
|
let startDate;
|
|
896
973
|
let endDate;
|
|
897
|
-
if (
|
|
974
|
+
if (opts.date && opts.weekday) {
|
|
975
|
+
console.error("Use either --date or --weekday, not both.");
|
|
976
|
+
process.exit(1);
|
|
977
|
+
}
|
|
978
|
+
if (opts.date) {
|
|
979
|
+
const parsed = parseIsoDateOrExit(opts.date);
|
|
980
|
+
startDate = endDate = parsed;
|
|
981
|
+
}
|
|
982
|
+
else if (opts.weekday) {
|
|
983
|
+
const parsed = nextDateForWeekday(opts.weekday);
|
|
984
|
+
startDate = endDate = parsed;
|
|
985
|
+
}
|
|
986
|
+
else if (when === "today") {
|
|
898
987
|
startDate = endDate = todayString();
|
|
899
988
|
}
|
|
900
989
|
else if (when === "tomorrow") {
|
|
@@ -905,14 +994,17 @@ async function outputSchedule(client, opts) {
|
|
|
905
994
|
}
|
|
906
995
|
const lessons = overview.schedule.filter((l) => l.date >= startDate && l.date <= endDate);
|
|
907
996
|
if (opts.json) {
|
|
908
|
-
const result = when === "week"
|
|
997
|
+
const result = !opts.date && !opts.weekday && when === "week"
|
|
909
998
|
? { when, weekStart: startDate, weekEnd: endDate, lessons }
|
|
910
|
-
: { when, date: startDate, lessons };
|
|
999
|
+
: { when: opts.date ? "date" : (opts.weekday ? "weekday" : when), date: startDate, lessons };
|
|
911
1000
|
console.log(JSON.stringify(result, null, 2));
|
|
912
1001
|
return;
|
|
913
1002
|
}
|
|
914
1003
|
const prefix = opts.label ? `[${opts.label}] ` : "";
|
|
915
|
-
if (
|
|
1004
|
+
if (opts.date || opts.weekday) {
|
|
1005
|
+
console.log(`\n${prefix}Schedule for ${startDate}`);
|
|
1006
|
+
}
|
|
1007
|
+
else if (when === "today") {
|
|
916
1008
|
console.log(`\n${prefix}Schedule for today (${startDate})`);
|
|
917
1009
|
}
|
|
918
1010
|
else if (when === "tomorrow") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wilm-ai/wilma-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,9 +8,17 @@
|
|
|
8
8
|
"wilmai": "dist/index.js",
|
|
9
9
|
"wilma": "dist/index.js"
|
|
10
10
|
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p tsconfig.json",
|
|
13
|
+
"lint": "echo 'add lint'",
|
|
14
|
+
"test": "echo 'add tests'",
|
|
15
|
+
"start": "node dist/index.js",
|
|
16
|
+
"prepack": "pnpm --filter @wilm-ai/wilma-client build && pnpm --filter @wilm-ai/wilma-cli build",
|
|
17
|
+
"test:live": "tsc -p tsconfig.json && node test/live.spec.mjs"
|
|
18
|
+
},
|
|
11
19
|
"dependencies": {
|
|
12
20
|
"@inquirer/prompts": "^5.3.8",
|
|
13
|
-
"@wilm-ai/wilma-client": "
|
|
21
|
+
"@wilm-ai/wilma-client": "workspace:^"
|
|
14
22
|
},
|
|
15
23
|
"devDependencies": {
|
|
16
24
|
"typescript": "^5.6.3"
|
|
@@ -21,12 +29,5 @@
|
|
|
21
29
|
],
|
|
22
30
|
"publishConfig": {
|
|
23
31
|
"access": "public"
|
|
24
|
-
},
|
|
25
|
-
"scripts": {
|
|
26
|
-
"build": "tsc -p tsconfig.json",
|
|
27
|
-
"lint": "echo 'add lint'",
|
|
28
|
-
"test": "echo 'add tests'",
|
|
29
|
-
"start": "node dist/index.js",
|
|
30
|
-
"test:live": "tsc -p tsconfig.json && node test/live.spec.mjs"
|
|
31
32
|
}
|
|
32
|
-
}
|
|
33
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Wilm.ai
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|