tronclass-auto 1.2.5 → 1.3.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/package.json +1 -1
- package/src/index.js +31 -11
- package/src/tui.js +2 -1
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -26,7 +26,20 @@ async function getUncompleted(page, courseId) {
|
|
|
26
26
|
const a = actScope.activity;
|
|
27
27
|
let completeness = '';
|
|
28
28
|
try { completeness = scope.getActivityCompleteness(a); } catch (e) {}
|
|
29
|
-
if (completeness
|
|
29
|
+
if (completeness === 'full') return;
|
|
30
|
+
|
|
31
|
+
let isUpcoming = false;
|
|
32
|
+
let isExpired = false;
|
|
33
|
+
try { isUpcoming = scope.activityUpcoming(a); } catch (e) {}
|
|
34
|
+
try { isExpired = scope.activityExpired(a); } catch (e) {}
|
|
35
|
+
if (isUpcoming) return;
|
|
36
|
+
|
|
37
|
+
let timeRange = '';
|
|
38
|
+
try {
|
|
39
|
+
const txt = actEl.textContent || '';
|
|
40
|
+
const tm = txt.match(/時間:\s*(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2})\s*~\s*(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2})/);
|
|
41
|
+
if (tm) timeRange = tm[0];
|
|
42
|
+
} catch (e) {}
|
|
30
43
|
let durationSec = 0;
|
|
31
44
|
try {
|
|
32
45
|
const durText = actEl.querySelector('.activity-attribute');
|
|
@@ -48,9 +61,9 @@ async function getUncompleted(page, courseId) {
|
|
|
48
61
|
id: a.id,
|
|
49
62
|
title: (a.title || '').substring(0, 60),
|
|
50
63
|
type: a.type || '',
|
|
51
|
-
durationSec
|
|
64
|
+
durationSec,
|
|
65
|
+
timeRange
|
|
52
66
|
});
|
|
53
|
-
}
|
|
54
67
|
});
|
|
55
68
|
return result;
|
|
56
69
|
});
|
|
@@ -161,23 +174,30 @@ async function showStatus() {
|
|
|
161
174
|
try {
|
|
162
175
|
const uncompleted = await getUncompleted(page, courseId);
|
|
163
176
|
const videos = uncompleted.filter(u => u.type === 'online_video');
|
|
177
|
+
const remaining = videos.filter(v => !isDone(courseId, v.id));
|
|
164
178
|
const exams = uncompleted.filter(u => u.type === 'exam').length;
|
|
165
|
-
const other = uncompleted.length - videos.length - exams;
|
|
166
179
|
totalVideos += videos.length;
|
|
167
|
-
totalRemaining +=
|
|
180
|
+
totalRemaining += remaining.length;
|
|
168
181
|
totalExams += exams;
|
|
169
182
|
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
183
|
+
const pct = videos.length > 0 ? Math.floor(((videos.length - remaining.length) / videos.length) * 100) : 100;
|
|
184
|
+
const filled = Math.floor(50 * pct / 100);
|
|
185
|
+
const empty = 50 - filled;
|
|
186
|
+
const bar = pct === 100
|
|
187
|
+
? chalk.green('█'.repeat(50))
|
|
188
|
+
: chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));
|
|
189
|
+
|
|
190
|
+
const doneCount = videos.length - remaining.length;
|
|
191
|
+
console.log(chalk.cyan('│') + ` [${courseId}] ${doneCount}/${videos.length} videos ${exams} exams`.padEnd(50) + chalk.cyan('│'));
|
|
192
|
+
console.log(chalk.cyan('│') + ` ${bar} ${pct}%`.padEnd(52) + chalk.cyan('│'));
|
|
173
193
|
} catch (e) {
|
|
174
194
|
console.log(chalk.cyan('│') + ` [${courseId}] ERROR`.padEnd(50) + chalk.cyan('│'));
|
|
175
195
|
}
|
|
176
196
|
}
|
|
177
197
|
|
|
178
198
|
console.log(chalk.cyan('├' + '─'.repeat(48) + '┤'));
|
|
179
|
-
console.log(chalk.cyan('│') + `
|
|
180
|
-
console.log(chalk.cyan('│') + `
|
|
199
|
+
console.log(chalk.cyan('│') + ` 剩餘: ${totalRemaining} videos | 考試: ${totalExams}`.padEnd(50) + chalk.cyan('│'));
|
|
200
|
+
console.log(chalk.cyan('│') + ` 預估: ${formatTime(totalRemaining * 120)}`.padEnd(50) + chalk.cyan('│'));
|
|
181
201
|
console.log(chalk.cyan('└' + '─'.repeat(48) + '┘'));
|
|
182
202
|
console.log('');
|
|
183
203
|
|
|
@@ -199,10 +219,10 @@ async function launchBrowser(headless) {
|
|
|
199
219
|
headless,
|
|
200
220
|
slowMo: 50,
|
|
201
221
|
args: [
|
|
222
|
+
'--disable-accelerated-video-decode',
|
|
202
223
|
'--disable-background-timer-throttling',
|
|
203
224
|
'--disable-backgrounding-occluded-windows',
|
|
204
225
|
'--disable-renderer-backgrounding',
|
|
205
|
-
'--disable-features=MediaFoundationVideoCapture,HardwareMediaKeyHandling',
|
|
206
226
|
]
|
|
207
227
|
};
|
|
208
228
|
if (exePath) launchOpts.executablePath = exePath;
|
package/src/tui.js
CHANGED
|
@@ -2,6 +2,7 @@ const inquirer = require('inquirer');
|
|
|
2
2
|
const chalk = require('chalk');
|
|
3
3
|
const { loadConfig, saveConfig, BASE_URL } = require('./config');
|
|
4
4
|
const { loadCookies } = require('./auth');
|
|
5
|
+
const pkg = require('../package.json');
|
|
5
6
|
|
|
6
7
|
function box(lines, width = 52) {
|
|
7
8
|
const top = '╔' + '═'.repeat(width - 2) + '╗';
|
|
@@ -25,7 +26,7 @@ async function mainMenu() {
|
|
|
25
26
|
const config = loadConfig();
|
|
26
27
|
|
|
27
28
|
box([
|
|
28
|
-
chalk.bold.white(
|
|
29
|
+
chalk.bold.white(`tronclass-auto v${pkg.version}`),
|
|
29
30
|
chalk.gray('自動觀看 eclass/TronClass 影片'),
|
|
30
31
|
'',
|
|
31
32
|
`課程: ${chalk.cyan(config.courses.length + ' 個')} | Cookie: ${chalk.green('✓')} | 倍速: ${chalk.yellow(config.playbackRate || 2)}x`,
|