ccgather 1.3.34 → 1.3.35
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/dist/index.js +196 -48
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -80,7 +80,7 @@ async function auth(options) {
|
|
|
80
80
|
console.log(import_chalk2.default.bold("\n\u{1F510} CCgather Authentication\n"));
|
|
81
81
|
const existingToken = config.get("apiToken");
|
|
82
82
|
if (existingToken) {
|
|
83
|
-
const { overwrite } = await
|
|
83
|
+
const { overwrite } = await import_inquirer.default.prompt([
|
|
84
84
|
{
|
|
85
85
|
type: "confirm",
|
|
86
86
|
name: "overwrite",
|
|
@@ -98,7 +98,7 @@ async function auth(options) {
|
|
|
98
98
|
return;
|
|
99
99
|
}
|
|
100
100
|
const apiUrl = getApiUrl();
|
|
101
|
-
const spinner = (0,
|
|
101
|
+
const spinner = (0, import_ora.default)("Initializing authentication...").start();
|
|
102
102
|
try {
|
|
103
103
|
const response = await fetch(`${apiUrl}/cli/auth/device`, {
|
|
104
104
|
method: "POST"
|
|
@@ -120,7 +120,7 @@ async function auth(options) {
|
|
|
120
120
|
console.log(import_chalk2.default.yellow(" Could not open browser automatically."));
|
|
121
121
|
console.log(import_chalk2.default.yellow(" Please open the URL above manually.\n"));
|
|
122
122
|
}
|
|
123
|
-
const pollSpinner = (0,
|
|
123
|
+
const pollSpinner = (0, import_ora.default)("Waiting for authorization...").start();
|
|
124
124
|
const startTime = Date.now();
|
|
125
125
|
const expiresAt = startTime + deviceData.expires_in * 1e3;
|
|
126
126
|
const pollInterval = Math.max(deviceData.interval * 1e3, 5e3);
|
|
@@ -167,7 +167,7 @@ Error: ${error2 instanceof Error ? error2.message : "Unknown error"}
|
|
|
167
167
|
async function authenticateWithToken(token) {
|
|
168
168
|
const config = getConfig();
|
|
169
169
|
const apiUrl = getApiUrl();
|
|
170
|
-
const spinner = (0,
|
|
170
|
+
const spinner = (0, import_ora.default)("Verifying token...").start();
|
|
171
171
|
try {
|
|
172
172
|
const response = await fetch(`${apiUrl}/cli/verify`, {
|
|
173
173
|
method: "POST",
|
|
@@ -204,13 +204,13 @@ Error: ${error2 instanceof Error ? error2.message : "Unknown error"}
|
|
|
204
204
|
function sleep2(ms) {
|
|
205
205
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
206
206
|
}
|
|
207
|
-
var import_chalk2,
|
|
207
|
+
var import_chalk2, import_ora, import_inquirer, import_open;
|
|
208
208
|
var init_auth = __esm({
|
|
209
209
|
"src/commands/auth.ts"() {
|
|
210
210
|
"use strict";
|
|
211
211
|
import_chalk2 = __toESM(require("chalk"));
|
|
212
|
-
|
|
213
|
-
|
|
212
|
+
import_ora = __toESM(require("ora"));
|
|
213
|
+
import_inquirer = __toESM(require("inquirer"));
|
|
214
214
|
import_open = __toESM(require("open"));
|
|
215
215
|
init_config();
|
|
216
216
|
}
|
|
@@ -222,8 +222,8 @@ var import_inquirer3 = __toESM(require("inquirer"));
|
|
|
222
222
|
var import_chalk3 = __toESM(require("chalk"));
|
|
223
223
|
|
|
224
224
|
// src/commands/submit.ts
|
|
225
|
-
var
|
|
226
|
-
var
|
|
225
|
+
var import_ora2 = __toESM(require("ora"));
|
|
226
|
+
var import_inquirer2 = __toESM(require("inquirer"));
|
|
227
227
|
init_config();
|
|
228
228
|
|
|
229
229
|
// src/lib/ccgather-json.ts
|
|
@@ -301,6 +301,41 @@ function extractProjectName(filePath) {
|
|
|
301
301
|
function getClaudeProjectsDir() {
|
|
302
302
|
return path2.join(os2.homedir(), ".claude", "projects");
|
|
303
303
|
}
|
|
304
|
+
function encodePathLikeClaude(inputPath) {
|
|
305
|
+
return inputPath.split("").map((char) => {
|
|
306
|
+
const code = char.charCodeAt(0);
|
|
307
|
+
if (code >= 48 && code <= 57 || // 0-9
|
|
308
|
+
code >= 65 && code <= 90 || // A-Z
|
|
309
|
+
code >= 97 && code <= 122 || // a-z
|
|
310
|
+
char === "-" || char === "_" || char === ".") {
|
|
311
|
+
return char;
|
|
312
|
+
}
|
|
313
|
+
return "-";
|
|
314
|
+
}).join("");
|
|
315
|
+
}
|
|
316
|
+
function getCurrentProjectDir() {
|
|
317
|
+
const projectsDir = getClaudeProjectsDir();
|
|
318
|
+
if (!fs2.existsSync(projectsDir)) {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
const cwd = process.cwd();
|
|
322
|
+
const encodedCwd = encodePathLikeClaude(cwd);
|
|
323
|
+
try {
|
|
324
|
+
const entries = fs2.readdirSync(projectsDir, { withFileTypes: true });
|
|
325
|
+
for (const entry of entries) {
|
|
326
|
+
if (!entry.isDirectory()) continue;
|
|
327
|
+
if (entry.name === encodedCwd) {
|
|
328
|
+
return path2.join(projectsDir, entry.name);
|
|
329
|
+
}
|
|
330
|
+
if (entry.name.toLowerCase() === encodedCwd.toLowerCase()) {
|
|
331
|
+
return path2.join(projectsDir, entry.name);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
} catch {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
304
339
|
function findJsonlFiles(dir) {
|
|
305
340
|
const files = [];
|
|
306
341
|
try {
|
|
@@ -339,8 +374,8 @@ function estimateCost(model, inputTokens, outputTokens, cacheWriteTokens = 0, ca
|
|
|
339
374
|
return Math.round((inputCost + outputCost + cacheWriteCost + cacheReadCost) * 100) / 100;
|
|
340
375
|
}
|
|
341
376
|
function scanUsageData(options = {}) {
|
|
342
|
-
const
|
|
343
|
-
if (!
|
|
377
|
+
const currentProjectDir = getCurrentProjectDir();
|
|
378
|
+
if (!currentProjectDir) {
|
|
344
379
|
return null;
|
|
345
380
|
}
|
|
346
381
|
const days = options.days ?? 30;
|
|
@@ -363,7 +398,7 @@ function scanUsageData(options = {}) {
|
|
|
363
398
|
const dailyData = {};
|
|
364
399
|
let firstTimestamp = null;
|
|
365
400
|
let lastTimestamp = null;
|
|
366
|
-
const jsonlFiles = findJsonlFiles(
|
|
401
|
+
const jsonlFiles = findJsonlFiles(currentProjectDir);
|
|
367
402
|
sessionsCount = jsonlFiles.length;
|
|
368
403
|
const { onProgress } = options;
|
|
369
404
|
for (let i = 0; i < jsonlFiles.length; i++) {
|
|
@@ -498,16 +533,23 @@ function scanUsageData(options = {}) {
|
|
|
498
533
|
};
|
|
499
534
|
}
|
|
500
535
|
function getSessionFileCount() {
|
|
501
|
-
const
|
|
502
|
-
if (!
|
|
536
|
+
const currentProjectDir = getCurrentProjectDir();
|
|
537
|
+
if (!currentProjectDir) {
|
|
503
538
|
return 0;
|
|
504
539
|
}
|
|
505
|
-
return findJsonlFiles(
|
|
540
|
+
return findJsonlFiles(currentProjectDir).length;
|
|
541
|
+
}
|
|
542
|
+
function hasProjectSessions() {
|
|
543
|
+
return getCurrentProjectDir() !== null;
|
|
544
|
+
}
|
|
545
|
+
function getCurrentProjectName() {
|
|
546
|
+
const cwd = process.cwd();
|
|
547
|
+
return path2.basename(cwd);
|
|
506
548
|
}
|
|
507
549
|
|
|
508
550
|
// src/lib/ui.ts
|
|
509
551
|
var import_chalk = __toESM(require("chalk"));
|
|
510
|
-
var VERSION = true ? "1.3.
|
|
552
|
+
var VERSION = true ? "1.3.35" : "0.0.0";
|
|
511
553
|
var colors = {
|
|
512
554
|
primary: import_chalk.default.hex("#DA7756"),
|
|
513
555
|
// Claude coral
|
|
@@ -663,13 +705,15 @@ function getCCplanBadge(ccplan) {
|
|
|
663
705
|
}
|
|
664
706
|
var LEVELS = [
|
|
665
707
|
{ min: 0, level: 1, name: "Novice", icon: "\u{1F331}", color: colors.dim },
|
|
666
|
-
{ min:
|
|
667
|
-
{ min:
|
|
668
|
-
{ min:
|
|
669
|
-
{ min:
|
|
670
|
-
{ min:
|
|
671
|
-
{ min:
|
|
672
|
-
{ min:
|
|
708
|
+
{ min: 5e7, level: 2, name: "Apprentice", icon: "\u{1F4DA}", color: colors.muted },
|
|
709
|
+
{ min: 2e8, level: 3, name: "Journeyman", icon: "\u26A1", color: colors.cyan },
|
|
710
|
+
{ min: 5e8, level: 4, name: "Expert", icon: "\u{1F48E}", color: colors.pro },
|
|
711
|
+
{ min: 1e9, level: 5, name: "Master", icon: "\u{1F525}", color: colors.warning },
|
|
712
|
+
{ min: 3e9, level: 6, name: "Grandmaster", icon: "\u{1F451}", color: colors.max },
|
|
713
|
+
{ min: 1e10, level: 7, name: "Legend", icon: "\u{1F31F}", color: colors.primary },
|
|
714
|
+
{ min: 3e10, level: 8, name: "Mythic", icon: "\u{1F3C6}", color: colors.secondary },
|
|
715
|
+
{ min: 5e10, level: 9, name: "Immortal", icon: "\u{1F4AB}", color: colors.team },
|
|
716
|
+
{ min: 1e11, level: 10, name: "Transcendent", icon: "\u{1F30C}", color: colors.white }
|
|
673
717
|
];
|
|
674
718
|
function getLevelInfo(tokens) {
|
|
675
719
|
for (let i = LEVELS.length - 1; i >= 0; i--) {
|
|
@@ -768,6 +812,48 @@ async function printAnimatedHeader() {
|
|
|
768
812
|
}
|
|
769
813
|
console.log();
|
|
770
814
|
}
|
|
815
|
+
async function slotMachineRank(finalRank, label, medal, iterations = 12) {
|
|
816
|
+
const maxRank = Math.max(finalRank * 3, 100);
|
|
817
|
+
for (let i = 0; i < iterations; i++) {
|
|
818
|
+
const fakeRank = Math.floor(Math.random() * maxRank) + 1;
|
|
819
|
+
const speed = Math.min(30 + i * 15, 150);
|
|
820
|
+
process.stdout.write(
|
|
821
|
+
`\r ${medal} ${colors.muted(label)} ${colors.dim(`#${fakeRank}`)} `
|
|
822
|
+
);
|
|
823
|
+
await sleep(speed);
|
|
824
|
+
}
|
|
825
|
+
process.stdout.write(
|
|
826
|
+
`\r ${medal} ${colors.muted(label)} ${colors.primary.bold(`#${finalRank}`)}
|
|
827
|
+
`
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
async function animatedProgressBar(targetPercent, barWidth = 20, stepDelay = 25) {
|
|
831
|
+
const steps = Math.min(targetPercent, 20);
|
|
832
|
+
const stepSize = targetPercent / steps;
|
|
833
|
+
for (let i = 0; i <= steps; i++) {
|
|
834
|
+
const currentPercent = Math.round(i * stepSize);
|
|
835
|
+
const filled = Math.round(currentPercent / 100 * barWidth);
|
|
836
|
+
const empty = barWidth - filled;
|
|
837
|
+
const bar = colors.primary("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty));
|
|
838
|
+
process.stdout.write(`\r [${bar}] ${colors.white(`${currentPercent}%`)} `);
|
|
839
|
+
await sleep(stepDelay);
|
|
840
|
+
}
|
|
841
|
+
const finalFilled = Math.round(targetPercent / 100 * barWidth);
|
|
842
|
+
const finalEmpty = barWidth - finalFilled;
|
|
843
|
+
return colors.primary("\u2588".repeat(finalFilled)) + colors.dim("\u2591".repeat(finalEmpty));
|
|
844
|
+
}
|
|
845
|
+
async function suspenseDots(message, durationMs = 600) {
|
|
846
|
+
const frames = ["", ".", "..", "..."];
|
|
847
|
+
const frameDelay = 100;
|
|
848
|
+
const iterations = Math.ceil(durationMs / (frames.length * frameDelay));
|
|
849
|
+
for (let i = 0; i < iterations; i++) {
|
|
850
|
+
for (const frame of frames) {
|
|
851
|
+
process.stdout.write(`\r ${colors.muted(message)}${colors.primary(frame)} `);
|
|
852
|
+
await sleep(frameDelay);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
856
|
+
}
|
|
771
857
|
async function printAnimatedWelcomeBox(user) {
|
|
772
858
|
const lines = [];
|
|
773
859
|
const welcomeLine = `\u{1F44B} ${colors.white.bold(`Welcome back, ${user.username}!`)}`;
|
|
@@ -812,6 +898,8 @@ function ccgatherToUsageData(data) {
|
|
|
812
898
|
cacheReadTokens: data.usage.cacheReadTokens,
|
|
813
899
|
cacheWriteTokens: data.usage.cacheWriteTokens,
|
|
814
900
|
daysTracked: data.stats.daysTracked,
|
|
901
|
+
firstUsed: data.stats.firstUsed,
|
|
902
|
+
lastUsed: data.stats.lastUsed,
|
|
815
903
|
ccplan: data.account?.ccplan || null,
|
|
816
904
|
rateLimitTier: data.account?.rateLimitTier || null,
|
|
817
905
|
dailyUsage: data.dailyUsage || []
|
|
@@ -847,6 +935,13 @@ async function submitToServer(data) {
|
|
|
847
935
|
});
|
|
848
936
|
if (!response.ok) {
|
|
849
937
|
const errorData = await response.json().catch(() => ({}));
|
|
938
|
+
if (response.status === 429 && errorData.retryAfterMinutes) {
|
|
939
|
+
return {
|
|
940
|
+
success: false,
|
|
941
|
+
error: errorData.error || "Rate limit exceeded",
|
|
942
|
+
retryAfterMinutes: errorData.retryAfterMinutes
|
|
943
|
+
};
|
|
944
|
+
}
|
|
850
945
|
return { success: false, error: errorData.error || `HTTP ${response.status}` };
|
|
851
946
|
}
|
|
852
947
|
const result = await response.json();
|
|
@@ -874,21 +969,30 @@ function formatBadgeDate(dateStr) {
|
|
|
874
969
|
if (!dateStr) return (/* @__PURE__ */ new Date()).toISOString().split("T")[0].replace(/-/g, ".");
|
|
875
970
|
return dateStr.split("T")[0].replace(/-/g, ".");
|
|
876
971
|
}
|
|
877
|
-
function displayNewBadges(badges) {
|
|
972
|
+
async function displayNewBadges(badges) {
|
|
878
973
|
if (badges.length === 0) return;
|
|
879
974
|
console.log();
|
|
880
|
-
|
|
975
|
+
await suspenseDots("Checking achievements", 800);
|
|
976
|
+
for (let i = 0; i < badges.length; i++) {
|
|
977
|
+
const badge = badges[i];
|
|
881
978
|
const rarityColor = getRarityColor(badge.rarity);
|
|
882
979
|
const rarityLabel = badge.rarity.toUpperCase();
|
|
980
|
+
if (i > 0) {
|
|
981
|
+
await sleep(300);
|
|
982
|
+
}
|
|
883
983
|
console.log(
|
|
884
|
-
` ${badge.icon} ${colors.white.bold(badge.name)} ${rarityColor(`[${rarityLabel}]`)}`
|
|
984
|
+
` \u2728 ${badge.icon} ${colors.white.bold(badge.name)} ${rarityColor(`[${rarityLabel}]`)}`
|
|
885
985
|
);
|
|
986
|
+
await sleep(100);
|
|
886
987
|
console.log(` ${colors.muted(badge.description)}`);
|
|
988
|
+
await sleep(80);
|
|
887
989
|
if (badge.praise) {
|
|
888
990
|
console.log(` ${colors.cyan(`"${badge.praise}"`)}`);
|
|
991
|
+
await sleep(80);
|
|
889
992
|
}
|
|
890
993
|
if (badge.category === "rank") {
|
|
891
994
|
console.log(` ${colors.dim(`\u{1F4C5} Achieved: ${formatBadgeDate(badge.earnedAt)}`)}`);
|
|
995
|
+
await sleep(80);
|
|
892
996
|
}
|
|
893
997
|
}
|
|
894
998
|
}
|
|
@@ -905,12 +1009,25 @@ async function submit(options) {
|
|
|
905
1009
|
console.log(`
|
|
906
1010
|
${colors.muted("Logged in as:")} ${colors.white(username)}`);
|
|
907
1011
|
}
|
|
1012
|
+
const projectName = getCurrentProjectName();
|
|
1013
|
+
if (!hasProjectSessions()) {
|
|
1014
|
+
console.log(`
|
|
1015
|
+
${error("No Claude Code sessions found for this project.")}`);
|
|
1016
|
+
console.log(` ${colors.muted("Project:")} ${colors.white(projectName)}`);
|
|
1017
|
+
console.log();
|
|
1018
|
+
console.log(` ${colors.muted("Make sure you:")}`);
|
|
1019
|
+
console.log(` ${colors.muted(" 1. Run this command from a project directory")}`);
|
|
1020
|
+
console.log(` ${colors.muted(" 2. Have used Claude Code in this project at least once")}`);
|
|
1021
|
+
console.log();
|
|
1022
|
+
process.exit(1);
|
|
1023
|
+
}
|
|
908
1024
|
let usageData = null;
|
|
909
1025
|
const totalFiles = getSessionFileCount();
|
|
1026
|
+
console.log(`
|
|
1027
|
+
${colors.muted("Project:")} ${colors.white(projectName)}`);
|
|
910
1028
|
if (totalFiles > 0) {
|
|
911
1029
|
console.log(
|
|
912
|
-
`
|
|
913
|
-
${colors.muted("Scanning")} ${colors.white(totalFiles.toString())} ${colors.muted("sessions...")}`
|
|
1030
|
+
` ${colors.muted("Scanning")} ${colors.white(totalFiles.toString())} ${colors.muted("sessions...")}`
|
|
914
1031
|
);
|
|
915
1032
|
const scannedData = scanUsageData({
|
|
916
1033
|
onProgress: (current, total) => {
|
|
@@ -938,10 +1055,20 @@ async function submit(options) {
|
|
|
938
1055
|
process.exit(1);
|
|
939
1056
|
}
|
|
940
1057
|
console.log();
|
|
1058
|
+
const formatDate = (dateStr) => {
|
|
1059
|
+
if (!dateStr) return "------";
|
|
1060
|
+
const d = new Date(dateStr);
|
|
1061
|
+
const yy = String(d.getFullYear()).slice(2);
|
|
1062
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
1063
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
1064
|
+
return `${yy}${mm}${dd}`;
|
|
1065
|
+
};
|
|
1066
|
+
const dateRange = usageData.firstUsed && usageData.lastUsed ? `${formatDate(usageData.firstUsed)} ~ ${formatDate(usageData.lastUsed)}` : "";
|
|
1067
|
+
const daysTrackedDisplay = dateRange ? `${usageData.daysTracked} days ${colors.dim(`(${dateRange})`)}` : usageData.daysTracked.toString();
|
|
941
1068
|
const summaryLines = [
|
|
942
1069
|
`${colors.muted("Total Cost")} ${colors.success(formatCost(usageData.totalCost))}`,
|
|
943
1070
|
`${colors.muted("Total Tokens")} ${colors.primary(formatNumber(usageData.totalTokens))}`,
|
|
944
|
-
`${colors.muted("
|
|
1071
|
+
`${colors.muted("Period")} ${colors.warning(daysTrackedDisplay)}`
|
|
945
1072
|
];
|
|
946
1073
|
if (usageData.ccplan) {
|
|
947
1074
|
summaryLines.push(
|
|
@@ -950,7 +1077,10 @@ async function submit(options) {
|
|
|
950
1077
|
}
|
|
951
1078
|
console.log(createBox(summaryLines));
|
|
952
1079
|
console.log();
|
|
953
|
-
|
|
1080
|
+
if (usageData.dailyUsage.length > 0) {
|
|
1081
|
+
console.log(` ${colors.dim(`Daily records: ${usageData.dailyUsage.length} days`)}`);
|
|
1082
|
+
}
|
|
1083
|
+
const { confirmSubmit } = await import_inquirer2.default.prompt([
|
|
954
1084
|
{
|
|
955
1085
|
type: "confirm",
|
|
956
1086
|
name: "confirmSubmit",
|
|
@@ -964,7 +1094,7 @@ async function submit(options) {
|
|
|
964
1094
|
`);
|
|
965
1095
|
return;
|
|
966
1096
|
}
|
|
967
|
-
const submitSpinner = (0,
|
|
1097
|
+
const submitSpinner = (0, import_ora2.default)({
|
|
968
1098
|
text: "Submitting to CCgather...",
|
|
969
1099
|
color: "cyan"
|
|
970
1100
|
}).start();
|
|
@@ -983,15 +1113,11 @@ async function submit(options) {
|
|
|
983
1113
|
console.log();
|
|
984
1114
|
if (result.rank) {
|
|
985
1115
|
const medal = result.rank === 1 ? "\u{1F947}" : result.rank === 2 ? "\u{1F948}" : result.rank === 3 ? "\u{1F949}" : result.rank <= 10 ? "\u{1F3C5}" : "\u{1F30D}";
|
|
986
|
-
|
|
987
|
-
` ${medal} ${colors.muted("Global:")} ${colors.primary.bold(`#${result.rank}`)}`
|
|
988
|
-
);
|
|
1116
|
+
await slotMachineRank(result.rank, "Global:", medal);
|
|
989
1117
|
}
|
|
990
1118
|
if (result.countryRank) {
|
|
991
1119
|
const countryMedal = result.countryRank === 1 ? "\u{1F947}" : result.countryRank <= 3 ? "\u{1F3C6}" : "\u{1F3E0}";
|
|
992
|
-
|
|
993
|
-
` ${countryMedal} ${colors.muted("Country:")} ${colors.primary.bold(`#${result.countryRank}`)}`
|
|
994
|
-
);
|
|
1120
|
+
await slotMachineRank(result.countryRank, "Country:", countryMedal, 10);
|
|
995
1121
|
}
|
|
996
1122
|
}
|
|
997
1123
|
console.log();
|
|
@@ -999,25 +1125,25 @@ async function submit(options) {
|
|
|
999
1125
|
console.log();
|
|
1000
1126
|
const levelProgress = getLevelProgress(usageData.totalTokens);
|
|
1001
1127
|
const currentLevel = levelProgress.current;
|
|
1128
|
+
await sleep(200);
|
|
1002
1129
|
console.log(
|
|
1003
1130
|
` ${currentLevel.icon} ${currentLevel.color(`Level ${currentLevel.level}`)} ${colors.muted("\u2022")} ${colors.white(currentLevel.name)}`
|
|
1004
1131
|
);
|
|
1005
1132
|
if (!levelProgress.isMaxLevel && levelProgress.next) {
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
const bar = colors.primary("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty));
|
|
1010
|
-
console.log(` [${bar}] ${colors.white(`${levelProgress.progress}%`)}`);
|
|
1133
|
+
await animatedProgressBar(levelProgress.progress, 20, 30);
|
|
1134
|
+
console.log();
|
|
1135
|
+
await sleep(150);
|
|
1011
1136
|
console.log(
|
|
1012
1137
|
` ${colors.dim("\u2192")} ${levelProgress.next.icon} ${colors.white(levelProgress.next.name)} ${colors.muted("in")} ${colors.primary(formatNumber(levelProgress.tokensToNext))}`
|
|
1013
1138
|
);
|
|
1014
1139
|
} else {
|
|
1140
|
+
await sleep(300);
|
|
1015
1141
|
console.log(` ${colors.max("\u2605")} ${colors.max("MAX LEVEL ACHIEVED!")}`);
|
|
1016
1142
|
}
|
|
1017
1143
|
if (result.newBadges && result.newBadges.length > 0) {
|
|
1018
1144
|
console.log();
|
|
1019
1145
|
console.log(sectionHeader("\u{1F389}", "New Badge Unlocked"));
|
|
1020
|
-
displayNewBadges(result.newBadges);
|
|
1146
|
+
await displayNewBadges(result.newBadges);
|
|
1021
1147
|
}
|
|
1022
1148
|
console.log();
|
|
1023
1149
|
const leaderboardUrl = `https://ccgather.com/leaderboard?u=${username}`;
|
|
@@ -1028,9 +1154,29 @@ async function submit(options) {
|
|
|
1028
1154
|
submitSpinner.fail(colors.error("Failed to submit"));
|
|
1029
1155
|
console.log(`
|
|
1030
1156
|
${error(result.error || "Unknown error")}`);
|
|
1031
|
-
if (result.
|
|
1157
|
+
if (result.retryAfterMinutes) {
|
|
1158
|
+
console.log();
|
|
1159
|
+
console.log(
|
|
1160
|
+
` ${colors.warning("\u23F3")} ${colors.muted("Try again in")} ${colors.white(`${result.retryAfterMinutes} minute${result.retryAfterMinutes !== 1 ? "s" : ""}`)}`
|
|
1161
|
+
);
|
|
1162
|
+
} else if (result.error?.includes("auth") || result.error?.includes("token")) {
|
|
1032
1163
|
console.log();
|
|
1033
|
-
|
|
1164
|
+
const { startAuth } = await import_inquirer2.default.prompt([
|
|
1165
|
+
{
|
|
1166
|
+
type: "confirm",
|
|
1167
|
+
name: "startAuth",
|
|
1168
|
+
message: "Would you like to authenticate now?",
|
|
1169
|
+
default: true
|
|
1170
|
+
}
|
|
1171
|
+
]);
|
|
1172
|
+
if (startAuth) {
|
|
1173
|
+
const { auth: auth2 } = await Promise.resolve().then(() => (init_auth(), auth_exports));
|
|
1174
|
+
await auth2({});
|
|
1175
|
+
console.log();
|
|
1176
|
+
console.log(` ${colors.muted("Please run")} ${colors.primary("npx ccgather")} ${colors.muted("again to submit.")}`);
|
|
1177
|
+
console.log();
|
|
1178
|
+
process.exit(0);
|
|
1179
|
+
}
|
|
1034
1180
|
}
|
|
1035
1181
|
console.log();
|
|
1036
1182
|
process.exit(1);
|
|
@@ -1038,7 +1184,7 @@ async function submit(options) {
|
|
|
1038
1184
|
}
|
|
1039
1185
|
|
|
1040
1186
|
// src/commands/status.ts
|
|
1041
|
-
var
|
|
1187
|
+
var import_ora3 = __toESM(require("ora"));
|
|
1042
1188
|
init_config();
|
|
1043
1189
|
|
|
1044
1190
|
// src/lib/api.ts
|
|
@@ -1080,7 +1226,7 @@ async function status(options) {
|
|
|
1080
1226
|
${error("Not authenticated.")}`);
|
|
1081
1227
|
process.exit(1);
|
|
1082
1228
|
}
|
|
1083
|
-
const spinner = (0,
|
|
1229
|
+
const spinner = (0, import_ora3.default)({
|
|
1084
1230
|
text: "Fetching your stats...",
|
|
1085
1231
|
color: "cyan"
|
|
1086
1232
|
}).start();
|
|
@@ -1157,7 +1303,9 @@ async function checkLatestVersion() {
|
|
|
1157
1303
|
}
|
|
1158
1304
|
async function promptForUpdate(latestVersion) {
|
|
1159
1305
|
console.log();
|
|
1160
|
-
console.log(
|
|
1306
|
+
console.log(
|
|
1307
|
+
` ${import_chalk3.default.yellow("\u26A0")} ${import_chalk3.default.yellow("New version")} ${import_chalk3.default.green(latestVersion)} ${import_chalk3.default.yellow("available!")} ${import_chalk3.default.dim(`(current: ${VERSION})`)}`
|
|
1308
|
+
);
|
|
1161
1309
|
console.log();
|
|
1162
1310
|
const { shouldUpdate } = await import_inquirer3.default.prompt([
|
|
1163
1311
|
{
|