cc98-cli 0.3.0 → 0.4.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.
Files changed (116) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/dist/api/client.d.ts +14 -0
  3. package/dist/api/client.d.ts.map +1 -1
  4. package/dist/api/client.js +83 -8
  5. package/dist/api/client.js.map +1 -1
  6. package/dist/api/types.d.ts +13 -0
  7. package/dist/api/types.d.ts.map +1 -1
  8. package/dist/api/webvpn.d.ts +68 -0
  9. package/dist/api/webvpn.d.ts.map +1 -0
  10. package/dist/api/webvpn.js +311 -0
  11. package/dist/api/webvpn.js.map +1 -0
  12. package/dist/cli/commands/board.js +1 -1
  13. package/dist/cli/commands/board.js.map +1 -1
  14. package/dist/cli/commands/forum.js +1 -1
  15. package/dist/cli/commands/forum.js.map +1 -1
  16. package/dist/cli/commands/login.js +1 -1
  17. package/dist/cli/commands/login.js.map +1 -1
  18. package/dist/cli/commands/logout.js +2 -2
  19. package/dist/cli/commands/logout.js.map +1 -1
  20. package/dist/cli/commands/me.js +1 -1
  21. package/dist/cli/commands/me.js.map +1 -1
  22. package/dist/cli/commands/message.js +1 -1
  23. package/dist/cli/commands/message.js.map +1 -1
  24. package/dist/cli/commands/notice.js +1 -1
  25. package/dist/cli/commands/notice.js.map +1 -1
  26. package/dist/cli/commands/post.js +1 -1
  27. package/dist/cli/commands/post.js.map +1 -1
  28. package/dist/cli/commands/search.js +1 -1
  29. package/dist/cli/commands/search.js.map +1 -1
  30. package/dist/cli/commands/topic.js +1 -1
  31. package/dist/cli/commands/topic.js.map +1 -1
  32. package/dist/cli/commands/user.js +1 -1
  33. package/dist/cli/commands/user.js.map +1 -1
  34. package/dist/cli/commands/vpn.d.ts +2 -0
  35. package/dist/cli/commands/vpn.d.ts.map +1 -0
  36. package/dist/cli/commands/vpn.js +200 -0
  37. package/dist/cli/commands/vpn.js.map +1 -0
  38. package/dist/cli/context.d.ts +2 -2
  39. package/dist/cli/context.d.ts.map +1 -1
  40. package/dist/cli/context.js +20 -2
  41. package/dist/cli/context.js.map +1 -1
  42. package/dist/cli/router.d.ts.map +1 -1
  43. package/dist/cli/router.js +5 -1
  44. package/dist/cli/router.js.map +1 -1
  45. package/dist/main.js +0 -0
  46. package/dist/storage/image-cache.d.ts +32 -0
  47. package/dist/storage/image-cache.d.ts.map +1 -0
  48. package/dist/storage/image-cache.js +90 -0
  49. package/dist/storage/image-cache.js.map +1 -0
  50. package/dist/storage/vpn-store.d.ts +39 -0
  51. package/dist/storage/vpn-store.d.ts.map +1 -0
  52. package/dist/storage/vpn-store.js +94 -0
  53. package/dist/storage/vpn-store.js.map +1 -0
  54. package/dist/tui/app.d.ts.map +1 -1
  55. package/dist/tui/app.js +13 -1
  56. package/dist/tui/app.js.map +1 -1
  57. package/dist/tui/components/layout.d.ts.map +1 -1
  58. package/dist/tui/components/layout.js +41 -52
  59. package/dist/tui/components/layout.js.map +1 -1
  60. package/dist/tui/components/overview.d.ts.map +1 -1
  61. package/dist/tui/components/overview.js +18 -8
  62. package/dist/tui/components/overview.js.map +1 -1
  63. package/dist/tui/components/sidebar.d.ts.map +1 -1
  64. package/dist/tui/components/sidebar.js +0 -1
  65. package/dist/tui/components/sidebar.js.map +1 -1
  66. package/dist/tui/components/status.d.ts.map +1 -1
  67. package/dist/tui/components/status.js +12 -6
  68. package/dist/tui/components/status.js.map +1 -1
  69. package/dist/tui/controller.d.ts +5 -0
  70. package/dist/tui/controller.d.ts.map +1 -1
  71. package/dist/tui/controller.js +121 -39
  72. package/dist/tui/controller.js.map +1 -1
  73. package/dist/tui/helpers.d.ts.map +1 -1
  74. package/dist/tui/helpers.js +19 -10
  75. package/dist/tui/helpers.js.map +1 -1
  76. package/dist/tui/navigation.d.ts.map +1 -1
  77. package/dist/tui/navigation.js +0 -1
  78. package/dist/tui/navigation.js.map +1 -1
  79. package/dist/tui/renderer.js +19 -16
  80. package/dist/tui/renderer.js.map +1 -1
  81. package/dist/tui/state/store.d.ts.map +1 -1
  82. package/dist/tui/state/store.js +1 -0
  83. package/dist/tui/state/store.js.map +1 -1
  84. package/dist/tui/state/types.d.ts +5 -1
  85. package/dist/tui/state/types.d.ts.map +1 -1
  86. package/dist/tui/topic-reader.d.ts.map +1 -1
  87. package/dist/tui/topic-reader.js +16 -5
  88. package/dist/tui/topic-reader.js.map +1 -1
  89. package/dist/tui/ubb-renderer.d.ts.map +1 -1
  90. package/dist/tui/ubb-renderer.js +176 -12
  91. package/dist/tui/ubb-renderer.js.map +1 -1
  92. package/package.json +1 -1
  93. package/dist/tui/app-new.d.ts +0 -2
  94. package/dist/tui/app-new.d.ts.map +0 -1
  95. package/dist/tui/app-new.js +0 -2589
  96. package/dist/tui/app-new.js.map +0 -1
  97. package/dist/tui/app-old.d.ts +0 -2
  98. package/dist/tui/app-old.d.ts.map +0 -1
  99. package/dist/tui/app-old.js +0 -2589
  100. package/dist/tui/app-old.js.map +0 -1
  101. package/dist/tui/keymap/actions.d.ts +0 -9
  102. package/dist/tui/keymap/actions.d.ts.map +0 -1
  103. package/dist/tui/keymap/actions.js +0 -208
  104. package/dist/tui/keymap/actions.js.map +0 -1
  105. package/dist/tui/keymap/bindings.d.ts +0 -5
  106. package/dist/tui/keymap/bindings.d.ts.map +0 -1
  107. package/dist/tui/keymap/bindings.js +0 -138
  108. package/dist/tui/keymap/bindings.js.map +0 -1
  109. package/dist/tui/keymap/index.d.ts +0 -4
  110. package/dist/tui/keymap/index.d.ts.map +0 -1
  111. package/dist/tui/keymap/index.js +0 -5
  112. package/dist/tui/keymap/index.js.map +0 -1
  113. package/dist/tui/keymap/types.d.ts +0 -17
  114. package/dist/tui/keymap/types.d.ts.map +0 -1
  115. package/dist/tui/keymap/types.js +0 -3
  116. package/dist/tui/keymap/types.js.map +0 -1
