canvaslms-cli 1.3.3 ā 1.4.1
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/commands/announcements.js +102 -80
- package/commands/assignments.js +100 -130
- package/commands/config.js +239 -242
- package/commands/grades.js +201 -205
- package/commands/list.js +68 -70
- package/commands/profile.js +35 -34
- package/commands/submit.js +98 -151
- package/lib/api-client.js +4 -8
- package/lib/config-validator.js +60 -63
- package/lib/config.js +103 -135
- package/lib/file-upload.js +73 -78
- package/lib/interactive.js +180 -132
- package/package.json +4 -2
- package/src/index.js +25 -47
package/commands/grades.js
CHANGED
|
@@ -1,205 +1,201 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Grades command
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
'
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
console.log(
|
|
47
|
-
console.log(
|
|
48
|
-
console.log(
|
|
49
|
-
console.log(
|
|
50
|
-
console.log(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
console.log('
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
submission.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
console.log('');
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// Ask if user wants to see detailed grades for a specific course
|
|
185
|
-
const viewDetailed = await askQuestion(rl, 'View detailed grades for a specific course? (Y/n): ');
|
|
186
|
-
|
|
187
|
-
if (viewDetailed.toLowerCase() === 'n' || viewDetailed.toLowerCase() === 'no') {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const courseChoice = await askQuestion(rl, '\nEnter course number for detailed grades: ');
|
|
192
|
-
const courseIndex = parseInt(courseChoice) - 1;
|
|
193
|
-
|
|
194
|
-
if (courseIndex >= 0 && courseIndex < coursesWithGrades.length) {
|
|
195
|
-
const selectedCourse = coursesWithGrades[courseIndex];
|
|
196
|
-
console.log(`\
|
|
197
|
-
await showCourseGrades(selectedCourse.id, options, rl);
|
|
198
|
-
} else {
|
|
199
|
-
console.log('Invalid course selection.');
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
module.exports = {
|
|
204
|
-
showGrades
|
|
205
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Grades command
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { makeCanvasRequest } from '../lib/api-client.js';
|
|
6
|
+
import { createReadlineInterface, askQuestion } from '../lib/interactive.js';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
|
|
9
|
+
export async function showGrades(courseId, options) {
|
|
10
|
+
const rl = createReadlineInterface();
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
if (courseId) {
|
|
14
|
+
// Get grades for specific course with assignment details
|
|
15
|
+
await showCourseGrades(courseId, options, rl);
|
|
16
|
+
} else {
|
|
17
|
+
// Interactive course selection for grades
|
|
18
|
+
await showInteractiveGrades(options, rl);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error(chalk.red('Error fetching grades: ') + error.message);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
} finally {
|
|
25
|
+
rl.close();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function showCourseGrades(courseId, options, rl) {
|
|
30
|
+
// Get course details
|
|
31
|
+
const course = await makeCanvasRequest('get', `courses/${courseId}`);
|
|
32
|
+
|
|
33
|
+
// Get overall enrollment grades
|
|
34
|
+
const enrollments = await makeCanvasRequest('get', `courses/${courseId}/enrollments`, [
|
|
35
|
+
'user_id=self',
|
|
36
|
+
'include[]=grades'
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
if (!enrollments || enrollments.length === 0) {
|
|
40
|
+
console.log(chalk.red('Error: No enrollment found for this course.'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const enrollment = enrollments[0];
|
|
45
|
+
|
|
46
|
+
console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
|
|
47
|
+
console.log(chalk.cyan.bold('Grades for: ') + course.name);
|
|
48
|
+
console.log(chalk.cyan('-'.repeat(60)));
|
|
49
|
+
console.log(chalk.white('Course Overview:'));
|
|
50
|
+
console.log(chalk.white(' Current Score: ') + (enrollment.grades?.current_score || 'N/A') + '%');
|
|
51
|
+
console.log(chalk.white(' Final Score: ') + (enrollment.grades?.final_score || 'N/A') + '%');
|
|
52
|
+
console.log(chalk.white(' Current Grade: ') + (enrollment.grades?.current_grade || 'N/A'));
|
|
53
|
+
console.log(chalk.white(' Final Grade: ') + (enrollment.grades?.final_grade || 'N/A'));
|
|
54
|
+
|
|
55
|
+
// Get assignment grades
|
|
56
|
+
console.log(chalk.cyan('\nLoading assignment grades...'));
|
|
57
|
+
const assignments = await makeCanvasRequest('get', `courses/${courseId}/assignments`, [
|
|
58
|
+
'include[]=submission',
|
|
59
|
+
'order_by=due_at',
|
|
60
|
+
'per_page=100'
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
if (!assignments || assignments.length === 0) {
|
|
64
|
+
console.log(chalk.yellow('No assignments found for this course.'));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Filter assignments with grades
|
|
69
|
+
const gradedAssignments = assignments.filter(assignment => {
|
|
70
|
+
const submission = assignment.submission;
|
|
71
|
+
return submission && (
|
|
72
|
+
submission.score !== null ||
|
|
73
|
+
submission.excused ||
|
|
74
|
+
submission.missing ||
|
|
75
|
+
submission.grade
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (gradedAssignments.length === 0) {
|
|
80
|
+
console.log(chalk.yellow('No graded assignments found.'));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log(chalk.green('Success: Grades loaded.'));
|
|
85
|
+
console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
|
|
86
|
+
console.log(chalk.cyan.bold(`Assignment Grades (${gradedAssignments.length} graded):`));
|
|
87
|
+
console.log(chalk.cyan('-'.repeat(60)));
|
|
88
|
+
gradedAssignments.forEach((assignment, index) => {
|
|
89
|
+
const submission = assignment.submission;
|
|
90
|
+
let gradeDisplay = '';
|
|
91
|
+
let gradeColor = chalk.white;
|
|
92
|
+
|
|
93
|
+
if (submission.score !== null && submission.score !== undefined) {
|
|
94
|
+
const score = submission.score % 1 === 0 ? Math.round(submission.score) : submission.score;
|
|
95
|
+
const total = assignment.points_possible || 0;
|
|
96
|
+
gradeDisplay = `${score}/${total} pts`;
|
|
97
|
+
|
|
98
|
+
// Color coding based on percentage
|
|
99
|
+
if (total > 0) {
|
|
100
|
+
const percentage = (submission.score / total) * 100;
|
|
101
|
+
if (percentage >= 90) gradeColor = chalk.green;
|
|
102
|
+
else if (percentage >= 80) gradeColor = chalk.cyan;
|
|
103
|
+
else if (percentage >= 70) gradeColor = chalk.yellow;
|
|
104
|
+
else if (percentage >= 60) gradeColor = chalk.magenta;
|
|
105
|
+
else gradeColor = chalk.red;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Add letter grade if available
|
|
109
|
+
if (submission.grade && isNaN(submission.grade)) {
|
|
110
|
+
gradeDisplay = `${submission.grade} (${gradeDisplay})`;
|
|
111
|
+
}
|
|
112
|
+
} else if (submission.excused) {
|
|
113
|
+
gradeDisplay = 'Excused';
|
|
114
|
+
gradeColor = chalk.blue;
|
|
115
|
+
} else if (submission.missing) {
|
|
116
|
+
gradeDisplay = 'Missing';
|
|
117
|
+
gradeColor = chalk.red;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log(chalk.white(`${index + 1}. ${assignment.name}`));
|
|
121
|
+
console.log(' Grade: ' + gradeColor(gradeDisplay));
|
|
122
|
+
|
|
123
|
+
if (submission.submitted_at) {
|
|
124
|
+
console.log(' Submitted: ' + new Date(submission.submitted_at).toLocaleDateString());
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (assignment.due_at) {
|
|
128
|
+
console.log(' Due: ' + new Date(assignment.due_at).toLocaleDateString());
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (options.verbose && submission.grader_comments) {
|
|
132
|
+
console.log(' Comments: ' + submission.grader_comments);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
console.log('');
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function showInteractiveGrades(options, rl) {
|
|
140
|
+
// Get all courses with enrollment information
|
|
141
|
+
const courses = await makeCanvasRequest('get', 'courses', [
|
|
142
|
+
'enrollment_state=active',
|
|
143
|
+
'include[]=enrollments',
|
|
144
|
+
'include[]=favorites',
|
|
145
|
+
'include[]=total_scores'
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
if (!courses || courses.length === 0) {
|
|
149
|
+
console.log(chalk.red('Error: No courses found.'));
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Move declaration above first use
|
|
154
|
+
const coursesWithGrades = courses.filter(course =>
|
|
155
|
+
course.enrollments && course.enrollments.length > 0
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Show courses overview first
|
|
159
|
+
console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
|
|
160
|
+
console.log(chalk.cyan.bold('Grades Overview'));
|
|
161
|
+
console.log(chalk.cyan('-'.repeat(60)));
|
|
162
|
+
console.log(chalk.white(`Found ${coursesWithGrades.length} enrolled course(s):\n`));
|
|
163
|
+
|
|
164
|
+
coursesWithGrades.forEach((course, index) => {
|
|
165
|
+
let gradeColor = chalk.gray;
|
|
166
|
+
const enrollment = course.enrollments[0];
|
|
167
|
+
const currentScore = enrollment.grades?.current_score;
|
|
168
|
+
if (currentScore !== null && currentScore !== undefined) {
|
|
169
|
+
if (currentScore >= 90) gradeColor = chalk.green;
|
|
170
|
+
else if (currentScore >= 80) gradeColor = chalk.cyan;
|
|
171
|
+
else if (currentScore >= 70) gradeColor = chalk.yellow;
|
|
172
|
+
else if (currentScore >= 60) gradeColor = chalk.magenta;
|
|
173
|
+
else gradeColor = chalk.red;
|
|
174
|
+
}
|
|
175
|
+
console.log(chalk.white(`${index + 1}. ${course.name}`));
|
|
176
|
+
if (enrollment.grades) {
|
|
177
|
+
console.log(' Current: ' + gradeColor(`${currentScore || 'N/A'}% (${enrollment.grades.current_grade || 'N/A'})`));
|
|
178
|
+
} else {
|
|
179
|
+
console.log(' Current: ' + chalk.gray('Grades not available'));
|
|
180
|
+
}
|
|
181
|
+
console.log('');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Ask if user wants to see detailed grades for a specific course
|
|
185
|
+
const viewDetailed = await askQuestion(rl, 'View detailed grades for a specific course? (Y/n): ');
|
|
186
|
+
|
|
187
|
+
if (viewDetailed.toLowerCase() === 'n' || viewDetailed.toLowerCase() === 'no') {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const courseChoice = await askQuestion(rl, '\nEnter course number for detailed grades: ');
|
|
192
|
+
const courseIndex = parseInt(courseChoice) - 1;
|
|
193
|
+
|
|
194
|
+
if (courseIndex >= 0 && courseIndex < coursesWithGrades.length) {
|
|
195
|
+
const selectedCourse = coursesWithGrades[courseIndex];
|
|
196
|
+
console.log(chalk.green(`\nSelected: ${selectedCourse.name}`));
|
|
197
|
+
await showCourseGrades(selectedCourse.id, options, rl);
|
|
198
|
+
} else {
|
|
199
|
+
console.log(chalk.red('Invalid course selection.'));
|
|
200
|
+
}
|
|
201
|
+
}
|
package/commands/list.js
CHANGED
|
@@ -1,70 +1,68 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* List courses command
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
queryParams.push('
|
|
16
|
-
queryParams.push('include[]=
|
|
17
|
-
queryParams.push('include[]=
|
|
18
|
-
queryParams.push('include[]=
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
let filteredCourses = courses;
|
|
29
|
-
if (!options.all) {
|
|
30
|
-
filteredCourses = courses.filter(course => course.is_favorite);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
console.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
listCourses
|
|
70
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* List courses command
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { makeCanvasRequest } from '../lib/api-client.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
|
|
8
|
+
function pad(str, len) {
|
|
9
|
+
return str + ' '.repeat(Math.max(0, len - str.length));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function listCourses(options) {
|
|
13
|
+
try {
|
|
14
|
+
const queryParams = [];
|
|
15
|
+
queryParams.push('enrollment_state=active');
|
|
16
|
+
queryParams.push('include[]=term');
|
|
17
|
+
queryParams.push('include[]=course_progress');
|
|
18
|
+
queryParams.push('include[]=total_students');
|
|
19
|
+
queryParams.push('include[]=favorites');
|
|
20
|
+
|
|
21
|
+
console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
|
|
22
|
+
console.log(chalk.cyan.bold('Loading courses, please wait...'));
|
|
23
|
+
const courses = await makeCanvasRequest('get', 'courses', queryParams);
|
|
24
|
+
if (!courses || courses.length === 0) {
|
|
25
|
+
console.log(chalk.red('Error: No courses found.'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
let filteredCourses = courses;
|
|
29
|
+
if (!options.all) {
|
|
30
|
+
filteredCourses = courses.filter(course => course.is_favorite);
|
|
31
|
+
if (filteredCourses.length === 0) {
|
|
32
|
+
console.log(chalk.red('Error: No starred courses found. Use -a to see all courses.'));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const courseLabel = options.all ? 'enrolled course(s)' : 'starred course(s)';
|
|
37
|
+
console.log(chalk.green(`Success: Found ${filteredCourses.length} ${courseLabel}.`));
|
|
38
|
+
console.log(chalk.cyan('-'.repeat(60)));
|
|
39
|
+
// Column headers
|
|
40
|
+
console.log(
|
|
41
|
+
pad(chalk.bold('No.'), 5) +
|
|
42
|
+
pad(chalk.bold('Course Name'), 35) +
|
|
43
|
+
pad(chalk.bold('ID'), 10) +
|
|
44
|
+
pad(chalk.bold('Code'), 12) +
|
|
45
|
+
(options.verbose ? pad(chalk.bold('Term'), 15) + pad(chalk.bold('Students'), 10) + pad(chalk.bold('Start'), 12) + pad(chalk.bold('End'), 12) + pad(chalk.bold('State'), 12) + pad(chalk.bold('Progress'), 18) : '')
|
|
46
|
+
);
|
|
47
|
+
console.log(chalk.cyan('-'.repeat(60)));
|
|
48
|
+
filteredCourses.forEach((course, index) => {
|
|
49
|
+
let line = pad(chalk.white((index + 1) + '.'), 5) +
|
|
50
|
+
pad(course.name, 35) +
|
|
51
|
+
pad(String(course.id), 10) +
|
|
52
|
+
pad(course.course_code || 'N/A', 12);
|
|
53
|
+
if (options.verbose) {
|
|
54
|
+
line += pad(course.term?.name || 'N/A', 15) +
|
|
55
|
+
pad(String(course.total_students || 'N/A'), 10) +
|
|
56
|
+
pad(course.start_at ? new Date(course.start_at).toLocaleDateString() : 'N/A', 12) +
|
|
57
|
+
pad(course.end_at ? new Date(course.end_at).toLocaleDateString() : 'N/A', 12) +
|
|
58
|
+
pad(course.workflow_state, 12) +
|
|
59
|
+
pad(course.course_progress ? `${course.course_progress.requirement_completed_count || 0}/${course.course_progress.requirement_count || 0}` : 'N/A', 18);
|
|
60
|
+
}
|
|
61
|
+
console.log(line);
|
|
62
|
+
});
|
|
63
|
+
console.log(chalk.cyan('-'.repeat(60)));
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error(chalk.red('Error fetching courses:'), error.message);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
}
|
package/commands/profile.js
CHANGED
|
@@ -1,34 +1,35 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Profile command
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
console.log(
|
|
14
|
-
console.log(
|
|
15
|
-
console.log(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
console.log(
|
|
23
|
-
console.log(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Profile command
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { makeCanvasRequest } from '../lib/api-client.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
|
|
8
|
+
export async function showProfile(options) {
|
|
9
|
+
try {
|
|
10
|
+
console.log(chalk.cyan.bold('Loading profile, please wait...'));
|
|
11
|
+
const user = await makeCanvasRequest('get', 'users/self', ['include[]=email', 'include[]=locale']);
|
|
12
|
+
|
|
13
|
+
console.log(chalk.cyan.bold('\n' + '-'.repeat(60)));
|
|
14
|
+
console.log(chalk.cyan.bold('User Profile'));
|
|
15
|
+
console.log(chalk.cyan('-'.repeat(60)));
|
|
16
|
+
console.log(chalk.white('Name: ') + user.name);
|
|
17
|
+
console.log(chalk.white('ID: ') + user.id);
|
|
18
|
+
console.log(chalk.white('Email: ') + (user.email || 'N/A'));
|
|
19
|
+
console.log(chalk.white('Login ID: ') + (user.login_id || 'N/A'));
|
|
20
|
+
|
|
21
|
+
if (options.verbose) {
|
|
22
|
+
console.log(chalk.white('Short Name: ') + (user.short_name || 'N/A'));
|
|
23
|
+
console.log(chalk.white('Sortable Name: ') + (user.sortable_name || 'N/A'));
|
|
24
|
+
console.log(chalk.white('Locale: ') + (user.locale || 'N/A'));
|
|
25
|
+
console.log(chalk.white('Time Zone: ') + (user.time_zone || 'N/A'));
|
|
26
|
+
console.log(chalk.white('Avatar URL: ') + (user.avatar_url || 'N/A'));
|
|
27
|
+
console.log(chalk.white('Created: ') + (user.created_at ? new Date(user.created_at).toLocaleString() : 'N/A'));
|
|
28
|
+
}
|
|
29
|
+
console.log(chalk.green('Success: Profile loaded.'));
|
|
30
|
+
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error(chalk.red('Error: Failed to fetch profile: ') + error.message);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
}
|