canvaslms-cli 1.7.4 → 1.9.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/CHANGELOG.md +94 -0
- package/README.md +63 -0
- package/dist/commands/announcements.js +2 -2
- package/dist/commands/announcements.js.map +1 -1
- package/dist/commands/assignments.d.ts.map +1 -1
- package/dist/commands/assignments.js +153 -3
- package/dist/commands/assignments.js.map +1 -1
- package/dist/commands/download.d.ts +7 -0
- package/dist/commands/download.d.ts.map +1 -0
- package/dist/commands/download.js +157 -0
- package/dist/commands/download.js.map +1 -0
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +5 -4
- package/dist/commands/files.js.map +1 -1
- package/dist/commands/gpa.d.ts +5 -0
- package/dist/commands/gpa.d.ts.map +1 -0
- package/dist/commands/gpa.js +334 -0
- package/dist/commands/gpa.js.map +1 -0
- package/dist/commands/grades.d.ts.map +1 -1
- package/dist/commands/grades.js +2 -1
- package/dist/commands/grades.js.map +1 -1
- package/dist/commands/groups.js +2 -2
- package/dist/commands/groups.js.map +1 -1
- package/dist/commands/modules.d.ts.map +1 -1
- package/dist/commands/modules.js +3 -1
- package/dist/commands/modules.js.map +1 -1
- package/dist/commands/star.d.ts +3 -0
- package/dist/commands/star.d.ts.map +1 -0
- package/dist/commands/star.js +131 -0
- package/dist/commands/star.js.map +1 -0
- package/dist/commands/submit.d.ts.map +1 -1
- package/dist/commands/submit.js +2 -2
- package/dist/commands/submit.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +5 -1
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +38 -24
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/display.d.ts.map +1 -1
- package/dist/lib/display.js +8 -11
- package/dist/lib/display.js.map +1 -1
- package/dist/src/index.js +39 -1
- package/dist/src/index.js.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +20 -21
- package/dist/commands/api.d.ts +0 -3
- package/dist/commands/api.d.ts.map +0 -1
- package/dist/commands/api.js +0 -8
- package/dist/commands/api.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,100 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.9.0] - 2026-01-04
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **GPA Calculator**: New `canvas gpa` command to calculate overall GPA
|
|
13
|
+
- Calculate GPA across all active courses on 4.0 scale
|
|
14
|
+
- Option to include past/completed courses with `-p` flag
|
|
15
|
+
- Shows individual course grades, letter grades, and GPA points
|
|
16
|
+
- Summary table with total credits and quality points
|
|
17
|
+
- Letter grade to GPA conversion (A=4.0, B=3.0, etc.)
|
|
18
|
+
- Smart interpretation and feedback based on GPA
|
|
19
|
+
|
|
20
|
+
- **What-If Grade Calculator**: New `canvas what-if` command
|
|
21
|
+
- Calculate what grade you need on remaining work to achieve target grade
|
|
22
|
+
- Interactive prompts for current grade, weight, and desired final grade
|
|
23
|
+
- Clear feedback on achievability and difficulty
|
|
24
|
+
- Shows maximum possible grade if goal is unachievable
|
|
25
|
+
- Helpful color-coded results
|
|
26
|
+
|
|
27
|
+
- **Bulk File Download**: New `canvas download` command
|
|
28
|
+
- Download all files from a course at once
|
|
29
|
+
- Preserves Canvas folder structure locally
|
|
30
|
+
- Progress tracking for each file download
|
|
31
|
+
- Skips already downloaded files automatically
|
|
32
|
+
- Custom output directory support with `-o` flag
|
|
33
|
+
- Download summary with success/failure counts
|
|
34
|
+
|
|
35
|
+
- **Advanced Assignment Filtering**: Enhanced `canvas assignments` command
|
|
36
|
+
- New `--all-courses` (`-a`) flag to view assignments from all courses
|
|
37
|
+
- New `--missing` (`-m`) flag to show only missing assignments
|
|
38
|
+
- New `--due-this-week` (`-w`) flag to show assignments due within 7 days
|
|
39
|
+
- Combine filters (e.g., `-a -m` for all missing assignments)
|
|
40
|
+
- Smart sorting by due date
|
|
41
|
+
- Cross-course assignment view with course names
|
|
42
|
+
- Color-coded status indicators (submitted, missing, pending)
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- **Assignment Display**: Improved multi-course assignment display
|
|
47
|
+
- Shows course code/name for each assignment
|
|
48
|
+
- Better status indicators with visual symbols (✓, ✗, ○)
|
|
49
|
+
- Color-coded due dates (red for overdue, yellow for soon, green for later)
|
|
50
|
+
- Enhanced table layout for cross-course views
|
|
51
|
+
|
|
52
|
+
### Improved
|
|
53
|
+
|
|
54
|
+
- **README Documentation**: Added comprehensive documentation for new features
|
|
55
|
+
- Shield badges for npm version, license, workflow status, and downloads
|
|
56
|
+
- New features section highlighting recent additions
|
|
57
|
+
- Detailed usage examples for all new commands
|
|
58
|
+
- Command combinations and filter examples
|
|
59
|
+
|
|
60
|
+
## [1.8.0] - 2025-12-21
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- **Star/Unstar Commands**: New commands to manage course favorites
|
|
65
|
+
- `canvas star [course-name]` - Add courses to favorites (alias: `s`)
|
|
66
|
+
- `canvas unstar [course-name]` - Remove courses from favorites (alias: `us`)
|
|
67
|
+
- Interactive course selection when no course name provided
|
|
68
|
+
- Unstar command only shows starred courses for safety
|
|
69
|
+
- Better user experience for managing course favorites
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
|
|
73
|
+
- **Interactive Course Selection**: Unified course selection across all commands
|
|
74
|
+
- All commands now support interactive course selection when course name is omitted
|
|
75
|
+
- Consistent numbered list display for multi-match scenarios
|
|
76
|
+
- Star indicators (⭐) shown next to favorited courses
|
|
77
|
+
- Improved user experience with readline-based selection
|
|
78
|
+
- Applied to: assignments, announcements, files, grades, modules, submit, star, unstar
|
|
79
|
+
|
|
80
|
+
### Improved
|
|
81
|
+
|
|
82
|
+
- **Test Suite**: Cleaned up E2E tests for better maintainability
|
|
83
|
+
- Removed redundant option tests (31% reduction in test file size)
|
|
84
|
+
- Focused tests on command functionality and aliases
|
|
85
|
+
- All 55 tests passing with improved clarity
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
|
|
89
|
+
- **Git Hooks**: Fixed Husky pre-commit hook auto-staging behavior
|
|
90
|
+
- Removed automatic `git add -u` command
|
|
91
|
+
- Developers now have full control over staged files
|
|
92
|
+
- Enables proper atomic commits
|
|
93
|
+
|
|
94
|
+
### Development
|
|
95
|
+
|
|
96
|
+
- **Dependencies**: Updated development tooling
|
|
97
|
+
- oxfmt updated to 0.19.0
|
|
98
|
+
- oxlint updated to 1.34.0
|
|
99
|
+
- @types/node updated to 22.10.5
|
|
100
|
+
- CI workflow now uses `bun ci` for deterministic builds
|
|
101
|
+
|
|
8
102
|
## [1.7.4] - 2025-12-20
|
|
9
103
|
|
|
10
104
|
### Changed
|
package/README.md
CHANGED
|
@@ -1,12 +1,53 @@
|
|
|
1
1
|
# Canvas CLI Tool
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/canvaslms-cli)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://github.com/caphefalumi/Canvas-CLI/actions/workflows/npm-publish.yml)
|
|
6
|
+
[](https://www.npmjs.com/package/canvaslms-cli)
|
|
7
|
+
|
|
3
8
|
A modern, user-friendly command-line interface for Canvas LMS. Manage courses, assignments, submissions, grades, and more directly from your terminal.
|
|
4
9
|
|
|
10
|
+
## ✨ New Features
|
|
11
|
+
|
|
12
|
+
### 📊 GPA Calculator
|
|
13
|
+
|
|
14
|
+
- Calculate your overall GPA across all courses on a 4.0 scale
|
|
15
|
+
- Include or exclude past/completed courses
|
|
16
|
+
- See letter grades and quality points for each course
|
|
17
|
+
- Automatic GPA calculation with detailed breakdown
|
|
18
|
+
|
|
19
|
+
### 🎯 What-If Grade Calculator
|
|
20
|
+
|
|
21
|
+
- Find out what grade you need on remaining work to achieve your target
|
|
22
|
+
- Interactive calculator with clear feedback
|
|
23
|
+
- Shows if your goal is achievable
|
|
24
|
+
|
|
25
|
+
### 📥 Bulk File Download
|
|
26
|
+
|
|
27
|
+
- Download ALL files from a course at once
|
|
28
|
+
- Preserves Canvas folder structure
|
|
29
|
+
- Skips already downloaded files
|
|
30
|
+
- Progress tracking for each file
|
|
31
|
+
|
|
32
|
+
### 🔍 Advanced Assignment Filtering
|
|
33
|
+
|
|
34
|
+
- View assignments from **all courses** at once
|
|
35
|
+
- Filter by **missing** assignments
|
|
36
|
+
- Filter by **due this week**
|
|
37
|
+
- Combine filters (e.g., all missing assignments across all courses)
|
|
38
|
+
- Smart sorting by due date
|
|
39
|
+
|
|
5
40
|
## Features
|
|
6
41
|
|
|
7
42
|
- List and filter enrolled/starred courses
|
|
43
|
+
- Star/unstar courses to manage favorites
|
|
44
|
+
- Interactive course selection for all commands
|
|
8
45
|
- View assignments, grades, and submission status
|
|
46
|
+
- **Advanced assignment filtering** (missing, due this week, all courses)
|
|
9
47
|
- Interactive file upload for assignments with visual file browser
|
|
48
|
+
- **Bulk download all course files** with organized folder structure
|
|
49
|
+
- **GPA Calculator** - Calculate overall GPA across all courses on 4.0 scale
|
|
50
|
+
- **What-if Grade Calculator** - Find out what you need on remaining work
|
|
10
51
|
- View upcoming due dates and calendar events
|
|
11
52
|
- Browse course modules and content
|
|
12
53
|
- View course announcements
|
|
@@ -86,11 +127,22 @@ canvas config # Configure domain and API token
|
|
|
86
127
|
canvas list # List starred courses
|
|
87
128
|
canvas list -a # List all enrolled courses
|
|
88
129
|
|
|
130
|
+
# Star/Unstar Courses
|
|
131
|
+
canvas star # Interactive course selection to star
|
|
132
|
+
canvas star database # Star course matching database
|
|
133
|
+
canvas unstar # Interactive selection (shows only starred courses)
|
|
134
|
+
canvas unstar math # Unstar course matching math
|
|
135
|
+
|
|
89
136
|
# Assignments (supports course name instead of ID)
|
|
90
137
|
canvas assignments # Interactive course selection
|
|
91
138
|
canvas assignments math # List assignments for course matching math
|
|
92
139
|
canvas assignments -s # Show only submitted assignments
|
|
93
140
|
canvas assignments -p # Show only pending assignments
|
|
141
|
+
canvas assignments -a # Show assignments from ALL courses
|
|
142
|
+
canvas assignments -m # Show MISSING assignments only
|
|
143
|
+
canvas assignments -w # Show assignments DUE THIS WEEK
|
|
144
|
+
canvas assignments -a -m # Show all missing assignments across all courses
|
|
145
|
+
canvas assignments -a -w # Show assignments due this week from all courses
|
|
94
146
|
|
|
95
147
|
# Grades (supports course name instead of ID)
|
|
96
148
|
canvas grades # Interactive course selection + detailed grades
|
|
@@ -98,6 +150,17 @@ canvas grades database # Show detailed grades for course matching databa
|
|
|
98
150
|
canvas grades -a # Include inactive/completed courses
|
|
99
151
|
canvas grades -v # Include verbose enrollment details
|
|
100
152
|
|
|
153
|
+
# GPA Calculator & What-If Scenarios
|
|
154
|
+
canvas gpa # Calculate overall GPA across all active courses
|
|
155
|
+
canvas gpa -p # Include past/completed courses in GPA calculation
|
|
156
|
+
canvas what-if # Calculate what grade you need on remaining work
|
|
157
|
+
|
|
158
|
+
# Bulk Download Files
|
|
159
|
+
canvas download # Interactive course selection for bulk download
|
|
160
|
+
canvas download math # Download all files from course matching math
|
|
161
|
+
canvas download -o ~/Downloads # Specify output directory
|
|
162
|
+
canvas download math -o ./files # Download to specific folder
|
|
163
|
+
|
|
101
164
|
# Announcements (supports course name instead of ID)
|
|
102
165
|
canvas announcements # Interactive course selection
|
|
103
166
|
canvas announcements software # Show announcements for course matching software
|
|
@@ -16,12 +16,12 @@ export async function showAnnouncements(courseName, options = {}) {
|
|
|
16
16
|
rl = result.rl;
|
|
17
17
|
}
|
|
18
18
|
else {
|
|
19
|
-
|
|
19
|
+
rl = createReadlineInterface();
|
|
20
|
+
const course = await getCanvasCourse(courseName, rl);
|
|
20
21
|
if (!course) {
|
|
21
22
|
return;
|
|
22
23
|
}
|
|
23
24
|
selectedCourseId = course.id.toString();
|
|
24
|
-
rl = createReadlineInterface();
|
|
25
25
|
}
|
|
26
26
|
const limit = parseInt(options.limit || "5") || 5;
|
|
27
27
|
printInfo("Loading announcements...");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"announcements.js","sourceRoot":"","sources":["../../commands/announcements.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,yBAAyB,EACzB,SAAS,EACT,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAAmB,EACnB,UAAoC,EAAE;IAEtC,IAAI,EAAE,GAAsD,IAAI,CAAC;IAEjE,IAAI,CAAC;QACH,IAAI,gBAAwB,CAAC;QAE7B,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;gBAC9B,KAAK,EAAE,wCAAwC;aAChD,CAAC,CAAC;YACH,IAAI,CAAC,MAAM;gBAAE,OAAO;YAEpB,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;YAC/C,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"announcements.js","sourceRoot":"","sources":["../../commands/announcements.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assignments.d.ts","sourceRoot":"","sources":["../../commands/assignments.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assignments.d.ts","sourceRoot":"","sources":["../../commands/assignments.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAGV,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAuM3B,wBAAsB,eAAe,CACnC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAuEf"}
|
|
@@ -1,8 +1,157 @@
|
|
|
1
1
|
import { makeCanvasRequest, getCanvasCourse } from "../lib/api-client.js";
|
|
2
|
-
import {
|
|
2
|
+
import { createReadlineInterface } from "../lib/interactive.js";
|
|
3
|
+
import { pickCourse, displayAssignments, printInfo, printError, printSuccess, printSeparator, Table, } from "../lib/display.js";
|
|
3
4
|
import chalk from "chalk";
|
|
5
|
+
async function listAllCoursesAssignments(options = {}) {
|
|
6
|
+
try {
|
|
7
|
+
printSeparator("=");
|
|
8
|
+
printInfo("Loading assignments from all courses...");
|
|
9
|
+
printSeparator("=");
|
|
10
|
+
const queryParams = [
|
|
11
|
+
"enrollment_state=active",
|
|
12
|
+
"include[]=term",
|
|
13
|
+
"per_page=100",
|
|
14
|
+
];
|
|
15
|
+
const courses = await makeCanvasRequest("get", "courses", queryParams);
|
|
16
|
+
if (!courses || courses.length === 0) {
|
|
17
|
+
printError("No courses found.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
console.log(chalk.cyan(`Found ${courses.length} active course(s)\n`));
|
|
21
|
+
const allAssignments = [];
|
|
22
|
+
for (const course of courses) {
|
|
23
|
+
try {
|
|
24
|
+
const assignmentParams = ["include[]=submission", "per_page=100"];
|
|
25
|
+
const assignments = await makeCanvasRequest("get", `courses/${course.id}/assignments`, assignmentParams);
|
|
26
|
+
if (assignments && assignments.length > 0) {
|
|
27
|
+
for (const assignment of assignments) {
|
|
28
|
+
allAssignments.push({
|
|
29
|
+
...assignment,
|
|
30
|
+
courseName: course.name,
|
|
31
|
+
courseCode: course.course_code,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (allAssignments.length === 0) {
|
|
41
|
+
printError("No assignments found in any course.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
let filteredAssignments = allAssignments;
|
|
45
|
+
if (options.missing) {
|
|
46
|
+
filteredAssignments = filteredAssignments.filter((a) => {
|
|
47
|
+
const submission = a.submission;
|
|
48
|
+
const isNotSubmitted = !submission || !submission.submitted_at;
|
|
49
|
+
const hasDueDate = a.due_at !== null;
|
|
50
|
+
return isNotSubmitted && hasDueDate;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (options.submitted) {
|
|
54
|
+
filteredAssignments = filteredAssignments.filter((a) => a.submission && a.submission.submitted_at);
|
|
55
|
+
}
|
|
56
|
+
if (options.pending) {
|
|
57
|
+
filteredAssignments = filteredAssignments.filter((a) => !a.submission || !a.submission.submitted_at);
|
|
58
|
+
}
|
|
59
|
+
if (options.dueThisWeek) {
|
|
60
|
+
const now = new Date();
|
|
61
|
+
const oneWeekFromNow = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
|
|
62
|
+
filteredAssignments = filteredAssignments.filter((a) => {
|
|
63
|
+
if (!a.due_at)
|
|
64
|
+
return false;
|
|
65
|
+
const dueDate = new Date(a.due_at);
|
|
66
|
+
return dueDate >= now && dueDate <= oneWeekFromNow;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
filteredAssignments.sort((a, b) => {
|
|
70
|
+
if (!a.due_at)
|
|
71
|
+
return 1;
|
|
72
|
+
if (!b.due_at)
|
|
73
|
+
return -1;
|
|
74
|
+
return new Date(a.due_at).getTime() - new Date(b.due_at).getTime();
|
|
75
|
+
});
|
|
76
|
+
printSuccess(`Found ${filteredAssignments.length} assignment(s) matching criteria.\n`);
|
|
77
|
+
const table = new Table([
|
|
78
|
+
{ key: "course", header: "Course", flex: 1.5, minWidth: 15 },
|
|
79
|
+
{ key: "assignment", header: "Assignment", flex: 2.5, minWidth: 25 },
|
|
80
|
+
{
|
|
81
|
+
key: "due",
|
|
82
|
+
header: "Due Date",
|
|
83
|
+
flex: 1.2,
|
|
84
|
+
minWidth: 12,
|
|
85
|
+
color: (val) => {
|
|
86
|
+
if (val === "No due date")
|
|
87
|
+
return chalk.gray(val);
|
|
88
|
+
const dueDate = new Date(val);
|
|
89
|
+
const now = new Date();
|
|
90
|
+
const daysUntilDue = Math.ceil((dueDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
|
91
|
+
if (daysUntilDue < 0)
|
|
92
|
+
return chalk.red(val);
|
|
93
|
+
if (daysUntilDue <= 2)
|
|
94
|
+
return chalk.red.bold(val);
|
|
95
|
+
if (daysUntilDue <= 7)
|
|
96
|
+
return chalk.yellow(val);
|
|
97
|
+
return chalk.green(val);
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
key: "status",
|
|
102
|
+
header: "Status",
|
|
103
|
+
flex: 1,
|
|
104
|
+
minWidth: 10,
|
|
105
|
+
color: (val) => {
|
|
106
|
+
if (val.includes("✓"))
|
|
107
|
+
return chalk.green(val);
|
|
108
|
+
if (val.includes("✗"))
|
|
109
|
+
return chalk.red(val);
|
|
110
|
+
return chalk.yellow(val);
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{ key: "points", header: "Points", flex: 0.8, minWidth: 8 },
|
|
114
|
+
], { showRowNumbers: true, title: undefined });
|
|
115
|
+
for (const assignment of filteredAssignments) {
|
|
116
|
+
const submission = assignment.submission;
|
|
117
|
+
const isSubmitted = submission && submission.submitted_at;
|
|
118
|
+
let statusText = "";
|
|
119
|
+
if (isSubmitted) {
|
|
120
|
+
const hasGrade = submission.score !== null && submission.score !== undefined;
|
|
121
|
+
statusText = hasGrade
|
|
122
|
+
? `✓ Graded (${submission.score})`
|
|
123
|
+
: "✓ Submitted";
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const dueDate = assignment.due_at ? new Date(assignment.due_at) : null;
|
|
127
|
+
const isPastDue = dueDate && dueDate < new Date();
|
|
128
|
+
statusText = isPastDue ? "✗ Missing" : "○ Pending";
|
|
129
|
+
}
|
|
130
|
+
table.addRow({
|
|
131
|
+
course: assignment.courseCode ||
|
|
132
|
+
assignment.courseName?.substring(0, 15) ||
|
|
133
|
+
"Unknown",
|
|
134
|
+
assignment: assignment.name,
|
|
135
|
+
due: assignment.due_at
|
|
136
|
+
? new Date(assignment.due_at).toLocaleDateString()
|
|
137
|
+
: "No due date",
|
|
138
|
+
status: statusText,
|
|
139
|
+
points: assignment.points_possible?.toString() || "N/A",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
table.render();
|
|
143
|
+
printSeparator("=");
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
147
|
+
printError(`Error fetching assignments: ${errorMessage}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
4
150
|
export async function listAssignments(courseName, options = {}) {
|
|
5
151
|
try {
|
|
152
|
+
if (options.allCourses) {
|
|
153
|
+
return await listAllCoursesAssignments(options);
|
|
154
|
+
}
|
|
6
155
|
let course;
|
|
7
156
|
let selectedCourseId;
|
|
8
157
|
if (!courseName) {
|
|
@@ -16,13 +165,14 @@ export async function listAssignments(courseName, options = {}) {
|
|
|
16
165
|
result.rl.close();
|
|
17
166
|
}
|
|
18
167
|
else {
|
|
19
|
-
|
|
168
|
+
const rl = createReadlineInterface();
|
|
169
|
+
course = await getCanvasCourse(courseName, rl);
|
|
20
170
|
if (!course) {
|
|
21
171
|
return;
|
|
22
172
|
}
|
|
23
173
|
selectedCourseId = course.id.toString();
|
|
24
174
|
}
|
|
25
|
-
printSeparator(
|
|
175
|
+
printSeparator();
|
|
26
176
|
const assignmentParams = ["include[]=submission", "per_page=100"];
|
|
27
177
|
printInfo("Loading assignments, please wait...");
|
|
28
178
|
const assignments = await makeCanvasRequest("get", `courses/${selectedCourseId}/assignments`, assignmentParams);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assignments.js","sourceRoot":"","sources":["../../commands/assignments.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,SAAS,EACT,UAAU,EACV,YAAY,EACZ,cAAc,
|
|
1
|
+
{"version":3,"file":"assignments.js","sourceRoot":"","sources":["../../commands/assignments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../commands/download.ts"],"names":[],"mappings":"AAoBA,UAAU,eAAe;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgGD,wBAAsB,YAAY,CAChC,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CA0Hf"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { makeCanvasRequest, getCanvasCourse } from "../lib/api-client.js";
|
|
2
|
+
import { pickCourse, printInfo, printError, printSuccess, printSeparator, } from "../lib/display.js";
|
|
3
|
+
import { createReadlineInterface } from "../lib/interactive.js";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import https from "https";
|
|
8
|
+
import http from "http";
|
|
9
|
+
function sanitizeFileName(name) {
|
|
10
|
+
return name.replace(/[<>:"/\\|?*\x00-\x1F]/g, "_").trim();
|
|
11
|
+
}
|
|
12
|
+
async function downloadFile(url, outputPath, fileName) {
|
|
13
|
+
return new Promise((resolve) => {
|
|
14
|
+
const client = url.startsWith("https") ? https : http;
|
|
15
|
+
const request = client.get(url, (response) => {
|
|
16
|
+
if (response.statusCode === 301 ||
|
|
17
|
+
response.statusCode === 302 ||
|
|
18
|
+
response.statusCode === 307 ||
|
|
19
|
+
response.statusCode === 308) {
|
|
20
|
+
const redirectUrl = response.headers.location;
|
|
21
|
+
if (redirectUrl) {
|
|
22
|
+
downloadFile(redirectUrl, outputPath, fileName).then(resolve);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (response.statusCode !== 200) {
|
|
27
|
+
console.log(chalk.red(` ✗ Failed to download ${fileName}: HTTP ${response.statusCode}`));
|
|
28
|
+
resolve(false);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const fileStream = fs.createWriteStream(outputPath);
|
|
32
|
+
response.pipe(fileStream);
|
|
33
|
+
fileStream.on("finish", () => {
|
|
34
|
+
fileStream.close();
|
|
35
|
+
console.log(chalk.green(` ✓ Downloaded: ${fileName}`));
|
|
36
|
+
resolve(true);
|
|
37
|
+
});
|
|
38
|
+
fileStream.on("error", (err) => {
|
|
39
|
+
fs.unlink(outputPath, () => { });
|
|
40
|
+
console.log(chalk.red(` ✗ Error downloading ${fileName}: ${err.message}`));
|
|
41
|
+
resolve(false);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
request.on("error", (err) => {
|
|
45
|
+
console.log(chalk.red(` ✗ Error downloading ${fileName}: ${err.message}`));
|
|
46
|
+
resolve(false);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async function getAllFolders(courseId) {
|
|
51
|
+
try {
|
|
52
|
+
const folders = await makeCanvasRequest("get", `courses/${courseId}/folders`, ["per_page=100"]);
|
|
53
|
+
return folders || [];
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async function getFilesInFolder(folderId) {
|
|
60
|
+
try {
|
|
61
|
+
const files = await makeCanvasRequest("get", `folders/${folderId}/files`, ["per_page=100"]);
|
|
62
|
+
return files || [];
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export async function bulkDownload(courseName, options = {}) {
|
|
69
|
+
try {
|
|
70
|
+
let course;
|
|
71
|
+
let selectedCourseId;
|
|
72
|
+
if (!courseName) {
|
|
73
|
+
const result = await pickCourse({
|
|
74
|
+
title: "\nSelect course to download files from...",
|
|
75
|
+
showAll: options.all,
|
|
76
|
+
});
|
|
77
|
+
if (!result)
|
|
78
|
+
return;
|
|
79
|
+
course = result.course;
|
|
80
|
+
selectedCourseId = course.id.toString();
|
|
81
|
+
result.rl.close();
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const rl = createReadlineInterface();
|
|
85
|
+
course = await getCanvasCourse(courseName, rl);
|
|
86
|
+
if (!course) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
selectedCourseId = course.id.toString();
|
|
90
|
+
rl.close();
|
|
91
|
+
}
|
|
92
|
+
printSeparator("=");
|
|
93
|
+
printInfo(`Downloading files from: ${course?.name || selectedCourseId}`);
|
|
94
|
+
printSeparator("=");
|
|
95
|
+
const sanitizedCourseName = sanitizeFileName(course?.name || `course_${selectedCourseId}`);
|
|
96
|
+
const baseOutputDir = options.output || process.cwd();
|
|
97
|
+
const outputDir = path.join(baseOutputDir, sanitizedCourseName);
|
|
98
|
+
if (!fs.existsSync(outputDir)) {
|
|
99
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
console.log(chalk.cyan(`\nOutput directory: ${outputDir}\n`));
|
|
102
|
+
printInfo("Fetching folder structure...");
|
|
103
|
+
const folders = await getAllFolders(selectedCourseId);
|
|
104
|
+
if (folders.length === 0) {
|
|
105
|
+
printError("No folders found in this course.");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
console.log(chalk.cyan(`Found ${folders.length} folder(s)\n`));
|
|
109
|
+
let totalFiles = 0;
|
|
110
|
+
let downloadedFiles = 0;
|
|
111
|
+
let failedFiles = 0;
|
|
112
|
+
for (const folder of folders) {
|
|
113
|
+
const folderPath = folder.full_name || folder.name;
|
|
114
|
+
const sanitizedPath = sanitizeFileName(folderPath);
|
|
115
|
+
const folderOutputDir = path.join(outputDir, sanitizedPath);
|
|
116
|
+
if (!fs.existsSync(folderOutputDir)) {
|
|
117
|
+
fs.mkdirSync(folderOutputDir, { recursive: true });
|
|
118
|
+
}
|
|
119
|
+
const files = await getFilesInFolder(folder.id.toString());
|
|
120
|
+
if (files.length > 0) {
|
|
121
|
+
console.log(chalk.bold(`\n📁 ${folderPath} (${files.length} files):`));
|
|
122
|
+
totalFiles += files.length;
|
|
123
|
+
for (const file of files) {
|
|
124
|
+
const sanitizedFileName = sanitizeFileName(file.display_name || file.filename);
|
|
125
|
+
const filePath = path.join(folderOutputDir, sanitizedFileName);
|
|
126
|
+
if (fs.existsSync(filePath)) {
|
|
127
|
+
console.log(chalk.gray(` ⊙ Skipped (exists): ${sanitizedFileName}`));
|
|
128
|
+
downloadedFiles++;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const success = await downloadFile(file.url, filePath, sanitizedFileName);
|
|
132
|
+
if (success) {
|
|
133
|
+
downloadedFiles++;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
failedFiles++;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
printSeparator("=");
|
|
142
|
+
console.log(chalk.white.bold("\n📊 Download Summary:\n"));
|
|
143
|
+
console.log(chalk.cyan(`Total files found: ${totalFiles}`));
|
|
144
|
+
console.log(chalk.green(`Successfully downloaded: ${downloadedFiles}`));
|
|
145
|
+
if (failedFiles > 0) {
|
|
146
|
+
console.log(chalk.red(`Failed: ${failedFiles}`));
|
|
147
|
+
}
|
|
148
|
+
console.log(chalk.cyan(`\nAll files saved to: ${outputDir}`));
|
|
149
|
+
printSeparator("=");
|
|
150
|
+
printSuccess("\nBulk download completed!");
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
154
|
+
printError(`Error during bulk download: ${errorMessage}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=download.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../commands/download.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../commands/files.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAIV,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAmH3B,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,MAAY,GACvB,OAAO,CAAC,IAAI,CAAC,CA8Kf;AAED,wBAAsB,SAAS,CAC7B,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../commands/files.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAIV,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAmH3B,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,MAAY,GACvB,OAAO,CAAC,IAAI,CAAC,CA8Kf;AAED,wBAAsB,SAAS,CAC7B,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAsJf"}
|
package/dist/commands/files.js
CHANGED
|
@@ -138,7 +138,7 @@ export async function browseFolder(courseId, folderId, courseName, folderPath =
|
|
|
138
138
|
}
|
|
139
139
|
console.log(chalk.cyan.bold(`\n${courseName}`));
|
|
140
140
|
console.log(chalk.gray(` Path: ${folderPath}`));
|
|
141
|
-
printSeparator(
|
|
141
|
+
printSeparator();
|
|
142
142
|
const menuItems = [];
|
|
143
143
|
if (folderId) {
|
|
144
144
|
menuItems.push({ type: "back", name: "📤 .. (Go back)" });
|
|
@@ -239,12 +239,13 @@ export async function showFiles(courseName, options = {}) {
|
|
|
239
239
|
result.rl.close();
|
|
240
240
|
}
|
|
241
241
|
else {
|
|
242
|
-
|
|
242
|
+
const rl = createReadlineInterface();
|
|
243
|
+
course = await getCanvasCourse(courseName, rl);
|
|
243
244
|
if (!course) {
|
|
244
245
|
return;
|
|
245
246
|
}
|
|
246
247
|
}
|
|
247
|
-
printSeparator(
|
|
248
|
+
printSeparator();
|
|
248
249
|
printInfo("Loading course files...");
|
|
249
250
|
const files = await makeCanvasRequest("get", `courses/${course.id}/files`, ["per_page=100", "sort=updated_at", "order=desc"]);
|
|
250
251
|
if (!files || files.length === 0) {
|
|
@@ -253,7 +254,7 @@ export async function showFiles(courseName, options = {}) {
|
|
|
253
254
|
}
|
|
254
255
|
console.log(chalk.cyan.bold(`\nFiles in: ${course.name}`));
|
|
255
256
|
console.log(chalk.gray(` Total: ${files.length} file(s)`));
|
|
256
|
-
printSeparator(
|
|
257
|
+
printSeparator();
|
|
257
258
|
const columns = [
|
|
258
259
|
{
|
|
259
260
|
key: "name",
|