const U = "https://beschief.site/widget/widget.js"; const H = "https://beschief.site/widget/"; const F = FileManager.local(); const P = F.joinPath(F.cacheDirectory(), "hub_lab_src.js"); const OLD = P + ".previous"; const errors = []; let completed = false; async function run(source) { if (typeof source !== "string" || !source.includes("HUB_WIDGET")) throw new Error("위젯 코드 형식 오류"); const execute = new Function("return (async()=>{" + source + "\n})()"); await execute(); } try { const r = new Request(U); r.timeoutInterval = 12; const candidate = await r.loadString(); await run(candidate); // Promote only after compile AND execution succeed. completed = true; try { if (F.fileExists(P)) F.writeString(OLD, F.readString(P)); F.writeString(P, candidate); } catch (error) { console.warn("정상 위젯 캐시 저장 실패: " + error); } } catch (error) { errors.push(String(error)); } if (!completed) { for (const path of [P, OLD]) { if (!F.fileExists(path)) continue; try { await run(F.readString(path)); completed = true; break; } catch (error) { errors.push(String(error)); } } } if (!completed) { const w = new ListWidget(); w.backgroundColor = new Color("#0f1115"); const retryURL = URLScheme.forRunningScript(); if (config.widgetFamily === "small") w.url = retryURL; else { const retry = w.addStack(); retry.url = retryURL; retry.addText("↻ 다시 불러오기"); const details = w.addStack(); details.url = H; details.addText("상세 보기"); } const a = w.addText("위젯을 불러오지 못했습니다"); a.font = Font.mediumSystemFont(12); a.textColor = new Color("#e0a53c"); const b = w.addText(errors.join(" · ").slice(0, 160)); b.font = Font.systemFont(10); b.textColor = new Color("#8b93a7"); w.refreshAfterDate = new Date(Date.now() + 120000); if (config.runsInWidget) Script.setWidget(w); else await w.presentMedium(); Script.complete(); }