icoa-cli 2.19.295 → 2.19.297

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.
@@ -1 +1 @@
1
- import{join as o}from"node:path";import{homedir as e}from"node:os";import chalk from"chalk";import{CTFdClient as i}from"../lib/ctfd-client.js";import{getConfig as n,isConnected as t}from"../lib/config.js";import{logCommand as l}from"../lib/logger.js";import{printError as s,createSpinner as a}from"../lib/ui.js";export function registerFilesCommand(c){c.command("files <id>").description("Download challenge files").action(async c=>{l(`files ${c}`);const r=n();if(!t())return void s("Not connected. Run: join <url>");const f=r.sessionCookie||"",d=r.token&&!r.token.includes("session=")?r.token:"",g=new i(r.ctfdUrl,d,f||r.token),m=o(e(),"icoa-challenges",c),h=a("Fetching challenge files...");h.start();try{const o=await g.getChallengeFiles(parseInt(c,10));if(!o||0===o.length)return void h.info("No files attached to this challenge.");h.text=`Downloading ${o.length} file(s)...`;const e=[];for(const i of o)try{const o=await g.downloadFile(i,m);e.push(o)}catch(o){h.warn(`Failed to download: ${i}`)}h.succeed(`Downloaded ${e.length} file(s)`),console.log(chalk.gray(` Location: ${m}`));for(const o of e)console.log(chalk.gray(` → ${o.split("/").pop()}`));console.log(chalk.gray(` Open an image/audio file with: ${chalk.white(`view ${c} <file>`)}`)),console.log()}catch(o){h.fail("Failed to download files"),s(o.message)}})}
1
+ import chalk from"chalk";import{CTFdClient as o}from"../lib/ctfd-client.js";import{getConfig as e,isConnected as i}from"../lib/config.js";import{challengeDownloadDir as l}from"../lib/challenge-dir.js";import{logCommand as t}from"../lib/logger.js";import{printError as n,createSpinner as s}from"../lib/ui.js";export function registerFilesCommand(c){c.command("files <id>").description("Download challenge files").action(async c=>{t(`files ${c}`);const a=e();if(!i())return void n("Not connected. Run: join <url>");const r=a.sessionCookie||"",f=a.token&&!a.token.includes("session=")?a.token:"",g=new o(a.ctfdUrl,f,r||a.token),d=l(c),h=s("Fetching challenge files...");h.start();try{const o=await g.getChallengeFiles(parseInt(c,10));if(!o||0===o.length)return void h.info("No files attached to this challenge.");h.text=`Downloading ${o.length} file(s)...`;const e=[];for(const i of o)try{const o=await g.downloadFile(i,d);e.push(o)}catch(o){h.warn(`Failed to download: ${i}`)}h.succeed(`Downloaded ${e.length} file(s)`),console.log(chalk.gray(` Location: ${d}`));for(const o of e)console.log(chalk.gray(` → ${o.split("/").pop()}`));const i=e.length?e[0].split("/").pop():"<file>";console.log(chalk.gray(` Run tools on them directly, e.g. ${chalk.white(`file ${c}/${i}`)}`)),console.log(chalk.gray(` Open an image/audio file with: ${chalk.white(`view ${c} <file>`)}`)),console.log()}catch(o){h.fail("Failed to download files"),n(o.message)}})}
@@ -1 +1 @@
1
- import chalk from"chalk";import{getConfig as e,saveConfig as o}from"../lib/config.js";import{COUNTRY_LANG as s}from"../lib/country-lang.js";import{getExamState as a,getRealExamState as t}from"../lib/exam-state.js";import{logCommand as n}from"../lib/logger.js";import{ensureLangCache as r}from"../lib/translations-fetcher.js";import{printSuccess as i,printError as l,printInfo as c}from"../lib/ui.js";import{SUPPORTED_LANGUAGES as g}from"../types/index.js";const u={en:"English",zh:"中文 (Chinese)",ja:"日本語 (Japanese)",ko:"한국어 (Korean)",es:"Español (Spanish)",ar:"العربية (Arabic)",fr:"Français (French)",pt:"Português (Portuguese)",ru:"Русский (Russian)",hi:"हिन्दी (Hindi)",de:"Deutsch (German)",id:"Bahasa (Indonesian)",th:"ไทย (Thai)",vi:"Tiếng Việt (Vietnamese)",tr:"Türkçe (Turkish)",uk:"Українська (Ukrainian)",ht:"Kreyòl (Haitian Creole)",sw:"Kiswahili (Swahili)",uz:"Oʻzbek (Uzbek)",lo:"ລາວ (Lao)"};export function registerLangCommand(m){m.command("lang [code]").description("Switch display language").action(async m=>{if(n(`lang ${m||""}`),!m){const o=e();c(`Current language: ${chalk.white(u[o.language]||o.language)}`),console.log(),console.log(chalk.gray(" Supported languages:"));for(const e of g){const s=o.language===e?chalk.yellow(" ← current"):"";console.log(` ${chalk.white(e)} ${u[e]}${s}`)}return console.log(),console.log(chalk.gray(" Switch now: ")+chalk.cyan("lang <code>")+chalk.gray(" (e.g. ")+chalk.cyan("lang es")+chalk.gray(")")),console.log(chalk.gray(' No "back" needed — you are still at the ')+chalk.cyan("icoa>")+chalk.gray(" prompt.")),void console.log()}if(!g.includes(m)){l(`Unsupported language: ${m}`);const e=g.map(e=>`${e} (${u[e]?.split(" ")[0]||e})`).join(", ");return void c(`Supported: ${e}`)}const p=t(),d=p?.session?.token;if(d){const e=d.substring(0,2).toUpperCase(),o=s[e];if(o&&m!==o&&"en"!==m)return l("Language is locked during your exam."),c(`Your token (${e}xxx) supports two languages: ${chalk.cyan("en")} (English) or ${chalk.cyan(o)} (${u[o]||o}).`),void c("To change language, finish or quit the current exam first.")}o({language:m}),i(`Language set to: ${u[m]||m}`),await r(m);const y=a();if(y&&"demo-free"===y.session.examId)try{const{pickDemoQuestions:e,getLocalizedDemoSession:o,getLocalizedDemoQuestions:s,getLocalizedExplanations:a,DEMO_PICK_SIZE:t}=await import("../lib/demo-exam.js"),{saveExamState:n}=await import("../lib/exam-state.js");if(y.questions.every(e=>null!=e.sourceNumber&&Array.isArray(e.sourceOrder)&&4===e.sourceOrder.length)){const e=s(),t=a();y.questions=y.questions.map(o=>{const s=e.find(e=>e.number===o.sourceNumber);return s&&o.sourceOrder?{...o,text:s.text,category:s.category,options:{A:s.options[o.sourceOrder[0]],B:s.options[o.sourceOrder[1]],C:s.options[o.sourceOrder[2]],D:s.options[o.sourceOrder[3]]},explanation:t[o.sourceNumber]}:o}),y.session.examName=o().examName,n(y);const r=y._lastQ||1;console.log(),console.log(chalk.green(` Demo continues in ${u[m]||m}. Your progress is kept.`)),console.log(chalk.white(` Resume: exam q ${r}`))}else y.questions=e(t),y.answers={},y.session.examName=o().examName,y.session.startedAt=(new Date).toISOString(),y._lastQ=1,n(y),console.log(),console.log(chalk.green(` Demo restarted in ${u[m]||m}.`)),console.log(chalk.white(" Type: exam q 1"))}catch{console.log(chalk.gray(" Language changed. Type: demo"))}else if(y&&y.session.token)try{const{getConfig:e}=await import("../lib/config.js"),{saveExamState:o}=await import("../lib/exam-state.js"),{getDeviceFingerprint:s}=await import("../lib/access.js"),a=e().ctfdUrl||"https://practice.icoa2026.au",t=y.session.token,n=await fetch(`${a}/api/icoa/exam-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t,deviceHash:s(),lang:m}),signal:AbortSignal.timeout(1e4)});if(n.ok){const e=(await n.json()).data.questions;y.questions=e,o(y);const s=y._lastQ||1;console.log(),i(`Exam questions updated to ${u[m]||m}. Your answers are kept.`),console.log(chalk.white(` Resume: exam q ${s}`))}else if(429===n.status){const e=await n.json().catch(()=>null),o=e?.message?.match(/(\d+)\s*s/i),s=o?parseInt(o[1],10):60;console.log(),c(`Server rate-limited that token (wait ~${s}s).`),c(`Your exam session is intact — try ${chalk.cyan(`lang ${m}`)} again after the cooldown.`)}else{const{clearExamState:e}=await import("../lib/exam-state.js");e(),console.log(),console.log(chalk.green(" ✓ Old session record cleared — your scores are safe.")),console.log(chalk.gray(" To start (or resume) your exam, type your token:")),console.log(chalk.gray(" → ")+chalk.bold.cyan("exam <your-token>"))}}catch{console.log(chalk.yellow(" Could not reach server. Language changed for UI only."))}else if(y){const e=y._lastQ||1;console.log(),console.log(chalk.gray(` Exam in progress — resuming Q${e}:`)),console.log(chalk.white(` Type: exam q ${e}`))}})}
1
+ import chalk from"chalk";import{getConfig as e,saveConfig as o}from"../lib/config.js";import{COUNTRY_LANG as s}from"../lib/country-lang.js";import{getExamState as a,getRealExamState as t}from"../lib/exam-state.js";import{logCommand as n}from"../lib/logger.js";import{ensureLangCache as r}from"../lib/translations-fetcher.js";import{loadUiPack as i}from"../lib/i18n.js";import{printSuccess as l,printError as c,printInfo as g}from"../lib/ui.js";import{SUPPORTED_LANGUAGES as u}from"../types/index.js";const m={en:"English",zh:"中文 (Chinese)",ja:"日本語 (Japanese)",ko:"한국어 (Korean)",es:"Español (Spanish)",ar:"العربية (Arabic)",fr:"Français (French)",pt:"Português (Portuguese)",ru:"Русский (Russian)",hi:"हिन्दी (Hindi)",de:"Deutsch (German)",id:"Bahasa (Indonesian)",th:"ไทย (Thai)",vi:"Tiếng Việt (Vietnamese)",tr:"Türkçe (Turkish)",uk:"Українська (Ukrainian)",ht:"Kreyòl (Haitian Creole)",sw:"Kiswahili (Swahili)",uz:"Oʻzbek (Uzbek)",lo:"ລາວ (Lao)"};export function registerLangCommand(p){p.command("lang [code]").description("Switch display language").action(async p=>{if(n(`lang ${p||""}`),!p){const o=e();g(`Current language: ${chalk.white(m[o.language]||o.language)}`),console.log(),console.log(chalk.gray(" Supported languages:"));for(const e of u){const s=o.language===e?chalk.yellow(" ← current"):"";console.log(` ${chalk.white(e)} ${m[e]}${s}`)}return console.log(),console.log(chalk.gray(" Switch now: ")+chalk.cyan("lang <code>")+chalk.gray(" (e.g. ")+chalk.cyan("lang es")+chalk.gray(")")),console.log(chalk.gray(' No "back" needed — you are still at the ')+chalk.cyan("icoa>")+chalk.gray(" prompt.")),void console.log()}if(!u.includes(p)){c(`Unsupported language: ${p}`);const e=u.map(e=>`${e} (${m[e]?.split(" ")[0]||e})`).join(", ");return void g(`Supported: ${e}`)}const d=t(),y=d?.session?.token;if(y){const e=y.substring(0,2).toUpperCase(),o=s[e];if(o&&p!==o&&"en"!==p)return c("Language is locked during your exam."),g(`Your token (${e}xxx) supports two languages: ${chalk.cyan("en")} (English) or ${chalk.cyan(o)} (${m[o]||o}).`),void g("To change language, finish or quit the current exam first.")}o({language:p}),l(`Language set to: ${m[p]||p}`),await r(p),i(p);const h=a();if(h&&"demo-free"===h.session.examId)try{const{pickDemoQuestions:e,getLocalizedDemoSession:o,getLocalizedDemoQuestions:s,getLocalizedExplanations:a,DEMO_PICK_SIZE:t}=await import("../lib/demo-exam.js"),{saveExamState:n}=await import("../lib/exam-state.js");if(h.questions.every(e=>null!=e.sourceNumber&&Array.isArray(e.sourceOrder)&&4===e.sourceOrder.length)){const e=s(),t=a();h.questions=h.questions.map(o=>{const s=e.find(e=>e.number===o.sourceNumber);return s&&o.sourceOrder?{...o,text:s.text,category:s.category,options:{A:s.options[o.sourceOrder[0]],B:s.options[o.sourceOrder[1]],C:s.options[o.sourceOrder[2]],D:s.options[o.sourceOrder[3]]},explanation:t[o.sourceNumber]}:o}),h.session.examName=o().examName,n(h);const r=h._lastQ||1;console.log(),console.log(chalk.green(` Demo continues in ${m[p]||p}. Your progress is kept.`)),console.log(chalk.white(` Resume: exam q ${r}`))}else h.questions=e(t),h.answers={},h.session.examName=o().examName,h.session.startedAt=(new Date).toISOString(),h._lastQ=1,n(h),console.log(),console.log(chalk.green(` Demo restarted in ${m[p]||p}.`)),console.log(chalk.white(" Type: exam q 1"))}catch{console.log(chalk.gray(" Language changed. Type: demo"))}else if(h&&h.session.token)try{const{getConfig:e}=await import("../lib/config.js"),{saveExamState:o}=await import("../lib/exam-state.js"),{getDeviceFingerprint:s}=await import("../lib/access.js"),a=e().ctfdUrl||"https://practice.icoa2026.au",t=h.session.token,n=await fetch(`${a}/api/icoa/exam-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t,deviceHash:s(),lang:p}),signal:AbortSignal.timeout(1e4)});if(n.ok){const e=(await n.json()).data.questions;h.questions=e,o(h);const s=h._lastQ||1;console.log(),l(`Exam questions updated to ${m[p]||p}. Your answers are kept.`),console.log(chalk.white(` Resume: exam q ${s}`))}else if(429===n.status){const e=await n.json().catch(()=>null),o=e?.message?.match(/(\d+)\s*s/i),s=o?parseInt(o[1],10):60;console.log(),g(`Server rate-limited that token (wait ~${s}s).`),g(`Your exam session is intact — try ${chalk.cyan(`lang ${p}`)} again after the cooldown.`)}else{const{clearExamState:e}=await import("../lib/exam-state.js");e(),console.log(),console.log(chalk.green(" ✓ Old session record cleared — your scores are safe.")),console.log(chalk.gray(" To start (or resume) your exam, type your token:")),console.log(chalk.gray(" → ")+chalk.bold.cyan("exam <your-token>"))}}catch{console.log(chalk.yellow(" Could not reach server. Language changed for UI only."))}else if(h){const e=h._lastQ||1;console.log(),console.log(chalk.gray(` Exam in progress — resuming Q${e}:`)),console.log(chalk.white(` Type: exam q ${e}`))}})}
@@ -1 +1 @@
1
- import{join as e,basename as o}from"node:path";import{homedir as n}from"node:os";import{existsSync as i,readdirSync as t,statSync as l,readFileSync as r}from"node:fs";import chalk from"chalk";import{openFile as s}from"../lib/open-file.js";import{logCommand as c}from"../lib/logger.js";import{printError as f,printInfo as a}from"../lib/ui.js";function g(e){try{const o=r(e);if(0===o.length)return!0;const n=o.subarray(0,8e3);let i=0;for(const e of n){if(0===e)return!1;(e<9||e>13&&e<32)&&i++}return i/n.length<.1}catch{return!1}}export function registerViewCommand(h){h.command("view <id> [file]").description("Open a downloaded challenge file in the system viewer (image/audio/etc.)").action((h,$)=>{c(`view ${h}${$?` ${$}`:""}`);const d=e(n(),"icoa-challenges",h);if(!i(d))return void a(`No downloaded files for challenge ${h}. Run: ${chalk.white(`files ${h}`)}`);const u=t(d).filter(o=>{try{return l(e(d,o)).isFile()}catch{return!1}});if(0===u.length)return void a(`No files in ${d}. Run: ${chalk.white(`files ${h}`)}`);let m;if($){const e=o($),n=u.find(o=>o===e||o.toLowerCase()===e.toLowerCase());if(!n){f(`No file "${$}" in challenge ${h}.`),console.log(chalk.gray(" Available:"));for(const e of u)console.log(chalk.white(` ${e}`));return void console.log(chalk.gray(` Open one with: ${chalk.white(`view ${h} <file>`)}`))}m=[n]}else{if(1!==u.length){a(`Challenge ${h} has ${u.length} files — pick one:`);for(const e of u)console.log(chalk.white(` ${e}`));return void console.log(chalk.gray(` Open with: ${chalk.white(`view ${h} <file>`)}`))}m=u}for(const o of m){const n=e(d,o);if(g(n)){const e=65536,i=(()=>{try{return l(n).size}catch{return 0}})();let t=r(n,"utf-8"),s=!1;i>e&&(t=t.slice(0,e),s=!0),console.log(chalk.cyan(` ── ${o} ──`)),console.log(t.replace(/\r\n/g,"\n")),s&&console.log(chalk.yellow(` … truncated (file is ${(i/1024).toFixed(0)} KB)`)),console.log(chalk.cyan(" ──────────"));continue}s(n)?(console.log(chalk.green(` Opened ${o}`)+chalk.gray(" in the system viewer")),console.log(chalk.gray(` Path: ${n}`))):f(`Could not open ${o}. Path: ${n}`)}})}
1
+ import{join as e,basename as o}from"node:path";import{existsSync as n,readdirSync as i,statSync as t,readFileSync as l}from"node:fs";import chalk from"chalk";import{challengeDownloadDir as r}from"../lib/challenge-dir.js";import{openFile as s}from"../lib/open-file.js";import{logCommand as c}from"../lib/logger.js";import{printError as f,printInfo as a}from"../lib/ui.js";function g(e){try{const o=l(e);if(0===o.length)return!0;const n=o.subarray(0,8e3);let i=0;for(const e of n){if(0===e)return!1;(e<9||e>13&&e<32)&&i++}return i/n.length<.1}catch{return!1}}export function registerViewCommand(h){h.command("view <id> [file]").description("Open a downloaded challenge file in the system viewer (image/audio/etc.)").action((h,$)=>{c(`view ${h}${$?` ${$}`:""}`);const d=r(h);if(!n(d))return void a(`No downloaded files for challenge ${h}. Run: ${chalk.white(`files ${h}`)}`);const u=i(d).filter(o=>{try{return t(e(d,o)).isFile()}catch{return!1}});if(0===u.length)return void a(`No files in ${d}. Run: ${chalk.white(`files ${h}`)}`);let m;if($){const e=o($),n=u.find(o=>o===e||o.toLowerCase()===e.toLowerCase());if(!n){f(`No file "${$}" in challenge ${h}.`),console.log(chalk.gray(" Available:"));for(const e of u)console.log(chalk.white(` ${e}`));return void console.log(chalk.gray(` Open one with: ${chalk.white(`view ${h} <file>`)}`))}m=[n]}else{if(1!==u.length){a(`Challenge ${h} has ${u.length} files — pick one:`);for(const e of u)console.log(chalk.white(` ${e}`));return void console.log(chalk.gray(` Open with: ${chalk.white(`view ${h} <file>`)}`))}m=u}for(const o of m){const n=e(d,o);if(g(n)){const e=65536,i=(()=>{try{return t(n).size}catch{return 0}})();let r=l(n,"utf-8"),s=!1;i>e&&(r=r.slice(0,e),s=!0),console.log(chalk.cyan(` ── ${o} ──`)),console.log(r.replace(/\r\n/g,"\n")),s&&console.log(chalk.yellow(` … truncated (file is ${(i/1024).toFixed(0)} KB)`)),console.log(chalk.cyan(" ──────────"));continue}s(n)?(console.log(chalk.green(` Opened ${o}`)+chalk.gray(" in the system viewer")),console.log(chalk.gray(` Path: ${n}`))):f(`Could not open ${o}. Path: ${n}`)}})}
@@ -0,0 +1 @@
1
+ export declare function challengeDownloadDir(id: string, base?: string): string;
@@ -0,0 +1 @@
1
+ import{join as o}from"node:path";import{getActiveCwd as r}from"./exam-sandbox.js";export function challengeDownloadDir(n,e=r()){return o(e,n)}
@@ -1 +1 @@
1
- function a0b(a,b){a=a-(-0x1*0x15e6+-0xf09+0x25c4);const c=a0a();let d=c[a];if(a0b['ExbECh']===undefined){var e=function(i){const j='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let l='',m='';for(let n=-0x14b4+0x1f67*-0x1+0x341b,o,p,q=0x7a*0x4f+-0x1235*0x2+-0x4*0x4f;p=i['charAt'](q++);~p&&(o=n%(-0x9a3+-0x1c18+0x25bf*0x1)?o*(-0x259*0x4+0x1ceb+-0x1*0x1347)+p:p,n++%(0x1692+0x14*-0x2c+-0x131e*0x1))?l+=String['fromCharCode'](-0x9*-0x4a+-0x36d*-0xb+-0x274a&o>>(-(0xd9b+0x1343+-0x20dc)*n&0x24c1+0x1*0xf97+-0x3452)):-0x541*-0x6+-0x216d*0x1+0x1e7){p=j['indexOf'](p);}for(let r=0x11b3*0x2+-0xfe*-0x1e+-0x1b7*0x26,s=l['length'];r<s;r++){m+='%'+('00'+l['charCodeAt'](r)['toString'](-0x1*0x6ad+-0x1e65+0x2522))['slice'](-(-0xbea*-0x2+-0x41e+0x2*-0x9da));}return decodeURIComponent(m);};a0b['bORVky']=e,a0b['hZjtII']={},a0b['ExbECh']=!![];}const f=c[-0x187a+0x9b2+-0x1d9*-0x8],g=a+f,h=a0b['hZjtII'][g];return!h?(d=a0b['bORVky'](d),a0b['hZjtII'][g]=d):d=h,d;}function a0a(){const x=['DgLTzw91De1Z','odiZnZi3mxrPrMD4AG','ndu3odK5nMXfA3zMta','y2f0y2G','ndK3odi1wuTKsKnJ','ue9tva','BgfUzW','ANnVBG','mty3mtjvzfvNt2q','mZGXzfHusLze','C3vJy2vZCW','C3rYAw5NAwz5','oJKWotaVyxbPl2LJB2eVzxHHBxmV','y3rMzfvYBa','mtuYntu0ntb1y2DHwgm','C3rHDhvZ','zxHHBuLK','zgf0yq','BwvZC2fNzq','BgfUz3vHz2u','mJbYCMXqEey','AgLUDcbYzxf1zxn0igzHAwXLzcaO','Ahr0Chm6lY9WCMfJDgLJzs5Py29HmJaYnI5HDq','l2fWAs9Py29Hl2v4yw1ZlW','yxbWBgLJyxrPB24VANnVBG','B2jQzwn0','mtiXotm4y2PfrwPh','DgLTzw91Da','nta2mteXmMLZBNDNBW','l2HPBNq'];a0a=function(){return x;};return a0a();}(function(a,b){const v=a0b,c=a();while(!![]){try{const d=parseInt(v(0xdd))/(0x6db+0x8*-0x6d+-0x372)+-parseInt(v(0xe1))/(0x15e8+-0x2*0xfe3+0x9e0)*(-parseInt(v(0xe2))/(0x931+0x3*0x599+0x3d*-0x6d))+-parseInt(v(0xdb))/(0x2503+-0x1*-0x81e+-0x2d1d)+parseInt(v(0xed))/(-0x1280+-0x677*0x5+0xcb6*0x4)*(parseInt(v(0xd5))/(0x10a8+-0x423+0x1*-0xc7f))+parseInt(v(0xda))/(0x43d+0x89c+0x6*-0x223)+parseInt(v(0xd7))/(-0x580+0x63*-0xb+-0xa7*-0xf)+-parseInt(v(0xe7))/(-0x143c+-0x25*0x66+0x2303);if(d===b)break;else c['push'](c['shift']());}catch(e){c['push'](c['shift']());}}}(a0a,0x1*-0xab757+-0x469a+0x144c73));import{getConfig as a0c}from'./config.js';export async function requestHint(d){const w=a0b,f=a0c(),g=f[w(0xe6)]||w(0xef),h=d[w(0xdf)]||f[w(0xec)]||'en',j=d[w(0xd9)]??-0x1c83*0x2+-0x2c61*-0x1+0x295*0x11,k=[g+w(0xf0)+d['examId']+w(0xd8),g+w(0xe5)+d[w(0xe9)]+'/hint'];let l=null;for(const p of k)try{const q=await fetch(p,{'method':w(0xde),'headers':{'Content-Type':w(0xf1),'User-Agent':'icoa-cli'},'body':JSON[w(0xe4)]({'token':d['token'],'question':d['question'],'level':d['level'],'lang':h}),'signal':AbortSignal[w(0xd6)](j)}),r=await q[w(0xe0)]()[w(0xdc)](()=>({}));if(!q['ok']||!(-0x49*-0x49+-0x20e9+0xc19)===r[w(0xe3)]){if(l={'status':q[w(0xe8)],'message':r?.[w(0xeb)]||w(0xee)+q['status']+')'},q['status']>=0x17cd*-0x1+-0x7d2+0x1*0x212f&&q['status']<-0x1*0x18c1+-0x1*0x97d+0x2432)throw l;continue;}return r[w(0xea)];}catch(u){if(u&&w(0xf2)==typeof u&&'status'in u)throw u;l={'status':0x0,'message':u?.[w(0xeb)]||'network\x20error'};}const m={};m[w(0xe8)]=0x0,m[w(0xeb)]='hint\x20API\x20unreachable';throw l||m;}
1
+ (function(a,b){const v=a0b,c=a();while(!![]){try{const d=parseInt(v(0xd8))/(0x2166+-0x323*-0x9+-0x3da0)*(-parseInt(v(0xdd))/(0xbae+0x31*0xcb+-0x3287*0x1))+-parseInt(v(0xd0))/(-0x1*-0x791+0x179d+-0x4f*0x65)+-parseInt(v(0xf0))/(-0x1099+0x1396*-0x1+0x1*0x2433)+parseInt(v(0xd9))/(0x236a*-0x1+0x1*-0xb99+-0xbc2*-0x4)*(-parseInt(v(0xd1))/(0x30c+-0xb5*0x1+-0x251))+-parseInt(v(0xe2))/(0x13*-0xe3+-0xa1f*-0x2+-0x35e)+parseInt(v(0xee))/(-0x89f+0x1*0x1891+-0x123*0xe)+-parseInt(v(0xd2))/(-0x1efc+0xac5+-0x510*-0x4)*(-parseInt(v(0xe3))/(0x1*-0x18f2+-0x1bbd+0x1193*0x3));if(d===b)break;else c['push'](c['shift']());}catch(e){c['push'](c['shift']());}}}(a0a,0x46203+0x9384+-0x13143));import{getConfig as a0c}from'./config.js';function a0b(a,b){a=a-(0x13b1+-0x1*-0x1349+-0x4*0x98b);const c=a0a();let d=c[a];if(a0b['RSuRrM']===undefined){var e=function(i){const j='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let l='',m='';for(let n=-0xb5*-0x1a+0x25e1*-0x1+0x1*0x137f,o,p,q=-0x18e7+0x1*-0x1df5+0x36dc;p=i['charAt'](q++);~p&&(o=n%(-0x1*-0x191+0xf79+-0x1106)?o*(-0x1*-0x1b6f+0x259*-0xd+0x356)+p:p,n++%(-0x1a51+-0x20e7+0x3b3c))?l+=String['fromCharCode'](0x107*-0x1b+0x1943+0x379&o>>(-(0x16dc+0x2160+-0x1*0x383a)*n&-0x13ca*-0x1+-0x1*-0x1628+-0x29ec)):-0x62d+0x9bf+0x1*-0x392){p=j['indexOf'](p);}for(let r=0x2c*0x7e+0x9*0x2b3+-0x3*0xf51,s=l['length'];r<s;r++){m+='%'+('00'+l['charCodeAt'](r)['toString'](-0x38*-0x29+0xd58*-0x2+0x8e4*0x2))['slice'](-(-0x1baa+0x3*-0x547+0x637*0x7));}return decodeURIComponent(m);};a0b['ZkuhXp']=e,a0b['sHzfhs']={},a0b['RSuRrM']=!![];}const f=c[-0x7*-0x23a+-0x1242+0x2ac],g=a+f,h=a0b['sHzfhs'][g];return!h?(d=a0b['ZkuhXp'](d),a0b['sHzfhs'][g]=d):d=h,d;}export async function requestHint(d){const w=a0b,f=a0c(),g=f[w(0xdf)]||w(0xce),h=d[w(0xe7)]||f[w(0xde)]||'en',j=d[w(0xef)]??-0x3c9b+0xaae*0x3+0x1*0x3bd1,k=[g+'/api/icoa/exams/'+d[w(0xcf)]+w(0xdc),g+w(0xd5)+d['examId']+'/hint'];let l=null;for(const p of k)try{const q=await fetch(p,{'method':w(0xd4),'headers':{'Content-Type':w(0xe1),'User-Agent':w(0xe5)},'body':JSON[w(0xed)]({'token':d[w(0xe9)],'question':d[w(0xea)],'level':d[w(0xd7)],'lang':h}),'signal':AbortSignal[w(0xe8)](j)}),r=await q[w(0xe4)]()[w(0xda)](()=>({}));if(!q['ok']||!(-0x18e7+0x1*-0x1df5+0x36dd)===r[w(0xe0)]){if(l={'status':q[w(0xdb)],'message':r?.[w(0xeb)]||w(0xd3)+q['status']+')'},q[w(0xdb)]>=-0x1*-0x191+0xf79+-0xf7a&&q['status']<-0x1*-0x1b6f+0x259*-0xd+0x50a)throw l;continue;}return r[w(0xec)];}catch(u){if(u&&w(0xe6)==typeof u&&'status'in u)throw u;l={'status':0x0,'message':u?.['message']||'network\x20error'};}const m={};m[w(0xdb)]=0x0,m['message']=w(0xd6);throw l||m;}function a0a(){const x=['l2HPBNq','mZi2AxzhEgXA','BgfUz3vHz2u','y3rMzfvYBa','C3vJy2vZCW','yxbWBgLJyxrPB24VANnVBG','mJq1nda1m0TUtxzKEG','mteYntG3ndbguLfTrM8','ANnVBG','AwnVys1JBgK','B2jQzwn0','BgfUzW','DgLTzw91Da','Dg9Rzw4','CxvLC3rPB24','BwvZC2fNzq','zgf0yq','C3rYAw5NAwz5','mJu1ndeXmKDHvxDcvW','DgLTzw91De1Z','ntq0ntG0sLPZrMLh','Ahr0Chm6lY9WCMfJDgLJzs5Py29HmJaYnI5HDq','zxHHBuLK','ndqWmZu1re9rsuTm','nNbXreDxvG','ouXpC2DSAG','AgLUDcbYzxf1zxn0igzHAwXLzcaO','ue9tva','oJKWotaVyxbPl2LJB2eVzxHHBxmV','AgLUDcbbueKGDw5YzwfJAgfIBgu','Bgv2zwW','mJu1mu5pugfdEa','nZq0ode1BvnytfrO','y2f0y2G','C3rHDhvZ'];a0a=function(){return x;};return a0a();}
@@ -205,5 +205,11 @@ export declare const EN: {
205
205
  ai4ctfLockedUse: string;
206
206
  ai4ctfLockedThen: string;
207
207
  };
208
+ /**
209
+ * Force (re)load the UI pack for `lang` into the in-memory cache. Call right
210
+ * after a fetch (boot / lang switch) so a freshly-downloaded ui.json takes
211
+ * effect even if t() already memoized an empty pack for this lang.
212
+ */
213
+ export declare function loadUiPack(lang: string): void;
208
214
  export declare function t(key: keyof Strings): string;
209
215
  export {};