@@ -0,0 +1,200 @@
1
+ import { VpnStore } from "../../storage/vpn-store.js";
2
+ import { WebVpnService } from "../../api/webvpn.js";
3
+ import { promptText, promptPassword } from "../prompt.js";
4
+ export async function vpnCommand(args) {
5
+ const [subCommand, ...rest] = args;
6
+ if (!subCommand || subCommand === "--help" || subCommand === "-h") {
7
+ printVpnHelp();
8
+ return;
9
+ }
10
+ switch (subCommand) {
11
+ case "login":
12
+ await vpnLogin(rest);
13
+ break;
14
+ case "logout":
15
+ await vpnLogout();
16
+ break;
17
+ case "status":
18
+ await vpnStatus();
19
+ break;
20
+ case "test":
21
+ await vpnTest();
22
+ break;
23
+ case "mode":
24
+ await vpnMode(rest);
25
+ break;
26
+ default:
27
+ throw new Error(`unknown vpn subcommand: ${subCommand}. Run "cc98 vpn --help" for usage.`);
28
+ }
29
+ }
30
+ async function vpnLogin(args) {
31
+ const store = new VpnStore();
32
+ const config = await store.getConfig();
33
+ // 获取用户名
34
+ let username = args[0] || config.username;
35
+ if (!username) {
36
+ username = await promptText("浙大通行证用户名: ");
37
+ if (!username) {
38
+ console.error("用户名不能为空");
39
+ return;
40
+ }
41
+ }
42
+ // 获取密码
43
+ let password = args[1];
44
+ if (!password) {
45
+ password = await promptPassword("浙大通行证密码: ");
46
+ if (!password) {
47
+ console.error("密码不能为空");
48
+ return;
49
+ }
50
+ }
51
+ console.log("正在登录 WebVPN...");
52
+ const vpn = new WebVpnService();
53
+ const result = await vpn.login(username, password);
54
+ if (result.needConfirm) {
55
+ console.log("需要确认登录(可能在其他设备已登录)");
56
+ const confirm = await promptText("是否确认登录?(y/N): ");
57
+ if (confirm.toLowerCase() === "y") {
58
+ const confirmResult = await vpn.confirmLogin();
59
+ if (confirmResult.success) {
60
+ console.log("✅ WebVPN 登录成功");
61
+ await store.saveSession(username, vpn.getCookies());
62
+ }
63
+ else {
64
+ console.error("❌ 确认登录失败:", confirmResult.message);
65
+ return;
66
+ }
67
+ }
68
+ else {
69
+ console.log("已取消登录");
70
+ return;
71
+ }
72
+ }
73
+ else if (result.success) {
74
+ console.log("✅ WebVPN 登录成功");
75
+ await store.saveSession(username, vpn.getCookies());
76
+ }
77
+ else {
78
+ console.error("❌ WebVPN 登录失败:", result.message);
79
+ return;
80
+ }
81
+ // 测试连接
82
+ console.log("\n测试 WebVPN 连接...");
83
+ vpn.enabled = true;
84
+ const testResponse = await vpn.fetch("https://api.cc98.org/config/index");
85
+ if (testResponse.ok) {
86
+ console.log("✅ WebVPN 连接正常");
87
+ }
88
+ else {
89
+ console.error("❌ WebVPN 连接失败:", testResponse.status);
90
+ }
91
+ }
92
+ async function vpnLogout() {
93
+ const store = new VpnStore();
94
+ const config = await store.getConfig();
95
+ if (!config.username) {
96
+ console.log("未配置 WebVPN");
97
+ return;
98
+ }
99
+ const vpn = new WebVpnService();
100
+ await vpn.logout();
101
+ await store.clear();
102
+ console.log("✅ 已清除 WebVPN 配置");
103
+ }
104
+ async function vpnStatus() {
105
+ const store = new VpnStore();
106
+ const config = await store.getConfig();
107
+ console.log("WebVPN 状态:");
108
+ console.log(` 模式: ${config.mode}`);
109
+ console.log(` 用户名: ${config.username || "未配置"}`);
110
+ console.log(` 会话: ${config.cookies ? "已保存" : "未登录"}`);
111
+ if (config.loggedInAt) {
112
+ console.log(` 登录时间: ${config.loggedInAt}`);
113
+ }
114
+ if (config.username) {
115
+ console.log("\n测试连接...");
116
+ const vpn = new WebVpnService(config.cookies);
117
+ const inCampus = await vpn.checkNetwork();
118
+ console.log(` 校园网: ${inCampus ? "是" : "否"}`);
119
+ if (!inCampus && config.mode !== "direct") {
120
+ console.log(" 提示: 不在校园网内,WebVPN 将自动启用");
121
+ }
122
+ }
123
+ }
124
+ async function vpnTest() {
125
+ console.log("测试 WebVPN 连接...\n");
126
+ const vpn = new WebVpnService();
127
+ // 1. 检测校园网
128
+ console.log("1. 检测校园网...");
129
+ const inCampus = await vpn.checkNetwork();
130
+ console.log(` 结果: ${inCampus ? "在校园网内" : "不在校园网内"}`);
131
+ if (inCampus) {
132
+ console.log("\n当前在校园网内,无需使用 WebVPN");
133
+ console.log("可以直接访问 CC98 API");
134
+ return;
135
+ }
136
+ // 2. 测试 WebVPN 访问
137
+ console.log("\n2. 测试 WebVPN 访问...");
138
+ vpn.enabled = true;
139
+ const store = new VpnStore();
140
+ const config = await store.getConfig();
141
+ if (config.username && config.cookies) {
142
+ console.log(` 使用账号: ${config.username}`);
143
+ vpn.loadCookies(config.cookies);
144
+ const response = await vpn.fetch("https://api.cc98.org/config/index");
145
+ console.log(` API 访问: ${response.ok ? "成功" : `失败 ${response.status}`}`);
146
+ }
147
+ else if (config.username) {
148
+ console.log(` 已配置账号: ${config.username}`);
149
+ console.log(" 未保存有效会话,请运行 'cc98 vpn login' 重新登录");
150
+ }
151
+ else {
152
+ console.log(" 未配置 WebVPN 账号");
153
+ console.log(" 请运行 'cc98 vpn login' 配置");
154
+ }
155
+ }
156
+ async function vpnMode(args) {
157
+ const store = new VpnStore();
158
+ const mode = args[0];
159
+ if (!mode) {
160
+ const config = await store.getConfig();
161
+ console.log(`当前模式: ${config.mode}`);
162
+ console.log("\n可用模式:");
163
+ console.log(" auto - 自动检测校园网,非校园网自动使用 WebVPN");
164
+ console.log(" vpn - 强制使用 WebVPN");
165
+ console.log(" direct - 强制直连(不使用 WebVPN)");
166
+ console.log("\n用法: cc98 vpn mode <mode>");
167
+ return;
168
+ }
169
+ if (!["auto", "vpn", "direct"].includes(mode)) {
170
+ console.error(`无效的模式: ${mode}`);
171
+ console.error("可用模式: auto, vpn, direct");
172
+ return;
173
+ }
174
+ await store.saveMode(mode);
175
+ console.log(`✅ 已设置模式: ${mode}`);
176
+ }
177
+ function printVpnHelp() {
178
+ console.log(`cc98 vpn - WebVPN 管理
179
+
180
+ Usage:
181
+ cc98 vpn login [username] [password] 登录 WebVPN
182
+ cc98 vpn logout 注销 WebVPN
183
+ cc98 vpn status 查看状态
184
+ cc98 vpn test 测试连接
185
+ cc98 vpn mode [auto|vpn|direct] 设置模式
186
+
187
+ Options:
188
+ -h, --help 显示帮助
189
+
190
+ 说明:
191
+ WebVPN 用于在非校园网环境下访问 CC98。
192
+ 登录需要使用浙大通行证账号密码。
193
+
194
+ 模式:
195
+ auto - 自动检测校园网,非校园网自动使用 WebVPN(默认)
196
+ vpn - 强制使用 WebVPN
197
+ direct - 强制直连(不使用 WebVPN)
198
+ `);
199
+ }
200
+ //# sourceMappingURL=vpn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vpn.js","sourceRoot":"","sources":["../../../src/cli/commands/vpn.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,8 @@ import { Cc98Client } from "../api/client.js";
2
2
  import { TokenStore } from "../storage/token-store.js";
3
3
  export declare function createCliContext(options?: {
4
4
  account?: string;
5
- }): {
5
+ }): Promise<{
6
6
  client: Cc98Client;
7
7
  tokenStore: TokenStore;
8
- };
8
+ }>;
9
9
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/cli/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAInH"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/cli/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAGvD,wBAAsB,gBAAgB,CAAC,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC,CASlI"}
@@ -1,8 +1,26 @@
1
1
  import { Cc98Client } from "../api/client.js";
2
2
  import { TokenStore } from "../storage/token-store.js";
3
- export function createCliContext(options = {}) {
3
+ import { VpnStore } from "../storage/vpn-store.js";
4
+ export async function createCliContext(options = {}) {
4
5
  const tokenStore = new TokenStore().withAccount(options.account);
5
- const client = new Cc98Client({ tokenStore });
6
+ const vpnConfig = await new VpnStore().getConfig();
7
+ const webVpn = getWebVpnOptions(vpnConfig);
8
+ const client = new Cc98Client({ tokenStore, webVpn });
9
+ if (webVpn) {
10
+ await client.initWebVpn();
11
+ }
6
12
  return { client, tokenStore };
7
13
  }
14
+ function getWebVpnOptions(config) {
15
+ if (config.mode === "direct") {
16
+ return { mode: "direct" };
17
+ }
18
+ if (config.mode === "vpn" || config.cookies) {
19
+ return {
20
+ mode: config.mode,
21
+ cookies: config.cookies,
22
+ };
23
+ }
24
+ return undefined;
25
+ }
8
26
  //# sourceMappingURL=context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/cli/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD,MAAM,UAAU,gBAAgB,CAAC,UAAgC,EAAE;IACjE,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IAC9C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/cli/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAgC,EAAE;IACvE,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,MAAM,IAAI,QAAQ,EAAE,CAAC,SAAS,EAAE,CAAC;IACnD,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC;IACtD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAkD;IAC1E,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC5B,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC5C,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/cli/router.ts"],"names":[],"mappings":"AAsCA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB1D"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/cli/router.ts"],"names":[],"mappings":"AAwCA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB1D"}
@@ -13,6 +13,7 @@ import { searchCommand } from "./commands/search.js";
13
13
  import { topicCommand } from "./commands/topic.js";
14
14
  import { updateCommand } from "./commands/update.js";
15
15
  import { userCommand } from "./commands/user.js";
16
+ import { vpnCommand } from "./commands/vpn.js";
16
17
  import { runTui } from "../tui/app.js";
17
18
  import { appName, appVersion } from "../version.js";
18
19
  const commands = {
@@ -30,7 +31,8 @@ const commands = {
30
31
  topic: topicCommand,
31
32
  tui: runTui,
32
33
  update: updateCommand,
33
- user: userCommand
34
+ user: userCommand,
35
+ vpn: vpnCommand
34
36
  };
35
37
  export async function runCli(args) {
36
38
  const accountOption = extractAccountOption(args);
@@ -82,6 +84,8 @@ Usage:
82
84
  cc98 cache stats Show cache statistics
83
85
  cc98 cache cleanup Remove expired cache entries
84
86
  cc98 cache clear Clear all cache
87
+ cc98 vpn login Login to WebVPN (non-campus network)
88
+ cc98 vpn status Show VPN status
85
89
  cc98 update Check the latest GitHub Release
86
90
 
87
91
  Options:
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/cli/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIpD,MAAM,QAAQ,GAAmC;IAC/C,OAAO,EAAE,cAAc;IACvB,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE,cAAc;IACvB,EAAE,EAAE,SAAS;IACb,MAAM,EAAE,aAAa;IACrB,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,aAAa;IACrB,KAAK,EAAE,YAAY;IACnB,GAAG,EAAE,MAAM;IACX,MAAM,EAAE,aAAa;IACrB,IAAI,EAAE,WAAW;CAClB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,MAAM,aAAa,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC;IAE9C,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QAC/E,SAAS,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,WAAW,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,IAAI,UAAU,EAAE,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,gCAAgC,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,IAAI,OAAO,KAAK,SAAS;QAChE,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC;QAC/C,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCb,CAAC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/cli/router.ts"],"names":[],"mappings":"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"}
package/dist/main.js CHANGED
File without changes
@@ -0,0 +1,32 @@
1
+ export interface ImageCacheOptions {
2
+ cacheDir?: string;
3
+ maxAge?: number;
4
+ }
5
+ export declare class ImageCache {
6
+ private readonly cacheDir;
7
+ private readonly maxAge;
8
+ constructor(options?: ImageCacheOptions);
9
+ /**
10
+ * 获取图片的本地缓存路径
11
+ */
12
+ getCachePath(url: string): string;
13
+ /**
14
+ * 检查图片是否已缓存且未过期
15
+ */
16
+ isCached(url: string): Promise<boolean>;
17
+ /**
18
+ * 获取缓存的图片路径,如果不存在则下载
19
+ * @returns 本地文件路径
20
+ */
21
+ getOrDownload(url: string): Promise<string>;
22
+ /**
23
+ * 下载图片到指定路径
24
+ */
25
+ download(url: string, destPath: string): Promise<void>;
26
+ /**
27
+ * 从 URL 推断文件扩展名
28
+ */
29
+ private getExtension;
30
+ }
31
+ export declare function getImageCache(): ImageCache;
32
+ //# sourceMappingURL=image-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-cache.d.ts","sourceRoot":"","sources":["../../src/storage/image-cache.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,OAAO,GAAE,iBAAsB;IAK3C;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAMjC;;OAEG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW7C;;;OAGG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAajD;;OAEG;IACG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5D;;OAEG;IACH,OAAO,CAAC,YAAY;CAiBrB;AAKD,wBAAgB,aAAa,IAAI,UAAU,CAK1C"}
@@ -0,0 +1,90 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, stat, writeFile } from "node:fs/promises";
3
+ import { join, extname } from "node:path";
4
+ import { getCacheDir } from "./paths.js";
5
+ export class ImageCache {
6
+ cacheDir;
7
+ maxAge;
8
+ constructor(options = {}) {
9
+ this.cacheDir = options.cacheDir ?? join(getCacheDir(), "images");
10
+ this.maxAge = options.maxAge ?? 7 * 24 * 60 * 60 * 1000; // 7 days
11
+ }
12
+ /**
13
+ * 获取图片的本地缓存路径
14
+ */
15
+ getCachePath(url) {
16
+ const hash = createHash("sha256").update(url).digest("hex");
17
+ const ext = this.getExtension(url);
18
+ return join(this.cacheDir, `${hash}${ext}`);
19
+ }
20
+ /**
21
+ * 检查图片是否已缓存且未过期
22
+ */
23
+ async isCached(url) {
24
+ const cachePath = this.getCachePath(url);
25
+ try {
26
+ const fileStat = await stat(cachePath);
27
+ const age = Date.now() - fileStat.mtimeMs;
28
+ return age < this.maxAge;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ /**
35
+ * 获取缓存的图片路径,如果不存在则下载
36
+ * @returns 本地文件路径
37
+ */
38
+ async getOrDownload(url) {
39
+ const cachePath = this.getCachePath(url);
40
+ // 检查缓存
41
+ if (await this.isCached(url)) {
42
+ return cachePath;
43
+ }
44
+ // 下载图片
45
+ await this.download(url, cachePath);
46
+ return cachePath;
47
+ }
48
+ /**
49
+ * 下载图片到指定路径
50
+ */
51
+ async download(url, destPath) {
52
+ // 确保目录存在
53
+ await mkdir(this.cacheDir, { recursive: true, mode: 0o700 });
54
+ // 下载
55
+ const response = await fetch(url);
56
+ if (!response.ok) {
57
+ throw new Error(`download failed: ${response.status} ${response.statusText}`);
58
+ }
59
+ const buffer = await response.arrayBuffer();
60
+ await writeFile(destPath, Buffer.from(buffer), { mode: 0o600 });
61
+ }
62
+ /**
63
+ * 从 URL 推断文件扩展名
64
+ */
65
+ getExtension(url) {
66
+ try {
67
+ const urlObj = new URL(url);
68
+ const pathname = urlObj.pathname;
69
+ const ext = extname(pathname).toLowerCase();
70
+ // 常见图片格式
71
+ if ([".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg"].includes(ext)) {
72
+ return ext;
73
+ }
74
+ // 默认使用 .jpg
75
+ return ".jpg";
76
+ }
77
+ catch {
78
+ return ".jpg";
79
+ }
80
+ }
81
+ }
82
+ // 单例
83
+ let defaultCache;
84
+ export function getImageCache() {
85
+ if (!defaultCache) {
86
+ defaultCache = new ImageCache();
87
+ }
88
+ return defaultCache;
89
+ }
90
+ //# sourceMappingURL=image-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-cache.js","sourceRoot":"","sources":["../../src/storage/image-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export interface VpnCredentials {
2
+ username: string;
3
+ password: string;
4
+ }
5
+ export interface VpnConfig {
6
+ mode: "auto" | "vpn" | "direct";
7
+ username?: string;
8
+ cookies?: Record<string, string>;
9
+ loggedInAt?: string;
10
+ }
11
+ export declare class VpnStore {
12
+ private readonly filePath;
13
+ constructor(filePath?: string);
14
+ /**
15
+ * 获取 VPN 配置
16
+ */
17
+ getConfig(): Promise<VpnConfig>;
18
+ /**
19
+ * 保存 VPN 配置
20
+ */
21
+ saveConfig(config: VpnConfig): Promise<void>;
22
+ /**
23
+ * 保存 VPN 用户名(密码不保存)
24
+ */
25
+ saveUsername(username: string): Promise<void>;
26
+ /**
27
+ * 保存 WebVPN 会话 Cookie
28
+ */
29
+ saveSession(username: string, cookies: Record<string, string>): Promise<void>;
30
+ /**
31
+ * 保存 VPN 模式
32
+ */
33
+ saveMode(mode: VpnConfig["mode"]): Promise<void>;
34
+ /**
35
+ * 清除 VPN 配置
36
+ */
37
+ clear(): Promise<void>;
38
+ }
39
+ //# sourceMappingURL=vpn-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vpn-store.d.ts","sourceRoot":"","sources":["../../src/storage/vpn-store.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CAErB;AAID,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,CAAC,EAAE,MAAM;IAI7B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC;IAgBrC;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IASlD;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnD;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnF;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
@@ -0,0 +1,94 @@
1
+ import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { getConfigDir } from "./paths.js";
4
+ import { join } from "node:path";
5
+ const VPN_CONFIG_FILE = "vpn.json";
6
+ export class VpnStore {
7
+ filePath;
8
+ constructor(filePath) {
9
+ this.filePath = filePath ?? join(getConfigDir(), VPN_CONFIG_FILE);
10
+ }
11
+ /**
12
+ * 获取 VPN 配置
13
+ */
14
+ async getConfig() {
15
+ try {
16
+ const raw = await readFile(this.filePath, "utf8");
17
+ const parsed = JSON.parse(raw);
18
+ if (isVpnConfig(parsed)) {
19
+ return parsed;
20
+ }
21
+ return { mode: "auto" };
22
+ }
23
+ catch (error) {
24
+ if (isFileNotFound(error)) {
25
+ return { mode: "auto" };
26
+ }
27
+ throw error;
28
+ }
29
+ }
30
+ /**
31
+ * 保存 VPN 配置
32
+ */
33
+ async saveConfig(config) {
34
+ await mkdir(dirname(this.filePath), { recursive: true, mode: 0o700 });
35
+ await writeFile(this.filePath, `${JSON.stringify(config, null, 2)}\n`, {
36
+ encoding: "utf8",
37
+ mode: 0o600,
38
+ });
39
+ await chmod(this.filePath, 0o600);
40
+ }
41
+ /**
42
+ * 保存 VPN 用户名(密码不保存)
43
+ */
44
+ async saveUsername(username) {
45
+ const config = await this.getConfig();
46
+ config.username = username;
47
+ await this.saveConfig(config);
48
+ }
49
+ /**
50
+ * 保存 WebVPN 会话 Cookie
51
+ */
52
+ async saveSession(username, cookies) {
53
+ const config = await this.getConfig();
54
+ await this.saveConfig({
55
+ ...config,
56
+ mode: config.mode ?? "auto",
57
+ username,
58
+ cookies,
59
+ loggedInAt: new Date().toISOString(),
60
+ });
61
+ }
62
+ /**
63
+ * 保存 VPN 模式
64
+ */
65
+ async saveMode(mode) {
66
+ const config = await this.getConfig();
67
+ config.mode = mode;
68
+ await this.saveConfig(config);
69
+ }
70
+ /**
71
+ * 清除 VPN 配置
72
+ */
73
+ async clear() {
74
+ const { rm } = await import("node:fs/promises");
75
+ await rm(this.filePath, { force: true });
76
+ }
77
+ }
78
+ function isVpnConfig(value) {
79
+ if (typeof value !== "object" ||
80
+ value === null ||
81
+ !("mode" in value) ||
82
+ typeof value.mode !== "string" ||
83
+ !["auto", "vpn", "direct"].includes(value.mode)) {
84
+ return false;
85
+ }
86
+ const config = value;
87
+ return config.cookies === undefined || (typeof config.cookies === "object" &&
88
+ config.cookies !== null &&
89
+ Object.values(config.cookies).every((cookie) => typeof cookie === "string"));
90
+ }
91
+ function isFileNotFound(error) {
92
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
93
+ }
94
+ //# sourceMappingURL=vpn-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vpn-store.js","sourceRoot":"","sources":["../../src/storage/vpn-store.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/tui/app.ts"],"names":[],"mappings":"AAQA,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAiD5C"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/tui/app.ts"],"names":[],"mappings":"AAUA,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAgE5C"}
package/dist/tui/app.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Cc98Client } from "../api/client.js";
2
2
  import { TokenStore } from "../storage/token-store.js";
3
+ import { VpnStore } from "../storage/vpn-store.js";
3
4
  import { CachedCc98Client } from "./cached-client.js";
4
5
  import { TuiController } from "./controller.js";
5
6
  import { draw } from "./renderer.js";
@@ -8,7 +9,18 @@ import { Terminal } from "./terminal.js";
8
9
  export async function runTui() {
9
10
  const terminal = new Terminal();
10
11
  const tokenStore = new TokenStore();
11
- const client = new CachedCc98Client(new Cc98Client({ tokenStore }));
12
+ const vpnStore = new VpnStore();
13
+ // 读取 VPN 配置
14
+ const vpnConfig = await vpnStore.getConfig();
15
+ const webVpnOptions = vpnConfig.mode === "vpn" || vpnConfig.cookies
16
+ ? { mode: vpnConfig.mode, cookies: vpnConfig.cookies }
17
+ : undefined;
18
+ const cc98Client = new Cc98Client({ tokenStore, webVpn: webVpnOptions });
19
+ // 初始化 WebVPN(如果需要)
20
+ if (webVpnOptions) {
21
+ await cc98Client.initWebVpn();
22
+ }
23
+ const client = new CachedCc98Client(cc98Client);
12
24
  const state = createInitialState();
13
25
  let exitRequested = false;
14
26
  terminal.enter();
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/tui/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;IACpE,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,IAAI,aAAa,GAAG,KAAK,CAAC;IAE1B,QAAQ,CAAC,KAAK,EAAE,CAAC;IAEjB,IAAI,CAAC;QACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,IAAI,YAAyC,CAAC;YAE9C,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC;YACjD,MAAM,UAAU,GAAG,GAAG,EAAE;gBACtB,YAAY,EAAE,CAAC;gBACf,YAAY,GAAG,IAAI,eAAe,EAAE,CAAC;gBACrC,OAAO,YAAY,CAAC,MAAM,CAAC;YAC7B,CAAC,CAAC;YACF,MAAM,MAAM,GAAG,GAAG,EAAE;gBAClB,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC,CAAC;YACF,MAAM,KAAK,GAAG,GAAG,EAAE;gBACjB,IAAI,MAAM;oBAAE,OAAO;gBACnB,MAAM,GAAG,IAAI,CAAC;gBACd,aAAa,GAAG,IAAI,CAAC;gBACrB,YAAY,EAAE,CAAC;gBACf,MAAM,EAAE,CAAC;gBACT,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAEF,MAAM,UAAU,GAAG,IAAI,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;YACzG,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;YAElE,MAAM,EAAE,CAAC;YACT,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/tui/app.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/tui/components/layout.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAmBlD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAqHV"}
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/tui/components/layout.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAoBlD,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAqHV"}