Upload 15 files
Browse files- exocore-web/public/FileManager.jsx +1288 -0
- exocore-web/public/console.jsx +305 -0
- exocore-web/public/dashboard.jsx +251 -0
- exocore-web/public/devtools.js +0 -0
- exocore-web/public/eruda.js +1 -0
- exocore-web/public/forgot.jsx +142 -0
- exocore-web/public/keywordsdetect.js +1 -0
- exocore-web/public/login.jsx +160 -0
- exocore-web/public/otp.jsx +195 -0
- exocore-web/public/panel.html +115 -0
- exocore-web/public/plans.jsx +418 -0
- exocore-web/public/profile.jsx +527 -0
- exocore-web/public/project.jsx +483 -0
- exocore-web/public/register.jsx +338 -0
- exocore-web/public/shell.jsx +215 -0
exocore-web/public/FileManager.jsx
ADDED
@@ -0,0 +1,1288 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, For, Show, onCleanup, createEffect } from 'solid-js';
|
3 |
+
|
4 |
+
import hljs from 'highlight.js/lib/core';
|
5 |
+
import javascript_hljs from 'highlight.js/lib/languages/javascript';
|
6 |
+
import typescript_hljs from 'highlight.js/lib/languages/typescript';
|
7 |
+
import json_hljs from 'highlight.js/lib/languages/json';
|
8 |
+
import xml_hljs from 'highlight.js/lib/languages/xml';
|
9 |
+
import css_hljs from 'highlight.js/lib/languages/css';
|
10 |
+
import bash_hljs from 'highlight.js/lib/languages/bash';
|
11 |
+
import markdown_hljs from 'highlight.js/lib/languages/markdown';
|
12 |
+
import sql_hljs from 'highlight.js/lib/languages/sql';
|
13 |
+
|
14 |
+
import { EditorView, keymap, lineNumbers } from '@codemirror/view';
|
15 |
+
import { EditorState, Compartment } from '@codemirror/state';
|
16 |
+
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
|
17 |
+
import { syntaxHighlighting, defaultHighlightStyle, foldGutter, foldKeymap } from '@codemirror/language';
|
18 |
+
import { lintGutter } from "@codemirror/lint";
|
19 |
+
import { oneDark } from '@codemirror/theme-one-dark';
|
20 |
+
|
21 |
+
import { javascript } from '@codemirror/lang-javascript';
|
22 |
+
import { json } from '@codemirror/lang-json';
|
23 |
+
import { html } from '@codemirror/lang-html';
|
24 |
+
import { css } from '@codemirror/lang-css';
|
25 |
+
import { markdown } from '@codemirror/lang-markdown';
|
26 |
+
|
27 |
+
hljs.registerLanguage('javascript', javascript_hljs);
|
28 |
+
hljs.registerLanguage('typescript', typescript_hljs);
|
29 |
+
hljs.registerLanguage('json', json_hljs);
|
30 |
+
hljs.registerLanguage('html', xml_hljs);
|
31 |
+
hljs.registerLanguage('css', css_hljs);
|
32 |
+
hljs.registerLanguage('bash', bash_hljs);
|
33 |
+
hljs.registerLanguage('markdown', markdown_hljs);
|
34 |
+
hljs.registerLanguage('sql', sql_hljs);
|
35 |
+
|
36 |
+
function App() {
|
37 |
+
const [loading, setLoading] = createSignal(true);
|
38 |
+
const [status, setStatus] = createSignal('');
|
39 |
+
const [notifications, setNotifications] = createSignal([]);
|
40 |
+
const [userData, setUserData] = createSignal(null);
|
41 |
+
const [files, setFiles] = createSignal([]);
|
42 |
+
const [selectedFile, setSelectedFile] = createSignal(null);
|
43 |
+
const [fileContent, setFileContent] = createSignal('');
|
44 |
+
const [newFileName, setNewFileName] = createSignal('');
|
45 |
+
const [newFolderName, setNewFolderName] = createSignal('');
|
46 |
+
const [openFolders, setOpenFolders] = createSignal({});
|
47 |
+
const [contextMenu, setContextMenu] = createSignal({
|
48 |
+
visible: false,
|
49 |
+
x: 0,
|
50 |
+
y: 0,
|
51 |
+
file: null,
|
52 |
+
});
|
53 |
+
const [isMobileView, setIsMobileView] = createSignal(false);
|
54 |
+
const [isEditingFile, setIsEditingFile] = createSignal(true);
|
55 |
+
const [initialLoadComplete, setInitialLoadComplete] = createSignal(false);
|
56 |
+
|
57 |
+
const [renameContainerInfo, setRenameContainerInfo] = createSignal({
|
58 |
+
visible: false,
|
59 |
+
file: null,
|
60 |
+
newName: '',
|
61 |
+
});
|
62 |
+
const [createItemModalInfo, setCreateItemModalInfo] = createSignal({
|
63 |
+
visible: false,
|
64 |
+
parentPath: null,
|
65 |
+
isDir: false,
|
66 |
+
itemName: '',
|
67 |
+
});
|
68 |
+
|
69 |
+
let renameInputRef;
|
70 |
+
let codeRef;
|
71 |
+
let createItemInputRef;
|
72 |
+
let editorRef;
|
73 |
+
let editorViewInstance = null;
|
74 |
+
|
75 |
+
const languageCompartment = new Compartment();
|
76 |
+
const themeCompartment = new Compartment();
|
77 |
+
const editableCompartment = new Compartment();
|
78 |
+
|
79 |
+
const linkManager = '/private/server/exocore/web/file';
|
80 |
+
|
81 |
+
const getToken = () => localStorage.getItem('exocore-token') || '';
|
82 |
+
const getCookies = () => localStorage.getItem('exocore-cookies') || '';
|
83 |
+
|
84 |
+
const addNotification = (message, type = 'info', duration = 4000) => {
|
85 |
+
const id = Date.now();
|
86 |
+
setNotifications(prev => [...prev, { id, message, type }]);
|
87 |
+
setTimeout(() => {
|
88 |
+
setNotifications(prev => prev.filter(n => n.id !== id));
|
89 |
+
}, duration);
|
90 |
+
};
|
91 |
+
|
92 |
+
function sortFileSystemItems(items) {
|
93 |
+
if (!Array.isArray(items)) return [];
|
94 |
+
|
95 |
+
const specialOrder = ['.git', 'package.json', 'package-lock.json'];
|
96 |
+
const nodeModulesName = 'node_modules';
|
97 |
+
|
98 |
+
const regularItems = items.filter(item => !specialOrder.includes(item.name) && item.name !== nodeModulesName);
|
99 |
+
const specialItemsOnList = items.filter(item => specialOrder.includes(item.name));
|
100 |
+
const nodeModulesItem = items.find(item => item.name === nodeModulesName);
|
101 |
+
|
102 |
+
regularItems.sort((a, b) => {
|
103 |
+
if (a.isDir && !b.isDir) return -1;
|
104 |
+
if (!a.isDir && b.isDir) return 1;
|
105 |
+
return a.name.localeCompare(b.name);
|
106 |
+
});
|
107 |
+
specialItemsOnList.sort((a, b) => specialOrder.indexOf(a.name) - specialOrder.indexOf(b.name));
|
108 |
+
|
109 |
+
const sortedItems = [...regularItems, ...specialItemsOnList];
|
110 |
+
if (nodeModulesItem) {
|
111 |
+
sortedItems.push(nodeModulesItem);
|
112 |
+
}
|
113 |
+
return sortedItems;
|
114 |
+
}
|
115 |
+
|
116 |
+
async function fetchUserInfo() {
|
117 |
+
setLoading(true);
|
118 |
+
const token = getToken();
|
119 |
+
const cookies = getCookies();
|
120 |
+
|
121 |
+
if (!token || !cookies) {
|
122 |
+
setLoading(false);
|
123 |
+
setInitialLoadComplete(true);
|
124 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
125 |
+
return;
|
126 |
+
}
|
127 |
+
|
128 |
+
try {
|
129 |
+
const res = await fetch('/private/server/exocore/web/userinfo', {
|
130 |
+
method: 'POST',
|
131 |
+
headers: { 'Content-Type': 'application/json' },
|
132 |
+
body: JSON.stringify({ token, cookies }),
|
133 |
+
});
|
134 |
+
|
135 |
+
if (!res.ok) {
|
136 |
+
let errorMsg = `Server error: ${res.status}`;
|
137 |
+
try {
|
138 |
+
const errorData = await res.json();
|
139 |
+
errorMsg = errorData.message || errorMsg;
|
140 |
+
} catch (parseError) {}
|
141 |
+
throw new Error(errorMsg);
|
142 |
+
}
|
143 |
+
|
144 |
+
const data = await res.json();
|
145 |
+
|
146 |
+
if (data.data?.user && data.data.user.verified === 'success') {
|
147 |
+
setUserData(data.data.user);
|
148 |
+
await fetchFiles('');
|
149 |
+
} else {
|
150 |
+
setUserData(null);
|
151 |
+
const redirectMsg = data.message || 'User verification failed. Redirecting to login...';
|
152 |
+
setStatus(redirectMsg);
|
153 |
+
localStorage.removeItem('exocore-token');
|
154 |
+
localStorage.removeItem('exocore-cookies');
|
155 |
+
setTimeout(() => {
|
156 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
157 |
+
}, 2500);
|
158 |
+
}
|
159 |
+
} catch (err) {
|
160 |
+
setUserData(null);
|
161 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
162 |
+
const redirectMsg = 'Failed to fetch user info: ' + errorMessage + '. Redirecting to login...';
|
163 |
+
setStatus(redirectMsg);
|
164 |
+
localStorage.removeItem('exocore-token');
|
165 |
+
localStorage.removeItem('exocore-cookies');
|
166 |
+
setTimeout(() => {
|
167 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
168 |
+
}, 2500);
|
169 |
+
} finally {
|
170 |
+
setLoading(false);
|
171 |
+
setInitialLoadComplete(true);
|
172 |
+
}
|
173 |
+
}
|
174 |
+
|
175 |
+
async function fetchFiles(currentPath = '') {
|
176 |
+
setLoading(true);
|
177 |
+
let endpoint = '';
|
178 |
+
let bodyPayload = {};
|
179 |
+
if (currentPath) {
|
180 |
+
endpoint = `${linkManager}/open-folder`;
|
181 |
+
bodyPayload = {
|
182 |
+
folder: currentPath,
|
183 |
+
};
|
184 |
+
} else {
|
185 |
+
endpoint = `${linkManager}/list`;
|
186 |
+
bodyPayload = {};
|
187 |
+
}
|
188 |
+
try {
|
189 |
+
const res = await fetch(endpoint, {
|
190 |
+
method: 'POST',
|
191 |
+
headers: {
|
192 |
+
'Content-Type': 'application/json',
|
193 |
+
},
|
194 |
+
body: JSON.stringify(bodyPayload),
|
195 |
+
});
|
196 |
+
const responseText = await res.text();
|
197 |
+
if (!res.ok) {
|
198 |
+
let errorMsg = responseText;
|
199 |
+
try {
|
200 |
+
const errData = JSON.parse(responseText);
|
201 |
+
errorMsg = errData.message || errData.error || responseText;
|
202 |
+
} catch (e) {}
|
203 |
+
throw new Error(errorMsg || `HTTP error! status: ${res.status}`);
|
204 |
+
}
|
205 |
+
const data = JSON.parse(responseText);
|
206 |
+
if (currentPath) {
|
207 |
+
if (data && Array.isArray(data.items)) {
|
208 |
+
setOpenFolders((prev) => ({
|
209 |
+
...prev,
|
210 |
+
[currentPath]: sortFileSystemItems(data.items),
|
211 |
+
}));
|
212 |
+
} else {
|
213 |
+
setOpenFolders((prev) => ({ ...prev, [currentPath]: [] }));
|
214 |
+
addNotification(`Error: Could not load content for folder ${currentPath}.`, 'error');
|
215 |
+
}
|
216 |
+
} else {
|
217 |
+
if (Array.isArray(data)) {
|
218 |
+
setFiles(sortFileSystemItems(data));
|
219 |
+
} else {
|
220 |
+
setFiles([]);
|
221 |
+
addNotification(`Error: Could not load root directory.`, 'error');
|
222 |
+
}
|
223 |
+
}
|
224 |
+
} catch (err) {
|
225 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
226 |
+
addNotification(`Failed to list ${currentPath || 'root'}: ${errorMessage}`, 'error');
|
227 |
+
if (currentPath) {
|
228 |
+
setOpenFolders((prev) => ({ ...prev, [currentPath]: undefined }));
|
229 |
+
}
|
230 |
+
} finally {
|
231 |
+
setLoading(false);
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
async function openFile(file) {
|
236 |
+
setLoading(true);
|
237 |
+
try {
|
238 |
+
const res = await fetch(`${linkManager}/open`, {
|
239 |
+
method: 'POST',
|
240 |
+
headers: {
|
241 |
+
'Content-Type': 'application/json',
|
242 |
+
},
|
243 |
+
body: JSON.stringify({
|
244 |
+
file,
|
245 |
+
}),
|
246 |
+
});
|
247 |
+
const text = await res.text();
|
248 |
+
if (!res.ok) throw new Error(text || `HTTP error! status: ${res.status}`);
|
249 |
+
setSelectedFile(file);
|
250 |
+
setFileContent(text);
|
251 |
+
setIsEditingFile(true);
|
252 |
+
} catch (err) {
|
253 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
254 |
+
addNotification('Failed to open file: ' + errorMessage, 'error');
|
255 |
+
} finally {
|
256 |
+
setLoading(false);
|
257 |
+
}
|
258 |
+
}
|
259 |
+
|
260 |
+
function closeFileEditor() {
|
261 |
+
setSelectedFile(null);
|
262 |
+
setFileContent('');
|
263 |
+
}
|
264 |
+
|
265 |
+
async function saveFile() {
|
266 |
+
if (!selectedFile()) return;
|
267 |
+
setLoading(true);
|
268 |
+
try {
|
269 |
+
const res = await fetch(`${linkManager}/save`, {
|
270 |
+
method: 'POST',
|
271 |
+
headers: {
|
272 |
+
'Content-Type': 'application/json',
|
273 |
+
},
|
274 |
+
body: JSON.stringify({
|
275 |
+
file: selectedFile(),
|
276 |
+
content: fileContent(),
|
277 |
+
}),
|
278 |
+
});
|
279 |
+
const message = await res.text();
|
280 |
+
if (!res.ok) throw new Error(message || `HTTP error! status: ${res.status}`);
|
281 |
+
addNotification(message, 'success');
|
282 |
+
} catch (err) {
|
283 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
284 |
+
addNotification('Failed to save file: ' + errorMessage, 'error');
|
285 |
+
} finally {
|
286 |
+
setLoading(false);
|
287 |
+
}
|
288 |
+
}
|
289 |
+
|
290 |
+
async function refreshFileSystem(affectedItemPath = '') {
|
291 |
+
let parentPath = '';
|
292 |
+
if (affectedItemPath) {
|
293 |
+
const lastSlashIndex = affectedItemPath.lastIndexOf('/');
|
294 |
+
if (lastSlashIndex !== -1) {
|
295 |
+
parentPath = affectedItemPath.substring(0, lastSlashIndex);
|
296 |
+
}
|
297 |
+
}
|
298 |
+
await fetchFiles();
|
299 |
+
if (parentPath && openFolders()[parentPath]) {
|
300 |
+
await fetchFiles(parentPath);
|
301 |
+
}
|
302 |
+
}
|
303 |
+
|
304 |
+
function fileOrFolderNameIsDirectory(path) {
|
305 |
+
if (openFolders()[path] !== undefined) return true;
|
306 |
+
const checkList = (list, currentBuildPath = '') => {
|
307 |
+
for (const item of list) {
|
308 |
+
const itemFullPath = currentBuildPath ? `${currentBuildPath}/${item.name}` : item.name;
|
309 |
+
if (itemFullPath === path) return item.isDir;
|
310 |
+
if (item.isDir && openFolders()[itemFullPath]) {
|
311 |
+
const foundInSub = checkList(openFolders()[itemFullPath], itemFullPath);
|
312 |
+
if (foundInSub !== undefined) return foundInSub;
|
313 |
+
}
|
314 |
+
}
|
315 |
+
return undefined;
|
316 |
+
};
|
317 |
+
return checkList(files()) || false;
|
318 |
+
}
|
319 |
+
|
320 |
+
async function createFile() {
|
321 |
+
const name = newFileName().trim();
|
322 |
+
if (!name) {
|
323 |
+
addNotification('Please enter a file name.', 'error');
|
324 |
+
return;
|
325 |
+
}
|
326 |
+
setLoading(true);
|
327 |
+
try {
|
328 |
+
const res = await fetch(`${linkManager}/create`, {
|
329 |
+
method: 'POST',
|
330 |
+
headers: { 'Content-Type': 'application/json' },
|
331 |
+
body: JSON.stringify({ file: name }),
|
332 |
+
});
|
333 |
+
const message = await res.text();
|
334 |
+
if (!res.ok) throw new Error(message || `HTTP error! status: ${res.status}`);
|
335 |
+
setNewFileName('');
|
336 |
+
await refreshFileSystem(name);
|
337 |
+
addNotification(`File "${name}" created successfully.`, 'success');
|
338 |
+
} catch (err) {
|
339 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
340 |
+
addNotification('Failed to create file: ' + errorMessage, 'error');
|
341 |
+
} finally {
|
342 |
+
setLoading(false);
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
async function createFolder() {
|
347 |
+
const name = newFolderName().trim();
|
348 |
+
if (!name) {
|
349 |
+
addNotification('Please enter a folder name.', 'error');
|
350 |
+
return;
|
351 |
+
}
|
352 |
+
setLoading(true);
|
353 |
+
try {
|
354 |
+
const res = await fetch(`${linkManager}/create-folder`, {
|
355 |
+
method: 'POST',
|
356 |
+
headers: { 'Content-Type': 'application/json' },
|
357 |
+
body: JSON.stringify({ folder: name }),
|
358 |
+
});
|
359 |
+
const message = await res.text();
|
360 |
+
if (!res.ok) throw new Error(message || `HTTP error! status: ${res.status}`);
|
361 |
+
setNewFolderName('');
|
362 |
+
await refreshFileSystem(name);
|
363 |
+
addNotification(`Folder "${name}" created successfully.`, 'success');
|
364 |
+
} catch (err) {
|
365 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
366 |
+
addNotification('Failed to create folder: ' + errorMessage, 'error');
|
367 |
+
} finally {
|
368 |
+
setLoading(false);
|
369 |
+
}
|
370 |
+
}
|
371 |
+
|
372 |
+
async function uploadFile(e) {
|
373 |
+
const fileToUpload = e.target.files[0];
|
374 |
+
if (!fileToUpload) return;
|
375 |
+
const targetPathForUpload = fileToUpload.name;
|
376 |
+
const form = new FormData();
|
377 |
+
form.append('file', fileToUpload);
|
378 |
+
setLoading(true);
|
379 |
+
try {
|
380 |
+
const res = await fetch(`${linkManager}/upload`, {
|
381 |
+
method: 'POST',
|
382 |
+
body: form,
|
383 |
+
});
|
384 |
+
const message = await res.text();
|
385 |
+
if (!res.ok) throw new Error(message || `HTTP error! status: ${res.status}`);
|
386 |
+
await refreshFileSystem(targetPathForUpload);
|
387 |
+
addNotification(`File "${fileToUpload.name}" uploaded successfully.`, 'success');
|
388 |
+
} catch (err) {
|
389 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
390 |
+
addNotification('Failed to upload file: ' + errorMessage, 'error');
|
391 |
+
} finally {
|
392 |
+
setLoading(false);
|
393 |
+
e.target.value = null;
|
394 |
+
}
|
395 |
+
}
|
396 |
+
|
397 |
+
function download(file) {
|
398 |
+
const form = document.createElement('form');
|
399 |
+
form.method = 'POST';
|
400 |
+
form.action = `${linkManager}/download`;
|
401 |
+
form.style.display = 'none';
|
402 |
+
const input = document.createElement('input');
|
403 |
+
input.name = 'file';
|
404 |
+
input.value = file;
|
405 |
+
input.type = 'hidden';
|
406 |
+
form.appendChild(input);
|
407 |
+
document.body.appendChild(form);
|
408 |
+
form.submit();
|
409 |
+
document.body.removeChild(form);
|
410 |
+
addNotification(`Downloading "${file}"...`, 'info');
|
411 |
+
}
|
412 |
+
|
413 |
+
function toggleFolder(folderPath) {
|
414 |
+
if (openFolders()[folderPath]) {
|
415 |
+
setOpenFolders((prev) => {
|
416 |
+
const updated = { ...prev };
|
417 |
+
delete updated[folderPath];
|
418 |
+
Object.keys(updated).forEach(key => {
|
419 |
+
if (key.startsWith(folderPath + '/')) {
|
420 |
+
delete updated[key];
|
421 |
+
}
|
422 |
+
});
|
423 |
+
return updated;
|
424 |
+
});
|
425 |
+
} else {
|
426 |
+
fetchFiles(folderPath);
|
427 |
+
}
|
428 |
+
}
|
429 |
+
|
430 |
+
function handleFileClick(file, fullPath) {
|
431 |
+
if (file.isDir) {
|
432 |
+
toggleFolder(fullPath);
|
433 |
+
} else {
|
434 |
+
openFile(fullPath);
|
435 |
+
}
|
436 |
+
}
|
437 |
+
|
438 |
+
function handleContextMenu(e, file, fullPath) {
|
439 |
+
e.preventDefault();
|
440 |
+
e.stopPropagation();
|
441 |
+
setContextMenu({
|
442 |
+
visible: true,
|
443 |
+
x: e.clientX,
|
444 |
+
y: e.clientY,
|
445 |
+
file: { ...file, path: fullPath },
|
446 |
+
});
|
447 |
+
}
|
448 |
+
|
449 |
+
function handleOpenFolderFromContextMenu() {
|
450 |
+
const folderToOpen = contextMenu().file;
|
451 |
+
if (folderToOpen && folderToOpen.isDir) {
|
452 |
+
if (!openFolders()[folderToOpen.path]) {
|
453 |
+
fetchFiles(folderToOpen.path);
|
454 |
+
}
|
455 |
+
}
|
456 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
457 |
+
}
|
458 |
+
|
459 |
+
function handleDownloadSelected() {
|
460 |
+
if (contextMenu().file && !contextMenu().file.isDir) {
|
461 |
+
download(contextMenu().file.path);
|
462 |
+
}
|
463 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
464 |
+
}
|
465 |
+
|
466 |
+
async function handleUnzipSelected() {
|
467 |
+
const fileToUnzip = contextMenu().file;
|
468 |
+
if (!fileToUnzip || fileToUnzip.isDir || !fileToUnzip.name.toLowerCase().endsWith('.zip')) {
|
469 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
470 |
+
return;
|
471 |
+
}
|
472 |
+
|
473 |
+
const zipFilePath = fileToUnzip.path;
|
474 |
+
setLoading(true);
|
475 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
476 |
+
|
477 |
+
try {
|
478 |
+
const res = await fetch(`${linkManager}/unzip`, {
|
479 |
+
method: 'POST',
|
480 |
+
headers: { 'Content-Type': 'application/json' },
|
481 |
+
body: JSON.stringify({
|
482 |
+
zipFilePath: zipFilePath,
|
483 |
+
overwrite: true,
|
484 |
+
destinationPath: '',
|
485 |
+
}),
|
486 |
+
});
|
487 |
+
const message = await res.text();
|
488 |
+
if (!res.ok) {
|
489 |
+
let errorMsg = message;
|
490 |
+
try {
|
491 |
+
const errData = JSON.parse(message);
|
492 |
+
errorMsg = errData.message || errData.error || message;
|
493 |
+
} catch (e) { }
|
494 |
+
throw new Error(errorMsg || `HTTP error! status: ${res.status}`);
|
495 |
+
}
|
496 |
+
addNotification(message, 'success');
|
497 |
+
await refreshFileSystem(zipFilePath);
|
498 |
+
|
499 |
+
} catch (err) {
|
500 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
501 |
+
addNotification(`Failed to unzip "${fileToUnzip.name}": ${errorMessage}`, 'error');
|
502 |
+
} finally {
|
503 |
+
setLoading(false);
|
504 |
+
}
|
505 |
+
}
|
506 |
+
|
507 |
+
function handleRenameClick() {
|
508 |
+
if (contextMenu().file) {
|
509 |
+
setRenameContainerInfo({
|
510 |
+
visible: true,
|
511 |
+
file: contextMenu().file,
|
512 |
+
newName: contextMenu().file.name,
|
513 |
+
});
|
514 |
+
}
|
515 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
516 |
+
}
|
517 |
+
|
518 |
+
async function handleDeleteSelected() {
|
519 |
+
const fileToDelete = contextMenu().file;
|
520 |
+
if (!fileToDelete) return;
|
521 |
+
|
522 |
+
const confirmation = window.confirm(`Are you sure you want to delete "${fileToDelete.name}"? This action cannot be undone.`);
|
523 |
+
if (!confirmation) {
|
524 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
525 |
+
return;
|
526 |
+
}
|
527 |
+
|
528 |
+
setLoading(true);
|
529 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
530 |
+
|
531 |
+
try {
|
532 |
+
const res = await fetch(`${linkManager}/delete`, {
|
533 |
+
method: 'POST',
|
534 |
+
headers: { 'Content-Type': 'application/json' },
|
535 |
+
body: JSON.stringify({ path: fileToDelete.path }),
|
536 |
+
});
|
537 |
+
const message = await res.text();
|
538 |
+
if (!res.ok) {
|
539 |
+
let errorMsg = message;
|
540 |
+
try {
|
541 |
+
const errData = JSON.parse(message);
|
542 |
+
errorMsg = errData.message || errData.error || message;
|
543 |
+
} catch (e) { }
|
544 |
+
throw new Error(errorMsg || `HTTP error! status: ${res.status}`);
|
545 |
+
}
|
546 |
+
addNotification(message || `Successfully deleted "${fileToDelete.name}".`, 'success');
|
547 |
+
|
548 |
+
if (selectedFile() && selectedFile().startsWith(fileToDelete.path)) {
|
549 |
+
closeFileEditor();
|
550 |
+
}
|
551 |
+
if (fileToDelete.isDir) {
|
552 |
+
setOpenFolders((prev) => {
|
553 |
+
const updated = { ...prev };
|
554 |
+
delete updated[fileToDelete.path];
|
555 |
+
Object.keys(updated).forEach(key => {
|
556 |
+
if (key.startsWith(fileToDelete.path + '/')) {
|
557 |
+
delete updated[key];
|
558 |
+
}
|
559 |
+
});
|
560 |
+
return updated;
|
561 |
+
});
|
562 |
+
}
|
563 |
+
await refreshFileSystem(fileToDelete.path);
|
564 |
+
} catch (err) {
|
565 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
566 |
+
addNotification(`Failed to delete "${fileToDelete.name}": ${errorMessage}`, 'error');
|
567 |
+
} finally {
|
568 |
+
setLoading(false);
|
569 |
+
}
|
570 |
+
}
|
571 |
+
|
572 |
+
function cancelRename() {
|
573 |
+
setRenameContainerInfo({ visible: false, file: null, newName: '' });
|
574 |
+
}
|
575 |
+
|
576 |
+
async function performRename() {
|
577 |
+
const fileToRename = renameContainerInfo().file;
|
578 |
+
const newName = renameContainerInfo().newName.trim();
|
579 |
+
|
580 |
+
if (!fileToRename || !newName) {
|
581 |
+
addNotification('Invalid rename operation. New name cannot be empty.', 'error');
|
582 |
+
cancelRename();
|
583 |
+
return;
|
584 |
+
}
|
585 |
+
setLoading(true);
|
586 |
+
try {
|
587 |
+
const oldPath = fileToRename.path;
|
588 |
+
const parentPath = oldPath.substring(0, oldPath.lastIndexOf('/'));
|
589 |
+
const newPath = parentPath ? `${parentPath}/${newName}` : newName;
|
590 |
+
|
591 |
+
if (oldPath === newPath) {
|
592 |
+
addNotification('No change detected. Renaming cancelled.', 'info');
|
593 |
+
cancelRename();
|
594 |
+
setLoading(false);
|
595 |
+
return;
|
596 |
+
}
|
597 |
+
|
598 |
+
const res = await fetch(`${linkManager}/rename`, {
|
599 |
+
method: 'POST',
|
600 |
+
headers: { 'Content-Type': 'application/json' },
|
601 |
+
body: JSON.stringify({ oldPath, newPath }),
|
602 |
+
});
|
603 |
+
const message = await res.text();
|
604 |
+
if (!res.ok) {
|
605 |
+
let errorMsg = message;
|
606 |
+
try {
|
607 |
+
const errData = JSON.parse(message);
|
608 |
+
errorMsg = errData.message || errData.error || message;
|
609 |
+
} catch (e) { }
|
610 |
+
throw new Error(errorMsg || `HTTP error! status: ${res.status}`);
|
611 |
+
}
|
612 |
+
addNotification(`Renamed "${fileToRename.name}" to "${newName}" successfully.`, 'success');
|
613 |
+
|
614 |
+
if (fileToRename.isDir && openFolders()[oldPath]) {
|
615 |
+
const contents = openFolders()[oldPath];
|
616 |
+
setOpenFolders((prev) => {
|
617 |
+
const updated = { ...prev };
|
618 |
+
delete updated[oldPath];
|
619 |
+
updated[newPath] = contents;
|
620 |
+
Object.keys(updated).forEach(key => {
|
621 |
+
if (key.startsWith(oldPath + '/')) {
|
622 |
+
const subPath = key.substring(oldPath.length);
|
623 |
+
const oldSubOpenFolderContent = updated[key];
|
624 |
+
delete updated[key];
|
625 |
+
updated[newPath + subPath] = oldSubOpenFolderContent;
|
626 |
+
}
|
627 |
+
});
|
628 |
+
return updated;
|
629 |
+
});
|
630 |
+
}
|
631 |
+
|
632 |
+
if (selectedFile() === oldPath) {
|
633 |
+
setSelectedFile(newPath);
|
634 |
+
}
|
635 |
+
|
636 |
+
await refreshFileSystem(newPath);
|
637 |
+
cancelRename();
|
638 |
+
|
639 |
+
} catch (err) {
|
640 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
641 |
+
addNotification('Failed to rename: ' + errorMessage, 'error');
|
642 |
+
} finally {
|
643 |
+
setLoading(false);
|
644 |
+
}
|
645 |
+
}
|
646 |
+
|
647 |
+
function handleShowCreateItemModal(isDirContext) {
|
648 |
+
const contextFile = contextMenu().file;
|
649 |
+
let parentPathTarget = '';
|
650 |
+
|
651 |
+
if (contextFile) {
|
652 |
+
if (contextFile.isDir) {
|
653 |
+
parentPathTarget = contextFile.path;
|
654 |
+
} else {
|
655 |
+
const lastSlash = contextFile.path.lastIndexOf('/');
|
656 |
+
parentPathTarget = lastSlash === -1 ? '' : contextFile.path.substring(0, lastSlash);
|
657 |
+
}
|
658 |
+
}
|
659 |
+
|
660 |
+
setCreateItemModalInfo({
|
661 |
+
visible: true,
|
662 |
+
parentPath: parentPathTarget,
|
663 |
+
isDir: isDirContext,
|
664 |
+
itemName: '',
|
665 |
+
});
|
666 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
667 |
+
}
|
668 |
+
|
669 |
+
function cancelCreateItem() {
|
670 |
+
setCreateItemModalInfo({ visible: false, parentPath: null, isDir: false, itemName: '' });
|
671 |
+
}
|
672 |
+
|
673 |
+
async function performCreateItem() {
|
674 |
+
const { parentPath, itemName, isDir } = createItemModalInfo();
|
675 |
+
const newItemNameTrimmed = itemName.trim();
|
676 |
+
|
677 |
+
if (!newItemNameTrimmed) {
|
678 |
+
addNotification(`Please enter a ${isDir ? 'folder' : 'file'} name.`, 'error');
|
679 |
+
return;
|
680 |
+
}
|
681 |
+
const fullPath = parentPath ? `${parentPath}/${newItemNameTrimmed}` : newItemNameTrimmed;
|
682 |
+
setLoading(true);
|
683 |
+
try {
|
684 |
+
const endpoint = isDir ? `${linkManager}/create-folder` : `${linkManager}/create`;
|
685 |
+
const payload = isDir ? { folder: fullPath } : { file: fullPath };
|
686 |
+
const res = await fetch(endpoint, {
|
687 |
+
method: 'POST',
|
688 |
+
headers: { 'Content-Type': 'application/json' },
|
689 |
+
body: JSON.stringify(payload),
|
690 |
+
});
|
691 |
+
const message = await res.text();
|
692 |
+
if (!res.ok) {
|
693 |
+
let errorMsg = message;
|
694 |
+
try {
|
695 |
+
const errData = JSON.parse(message);
|
696 |
+
errorMsg = errData.message || errData.error || message;
|
697 |
+
} catch (e) { }
|
698 |
+
throw new Error(errorMsg || `HTTP error! status: ${res.status}`);
|
699 |
+
}
|
700 |
+
addNotification(`${isDir ? 'Folder' : 'File'} "${newItemNameTrimmed}" created successfully in "${parentPath || 'root'}".`, 'success');
|
701 |
+
cancelCreateItem();
|
702 |
+
await refreshFileSystem(fullPath);
|
703 |
+
if (parentPath) {
|
704 |
+
await fetchFiles(parentPath);
|
705 |
+
}
|
706 |
+
} catch (err) {
|
707 |
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
708 |
+
addNotification(`Failed to create ${isDir ? 'folder' : 'file'}: ${errorMessage}`, 'error');
|
709 |
+
} finally {
|
710 |
+
setLoading(false);
|
711 |
+
}
|
712 |
+
}
|
713 |
+
|
714 |
+
function getFileIconPath(fileItem, isFolderOpen) {
|
715 |
+
const baseIconPath = './icons/';
|
716 |
+
const nameLower = fileItem.name.toLowerCase();
|
717 |
+
if (fileItem.isDir) {
|
718 |
+
if (nameLower === '.git') {
|
719 |
+
return `${baseIconPath}git.svg`;
|
720 |
+
}
|
721 |
+
return isFolderOpen ? `${baseIconPath}folder-open.svg` : `${baseIconPath}folder.svg`;
|
722 |
+
}
|
723 |
+
if (nameLower === 'exocore.run') { return `${baseIconPath}exocore.run.svg`; }
|
724 |
+
if (nameLower === '.gitignore' || nameLower === '.gitattributes' || nameLower === '.gitmodules') {
|
725 |
+
return `${baseIconPath}git.svg`;
|
726 |
+
}
|
727 |
+
const parts = nameLower.split('.');
|
728 |
+
let extension = '';
|
729 |
+
if (parts.length > 1) {
|
730 |
+
const potentialExtension = parts.pop();
|
731 |
+
if (parts[0] !== '' || parts.length > 0) {
|
732 |
+
if (potentialExtension !== undefined) {
|
733 |
+
extension = potentialExtension;
|
734 |
+
}
|
735 |
+
} else if (potentialExtension !== undefined) {
|
736 |
+
extension = potentialExtension;
|
737 |
+
}
|
738 |
+
}
|
739 |
+
switch (extension) {
|
740 |
+
case 'js': return `${baseIconPath}js.svg`;
|
741 |
+
case 'jsx': return `${baseIconPath}jsx.svg`;
|
742 |
+
case 'ts': return `${baseIconPath}ts.svg`;
|
743 |
+
case 'tsx': return `${baseIconPath}tsx.svg`;
|
744 |
+
case 'json': return `${baseIconPath}json.svg`;
|
745 |
+
case 'xml': return `${baseIconPath}xml.svg`;
|
746 |
+
case 'html': return `${baseIconPath}html.svg`;
|
747 |
+
case 'css': return `${baseIconPath}css.svg`;
|
748 |
+
case 'md': return `${baseIconPath}md.svg`;
|
749 |
+
case 'sh': return `${baseIconPath}sh.svg`;
|
750 |
+
case 'sql': return `${baseIconPath}sql.svg`;
|
751 |
+
case 'zip': return `${baseIconPath}zip.svg`;
|
752 |
+
case 'gif': return `${baseIconPath}gifImage.svg`;
|
753 |
+
case 'jpg':
|
754 |
+
case 'jpeg':
|
755 |
+
case 'png':
|
756 |
+
return `${baseIconPath}image.svg`;
|
757 |
+
case 'mp4':
|
758 |
+
case 'mov':
|
759 |
+
case 'avi':
|
760 |
+
case 'mkv':
|
761 |
+
case 'webm':
|
762 |
+
case 'flv':
|
763 |
+
case 'wmv':
|
764 |
+
return `${baseIconPath}video.svg`;
|
765 |
+
case 'git':
|
766 |
+
return `${baseIconPath}git.svg`;
|
767 |
+
default:
|
768 |
+
return `${baseIconPath}undefined.svg`;
|
769 |
+
}
|
770 |
+
}
|
771 |
+
|
772 |
+
function renderFiles(list, parentPath = '') {
|
773 |
+
return (
|
774 |
+
<ul style={{ 'margin-left': '1rem', 'padding-left': '0', 'list-style-type': 'none' }}>
|
775 |
+
<For each={list}>
|
776 |
+
{(file) => {
|
777 |
+
const fullPath = parentPath ? `${parentPath}/${file.name}` : file.name;
|
778 |
+
const isDirOpen = file.isDir && openFolders()[fullPath];
|
779 |
+
const iconPath = getFileIconPath(file, isDirOpen);
|
780 |
+
let listItemRef;
|
781 |
+
const baseItemStyle = {
|
782 |
+
'user-select': 'none',
|
783 |
+
padding: '0.2rem 0.1rem',
|
784 |
+
'border-radius': theme.borderRadius,
|
785 |
+
transition: 'background-color 0.2s',
|
786 |
+
'margin-bottom': '2px',
|
787 |
+
};
|
788 |
+
|
789 |
+
return (
|
790 |
+
<li
|
791 |
+
ref={listItemRef}
|
792 |
+
style={baseItemStyle}
|
793 |
+
onMouseEnter={() => { if (listItemRef) listItemRef.style.backgroundColor = theme.itemHoverBg; }}
|
794 |
+
onMouseLeave={() => { if (listItemRef) listItemRef.style.backgroundColor = 'transparent'; }}
|
795 |
+
title={fullPath}
|
796 |
+
>
|
797 |
+
<div style={{ display: 'flex', 'align-items': 'center', 'justify-content': 'space-between' }}>
|
798 |
+
<div
|
799 |
+
onClick={() => handleFileClick(file, fullPath)}
|
800 |
+
style={{ flexGrow: 1, display: 'flex', 'align-items': 'center', cursor: 'pointer', padding: '0.3rem 0.2rem' }}
|
801 |
+
>
|
802 |
+
<img src={iconPath} alt={file.isDir ? 'Folder' : 'File'} style={{ width: '18px', height: '18px', 'margin-right': '0.75rem', 'flex-shrink': 0 }} />
|
803 |
+
<span style={{ color: theme.text, 'font-size': '1.05rem' }}>{file.name}</span>
|
804 |
+
</div>
|
805 |
+
<span
|
806 |
+
onClick={(e) => handleContextMenu(e, file, fullPath)}
|
807 |
+
style={{ cursor: 'pointer', 'font-weight': 'bold', padding: '0 0.5rem', color: theme.textMuted, 'font-size': '1.2rem' }}
|
808 |
+
onMouseEnter={(e) => e.target.style.color = theme.primary}
|
809 |
+
onMouseLeave={(e) => e.target.style.color = theme.textMuted}
|
810 |
+
> ⋮ </span>
|
811 |
+
</div>
|
812 |
+
<Show when={file.isDir && openFolders()[fullPath] && Array.isArray(openFolders()[fullPath]) && openFolders()[fullPath].length > 0}>
|
813 |
+
{renderFiles(openFolders()[fullPath], fullPath)}
|
814 |
+
</Show>
|
815 |
+
<Show when={file.isDir && openFolders()[fullPath] && Array.isArray(openFolders()[fullPath]) && openFolders()[fullPath].length === 0}>
|
816 |
+
<div style={{ 'margin-left': '2rem', padding: '0.3rem 0', color: theme.textMuted, 'font-style': 'italic', 'font-size': '0.9rem' }}>(empty folder)</div>
|
817 |
+
</Show>
|
818 |
+
</li>
|
819 |
+
);
|
820 |
+
}}
|
821 |
+
</For>
|
822 |
+
</ul>
|
823 |
+
);
|
824 |
+
}
|
825 |
+
|
826 |
+
function handleDownloadAll() {
|
827 |
+
const form = document.createElement('form');
|
828 |
+
form.method = 'POST';
|
829 |
+
form.action = `${linkManager}/download-zip`;
|
830 |
+
form.style.display = 'none';
|
831 |
+
document.body.appendChild(form);
|
832 |
+
form.submit();
|
833 |
+
document.body.removeChild(form);
|
834 |
+
addNotification('Downloading all files (root) as ZIP...', 'info');
|
835 |
+
}
|
836 |
+
|
837 |
+
const getCodeMirrorLanguageSupport = (filename) => {
|
838 |
+
const extension = filename?.split('.').pop()?.toLowerCase();
|
839 |
+
if (!extension) return javascript();
|
840 |
+
switch (extension) {
|
841 |
+
case 'js': case 'jsx': return javascript();
|
842 |
+
case 'ts': case 'tsx': return javascript({typescript: true, jsx: true});
|
843 |
+
case 'json': return json();
|
844 |
+
case 'html': case 'htm': case 'xml': case 'svg': return html();
|
845 |
+
case 'css': return css();
|
846 |
+
case 'md': case 'markdown': return markdown();
|
847 |
+
default: return javascript();
|
848 |
+
}
|
849 |
+
};
|
850 |
+
|
851 |
+
onMount(() => {
|
852 |
+
const patrickHandFontLink = document.createElement('link');
|
853 |
+
patrickHandFontLink.href = 'https://fonts.googleapis.com/css2?family=Patrick+Hand&display=swap';
|
854 |
+
patrickHandFontLink.rel = 'stylesheet';
|
855 |
+
document.head.appendChild(patrickHandFontLink);
|
856 |
+
|
857 |
+
const firaCodeFontLink = document.createElement('link');
|
858 |
+
firaCodeFontLink.href = 'https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&display=swap';
|
859 |
+
firaCodeFontLink.rel = 'stylesheet';
|
860 |
+
document.head.appendChild(firaCodeFontLink);
|
861 |
+
|
862 |
+
const hljsThemeLink = document.createElement('link');
|
863 |
+
hljsThemeLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css';
|
864 |
+
hljsThemeLink.rel = 'stylesheet';
|
865 |
+
document.head.appendChild(hljsThemeLink);
|
866 |
+
|
867 |
+
const appElement = document.getElementById('app');
|
868 |
+
if (appElement) {
|
869 |
+
appElement.style.fontFamily = theme.fontFamily;
|
870 |
+
appElement.style.minHeight = '100vh';
|
871 |
+
}
|
872 |
+
|
873 |
+
fetchUserInfo();
|
874 |
+
|
875 |
+
const handleClickOutside = (e) => {
|
876 |
+
const contextMenuElement = document.getElementById('context-menu');
|
877 |
+
const createItemModalOverlayElement = document.querySelector('.create-item-modal-overlay');
|
878 |
+
const renameModalOverlayElement = document.querySelector('.rename-modal-overlay');
|
879 |
+
|
880 |
+
if (contextMenu().visible && contextMenuElement && !contextMenuElement.contains(e.target)) {
|
881 |
+
setContextMenu({ visible: false, x: 0, y: 0, file: null });
|
882 |
+
}
|
883 |
+
if (createItemModalInfo().visible && createItemModalOverlayElement && e.target === createItemModalOverlayElement) {
|
884 |
+
cancelCreateItem();
|
885 |
+
}
|
886 |
+
if (renameContainerInfo().visible && renameModalOverlayElement && e.target === renameModalOverlayElement) {
|
887 |
+
cancelRename();
|
888 |
+
}
|
889 |
+
};
|
890 |
+
document.addEventListener('click', handleClickOutside);
|
891 |
+
|
892 |
+
const checkMobile = () => setIsMobileView(window.innerWidth < 768);
|
893 |
+
checkMobile();
|
894 |
+
window.addEventListener('resize', checkMobile);
|
895 |
+
|
896 |
+
onCleanup(() => {
|
897 |
+
window.removeEventListener('resize', checkMobile);
|
898 |
+
document.removeEventListener('click', handleClickOutside);
|
899 |
+
if (editorViewInstance) {
|
900 |
+
editorViewInstance.destroy();
|
901 |
+
editorViewInstance = null;
|
902 |
+
}
|
903 |
+
});
|
904 |
+
});
|
905 |
+
|
906 |
+
createEffect(() => {
|
907 |
+
const currentFile = selectedFile();
|
908 |
+
const editing = isEditingFile();
|
909 |
+
const content = fileContent();
|
910 |
+
|
911 |
+
if (editorRef && editing && currentFile) {
|
912 |
+
const cmLanguageSupport = getCodeMirrorLanguageSupport(currentFile);
|
913 |
+
if (editorViewInstance) {
|
914 |
+
if (editorViewInstance.state.doc.toString() !== content) {
|
915 |
+
editorViewInstance.dispatch({
|
916 |
+
changes: { from: 0, to: editorViewInstance.state.doc.length, insert: content || '' }
|
917 |
+
});
|
918 |
+
}
|
919 |
+
editorViewInstance.dispatch({
|
920 |
+
effects: [
|
921 |
+
languageCompartment.reconfigure(cmLanguageSupport),
|
922 |
+
editableCompartment.reconfigure(EditorView.editable.of(true)),
|
923 |
+
]
|
924 |
+
});
|
925 |
+
} else {
|
926 |
+
const state = EditorState.create({
|
927 |
+
doc: content || '',
|
928 |
+
extensions: [
|
929 |
+
EditorView.lineWrapping,
|
930 |
+
history(),
|
931 |
+
keymap.of([...defaultKeymap, ...historyKeymap, ...foldKeymap]),
|
932 |
+
lineNumbers(),
|
933 |
+
foldGutter(),
|
934 |
+
lintGutter(),
|
935 |
+
editableCompartment.of(EditorView.editable.of(true)),
|
936 |
+
languageCompartment.of(cmLanguageSupport),
|
937 |
+
themeCompartment.of(oneDark),
|
938 |
+
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
939 |
+
EditorView.theme({
|
940 |
+
'&': { fontSize: '12px' },
|
941 |
+
'.cm-content': { fontFamily: theme.monospaceFontFamily },
|
942 |
+
'.cm-gutters': { fontSize: '13px', backgroundColor: '#282c34' },
|
943 |
+
'.cm-lineNumbers .cm-gutterElement': { padding: '0 3px 0 5px', minWidth: '20px', textAlign: 'right' }
|
944 |
+
}),
|
945 |
+
EditorView.updateListener.of(update => {
|
946 |
+
if (update.docChanged) {
|
947 |
+
if (update.transactions.some(tr => tr.isUserEvent('input') || tr.isUserEvent('delete'))) {
|
948 |
+
setFileContent(update.state.doc.toString());
|
949 |
+
}
|
950 |
+
}
|
951 |
+
})
|
952 |
+
]
|
953 |
+
});
|
954 |
+
editorViewInstance = new EditorView({ state, parent: editorRef });
|
955 |
+
}
|
956 |
+
} else if (editorViewInstance) {
|
957 |
+
editorViewInstance.destroy();
|
958 |
+
editorViewInstance = null;
|
959 |
+
}
|
960 |
+
});
|
961 |
+
|
962 |
+
let hasFocusedRenameInput = false;
|
963 |
+
createEffect(() => {
|
964 |
+
if (renameContainerInfo().visible && renameInputRef && !hasFocusedRenameInput) {
|
965 |
+
setTimeout(() => {
|
966 |
+
if (renameInputRef) {
|
967 |
+
renameInputRef.focus();
|
968 |
+
renameInputRef.select();
|
969 |
+
}
|
970 |
+
hasFocusedRenameInput = true;
|
971 |
+
}, 50);
|
972 |
+
} else if (!renameContainerInfo().visible) {
|
973 |
+
hasFocusedRenameInput = false;
|
974 |
+
}
|
975 |
+
});
|
976 |
+
|
977 |
+
let hasFocusedCreateItemInput = false;
|
978 |
+
createEffect(() => {
|
979 |
+
if (createItemModalInfo().visible && createItemInputRef && !hasFocusedCreateItemInput) {
|
980 |
+
setTimeout(() => {
|
981 |
+
if (createItemInputRef) {
|
982 |
+
createItemInputRef.focus();
|
983 |
+
}
|
984 |
+
hasFocusedCreateItemInput = true;
|
985 |
+
}, 50);
|
986 |
+
} else if (!createItemModalInfo().visible) {
|
987 |
+
hasFocusedCreateItemInput = false;
|
988 |
+
}
|
989 |
+
});
|
990 |
+
|
991 |
+
const theme = {
|
992 |
+
bg: '#0F172A',
|
993 |
+
panelBg: '#1E293B',
|
994 |
+
border: '#334155',
|
995 |
+
text: '#E2E8F0',
|
996 |
+
textMuted: '#94A3B8',
|
997 |
+
primary: '#38BDF8',
|
998 |
+
primaryHover: '#0EA5E9',
|
999 |
+
primaryText: '#0F172A',
|
1000 |
+
secondary: '#FACC15',
|
1001 |
+
secondaryHover: '#EAB308',
|
1002 |
+
secondaryText: '#1E293B',
|
1003 |
+
destructive: '#F43F5E',
|
1004 |
+
destructiveHover: '#E11D48',
|
1005 |
+
destructiveText: '#E2E8F0',
|
1006 |
+
inputBg: '#0A0F1A',
|
1007 |
+
inputBorder: '#334155',
|
1008 |
+
inputFocusBorder: '#38BDF8',
|
1009 |
+
fontFamily: "'Patrick Hand', cursive",
|
1010 |
+
monospaceFontFamily: "'Fira Code', 'Source Code Pro', monospace",
|
1011 |
+
borderRadius: '6px',
|
1012 |
+
itemHoverBg: 'rgba(51, 65, 85, 0.7)',
|
1013 |
+
shadow: '0 6px 16px rgba(0, 0, 0, 0.4)',
|
1014 |
+
itemSelectedBg: '#38BDF8',
|
1015 |
+
notificationSuccess: '#10B981',
|
1016 |
+
notificationError: '#F43F5E',
|
1017 |
+
notificationInfo: '#38BDF8',
|
1018 |
+
};
|
1019 |
+
|
1020 |
+
const NotificationContainer = () => {
|
1021 |
+
const baseStyle = {
|
1022 |
+
padding: '1rem 1.5rem',
|
1023 |
+
'margin-bottom': '0.75rem',
|
1024 |
+
'border-radius': theme.borderRadius,
|
1025 |
+
color: 'white',
|
1026 |
+
'font-size': '1.05rem',
|
1027 |
+
'box-shadow': '0 4px 10px rgba(0,0,0,0.3)',
|
1028 |
+
'font-family': theme.fontFamily,
|
1029 |
+
'letter-spacing': '0.5px',
|
1030 |
+
transition: 'transform 0.3s ease-out, opacity 0.3s ease-out',
|
1031 |
+
transform: 'translateX(0)',
|
1032 |
+
opacity: 1,
|
1033 |
+
};
|
1034 |
+
|
1035 |
+
const typeStyles = {
|
1036 |
+
success: { 'background-color': theme.notificationSuccess },
|
1037 |
+
error: { 'background-color': theme.notificationError },
|
1038 |
+
info: { 'background-color': theme.notificationInfo, color: theme.primaryText },
|
1039 |
+
};
|
1040 |
+
|
1041 |
+
return (
|
1042 |
+
<div style={{ position: 'fixed', top: '20px', right: '20px', 'z-index': '2000', width: '350px', 'max-width': '90%' }}>
|
1043 |
+
<For each={notifications()}>
|
1044 |
+
{notification => (
|
1045 |
+
<div style={{ ...baseStyle, ...typeStyles[notification.type] }}>
|
1046 |
+
{notification.message}
|
1047 |
+
</div>
|
1048 |
+
)}
|
1049 |
+
</For>
|
1050 |
+
</div>
|
1051 |
+
);
|
1052 |
+
};
|
1053 |
+
|
1054 |
+
const baseButtonStyle = {
|
1055 |
+
padding: '0.6rem 1.2rem',
|
1056 |
+
'font-size': '1.1rem',
|
1057 |
+
border: 'none',
|
1058 |
+
'border-radius': theme.borderRadius,
|
1059 |
+
cursor: 'pointer',
|
1060 |
+
'font-family': theme.fontFamily,
|
1061 |
+
'letter-spacing': '0.5px',
|
1062 |
+
transition: 'background-color 0.2s, transform 0.1s',
|
1063 |
+
'margin-right': '0.5rem',
|
1064 |
+
'line-height': '1.4',
|
1065 |
+
};
|
1066 |
+
|
1067 |
+
const createButtonStyler = (baseColor, hoverColor, textColor) => {
|
1068 |
+
let btnRef;
|
1069 |
+
return {
|
1070 |
+
ref: el => btnRef = el,
|
1071 |
+
style: { ...baseButtonStyle, background: baseColor, color: textColor },
|
1072 |
+
onMouseEnter: () => btnRef && (btnRef.style.backgroundColor = hoverColor),
|
1073 |
+
onMouseLeave: () => btnRef && (btnRef.style.backgroundColor = baseColor),
|
1074 |
+
};
|
1075 |
+
};
|
1076 |
+
|
1077 |
+
const primaryButtonProps = (text, onClick) => {
|
1078 |
+
const { ref, style, onMouseEnter, onMouseLeave } = createButtonStyler(theme.primary, theme.primaryHover, theme.primaryText);
|
1079 |
+
return <button ref={ref} style={style} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onClick={onClick}>{text}</button>;
|
1080 |
+
};
|
1081 |
+
|
1082 |
+
const secondaryButtonProps = (text, onClick) => {
|
1083 |
+
const { ref, style, onMouseEnter, onMouseLeave } = createButtonStyler(theme.secondary, theme.secondaryHover, theme.secondaryText);
|
1084 |
+
return <button ref={ref} style={style} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onClick={onClick}>{text}</button>;
|
1085 |
+
};
|
1086 |
+
|
1087 |
+
const destructiveButtonProps = (text, onClick) => {
|
1088 |
+
const { ref, style, onMouseEnter, onMouseLeave } = createButtonStyler(theme.destructive, theme.destructiveHover, theme.destructiveText);
|
1089 |
+
return <button ref={ref} style={style} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onClick={onClick}>{text}</button>;
|
1090 |
+
};
|
1091 |
+
|
1092 |
+
const defaultButtonProps = (text, onClick, additionalStyles = {}) => {
|
1093 |
+
const { ref, style, onMouseEnter, onMouseLeave } = createButtonStyler(theme.panelBg, theme.border, theme.textMuted);
|
1094 |
+
return <button ref={ref} style={{...style, border: `1px solid ${theme.border}`, ...additionalStyles}} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onClick={onClick}>{text}</button>;
|
1095 |
+
};
|
1096 |
+
|
1097 |
+
const iconButtonStyler = (baseColor, hoverColor, textColor) => {
|
1098 |
+
let btnRef;
|
1099 |
+
const iconBaseStyle = { ...baseButtonStyle, padding: '0.5rem 0.7rem', 'font-size': '1.5rem', 'line-height': '1', 'margin-right': '0' };
|
1100 |
+
return {
|
1101 |
+
ref: el => btnRef = el,
|
1102 |
+
style: { ...iconBaseStyle, background: baseColor, color: textColor, border: `1px solid ${theme.border}`},
|
1103 |
+
onMouseEnter: () => btnRef && (btnRef.style.backgroundColor = hoverColor),
|
1104 |
+
onMouseLeave: () => btnRef && (btnRef.style.backgroundColor = baseColor),
|
1105 |
+
};
|
1106 |
+
};
|
1107 |
+
|
1108 |
+
const inputStyle = {
|
1109 |
+
padding: '0.7rem 0.9rem',
|
1110 |
+
'font-size': '1.05rem',
|
1111 |
+
border: `1px solid ${theme.inputBorder}`,
|
1112 |
+
'border-radius': theme.borderRadius,
|
1113 |
+
flex: '1',
|
1114 |
+
'margin-right': '0.5rem',
|
1115 |
+
'font-family': theme.fontFamily,
|
1116 |
+
'background-color': theme.inputBg,
|
1117 |
+
color: theme.text,
|
1118 |
+
outline: 'none',
|
1119 |
+
transition: 'border-color 0.2s, box-shadow 0.2s',
|
1120 |
+
'letter-spacing': '0.5px',
|
1121 |
+
};
|
1122 |
+
|
1123 |
+
const modalInputStyle = {
|
1124 |
+
...inputStyle,
|
1125 |
+
width: 'calc(100% - 22px)',
|
1126 |
+
'margin-bottom': '20px',
|
1127 |
+
'margin-right': '0',
|
1128 |
+
'font-size': '1.1rem',
|
1129 |
+
};
|
1130 |
+
|
1131 |
+
const codeViewerBaseStyle = {
|
1132 |
+
width: '100%',
|
1133 |
+
fontFamily: theme.monospaceFontFamily,
|
1134 |
+
border: `1px solid ${theme.border}`,
|
1135 |
+
padding: '15px',
|
1136 |
+
boxSizing: 'border-box',
|
1137 |
+
flex: '1',
|
1138 |
+
marginBottom: '15px',
|
1139 |
+
minHeight: isMobileView() ? '250px' : '350px',
|
1140 |
+
resize: 'vertical',
|
1141 |
+
overflow: 'auto',
|
1142 |
+
backgroundColor: '#282c34',
|
1143 |
+
color: theme.text,
|
1144 |
+
borderRadius: theme.borderRadius,
|
1145 |
+
fontSize: '12px',
|
1146 |
+
};
|
1147 |
+
|
1148 |
+
const codeMirrorEditorStyle = {
|
1149 |
+
...codeViewerBaseStyle,
|
1150 |
+
padding: '0px',
|
1151 |
+
};
|
1152 |
+
|
1153 |
+
return (
|
1154 |
+
<div style={{ 'font-size': '1.1rem', background: theme.bg, color: theme.text, 'min-height': '100vh', padding: '25px', 'box-sizing': 'border-box' }}>
|
1155 |
+
<NotificationContainer />
|
1156 |
+
<h2 style={{ color: theme.primary, 'font-size': '2.8rem', 'margin-bottom': '25px', 'text-align': 'center', 'letter-spacing': '1px' }}>
|
1157 |
+
📁 ExoCore Explorer 📂
|
1158 |
+
</h2>
|
1159 |
+
|
1160 |
+
<Show when={status()}>
|
1161 |
+
<div class="status-box" style={{ 'background-color': theme.panelBg, border: `1px solid ${theme.border}`, color: theme.text, padding: '12px 18px', 'margin-bottom': '1.5rem', 'border-radius': theme.borderRadius, display: 'flex', 'align-items': 'center', 'justify-content': 'space-between', 'box-shadow': '0 2px 5px rgba(0,0,0,0.2)', 'font-size': '1.05rem' }}>
|
1162 |
+
{status()}
|
1163 |
+
{defaultButtonProps('Clear', () => setStatus(''), { padding: '0.2rem 0.5rem', 'margin-left': '10px', 'font-size': '0.9rem' })}
|
1164 |
+
</div>
|
1165 |
+
</Show>
|
1166 |
+
|
1167 |
+
<Show when={loading() && !(isMobileView() && selectedFile())}>
|
1168 |
+
<div style={{ 'margin-top': '1.5rem', color: theme.textMuted, 'font-size': '1.2rem', 'text-align': 'center' }}>Loading... ⏳ Please wait...</div>
|
1169 |
+
</Show>
|
1170 |
+
|
1171 |
+
<div class="main-content-flex" style={{ display: 'flex', 'margin-top': '1.5rem', gap: '25px', 'flex-wrap': (isMobileView() && selectedFile()) ? 'wrap' : 'nowrap' }}>
|
1172 |
+
<div class="file-list-panel" style={{ ...(isMobileView() && selectedFile() ? {display: 'none'} : {flex: '1'}), border: `1px solid ${theme.border}`, padding: '20px', background: theme.panelBg, 'min-width': '320px', color: theme.text, 'border-radius': theme.borderRadius, 'box-shadow': theme.shadow }}>
|
1173 |
+
<h4 style={{ color: theme.primary, 'font-size': '1.5rem', 'margin-top': '0', 'margin-bottom': '1rem', 'border-bottom': `1px solid ${theme.border}`, 'padding-bottom': '0.5rem' }}>Controls</h4>
|
1174 |
+
<div style={{ 'margin-bottom': '0.8rem', display: 'flex', 'align-items': 'center', gap: '0.5rem' }}>
|
1175 |
+
<input style={inputStyle} placeholder="New file name..." value={newFileName()} onInput={e => setNewFileName(e.target.value)} onKeyPress={e => e.key === 'Enter' && createFile()} onFocus={e => e.target.style.borderColor = theme.inputFocusBorder} onBlur={e => e.target.style.borderColor = theme.inputBorder} />
|
1176 |
+
{(() => {
|
1177 |
+
const { ref, style, onMouseEnter, onMouseLeave } = iconButtonStyler(theme.panelBg, theme.border, theme.primary);
|
1178 |
+
return <button ref={ref} style={style} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onClick={createFile} title="Create File">📄</button>;
|
1179 |
+
})()}
|
1180 |
+
</div>
|
1181 |
+
<div style={{ 'margin-bottom': '0.8rem', display: 'flex', 'align-items': 'center', gap: '0.5rem' }}>
|
1182 |
+
<input style={inputStyle} placeholder="New folder name..." value={newFolderName()} onInput={e => setNewFolderName(e.target.value)} onKeyPress={e => e.key === 'Enter' && createFolder()} onFocus={e => e.target.style.borderColor = theme.inputFocusBorder} onBlur={e => e.target.style.borderColor = theme.inputBorder} />
|
1183 |
+
{(() => {
|
1184 |
+
const { ref, style, onMouseEnter, onMouseLeave } = iconButtonStyler(theme.panelBg, theme.border, theme.primary);
|
1185 |
+
return <button ref={ref} style={style} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onClick={createFolder} title="Create Folder">📁</button>;
|
1186 |
+
})()}
|
1187 |
+
</div>
|
1188 |
+
<div style={{ 'margin-bottom': '1.5rem' }}>
|
1189 |
+
{(() => {
|
1190 |
+
const { ref, style, onMouseEnter, onMouseLeave } = createButtonStyler(theme.primary, theme.primaryHover, theme.primaryText);
|
1191 |
+
return <label for="fileUpload" ref={ref} style={{...style, display: 'inline-block', width: '100%', 'box-sizing': 'border-box', 'text-align': 'center', 'margin-right': 0}} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>📤 Upload File</label>;
|
1192 |
+
})()}
|
1193 |
+
<input id="fileUpload" type="file" onChange={uploadFile} style={{display: 'none'}} />
|
1194 |
+
</div>
|
1195 |
+
|
1196 |
+
<h4 style={{ color: theme.primary, 'font-size': '1.5rem', 'margin-bottom': '1rem', 'border-bottom': `1px solid ${theme.border}`, 'padding-bottom': '0.5rem' }}>File System</h4>
|
1197 |
+
<div style={{ 'max-height': '450px', 'overflow-y': 'auto', border: `1px solid ${theme.border}`, padding: '10px', 'border-radius': theme.borderRadius, background: theme.inputBg }}>
|
1198 |
+
{renderFiles(files())}
|
1199 |
+
</div>
|
1200 |
+
<div style={{'margin-top': '1.5rem'}}>
|
1201 |
+
{secondaryButtonProps('Download All (Root) as ZIP 📦', handleDownloadAll)}
|
1202 |
+
</div>
|
1203 |
+
</div>
|
1204 |
+
|
1205 |
+
<div class="file-editor-panel" style={ isMobileView() && selectedFile() ? { position: 'fixed', top: '0', left: '0', width: '100%', height: '100%', background: 'rgba(15, 23, 42, 0.9)', display: 'flex', 'align-items': 'center', 'justify-content': 'center', 'z-index': '1001', padding: '15px', 'box-sizing': 'border-box' } : { flex: '3.5', 'min-width': '0', display: selectedFile() ? 'flex' : 'block', 'flex-direction': 'column' } }>
|
1206 |
+
<Show when={selectedFile()} fallback={ !isMobileView() || (isMobileView() && !selectedFile()) ? <div style={{ border: `2px dashed ${theme.border}`, padding: '30px', 'text-align': 'center', background: theme.panelBg, color: theme.textMuted, height: '100%', display: 'flex', 'align-items': 'center', 'justify-content': 'center', 'border-radius': theme.borderRadius, 'font-size': '1.3rem', 'box-shadow': theme.shadow }}>Select a file to embark on an editing adventure! 🚀</div> : null }>
|
1207 |
+
<div style={ isMobileView() ? { background: theme.panelBg, padding: '20px', 'border-radius': theme.borderRadius, 'box-shadow': theme.shadow, width: '100%', height: 'auto', 'max-height': 'calc(100vh - 40px)', display: 'flex', 'flex-direction': 'column', 'overflow-y': 'auto', color: theme.text, border: `1px solid ${theme.border}` } : { border: `1px solid ${theme.border}`, padding: '20px', background: theme.panelBg, height: '100%', display: 'flex', 'flex-direction': 'column', color: theme.text, 'border-radius': theme.borderRadius, 'box-shadow': theme.shadow } }>
|
1208 |
+
<h3 style={{ 'margin-top': '0', color: theme.primary, 'font-size': '1.6rem', 'margin-bottom': '1rem', 'word-break': 'break-all' }}>
|
1209 |
+
Now Editing: {selectedFile()}
|
1210 |
+
</h3>
|
1211 |
+
<div ref={el => editorRef = el} style={codeMirrorEditorStyle}></div>
|
1212 |
+
<div style={{ 'text-align': 'right', 'margin-top': '10px', display: 'flex', 'justify-content': 'flex-end', gap: '0.5rem' }}>
|
1213 |
+
{primaryButtonProps('💾 Save', saveFile)}
|
1214 |
+
{destructiveButtonProps('❌ Close', closeFileEditor)}
|
1215 |
+
</div>
|
1216 |
+
</div>
|
1217 |
+
</Show>
|
1218 |
+
</div>
|
1219 |
+
</div>
|
1220 |
+
|
1221 |
+
<Show when={contextMenu().visible}>
|
1222 |
+
<div id="context-menu" style={{ position: 'fixed', top: `${contextMenu().y}px`, left: `${contextMenu().x}px`, background: theme.panelBg, border: `1px solid ${theme.border}`, padding: '0.4rem', 'z-index': '1000', 'box-shadow': '0 5px 15px rgba(0,0,0,0.5)', 'min-width': '170px', 'text-align': 'left', color: theme.text, 'border-radius': theme.borderRadius, transform: contextMenu().x > (window.innerWidth - 200) ? 'translateX(-100%)' : 'none' }}>
|
1223 |
+
{[
|
1224 |
+
{ label: '✏️ Rename', action: handleRenameClick, show: () => true },
|
1225 |
+
{ label: '📂 Open', action: handleOpenFolderFromContextMenu, show: () => contextMenu().file?.isDir },
|
1226 |
+
{ label: '➕📄 Add New File', action: () => handleShowCreateItemModal(false), show: () => contextMenu().file?.isDir || !contextMenu().file },
|
1227 |
+
{ label: '➕📁 Add New Folder', action: () => handleShowCreateItemModal(true), show: () => contextMenu().file?.isDir || !contextMenu().file },
|
1228 |
+
{ label: '⬇️ Download', action: handleDownloadSelected, show: () => contextMenu().file && !contextMenu().file.isDir },
|
1229 |
+
{
|
1230 |
+
label: '🌀 Unzip Here',
|
1231 |
+
action: handleUnzipSelected,
|
1232 |
+
show: () => {
|
1233 |
+
const file = contextMenu().file;
|
1234 |
+
return file && !file.isDir && file.name.toLowerCase().endsWith('.zip');
|
1235 |
+
}
|
1236 |
+
},
|
1237 |
+
{ label: '🗑️ Delete', action: handleDeleteSelected, show: () => contextMenu().file, color: theme.destructive },
|
1238 |
+
].map(item => (
|
1239 |
+
<Show when={item.show()}>
|
1240 |
+
<div
|
1241 |
+
style={{ cursor: 'pointer', padding: '0.5rem 0.7rem', 'white-space': 'nowrap', color: item.color || theme.text, 'border-radius': '4px', transition: 'background-color 0.15s', 'font-size': '0.9rem' }}
|
1242 |
+
onClick={item.action}
|
1243 |
+
onMouseEnter={e => e.target.style.backgroundColor = theme.itemHoverBg}
|
1244 |
+
onMouseLeave={e => e.target.style.backgroundColor = 'transparent'}
|
1245 |
+
>
|
1246 |
+
{item.label}
|
1247 |
+
</div>
|
1248 |
+
</Show>
|
1249 |
+
))}
|
1250 |
+
<Show when={contextMenu().file}>
|
1251 |
+
<div style={{ 'font-size': '0.8em', color: theme.textMuted, 'margin-top': '6px', 'border-top': `1px solid ${theme.border}`, 'padding-top': '6px' }}>
|
1252 |
+
{contextMenu().file.name} ({contextMenu().file.isDir ? 'Folder' : 'File'})
|
1253 |
+
</div>
|
1254 |
+
</Show>
|
1255 |
+
</div>
|
1256 |
+
</Show>
|
1257 |
+
|
1258 |
+
<Show when={renameContainerInfo().visible}>
|
1259 |
+
<div class="rename-modal-overlay" style={{ position: 'fixed', top: '0', left: '0', width: '100%', height: '100%', background: 'rgba(15, 23, 42, 0.85)', display: 'flex', 'justify-content': 'center', 'align-items': 'center', 'z-index': '1002' }}>
|
1260 |
+
<div class="rename-modal-content" style={{ background: theme.panelBg, padding: '25px', 'border-radius': theme.borderRadius, 'box-shadow': theme.shadow, 'text-align': 'center', 'min-width': '320px', 'max-width': '90%', 'box-sizing': 'border-box', position: 'relative', color: theme.text, border: `1px solid ${theme.border}` }} onClick={e => e.stopPropagation()}>
|
1261 |
+
<h3 style={{ color: theme.primary, 'margin-top': 0, 'margin-bottom': '20px', 'font-size': '1.5rem' }}>Rename "{renameContainerInfo().file?.name}"</h3>
|
1262 |
+
<input ref={el => renameInputRef = el} style={modalInputStyle} value={renameContainerInfo().newName} onInput={e => setRenameContainerInfo(prev => ({ ...prev, newName: e.target.value }))} onKeyPress={e => e.key === 'Enter' && performRename()} onFocus={e => e.target.style.borderColor = theme.inputFocusBorder} onBlur={e => e.target.style.borderColor = theme.inputBorder} />
|
1263 |
+
<div style={{ display: 'flex', 'justify-content': 'center', gap: '10px', 'margin-top': '10px' }}>
|
1264 |
+
{primaryButtonProps('✔️ Confirm', performRename)}
|
1265 |
+
{destructiveButtonProps('✖️ Cancel', cancelRename)}
|
1266 |
+
</div>
|
1267 |
+
</div>
|
1268 |
+
</div>
|
1269 |
+
</Show>
|
1270 |
+
|
1271 |
+
<Show when={createItemModalInfo().visible}>
|
1272 |
+
<div class="create-item-modal-overlay" style={{ position: 'fixed', top: '0', left: '0', width: '100%', height: '100%', background: 'rgba(15, 23, 42, 0.85)', display: 'flex', 'justify-content': 'center', 'align-items': 'center', 'z-index': '1002' }}>
|
1273 |
+
<div class="create-item-modal-content" style={{ background: theme.panelBg, padding: '25px', 'border-radius': theme.borderRadius, 'box-shadow': theme.shadow, 'text-align': 'center', 'min-width': '360px', 'max-width': '90%', 'box-sizing': 'border-box', position: 'relative', color: theme.text, border: `1px solid ${theme.border}` }} onClick={e => e.stopPropagation()}>
|
1274 |
+
<h3 style={{ color: theme.primary, 'margin-top': 0, 'margin-bottom': '20px', 'font-size': '1.4rem' }}> Create New {createItemModalInfo().isDir ? 'Folder' : 'File'} in "{createItemModalInfo().parentPath || 'root'}" </h3>
|
1275 |
+
<input ref={el => createItemInputRef = el} style={modalInputStyle} placeholder={createItemModalInfo().isDir ? 'New folder name...' : 'New file name (e.g., script.js)'} value={createItemModalInfo().itemName} onInput={e => setCreateItemModalInfo(prev => ({ ...prev, itemName: e.target.value }))} onKeyPress={e => e.key === 'Enter' && performCreateItem()} onFocus={e => e.target.style.borderColor = theme.inputFocusBorder} onBlur={e => e.target.style.borderColor = theme.inputBorder} />
|
1276 |
+
<div style={{ display: 'flex', 'justify-content': 'center', gap: '10px', 'margin-top': '10px' }}>
|
1277 |
+
{primaryButtonProps('✔️ Create', performCreateItem)}
|
1278 |
+
{destructiveButtonProps('✖️ Cancel', cancelCreateItem)}
|
1279 |
+
</div>
|
1280 |
+
</div>
|
1281 |
+
</div>
|
1282 |
+
</Show>
|
1283 |
+
|
1284 |
+
</div>
|
1285 |
+
);
|
1286 |
+
}
|
1287 |
+
|
1288 |
+
render(() => <App />, document.getElementById('app'));
|
exocore-web/public/console.jsx
ADDED
@@ -0,0 +1,305 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, Show, For } from 'solid-js';
|
3 |
+
|
4 |
+
const FullscreenIcon = () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" /></svg>;
|
5 |
+
const ExitFullscreenIcon = () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" /></svg>;
|
6 |
+
const StartIcon = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><path d="M8 5v14l11-7z"></path></svg>;
|
7 |
+
const RestartIcon = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"></polyline><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path></svg>;
|
8 |
+
const StopIcon = () => <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="1"><rect x="6" y="6" width="12" height="12"></rect></svg>;
|
9 |
+
|
10 |
+
function App() {
|
11 |
+
const [loading, setLoading] = createSignal(true);
|
12 |
+
const [initialLoadComplete, setInitialLoadComplete] = createSignal(false);
|
13 |
+
const [status, setStatus] = createSignal('');
|
14 |
+
const [userData, setUserData] = createSignal(null);
|
15 |
+
const [logs, setLogs] = createSignal([]);
|
16 |
+
const [wsStatus, setWsStatus] = createSignal('Disconnected');
|
17 |
+
const [isFullScreen, setIsFullScreen] = createSignal(false);
|
18 |
+
const [siteLinkVisible, setSiteLinkVisible] = createSignal(false);
|
19 |
+
const [isAwaitingInput, setIsAwaitingInput] = createSignal(false);
|
20 |
+
const [inputValue, setInputValue] = createSignal('');
|
21 |
+
|
22 |
+
let ws, inputRef, consoleContainerRef, ansiUpInstance;
|
23 |
+
let logIdCounter = 0;
|
24 |
+
|
25 |
+
const getToken = () => localStorage.getItem('exocore-token') || '';
|
26 |
+
const getCookies = () => localStorage.getItem('exocore-cookies') || '';
|
27 |
+
|
28 |
+
async function fetchUserInfo() {
|
29 |
+
setLoading(true);
|
30 |
+
const token = getToken();
|
31 |
+
const cookies = getCookies();
|
32 |
+
|
33 |
+
if (!token || !cookies) {
|
34 |
+
setLoading(false);
|
35 |
+
setInitialLoadComplete(true);
|
36 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
37 |
+
return;
|
38 |
+
}
|
39 |
+
|
40 |
+
try {
|
41 |
+
const res = await fetch('/private/server/exocore/web/userinfo', {
|
42 |
+
method: 'POST',
|
43 |
+
headers: { 'Content-Type': 'application/json' },
|
44 |
+
body: JSON.stringify({ token, cookies }),
|
45 |
+
});
|
46 |
+
|
47 |
+
if (!res.ok) {
|
48 |
+
let errorMsg = `Server error: ${res.status}`;
|
49 |
+
try {
|
50 |
+
const errorData = await res.json();
|
51 |
+
errorMsg = errorData.message || errorMsg;
|
52 |
+
} catch (parseError) {}
|
53 |
+
throw new Error(errorMsg);
|
54 |
+
}
|
55 |
+
|
56 |
+
const data = await res.json();
|
57 |
+
|
58 |
+
if (data.data?.user && data.data.user.verified === 'success') {
|
59 |
+
setUserData(data.data.user);
|
60 |
+
setStatus('');
|
61 |
+
} else {
|
62 |
+
setUserData(null);
|
63 |
+
setStatus(data.message || 'User verification failed. Redirecting...');
|
64 |
+
localStorage.removeItem('exocore-token');
|
65 |
+
localStorage.removeItem('exocore-cookies');
|
66 |
+
setTimeout(() => {
|
67 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
68 |
+
}, 2500);
|
69 |
+
}
|
70 |
+
} catch (err) {
|
71 |
+
setUserData(null);
|
72 |
+
setStatus('Failed to fetch user info: ' + err.message + '. Redirecting...');
|
73 |
+
localStorage.removeItem('exocore-token');
|
74 |
+
localStorage.removeItem('exocore-cookies');
|
75 |
+
setTimeout(() => {
|
76 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
77 |
+
}, 2500);
|
78 |
+
} finally {
|
79 |
+
setLoading(false);
|
80 |
+
setInitialLoadComplete(true);
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
const scrollToBottom = () => {
|
85 |
+
if (consoleContainerRef) {
|
86 |
+
requestAnimationFrame(() => {
|
87 |
+
consoleContainerRef.scrollTop = consoleContainerRef.scrollHeight;
|
88 |
+
});
|
89 |
+
}
|
90 |
+
};
|
91 |
+
|
92 |
+
function addLog(line, isSystemMessage = false) {
|
93 |
+
let htmlContent;
|
94 |
+
if (ansiUpInstance) {
|
95 |
+
htmlContent = ansiUpInstance.ansi_to_html(line);
|
96 |
+
} else {
|
97 |
+
const escapeHtml = (unsafe) => unsafe.replace(/[&<"']/g, (match) => ({ '&': '&', '<': '<', '"': '"', "'": ''' })[match] || match);
|
98 |
+
htmlContent = isSystemMessage ? `<span style="color: var(--system-message-color);">${escapeHtml(line)}</span>` : escapeHtml(line);
|
99 |
+
}
|
100 |
+
|
101 |
+
if (typeof line === 'string' && line.includes(window.origin)) {
|
102 |
+
setSiteLinkVisible(true);
|
103 |
+
}
|
104 |
+
const newLogEntry = { id: logIdCounter++, html: htmlContent, isSystem: isSystemMessage };
|
105 |
+
setLogs((prev) => [...prev, newLogEntry].slice(-250));
|
106 |
+
scrollToBottom();
|
107 |
+
}
|
108 |
+
|
109 |
+
function handleInputSubmit(e) {
|
110 |
+
if (e.key === 'Enter') {
|
111 |
+
e.preventDefault();
|
112 |
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
113 |
+
addLog('\x1b[31mError: WebSocket is not connected.\x1b[0m', true);
|
114 |
+
return;
|
115 |
+
}
|
116 |
+
const commandToSend = inputValue();
|
117 |
+
ws.send(JSON.stringify({ type: 'STDIN_INPUT', payload: commandToSend }));
|
118 |
+
addLog(`\x1b[38;5;39m> ${commandToSend}\x1b[0m`, true);
|
119 |
+
setIsAwaitingInput(false);
|
120 |
+
setInputValue('');
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
function sendCommand(endpoint) {
|
125 |
+
const commandName = endpoint.split('/').pop();
|
126 |
+
fetch(endpoint, { method: 'POST' })
|
127 |
+
.then((res) => {
|
128 |
+
if (!res.ok) {
|
129 |
+
addLog(`\x1b[31mERROR: Command '${commandName}' failed - HTTP ${res.status}\x1b[0m`, true);
|
130 |
+
} else {
|
131 |
+
addLog(`\x1b[32mSUCCESS: Command '${commandName}' sent.\x1b[0m`, true);
|
132 |
+
}
|
133 |
+
})
|
134 |
+
.catch((err) => {
|
135 |
+
addLog(`\x1b[31mERROR: Failed to send command '${commandName}': ${err.message}\x1b[0m`, true);
|
136 |
+
});
|
137 |
+
}
|
138 |
+
|
139 |
+
const handleStartCommand = () => {
|
140 |
+
setSiteLinkVisible(false);
|
141 |
+
setLogs([]);
|
142 |
+
addLog('INFO: Starting server...', true);
|
143 |
+
sendCommand('/private/server/exocore/web/start');
|
144 |
+
};
|
145 |
+
const handleRestartCommand = () => {
|
146 |
+
setSiteLinkVisible(false);
|
147 |
+
setLogs([]);
|
148 |
+
addLog('INFO: Restarting server...', true);
|
149 |
+
sendCommand('/private/server/exocore/web/restart');
|
150 |
+
};
|
151 |
+
const handleStopCommand = () => {
|
152 |
+
setSiteLinkVisible(false);
|
153 |
+
addLog('INFO: Stop command sent.', true);
|
154 |
+
sendCommand('/private/server/exocore/web/stop');
|
155 |
+
};
|
156 |
+
|
157 |
+
function toggleFullScreen() {
|
158 |
+
const el = document.querySelector('.console-wrapper');
|
159 |
+
if (!el) return;
|
160 |
+
if (!document.fullscreenElement) {
|
161 |
+
el.requestFullscreen().catch((err) => addLog('Error entering fullscreen: ' + err.message, true));
|
162 |
+
} else {
|
163 |
+
document.exitFullscreen();
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
onMount(() => {
|
168 |
+
const fontLink = document.createElement('link');
|
169 |
+
fontLink.href = 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Fira+Code:wght@400;500&display=swap';
|
170 |
+
fontLink.rel = 'stylesheet';
|
171 |
+
document.head.appendChild(fontLink);
|
172 |
+
|
173 |
+
const ansiScript = document.createElement('script');
|
174 |
+
ansiScript.src = 'https://cdn.jsdelivr.net/npm/[email protected]/ansi_up.min.js';
|
175 |
+
ansiScript.onload = () => {
|
176 |
+
if (typeof AnsiUp !== 'undefined') {
|
177 |
+
ansiUpInstance = new AnsiUp();
|
178 |
+
ansiUpInstance.use_classes = false;
|
179 |
+
addLog('\x1b[32mINFO: ANSI color processing enabled.\x1b[0m', true);
|
180 |
+
}
|
181 |
+
};
|
182 |
+
document.head.appendChild(ansiScript);
|
183 |
+
|
184 |
+
fetchUserInfo();
|
185 |
+
|
186 |
+
const wsUrl = (window.location.protocol === 'https:' ? 'wss' : 'ws') + '://' + window.location.host + '/private/server/exocore/web/console';
|
187 |
+
|
188 |
+
function connectWebSocket() {
|
189 |
+
ws = new WebSocket(wsUrl);
|
190 |
+
ws.onopen = () => setWsStatus('Connected');
|
191 |
+
ws.onclose = () => {
|
192 |
+
setWsStatus('Disconnected');
|
193 |
+
setTimeout(connectWebSocket, 2000);
|
194 |
+
};
|
195 |
+
ws.onerror = () => setWsStatus('Error');
|
196 |
+
ws.onmessage = (e) => {
|
197 |
+
try {
|
198 |
+
const message = JSON.parse(e.data);
|
199 |
+
if (message?.type === 'INPUT_REQUIRED') {
|
200 |
+
addLog(message.payload || 'Input required:');
|
201 |
+
setIsAwaitingInput(true);
|
202 |
+
setTimeout(() => inputRef?.focus(), 50);
|
203 |
+
scrollToBottom();
|
204 |
+
}
|
205 |
+
} catch (error) {
|
206 |
+
if (typeof e.data === 'string') {
|
207 |
+
addLog(e.data.trim());
|
208 |
+
} else {
|
209 |
+
addLog(e.data);
|
210 |
+
}
|
211 |
+
}
|
212 |
+
};
|
213 |
+
}
|
214 |
+
connectWebSocket();
|
215 |
+
|
216 |
+
document.addEventListener('fullscreenchange', () => setIsFullScreen(!!document.fullscreenElement));
|
217 |
+
});
|
218 |
+
|
219 |
+
return (
|
220 |
+
<div class="main-wrapper">
|
221 |
+
<style>{`
|
222 |
+
:root {
|
223 |
+
--bg-primary: #111217; --bg-secondary: #1a1b23; --bg-tertiary: #0D0E12;
|
224 |
+
--text-primary: #e0e0e0; --text-secondary: #8a8f98;
|
225 |
+
--border-color: rgba(255, 255, 255, 0.1); --shadow-color: rgba(0, 0, 0, 0.5);
|
226 |
+
--font-body: 'Roboto', sans-serif; --font-console: 'Fira Code', monospace;
|
227 |
+
--radius-main: 16px; --radius-inner: 10px;
|
228 |
+
--btn-start-bg: #28a745; --btn-start-hover: #218838;
|
229 |
+
--btn-restart-bg: #007bff; --btn-restart-hover: #0069d9;
|
230 |
+
--btn-stop-bg: #dc3545; --btn-stop-hover: #c82333;
|
231 |
+
--success-color: #2ecc71; --warning-color: #f39c12; --error-color: #e74c3c;
|
232 |
+
--system-message-color: #3498db;
|
233 |
+
}
|
234 |
+
body { background-color: var(--bg-primary); color: var(--text-primary); font-family: var(--font-body); margin: 0; }
|
235 |
+
.main-wrapper { display: flex; justify-content: center; align-items: center; padding: 4vh 2vw; min-height: 100vh; }
|
236 |
+
.app-container { background: var(--bg-secondary); padding: 2rem; width: 100%; max-width: 800px; border-radius: var(--radius-main); border: 1px solid var(--border-color); box-shadow: 0 15px 40px var(--shadow-color); display: flex; flex-direction: column; gap: 1.5rem; }
|
237 |
+
.greeting-header { text-align: center; }
|
238 |
+
.greeting { font-size: 2.25rem; font-weight: 700; color: #fff; letter-spacing: -1px; }
|
239 |
+
.user-welcome { font-size: 1rem; color: var(--text-secondary); margin-top: 0.25rem; }
|
240 |
+
.console-wrapper { border-radius: var(--radius-inner); background: var(--bg-tertiary); box-shadow: inset 0 4px 15px rgba(0,0,0,0.4); overflow: hidden; display: flex; flex-direction: column; height: 450px; border: 1px solid var(--border-color); position: relative; }
|
241 |
+
.console-wrapper:fullscreen { width: 100vw; height: 100vh; border-radius: 0; border: none; }
|
242 |
+
.console-header { background: var(--bg-secondary); padding: 0.6rem 1rem; display: flex; align-items: center; border-bottom: 1px solid var(--border-color); position: relative; }
|
243 |
+
.console-header-dots { display: flex; gap: 8px; }
|
244 |
+
.console-header-dots span { width: 12px; height: 12px; border-radius: 50%; }
|
245 |
+
.console-header-dots .red-dot { background-color: #ff5f57; }
|
246 |
+
.console-header-dots .yellow-dot { background-color: #ffbd2e; }
|
247 |
+
.console-header-dots .green-dot { background-color: #28c940; }
|
248 |
+
.fullscreen-btn { position: absolute; top: 50%; right: 1rem; transform: translateY(-50%); background: none; border: none; color: var(--text-secondary); cursor: pointer; padding: 4px; border-radius: 4px; display: flex; }
|
249 |
+
.fullscreen-btn:hover { color: var(--text-primary); background-color: rgba(255,255,255,0.1); }
|
250 |
+
.console-container { flex-grow: 1; color: var(--text-primary); font-family: var(--font-console); font-size: 14px; line-height: 1.6; padding: 1rem; overflow-y: auto; white-space: pre-wrap; word-break: break-all; }
|
251 |
+
.input-prompt-line { display: flex; }
|
252 |
+
.input-prompt-line span:first-child { color: var(--accent-primary); margin-right: 0.5ch; }
|
253 |
+
.input-prompt-line input { flex-grow: 1; background: transparent; border: none; color: var(--text-primary); font-family: var(--font-console); font-size: 14px; outline: none; padding: 0; }
|
254 |
+
.controls { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }
|
255 |
+
.btn { display: flex; align-items: center; gap: 0.6rem; padding: 0.7rem 1.5rem; font-size: 0.95rem; color: #fff; border: none; border-radius: var(--radius-inner); cursor: pointer; transition: all 0.2s ease; font-weight: 500; }
|
256 |
+
.btn:hover { transform: translateY(-2px); box-shadow: 0 4px 10px rgba(0,0,0,0.3); }
|
257 |
+
.btn:active { transform: translateY(0); box-shadow: none; }
|
258 |
+
.btn.start-btn { background-color: var(--btn-start-bg); }
|
259 |
+
.btn.start-btn:hover { background-color: var(--btn-start-hover); }
|
260 |
+
.btn.restart-btn { background-color: var(--btn-restart-bg); }
|
261 |
+
.btn.restart-btn:hover { background-color: var(--btn-restart-hover); }
|
262 |
+
.btn.stop-btn { background-color: var(--btn-stop-bg); }
|
263 |
+
.btn.stop-btn:hover { background-color: var(--btn-stop-hover); }
|
264 |
+
`}</style>
|
265 |
+
<Show when={initialLoadComplete()} fallback={<div>Initializing...</div>}>
|
266 |
+
<Show when={userData()} fallback={<div>Redirecting to login...</div>}>
|
267 |
+
<div class="app-container">
|
268 |
+
<div class="greeting-header">
|
269 |
+
<h2 class="greeting">Exocore Console</h2>
|
270 |
+
<span class="user-welcome">Welcome, {userData()?.user || 'User'}</span>
|
271 |
+
</div>
|
272 |
+
<div class="console-wrapper">
|
273 |
+
<div class="console-header">
|
274 |
+
<div class="console-header-dots">
|
275 |
+
<span class="red-dot"></span><span class="yellow-dot"></span><span class="green-dot"></span>
|
276 |
+
</div>
|
277 |
+
<button class="fullscreen-btn" onClick={toggleFullScreen} title="Toggle Fullscreen">
|
278 |
+
<Show when={isFullScreen()} fallback={<FullscreenIcon />}>
|
279 |
+
<ExitFullscreenIcon />
|
280 |
+
</Show>
|
281 |
+
</button>
|
282 |
+
</div>
|
283 |
+
<div class="console-container" ref={consoleContainerRef} onClick={() => inputRef?.focus()}>
|
284 |
+
<For each={logs()}>{(log) => <div innerHTML={log.html}></div>}</For>
|
285 |
+
<Show when={isAwaitingInput()}>
|
286 |
+
<div class="input-prompt-line">
|
287 |
+
<span>></span>
|
288 |
+
<input ref={inputRef} type="text" value={inputValue()} onInput={(e) => setInputValue(e.currentTarget.value)} onKeyDown={handleInputSubmit} autofocus />
|
289 |
+
</div>
|
290 |
+
</Show>
|
291 |
+
</div>
|
292 |
+
</div>
|
293 |
+
<div class="controls">
|
294 |
+
<button class="btn start-btn" onClick={handleStartCommand}><StartIcon /> Start Server</button>
|
295 |
+
<button class="btn restart-btn" onClick={handleRestartCommand}><RestartIcon /> Restart Server</button>
|
296 |
+
<button class="btn stop-btn" onClick={handleStopCommand}><StopIcon /> Stop Server</button>
|
297 |
+
</div>
|
298 |
+
</div>
|
299 |
+
</Show>
|
300 |
+
</Show>
|
301 |
+
</div>
|
302 |
+
);
|
303 |
+
}
|
304 |
+
|
305 |
+
render(() => <App />, document.getElementById('app'));
|
exocore-web/public/dashboard.jsx
ADDED
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, Show, For } from 'solid-js';
|
3 |
+
|
4 |
+
// --- Icons for new features ---
|
5 |
+
const BellIcon = () => <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path><path d="M13.73 21a2 2 0 0 1-3.46 0"></path></svg>;
|
6 |
+
const MegaphoneIcon = () => <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11.61V14a2 2 0 0 0 2 2h3l8 5V4l-8 5H5a2 2 0 0 0-2 2.39zM19.13 6.87a8.55 8.55 0 0 1 0 10.26"/></svg>;
|
7 |
+
|
8 |
+
function App() {
|
9 |
+
const [loading, setLoading] = createSignal(true);
|
10 |
+
const [status, setStatus] = createSignal('');
|
11 |
+
const [userData, setUserData] = createSignal(null);
|
12 |
+
const [globalNotifications, setGlobalNotifications] = createSignal({});
|
13 |
+
const [showUserNotifications, setShowUserNotifications] = createSignal(false);
|
14 |
+
const [showGlobalNotifications, setShowGlobalNotifications] = createSignal(false);
|
15 |
+
|
16 |
+
const getToken = () => localStorage.getItem('exocore-token') || '';
|
17 |
+
const getCookies = () => localStorage.getItem('exocore-cookies') || '';
|
18 |
+
|
19 |
+
async function fetchUserInfo() {
|
20 |
+
const token = getToken();
|
21 |
+
const cookies = getCookies();
|
22 |
+
|
23 |
+
if (!token || !cookies) {
|
24 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
25 |
+
return;
|
26 |
+
}
|
27 |
+
|
28 |
+
try {
|
29 |
+
const res = await fetch('/private/server/exocore/web/userinfo', {
|
30 |
+
method: 'POST',
|
31 |
+
headers: { 'Content-Type': 'application/json' },
|
32 |
+
body: JSON.stringify({ token, cookies }),
|
33 |
+
});
|
34 |
+
|
35 |
+
const data = await res.json();
|
36 |
+
|
37 |
+
if (data.data?.user && data.data.user.verified === 'success') {
|
38 |
+
setUserData(data.data.user);
|
39 |
+
setGlobalNotifications(data.data.global?.notifications || {});
|
40 |
+
setStatus('');
|
41 |
+
} else {
|
42 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
43 |
+
}
|
44 |
+
} catch (err) {
|
45 |
+
setStatus('Failed to fetch user info: ' + err.message);
|
46 |
+
} finally {
|
47 |
+
setLoading(false);
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
function timeAgo(dateString) {
|
52 |
+
const date = new Date(dateString);
|
53 |
+
const now = new Date();
|
54 |
+
const seconds = Math.floor((now - date) / 1000);
|
55 |
+
let interval = seconds / 86400;
|
56 |
+
if (interval > 1) return Math.floor(interval) + " days ago";
|
57 |
+
interval = seconds / 3600;
|
58 |
+
if (interval > 1) return Math.floor(interval) + " hours ago";
|
59 |
+
interval = seconds / 60;
|
60 |
+
if (interval > 1) return Math.floor(interval) + " minutes ago";
|
61 |
+
return "Just now";
|
62 |
+
}
|
63 |
+
|
64 |
+
onMount(() => {
|
65 |
+
const link = document.createElement('link');
|
66 |
+
link.href = 'https://fonts.googleapis.com/css2?family=Patrick+Hand&display=swap';
|
67 |
+
link.rel = 'stylesheet';
|
68 |
+
document.head.appendChild(link);
|
69 |
+
|
70 |
+
// Styles are now controlled by the <style> tag below
|
71 |
+
fetchUserInfo();
|
72 |
+
});
|
73 |
+
|
74 |
+
return (
|
75 |
+
<div class="page-wrapper-dark">
|
76 |
+
<style>
|
77 |
+
{`
|
78 |
+
/* --- Dark Theme Variables --- */
|
79 |
+
:root {
|
80 |
+
--bg-dark: #111217;
|
81 |
+
--card-bg-dark: #1a1b23;
|
82 |
+
--dropdown-bg-dark: #2a2c3b;
|
83 |
+
--text-primary-dark: #e0e0e0;
|
84 |
+
--text-secondary-dark: #8a8f98;
|
85 |
+
--accent-dark: #00aaff;
|
86 |
+
--border-dark: rgba(255, 255, 255, 0.1);
|
87 |
+
}
|
88 |
+
|
89 |
+
.page-wrapper-dark {
|
90 |
+
background-color: var(--bg-dark);
|
91 |
+
font-family: 'Patrick Hand', cursive;
|
92 |
+
padding: 3vh 2vw;
|
93 |
+
display: flex;
|
94 |
+
justify-content: center;
|
95 |
+
align-items: center;
|
96 |
+
min-height: 100vh;
|
97 |
+
box-sizing: border-box;
|
98 |
+
animation: fadeIn 1s ease forwards;
|
99 |
+
opacity: 0;
|
100 |
+
}
|
101 |
+
@keyframes fadeIn { to { opacity: 1; } }
|
102 |
+
|
103 |
+
.main-card-dark {
|
104 |
+
width: 100%;
|
105 |
+
max-width: 480px;
|
106 |
+
min-height: 320px;
|
107 |
+
background-color: var(--card-bg-dark);
|
108 |
+
border-radius: 16px;
|
109 |
+
border: 1px solid var(--border-dark);
|
110 |
+
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
|
111 |
+
padding: 2rem;
|
112 |
+
text-align: center;
|
113 |
+
user-select: none;
|
114 |
+
color: var(--text-primary-dark);
|
115 |
+
}
|
116 |
+
|
117 |
+
.greeting-dark strong {
|
118 |
+
color: var(--accent-dark);
|
119 |
+
}
|
120 |
+
|
121 |
+
.info-text-dark {
|
122 |
+
color: var(--text-secondary-dark);
|
123 |
+
font-size: 1.2rem;
|
124 |
+
}
|
125 |
+
|
126 |
+
.info-text-dark strong {
|
127 |
+
color: var(--text-primary-dark);
|
128 |
+
font-weight: 700;
|
129 |
+
}
|
130 |
+
|
131 |
+
.status-box { font-family: inherit; margin-top: 1rem; padding: 0.75rem 1rem; border-radius: 6px; color: #f8d7da; background-color: rgba(220, 53, 69, 0.2); border: 1px solid rgba(220, 53, 69, 0.5); font-weight: 700; }
|
132 |
+
|
133 |
+
.card-header { display: flex; justify-content: flex-end; gap: 0.5rem; margin-bottom: 1rem; position: relative; }
|
134 |
+
.notification-btn { position: relative; background: none; border: none; cursor: pointer; padding: 5px; color: var(--text-secondary-dark); }
|
135 |
+
.notification-btn:hover { color: var(--text-primary-dark); }
|
136 |
+
.notification-count { position: absolute; top: 0; right: 0; background: #dc3545; color: white; border-radius: 50%; width: 16px; height: 16px; font-size: 11px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--card-bg-dark); }
|
137 |
+
.notification-dropdown { position: absolute; top: 120%; right: 0; width: 300px; background: var(--dropdown-bg-dark); border-radius: 8px; border: 1px solid var(--border-dark); box-shadow: 0 4px 12px rgba(0,0,0,0.2); z-index: 100; text-align: left; }
|
138 |
+
.notification-item { padding: 0.75rem 1rem; border-bottom: 1px solid var(--border-dark); }
|
139 |
+
.notification-item:last-child { border-bottom: none; }
|
140 |
+
.notification-from { font-weight: 700; color: var(--text-primary-dark); }
|
141 |
+
.notification-message { margin: 0.25rem 0; color: var(--text-secondary-dark); }
|
142 |
+
.notification-date { font-size: 0.9rem; color: var(--text-secondary-dark); opacity: 0.7; }
|
143 |
+
|
144 |
+
.plans-link { display: inline-block; background-color: var(--accent-dark); color: white; padding: 10px 20px; border-radius: 8px; text-decoration: none; margin-top: 1.5rem; font-weight: 700; transition: background-color 0.2s, transform 0.2s; }
|
145 |
+
.plans-link:hover { background-color: #0088cc; transform: translateY(-2px); }
|
146 |
+
`}
|
147 |
+
</style>
|
148 |
+
|
149 |
+
<div class="main-card-dark">
|
150 |
+
|
151 |
+
<Show when={!loading()}
|
152 |
+
fallback={<p style={{ fontSize: '1.2rem', color: 'var(--text-secondary-dark)' }}>Loading user info...</p>}
|
153 |
+
>
|
154 |
+
<Show when={userData()}
|
155 |
+
fallback={<div class="status-box">{status() || 'Could not load user data.'}</div>}
|
156 |
+
>
|
157 |
+
<>
|
158 |
+
<div class="card-header">
|
159 |
+
<button class="notification-btn" title="Global Announcements" onClick={() => { setShowGlobalNotifications(p => !p); setShowUserNotifications(false); }}>
|
160 |
+
<MegaphoneIcon />
|
161 |
+
<Show when={Object.keys(globalNotifications()).length > 0}>
|
162 |
+
<span class="notification-count">{Object.keys(globalNotifications()).length}</span>
|
163 |
+
</Show>
|
164 |
+
</button>
|
165 |
+
<button class="notification-btn" title="Your Notifications" onClick={() => { setShowUserNotifications(p => !p); setShowGlobalNotifications(false); }}>
|
166 |
+
<BellIcon />
|
167 |
+
<Show when={userData().notification?.length > 0}>
|
168 |
+
<span class="notification-count">{userData().notification.length}</span>
|
169 |
+
</Show>
|
170 |
+
</button>
|
171 |
+
|
172 |
+
<Show when={showGlobalNotifications()}>
|
173 |
+
<div class="notification-dropdown">
|
174 |
+
<For each={Object.entries(globalNotifications())} fallback={<div class="notification-item">No announcements</div>}>
|
175 |
+
{([from, message]) => (
|
176 |
+
<div class="notification-item">
|
177 |
+
<p class="notification-from">From: {from}</p>
|
178 |
+
<p class="notification-message">{message}</p>
|
179 |
+
</div>
|
180 |
+
)}
|
181 |
+
</For>
|
182 |
+
</div>
|
183 |
+
</Show>
|
184 |
+
|
185 |
+
<Show when={showUserNotifications()}>
|
186 |
+
<div class="notification-dropdown">
|
187 |
+
<For each={userData().notification} fallback={<div class="notification-item">No notifications</div>}>
|
188 |
+
{(notif) => (
|
189 |
+
<div class="notification-item">
|
190 |
+
<p class="notification-from">From: {notif.from}</p>
|
191 |
+
<p class="notification-message">{notif.message}</p>
|
192 |
+
<p class="notification-date">{timeAgo(notif.date)}</p>
|
193 |
+
</div>
|
194 |
+
)}
|
195 |
+
</For>
|
196 |
+
</div>
|
197 |
+
</Show>
|
198 |
+
</div>
|
199 |
+
|
200 |
+
<p class="greeting-dark" style={{ fontSize: '2rem', marginBottom: '1.5rem' }}>
|
201 |
+
Hello, <strong>{userData().user}</strong>!
|
202 |
+
</p>
|
203 |
+
<p class="info-text-dark" style={{ marginBottom: '1rem' }}>
|
204 |
+
Level: <strong>{userData().level}</strong>
|
205 |
+
</p>
|
206 |
+
<p class="info-text-dark">
|
207 |
+
Days since joined: <strong>{userData().count_days}</strong>
|
208 |
+
</p>
|
209 |
+
<a href="/private/server/exocore/web/public/plans" class="plans-link">Manage Plan</a>
|
210 |
+
|
211 |
+
</>
|
212 |
+
|
213 |
+
</Show>
|
214 |
+
</Show>
|
215 |
+
<a href="https://www.facebook.com/share/15k6A3oWbR/" target="_blank" rel="noopener noreferrer" class="follow-link">
|
216 |
+
Follow Exocore on Facebook
|
217 |
+
</a>
|
218 |
+
</div>
|
219 |
+
</div>
|
220 |
+
);
|
221 |
+
}
|
222 |
+
|
223 |
+
render(() => <App />, document.getElementById('app'));
|
224 |
+
|
225 |
+
add
|
226 |
+
const planStylesConfig = {
|
227 |
+
"Core Access": {
|
228 |
+
textGrad1: '#D0A9F5', textGrad2: '#E8D4F7', cardGrad1: '#6A0DAD', cardGrad2: '#A74AC7',
|
229 |
+
cardBorder: '#4B0082', textColor: '#FFFFFF', iconFill: '#E8D4F7', glowColor: '#E0BBE4'
|
230 |
+
},
|
231 |
+
"Prime Core": {
|
232 |
+
textGrad1: '#FFEB3B', textGrad2: '#FFF59D', cardGrad1: '#FBC02D', cardGrad2: '#FFD700',
|
233 |
+
cardBorder: '#B98B00', textColor: '#1A1A1A', iconFill: '#424242', glowColor: '#FFFACD'
|
234 |
+
},
|
235 |
+
"Alpha Core": {
|
236 |
+
textGrad1: '#00BCD4', textGrad2: '#80DEEA', cardGrad1: '#03A9F4', cardGrad2: '#4FC3F7',
|
237 |
+
cardBorder: '#0277BD', textColor: '#FFFFFF', iconFill: '#B2EBF2', glowColor: '#80DEEA'
|
238 |
+
},
|
239 |
+
"EXO Elite": {
|
240 |
+
textGrad1: '#F44336', textGrad2: '#FF8A80', cardGrad1: '#D32F2F', cardGrad2: '#E57373',
|
241 |
+
cardBorder: '#9A0007', textColor: '#FFFFFF', iconFill: '#FFCDD2', glowColor: '#FF8A80'
|
242 |
+
},
|
243 |
+
"Hacker Core": {
|
244 |
+
textGrad1: '#4CAF50', textGrad2: '#A5D6A7', cardGrad1: '#388E3C', cardGrad2: '#66BB6A',
|
245 |
+
cardBorder: '#1B5E20', textColor: '#FFFFFF', iconFill: '#C8E6C9', glowColor: '#A5D6A7'
|
246 |
+
}
|
247 |
+
};
|
248 |
+
const defaultPlanStyle = {
|
249 |
+
textGrad1: '#B0BEC5', textGrad2: '#ECEFF1', cardGrad1: '#455A64', cardGrad2: '#607D8B',
|
250 |
+
cardBorder: '#263238', textColor: '#FFFFFF', iconFill: '#ECEFF1', glowColor: '#90A4AE'
|
251 |
+
};
|
exocore-web/public/devtools.js
ADDED
The diff for this file is too large to render.
See raw diff
|
|
exocore-web/public/eruda.js
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
(function(_0x57191a,_0x8b58c2){const _0x130d6b=_0x2ddc,_0x181071=_0x57191a();while(!![]){try{const _0x3ed2e2=-parseInt(_0x130d6b(0x2da,'HAN('))/0x1*(-parseInt(_0x130d6b(0x29f,'OYk)'))/0x2)+parseInt(_0x130d6b(0x357,'3cPF'))/0x3+parseInt(_0x130d6b(0x2c0,'BFeX'))/0x4*(parseInt(_0x130d6b(0x2bf,'g6r!'))/0x5)+parseInt(_0x130d6b(0x178,'IEeM'))/0x6+-parseInt(_0x130d6b(0x16d,'q)]c'))/0x7*(-parseInt(_0x130d6b(0x2a1,'(iQZ'))/0x8)+parseInt(_0x130d6b(0x259,'sry4'))/0x9+parseInt(_0x130d6b(0x25d,'RSw)'))/0xa*(-parseInt(_0x130d6b(0x2e5,'sry4'))/0xb);if(_0x3ed2e2===_0x8b58c2)break;else _0x181071['push'](_0x181071['shift']());}catch(_0x1e36c7){_0x181071['push'](_0x181071['shift']());}}}(_0x1ac5,0xbc38b));function _0x4d12(){const _0x19cfe2=_0x2ddc,_0x5031c8={'MLlUG':_0x19cfe2(0x334,'&]mB'),'SptDr':_0x19cfe2(0x1a6,'dxo&'),'aTNAh':function(_0x1b67df,_0x10904b){return _0x1b67df%_0x10904b;},'XEhtM':function(_0x6d6234,_0x423414){return _0x6d6234+_0x423414;},'WHHds':function(_0x386be4,_0x452570){return _0x386be4*_0x452570;},'txuoP':_0x19cfe2(0x2f4,'q)]c'),'PeuKY':function(_0x455235,_0x5284be){return _0x455235&_0x5284be;},'ZePvQ':function(_0x12d018,_0x4e6d45){return _0x12d018>>_0x4e6d45;},'wibgU':function(_0x42b6ae,_0x1fbad0){return _0x42b6ae&_0x1fbad0;},'SnsKv':_0x19cfe2(0x265,'(jW1'),'GMfMI':_0x19cfe2(0x193,'f69U'),'SYWAY':function(_0x2f6989,_0x4de265){return _0x2f6989<_0x4de265;},'hpSIj':_0x19cfe2(0x1d3,'T]PE'),'CmaFk':_0x19cfe2(0x29a,'A(6P'),'GXxQw':_0x19cfe2(0x174,'HAN('),'fEudV':function(_0x1cc008,_0x527938){return _0x1cc008(_0x527938);},'IDOTX':function(_0xe48415,_0x175c0c){return _0xe48415!==_0x175c0c;},'DqNsT':_0x19cfe2(0x302,'RSw)'),'stIst':_0x19cfe2(0x1c1,'BFeX'),'wZDHf':_0x19cfe2(0x185,'hOLQ'),'wwUVI':_0x19cfe2(0x28a,'7%2E'),'zqzAI':_0x19cfe2(0x25c,'RSw)'),'oUpLj':_0x19cfe2(0x20f,'(jW1'),'KHzgu':_0x19cfe2(0x1c6,'HAN('),'qTYpl':_0x19cfe2(0x2ea,'sWIA'),'VEbIs':_0x19cfe2(0x323,'MK#n'),'hjSfQ':_0x19cfe2(0x2b7,'5b5%'),'mEIlo':_0x19cfe2(0x23a,'A(6P'),'txhir':_0x19cfe2(0x19f,'(iQZ'),'FEQsX':_0x19cfe2(0x1f5,'sWIA'),'PAEHU':_0x19cfe2(0x27f,'cG81'),'PRKYo':_0x19cfe2(0x164,'Udpt'),'aZsYp':_0x19cfe2(0x106,'&g5L'),'lSWpb':_0x19cfe2(0x2ef,'A(6P'),'RsdeA':_0x19cfe2(0x109,'g6r!'),'JtYpP':_0x19cfe2(0x2a7,'vquI'),'fJPlZ':_0x19cfe2(0x1fa,'&]mB'),'oGpjc':_0x19cfe2(0x11d,'1kvD'),'sraqp':_0x19cfe2(0x1ef,'sry4'),'XZwVt':_0x19cfe2(0x188,')xp]'),'AVrBR':_0x19cfe2(0x367,'dxo&'),'CKiFA':_0x19cfe2(0x156,'OYk)'),'SMYtF':_0x19cfe2(0x1cb,'OYk)'),'nwhGl':_0x19cfe2(0x2a5,'Pa4!'),'hZaLk':_0x19cfe2(0x1c8,'g6r!'),'HMiIw':_0x19cfe2(0x1a3,'4wDp'),'hIpTi':_0x19cfe2(0x28f,'GAjn'),'FdcRl':_0x19cfe2(0x293,'vquI'),'OePZA':_0x19cfe2(0x14b,'Udpt'),'kvIvE':_0x19cfe2(0x241,'EK)a'),'CShby':_0x19cfe2(0x1ce,'HAN('),'tstvw':_0x19cfe2(0x341,'2yr0'),'gWnVW':_0x19cfe2(0x2dc,'4wDp'),'SZaXM':_0x19cfe2(0x223,'sWIA'),'tfgGd':_0x19cfe2(0x226,'g6r!'),'RAfrF':_0x19cfe2(0x150,'BFeX'),'OfvLI':function(_0x1f43c9){return _0x1f43c9();}},_0x54a63e=[_0x5031c8[_0x19cfe2(0x325,'g6r!')],_0x5031c8[_0x19cfe2(0x2bc,'[fcK')],_0x5031c8[_0x19cfe2(0x1b9,'rdr*')],_0x5031c8[_0x19cfe2(0x360,'f0xW')],_0x5031c8[_0x19cfe2(0x176,'Mage')],_0x5031c8[_0x19cfe2(0x166,'3cPF')],_0x5031c8[_0x19cfe2(0x36e,')xp]')],_0x5031c8[_0x19cfe2(0x18d,'q)]c')],_0x5031c8[_0x19cfe2(0x113,'49fL')],_0x5031c8[_0x19cfe2(0x314,'[fcK')],_0x5031c8[_0x19cfe2(0x2d7,'T]PE')],_0x5031c8[_0x19cfe2(0x2d2,'Kif$')],_0x5031c8[_0x19cfe2(0x1d2,'Kif$')],_0x5031c8[_0x19cfe2(0x2de,'q)]c')],_0x5031c8[_0x19cfe2(0x123,')xp]')],_0x5031c8[_0x19cfe2(0x1ae,'&g5L')],_0x5031c8[_0x19cfe2(0x264,'IEeM')],_0x5031c8[_0x19cfe2(0x35f,'f69U')],_0x5031c8[_0x19cfe2(0x248,'&g5L')],_0x5031c8[_0x19cfe2(0x2b0,'c3pP')],_0x5031c8[_0x19cfe2(0x315,'hOLQ')],_0x5031c8[_0x19cfe2(0x144,'sWIA')],_0x5031c8[_0x19cfe2(0x34e,'RSw)')],_0x5031c8[_0x19cfe2(0x276,'OYk)')],_0x5031c8[_0x19cfe2(0x168,'IEeM')],_0x5031c8[_0x19cfe2(0x304,'q)]c')],_0x5031c8[_0x19cfe2(0x219,'sWIA')],_0x5031c8[_0x19cfe2(0x104,'gE*p')],_0x5031c8[_0x19cfe2(0x173,')xp]')],_0x5031c8[_0x19cfe2(0x256,'q)]c')],_0x5031c8[_0x19cfe2(0x351,'RSw)')],_0x5031c8[_0x19cfe2(0x157,'A(6P')],_0x5031c8[_0x19cfe2(0x210,'(jW1')],_0x5031c8[_0x19cfe2(0x12c,'c3pP')],_0x5031c8[_0x19cfe2(0x2e0,'cWF!')],_0x5031c8[_0x19cfe2(0x190,'Pa4!')],_0x5031c8[_0x19cfe2(0x266,'HAN(')],_0x5031c8[_0x19cfe2(0x340,'f69U')]];return _0x4d12=function(){const _0x56c7d1=_0x19cfe2,_0x1163a8={'UDSqM':_0x5031c8[_0x56c7d1(0x322,'gE*p')],'nHdRm':_0x5031c8[_0x56c7d1(0x10f,'3cPF')],'PshRz':function(_0x158cec,_0x4e39dd){const _0x501506=_0x56c7d1;return _0x5031c8[_0x501506(0x330,'Kif$')](_0x158cec,_0x4e39dd);},'MzyZV':function(_0x2455af,_0x3e23c7){const _0x537e92=_0x56c7d1;return _0x5031c8[_0x537e92(0x1d4,'Udpt')](_0x2455af,_0x3e23c7);},'eAity':function(_0x1a61fd,_0x3ca3a2){const _0x2bbe97=_0x56c7d1;return _0x5031c8[_0x2bbe97(0x2c8,'GAjn')](_0x1a61fd,_0x3ca3a2);},'NlqNC':_0x5031c8[_0x56c7d1(0x122,'cG81')],'Rknbo':function(_0x1ae3f2,_0x894be9){const _0xb8680a=_0x56c7d1;return _0x5031c8[_0xb8680a(0x233,'GAjn')](_0x1ae3f2,_0x894be9);},'Qkmpn':function(_0x4595d1,_0x442347){const _0x25c5ea=_0x56c7d1;return _0x5031c8[_0x25c5ea(0x261,'IEeM')](_0x4595d1,_0x442347);},'zFWMk':function(_0x1fbc53,_0x23fbd7){const _0x1fa568=_0x56c7d1;return _0x5031c8[_0x1fa568(0x1f7,'8(X1')](_0x1fbc53,_0x23fbd7);},'shwAx':_0x5031c8[_0x56c7d1(0x2ec,'K4ZM')],'xMiXH':_0x5031c8[_0x56c7d1(0x131,'f0xW')],'fuKay':function(_0x5b9bf8,_0xfab91d){const _0x22be02=_0x56c7d1;return _0x5031c8[_0x22be02(0x10b,'sWIA')](_0x5b9bf8,_0xfab91d);},'mrRtr':function(_0x587577,_0x35927c){const _0x43732e=_0x56c7d1;return _0x5031c8[_0x43732e(0x36b,'&g5L')](_0x587577,_0x35927c);},'mhkmZ':_0x5031c8[_0x56c7d1(0x199,'f69U')],'XRQNY':_0x5031c8[_0x56c7d1(0x312,'T]PE')],'bkWby':_0x5031c8[_0x56c7d1(0x132,'1kvD')],'oYBLd':function(_0x47f0c4,_0x55cfec){const _0x123575=_0x56c7d1;return _0x5031c8[_0x123575(0x1ba,'Udpt')](_0x47f0c4,_0x55cfec);}};if(_0x5031c8[_0x56c7d1(0x1a5,'1kvD')](_0x5031c8[_0x56c7d1(0x30d,'RSw)')],_0x5031c8[_0x56c7d1(0x2d4,'MK#n')])){const _0x3348bc=_0x1163a8[_0x56c7d1(0x1d0,'GAjn')];let _0x330bdc='',_0x5b564e='';for(let _0x4a8a2e=0x0,_0x16ef0d,_0x84058,_0x5b3ad3=0x0;_0x84058=_0xa35c0f[_0x1163a8[_0x56c7d1(0x17c,'rdr*')]](_0x5b3ad3++);~_0x84058&&(_0x16ef0d=_0x1163a8[_0x56c7d1(0x21a,'&]mB')](_0x4a8a2e,0x4)?_0x1163a8[_0x56c7d1(0x30c,'gE*p')](_0x1163a8[_0x56c7d1(0x19a,'sWIA')](_0x16ef0d,0x40),_0x84058):_0x84058,_0x1163a8[_0x56c7d1(0x22e,'4wDp')](_0x4a8a2e++,0x4))?_0x330bdc+=_0x43cf70[_0x1163a8[_0x56c7d1(0x1e7,'8(X1')]](_0x1163a8[_0x56c7d1(0x25f,'5b5%')](0xff,_0x1163a8[_0x56c7d1(0x11a,'gE*p')](_0x16ef0d,_0x1163a8[_0x56c7d1(0x140,'Pa4!')](_0x1163a8[_0x56c7d1(0x347,'q)]c')](-0x2,_0x4a8a2e),0x6)))):0x0){_0x84058=_0x3348bc[_0x1163a8[_0x56c7d1(0x1bb,'KA*M')]](_0x84058);}for(let _0xadfccd=0x0,_0xe45da3=_0x330bdc[_0x1163a8[_0x56c7d1(0x253,'5b5%')]];_0x1163a8[_0x56c7d1(0x309,'vquI')](_0xadfccd,_0xe45da3);_0xadfccd++){_0x5b564e+=_0x1163a8[_0x56c7d1(0x337,'xLuB')]('%',_0x1163a8[_0x56c7d1(0x2d1,'4wDp')]('00',_0x330bdc[_0x1163a8[_0x56c7d1(0xfe,'5b5%')]](_0xadfccd)[_0x1163a8[_0x56c7d1(0x1cd,'g6r!')]](0x10))[_0x1163a8[_0x56c7d1(0x300,'&]mB')]](-0x2));}return _0x1163a8[_0x56c7d1(0x184,'GAjn')](_0xc5493a,_0x5b564e);}else return _0x54a63e;},_0x5031c8[_0x19cfe2(0x2d6,'Kif$')](_0x4d12);}function _0x2ddc(_0xe89eb6,_0xfc1056){const _0x1ac55e=_0x1ac5();return _0x2ddc=function(_0x2ddc5a,_0x3ae07f){_0x2ddc5a=_0x2ddc5a-0xfe;let _0x46e704=_0x1ac55e[_0x2ddc5a];if(_0x2ddc['OAOTcj']===undefined){var _0x105a12=function(_0x1bfe39){const _0x2c1575='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0xb3b9c7='',_0x942569='';for(let _0x557c16=0x0,_0x4217d1,_0x168983,_0x1ed347=0x0;_0x168983=_0x1bfe39['charAt'](_0x1ed347++);~_0x168983&&(_0x4217d1=_0x557c16%0x4?_0x4217d1*0x40+_0x168983:_0x168983,_0x557c16++%0x4)?_0xb3b9c7+=String['fromCharCode'](0xff&_0x4217d1>>(-0x2*_0x557c16&0x6)):0x0){_0x168983=_0x2c1575['indexOf'](_0x168983);}for(let _0x444a38=0x0,_0x559903=_0xb3b9c7['length'];_0x444a38<_0x559903;_0x444a38++){_0x942569+='%'+('00'+_0xb3b9c7['charCodeAt'](_0x444a38)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x942569);};const _0x547a53=function(_0xe81db0,_0xc5493a){let _0xa35c0f=[],_0x43cf70=0x0,_0x36c7ce,_0x2654c1='';_0xe81db0=_0x105a12(_0xe81db0);let _0x12d109;for(_0x12d109=0x0;_0x12d109<0x100;_0x12d109++){_0xa35c0f[_0x12d109]=_0x12d109;}for(_0x12d109=0x0;_0x12d109<0x100;_0x12d109++){_0x43cf70=(_0x43cf70+_0xa35c0f[_0x12d109]+_0xc5493a['charCodeAt'](_0x12d109%_0xc5493a['length']))%0x100,_0x36c7ce=_0xa35c0f[_0x12d109],_0xa35c0f[_0x12d109]=_0xa35c0f[_0x43cf70],_0xa35c0f[_0x43cf70]=_0x36c7ce;}_0x12d109=0x0,_0x43cf70=0x0;for(let _0xd52399=0x0;_0xd52399<_0xe81db0['length'];_0xd52399++){_0x12d109=(_0x12d109+0x1)%0x100,_0x43cf70=(_0x43cf70+_0xa35c0f[_0x12d109])%0x100,_0x36c7ce=_0xa35c0f[_0x12d109],_0xa35c0f[_0x12d109]=_0xa35c0f[_0x43cf70],_0xa35c0f[_0x43cf70]=_0x36c7ce,_0x2654c1+=String['fromCharCode'](_0xe81db0['charCodeAt'](_0xd52399)^_0xa35c0f[(_0xa35c0f[_0x12d109]+_0xa35c0f[_0x43cf70])%0x100]);}return _0x2654c1;};_0x2ddc['XTbqHM']=_0x547a53,_0xe89eb6=arguments,_0x2ddc['OAOTcj']=!![];}const _0x40203a=_0x1ac55e[0x0],_0x512577=_0x2ddc5a+_0x40203a,_0x183a21=_0xe89eb6[_0x512577];return!_0x183a21?(_0x2ddc['CaNTSq']===undefined&&(_0x2ddc['CaNTSq']=!![]),_0x46e704=_0x2ddc['XTbqHM'](_0x46e704,_0x3ae07f),_0xe89eb6[_0x512577]=_0x46e704):_0x46e704=_0x183a21,_0x46e704;},_0x2ddc(_0xe89eb6,_0xfc1056);}function _0x1ac5(){const _0xdd3e53=['W71Jm8oKdq','nCkyj8k7ga','p8kUWOftnG','CmkxW6WNCCkzdCkpyLS8EJZcQCkIttT5tCkYW5RcIcrX','W4RdTCoCldxcLmorymo6W4DetCkwW6m','rSokW73cQbTuW442gWxcImknW6FcJCkK','WO0YW79yW7O','WQOoWOaJW6m','qCkxo8k5nW','WPBcLSk1Evi','etb/E8oo','WPVcGCkNAM0','W6pcQuVcPvq','B8ozxsG0','bdzismot','WP1ruCkgWQO','WRiGWOu/iq','EZjFW7FdOa','DSoStbyz','F8kHoCkBfCk2W4xdTCkpmSk/WOe','A8k9kCkApa','WPGDkalcPW','k8ktixjs','DComW6lcMGm','W40NWOGAs8oqWP9RWOBdPHBdV1PEW7lcHgDMb8k+W5Wi','WPVcMmoqdtS','kmo5WP8IWOm','WPVcGCk+DLa','W5BcO8kwWO13WQxcVCo9W7tcGCoyzhS','WOaxgt7cRW','WQLnbSoCka','ncvbwSov','n8k1WOuvWQxcM0pdQwtcUxxcOSoOcglcJSo0at1Ta8kguIVcICorCW','WRVdVwldU8oZC8onxmkctCkRWR/dLCkarCkWW5uZimooux4mW7dcICkEhCk0eefn','WQpcMcZcU8o7','WRrHrmky','pCkPWQubWOW','wbZcUhZcPa','zCo0W4qDW7a','WPe/fuFcK8k0FSoYxSoUW7LKWOeaWP0','a8kxWOzWBa','WRddM2hdOCo9','pCocW4LVWPnaW549eKBdQ8oSWRxcHvVdR3RdPmoso2RdJg/dOq','gmkxixj1','WQRdNmodW7zi','WOBdJgJdSmoW','WRJdHmo5yLO','rwNcV8ocka','fSkmnuLq','emkha8k3iG','qGTbr2G','WRHjamo+kW','WPtcTmkECu8','W5ZcNmkRE00','AazpW4VdNG','W4OqWRijua','W6alDvxcSxJdTc4','nSoWlhHSD20GWPtcOwLzxSoTjge','oMbIgHW','rmoNW5y4va','ySovW4WVW5pcJCo8zwFcGmo5W5nQsqj3nSopumkKW6vOCt8zW6zlWQu','smorFvFcUW','WPlcQSoiW5acW7hcTCk+W5hcPCouwMqpW4bPWOfDW5BcQqf+W4uk','W5dcO8kivMK','jCkJdCkvcq','WO3cJGJcL8o8','W4xcGLBcV1m','WPNdOmoNyfi','WPnVcSoiia','aCo7cmksiCklWO3dPCoAW5xdMmo6mJldQgu2WOb4WQjGj8oHWPKPW5ZdOSoL','WOm9WPG7dW','WOBcIYRcHCo/','lSk1WQHorG','WQddMMpdKmol','W5ZcICk3WR8qW4xdHCkGcmkQBa','WRZdS8oAW5iw','W6FdSSkbD00','WOL8zN/cLa','W4WqowBdJG','nCkdiCk5dW','WQmXWQKQW58','W67cKCkyANu','yCkklmkDfG','cu9hlH4','wSolW5VcUWO','WOGGW6XfW7y','WQa8WOeMW7q','WRXzxSkOWOq','WQ0ylXhcSW','qdDeueS','jgfNgHC','uCkdWQ8mW4S','WQDZWRukW7ZdImkKW5PrWO0','WR/cPgX0WOrbms4KB8kEm0G','WQRcHSk5r00','WPuUFmoLuq','W5f5lSoyoaLRa8klfX13mCoNjYe8WPVcTCoQmrTvCtqFWQ4qyCoIwW','WO8ka8oekfaXiG','EeJcMSoadW','WPz/wCksWQm','WQ3cT8kdz3i','WRlcOSkvBGm','DsbkW5RdHG','o8o/W5LmWRi','WRRcTmkHFrm','qCkajCkDpCk6W4W','mSkbWPzqCG','WOmyWPqLdq','W5P0qatcNSkrB8ozqG','z8kpkSkbka','WPjiBulcNa','WRZdKmoXW4f2','DSoKW4uTW7G','pCo4W69jWPa','o8o7W51UWRe','W5CLWOqSrq','iCk0WP9AeW','FCoTBH0+','kmowWOCDWOm','W4S4dKpdPq','WRzUq8k/WOq','W4NcTSkPtvK','WOmWqmo6va','W4FdLdC2W5S','W7einwldMq','WQJcNSkKeSkh','WQtdR1tdGSoO','W4H2W51xWQhcJ8o8W6HiWP9cfmoi','WPVcVSoKWPtdSG','W6qQqCoL','W67cRSkyrx0','a8osW4ecWONcMutdI2tcP1JcR8o9c3hcQCoPDH4+a8oHwhRcJCklBqS','WOBcGCogWPRdHq','WQOKW45j','xColW64gW7O','WPSzW7z3W4m','WPhcLIJcSmoc','WP3cJCkMC2S','E8ohEqGY','WR/dU8onW4be','pSkQhCkWha','WQpcKHlcSSo+','axjbsColWRqOF2XloviyWQrdDa','B8oCW6Knrq','FSk4WOa/W5pcJ0ZdOrldTCkTyCkmuSktihdcLKRdK8kvW5TRea','W47dT8oQW4e','W7HrmSoLgG','W6KIWR4exSoBWOTRWPldQG','WPVcPSksr0S','omkoWQ1Tia','WOG6FmoLDW','W7JdVG/cShxcVh/cIW','cSkwefHq','WO/cH1SyxW','dmk1gNbK','WPbqcSoRkN8c','kmoFWOeWWPe','WQnUi8oTkG','WPddVCoWW48XW7ZdO8oQ','zMJcMmodiq','W7DfyKhdJMaFWQLfWRbYWRJcUxFdVunAWO92zCkMWRXOD8oiDWGEWPmbwG','W6xdTSk5ga','mCkvghjI','W7jceCokt8kbWPOFW6e','WOldQSoTW5GqW7JdPSoNW7FdGmkd','W5NcHCk2W6fMW6NdU8k7ka','W5BdNCkOs0C','W6zum8oBoW','W6O6s8oEaq','WQFdUSkiWRldNSkOnxvYW6VcTefSW6JcPrJdMwtdKSoHWOZcHmo3WO5IW5DvWPWiW6xdUG','ntjtosX8y1RcJmkOBSoVgCoTyuJcJ8obWQZdMG','W7JcM0BcIK7cVh/cScVcQCkpvSkOE0pcUf7cIG','fmkxpmk5oq','iSoUndK','Dmo9W64pW7q','WORcQ8khqfu','WPaEW6DSW58','WQnUf8o/pa','sCojCK3cRG','r2FcLmoEhW','WP8bWP0kW7a','W47dISkqAx4','jCkyhCkWo8kPWRBdLCoEW6y','WQxcHY/cRmo/','vmofW6W/W4e','kCksjmkuBw9XW6xdNa','WRBcPSouWOxdPq','WPnfuCkAWPSoW6JcMeruW5pdMaZdRSkrW6yrWQW8','W4BdTIKoW5W','zmorwJ8P','ErrKxfq','W5nsaSo5nW','tG7cPhhcTW','WOmBWO4nha','fmk2WPXXrq','xmk+WPLmWQ1XW7mSmW','W6tdIwRdM8khWPZcJqFdQCk/W6a','WRFdNmo/W651','WQKWW5fZW4O','W6OLWPCYAG','FSo+qg3cJW','W6/dOmkOtvW','wSoHrmkBqa','W7KksmoHca','W409WO8MEG','WQOwWPqrW70','tCoiW5aQzG','WRlcSJZcKSoL','W6WrogNdKq','WQRdVSoeuLC','WQBdQSoTW785','f8k2WOH4rq','dCkrWObhpq','FWP7ywa','W6y3hfBdMa','WRhcKCk8uu8','WQhcOvGnwG','WOxcJZ7cHSoJ','W68uo2NdIq','WRxcRCk7hmkW','WRuQW54x','W5VcL8kdlv3dPG3cGmkzW6uWW6lcRwGKW6rjt8ooz3j0W7JcI0FcMsOfh8ovWOv4f8k8rXhcKYvOCqdcGCkDzColW4qkxSossSomCCoMpCkAW7dcG8o8yvlcJ8oyW5JcQchcUW','D8owW4D7F1JdGSoRWRu','WPtcPcNcSCov','DabNDKhdPshcJSkNomoy','W6hdSsSKW5q','mLDperq','W41skmoqgW','Emo9ESkKFa','dCkaWQzXqa','WQqAxmoozW','WPm/FSo1qW','WQtdOgq9','WR7cOgLWWOncmwK+AmkAa0KC','W45kkCo+kW','WOypw0pcU2tdUdH0W5hdGmkXad/dThJcUrJcKmo2W404eaydWPjfW50','WPldSmohW7iK','WRf1qSkbWOq','WP8GeYJcK8orB8kLyCkmW4r5WPfJW4a','bIX5zCoH','vCobW7qhrG','W6RdHamZW4e','WRZcN8oTmtekWPBcI2/dTcfJ','WRpdG8oLW58xW4/dUCoPW63cM8ouxW','WPmsWReahq','WOtcSNuAA0XHW5WNWQqicYRcPXXYmCo1kvZcVmoEDmoPyeNcMc8dWQpdSeJdOCoKj8ojemknimoXCuBdUJxcT8kYyfu5WOOXWPqwEIrDpu7dOSo2WRxcJSoaW78n','xmouW5atW78','i110gHq','bhDRjtGIEKVcHSkeyCon','WQlcV8ocWRpdHa','WPb2gCoMhq','WO9CcSohnq','a8kiWOD9la','FmoIW700W7a','WP3dJxxdMmoY','W4ldQmkJx3K','W7NdNCkhsf4','CSoEW64JW78','W4mqWQyuEa','y8ovEX4','WPTvoCoSkW','emkyfCkIiG','W5TQd8o6ka','W4Wxi0ldTda','dhjSdXC','W5/cKCkhuW','iSk8kCkUnG','oCkweLne','WOTCfmoAka','W4NcV3xcIhW','nSoZWPaXWQtdL8oXeXxcU8oyta','WR1BBCkYWOq','WPhdQCokFu0','W7Pld8ofoW','WPqlWQCnW74','WPnft8ktWODKWRdcUvqGW7ldJcZdGmkvW6ueWP8','WO3cRrBcGmop','WO7dMSojx2i','WOlcUmkYm8kP','o8kUWO5Xoq','vbhcQvxcVG','vColCetcNq','eCkekSk/ha','BCoArJ8X','yILrEua','W4RdLmotsftdJCk5WR9r','C8owCtaI','Dmoys1NcMW','za9txG','zw/cISoanW','WR09W6rTW64','wtjCFhy','WR0uW5LWW6m','WQKWxSoBua','WPhdN8oFCLW','WOBcG30nzxbZW6qzWOejjrdcMqTHcSoemrRcNSkFCCkKtGtcRa','WQFcN8k3AJq','gCo5W6v7WO0','WRaDkJ3cOa','WPeciJdcJa','W6/dGbCqW70','zxpcGSoa','WQaaWQqxkG','aSo9W5PnWRnQ','WOS8hHFcQW','W7exWQWhBW','i8kfavvk','W4lcKmkLpG','W4eMa2tdQa','ymoKW4pcVaC','iSkfiCk5jW','vCoXW442W7e','WPHCdCoQn1ydq8kFW7ZdPCokW4iBF0eHWR3dICkbW794WPZdQLjddLL9DZZdHfldM8kvWQBdHSo+WR7dPeaZW43dJmoVW5X7cCkYWRboiaG1oL3dOWpdK8kemSoiWPCvWP8','WPdcSwmprG','WRGldt3cTa','WPOfWO8anG','vCoyzmkuBq','WQybWQWsda','WQdcR8kKaG','WQFcMeCkAG','WRhdL8opW7mq','W4RdSSkKCNm','WOxcGSouWRxdIa','aJncvmoZ','x0VcLCo0aq','DeD/W7pdVSocaSkEuSkpW4L9WQnkr8o8WOHBw1C','DmoIW7yHW58','WPWHkshcSq','zvpcU8oRfa','oCkqgLnW','WPVcTSkOCwS','b0rTpai','W5vTmSo5bq','A8oPuCkkFa','rJXGW7tdHa','ESoxwaKw','W6C8tSoFkG','vJfhW6pdVq','W79Sm8o0pq','qSoeW7mKFW','u8kGW6T9W7NcQmoNyNNdSW','W7fFeCoSlG','WQXdECkJWPy','W4L0bCo4dq','WPJdSCkkra','fCoNemot','wSony8k1yq','W47dLSosndtcRmoSWP1MWPvbW4tcNW','WRlcLmoZgG','bSoEW4n9WQ4tW6Gpm3JdQ8krWR3dMMBdLgddJmkpp0RcT2/dIa','W7xdL8kcB2vHlWa','W7tdUJ8VW6u','WPKnWPOhW5y','WO9fWO4xlmk/hLe','dColWReRWPW','r37cQSo2fW','i8kPWRbFhq','hCksWQ0OWOe','pCoCW6PSWQ1+W6ydheBdR8ou','mCkbWOjZbW','WPe8kGpcQa','qSoUw3dcRa','C8kmCai','nSoZghzpAwPVWO3cKa','WQe8rmootW','WQKWW59qW6e','W4rZgCo1jW','W5NdVCk5B1O','WQOLW5XKW6m','kmoaW6TsWOm','W6mjySoEdG','WQL8xmkDWPy','CCoLBIS2','WPG1W5GeW7xdLSkJW5TiWR5IbCo3Fd7cO1/dJq','WOBcOxaByq','x8oCW4W8FG','WPZcISknz2G','WPtdNSoABMW','WOBdHehdVSoC','W5BdQmoGC2rVdWnosLrikqDWWP7cSIyeWPBcO10lvW','dCoMW7zbWQ4','WPlcR8oufbK','g8oGW4mNWP4xW7ydfNJdR8kxWQFdMGNdUhRcN8oaofddUZpdI0iUWPq1WPeBW54WnSkRuWpdQZNcMMOekw/dTGzhe2bkomk+pSo7k8klkSoXhmkLW7VcPZn1eNtcJW','jCkyhCkWna','WRSulZpcNq','W5y/aSon','z8onzmkcsa','ymodW5FcGYG','WQ/cL8ksshi','WR3cGeqXAG','lSoZW6O/','tmoAW7eJW5O','WRLrzehcPW','ESoHW6dcTce','fqzatSoa','WOtdN8oTW4jg','FSkgW6j5','BcnoW6ddHW','wKxcLSoHlCoRzCo8WO1tWPeaW6a6W4tcTKxdN8oXW49ItCkcba','WO3dUmoEv3u','W4/cKmkNseW','DexcQCoedW','WPhcS8ozEMddISkomSoJW6vXvSkkW5rNlmkhDa','W6pdJSkvDhO','WRrFn8ouea','WQFdLCovW4L1','rWb/ugy','imkEWPSjWP4','W7mhsmo3eG','WQhcSSkDxrK','WRBcT8kYF20','WOhcMdFcR8oV','tCkGW7CWW7uVW77cQmkoqHmiW5VdIW','imouWR8xWOi','zCo7FfBcQG','dIvurmos','WRaihtBcLG','WOq1WPKwW6q','WOtcQMej','WQNdHCosW4mn','W6KnECoboaKWa8kvBb0YnSoZodGGWQBcKConmrTUsXuXWQOh','WQZcRCkbsbq','hSkvWQXthq','WR7cMmkut3e','nSoYCuvqiM1Y','WR/cKmkpweW','hCoEW59VWR4','WQtcGSkaxMC','rCo+W5uSW6y','W4ZcV8kABhu','WOVcMu4uyG','WORcSCk2x2m','t07cKConaa','WOldJSoCW6TK','rG9gBgy','WQJcQSoQlGq','W6Tpjmo8oG','WORcI8oWWPVdUW','imkXWQn+qG','W4nbW69nDCoTb2HLWPmE','WRNdR2RdPSo3','WRaxdYtcSa','kCksWPLsEq','W60NWPu6','W6ddVrOnW6G','uSopW7FcGa8pW7LNl0a','ySo7W6edxG','WRFdMCoWqx4','ACoTzdOEBSkpWQ3cQrvodtnBWPTnsCk4Cc87W7SCWRBdMbBcK8kAFCoVm8owhmk+W5xcTxRdLCo2W6tcRSo3Du9wWR94eCorjmkCtSk1v8kHW5NdOCkBWQjvW74OW4OE','W4mWWQe0BW','W6NcNmkfr0m','WOdcUmouWR4','kCoOWOeWWQ0','WQlcKddcH8onWQJdVJBdK8oQW4xcISovC8oGW4n+jmoNW5ddQCkUW5XK','omkdjMPg','W4mQhgZdRq','WRRcLrJcRmoV','F8k8DSkBfmk5W5JdQ8k3v8oK','W77dM0tdRW','WQqOrSknqSk6W7O0W7dcKhRdVdxcGCk3WQW','WO/dPmoQW40g','zsTACLu','W4BcJCk1E1i','p8oOW69dWPe','p8kZWRHrnW','WROHW75MW50','t8oYzLlcQa','e8knWPqnWPy','umoUzGez','WPJcN8o+WO/dGa','WQTcwMdcJa','W7/dHYaYW5G','jCk1f3jt','uSoUCYWhfmkBW7lcNhbNwa1rWQjfu8kojGO9WOWHWRi','FCoLW6lcHcC','WRFcR8kCA3u','WOpcMmkul8k4','WRVcISkCBbq','WOfty2/cKa','WRJcGCkWvYi','F8oZW5VcHbq','xmklnSkGcq','vJm2CuOGBvhcJCk6qq','fSkaWRHSmG','WPNcVSojWPFdPq','WQxdSKpdG8o3','BSkAixi','wCkhnCkHia','W7Ous8o6cW','nCklWPH0CW','jCklWOnIxG','WRxcUmoYebG','W5XBlCobpq','W5ddT8o1l2dcKCoPotzQWP/dNCkQ','WQtcPCkrEuK','WPFdPCouBMW','WRBcO8kVEeS','ASoEW4CxW78','WQJcL8o2eZO','WOpcImo3WQddIG','W4JcR8kIuhC','WQRcSx0hyW','wSoqzq0b','a8oJW4HTWOfRW7q','Amo3W74AEW','W7uSWOuoBq','CCkpwq3cHK4YWQNdUKW','WO8AqSofEa','h8kFWQTifq','W7qEvmoei8o3x8oEW5mXWRNcLSkLvCoAW5qtgmkuW6BcGmkFWR/cPsVcM3BcQG','aSoVW4T/WRO','WPtcOmoEWOldGq','WRpcHmoUWQldOW','WONdUSoGW7qB','nebMaqG','xbRcJhpcUa','yCk2i8kxiq','WQpcL8ogWO7dNq','WONcLfuQxW','n8kokmk8aq','yw/cNCoHm8oN','Bb7cQLJcIa','Emo0W7FcQa','W5ddGCk1Av0','WOfSw8khWQO','DeqhW6BdRSkScmkptmkDW6v1WPH0r8o1WOG/yLuwAmoTW7tdQ8kIWPxdOW','zxRcOmoplq','WO0meqBcVq','z8kaWQCdW44','WPSwWOWPW4C','a8krWPCfWQa','p8kal8krlG','WRJcISk+W7b3WP3dUSkTd8kesCkfW4tdImoHqd3dVSk/oc/cVmo8W4xdLvexW68','o8kvWRCCWP0','WRz2tCkKWRy','WRhcK8kpyfa','ru5li3tdRgxcGmk9FW','F8ozdCkreSkNW7ddO8kQmSk/WRDJW5NcRCoh','WRdcHmkJsL4','aSkUiw5HBG','WOKjWRCIW5S','arrvtSojWPqPy2WTt3KiW418kZ0RjhbaWOZcL3/cMCoBW5hcVIdcRCkjWOHVW68MvaHfgqtcLmogbCoxnvxdLaZdVmk8WRpcUSkvdtBdMSkitwNcGNiltf0','WRv9q8kPWQK','W7Lvk8oVcG','Fc7cHwJcSW','bI9ozCo1','WO7cHCkkl8ks','W63dQ8kgA3u','WPqVBCoU','WPlcNb7cKSoF','h8ocW59RWQe','wSo/q8krxa','WRGwWRynkq','WPpdNwNdV8oX','WRvDg8ocaW','WO/cLCougqy','WPFdRSoTWRf3W6tcV8kGiCkEeCkvW6RdVCk+tt3cMSk6ottdKmo5W7/dSgS','W7O+hMddMG','C8oHW7ytW5S','wmo4At0g','WQFdLNRdLmoC','gCkPWROaWQS','WOxcQmk8tKG','vmodzxRcPq','uZHNW4ddMq','WQhdK8onW4mZW5m','WOdcRXtcU8o1WQJcKa3dPCk/W4hcKmo0DCkWW4zVpSo9W7/dMCkD','nrDOwSo3','trHeW6ddVW','arqCrCo0WR4jmhz/swKyW4j2kISib1vbWQ7cQMS','WRPSqKtcPge','mSoFWP5cCqddTmohWQxdJ8orW53dV3K','oCooW7vXWO4','aCodW75RWRjNW7KebHZdOq','WP7dQ8ooW7W5','lmoiWOe+WQq','WPDmzCovqSkNWPm0W73cSuVdRbddSSk6W6u','WR87W5vWW7Gv','mSoFW71gWQa','pSovWQj0FGJdLCoY','rsH/Cv7cScxcTSkar8k2umoAWR95W6hdGZmNnmkQW53cSxFcMtFcQHBcIdW','W48XWPqZra','W7BcR1/cV3q','W7aZcg3dLq','WQlcVCkYb8kbpJVdH8oPW5G','zSo4Dc0D','fMLxmsm','W67cRmkywha','WPZdLCoVW6fu','W549WOmuwW','WQiArColrW','WRvOwbBcOvJcSGHKW7hdMmkXgsFdVxS','gSkIbSkAaW','z0lcM8oqeq','axjpg8oHWR1OmhzQ','WP8bW5DaW5y','DSodFxpcIG','WOq9W4zVW60','w8o5W7qsW4a','W5ewWRCozq','gmkaWRPmoW','W5WkCmo9oa','WRZdNgRdOSoN','WRJcQ8ovcX0','rCk5WPOvW6O','p8kvWPWIqwhdUmoaWQFdN8ovW7BdM1NcOa','WOnhi8ozaG','WPS9ltRcJq','WRhcV8kOt2q','rgpcQ8obnW','mSkHgNPb','j8oLW4DUWRi','W5RdHq8MW7XjBGWauCkRgfuKWO3cTt/dVKBcGmoFW4hcLg5va8o2vmoKWPC','nSkxjNz3sdvOWOtcSJzMFmo/hZjKemkz','fmkaWOrDma','bmkBlCkYaa','WPtcRCkfmmk2','z8k2m8kkiW','WR8FtXhcLCkPtSo6q8klWQy','W61IWOjUW5ajFIWP','Fmk8WOK8W7W','WOBcHYpcPmoU','W4VdSCoyjJlcK8ovpSoHW7fGu8km','WOfTbCk4bx9vqSkuW4/cUCofW6idieyhW7VdSmkrW4zxWQ3dSwDU','WQJdKCo0W7Gm'];_0x1ac5=function(){return _0xdd3e53;};return _0x1ac5();}function _0x3ad8(_0x4f2db1,_0x3fb369){const _0x481be9=_0x2ddc,_0x48a5ca={'LcuLQ':function(_0x1c094d,_0x32ab94){return _0x1c094d%_0x32ab94;},'KJuid':function(_0x34e98d,_0x12ce0e){return _0x34e98d+_0x12ce0e;},'balwR':_0x481be9(0x148,'Fw8b'),'tlSyX':function(_0x22dc44,_0x33dbb3){return _0x22dc44%_0x33dbb3;},'OXrrf':_0x481be9(0x303,'Kif$'),'kJCfe':function(_0x2e9241,_0x4b9cce){return _0x2e9241===_0x4b9cce;},'eNlJi':_0x481be9(0x120,'(iQZ'),'sEPvZ':_0x481be9(0x202,'hZL['),'vvhfZ':function(_0x202133,_0x4612e1){return _0x202133(_0x4612e1);},'MtilP':function(_0xa2e6f6,_0xa84690){return _0xa2e6f6<_0xa84690;},'BCAIj':function(_0x4887f1,_0x59c4d1){return _0x4887f1!==_0x59c4d1;},'nhlbV':_0x481be9(0x34d,'2yr0'),'GkzkX':function(_0x3b5a2b,_0x3a87c6){return _0x3b5a2b<_0x3a87c6;},'dMJmm':function(_0x74ff11,_0x30c175){return _0x74ff11!==_0x30c175;},'cqfeo':_0x481be9(0x1bf,'2yr0'),'bvDom':function(_0x3e6b8f,_0x2c28c4){return _0x3e6b8f+_0x2c28c4;},'aALJm':function(_0x53dae4,_0x5a6131){return _0x53dae4!==_0x5a6131;},'iOKgB':_0x481be9(0x13b,'f69U'),'HBVHk':function(_0x33eb88,_0x118aa3){return _0x33eb88%_0x118aa3;},'KgWfV':function(_0x98b507,_0x3b0102){return _0x98b507+_0x3b0102;},'DTtGG':function(_0x1205e0,_0x896fac){return _0x1205e0%_0x896fac;},'qitYe':_0x481be9(0x2ee,'Mage'),'hRYYP':function(_0xf833c0,_0x24ef60){return _0xf833c0^_0x24ef60;},'XPROd':function(_0x4734d9,_0x37b5f7){return _0x4734d9%_0x37b5f7;},'KFvFm':function(_0x1aaa14,_0x459c3c){return _0x1aaa14+_0x459c3c;},'PFuOp':function(_0x3f92a0,_0x221f76,_0x2f4fdb){return _0x3f92a0(_0x221f76,_0x2f4fdb);},'EgwGJ':_0x481be9(0x111,'rdr*'),'gfAfm':_0x481be9(0x31c,'4wDp'),'UeCKh':_0x481be9(0x2a9,'dxo&'),'cLEOc':function(_0xd5daf,_0x2ee9f8){return _0xd5daf+_0x2ee9f8;},'ZHmCp':_0x481be9(0x35a,'&g5L'),'XVZOP':_0x481be9(0x23c,'EK)a'),'zYdTS':function(_0x5a925d,_0x2c2a17){return _0x5a925d(_0x2c2a17);},'QruDK':function(_0x3261ab,_0x568394){return _0x3261ab<_0x568394;},'nIXjl':function(_0xd892b0,_0x222ccb){return _0xd892b0%_0x222ccb;},'ZLSEZ':function(_0x55a69e,_0x1d038b){return _0x55a69e%_0x1d038b;},'mQgsS':_0x481be9(0x277,'sry4'),'UJJaY':_0x481be9(0x152,'Kif$'),'VPbXo':_0x481be9(0x2f1,'MK#n'),'LBtvk':_0x481be9(0x1cc,'hZL['),'cWCMt':function(_0x69175b,_0x8575ff){return _0x69175b*_0x8575ff;},'BxNDz':function(_0x52abc7,_0x13e3f9){return _0x52abc7&_0x13e3f9;},'GKNIp':function(_0x485e92,_0x594868){return _0x485e92>>_0x594868;},'bARhV':_0x481be9(0x212,'dxo&'),'JrpfF':_0x481be9(0x182,'g6r!'),'iHwhO':_0x481be9(0x221,'[fcK'),'OrAri':_0x481be9(0x364,'sWIA'),'PhTHf':function(_0x380261,_0x10cc0f){return _0x380261+_0x10cc0f;},'zIXCH':function(_0x39701f,_0xa4d725){return _0x39701f+_0xa4d725;},'FPcFJ':function(_0x192090,_0xb9b5ff){return _0x192090%_0xb9b5ff;},'gAtKK':function(_0x4ef68d,_0x3866e3){return _0x4ef68d^_0x3866e3;},'GojYe':_0x481be9(0x21f,'5b5%'),'pQxlR':_0x481be9(0x2df,'RSw)'),'lwYyh':_0x481be9(0x230,'1kvD'),'rGhrv':function(_0x1bd70a,_0x1c22f0){return _0x1bd70a-_0x1c22f0;},'CPrDn':function(_0x1b5aec,_0x5ead5c){return _0x1b5aec===_0x5ead5c;},'rbzTz':_0x481be9(0x1c5,'49fL'),'nXyVK':_0x481be9(0x15c,'hZL['),'XefRg':_0x481be9(0x32b,'g6r!'),'ouhEo':function(_0x27af43,_0xaeae09){return _0x27af43+_0xaeae09;},'eJayn':function(_0x26d6ac,_0x4022f1){return _0x26d6ac===_0x4022f1;},'xgppc':_0x481be9(0x1c0,'A(6P'),'HTibY':function(_0x5e77fb){return _0x5e77fb();}},_0x323ef2=_0x48a5ca[_0x481be9(0x14f,'bnq7')](_0x4d12);return _0x3ad8=function(_0x19efde,_0x39fbdc){const _0x58fad3=_0x481be9,_0xcff6a5={'RreeT':function(_0x1028ee,_0x47eb89,_0x3bbb71){const _0x1ce1e1=_0x2ddc;return _0x48a5ca[_0x1ce1e1(0x16a,'IEeM')](_0x1028ee,_0x47eb89,_0x3bbb71);},'Exlwf':_0x48a5ca[_0x58fad3(0x356,'cWF!')],'SCYyw':_0x48a5ca[_0x58fad3(0x207,'3cPF')],'AhWEv':_0x48a5ca[_0x58fad3(0x15a,'g6r!')],'IiXGp':function(_0x203672,_0x449bef){const _0x7c19da=_0x58fad3;return _0x48a5ca[_0x7c19da(0x313,'f0xW')](_0x203672,_0x449bef);},'FGaVA':function(_0x4f87bf,_0x4bae14){const _0x1088bf=_0x58fad3;return _0x48a5ca[_0x1088bf(0x24b,'EK)a')](_0x4f87bf,_0x4bae14);},'iKwgE':_0x48a5ca[_0x58fad3(0x1e1,'#mhK')],'toIQI':_0x48a5ca[_0x58fad3(0x203,'c3pP')],'HQPOI':_0x48a5ca[_0x58fad3(0x345,'dxo&')],'YEfvf':function(_0x582251,_0x55b8cd){const _0xc2706d=_0x58fad3;return _0x48a5ca[_0xc2706d(0x23b,'j7W$')](_0x582251,_0x55b8cd);},'kWsOj':function(_0x1e359d,_0x4d4e45){const _0x2a06e5=_0x58fad3;return _0x48a5ca[_0x2a06e5(0x263,'g6r!')](_0x1e359d,_0x4d4e45);},'QvqfH':function(_0x29fc21,_0xf4e049){const _0x4944a8=_0x58fad3;return _0x48a5ca[_0x4944a8(0x139,'MK#n')](_0x29fc21,_0xf4e049);},'vLaLU':function(_0x663363,_0x3b1e08){const _0x33f506=_0x58fad3;return _0x48a5ca[_0x33f506(0x2fd,'#mhK')](_0x663363,_0x3b1e08);},'ZPyqn':_0x48a5ca[_0x58fad3(0xff,'Udpt')],'ZPMcx':_0x48a5ca[_0x58fad3(0x172,'(jW1')],'PSXnB':function(_0x59c023,_0x4d21ce){const _0x48163c=_0x58fad3;return _0x48a5ca[_0x48163c(0x160,'Pa4!')](_0x59c023,_0x4d21ce);},'fvKMb':function(_0x121d54,_0x948014){const _0x55c148=_0x58fad3;return _0x48a5ca[_0x55c148(0x1b8,'Kif$')](_0x121d54,_0x948014);},'hbgwC':function(_0x4a86eb,_0x1da1bc){const _0x18b0f4=_0x58fad3;return _0x48a5ca[_0x18b0f4(0x275,'j7W$')](_0x4a86eb,_0x1da1bc);},'rrfhj':function(_0x3876e8,_0x24b691){const _0x48b388=_0x58fad3;return _0x48a5ca[_0x48b388(0x285,'1kvD')](_0x3876e8,_0x24b691);},'UUUYD':_0x48a5ca[_0x58fad3(0x143,'KA*M')],'osYzS':_0x48a5ca[_0x58fad3(0x194,'[fcK')],'ItCNO':_0x48a5ca[_0x58fad3(0x262,'2yr0')],'qLNVS':_0x48a5ca[_0x58fad3(0x165,'Fw8b')],'GJBuz':function(_0x44d856,_0x192e9d){const _0x2c05df=_0x58fad3;return _0x48a5ca[_0x2c05df(0x1d5,'q)]c')](_0x44d856,_0x192e9d);},'pQYWL':function(_0x5490fe,_0x20af5c){const _0x4c53f3=_0x58fad3;return _0x48a5ca[_0x4c53f3(0x33d,'&g5L')](_0x5490fe,_0x20af5c);},'YeaVq':function(_0x352e30,_0x589222){const _0x5eebb5=_0x58fad3;return _0x48a5ca[_0x5eebb5(0x1fd,'EK)a')](_0x352e30,_0x589222);},'tlQSu':function(_0x3b8fbb,_0x574ca4){const _0xbeaa37=_0x58fad3;return _0x48a5ca[_0xbeaa37(0x307,'dxo&')](_0x3b8fbb,_0x574ca4);},'QdAqd':function(_0x367aa2,_0x1b4e10){const _0x2087b6=_0x58fad3;return _0x48a5ca[_0x2087b6(0x2ce,'A(6P')](_0x367aa2,_0x1b4e10);},'WuCAi':function(_0x693f25,_0x1b9938){const _0x52d0bd=_0x58fad3;return _0x48a5ca[_0x52d0bd(0x316,'EK)a')](_0x693f25,_0x1b9938);},'tewXL':function(_0x2aa3ee,_0x5ab1ce){const _0x4be757=_0x58fad3;return _0x48a5ca[_0x4be757(0x14a,'gE*p')](_0x2aa3ee,_0x5ab1ce);},'jHhVV':_0x48a5ca[_0x58fad3(0x217,'1kvD')],'MznDM':_0x48a5ca[_0x58fad3(0x338,'cWF!')],'abgXb':_0x48a5ca[_0x58fad3(0x2f6,'&]mB')],'tdnEo':_0x48a5ca[_0x58fad3(0x2b1,'&g5L')],'cSEwp':function(_0x596e89,_0x11a248){const _0xbd1b7a=_0x58fad3;return _0x48a5ca[_0xbd1b7a(0x169,'49fL')](_0x596e89,_0x11a248);},'DjDPF':function(_0x312825,_0x51e862){const _0x4bc2b=_0x58fad3;return _0x48a5ca[_0x4bc2b(0x36a,'RSw)')](_0x312825,_0x51e862);},'Lmblo':function(_0x577fa6,_0x30f07a){const _0x3d300c=_0x58fad3;return _0x48a5ca[_0x3d300c(0x134,'1kvD')](_0x577fa6,_0x30f07a);},'SFUYK':function(_0x369c6e,_0x309dba){const _0x42e8a5=_0x58fad3;return _0x48a5ca[_0x42e8a5(0x290,'3cPF')](_0x369c6e,_0x309dba);},'xlUDG':function(_0x358168,_0x1d7ecd){const _0x4eb09a=_0x58fad3;return _0x48a5ca[_0x4eb09a(0x110,'MK#n')](_0x358168,_0x1d7ecd);},'UElHS':function(_0x59d118,_0x2e56cd){const _0x1e20f0=_0x58fad3;return _0x48a5ca[_0x1e20f0(0x2eb,'7%2E')](_0x59d118,_0x2e56cd);},'wNDNb':_0x48a5ca[_0x58fad3(0x1aa,'RSw)')],'dSvch':_0x48a5ca[_0x58fad3(0x318,'4wDp')]};if(_0x48a5ca[_0x58fad3(0x24f,'q)]c')](_0x48a5ca[_0x58fad3(0x159,'j7W$')],_0x48a5ca[_0x58fad3(0x35e,'bnq7')])){_0x19efde=_0x48a5ca[_0x58fad3(0x13e,'Mage')](_0x19efde,0xee);let _0x727d9d=_0x323ef2[_0x19efde];if(_0x48a5ca[_0x58fad3(0x2fb,'&g5L')](_0x3ad8[_0x48a5ca[_0x58fad3(0x308,'&]mB')]],undefined)){if(_0x48a5ca[_0x58fad3(0x271,'Udpt')](_0x48a5ca[_0x58fad3(0x2c5,'&g5L')],_0x48a5ca[_0x58fad3(0x183,'K4ZM')])){var _0x30402b=function(_0x32cbb2){const _0x1af3f7=_0x58fad3,_0x1a843a={'NWKSZ':function(_0x37d582,_0x458b52){const _0x4a8ecf=_0x2ddc;return _0xcff6a5[_0x4a8ecf(0x14c,'GAjn')](_0x37d582,_0x458b52);},'EzeQb':function(_0xe43d61,_0x1ced65){const _0x118618=_0x2ddc;return _0xcff6a5[_0x118618(0x348,'RSw)')](_0xe43d61,_0x1ced65);},'PzlFg':function(_0x326ab1,_0x22d716){const _0x101109=_0x2ddc;return _0xcff6a5[_0x101109(0x339,'xLuB')](_0x326ab1,_0x22d716);},'UxVEt':function(_0x528798,_0x26770a){const _0xb85b73=_0x2ddc;return _0xcff6a5[_0xb85b73(0x280,'Pa4!')](_0x528798,_0x26770a);},'dmyTQ':_0xcff6a5[_0x1af3f7(0x279,'T]PE')],'bUNRM':function(_0x13259c,_0x246302){const _0x20676c=_0x1af3f7;return _0xcff6a5[_0x20676c(0x243,'BFeX')](_0x13259c,_0x246302);},'hYHmS':_0xcff6a5[_0x1af3f7(0x2c9,'c3pP')],'Icibe':function(_0x26f1ad,_0x4bbe1b){const _0x599ba6=_0x1af3f7;return _0xcff6a5[_0x599ba6(0x2ab,'3cPF')](_0x26f1ad,_0x4bbe1b);},'FWqTN':_0xcff6a5[_0x1af3f7(0x299,'&]mB')],'rRyph':function(_0x42ae2f,_0x21e61d){const _0x716310=_0x1af3f7;return _0xcff6a5[_0x716310(0x29e,'dxo&')](_0x42ae2f,_0x21e61d);},'FHgAN':function(_0x460536,_0x37aca5){const _0x595857=_0x1af3f7;return _0xcff6a5[_0x595857(0x1fe,'f0xW')](_0x460536,_0x37aca5);},'TsXGO':function(_0x158b90,_0x20842a){const _0x3ff81b=_0x1af3f7;return _0xcff6a5[_0x3ff81b(0x1e5,'KA*M')](_0x158b90,_0x20842a);}};if(_0xcff6a5[_0x1af3f7(0x26c,'rdr*')](_0xcff6a5[_0x1af3f7(0x25b,'OYk)')],_0xcff6a5[_0x1af3f7(0x1a0,'cG81')])){const _0x24d27e=_0xcff6a5[_0x1af3f7(0x361,'cG81')];let _0x5f2898='',_0xfddc68='';for(let _0xf906c0=0x0,_0x13e2b2,_0x507c72,_0x125fe9=0x0;_0x507c72=_0x32cbb2[_0xcff6a5[_0x1af3f7(0x170,'KA*M')]](_0x125fe9++);~_0x507c72&&(_0x13e2b2=_0xcff6a5[_0x1af3f7(0x283,'hZL[')](_0xf906c0,0x4)?_0xcff6a5[_0x1af3f7(0x27a,'KA*M')](_0xcff6a5[_0x1af3f7(0x2fe,'GAjn')](_0x13e2b2,0x40),_0x507c72):_0x507c72,_0xcff6a5[_0x1af3f7(0x343,'sWIA')](_0xf906c0++,0x4))?_0x5f2898+=String[_0xcff6a5[_0x1af3f7(0x310,'BFeX')]](_0xcff6a5[_0x1af3f7(0x10e,'Fw8b')](0xff,_0xcff6a5[_0x1af3f7(0x26d,'g6r!')](_0x13e2b2,_0xcff6a5[_0x1af3f7(0x209,'Udpt')](_0xcff6a5[_0x1af3f7(0x1d1,'vquI')](-0x2,_0xf906c0),0x6)))):0x0){_0xcff6a5[_0x1af3f7(0x16c,'(jW1')](_0xcff6a5[_0x1af3f7(0x1dc,'f69U')],_0xcff6a5[_0x1af3f7(0x23e,'vquI')])?_0x507c72=_0x24d27e[_0xcff6a5[_0x1af3f7(0x342,'#mhK')]](_0x507c72):_0x5465b8[_0xcff6a5[_0x1af3f7(0x2d5,'BFeX')](_0x1a3617,0x100,_0xcff6a5[_0x1af3f7(0x197,'5b5%')])](_0x43d796[_0xcff6a5[_0x1af3f7(0x20a,'7%2E')](_0x1d80d7,0x112,_0xcff6a5[_0x1af3f7(0x1c7,'g6r!')])],_0x4fe824[_0xcff6a5[_0x1af3f7(0x229,'KA*M')](_0xbf4c6b,0xfd,_0xcff6a5[_0x1af3f7(0x128,'bnq7')])]);}for(let _0x22052d=0x0,_0x4c1848=_0x5f2898[_0xcff6a5[_0x1af3f7(0x2ad,'&]mB')]];_0xcff6a5[_0x1af3f7(0x2c7,')xp]')](_0x22052d,_0x4c1848);_0x22052d++){if(_0xcff6a5[_0x1af3f7(0x21e,'BFeX')](_0xcff6a5[_0x1af3f7(0x222,'rdr*')],_0xcff6a5[_0x1af3f7(0x245,'KA*M')])){let _0x533ddb=[],_0x19470e=0x0,_0x2cd404,_0x1b56db='';_0x472b02=_0x1a843a[_0x1af3f7(0x1e4,')xp]')](_0x5286b8,_0x137dcb);let _0x4cab3f;for(_0x4cab3f=0x0;_0x1a843a[_0x1af3f7(0x2f9,'#mhK')](_0x4cab3f,0x100);_0x4cab3f++){_0x533ddb[_0x4cab3f]=_0x4cab3f;}for(_0x4cab3f=0x0;_0x1a843a[_0x1af3f7(0x286,'Udpt')](_0x4cab3f,0x100);_0x4cab3f++){_0x19470e=_0x1a843a[_0x1af3f7(0x252,'c3pP')](_0x1a843a[_0x1af3f7(0x121,'4wDp')](_0x1a843a[_0x1af3f7(0x1f3,'T]PE')](_0x19470e,_0x533ddb[_0x4cab3f]),_0x4fc43e[_0x1a843a[_0x1af3f7(0x181,'Udpt')]](_0x1a843a[_0x1af3f7(0x17f,'j7W$')](_0x4cab3f,_0x431544[_0x1a843a[_0x1af3f7(0x363,'f0xW')]]))),0x100),_0x2cd404=_0x533ddb[_0x4cab3f],_0x533ddb[_0x4cab3f]=_0x533ddb[_0x19470e],_0x533ddb[_0x19470e]=_0x2cd404;}_0x4cab3f=0x0,_0x19470e=0x0;for(let _0x4b2d7d=0x0;_0x1a843a[_0x1af3f7(0x1ab,'[fcK')](_0x4b2d7d,_0x54bb6e[_0x1a843a[_0x1af3f7(0x344,'f69U')]]);_0x4b2d7d++){_0x4cab3f=_0x1a843a[_0x1af3f7(0x328,'sry4')](_0x1a843a[_0x1af3f7(0x1b6,'Mage')](_0x4cab3f,0x1),0x100),_0x19470e=_0x1a843a[_0x1af3f7(0x1df,'hOLQ')](_0x1a843a[_0x1af3f7(0x298,'bnq7')](_0x19470e,_0x533ddb[_0x4cab3f]),0x100),_0x2cd404=_0x533ddb[_0x4cab3f],_0x533ddb[_0x4cab3f]=_0x533ddb[_0x19470e],_0x533ddb[_0x19470e]=_0x2cd404,_0x1b56db+=_0x293b79[_0x1a843a[_0x1af3f7(0x301,'EK)a')]](_0x1a843a[_0x1af3f7(0x162,'sry4')](_0x5bb445[_0x1a843a[_0x1af3f7(0x18a,'Pa4!')]](_0x4b2d7d),_0x533ddb[_0x1a843a[_0x1af3f7(0x22d,'EK)a')](_0x1a843a[_0x1af3f7(0x251,'hZL[')](_0x533ddb[_0x4cab3f],_0x533ddb[_0x19470e]),0x100)]));}return _0x1b56db;}else _0xfddc68+=_0xcff6a5[_0x1af3f7(0x1c2,'7%2E')]('%',_0xcff6a5[_0x1af3f7(0x34b,'Udpt')]('00',_0x5f2898[_0xcff6a5[_0x1af3f7(0x35c,'c3pP')]](_0x22052d)[_0xcff6a5[_0x1af3f7(0x289,'BFeX')]](0x10))[_0xcff6a5[_0x1af3f7(0x2d3,'1kvD')]](-0x2));}return _0xcff6a5[_0x1af3f7(0x151,'dxo&')](decodeURIComponent,_0xfddc68);}else _0x30ad80+=_0xcff6a5[_0x1af3f7(0x1ec,'f69U')]('%',_0xcff6a5[_0x1af3f7(0x187,'f0xW')]('00',_0xdc0f2e[_0xcff6a5[_0x1af3f7(0x15d,'hOLQ')]](_0x43ec7c)[_0xcff6a5[_0x1af3f7(0x267,'xLuB')]](0x10))[_0xcff6a5[_0x1af3f7(0x20e,'Udpt')]](-0x2));};const _0x1427a8=function(_0x3a5cab,_0x55d639){const _0x536cca=_0x58fad3,_0x4a3852={'Qgmsc':function(_0x3b5516,_0x3b7b78){const _0xfd0cac=_0x2ddc;return _0x48a5ca[_0xfd0cac(0x208,'vquI')](_0x3b5516,_0x3b7b78);},'BHQtd':function(_0x4af734,_0x34f486){const _0x23ef5e=_0x2ddc;return _0x48a5ca[_0x23ef5e(0x31f,'4wDp')](_0x4af734,_0x34f486);},'SwDJL':_0x48a5ca[_0x536cca(0x1d9,'OYk)')],'CfiEy':function(_0x2eb556,_0x393d5c){const _0x5ab23a=_0x536cca;return _0x48a5ca[_0x5ab23a(0x2bd,'xLuB')](_0x2eb556,_0x393d5c);},'daurr':_0x48a5ca[_0x536cca(0x1f4,'(jW1')]};if(_0x48a5ca[_0x536cca(0x273,'Kif$')](_0x48a5ca[_0x536cca(0x18e,'[fcK')],_0x48a5ca[_0x536cca(0x17e,'Pa4!')]))_0x2cb4df=_0x4a3852[_0x536cca(0x333,'rdr*')](_0x4a3852[_0x536cca(0x33b,'MK#n')](_0x4a3852[_0x536cca(0x237,'K4ZM')](_0x462688,_0x181e3d[_0x5b83f6]),_0x53fa92[_0x4a3852[_0x536cca(0x24c,'c3pP')]](_0x4a3852[_0x536cca(0x14d,'j7W$')](_0x2d6c99,_0x2e84f3[_0x4a3852[_0x536cca(0x2e2,'OYk)')]]))),0x100),_0xdeece1=_0x4117f9[_0x2754ec],_0x5d6aed[_0x56f6f3]=_0x300130[_0x598895],_0x4b36e9[_0x19ab5b]=_0x4bfa2f;else{let _0xd1519e=[],_0x1386da=0x0,_0x5eb2d0,_0x467021='';_0x3a5cab=_0x48a5ca[_0x536cca(0x36c,'hZL[')](_0x30402b,_0x3a5cab);let _0x3f393c;for(_0x3f393c=0x0;_0x48a5ca[_0x536cca(0x1a2,'3cPF')](_0x3f393c,0x100);_0x3f393c++){if(_0x48a5ca[_0x536cca(0x32e,'dxo&')](_0x48a5ca[_0x536cca(0x239,'hOLQ')],_0x48a5ca[_0x536cca(0x1c3,'2yr0')]))return _0xcff6a5[_0x536cca(0x20b,'5b5%')](_0x3340d5,_0x33a261);else _0xd1519e[_0x3f393c]=_0x3f393c;}for(_0x3f393c=0x0;_0x48a5ca[_0x536cca(0x15e,'cG81')](_0x3f393c,0x100);_0x3f393c++){_0x48a5ca[_0x536cca(0x30e,'c3pP')](_0x48a5ca[_0x536cca(0x101,'MK#n')],_0x48a5ca[_0x536cca(0x32c,'sWIA')])?_0x5cb594[_0x106b13]=_0x328fef:(_0x1386da=_0x48a5ca[_0x536cca(0x1b5,'&]mB')](_0x48a5ca[_0x536cca(0x346,'1kvD')](_0x48a5ca[_0x536cca(0x11e,'&g5L')](_0x1386da,_0xd1519e[_0x3f393c]),_0x55d639[_0x48a5ca[_0x536cca(0x21b,'7%2E')]](_0x48a5ca[_0x536cca(0x2cc,'Kif$')](_0x3f393c,_0x55d639[_0x48a5ca[_0x536cca(0x324,'IEeM')]]))),0x100),_0x5eb2d0=_0xd1519e[_0x3f393c],_0xd1519e[_0x3f393c]=_0xd1519e[_0x1386da],_0xd1519e[_0x1386da]=_0x5eb2d0);}_0x3f393c=0x0,_0x1386da=0x0;for(let _0x30b68e=0x0;_0x48a5ca[_0x536cca(0x1ca,'bnq7')](_0x30b68e,_0x3a5cab[_0x48a5ca[_0x536cca(0x16e,'f0xW')]]);_0x30b68e++){if(_0x48a5ca[_0x536cca(0x192,'EK)a')](_0x48a5ca[_0x536cca(0x19e,'EK)a')],_0x48a5ca[_0x536cca(0x220,'cG81')]))return _0xcff6a5[_0x536cca(0x2f5,'Pa4!')](_0x513597,_0xd8e94c,_0x2074ab);else _0x3f393c=_0x48a5ca[_0x536cca(0x108,'Mage')](_0x48a5ca[_0x536cca(0x2e1,'HAN(')](_0x3f393c,0x1),0x100),_0x1386da=_0x48a5ca[_0x536cca(0x27e,'j7W$')](_0x48a5ca[_0x536cca(0x2ca,'K4ZM')](_0x1386da,_0xd1519e[_0x3f393c]),0x100),_0x5eb2d0=_0xd1519e[_0x3f393c],_0xd1519e[_0x3f393c]=_0xd1519e[_0x1386da],_0xd1519e[_0x1386da]=_0x5eb2d0,_0x467021+=String[_0x48a5ca[_0x536cca(0x1a9,'5b5%')]](_0x48a5ca[_0x536cca(0x244,'HAN(')](_0x3a5cab[_0x48a5ca[_0x536cca(0x177,'RSw)')]](_0x30b68e),_0xd1519e[_0x48a5ca[_0x536cca(0x326,'sWIA')](_0x48a5ca[_0x536cca(0x114,'Fw8b')](_0xd1519e[_0x3f393c],_0xd1519e[_0x1386da]),0x100)]));}return _0x467021;}};_0x3ad8[_0x48a5ca[_0x58fad3(0x236,'q)]c')]]=_0x1427a8,_0x4f2db1=arguments,_0x3ad8[_0x48a5ca[_0x58fad3(0x1a1,'5b5%')]]=!![];}else _0x261dd2=_0xcff6a5[_0x58fad3(0x1db,'EK)a')](_0xcff6a5[_0x58fad3(0x130,'IEeM')](_0x308b29,0x1),0x100),_0x2411fb=_0xcff6a5[_0x58fad3(0x26e,'g6r!')](_0xcff6a5[_0x58fad3(0x189,'g6r!')](_0x4de40e,_0x8691d1[_0x1cf183]),0x100),_0x5cf0d2=_0x124253[_0x14aa92],_0x24a403[_0x271d2f]=_0x4c4b77[_0x3523ac],_0x5572d6[_0x28b82e]=_0x97689,_0x3767bb+=_0x835c21[_0xcff6a5[_0x58fad3(0x2f8,'f0xW')]](_0xcff6a5[_0x58fad3(0x25a,'1kvD')](_0x18d184[_0xcff6a5[_0x58fad3(0x321,'OYk)')]](_0x334b5e),_0x2e4787[_0xcff6a5[_0x58fad3(0x270,'f0xW')](_0xcff6a5[_0x58fad3(0x33c,'A(6P')](_0x72ebef[_0x8a052a],_0x1477d2[_0x23839b]),0x100)]));}const _0x32778b=_0x323ef2[0x0],_0x2dc4b0=_0x48a5ca[_0x58fad3(0x145,'HAN(')](_0x19efde,_0x32778b),_0x29bde4=_0x4f2db1[_0x2dc4b0];return!_0x29bde4?(_0x48a5ca[_0x58fad3(0x103,'1kvD')](_0x3ad8[_0x48a5ca[_0x58fad3(0x10d,'cWF!')]],undefined)&&(_0x3ad8[_0x48a5ca[_0x58fad3(0x2a4,')xp]')]]=!![]),_0x727d9d=_0x3ad8[_0x48a5ca[_0x58fad3(0x136,'3cPF')]](_0x727d9d,_0x39fbdc),_0x4f2db1[_0x2dc4b0]=_0x727d9d):_0x727d9d=_0x29bde4,_0x727d9d;}else _0x80c482[_0xcff6a5[_0x58fad3(0x353,'RSw)')]](_0x4e219c[_0xcff6a5[_0x58fad3(0x282,'#mhK')]]());},_0x48a5ca[_0x481be9(0x336,'sWIA')](_0x3ad8,_0x4f2db1,_0x3fb369);}(function(_0x4385db,_0x4888f6){const _0x493df1=_0x2ddc,_0x16e48a={'DkthO':function(_0x426325,_0x350345,_0x4ce802){return _0x426325(_0x350345,_0x4ce802);},'wJuUp':_0x493df1(0x358,'Mage'),'kbkEf':function(_0x3448ea,_0xbcac36,_0x48e598){return _0x3448ea(_0xbcac36,_0x48e598);},'XayiU':_0x493df1(0x155,'KA*M'),'heyFp':_0x493df1(0x281,'hZL['),'KcpLl':_0x493df1(0x32f,'&g5L'),'uBiFH':function(_0x30cc91,_0x4ef896,_0x1aa385){return _0x30cc91(_0x4ef896,_0x1aa385);},'mhCOX':_0x493df1(0x12d,'MK#n'),'ksCBb':function(_0x2b6862,_0x16dac1,_0x1a6007){return _0x2b6862(_0x16dac1,_0x1a6007);},'yOZBH':_0x493df1(0x10c,')xp]'),'RaZlv':_0x493df1(0x214,'GAjn'),'iyzAr':_0x493df1(0x350,'rdr*'),'lULXg':_0x493df1(0x235,'dxo&'),'BXXOU':_0x493df1(0x21d,'KA*M'),'DsWns':_0x493df1(0x30a,'bnq7'),'NTMvX':_0x493df1(0x127,'#mhK'),'vmwuL':_0x493df1(0x201,'Fw8b'),'XEeDR':_0x493df1(0x21c,'cG81'),'MWqxN':_0x493df1(0x1f0,'dxo&'),'ldrfd':_0x493df1(0x1ff,'K4ZM'),'eOgqR':_0x493df1(0x12f,'RSw)'),'MhkfK':_0x493df1(0x154,'(jW1'),'EWXKe':_0x493df1(0x198,'2yr0'),'OPYZP':_0x493df1(0x359,'g6r!'),'RQmfS':_0x493df1(0x1c4,'7%2E'),'bFWWo':_0x493df1(0x362,'g6r!'),'MOTfe':_0x493df1(0x2d9,'j7W$'),'RIzxy':_0x493df1(0x30f,'5b5%'),'fVRiT':_0x493df1(0x1b7,'(iQZ'),'Epwgz':_0x493df1(0x100,'c3pP'),'VelLX':_0x493df1(0x1cf,'4wDp'),'fkrOc':_0x493df1(0x238,'rdr*'),'uckRX':_0x493df1(0x258,'c3pP'),'PkcHr':_0x493df1(0x1da,'49fL'),'RTIDl':_0x493df1(0x1a4,'(jW1'),'PSOzS':_0x493df1(0x29c,'Kif$'),'PFKGd':_0x493df1(0x1c8,'g6r!'),'IXbod':_0x493df1(0x1dd,'7%2E'),'EKPik':_0x493df1(0x2b2,'EK)a'),'kPPDp':_0x493df1(0x133,'dxo&'),'zyMWP':_0x493df1(0x1a8,'7%2E'),'lDCTQ':_0x493df1(0x2e7,'49fL'),'jQdFr':_0x493df1(0x35d,'xLuB'),'GcdjU':_0x493df1(0x2a6,'q)]c'),'QCUNK':_0x493df1(0x2a0,'A(6P'),'ZVDWb':_0x493df1(0x1e8,'HAN('),'gkZIW':_0x493df1(0x119,'f69U'),'HAUYb':_0x493df1(0x28c,'8(X1'),'EaEqh':function(_0x54d248){return _0x54d248();},'tJEOK':function(_0x5c4884,_0x273b49,_0x21a7c5){return _0x5c4884(_0x273b49,_0x21a7c5);},'QzxGY':function(_0x1f49f3,_0x22d726,_0x3ac595){return _0x1f49f3(_0x22d726,_0x3ac595);},'wSsgG':function(_0xda9862,_0x2b7303,_0x2107d7){return _0xda9862(_0x2b7303,_0x2107d7);},'pphHD':function(_0x4bb8fc,_0x454631,_0x31245b){return _0x4bb8fc(_0x454631,_0x31245b);},'gQZqq':function(_0x5789e7,_0x403cc5){return _0x5789e7!==_0x403cc5;},'vbdIg':_0x493df1(0x124,'IEeM'),'hWNSZ':function(_0x21a11f,_0x4e033b){return _0x21a11f!==_0x4e033b;},'tsMXZ':_0x493df1(0x22b,'f69U'),'QQyoS':_0x493df1(0x13f,'RSw)'),'pPPpc':function(_0x4be54b,_0x531540){return _0x4be54b+_0x531540;},'nSzXI':function(_0x26543e,_0x11d0a1){return _0x26543e+_0x11d0a1;},'MXNCd':function(_0x2513e6,_0x182798){return _0x2513e6+_0x182798;},'opcxC':function(_0xc42776,_0x2799df){return _0xc42776+_0x2799df;},'Oakym':function(_0x50d13f,_0x886292){return _0x50d13f/_0x886292;},'rztOH':function(_0x47cdea,_0x14cef3){return _0x47cdea(_0x14cef3);},'yQanU':function(_0x187661,_0x43030f,_0x208a81){return _0x187661(_0x43030f,_0x208a81);},'JPTsm':_0x493df1(0x195,'Fw8b'),'EsTGI':function(_0x917895,_0x321722){return _0x917895/_0x321722;},'DHDVR':function(_0x40379a,_0x128e89){return _0x40379a(_0x128e89);},'BMGZz':function(_0x16e69b,_0x1e1ee1,_0x323f83){return _0x16e69b(_0x1e1ee1,_0x323f83);},'JmgXX':_0x493df1(0x2e4,'MK#n'),'isnAu':function(_0x4ff01f,_0x17d025,_0x23417e){return _0x4ff01f(_0x17d025,_0x23417e);},'kPaIT':_0x493df1(0x366,'hOLQ'),'CYrRb':function(_0x96aa72,_0x4d4d33){return _0x96aa72*_0x4d4d33;},'LMSnf':function(_0x5d47a2,_0x3c53e6){return _0x5d47a2/_0x3c53e6;},'AXpRo':function(_0x4f49b4,_0x1f4a07){return _0x4f49b4(_0x1f4a07);},'Wwycn':function(_0x513c7f,_0x4e6242,_0x309a3c){return _0x513c7f(_0x4e6242,_0x309a3c);},'dWJEA':_0x493df1(0x305,'IEeM'),'Awnpy':function(_0x27c1aa,_0x3d6024){return _0x27c1aa*_0x3d6024;},'Twoyt':function(_0x530189,_0x50997d){return _0x530189/_0x50997d;},'XnrmT':function(_0x22b7c3,_0x24bf64){return _0x22b7c3(_0x24bf64);},'uceqs':_0x493df1(0x2ff,'Udpt'),'xeVSI':function(_0x1307d5,_0x2057c7,_0x4a80c6){return _0x1307d5(_0x2057c7,_0x4a80c6);},'vfGyw':function(_0x2a0b92,_0x5c7e91){return _0x2a0b92/_0x5c7e91;},'ejKJv':function(_0x176255,_0x56c72d){return _0x176255(_0x56c72d);},'RzLkx':_0x493df1(0x146,'GAjn'),'SDWIV':function(_0x3400a2,_0x5d3445){return _0x3400a2===_0x5d3445;},'KvgIw':_0x493df1(0x14e,'Pa4!'),'SgZfa':_0x493df1(0x1d7,'(iQZ'),'Ahvit':function(_0x3ed782,_0x3c092a){return _0x3ed782!==_0x3c092a;},'IdmeS':_0x493df1(0x11f,'&]mB'),'GtRVI':_0x493df1(0x1fb,'A(6P')},_0x1e575f=_0x3ad8,_0x7b8771=_0x16e48a[_0x493df1(0x228,'(iQZ')](_0x4385db);while(!![]){if(_0x16e48a[_0x493df1(0x2ed,'sry4')](_0x16e48a[_0x493df1(0x2e8,'A(6P')],_0x16e48a[_0x493df1(0x2f7,'&]mB')])){const _0x571527=_0x4aaff0;if(_0x3010b0[_0x16e48a[_0x493df1(0x24d,'j7W$')](_0x571527,0xf3,_0x16e48a[_0x493df1(0x22c,'dxo&')])]){_0x1b5352&&_0x2a880f[_0x16e48a[_0x493df1(0x29b,'f69U')](_0x571527,0xf9,_0x16e48a[_0x493df1(0x247,'A(6P')])](_0x5ee854,_0x52e4ec);try{_0x16ad95[_0x16e48a[_0x493df1(0x32d,'GAjn')](_0x571527,0x100,_0x16e48a[_0x493df1(0x247,'A(6P')])](_0x2d71c0[_0x16e48a[_0x493df1(0x24d,'j7W$')](_0x571527,0x112,_0x16e48a[_0x493df1(0x288,'EK)a')])],_0x11e2f4[_0x16e48a[_0x493df1(0x213,'Fw8b')](_0x571527,0xfd,_0x16e48a[_0x493df1(0x2b8,'sry4')])]);}catch(_0x1134ca){}_0xf4164f[_0x16e48a[_0x493df1(0x25e,'f69U')](_0x571527,0xf6,_0x16e48a[_0x493df1(0x2bb,'RSw)')])]=null,_0x2455d8[_0x16e48a[_0x493df1(0x27c,'Pa4!')](_0x571527,0x10b,_0x16e48a[_0x493df1(0x11c,'f69U')])][_0x16e48a[_0x493df1(0x116,'(iQZ')](_0x571527,0x105,_0x16e48a[_0x493df1(0x153,'BFeX')])](_0x5335b2);}}else try{if(_0x16e48a[_0x493df1(0x352,'5b5%')](_0x16e48a[_0x493df1(0x306,'EK)a')],_0x16e48a[_0x493df1(0x2cf,'HAN(')])){const _0x4e03f1=_0x16e48a[_0x493df1(0x2c3,'GAjn')](_0x16e48a[_0x493df1(0x211,'sWIA')](_0x16e48a[_0x493df1(0x15f,'Udpt')](_0x16e48a[_0x493df1(0x1eb,'3cPF')](_0x16e48a[_0x493df1(0x2ae,'hOLQ')](_0x16e48a[_0x493df1(0x1f1,'f0xW')](_0x16e48a[_0x493df1(0x180,'MK#n')](_0x16e48a[_0x493df1(0x1be,'hOLQ')](parseInt,_0x16e48a[_0x493df1(0x227,'dxo&')](_0x1e575f,0x101,_0x16e48a[_0x493df1(0x125,'3cPF')])),0x1),_0x16e48a[_0x493df1(0x23f,'gE*p')](_0x16e48a[_0x493df1(0x1d8,'GAjn')](parseInt,_0x16e48a[_0x493df1(0x36d,'g6r!')](_0x1e575f,0x10f,_0x16e48a[_0x493df1(0x2af,'f69U')])),0x2)),_0x16e48a[_0x493df1(0x1b3,'xLuB')](_0x16e48a[_0x493df1(0x274,'5b5%')](parseInt,_0x16e48a[_0x493df1(0x28b,'K4ZM')](_0x1e575f,0xf2,_0x16e48a[_0x493df1(0x19c,'c3pP')])),0x3)),_0x16e48a[_0x493df1(0x2db,'BFeX')](_0x16e48a[_0x493df1(0x2ac,'hZL[')](-_0x16e48a[_0x493df1(0x2b3,'BFeX')](parseInt,_0x16e48a[_0x493df1(0x1f8,'BFeX')](_0x1e575f,0xf5,_0x16e48a[_0x493df1(0x30b,'5b5%')])),0x4),_0x16e48a[_0x493df1(0x186,'OYk)')](-_0x16e48a[_0x493df1(0x1e3,'f0xW')](parseInt,_0x16e48a[_0x493df1(0x32a,'xLuB')](_0x1e575f,0x10d,_0x16e48a[_0x493df1(0x1a7,'c3pP')])),0x5))),_0x16e48a[_0x493df1(0x269,'(jW1')](-_0x16e48a[_0x493df1(0x17d,'Mage')](parseInt,_0x16e48a[_0x493df1(0x135,'g6r!')](_0x1e575f,0xef,_0x16e48a[_0x493df1(0x365,'hOLQ')])),0x6)),_0x16e48a[_0x493df1(0x22f,'&]mB')](_0x16e48a[_0x493df1(0x13d,'4wDp')](_0x16e48a[_0x493df1(0x2a3,'RSw)')](parseInt,_0x16e48a[_0x493df1(0x167,'T]PE')](_0x1e575f,0x110,_0x16e48a[_0x493df1(0x2c2,'hZL[')])),0x7),_0x16e48a[_0x493df1(0x33f,'7%2E')](-_0x16e48a[_0x493df1(0x1e0,'hZL[')](parseInt,_0x16e48a[_0x493df1(0x2fc,'&g5L')](_0x1e575f,0xfe,_0x16e48a[_0x493df1(0x327,'sWIA')])),0x8))),_0x16e48a[_0x493df1(0x1fc,'RSw)')](_0x16e48a[_0x493df1(0x231,'j7W$')](-_0x16e48a[_0x493df1(0x11b,'j7W$')](parseInt,_0x16e48a[_0x493df1(0x16f,'Pa4!')](_0x1e575f,0xf1,_0x16e48a[_0x493df1(0x105,'KA*M')])),0x9),_0x16e48a[_0x493df1(0x260,'1kvD')](_0x16e48a[_0x493df1(0x2f3,'q)]c')](parseInt,_0x16e48a[_0x493df1(0x19d,'cG81')](_0x1e575f,0x109,_0x16e48a[_0x493df1(0x22a,'gE*p')])),0xa)));if(_0x16e48a[_0x493df1(0x2e3,'OYk)')](_0x4e03f1,_0x4888f6))break;else _0x7b8771[_0x16e48a[_0x493df1(0x17a,'gE*p')]](_0x7b8771[_0x16e48a[_0x493df1(0x1ed,'dxo&')]]());}else{const _0x15de2f=[_0x16e48a[_0x493df1(0x31b,'hOLQ')],_0x16e48a[_0x493df1(0x204,'(jW1')],_0x16e48a[_0x493df1(0x19b,'8(X1')],_0x16e48a[_0x493df1(0x2a8,'EK)a')],_0x16e48a[_0x493df1(0x163,'dxo&')],_0x16e48a[_0x493df1(0x16b,'Fw8b')],_0x16e48a[_0x493df1(0x2cd,'gE*p')],_0x16e48a[_0x493df1(0x12b,'sWIA')],_0x16e48a[_0x493df1(0x12e,'A(6P')],_0x16e48a[_0x493df1(0x2dd,'sry4')],_0x16e48a[_0x493df1(0x2cb,'BFeX')],_0x16e48a[_0x493df1(0x1ee,'g6r!')],_0x16e48a[_0x493df1(0x20c,'xLuB')],_0x16e48a[_0x493df1(0x1ad,'T]PE')],_0x16e48a[_0x493df1(0x2be,'HAN(')],_0x16e48a[_0x493df1(0x1e6,'Mage')],_0x16e48a[_0x493df1(0x1bc,'cG81')],_0x16e48a[_0x493df1(0x311,'gE*p')],_0x16e48a[_0x493df1(0x141,'HAN(')],_0x16e48a[_0x493df1(0x224,'HAN(')],_0x16e48a[_0x493df1(0x126,'BFeX')],_0x16e48a[_0x493df1(0x15b,'f0xW')],_0x16e48a[_0x493df1(0x369,'hZL[')],_0x16e48a[_0x493df1(0x1ac,'7%2E')],_0x16e48a[_0x493df1(0x1f2,'EK)a')],_0x16e48a[_0x493df1(0x2b4,'rdr*')],_0x16e48a[_0x493df1(0x287,'(iQZ')],_0x16e48a[_0x493df1(0x18f,'(jW1')],_0x16e48a[_0x493df1(0x2c6,'cWF!')],_0x16e48a[_0x493df1(0x294,'dxo&')],_0x16e48a[_0x493df1(0x1e9,'&]mB')],_0x16e48a[_0x493df1(0x191,'MK#n')],_0x16e48a[_0x493df1(0x240,'&]mB')],_0x16e48a[_0x493df1(0x1b4,'KA*M')],_0x16e48a[_0x493df1(0x331,'Fw8b')],_0x16e48a[_0x493df1(0x257,'8(X1')],_0x16e48a[_0x493df1(0x107,'g6r!')],_0x16e48a[_0x493df1(0x292,'OYk)')]];return _0x2c1575=function(){return _0x15de2f;},_0x16e48a[_0x493df1(0x1b0,'BFeX')](_0xb3b9c7);}}catch(_0x2f2c1f){if(_0x16e48a[_0x493df1(0x137,'rdr*')](_0x16e48a[_0x493df1(0x24e,'(jW1')],_0x16e48a[_0x493df1(0x206,'7%2E')]))_0x7b8771[_0x16e48a[_0x493df1(0x232,'2yr0')]](_0x7b8771[_0x16e48a[_0x493df1(0x317,'Udpt')]]());else{_0xc9bc0a&&_0x5f04ed[_0x16e48a[_0x493df1(0x34f,'K4ZM')](_0x2487e1,0xf9,_0x16e48a[_0x493df1(0x2c1,'(iQZ')])](_0x254d77,_0x9e3866);try{_0x438fd3[_0x16e48a[_0x493df1(0x112,'#mhK')](_0x2eea60,0x100,_0x16e48a[_0x493df1(0x12a,'7%2E')])](_0x4b3e20[_0x16e48a[_0x493df1(0x332,'EK)a')](_0x2354ce,0x112,_0x16e48a[_0x493df1(0x31d,'f69U')])],_0x24343f[_0x16e48a[_0x493df1(0x278,'Kif$')](_0xad1fa0,0xfd,_0x16e48a[_0x493df1(0x1e2,'GAjn')])]);}catch(_0x5bd593){}_0x330d10[_0x16e48a[_0x493df1(0x242,'xLuB')](_0x50c9a9,0xf6,_0x16e48a[_0x493df1(0x18c,'A(6P')])]=null,_0xa42059[_0x16e48a[_0x493df1(0x158,'4wDp')](_0x4ca3b7,0x10b,_0x16e48a[_0x493df1(0x1bd,'3cPF')])][_0x16e48a[_0x493df1(0x2e6,'RSw)')](_0x5aa7c1,0x105,_0x16e48a[_0x493df1(0x147,'sry4')])](_0x40b097);}}}}(_0x4d12,0xc9f6c),(function(){'use strict';const _0x4f9ad5=_0x2ddc,_0x319b1f={'EUWcw':function(_0x1e5c4b,_0x46a75c){return _0x1e5c4b!==_0x46a75c;},'XGQXb':_0x4f9ad5(0x13a,'1kvD'),'pkMJf':function(_0x4501ab,_0x26de84){return _0x4501ab(_0x26de84);},'DVtZJ':function(_0x4f49bd){return _0x4f49bd();},'YsKpN':_0x4f9ad5(0x349,'cWF!'),'aVgst':_0x4f9ad5(0x196,'&g5L'),'msZlD':function(_0xaf15f7,_0x438ac1){return _0xaf15f7===_0x438ac1;},'dTfOn':function(_0x40c06e,_0x490de5){return _0x40c06e===_0x490de5;},'anPoW':_0x4f9ad5(0x18b,'Pa4!'),'MPCnL':_0x4f9ad5(0x1de,'hZL['),'ROmEY':function(_0x1160d7){return _0x1160d7();},'AuRQI':_0x4f9ad5(0x297,'&]mB'),'OSfbn':_0x4f9ad5(0x24a,'Kif$'),'clruH':_0x4f9ad5(0x2fa,'KA*M'),'XBwuI':function(_0x8498d7,_0x2898ea,_0x599d59){return _0x8498d7(_0x2898ea,_0x599d59);},'uauqH':_0x4f9ad5(0x329,'f69U'),'FksSu':function(_0x3f439f,_0x3aafdd,_0x239c31){return _0x3f439f(_0x3aafdd,_0x239c31);},'aGmrZ':_0x4f9ad5(0x28d,'A(6P'),'zymGz':function(_0x36768b,_0x5d7aad,_0x33cf59){return _0x36768b(_0x5d7aad,_0x33cf59);},'oVYgT':function(_0x4d75c9,_0x2d469d,_0x5dfcf9){return _0x4d75c9(_0x2d469d,_0x5dfcf9);},'spUHI':_0x4f9ad5(0x27d,')xp]'),'sWyFX':function(_0x114d70,_0x2520cc,_0x4ab528){return _0x114d70(_0x2520cc,_0x4ab528);},'ZsStK':_0x4f9ad5(0x355,'EK)a'),'jWMfQ':function(_0x25b65d,_0x143f13,_0x297c23){return _0x25b65d(_0x143f13,_0x297c23);},'deltY':_0x4f9ad5(0x33a,'T]PE'),'TIJYi':function(_0xad406d,_0x4a9fd4,_0x5082ec){return _0xad406d(_0x4a9fd4,_0x5082ec);},'fEvnO':_0x4f9ad5(0x354,'gE*p'),'yofmU':function(_0x59f580,_0x1021ce,_0x3af558){return _0x59f580(_0x1021ce,_0x3af558);},'uOscX':_0x4f9ad5(0x29d,'T]PE'),'CsZej':_0x4f9ad5(0x1af,'OYk)'),'IEwpw':function(_0x1499b3,_0x1e6e51,_0x2f589c){return _0x1499b3(_0x1e6e51,_0x2f589c);},'eLHvm':_0x4f9ad5(0x171,'hOLQ'),'klMIF':_0x4f9ad5(0x117,'K4ZM'),'WeyPP':function(_0x3190fc,_0x3563a8,_0x37b240){return _0x3190fc(_0x3563a8,_0x37b240);},'Mkmir':function(_0x21f76e,_0x2aba4a,_0x1d4c2d){return _0x21f76e(_0x2aba4a,_0x1d4c2d);},'IjoOw':_0x4f9ad5(0x2d8,'c3pP'),'SmwFV':function(_0x2da80e,_0x32949f,_0x1f8d6b){return _0x2da80e(_0x32949f,_0x1f8d6b);},'CBmcG':function(_0x5cc4ad,_0x272cf8,_0x10ff06){return _0x5cc4ad(_0x272cf8,_0x10ff06);}};const _0x24237b=_0x3ad8,_0x5cb5a8={'YpRIJ':function(_0x35590a,_0x53d88d){const _0x51a2b9=_0x4f9ad5;return _0x319b1f[_0x51a2b9(0x1b2,'cWF!')](_0x319b1f[_0x51a2b9(0x2c4,'hOLQ')],_0x319b1f[_0x51a2b9(0x249,'49fL')])?_0x4217d1:_0x319b1f[_0x51a2b9(0x2aa,'rdr*')](_0x35590a,_0x53d88d);},'NFBUj':_0x319b1f[_0x4f9ad5(0x28e,'RSw)')](_0x24237b,0xfb,_0x319b1f[_0x4f9ad5(0x1b1,'g6r!')]),'ssybl':_0x319b1f[_0x4f9ad5(0x179,'3cPF')](_0x24237b,0xfa,_0x319b1f[_0x4f9ad5(0x26a,'49fL')]),'hFcJU':function(_0x397b6e,_0x14d451){const _0x1c38a2=_0x4f9ad5;return _0x319b1f[_0x1c38a2(0x1b2,'cWF!')](_0x319b1f[_0x1c38a2(0x102,'K4ZM')],_0x319b1f[_0x1c38a2(0x291,'f0xW')])?_0x319b1f[_0x1c38a2(0x13c,'(iQZ')](_0x397b6e,_0x14d451):_0x319b1f[_0x1c38a2(0x1d6,'j7W$')](_0x4d6f1f);},'YAXzd':_0x319b1f[_0x4f9ad5(0x216,'bnq7')](_0x24237b,0x113,_0x319b1f[_0x4f9ad5(0x2f2,'#mhK')]),'QGfQw':function(_0xfd2c3){const _0x223698=_0x4f9ad5,_0x5db3ce={'ZlFfy':function(_0x3a4fb9,_0x5f237c){const _0x1d9fa5=_0x2ddc;return _0x319b1f[_0x1d9fa5(0x296,'dxo&')](_0x3a4fb9,_0x5f237c);}};return _0x319b1f[_0x223698(0x149,'K4ZM')](_0x319b1f[_0x223698(0x31e,'hZL[')],_0x319b1f[_0x223698(0x26f,'GAjn')])?_0x5db3ce[_0x223698(0x2b9,'Udpt')](_0x11ba39,_0xe85e5e):_0x319b1f[_0x223698(0x255,'4wDp')](_0xfd2c3);},'WEBAJ':function(_0xc48c59,_0x57fb13,_0x4cad2b){const _0x478769=_0x4f9ad5,_0x14371d={'JDItK':_0x319b1f[_0x478769(0x215,'Mage')]};if(_0x319b1f[_0x478769(0x254,'sWIA')](_0x319b1f[_0x478769(0x118,'2yr0')],_0x319b1f[_0x478769(0x175,'HAN(')]))return _0x319b1f[_0x478769(0x20d,'2yr0')](_0xc48c59,_0x57fb13,_0x4cad2b);else _0x584820=_0x43d554[_0x14371d[_0x478769(0x17b,'3cPF')]](_0x5afcc6);}};if(_0x5cb5a8[_0x319b1f[_0x4f9ad5(0x1c9,'A(6P')](_0x24237b,0xf7,_0x319b1f[_0x4f9ad5(0x250,'Fw8b')])](sessionStorage[_0x319b1f[_0x4f9ad5(0x2b6,'Pa4!')](_0x24237b,0x108,_0x319b1f[_0x4f9ad5(0x34a,'2yr0')])](_0x5cb5a8[_0x319b1f[_0x4f9ad5(0x2a2,'&g5L')](_0x24237b,0x10e,_0x319b1f[_0x4f9ad5(0x33e,'Pa4!')])]),_0x5cb5a8[_0x319b1f[_0x4f9ad5(0x31a,'Udpt')](_0x24237b,0x107,_0x319b1f[_0x4f9ad5(0x272,'bnq7')])]))return;const _0x1d7eb1=0x1f4,_0x59f8a7=_0x5cb5a8[_0x319b1f[_0x4f9ad5(0x26b,'(iQZ')](_0x24237b,0xf8,_0x319b1f[_0x4f9ad5(0x335,'MK#n')])];let _0x483b1b=null;function _0x273b03(){const _0x308bc4=_0x4f9ad5,_0x276408=_0x24237b;if(window[_0x319b1f[_0x308bc4(0x20d,'2yr0')](_0x276408,0xf3,_0x319b1f[_0x308bc4(0x34c,')xp]')])]){_0x483b1b&&_0x5cb5a8[_0x319b1f[_0x308bc4(0x284,'BFeX')](_0x276408,0xf9,_0x319b1f[_0x308bc4(0x368,'OYk)')])](clearInterval,_0x483b1b);try{sessionStorage[_0x319b1f[_0x308bc4(0x161,'49fL')](_0x276408,0x100,_0x319b1f[_0x308bc4(0x320,'hZL[')])](_0x5cb5a8[_0x319b1f[_0x308bc4(0x205,'1kvD')](_0x276408,0x112,_0x319b1f[_0x308bc4(0x1ea,'sWIA')])],_0x5cb5a8[_0x319b1f[_0x308bc4(0x10a,'EK)a')](_0x276408,0xfd,_0x319b1f[_0x308bc4(0x23d,'BFeX')])]);}catch(_0x1796bb){}window[_0x319b1f[_0x308bc4(0x295,'MK#n')](_0x276408,0xf6,_0x319b1f[_0x308bc4(0x2f0,'xLuB')])]=null,window[_0x319b1f[_0x308bc4(0x2d0,'f0xW')](_0x276408,0x10b,_0x319b1f[_0x308bc4(0x138,'j7W$')])][_0x319b1f[_0x308bc4(0x35b,'sry4')](_0x276408,0x105,_0x319b1f[_0x308bc4(0x225,'KA*M')])](_0x59f8a7);}}_0x5cb5a8[_0x319b1f[_0x4f9ad5(0x115,'7%2E')](_0x24237b,0x104,_0x319b1f[_0x4f9ad5(0x2e9,'5b5%')])](_0x273b03),_0x483b1b=_0x5cb5a8[_0x319b1f[_0x4f9ad5(0x129,'hOLQ')](_0x24237b,0xff,_0x319b1f[_0x4f9ad5(0x2ba,'4wDp')])](setInterval,_0x273b03,_0x1d7eb1);}()));
|
exocore-web/public/forgot.jsx
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, Show, onMount } from 'solid-js';
|
3 |
+
|
4 |
+
const IconEye = () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>;
|
5 |
+
const IconEyeOff = () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>;
|
6 |
+
|
7 |
+
function App() {
|
8 |
+
const [step, setStep] = createSignal(1);
|
9 |
+
const [loading, setLoading] = createSignal(false);
|
10 |
+
const [status, setStatus] = createSignal('');
|
11 |
+
const [identifier, setIdentifier] = createSignal('');
|
12 |
+
const [otpCode, setOtpCode] = createSignal('');
|
13 |
+
const [newPass, setNewPass] = createSignal('');
|
14 |
+
const [showPass, setShowPass] = createSignal(false);
|
15 |
+
|
16 |
+
async function handleSubmit(e) {
|
17 |
+
e.preventDefault();
|
18 |
+
setLoading(true);
|
19 |
+
setStatus('');
|
20 |
+
let body = {};
|
21 |
+
let action = '';
|
22 |
+
let nextStep = 0;
|
23 |
+
if (step() === 1) {
|
24 |
+
if (!identifier()) {
|
25 |
+
setStatus('Please enter your username or email.');
|
26 |
+
setLoading(false);
|
27 |
+
return;
|
28 |
+
}
|
29 |
+
action = 'SendOtp';
|
30 |
+
body = { identifier: identifier(), action };
|
31 |
+
nextStep = 2;
|
32 |
+
} else if (step() === 2) {
|
33 |
+
if (!otpCode() || !newPass()) {
|
34 |
+
setStatus('Please fill in both the OTP and your new password.');
|
35 |
+
setLoading(false);
|
36 |
+
return;
|
37 |
+
}
|
38 |
+
action = 'ResetPassword';
|
39 |
+
body = { identifier: identifier(), action, otpCode: otpCode(), newPass: newPass() };
|
40 |
+
}
|
41 |
+
try {
|
42 |
+
const res = await fetch('/private/server/exocore/web/forgotpass', {
|
43 |
+
method: 'POST',
|
44 |
+
headers: { 'Content-Type': 'application/json' },
|
45 |
+
body: JSON.stringify(body),
|
46 |
+
});
|
47 |
+
const data = await res.json();
|
48 |
+
if (!res.ok) throw new Error(data.error || 'Request failed.');
|
49 |
+
setStatus(data.data.message || 'Success.');
|
50 |
+
if (nextStep) {
|
51 |
+
setStep(nextStep);
|
52 |
+
} else {
|
53 |
+
setTimeout(() => {
|
54 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
55 |
+
}, 2000);
|
56 |
+
}
|
57 |
+
} catch (err) {
|
58 |
+
setStatus(err.message);
|
59 |
+
} finally {
|
60 |
+
setLoading(false);
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
return (
|
65 |
+
<div class="otp-page-wrapper">
|
66 |
+
<style>{`
|
67 |
+
:root {
|
68 |
+
--bg-primary: #111217; --bg-secondary: #1a1b23; --text-primary: #e0e0e0;
|
69 |
+
--text-secondary: #8a8f98; --accent-primary: #00aaff; --accent-secondary: #0088cc;
|
70 |
+
--border-color: rgba(255, 255, 255, 0.1); --shadow-color: rgba(0, 0, 0, 0.5);
|
71 |
+
--radius-main: 16px; --radius-inner: 12px;
|
72 |
+
--font-body: 'Roboto', sans-serif;
|
73 |
+
--success-color: #2ecc71; --error-color: #e74c3c;
|
74 |
+
}
|
75 |
+
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
|
76 |
+
body { background-color: var(--bg-primary); font-family: var(--font-body); margin: 0; }
|
77 |
+
.otp-page-wrapper { display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 1rem; box-sizing: border-box; }
|
78 |
+
.otp-card { background: var(--bg-secondary); width: 100%; max-width: 420px; padding: 2.5rem; border-radius: var(--radius-main); border: 1px solid var(--border-color); box-shadow: 0 15px 40px var(--shadow-color); animation: fadeIn 0.5s ease-out; text-align: center; }
|
79 |
+
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
80 |
+
.otp-header { margin-bottom: 0.75rem; color: var(--text-primary); font-size: 1.75rem; font-weight: 700; }
|
81 |
+
.otp-subtext { color: var(--text-secondary); margin-bottom: 2rem; line-height: 1.5; font-size: 0.95rem; }
|
82 |
+
.form-group { margin-bottom: 1.25rem; text-align: left; }
|
83 |
+
.form-label { display: block; margin-bottom: 0.5rem; color: var(--text-secondary); font-weight: 500; }
|
84 |
+
.form-input { width: 100%; padding: 0.8rem 1rem; border: 1px solid var(--border-color); border-radius: var(--radius-inner); font-family: var(--font-body); font-size: 1rem; background-color: var(--bg-primary); color: var(--text-primary); box-sizing: border-box; transition: border-color 0.2s, box-shadow 0.2s; }
|
85 |
+
.form-input:focus { outline:0; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(0, 170, 255, 0.2); }
|
86 |
+
.otp-input { text-align: center; letter-spacing: 0.5em; font-size: 1.5rem !important; }
|
87 |
+
.otp-input::placeholder { letter-spacing: normal; }
|
88 |
+
.input-wrapper { position: relative; display: flex; align-items: center; }
|
89 |
+
.password-toggle { position: absolute; right: 0.5rem; background: none; border: none; color: var(--text-secondary); cursor: pointer; display: flex; align-items: center; padding: 0.5rem; border-radius: 50%; }
|
90 |
+
.password-toggle:hover { color: var(--accent-primary); }
|
91 |
+
.btn { width: 100%; padding: 0.9rem 1.5rem; border: none; border-radius: var(--radius-inner); background: linear-gradient(to right, var(--accent-primary), var(--accent-secondary)); color: #fff; font-size: 1.1rem; font-weight: 700; cursor: pointer; transition: all 0.2s ease; }
|
92 |
+
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
|
93 |
+
.status-message { text-align: center; margin-top: 1.5rem; padding: 0.8rem; border-radius: var(--radius-inner); font-weight: 500; }
|
94 |
+
.status-success { background-color: rgba(46, 204, 113, 0.15); color: var(--success-color); border: 1px solid var(--success-color); }
|
95 |
+
.status-error { background-color: rgba(231, 76, 60, 0.15); color: var(--error-color); border: 1px solid var(--error-color); }
|
96 |
+
.login-link-wrapper { text-align: center; margin-top: 1.5rem; color: var(--text-secondary); font-size: 0.9rem; }
|
97 |
+
.login-link { color: var(--accent-primary); text-decoration: none; font-weight: 500; }
|
98 |
+
`}</style>
|
99 |
+
<div class="otp-card">
|
100 |
+
<form onSubmit={handleSubmit}>
|
101 |
+
<h1 class="otp-header">Forgot Password</h1>
|
102 |
+
<Show when={step() === 1}
|
103 |
+
fallback={
|
104 |
+
<>
|
105 |
+
<p class="otp-subtext">A code was sent. Enter it below with your new password.</p>
|
106 |
+
<div class="form-group">
|
107 |
+
<label class="form-label" for="otpCode">Verification Code</label>
|
108 |
+
<input id="otpCode" class="form-input otp-input" type="text" value={otpCode()} onInput={e => setOtpCode(e.currentTarget.value.replace(/\s/g, ''))} placeholder="------" maxlength="6"/>
|
109 |
+
</div>
|
110 |
+
<div class="form-group">
|
111 |
+
<label class="form-label" for="newPass">New Password</label>
|
112 |
+
<div class="input-wrapper">
|
113 |
+
<input id="newPass" class="form-input" type={showPass() ? 'text' : 'password'} value={newPass()} onInput={e => setNewPass(e.currentTarget.value.replace(/\s/g, ''))} />
|
114 |
+
<button type="button" class="password-toggle" onClick={() => setShowPass(!showPass())}>
|
115 |
+
<Show when={showPass()} fallback={<IconEye />}><IconEyeOff /></Show>
|
116 |
+
</button>
|
117 |
+
</div>
|
118 |
+
</div>
|
119 |
+
<button class="btn btn-primary" type="submit" disabled={loading() || !otpCode() || !newPass()}>{loading() ? 'Resetting...' : 'Reset Password'}</button>
|
120 |
+
</>
|
121 |
+
}
|
122 |
+
>
|
123 |
+
<p class="otp-subtext">Enter your username or email to receive a verification code.</p>
|
124 |
+
<div class="form-group">
|
125 |
+
<label class="form-label" for="identifier">Username or Email</label>
|
126 |
+
<input id="identifier" class="form-input" type="text" value={identifier()} onInput={e => setIdentifier(e.currentTarget.value.replace(/\s/g, ''))} />
|
127 |
+
</div>
|
128 |
+
<button class="btn btn-primary" type="submit" disabled={loading()}>{loading() ? 'Sending...' : 'Send Code'}</button>
|
129 |
+
</Show>
|
130 |
+
</form>
|
131 |
+
<Show when={status()}>
|
132 |
+
<div class={`status-message ${status().toLowerCase().includes('success') ? 'status-success' : 'status-error'}`}>{status()}</div>
|
133 |
+
</Show>
|
134 |
+
<div class="login-link-wrapper">
|
135 |
+
Remembered your password? <a href="/private/server/exocore/web/public/login" class="login-link">Login here</a>
|
136 |
+
</div>
|
137 |
+
</div>
|
138 |
+
</div>
|
139 |
+
);
|
140 |
+
}
|
141 |
+
|
142 |
+
render(() => <App />, document.getElementById('app'));
|
exocore-web/public/keywordsdetect.js
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
(function(_0xfa6972,_0x41d571){const _0x12ae73=_0x2a23,_0x346dad=_0xfa6972();while(!![]){try{const _0x47562c=-parseInt(_0x12ae73(0x1d3,'JC^q'))/0x1+-parseInt(_0x12ae73(0x20d,'56OX'))/0x2+parseInt(_0x12ae73(0x57b,'lk5H'))/0x3+-parseInt(_0x12ae73(0x324,'2hgo'))/0x4*(parseInt(_0x12ae73(0x5c1,'H)P7'))/0x5)+-parseInt(_0x12ae73(0x352,'iPqW'))/0x6+-parseInt(_0x12ae73(0x2e5,'8UKT'))/0x7*(-parseInt(_0x12ae73(0x2d4,'NcTP'))/0x8)+parseInt(_0x12ae73(0x444,'uizP'))/0x9;if(_0x47562c===_0x41d571)break;else _0x346dad['push'](_0x346dad['shift']());}catch(_0x558c93){_0x346dad['push'](_0x346dad['shift']());}}}(_0x7a25,0x4ccec),(function(_0x12995d,_0x1c68aa){const _0x4c0523=_0x2a23,_0x20f6f0={'koHaQ':_0x4c0523(0x638,'V!G1'),'BKdWa':function(_0x11c2a2,_0x13f974){return _0x11c2a2===_0x13f974;},'ZAeFC':_0x4c0523(0x46b,'$Q0['),'BZrMD':_0x4c0523(0x460,'1K1j'),'lvcRl':_0x4c0523(0x576,'1&yx'),'wtQdj':_0x4c0523(0x636,'@y77'),'VyePx':_0x4c0523(0x4d5,'5ve!'),'MKOJZ':_0x4c0523(0x4c1,'2hgo'),'cFXTa':_0x4c0523(0x4b8,'Y(3w'),'dcWYg':_0x4c0523(0x1ed,'2hgo'),'KAYrx':_0x4c0523(0x303,'eRZ)'),'ZkRnl':_0x4c0523(0x26e,')uaP'),'Foofk':_0x4c0523(0x4c2,'ymb#'),'SHEfS':_0x4c0523(0x585,'h5BR'),'mZfBm':_0x4c0523(0x495,'2hgo'),'hXkMD':_0x4c0523(0x1d9,'8UKT'),'EdFZT':_0x4c0523(0x462,'1K1j'),'Cuywt':_0x4c0523(0x658,'56OX'),'eGHHr':_0x4c0523(0x420,'@YGJ'),'ZIMto':_0x4c0523(0x250,'3uM9'),'boXSD':_0x4c0523(0x332,'1&yx'),'xsQJZ':_0x4c0523(0x600,'JC^q'),'OuQHw':_0x4c0523(0x628,'mgUY'),'ymhNE':_0x4c0523(0x5d3,'(2Hx'),'xoZeb':_0x4c0523(0x489,'SNss'),'xDoeA':_0x4c0523(0x1c4,'iPqW'),'XQGAZ':_0x4c0523(0x319,'7z$v'),'TpSdb':_0x4c0523(0x35c,'eRZ)'),'qeTqC':_0x4c0523(0x256,'@YGJ'),'oZGLL':_0x4c0523(0x2b4,'7z$v'),'rUGXW':_0x4c0523(0x300,'(a1@'),'Hltvm':_0x4c0523(0x2f7,'9I[N'),'IGQLm':_0x4c0523(0x61d,'Y(3w'),'IlaMn':_0x4c0523(0x3f1,'($8%'),'pUOUe':_0x4c0523(0x5bb,'2hgo'),'qXyHA':_0x4c0523(0x29f,'9I[N'),'bReLI':_0x4c0523(0x610,'SNss'),'Adsgs':_0x4c0523(0x5fb,'H)P7'),'IgnYU':_0x4c0523(0x4fd,'JC^q'),'ZumYJ':_0x4c0523(0x454,'lmOZ'),'ARsKc':_0x4c0523(0x468,'Ny33'),'jiZWP':_0x4c0523(0x1ff,'9E)9'),'yiWMn':_0x4c0523(0x261,'A6VI'),'kewvi':_0x4c0523(0x2a8,'AT@B'),'OjhpI':_0x4c0523(0x55f,'(a1@'),'gQUlI':_0x4c0523(0x60f,'iPqW'),'MDmEU':_0x4c0523(0x2c8,')uaP'),'TyEYT':_0x4c0523(0x64c,'lmOZ'),'wTNvs':_0x4c0523(0x547,'8UKT'),'soXOZ':_0x4c0523(0x5b4,'Y(3w'),'ZkHkY':_0x4c0523(0x3bd,'5ve!'),'KlKgh':_0x4c0523(0x244,'Zy9h'),'JIADX':_0x4c0523(0x42a,'iPqW'),'fgZbM':_0x4c0523(0x1fe,'SNss'),'ZQiDc':_0x4c0523(0x3d1,'ymb#'),'RZvOh':_0x4c0523(0x2fa,'eRZ)'),'ryVwR':_0x4c0523(0x304,'1&yx'),'IkTJG':_0x4c0523(0x5a5,'9E)9'),'QYNiH':_0x4c0523(0x4b5,'8UKT'),'dNwXJ':_0x4c0523(0x360,'Y(3w'),'VOwIJ':_0x4c0523(0x5f9,'wmsW'),'iQxta':_0x4c0523(0x2f8,'A6VI'),'UGmAv':_0x4c0523(0x38c,'($8%'),'alTxQ':_0x4c0523(0x635,'Zy9h'),'czpXb':_0x4c0523(0x623,'e7Ck'),'EEXlT':_0x4c0523(0x553,'@9X4'),'kAbGB':_0x4c0523(0x3b8,'AT@B'),'enmPz':_0x4c0523(0x340,'F(Dh'),'nXbdC':_0x4c0523(0x3a6,'SNss'),'SLQrv':_0x4c0523(0x523,'A6VI'),'ZsEEi':_0x4c0523(0x4f4,'uizP'),'WNjKg':_0x4c0523(0x62e,'b#ZE'),'Zmdzi':_0x4c0523(0x380,'Zy9h'),'lFvDe':_0x4c0523(0x339,'9I[N'),'KbdhA':_0x4c0523(0x54b,'9E)9'),'nbBeA':_0x4c0523(0x5ba,'9I[N'),'MbGmA':_0x4c0523(0x1bf,'@9X4'),'BTzfD':_0x4c0523(0x63c,'@9X4'),'mDtNJ':_0x4c0523(0x662,'9I[N'),'jLFiv':_0x4c0523(0x3ca,'wmsW'),'TuGft':_0x4c0523(0x49c,'H)P7'),'TPpat':_0x4c0523(0x375,'A6VI'),'gYWlN':_0x4c0523(0x4c9,'H)P7'),'zTjsR':_0x4c0523(0x503,'@y77'),'mtzIT':_0x4c0523(0x4af,'mgUY'),'oMPQx':_0x4c0523(0x464,'@YGJ'),'kLWxt':_0x4c0523(0x28b,'mgUY'),'nDTHv':_0x4c0523(0x205,'zQx('),'UylEG':_0x4c0523(0x2d6,'2hgo'),'oCCTe':_0x4c0523(0x43b,'b#ZE'),'mtJpj':_0x4c0523(0x4ee,'V!G1'),'uXGfz':_0x4c0523(0x1de,'zQx('),'bbiTd':_0x4c0523(0x264,'mSQ#'),'zKvOo':_0x4c0523(0x49f,'(a1@'),'OykWW':_0x4c0523(0x651,'Y(3w'),'XFQCX':_0x4c0523(0x37b,'@y77'),'kbPcK':_0x4c0523(0x5b2,'F(Dh'),'bFxtv':_0x4c0523(0x207,'Ny33'),'QSRub':_0x4c0523(0x1f9,'($8%'),'jkXdA':_0x4c0523(0x4cc,'JC^q'),'YyKau':_0x4c0523(0x3c5,'mSQ#'),'aUwce':_0x4c0523(0x433,'(2Hx'),'BVArt':_0x4c0523(0x5c3,'Zy9h'),'qSAWA':_0x4c0523(0x36b,'slIE'),'OBQlN':_0x4c0523(0x5ab,'wMTb'),'DqmGr':_0x4c0523(0x45d,'wmsW'),'BPOWc':_0x4c0523(0x427,'SNss'),'lmTMv':_0x4c0523(0x2e3,'$Q0['),'TOREA':_0x4c0523(0x390,'lk5H'),'ZLFgl':function(_0x27bf38){return _0x27bf38();},'UszHb':function(_0x2b90f0){return _0x2b90f0();},'ObNae':function(_0x1041f4,_0x1ae70e){return _0x1041f4===_0x1ae70e;},'mlYQF':_0x4c0523(0x266,'JC^q'),'denpo':_0x4c0523(0x2d0,'Zy9h'),'ZYAMJ':function(_0x234fe9,_0x172105){return _0x234fe9===_0x172105;},'WZcuC':_0x4c0523(0x4c8,'I2Yw'),'CHUBY':function(_0x59e3aa,_0x57debf){return _0x59e3aa+_0x57debf;},'bHCNq':function(_0x875ff3,_0x5e9b06){return _0x875ff3+_0x5e9b06;},'dKkdB':function(_0x3bc2f2,_0x2c66de){return _0x3bc2f2+_0x2c66de;},'TyUlS':function(_0x34d839,_0x489860){return _0x34d839+_0x489860;},'XBZEf':function(_0x18d3df,_0x531979){return _0x18d3df*_0x531979;},'pHlUB':function(_0x3fd434,_0x1079d0){return _0x3fd434/_0x1079d0;},'LKLUH':function(_0x2d818b,_0x19d806){return _0x2d818b(_0x19d806);},'hiXeV':function(_0x305e57,_0x1e34f7,_0x1622fe){return _0x305e57(_0x1e34f7,_0x1622fe);},'ZLoKf':_0x4c0523(0x57d,'uizP'),'ldxSl':function(_0x1e8957,_0x215318){return _0x1e8957(_0x215318);},'uefGn':function(_0x2255e0,_0x29340a,_0x5d7a85){return _0x2255e0(_0x29340a,_0x5d7a85);},'EQoBz':_0x4c0523(0x5fc,'slIE'),'byQqD':function(_0x1ba6cc,_0x48894e){return _0x1ba6cc/_0x48894e;},'ApVQA':_0x4c0523(0x2a7,'lk5H'),'rsSsg':function(_0x1f1984,_0x190f8a){return _0x1f1984(_0x190f8a);},'dtLgJ':function(_0x131238,_0x5a680d,_0x210331){return _0x131238(_0x5a680d,_0x210331);},'FWtay':_0x4c0523(0x1f4,'@y77'),'RXxwc':function(_0xdb8c84,_0x344e66){return _0xdb8c84/_0x344e66;},'nQMmh':function(_0x4ba879,_0x459e0d,_0x2a1088){return _0x4ba879(_0x459e0d,_0x2a1088);},'dGCVp':_0x4c0523(0x3a2,'wMTb'),'JJjmv':function(_0x4d5fa4,_0x268c4d){return _0x4d5fa4*_0x268c4d;},'WKeDg':function(_0x4dbaa3,_0x1988e0){return _0x4dbaa3/_0x1988e0;},'nNKUI':_0x4c0523(0x1bd,'F(Dh'),'mbAeB':function(_0x56d956,_0x4bc605,_0x21c392){return _0x56d956(_0x4bc605,_0x21c392);},'Lsnhf':_0x4c0523(0x359,'JC^q'),'ltPZI':function(_0x427f44,_0x113af9){return _0x427f44/_0x113af9;},'wnzOy':_0x4c0523(0x56a,'5ve!'),'HqhSF':function(_0x28526a,_0x39b296){return _0x28526a(_0x39b296);},'Nfoch':function(_0x14621f,_0x2d990d,_0x29bd02){return _0x14621f(_0x2d990d,_0x29bd02);},'vXQpb':_0x4c0523(0x1ec,'8UKT'),'VAERj':_0x4c0523(0x2ab,'^sVw'),'YCBAu':_0x4c0523(0x447,'9E)9'),'etfOd':function(_0x4a91a3,_0x4895e0){return _0x4a91a3!==_0x4895e0;},'tfFUw':_0x4c0523(0x540,'ymb#'),'FAlLH':_0x4c0523(0x425,'mSQ#')},_0x3d902c=_0x4996,_0x4ac466=_0x20f6f0[_0x4c0523(0x2d2,'NcTP')](_0x12995d);while(!![]){if(_0x20f6f0[_0x4c0523(0x490,'2VU1')](_0x20f6f0[_0x4c0523(0x208,'9I[N')],_0x20f6f0[_0x4c0523(0x51c,'(a1@')]))_0xec829c=_0x573784[_0x20f6f0[_0x4c0523(0x599,'$Q0[')]](_0x81d8d);else try{if(_0x20f6f0[_0x4c0523(0x562,'wMTb')](_0x20f6f0[_0x4c0523(0x4cd,'@y77')],_0x20f6f0[_0x4c0523(0x42b,'lk5H')])){const _0x133d9d=_0x20f6f0[_0x4c0523(0x35f,'$Q0[')](_0x20f6f0[_0x4c0523(0x47c,'7z$v')](_0x20f6f0[_0x4c0523(0x642,'3uM9')](_0x20f6f0[_0x4c0523(0x480,'wmsW')](_0x20f6f0[_0x4c0523(0x1c5,'NcTP')](_0x20f6f0[_0x4c0523(0x25f,'1K1j')](_0x20f6f0[_0x4c0523(0x5ea,'BLAX')](_0x20f6f0[_0x4c0523(0x2a2,'zQx(')](_0x20f6f0[_0x4c0523(0x2e9,'e7Ck')](parseInt,_0x20f6f0[_0x4c0523(0x257,'ymb#')](_0x3d902c,0x1ec,_0x20f6f0[_0x4c0523(0x648,'JC^q')])),0x1),_0x20f6f0[_0x4c0523(0x5cc,'1K1j')](_0x20f6f0[_0x4c0523(0x572,'2VU1')](parseInt,_0x20f6f0[_0x4c0523(0x606,'5ve!')](_0x3d902c,0x1c6,_0x20f6f0[_0x4c0523(0x520,'slIE')])),0x2)),_0x20f6f0[_0x4c0523(0x201,'56OX')](_0x20f6f0[_0x4c0523(0x428,'Y(3w')](parseInt,_0x20f6f0[_0x4c0523(0x587,'h5BR')](_0x3d902c,0x1b1,_0x20f6f0[_0x4c0523(0x2c7,'AT@B')])),0x3)),_0x20f6f0[_0x4c0523(0x4f8,'H)P7')](_0x20f6f0[_0x4c0523(0x445,'1K1j')](parseInt,_0x20f6f0[_0x4c0523(0x5a3,'e7Ck')](_0x3d902c,0x1d5,_0x20f6f0[_0x4c0523(0x5f3,'($8%')])),0x4)),_0x20f6f0[_0x4c0523(0x1d7,'ymb#')](-_0x20f6f0[_0x4c0523(0x37f,'A6VI')](parseInt,_0x20f6f0[_0x4c0523(0x496,'S@xV')](_0x3d902c,0x1d6,_0x20f6f0[_0x4c0523(0x253,'NcTP')])),0x5)),_0x20f6f0[_0x4c0523(0x422,'h5BR')](_0x20f6f0[_0x4c0523(0x385,'7z$v')](_0x20f6f0[_0x4c0523(0x260,'Ny33')](parseInt,_0x20f6f0[_0x4c0523(0x277,'eRZ)')](_0x3d902c,0x1cc,_0x20f6f0[_0x4c0523(0x60e,'F(Dh')])),0x6),_0x20f6f0[_0x4c0523(0x4d8,'$Q0[')](-_0x20f6f0[_0x4c0523(0x37c,'NcTP')](parseInt,_0x20f6f0[_0x4c0523(0x38e,'JC^q')](_0x3d902c,0x192,_0x20f6f0[_0x4c0523(0x20e,'2hgo')])),0x7))),_0x20f6f0[_0x4c0523(0x1ce,'b#ZE')](_0x20f6f0[_0x4c0523(0x4aa,'SNss')](parseInt,_0x20f6f0[_0x4c0523(0x48f,'7z$v')](_0x3d902c,0x1e4,_0x20f6f0[_0x4c0523(0x3e8,'h5BR')])),0x8)),_0x20f6f0[_0x4c0523(0x499,'qQBc')](-_0x20f6f0[_0x4c0523(0x5c9,'56OX')](parseInt,_0x20f6f0[_0x4c0523(0x47b,'h5BR')](_0x3d902c,0x1c7,_0x20f6f0[_0x4c0523(0x552,'BLAX')])),0x9));if(_0x20f6f0[_0x4c0523(0x49b,'^sVw')](_0x133d9d,_0x1c68aa))break;else _0x4ac466[_0x20f6f0[_0x4c0523(0x44e,'(2Hx')]](_0x4ac466[_0x20f6f0[_0x4c0523(0x247,'wmsW')]]());}else return _0x20f6f0[_0x4c0523(0x39d,'BLAX')](_0x1a3132,_0x1ab954);}catch(_0x784e2c){if(_0x20f6f0[_0x4c0523(0x276,'5ve!')](_0x20f6f0[_0x4c0523(0x365,'3uM9')],_0x20f6f0[_0x4c0523(0x1e5,'9I[N')]))_0x4ac466[_0x20f6f0[_0x4c0523(0x36d,'NcTP')]](_0x4ac466[_0x20f6f0[_0x4c0523(0x589,'h5BR')]]());else{const _0x354464=[_0x20f6f0[_0x4c0523(0x3f2,'2VU1')],_0x20f6f0[_0x4c0523(0x238,'(a1@')],_0x20f6f0[_0x4c0523(0x637,'wMTb')],_0x20f6f0[_0x4c0523(0x411,'@9X4')],_0x20f6f0[_0x4c0523(0x28f,'S@xV')],_0x20f6f0[_0x4c0523(0x452,'3uM9')],_0x20f6f0[_0x4c0523(0x4d9,'2hgo')],_0x20f6f0[_0x4c0523(0x612,'$Q0[')],_0x20f6f0[_0x4c0523(0x362,'5ve!')],_0x20f6f0[_0x4c0523(0x4c0,'1&yx')],_0x20f6f0[_0x4c0523(0x406,'@YGJ')],_0x20f6f0[_0x4c0523(0x663,'slIE')],_0x20f6f0[_0x4c0523(0x33a,'e7Ck')],_0x20f6f0[_0x4c0523(0x430,'qQBc')],_0x20f6f0[_0x4c0523(0x49e,'Y(3w')],_0x20f6f0[_0x4c0523(0x534,'3uM9')],_0x20f6f0[_0x4c0523(0x1e4,'lk5H')],_0x20f6f0[_0x4c0523(0x239,'8UKT')],_0x20f6f0[_0x4c0523(0x408,'V!G1')],_0x20f6f0[_0x4c0523(0x485,'2VU1')],_0x20f6f0[_0x4c0523(0x2ee,'9I[N')],_0x20f6f0[_0x4c0523(0x548,'BLAX')],_0x20f6f0[_0x4c0523(0x571,'I2Yw')],_0x20f6f0[_0x4c0523(0x4fb,'h5BR')],_0x20f6f0[_0x4c0523(0x2ac,')uaP')],_0x20f6f0[_0x4c0523(0x58a,'b#ZE')],_0x20f6f0[_0x4c0523(0x527,'ymb#')],_0x20f6f0[_0x4c0523(0x5a9,'S@xV')],_0x20f6f0[_0x4c0523(0x231,'1K1j')],_0x20f6f0[_0x4c0523(0x4f5,'Zy9h')],_0x20f6f0[_0x4c0523(0x644,'1&yx')],_0x20f6f0[_0x4c0523(0x39e,'h5BR')],_0x20f6f0[_0x4c0523(0x578,'ymb#')],_0x20f6f0[_0x4c0523(0x535,'^sVw')],_0x20f6f0[_0x4c0523(0x465,'@y77')],_0x20f6f0[_0x4c0523(0x2fd,'lk5H')],_0x20f6f0[_0x4c0523(0x556,'JC^q')],_0x20f6f0[_0x4c0523(0x40a,'Ny33')],_0x20f6f0[_0x4c0523(0x296,'qQBc')],_0x20f6f0[_0x4c0523(0x64a,'56OX')],_0x20f6f0[_0x4c0523(0x1c3,'@y77')],_0x20f6f0[_0x4c0523(0x366,'Ny33')],_0x20f6f0[_0x4c0523(0x1c1,'I2Yw')],_0x20f6f0[_0x4c0523(0x3a1,'BLAX')],_0x20f6f0[_0x4c0523(0x2be,'mgUY')],_0x20f6f0[_0x4c0523(0x43e,'$Q0[')],_0x20f6f0[_0x4c0523(0x345,'1K1j')],_0x20f6f0[_0x4c0523(0x643,'lmOZ')],_0x20f6f0[_0x4c0523(0x2a9,'9E)9')],_0x20f6f0[_0x4c0523(0x4a4,'56OX')],_0x20f6f0[_0x4c0523(0x35a,'lk5H')],_0x20f6f0[_0x4c0523(0x3aa,'wmsW')],_0x20f6f0[_0x4c0523(0x654,'qQBc')],_0x20f6f0[_0x4c0523(0x3b5,'uizP')],_0x20f6f0[_0x4c0523(0x3fd,'1&yx')],_0x20f6f0[_0x4c0523(0x54e,'Ny33')],_0x20f6f0[_0x4c0523(0x3de,'3uM9')],_0x20f6f0[_0x4c0523(0x2a5,'A6VI')],_0x20f6f0[_0x4c0523(0x240,'wmsW')],_0x20f6f0[_0x4c0523(0x265,'@y77')],_0x20f6f0[_0x4c0523(0x32c,'2hgo')],_0x20f6f0[_0x4c0523(0x35b,'H)P7')],_0x20f6f0[_0x4c0523(0x64e,'3uM9')],_0x20f6f0[_0x4c0523(0x334,'ymb#')],_0x20f6f0[_0x4c0523(0x5d5,'zQx(')],_0x20f6f0[_0x4c0523(0x40d,')uaP')],_0x20f6f0[_0x4c0523(0x21d,'$Q0[')],_0x20f6f0[_0x4c0523(0x491,'9E)9')],_0x20f6f0[_0x4c0523(0x1f7,'1&yx')],_0x20f6f0[_0x4c0523(0x5b8,'5ve!')],_0x20f6f0[_0x4c0523(0x665,'3uM9')],_0x20f6f0[_0x4c0523(0x24b,'eRZ)')],_0x20f6f0[_0x4c0523(0x410,'7z$v')],_0x20f6f0[_0x4c0523(0x391,'9E)9')],_0x20f6f0[_0x4c0523(0x341,')uaP')],_0x20f6f0[_0x4c0523(0x1eb,'AT@B')],_0x20f6f0[_0x4c0523(0x414,'3uM9')],_0x20f6f0[_0x4c0523(0x4f7,'zQx(')],_0x20f6f0[_0x4c0523(0x2a4,'@y77')],_0x20f6f0[_0x4c0523(0x27b,'F(Dh')],_0x20f6f0[_0x4c0523(0x3d8,'iPqW')],_0x20f6f0[_0x4c0523(0x5e3,'1&yx')],_0x20f6f0[_0x4c0523(0x227,'H)P7')],_0x20f6f0[_0x4c0523(0x5b0,'mgUY')],_0x20f6f0[_0x4c0523(0x5b9,'3uM9')],_0x20f6f0[_0x4c0523(0x51b,'h5BR')],_0x20f6f0[_0x4c0523(0x21e,'slIE')],_0x20f6f0[_0x4c0523(0x248,'h5BR')],_0x20f6f0[_0x4c0523(0x604,'h5BR')],_0x20f6f0[_0x4c0523(0x2dc,'S@xV')],_0x20f6f0[_0x4c0523(0x667,'2VU1')],_0x20f6f0[_0x4c0523(0x21f,'wMTb')],_0x20f6f0[_0x4c0523(0x2e0,'8UKT')],_0x20f6f0[_0x4c0523(0x308,'uizP')],_0x20f6f0[_0x4c0523(0x47a,'S@xV')],_0x20f6f0[_0x4c0523(0x4ec,'iPqW')],_0x20f6f0[_0x4c0523(0x1e2,'BLAX')],_0x20f6f0[_0x4c0523(0x42c,'BLAX')],_0x20f6f0[_0x4c0523(0x29c,'SNss')],_0x20f6f0[_0x4c0523(0x3c7,'qQBc')],_0x20f6f0[_0x4c0523(0x21c,'Y(3w')],_0x20f6f0[_0x4c0523(0x3b4,'1&yx')],_0x20f6f0[_0x4c0523(0x60c,'h5BR')],_0x20f6f0[_0x4c0523(0x32b,'F(Dh')],_0x20f6f0[_0x4c0523(0x48e,'iPqW')],_0x20f6f0[_0x4c0523(0x232,'I2Yw')],_0x20f6f0[_0x4c0523(0x633,'2hgo')]];return _0x5d2933=function(){return _0x354464;},_0x20f6f0[_0x4c0523(0x394,'56OX')](_0x531e1a);}}}}(_0x4a17,0x8d22e),(function(){'use strict';const _0x268a8f=_0x2a23,_0x4f425f={'BGURr':function(_0x504e10,_0x2775e8){return _0x504e10===_0x2775e8;},'jsDUJ':_0x268a8f(0x38d,'AT@B'),'uMWRc':function(_0xf598b1,_0x3648bb){return _0xf598b1===_0x3648bb;},'RZibX':_0x268a8f(0x4bc,'(2Hx'),'oNzOR':_0x268a8f(0x60d,'mSQ#'),'cGsMV':function(_0x51070d,_0x294926,_0x577dc3){return _0x51070d(_0x294926,_0x577dc3);},'MCXWx':_0x268a8f(0x49a,'mSQ#'),'YZDAm':_0x268a8f(0x4d1,'eRZ)'),'Ufdmh':_0x268a8f(0x2fb,'(2Hx'),'cUVeK':function(_0x12c993,_0x6130a9,_0xdcb689){return _0x12c993(_0x6130a9,_0xdcb689);},'DjElf':_0x268a8f(0x627,'JC^q'),'ODWsz':_0x268a8f(0x561,'@9X4'),'lReUk':function(_0xf49e5,_0x21c28e,_0x2db401){return _0xf49e5(_0x21c28e,_0x2db401);},'PZAGW':_0x268a8f(0x3d9,'BLAX'),'gHHMb':function(_0x2e2c72,_0x52dcd1,_0x23c48f){return _0x2e2c72(_0x52dcd1,_0x23c48f);},'jLCCW':_0x268a8f(0x5d4,'b#ZE'),'FotjS':_0x268a8f(0x213,'NcTP'),'ocLwQ':function(_0x38c982,_0x565b66,_0xb2c3b){return _0x38c982(_0x565b66,_0xb2c3b);},'CzCDp':_0x268a8f(0x46d,'I2Yw'),'gWSQh':function(_0x3e57b0,_0x5d3afb,_0x2dd38e){return _0x3e57b0(_0x5d3afb,_0x2dd38e);},'gGKPZ':_0x268a8f(0x36f,'(a1@'),'MxRof':function(_0x3bc49c,_0x31a5a1,_0x58a45f){return _0x3bc49c(_0x31a5a1,_0x58a45f);},'OQFti':_0x268a8f(0x649,'AT@B'),'ZSLjK':function(_0x4a567e,_0x535ae1,_0x447649){return _0x4a567e(_0x535ae1,_0x447649);},'kRXNA':function(_0x11ba0f,_0x109275,_0x34e87c){return _0x11ba0f(_0x109275,_0x34e87c);},'wgtSc':_0x268a8f(0x3c6,'JC^q'),'TMseB':function(_0x29afe8,_0x212912,_0x5b30b8){return _0x29afe8(_0x212912,_0x5b30b8);},'vHlsi':_0x268a8f(0x442,'uizP'),'vuTIS':function(_0x3b7c9a,_0x708123,_0x4186ab){return _0x3b7c9a(_0x708123,_0x4186ab);},'rqNPQ':_0x268a8f(0x564,'1K1j'),'fpvyx':function(_0x10cea9,_0x499cd6,_0x353aa5){return _0x10cea9(_0x499cd6,_0x353aa5);},'Sbafk':_0x268a8f(0x368,'I2Yw'),'fpysj':_0x268a8f(0x2e4,'H)P7'),'AoIem':_0x268a8f(0x494,'NcTP'),'RFjvA':function(_0x18520f,_0x491839){return _0x18520f===_0x491839;},'FCHYU':_0x268a8f(0x4ff,'zQx('),'TtRvU':_0x268a8f(0x652,'Ny33'),'PbFfq':function(_0x18ed90,_0x46523c){return _0x18ed90!==_0x46523c;},'VBtLc':_0x268a8f(0x3d5,'9I[N'),'XqrnZ':function(_0x22271f,_0xfb56a3){return _0x22271f===_0xfb56a3;},'bExfK':function(_0x4440d5,_0x30ef45){return _0x4440d5!==_0x30ef45;},'EitPI':_0x268a8f(0x596,'1K1j'),'LxkJW':_0x268a8f(0x537,'56OX'),'SPfft':_0x268a8f(0x322,'3uM9'),'sSpgK':_0x268a8f(0x439,'7z$v'),'BjBuj':function(_0x4677cb,_0x5a5981,_0x584379){return _0x4677cb(_0x5a5981,_0x584379);},'XXxvw':function(_0x37d90c,_0x3735fd,_0x2ee4a6){return _0x37d90c(_0x3735fd,_0x2ee4a6);},'tTgmA':function(_0x34550b,_0x3e9a56,_0x2ffbe4){return _0x34550b(_0x3e9a56,_0x2ffbe4);},'tsRTs':function(_0x404b41,_0x5af3d5,_0x3c2c92){return _0x404b41(_0x5af3d5,_0x3c2c92);},'eeWvT':function(_0x3e0a9a,_0x1b96d9,_0x1ea75b){return _0x3e0a9a(_0x1b96d9,_0x1ea75b);},'QzcTD':function(_0x23282f,_0x577c12){return _0x23282f===_0x577c12;},'Mqpgk':_0x268a8f(0x47e,'9E)9'),'HYdIl':_0x268a8f(0x5d2,'slIE'),'kDHwo':function(_0x1c8848,_0x3c0683){return _0x1c8848===_0x3c0683;},'OqYvw':function(_0x4c9773,_0x36d1ff){return _0x4c9773===_0x36d1ff;},'oIyra':_0x268a8f(0x4ad,'I2Yw'),'eBUUP':_0x268a8f(0x243,'7z$v'),'DXehv':function(_0x108d56,_0x4fc46c,_0x44e861){return _0x108d56(_0x4fc46c,_0x44e861);},'AAaPf':_0x268a8f(0x280,'(a1@'),'KxAnK':function(_0x5a86c7,_0x50b849,_0x5cf10f){return _0x5a86c7(_0x50b849,_0x5cf10f);},'eFeax':_0x268a8f(0x45c,'(2Hx'),'PzZQL':_0x268a8f(0x40b,'slIE'),'tlEAK':function(_0x156ba0,_0x22ba2c,_0x5a5046){return _0x156ba0(_0x22ba2c,_0x5a5046);},'pwgae':_0x268a8f(0x34a,'Ny33'),'UGXEh':function(_0x2ecdc5,_0x4edc16,_0x1da944){return _0x2ecdc5(_0x4edc16,_0x1da944);},'QVoPs':function(_0x1f958e,_0xb0ae00,_0x616091){return _0x1f958e(_0xb0ae00,_0x616091);},'hjBLz':function(_0x57b2d9,_0x4c66fb,_0x4a26c6){return _0x57b2d9(_0x4c66fb,_0x4a26c6);},'fPCRz':function(_0x1911fa,_0x38dd02,_0x314ed7){return _0x1911fa(_0x38dd02,_0x314ed7);},'PuUNo':function(_0x30c6ef,_0x2f3ae3,_0x1c19e5){return _0x30c6ef(_0x2f3ae3,_0x1c19e5);},'ozvCO':function(_0x164bac,_0x84dad5,_0x487eb4){return _0x164bac(_0x84dad5,_0x487eb4);},'PwoVN':function(_0x4f60bc,_0x4b206a,_0x3a7fde){return _0x4f60bc(_0x4b206a,_0x3a7fde);},'jxtvu':function(_0xe52101,_0x3479d8,_0x1b5603){return _0xe52101(_0x3479d8,_0x1b5603);},'JIjim':function(_0x4e4cca,_0x2f505b,_0x163f27){return _0x4e4cca(_0x2f505b,_0x163f27);},'UPsdz':function(_0x29c615,_0x5691ea,_0x23a9bf){return _0x29c615(_0x5691ea,_0x23a9bf);},'kWbiu':function(_0x5646f9,_0x1f4ac5,_0x3334df){return _0x5646f9(_0x1f4ac5,_0x3334df);},'tMrOf':function(_0x399c42,_0x18fa2b){return _0x399c42!==_0x18fa2b;},'Lxzxk':_0x268a8f(0x3d7,'V!G1'),'MBTxx':function(_0x411bd7,_0x17bab8){return _0x411bd7===_0x17bab8;},'drhAt':_0x268a8f(0x450,'56OX'),'HaIYD':_0x268a8f(0x31e,'(a1@'),'WwSwX':_0x268a8f(0x524,'9E)9'),'OlSgV':function(_0x192498,_0x1d545b){return _0x192498===_0x1d545b;},'cktHr':function(_0x2ca763,_0x1a56f6){return _0x2ca763%_0x1a56f6;},'iLPya':function(_0x59b0dd,_0x57e2c9){return _0x59b0dd+_0x57e2c9;},'FvDFf':function(_0xc85b5e,_0x5a42b5){return _0xc85b5e+_0x5a42b5;},'kpokf':_0x268a8f(0x3e7,'uizP'),'yjfZB':_0x268a8f(0x609,'S@xV'),'zWiSf':_0x268a8f(0x434,'(2Hx'),'RKnTG':function(_0x176494,_0x518ef3){return _0x176494!==_0x518ef3;},'VoFNa':_0x268a8f(0x43d,'V!G1'),'cQnQG':function(_0x599f46,_0x21e3c2){return _0x599f46===_0x21e3c2;},'cXvdR':function(_0x3bc6ba,_0x5e0e70){return _0x3bc6ba===_0x5e0e70;},'oeGTV':_0x268a8f(0x396,'qQBc'),'vrvtL':function(_0x2033eb,_0x9574ad,_0x5242fe){return _0x2033eb(_0x9574ad,_0x5242fe);},'PKEeM':function(_0x191551,_0x133f2b,_0x36a6e0){return _0x191551(_0x133f2b,_0x36a6e0);},'xdzND':_0x268a8f(0x20a,'2VU1'),'ZyqFL':function(_0x27ee64,_0x2c8c4d,_0x10f731){return _0x27ee64(_0x2c8c4d,_0x10f731);},'CjYkL':_0x268a8f(0x2ce,'slIE'),'SBHNK':_0x268a8f(0x583,'1&yx'),'bgoMk':_0x268a8f(0x426,'H)P7'),'jfSIh':function(_0x475a77,_0x158e8a){return _0x475a77*_0x158e8a;},'ANiBD':function(_0x2f9e67,_0x242a15){return _0x2f9e67%_0x242a15;},'MFtaf':_0x268a8f(0x5f0,'wMTb'),'eUvuc':function(_0x4302b9,_0x1258c4){return _0x4302b9&_0x1258c4;},'NIQjl':function(_0x2b2bab,_0x41a1de){return _0x2b2bab>>_0x41a1de;},'AdPTR':_0x268a8f(0x53d,'H)P7'),'uLvBD':function(_0x3d1f0a,_0x30e19e){return _0x3d1f0a<_0x30e19e;},'VnJvU':_0x268a8f(0x5e5,'zQx('),'PYHll':_0x268a8f(0x2bd,'9E)9'),'lgukk':function(_0x4f5561,_0x5d604){return _0x4f5561(_0x5d604);},'ZzdQX':function(_0x2eb8f7,_0x67083d){return _0x2eb8f7+_0x67083d;},'RXtZG':function(_0xe0b9a0,_0x5b5b76){return _0xe0b9a0(_0x5b5b76);},'MuGUB':function(_0x504329,_0x339eeb){return _0x504329<_0x339eeb;},'zSEpD':function(_0x2c7f26,_0x292abf){return _0x2c7f26%_0x292abf;},'kxSOv':function(_0x59f64f,_0x15a561){return _0x59f64f+_0x15a561;},'gnZeA':function(_0x151d41,_0x2b933a){return _0x151d41^_0x2b933a;},'SuRWp':function(_0x13aefa,_0x2079e4){return _0x13aefa%_0x2079e4;},'IBurR':function(_0x57a355,_0x1071de){return _0x57a355===_0x1071de;},'vvBnq':_0x268a8f(0x4d7,'2VU1'),'COqDr':function(_0x25fec6,_0x509979,_0x36e37d){return _0x25fec6(_0x509979,_0x36e37d);},'cvvTy':_0x268a8f(0x1e3,'slIE'),'LOIOl':_0x268a8f(0x5e1,'V!G1'),'WzJhg':_0x268a8f(0x58e,'SNss'),'uyZUH':function(_0x48cf53,_0x15b380,_0x1d3712){return _0x48cf53(_0x15b380,_0x1d3712);},'QhOPZ':_0x268a8f(0x2f4,'@YGJ'),'vgGHj':function(_0x2abc3f,_0x4f1159){return _0x2abc3f===_0x4f1159;},'oTnwv':_0x268a8f(0x5eb,'(a1@'),'IQteD':function(_0x3be74b,_0x280291,_0xcbfe99){return _0x3be74b(_0x280291,_0xcbfe99);},'FUMQd':function(_0x40077d,_0x580fa7,_0xb40612){return _0x40077d(_0x580fa7,_0xb40612);},'jTPRg':function(_0x42621f,_0x51be88,_0x10b617){return _0x42621f(_0x51be88,_0x10b617);},'hoGXt':_0x268a8f(0x46e,'9E)9'),'IVnPg':_0x268a8f(0x493,'8UKT'),'fZeeD':function(_0x584046,_0x2f1ef7,_0x491647){return _0x584046(_0x2f1ef7,_0x491647);},'lPDXn':function(_0x2fd247,_0x42ce09,_0x29e59b){return _0x2fd247(_0x42ce09,_0x29e59b);},'WtqtS':function(_0x181f2b,_0x46c672,_0x25942a){return _0x181f2b(_0x46c672,_0x25942a);},'rNUFh':function(_0x1a11ad,_0x5fb094){return _0x1a11ad===_0x5fb094;},'Rpqut':_0x268a8f(0x5ed,'wmsW'),'aDndt':function(_0x39acc1,_0xe6cc10,_0x3cd4dd){return _0x39acc1(_0xe6cc10,_0x3cd4dd);},'jVFkX':function(_0x2ac474,_0x564aa9,_0x4866c2){return _0x2ac474(_0x564aa9,_0x4866c2);},'xASVr':function(_0x118317,_0x2045a2,_0x48252a){return _0x118317(_0x2045a2,_0x48252a);},'KKjSY':function(_0x5354df,_0x42aac6,_0x2011c0){return _0x5354df(_0x42aac6,_0x2011c0);},'FeEzh':function(_0x49ca90,_0x112808){return _0x49ca90!==_0x112808;},'bSOSj':_0x268a8f(0x5ae,'A6VI'),'bZryB':function(_0x1a6048,_0x9f092c,_0x47ae62){return _0x1a6048(_0x9f092c,_0x47ae62);},'TFaBR':_0x268a8f(0x27a,'9I[N'),'ZNrOq':_0x268a8f(0x2c1,'ymb#'),'ZOOoX':_0x268a8f(0x4b4,'1K1j'),'TfYJS':_0x268a8f(0x399,'(a1@'),'nGDJo':function(_0x5040b6,_0x5b6f04){return _0x5040b6!==_0x5b6f04;},'llibW':_0x268a8f(0x539,'9I[N'),'lqRdp':_0x268a8f(0x4de,'^sVw'),'CSWav':_0x268a8f(0x48a,')uaP'),'lRXuR':_0x268a8f(0x268,'JC^q'),'MweNL':function(_0x4cc0ad,_0x21bdb6,_0x4409e4){return _0x4cc0ad(_0x21bdb6,_0x4409e4);},'rawoy':_0x268a8f(0x1ee,'@9X4'),'zOpPl':_0x268a8f(0x2d9,'S@xV'),'Phaax':_0x268a8f(0x45e,'slIE'),'UcJEr':function(_0xf1a535,_0x36a5a9){return _0xf1a535===_0x36a5a9;},'PrdcK':_0x268a8f(0x3ee,'mSQ#'),'HWunX':_0x268a8f(0x314,'@y77'),'xNhve':function(_0x2ea7ac,_0x44194b,_0x53f6f8){return _0x2ea7ac(_0x44194b,_0x53f6f8);},'OLBjX':_0x268a8f(0x3cd,'1&yx'),'LkDxm':_0x268a8f(0x203,'3uM9'),'Rohbe':function(_0x2cd07d,_0x5a4613,_0x5cda89){return _0x2cd07d(_0x5a4613,_0x5cda89);},'BPnKn':_0x268a8f(0x200,'9E)9'),'GuwKY':function(_0x5c30d6,_0x3eb80b,_0x4c9600){return _0x5c30d6(_0x3eb80b,_0x4c9600);},'CfYuW':_0x268a8f(0x313,'9E)9'),'cvsbu':function(_0x55db81,_0x30fa38,_0x97b894){return _0x55db81(_0x30fa38,_0x97b894);},'WBWjR':_0x268a8f(0x274,'BLAX'),'CubqP':_0x268a8f(0x622,'JC^q'),'aVNlu':function(_0x496713,_0x44fec5,_0xff4811){return _0x496713(_0x44fec5,_0xff4811);},'wTldB':function(_0x444b74,_0x35d54d,_0x2934ef){return _0x444b74(_0x35d54d,_0x2934ef);},'YJdOz':function(_0x435de7,_0x76f3e6,_0x390e56){return _0x435de7(_0x76f3e6,_0x390e56);},'wnXLb':function(_0x94f870,_0x4e129e,_0x5aa863){return _0x94f870(_0x4e129e,_0x5aa863);},'JKBTk':function(_0x31e3f0,_0x13380b,_0x342a36){return _0x31e3f0(_0x13380b,_0x342a36);},'oaLDb':_0x268a8f(0x451,'(2Hx'),'MQjVu':function(_0x5319e8,_0x2b7620,_0x13eb79){return _0x5319e8(_0x2b7620,_0x13eb79);},'eJVbb':function(_0x4913d3,_0x5b35e9,_0x4b32a6){return _0x4913d3(_0x5b35e9,_0x4b32a6);},'CDroI':function(_0x21143b,_0x380061,_0x5e3767){return _0x21143b(_0x380061,_0x5e3767);},'xutAP':function(_0x4c8036,_0x3e46cd,_0x1c5fcd){return _0x4c8036(_0x3e46cd,_0x1c5fcd);},'zJOnW':function(_0x53b8a6,_0x4411a2,_0x5cc370){return _0x53b8a6(_0x4411a2,_0x5cc370);},'YDkLI':function(_0x3c4615,_0x44d0d3,_0x38ab53){return _0x3c4615(_0x44d0d3,_0x38ab53);},'nPcQN':_0x268a8f(0x58c,'@y77'),'aPzii':_0x268a8f(0x4bd,'slIE'),'RUsQY':function(_0x170686,_0x933ddb,_0x1caee0){return _0x170686(_0x933ddb,_0x1caee0);}};const _0x408723=_0x4996,_0xbee5b8={'zCsxu':_0x4f425f[_0x268a8f(0x3f0,'2VU1')](_0x408723,0x1b9,_0x4f425f[_0x268a8f(0x4ae,'A6VI')]),'ziARw':_0x4f425f[_0x268a8f(0x5c8,'ymb#')](_0x408723,0x1f5,_0x4f425f[_0x268a8f(0x456,'wMTb')]),'tNEuJ':_0x4f425f[_0x268a8f(0x310,'zQx(')](_0x408723,0x1dc,_0x4f425f[_0x268a8f(0x448,'I2Yw')]),'fRhYg':function(_0x4fe499,_0x5c431c){const _0x431314=_0x268a8f;return _0x4f425f[_0x431314(0x624,'Ny33')](_0x4f425f[_0x431314(0x467,'lk5H')],_0x4f425f[_0x431314(0x5ca,'$Q0[')])?_0x4f425f[_0x431314(0x3a9,'b#ZE')](_0x4fe499,_0x5c431c):_0x369def;},'cSMdb':function(_0x38339a,_0x2cbbef){const _0xd15b3e=_0x268a8f,_0x2162e={'bTPlS':function(_0x52bcfe,_0x5488d1){const _0x10612c=_0x2a23;return _0x4f425f[_0x10612c(0x3df,'I2Yw')](_0x52bcfe,_0x5488d1);}};return _0x4f425f[_0xd15b3e(0x5f4,'1K1j')](_0x4f425f[_0xd15b3e(0x294,'JC^q')],_0x4f425f[_0xd15b3e(0x567,'wmsW')])?_0x2162e[_0xd15b3e(0x22e,'zQx(')](_0x22f22c,_0x110a69):_0x4f425f[_0xd15b3e(0x4da,'H)P7')](_0x38339a,_0x2cbbef);},'hVktQ':_0x4f425f[_0x268a8f(0x30c,'3uM9')](_0x408723,0x1b4,_0x4f425f[_0x268a8f(0x29b,'slIE')]),'WhUhl':_0x4f425f[_0x268a8f(0x423,'2VU1')](_0x408723,0x1b5,_0x4f425f[_0x268a8f(0x47d,'wMTb')]),'EKLdg':function(_0x665db4,_0x5cd899){const _0x586739=_0x268a8f;if(_0x4f425f[_0x586739(0x1f5,'Zy9h')](_0x4f425f[_0x586739(0x43f,'8UKT')],_0x4f425f[_0x586739(0x275,'@YGJ')]))return _0x4f425f[_0x586739(0x44d,'2hgo')](_0x665db4,_0x5cd899);else{if(_0x2ce0a4[_0x4f425f[_0x586739(0x3a0,'A6VI')](_0x3a020b,0x1a5,_0x4f425f[_0x586739(0x5e2,'Y(3w')])]&&_0x481c91[_0x4f425f[_0x586739(0x41c,'slIE')](_0x1c6a94,0x1a7,_0x4f425f[_0x586739(0x629,'Ny33')])]&&(_0x5f48ee[_0x4f425f[_0x586739(0x1cd,'I2Yw')](_0x5cd2ae,0x1a4,_0x4f425f[_0x586739(0x586,'slIE')])](_0x226aa5,0x49)||_0xc304c5[_0x4f425f[_0x586739(0x3d6,'mSQ#')](_0x2ebf04,0x199,_0x4f425f[_0x586739(0x2cc,'@YGJ')])](_0x180451,0x4a)||_0x574611[_0x4f425f[_0x586739(0x279,'V!G1')](_0x3b2621,0x18d,_0x4f425f[_0x586739(0x63d,'uizP')])](_0x10944e,0x43)||_0x437167[_0x4f425f[_0x586739(0x25e,'2hgo')](_0x196ff4,0x1ce,_0x4f425f[_0x586739(0x241,'wMTb')])](_0x319a08,0x4b)))_0x3623bb[_0x4f425f[_0x586739(0x2b2,'H)P7')](_0xaa30ca,0x1a6,_0x4f425f[_0x586739(0x23c,'H)P7')])](_0x2fa3c0[_0x4f425f[_0x586739(0x2e7,'3uM9')](_0x2e89da,0x1f4,_0x4f425f[_0x586739(0x3f6,'2hgo')])],_0x2de1ab[_0x4f425f[_0x586739(0x1db,'mgUY')](_0x2387cd,0x1d0,_0x4f425f[_0x586739(0x544,'5ve!')])])?_0x298b6c=!![]:_0x4081d1=!![];else{if(_0x1b04ed[_0x4f425f[_0x586739(0x3e3,'NcTP')](_0x50170f,0x1b6,_0x4f425f[_0x586739(0x5f1,'9I[N')])]&&_0x3f8c62[_0x4f425f[_0x586739(0x237,'uizP')](_0x5459c2,0x1ac,_0x4f425f[_0x586739(0x601,'9E)9')])](_0x9750a7,0x55))_0x1f8af3[_0x4f425f[_0x586739(0x31b,'e7Ck')](_0x25cd01,0x18e,_0x4f425f[_0x586739(0x2d7,'NcTP')])](_0x5a6762[_0x4f425f[_0x586739(0x31d,'H)P7')](_0x1d04bb,0x1cd,_0x4f425f[_0x586739(0x3dc,'e7Ck')])],_0xd3da06[_0x4f425f[_0x586739(0x50d,'@YGJ')](_0x3e4245,0x18f,_0x4f425f[_0x586739(0x594,'9E)9')])])?_0xf71952=!![]:_0x442221=!![];else _0x27b2ec[_0x4f425f[_0x586739(0x372,'1&yx')](_0x3ddb78,0x1e3,_0x4f425f[_0x586739(0x3cf,'1&yx')])]&&_0x327723[_0x4f425f[_0x586739(0x409,'(2Hx')](_0x48ee5a,0x1c1,_0x4f425f[_0x586739(0x2b6,'wMTb')])](_0x38ee44,0x55)&&(_0xdffe08[_0x4f425f[_0x586739(0x3ac,'JC^q')](_0x5c3b2d,0x1e1,_0x4f425f[_0x586739(0x2ec,'($8%')])](_0x3ea48e[_0x4f425f[_0x586739(0x668,'$Q0[')](_0x37d9a4,0x1ad,_0x4f425f[_0x586739(0x3ae,'9I[N')])],_0x161bc3[_0x4f425f[_0x586739(0x2c4,'JC^q')](_0x3911be,0x1ab,_0x4f425f[_0x586739(0x47d,'wMTb')])])?_0xedc64=!![]:_0x253af7=!![]);}}},'QMtwB':function(_0x25c1d7,_0x1b9c87){const _0x4f2903=_0x268a8f,_0x5b97d4={'ldYYR':function(_0x5edaca,_0x2f05ae){const _0x54f2e0=_0x2a23;return _0x4f425f[_0x54f2e0(0x435,'2VU1')](_0x5edaca,_0x2f05ae);}};return _0x4f425f[_0x4f2903(0x309,'9E)9')](_0x4f425f[_0x4f2903(0x376,'lk5H')],_0x4f425f[_0x4f2903(0x5fd,'wmsW')])?_0x5b97d4[_0x4f2903(0x4c3,'wmsW')](_0x46206f,_0x13f733):_0x4f425f[_0x4f2903(0x23e,'H)P7')](_0x25c1d7,_0x1b9c87);},'SIpmh':function(_0x4bbcb9,_0x392e6c){const _0x3ef485=_0x268a8f;if(_0x4f425f[_0x3ef485(0x58f,'ymb#')](_0x4f425f[_0x3ef485(0x566,'^sVw')],_0x4f425f[_0x3ef485(0x1cf,'8UKT')]))_0x3f0f8a[_0x3e3ff9]=_0x2a8b30;else return _0x4f425f[_0x3ef485(0x3d3,'wMTb')](_0x4bbcb9,_0x392e6c);},'bBLfh':_0x4f425f[_0x268a8f(0x320,'lmOZ')](_0x408723,0x19f,_0x4f425f[_0x268a8f(0x579,'e7Ck')]),'znocf':function(_0x33469c,_0x1cc54c){const _0x503958=_0x268a8f,_0x59edad={'lzkLg':function(_0x19b146,_0xacdf84){const _0xb5f684=_0x2a23;return _0x4f425f[_0xb5f684(0x3c3,'NcTP')](_0x19b146,_0xacdf84);}};return _0x4f425f[_0x503958(0x3d4,'9I[N')](_0x4f425f[_0x503958(0x273,'b#ZE')],_0x4f425f[_0x503958(0x302,'BLAX')])?_0x4f425f[_0x503958(0x4ce,'wmsW')](_0x33469c,_0x1cc54c):_0x59edad[_0x503958(0x217,'h5BR')](_0x90ab6b,_0x1a5cb0);},'XRLDf':function(_0x1f9939,_0x54a19d){const _0x445296=_0x268a8f,_0x1af5c7={'crTLo':function(_0x196568,_0x445f35){const _0x5d8390=_0x2a23;return _0x4f425f[_0x5d8390(0x370,'BLAX')](_0x196568,_0x445f35);}};return _0x4f425f[_0x445296(0x2bb,'slIE')](_0x4f425f[_0x445296(0x2bc,'eRZ)')],_0x4f425f[_0x445296(0x5b7,'($8%')])?_0x1af5c7[_0x445296(0x53e,'@9X4')](_0x3222a7,_0x3cbc6e):_0x4f425f[_0x445296(0x405,'1&yx')](_0x1f9939,_0x54a19d);},'OzTXq':function(_0xf272f8,_0x4f187b){const _0x2c71e2=_0x268a8f,_0xa7fc15={'nmBxj':function(_0x5578ff,_0x20438f,_0xc33bcf){const _0x46b504=_0x2a23;return _0x4f425f[_0x46b504(0x466,'7z$v')](_0x5578ff,_0x20438f,_0xc33bcf);},'MYQdn':_0x4f425f[_0x2c71e2(0x512,'eRZ)')],'wPcet':function(_0xf6ea23,_0x3d7c14,_0x19ff2c){const _0x43725f=_0x2c71e2;return _0x4f425f[_0x43725f(0x506,'S@xV')](_0xf6ea23,_0x3d7c14,_0x19ff2c);},'rkhPu':_0x4f425f[_0x2c71e2(0x331,'wMTb')],'sPBiI':function(_0x21e109,_0x118500,_0x5cbfc5){const _0xfcc863=_0x2c71e2;return _0x4f425f[_0xfcc863(0x2dd,'BLAX')](_0x21e109,_0x118500,_0x5cbfc5);},'ywcoI':_0x4f425f[_0x2c71e2(0x1df,'56OX')],'CLtGx':_0x4f425f[_0x2c71e2(0x393,')uaP')],'wnItf':function(_0x2dfb0f,_0x22f491,_0x44dbc4){const _0x24f225=_0x2c71e2;return _0x4f425f[_0x24f225(0x598,'mSQ#')](_0x2dfb0f,_0x22f491,_0x44dbc4);},'mmZQI':_0x4f425f[_0x2c71e2(0x335,'8UKT')],'gWvcp':_0x4f425f[_0x2c71e2(0x338,'e7Ck')],'rgafA':function(_0x1d82ff,_0x44aada,_0x4dfe27){const _0x4efea9=_0x2c71e2;return _0x4f425f[_0x4efea9(0x621,'2hgo')](_0x1d82ff,_0x44aada,_0x4dfe27);},'qxyoX':_0x4f425f[_0x2c71e2(0x2b6,'wMTb')],'gqkUQ':function(_0x468d68,_0x4b5ee2,_0xbda8a4){const _0x1ee900=_0x2c71e2;return _0x4f425f[_0x1ee900(0x254,'9E)9')](_0x468d68,_0x4b5ee2,_0xbda8a4);},'tCuYL':_0x4f425f[_0x2c71e2(0x557,'Zy9h')],'Ascik':function(_0x2b4b69,_0x2741c1,_0x5d5fb8){const _0x2682bc=_0x2c71e2;return _0x4f425f[_0x2682bc(0x36e,'@YGJ')](_0x2b4b69,_0x2741c1,_0x5d5fb8);},'hFWCJ':_0x4f425f[_0x2c71e2(0x440,'1K1j')],'SbXSw':_0x4f425f[_0x2c71e2(0x24a,'1&yx')]};if(_0x4f425f[_0x2c71e2(0x1e7,'1&yx')](_0x4f425f[_0x2c71e2(0x432,'@y77')],_0x4f425f[_0x2c71e2(0x64d,'@9X4')])){if(_0x4be515[_0xa7fc15[_0x2c71e2(0x5f5,'h5BR')](_0x35956d,0x1b6,_0xa7fc15[_0x2c71e2(0x4c7,'Zy9h')])]&&_0x27ccda[_0xa7fc15[_0x2c71e2(0x5a0,'H)P7')](_0x30ebe6,0x1ac,_0xa7fc15[_0x2c71e2(0x507,'zQx(')])](_0x42ec2c,0x55))_0x4f1dc7[_0xa7fc15[_0x2c71e2(0x1e6,'BLAX')](_0x8da3c6,0x18e,_0xa7fc15[_0x2c71e2(0x626,'5ve!')])](_0x3383d9[_0xa7fc15[_0x2c71e2(0x3fe,'I2Yw')](_0x159978,0x1cd,_0xa7fc15[_0x2c71e2(0x613,'56OX')])],_0x3e3415[_0xa7fc15[_0x2c71e2(0x4df,'AT@B')](_0x34e14,0x18f,_0xa7fc15[_0x2c71e2(0x55c,'7z$v')])])?_0xa450cc=!![]:_0x125c3f=!![];else _0x3795e6[_0xa7fc15[_0x2c71e2(0x5dc,'lmOZ')](_0xecf618,0x1e3,_0xa7fc15[_0x2c71e2(0x4a0,'1K1j')])]&&_0xefa7db[_0xa7fc15[_0x2c71e2(0x429,'H)P7')](_0x265377,0x1c1,_0xa7fc15[_0x2c71e2(0x26b,'A6VI')])](_0xb7183f,0x55)&&(_0x1dd090[_0xa7fc15[_0x2c71e2(0x3d0,'9I[N')](_0x5d9ad8,0x1e1,_0xa7fc15[_0x2c71e2(0x3e5,'56OX')])](_0x25bee1[_0xa7fc15[_0x2c71e2(0x2a6,'2VU1')](_0x24a5a1,0x1ad,_0xa7fc15[_0x2c71e2(0x31c,'wmsW')])],_0xa38b95[_0xa7fc15[_0x2c71e2(0x424,'I2Yw')](_0x11dc4a,0x1ab,_0xa7fc15[_0x2c71e2(0x1f6,'lmOZ')])])?_0x583cfe=!![]:_0x2d6da4=!![]);}else return _0x4f425f[_0x2c71e2(0x223,'5ve!')](_0xf272f8,_0x4f187b);},'TWIHN':_0x4f425f[_0x268a8f(0x373,'7z$v')](_0x408723,0x1b8,_0x4f425f[_0x268a8f(0x2b1,'Zy9h')]),'nkfDX':function(_0x97fe39,_0x27e842){const _0x3c6067=_0x268a8f;return _0x4f425f[_0x3c6067(0x569,'NcTP')](_0x4f425f[_0x3c6067(0x5d0,'@YGJ')],_0x4f425f[_0x3c6067(0x3ea,'@9X4')])?_0x4f425f[_0x3c6067(0x3f4,'mSQ#')](_0x2b7061,_0x54da14):_0x4f425f[_0x3c6067(0x3c3,'NcTP')](_0x97fe39,_0x27e842);},'AOlUI':function(_0x4eb8c1,_0x296837){const _0x65cd9d=_0x268a8f;if(_0x4f425f[_0x65cd9d(0x328,'NcTP')](_0x4f425f[_0x65cd9d(0x418,'^sVw')],_0x4f425f[_0x65cd9d(0x478,'($8%')])){if(_0x22e96e[_0x4f425f[_0x65cd9d(0x343,'7z$v')](_0x14aaeb,0x1be,_0x4f425f[_0x65cd9d(0x1e0,'BLAX')])]&&_0x2202d1[_0x4f425f[_0x65cd9d(0x1ca,'SNss')](_0x153551,0x19c,_0x4f425f[_0x65cd9d(0x262,'H)P7')])]&&(_0x429f5a[_0x4f425f[_0x65cd9d(0x24e,'Ny33')](_0x540e70,0x1f0,_0x4f425f[_0x65cd9d(0x441,'H)P7')])](_0x56fcdd,0x49)||_0x6cd6e[_0x4f425f[_0x65cd9d(0x62d,'ymb#')](_0x58592b,0x197,_0x4f425f[_0x65cd9d(0x3ce,'lmOZ')])](_0x5bf582,0x4a)||_0x40f28a[_0x4f425f[_0x65cd9d(0x283,'1K1j')](_0x1d06e4,0x1ca,_0x4f425f[_0x65cd9d(0x34e,'e7Ck')])](_0x5c5f5d,0x43)||_0x37ebae[_0x4f425f[_0x65cd9d(0x23d,'NcTP')](_0x146134,0x1e6,_0x4f425f[_0x65cd9d(0x461,'NcTP')])](_0x296af3,0x4b))){if(_0x5771fd[_0x4f425f[_0x65cd9d(0x3e2,'eRZ)')](_0x111a60,0x1c0,_0x4f425f[_0x65cd9d(0x245,'@YGJ')])](_0x27056e[_0x4f425f[_0x65cd9d(0x602,'AT@B')](_0x161fb6,0x1cf,_0x4f425f[_0x65cd9d(0x647,'lmOZ')])],_0x44d521[_0x4f425f[_0x65cd9d(0x2e1,'9I[N')](_0x522f61,0x1cf,_0x4f425f[_0x65cd9d(0x321,'^sVw')])]))_0x5daaf2=!![];else return;}else{if(_0x3ea6a4[_0x4f425f[_0x65cd9d(0x63f,'I2Yw')](_0xc48a92,0x1a5,_0x4f425f[_0x65cd9d(0x419,'S@xV')])]&&_0x5b8cc9[_0x4f425f[_0x65cd9d(0x4cb,'lmOZ')](_0x25cd4e,0x1a7,_0x4f425f[_0x65cd9d(0x272,'slIE')])]&&(_0x2f13c2[_0x4f425f[_0x65cd9d(0x59b,'@9X4')](_0x23468a,0x1a4,_0x4f425f[_0x65cd9d(0x318,'AT@B')])](_0x5d8f10,0x49)||_0x282a34[_0x4f425f[_0x65cd9d(0x518,'1&yx')](_0x118bb1,0x199,_0x4f425f[_0x65cd9d(0x333,'b#ZE')])](_0x35669d,0x4a)||_0x1e3e50[_0x4f425f[_0x65cd9d(0x56d,'slIE')](_0x107ac4,0x18d,_0x4f425f[_0x65cd9d(0x2b7,'S@xV')])](_0x545a27,0x43)||_0x57ee7b[_0x4f425f[_0x65cd9d(0x2a3,'wmsW')](_0x455dc3,0x1ce,_0x4f425f[_0x65cd9d(0x655,'slIE')])](_0x13f0fd,0x4b)))_0x14f6e4[_0x4f425f[_0x65cd9d(0x22a,'(2Hx')](_0x5fde95,0x1a6,_0x4f425f[_0x65cd9d(0x4b2,'Y(3w')])](_0x66dfb7[_0x4f425f[_0x65cd9d(0x1d5,'ymb#')](_0x1cba71,0x1f4,_0x4f425f[_0x65cd9d(0x543,'@YGJ')])],_0x1375b0[_0x4f425f[_0x65cd9d(0x2de,'h5BR')](_0x29204b,0x1d0,_0x4f425f[_0x65cd9d(0x536,'zQx(')])])?_0x27bddf=!![]:_0x173dfb=!![];else{if(_0x5042ff[_0x4f425f[_0x65cd9d(0x367,'uizP')](_0x1f1d1f,0x1b6,_0x4f425f[_0x65cd9d(0x5e7,'3uM9')])]&&_0x6d8006[_0x4f425f[_0x65cd9d(0x4dd,'JC^q')](_0x145508,0x1ac,_0x4f425f[_0x65cd9d(0x4e2,'2hgo')])](_0x390fc,0x55))_0x1fe1b8[_0x4f425f[_0x65cd9d(0x4d2,'3uM9')](_0x3dc234,0x18e,_0x4f425f[_0x65cd9d(0x4ab,'AT@B')])](_0x40f743[_0x4f425f[_0x65cd9d(0x436,'SNss')](_0x18dd3c,0x1cd,_0x4f425f[_0x65cd9d(0x202,'SNss')])],_0x302a39[_0x4f425f[_0x65cd9d(0x1bb,'1&yx')](_0x5bbb69,0x18f,_0x4f425f[_0x65cd9d(0x271,'3uM9')])])?_0x2ab8a7=!![]:_0xda22d1=!![];else _0xa17916[_0x4f425f[_0x65cd9d(0x377,'(2Hx')](_0x50a6be,0x1e3,_0x4f425f[_0x65cd9d(0x3a7,'mSQ#')])]&&_0x3e4ece[_0x4f425f[_0x65cd9d(0x634,'Y(3w')](_0x20ca15,0x1c1,_0x4f425f[_0x65cd9d(0x62a,'(a1@')])](_0x4cd6d2,0x55)&&(_0x2a2670[_0x4f425f[_0x65cd9d(0x56e,'zQx(')](_0xaf1b5,0x1e1,_0x4f425f[_0x65cd9d(0x559,'ymb#')])](_0x515321[_0x4f425f[_0x65cd9d(0x4e0,'b#ZE')](_0x3e84e4,0x1ad,_0x4f425f[_0x65cd9d(0x4f2,'iPqW')])],_0x468992[_0x4f425f[_0x65cd9d(0x2b0,'9E)9')](_0x10304e,0x1ab,_0x4f425f[_0x65cd9d(0x47d,'wMTb')])])?_0x260ac8=!![]:_0x10ba25=!![]);}}}else return _0x4f425f[_0x65cd9d(0x502,'AT@B')](_0x4eb8c1,_0x296837);},'iKhFv':_0x4f425f[_0x268a8f(0x584,'Zy9h')](_0x408723,0x191,_0x4f425f[_0x268a8f(0x342,'2VU1')]),'ybJAo':function(_0x448ee7,_0xbec42a){const _0x4078f0=_0x268a8f;if(_0x4f425f[_0x4078f0(0x509,'Zy9h')](_0x4f425f[_0x4078f0(0x590,'($8%')],_0x4f425f[_0x4078f0(0x3a4,'^sVw')]))_0x4f8bd2[_0x4f425f[_0x4078f0(0x4a9,'^sVw')]](_0xee7efb[_0x4f425f[_0x4078f0(0x4a5,'7z$v')]]());else return _0x4f425f[_0x4078f0(0x22c,'($8%')](_0x448ee7,_0xbec42a);},'TrrSZ':_0x4f425f[_0x268a8f(0x2ef,'wmsW')](_0x408723,0x1c8,_0x4f425f[_0x268a8f(0x206,'JC^q')]),'eKMNN':_0x4f425f[_0x268a8f(0x28a,'eRZ)')](_0x408723,0x1c2,_0x4f425f[_0x268a8f(0x40f,'NcTP')]),'mKJDo':_0x4f425f[_0x268a8f(0x5d1,'JC^q')](_0x408723,0x1c3,_0x4f425f[_0x268a8f(0x22d,'7z$v')]),'kZUSC':function(_0x1879be,_0x43f897){const _0x7f8066=_0x268a8f;if(_0x4f425f[_0x7f8066(0x66e,'AT@B')](_0x4f425f[_0x7f8066(0x25b,'b#ZE')],_0x4f425f[_0x7f8066(0x29e,'AT@B')]))_0x2f51ec=_0x4f425f[_0x7f8066(0x51a,'uizP')](_0x4f425f[_0x7f8066(0x361,'I2Yw')](_0x4f425f[_0x7f8066(0x1dd,'9E)9')](_0x404d72,_0x164a8f[_0x19aab6]),_0x102865[_0x4f425f[_0x7f8066(0x4d6,'b#ZE')]](_0x4f425f[_0x7f8066(0x4f0,'NcTP')](_0xd6cfb2,_0x377a70[_0x4f425f[_0x7f8066(0x542,'b#ZE')]]))),0x100),_0x4db82d=_0x3ec1b7[_0x62d10b],_0x4e850c[_0x2a6d1b]=_0xb937a4[_0x1ae642],_0x76d0c8[_0x5b86a9]=_0x27c91f;else return _0x4f425f[_0x7f8066(0x52d,'BLAX')](_0x1879be,_0x43f897);},'LTwBw':_0x4f425f[_0x268a8f(0x249,'H)P7')](_0x408723,0x1e0,_0x4f425f[_0x268a8f(0x591,'SNss')]),'pccyJ':_0x4f425f[_0x268a8f(0x317,'F(Dh')](_0x408723,0x1db,_0x4f425f[_0x268a8f(0x56c,'wmsW')]),'ngbzo':function(_0x39f447,_0x1ad109){const _0x90e14f=_0x268a8f;return _0x4f425f[_0x90e14f(0x288,'9E)9')](_0x4f425f[_0x90e14f(0x45f,'mSQ#')],_0x4f425f[_0x90e14f(0x282,'2VU1')])?_0x4f425f[_0x90e14f(0x2c6,'56OX')](_0x6847f9,_0x2acd9e):_0x4f425f[_0x90e14f(0x5a6,'uizP')](_0x39f447,_0x1ad109);},'fuCij':_0x4f425f[_0x268a8f(0x1c9,'^sVw')](_0x408723,0x1a3,_0x4f425f[_0x268a8f(0x5df,'mSQ#')]),'XaQxS':_0x4f425f[_0x268a8f(0x4ac,'3uM9')](_0x408723,0x1d3,_0x4f425f[_0x268a8f(0x526,'@YGJ')]),'BQIuA':_0x4f425f[_0x268a8f(0x382,'$Q0[')](_0x408723,0x1ed,_0x4f425f[_0x268a8f(0x525,'5ve!')])};if(_0xbee5b8[_0x4f425f[_0x268a8f(0x27e,'(a1@')](_0x408723,0x1d4,_0x4f425f[_0x268a8f(0x3dd,'S@xV')])](sessionStorage[_0x4f425f[_0x268a8f(0x54f,'h5BR')](_0x408723,0x19a,_0x4f425f[_0x268a8f(0x4db,'qQBc')])](_0xbee5b8[_0x4f425f[_0x268a8f(0x51f,'uizP')](_0x408723,0x1bf,_0x4f425f[_0x268a8f(0x1d0,'e7Ck')])]),_0xbee5b8[_0x4f425f[_0x268a8f(0x3f8,'^sVw')](_0x408723,0x1f2,_0x4f425f[_0x268a8f(0x4bf,'3uM9')])])){if(_0x4f425f[_0x268a8f(0x57e,'@YGJ')](_0x4f425f[_0x268a8f(0x1f2,'wmsW')],_0x4f425f[_0x268a8f(0x315,'h5BR')]))return _0x4f425f[_0x268a8f(0x671,'iPqW')](_0x4386a6,_0x4f3517);else{if(_0xbee5b8[_0x4f425f[_0x268a8f(0x4a2,'1&yx')](_0x408723,0x1ea,_0x4f425f[_0x268a8f(0x1e9,'mgUY')])](_0xbee5b8[_0x4f425f[_0x268a8f(0x570,'S@xV')](_0x408723,0x1e9,_0x4f425f[_0x268a8f(0x5e6,'1&yx')])],_0xbee5b8[_0x4f425f[_0x268a8f(0x367,'uizP')](_0x408723,0x1f1,_0x4f425f[_0x268a8f(0x1f3,'lk5H')])]))_0x438b4f[_0x4f425f[_0x268a8f(0x3d2,'wMTb')](_0x408723,0x1f3,_0x4f425f[_0x268a8f(0x3bc,'1K1j')])](_0xbee5b8[_0x4f425f[_0x268a8f(0x615,'iPqW')](_0x408723,0x1ba,_0x4f425f[_0x268a8f(0x235,'1&yx')])],_0xbee5b8[_0x4f425f[_0x268a8f(0x1d8,'NcTP')](_0x408723,0x195,_0x4f425f[_0x268a8f(0x32e,'8UKT')])]);else return;}}const _0x1e2448=_0xbee5b8[_0x4f425f[_0x268a8f(0x1c7,'@YGJ')](_0x408723,0x1bc,_0x4f425f[_0x268a8f(0x3b7,'lmOZ')])];function _0x1e5fb8(_0x15a400){const _0x49e338=_0x268a8f,_0x3c0d13={'JkxKC':function(_0x1249cf,_0x3ef548){const _0x5cee50=_0x2a23;return _0x4f425f[_0x5cee50(0x5a7,'S@xV')](_0x1249cf,_0x3ef548);},'mZUlg':function(_0x4c7d0f,_0x4463b1){const _0x4d68c8=_0x2a23;return _0x4f425f[_0x4d68c8(0x50c,'wmsW')](_0x4c7d0f,_0x4463b1);},'CtsMg':function(_0xc3c7c1,_0x426a12){const _0x41455d=_0x2a23;return _0x4f425f[_0x41455d(0x2f1,'AT@B')](_0xc3c7c1,_0x426a12);},'OzvmT':function(_0x4d7ab4,_0x51dba3){const _0xee4a36=_0x2a23;return _0x4f425f[_0xee4a36(0x483,'2hgo')](_0x4d7ab4,_0x51dba3);},'ovgde':function(_0x4a2495,_0x410893){const _0x1a4beb=_0x2a23;return _0x4f425f[_0x1a4beb(0x574,'Y(3w')](_0x4a2495,_0x410893);},'sdAtd':function(_0x530f44,_0x7b81c5){const _0x3c40b7=_0x2a23;return _0x4f425f[_0x3c40b7(0x581,'@YGJ')](_0x530f44,_0x7b81c5);},'gsKxN':_0x4f425f[_0x49e338(0x1c6,'iPqW')],'mMljl':function(_0x4ab44c,_0x2e7666){const _0x2399ed=_0x49e338;return _0x4f425f[_0x2399ed(0x27f,'b#ZE')](_0x4ab44c,_0x2e7666);},'ugqoa':_0x4f425f[_0x49e338(0x226,'56OX')],'wheio':function(_0x585a21,_0x50e151){const _0x2aab53=_0x49e338;return _0x4f425f[_0x2aab53(0x292,'2hgo')](_0x585a21,_0x50e151);},'XCSjq':_0x4f425f[_0x49e338(0x38f,'8UKT')],'nMVNA':function(_0x3884bd,_0x476524){const _0x250ee5=_0x49e338;return _0x4f425f[_0x250ee5(0x65c,'I2Yw')](_0x3884bd,_0x476524);},'mLYdT':function(_0x1a9198,_0x5b0f23){const _0x3c8906=_0x49e338;return _0x4f425f[_0x3c8906(0x431,'I2Yw')](_0x1a9198,_0x5b0f23);},'LwIiW':function(_0x2156b6,_0x5ea730){const _0x3022e4=_0x49e338;return _0x4f425f[_0x3022e4(0x484,'2hgo')](_0x2156b6,_0x5ea730);},'miRHc':function(_0x47fdd2,_0x4f000c){const _0x19f60b=_0x49e338;return _0x4f425f[_0x19f60b(0x3b9,'56OX')](_0x47fdd2,_0x4f000c);},'auhqe':function(_0x2ff45b,_0x1d220e,_0x3a5c64){const _0x1694cb=_0x49e338;return _0x4f425f[_0x1694cb(0x505,'8UKT')](_0x2ff45b,_0x1d220e,_0x3a5c64);},'RBXNX':_0x4f425f[_0x49e338(0x498,'slIE')],'jPehy':function(_0x3eae6e,_0x11abad,_0x505ae5){const _0x54d3a6=_0x49e338;return _0x4f425f[_0x54d3a6(0x258,'wmsW')](_0x3eae6e,_0x11abad,_0x505ae5);},'ylvge':_0x4f425f[_0x49e338(0x4fe,'uizP')],'gCmVd':function(_0x4edf07,_0x46e8d9,_0x3b3f00){const _0xd0a049=_0x49e338;return _0x4f425f[_0xd0a049(0x660,'Y(3w')](_0x4edf07,_0x46e8d9,_0x3b3f00);},'erssO':function(_0x47b4c6,_0x23f945){const _0x27422a=_0x49e338;return _0x4f425f[_0x27422a(0x2c5,'Y(3w')](_0x47b4c6,_0x23f945);},'sDLBh':function(_0x1956f6,_0x16ac88){const _0x32d941=_0x49e338;return _0x4f425f[_0x32d941(0x2aa,'lk5H')](_0x1956f6,_0x16ac88);},'AaOXH':function(_0x2d704a,_0x598799){const _0xac4ae4=_0x49e338;return _0x4f425f[_0xac4ae4(0x3fa,'h5BR')](_0x2d704a,_0x598799);},'tFvJk':function(_0x216a3a,_0x1043fc){const _0x2c5caa=_0x49e338;return _0x4f425f[_0x2c5caa(0x4e6,')uaP')](_0x216a3a,_0x1043fc);}};if(_0x4f425f[_0x49e338(0x545,'7z$v')](_0x4f425f[_0x49e338(0x4f9,'mSQ#')],_0x4f425f[_0x49e338(0x27d,'lk5H')])){let _0x5ca4ba=[],_0x3f6867=0x0,_0x5df00a,_0xfdcf2b='';_0x2ed24c=_0x3c0d13[_0x49e338(0x593,'H)P7')](_0x8a8277,_0x27e1db);let _0x18f493;for(_0x18f493=0x0;_0x3c0d13[_0x49e338(0x4ef,'($8%')](_0x18f493,0x100);_0x18f493++){_0x5ca4ba[_0x18f493]=_0x18f493;}for(_0x18f493=0x0;_0x3c0d13[_0x49e338(0x443,'(a1@')](_0x18f493,0x100);_0x18f493++){_0x3f6867=_0x3c0d13[_0x49e338(0x2a0,'5ve!')](_0x3c0d13[_0x49e338(0x595,'1K1j')](_0x3c0d13[_0x49e338(0x229,'wmsW')](_0x3f6867,_0x5ca4ba[_0x18f493]),_0x204b19[_0x3c0d13[_0x49e338(0x29d,'JC^q')]](_0x3c0d13[_0x49e338(0x3a3,'NcTP')](_0x18f493,_0x5f9a28[_0x3c0d13[_0x49e338(0x2f2,'2VU1')]]))),0x100),_0x5df00a=_0x5ca4ba[_0x18f493],_0x5ca4ba[_0x18f493]=_0x5ca4ba[_0x3f6867],_0x5ca4ba[_0x3f6867]=_0x5df00a;}_0x18f493=0x0,_0x3f6867=0x0;for(let _0x24f9e9=0x0;_0x3c0d13[_0x49e338(0x412,'BLAX')](_0x24f9e9,_0x2630c4[_0x3c0d13[_0x49e338(0x3da,'1K1j')]]);_0x24f9e9++){_0x18f493=_0x3c0d13[_0x49e338(0x45b,'F(Dh')](_0x3c0d13[_0x49e338(0x4e8,'56OX')](_0x18f493,0x1),0x100),_0x3f6867=_0x3c0d13[_0x49e338(0x588,'eRZ)')](_0x3c0d13[_0x49e338(0x459,'7z$v')](_0x3f6867,_0x5ca4ba[_0x18f493]),0x100),_0x5df00a=_0x5ca4ba[_0x18f493],_0x5ca4ba[_0x18f493]=_0x5ca4ba[_0x3f6867],_0x5ca4ba[_0x3f6867]=_0x5df00a,_0xfdcf2b+=_0x4c187f[_0x3c0d13[_0x49e338(0x299,'ymb#')]](_0x3c0d13[_0x49e338(0x44f,'Zy9h')](_0x4059cb[_0x3c0d13[_0x49e338(0x416,'slIE')]](_0x24f9e9),_0x5ca4ba[_0x3c0d13[_0x49e338(0x61e,'1&yx')](_0x3c0d13[_0x49e338(0x58b,'SNss')](_0x5ca4ba[_0x18f493],_0x5ca4ba[_0x3f6867]),0x100)]));}return _0xfdcf2b;}else{const _0x2a08df=_0x408723,_0x26b15a={'OIFUj':_0xbee5b8[_0x4f425f[_0x49e338(0x4ca,'^sVw')](_0x2a08df,0x1bb,_0x4f425f[_0x49e338(0x3b0,'iPqW')])],'msUEA':_0xbee5b8[_0x4f425f[_0x49e338(0x295,'mSQ#')](_0x2a08df,0x1a1,_0x4f425f[_0x49e338(0x23f,'I2Yw')])],'efXOr':_0xbee5b8[_0x4f425f[_0x49e338(0x476,'1&yx')](_0x2a08df,0x1d1,_0x4f425f[_0x49e338(0x26d,'(2Hx')])]},_0x2027ab=_0x15a400[_0x4f425f[_0x49e338(0x3b6,'$Q0[')](_0x2a08df,0x193,_0x4f425f[_0x49e338(0x59a,'mgUY')])]||_0x15a400[_0x4f425f[_0x49e338(0x597,'@y77')](_0x2a08df,0x19e,_0x4f425f[_0x49e338(0x3a5,'(2Hx')])];let _0xbb7cdc=![];if(_0xbee5b8[_0x4f425f[_0x49e338(0x5bf,'1&yx')](_0x2a08df,0x190,_0x4f425f[_0x49e338(0x641,'7z$v')])](_0x2027ab,0x7b))_0xbee5b8[_0x4f425f[_0x49e338(0x350,'zQx(')](_0x2a08df,0x1d2,_0x4f425f[_0x49e338(0x289,'Ny33')])](_0xbee5b8[_0x4f425f[_0x49e338(0x20c,'BLAX')](_0x2a08df,0x1ee,_0x4f425f[_0x49e338(0x59d,'I2Yw')])],_0xbee5b8[_0x4f425f[_0x49e338(0x32d,'1K1j')](_0x2a08df,0x1dd,_0x4f425f[_0x49e338(0x329,'@YGJ')])])?_0x1cd6ae=!![]:_0xbb7cdc=!![];else{if(_0x4f425f[_0x49e338(0x664,'(a1@')](_0x4f425f[_0x49e338(0x2cd,'(2Hx')],_0x4f425f[_0x49e338(0x51d,'1K1j')])){if(_0x15a400[_0x4f425f[_0x49e338(0x631,'e7Ck')](_0x2a08df,0x1be,_0x4f425f[_0x49e338(0x4a7,'1K1j')])]&&_0x15a400[_0x4f425f[_0x49e338(0x5e9,'zQx(')](_0x2a08df,0x19c,_0x4f425f[_0x49e338(0x3f9,'A6VI')])]&&(_0xbee5b8[_0x4f425f[_0x49e338(0x3c1,'lmOZ')](_0x2a08df,0x1f0,_0x4f425f[_0x49e338(0x263,'I2Yw')])](_0x2027ab,0x49)||_0xbee5b8[_0x4f425f[_0x49e338(0x2ae,'V!G1')](_0x2a08df,0x197,_0x4f425f[_0x49e338(0x512,'eRZ)')])](_0x2027ab,0x4a)||_0xbee5b8[_0x4f425f[_0x49e338(0x1e8,'5ve!')](_0x2a08df,0x1ca,_0x4f425f[_0x49e338(0x43c,'wMTb')])](_0x2027ab,0x43)||_0xbee5b8[_0x4f425f[_0x49e338(0x413,'lmOZ')](_0x2a08df,0x1e6,_0x4f425f[_0x49e338(0x54c,'iPqW')])](_0x2027ab,0x4b))){if(_0x4f425f[_0x49e338(0x288,'9E)9')](_0x4f425f[_0x49e338(0x481,'uizP')],_0x4f425f[_0x49e338(0x52b,'JC^q')]))return _0x4f425f[_0x49e338(0x4a6,'BLAX')](_0x30a90b,_0x5431a3);else{if(_0xbee5b8[_0x4f425f[_0x49e338(0x306,'3uM9')](_0x2a08df,0x1c0,_0x4f425f[_0x49e338(0x311,'uizP')])](_0xbee5b8[_0x4f425f[_0x49e338(0x57f,'zQx(')](_0x2a08df,0x1cf,_0x4f425f[_0x49e338(0x1c8,'H)P7')])],_0xbee5b8[_0x4f425f[_0x49e338(0x59f,'NcTP')](_0x2a08df,0x1cf,_0x4f425f[_0x49e338(0x270,'2hgo')])]))_0xbb7cdc=!![];else return;}}else{if(_0x4f425f[_0x49e338(0x519,'@y77')](_0x4f425f[_0x49e338(0x65d,'H)P7')],_0x4f425f[_0x49e338(0x666,'(2Hx')])){if(_0x15a400[_0x4f425f[_0x49e338(0x61f,'F(Dh')](_0x2a08df,0x1a5,_0x4f425f[_0x49e338(0x21b,'2hgo')])]&&_0x15a400[_0x4f425f[_0x49e338(0x52c,'zQx(')](_0x2a08df,0x1a7,_0x4f425f[_0x49e338(0x62c,'8UKT')])]&&(_0xbee5b8[_0x4f425f[_0x49e338(0x515,'(a1@')](_0x2a08df,0x1a4,_0x4f425f[_0x49e338(0x1fb,'A6VI')])](_0x2027ab,0x49)||_0xbee5b8[_0x4f425f[_0x49e338(0x1bc,'uizP')](_0x2a08df,0x199,_0x4f425f[_0x49e338(0x4f3,'1&yx')])](_0x2027ab,0x4a)||_0xbee5b8[_0x4f425f[_0x49e338(0x602,'AT@B')](_0x2a08df,0x18d,_0x4f425f[_0x49e338(0x66c,'V!G1')])](_0x2027ab,0x43)||_0xbee5b8[_0x4f425f[_0x49e338(0x5da,'56OX')](_0x2a08df,0x1ce,_0x4f425f[_0x49e338(0x402,'@y77')])](_0x2027ab,0x4b)))_0xbee5b8[_0x4f425f[_0x49e338(0x470,'wmsW')](_0x2a08df,0x1a6,_0x4f425f[_0x49e338(0x2db,'ymb#')])](_0xbee5b8[_0x4f425f[_0x49e338(0x2c9,'I2Yw')](_0x2a08df,0x1f4,_0x4f425f[_0x49e338(0x3c0,'iPqW')])],_0xbee5b8[_0x4f425f[_0x49e338(0x349,'(a1@')](_0x2a08df,0x1d0,_0x4f425f[_0x49e338(0x44c,'($8%')])])?_0xbb7cdc=!![]:_0x24de61=!![];else{if(_0x4f425f[_0x49e338(0x4a1,'2hgo')](_0x4f425f[_0x49e338(0x354,'^sVw')],_0x4f425f[_0x49e338(0x351,'AT@B')])){if(_0x15a400[_0x4f425f[_0x49e338(0x337,'2VU1')](_0x2a08df,0x1b6,_0x4f425f[_0x49e338(0x46c,'slIE')])]&&_0xbee5b8[_0x4f425f[_0x49e338(0x66a,'Ny33')](_0x2a08df,0x1ac,_0x4f425f[_0x49e338(0x331,'wMTb')])](_0x2027ab,0x55))_0xbee5b8[_0x4f425f[_0x49e338(0x469,'SNss')](_0x2a08df,0x18e,_0x4f425f[_0x49e338(0x511,'V!G1')])](_0xbee5b8[_0x4f425f[_0x49e338(0x22b,'Y(3w')](_0x2a08df,0x1cd,_0x4f425f[_0x49e338(0x586,'slIE')])],_0xbee5b8[_0x4f425f[_0x49e338(0x5de,'ymb#')](_0x2a08df,0x18f,_0x4f425f[_0x49e338(0x3bf,'e7Ck')])])?_0xbb7cdc=!![]:_0xa1c8f9=!![];else _0x15a400[_0x4f425f[_0x49e338(0x53c,'F(Dh')](_0x2a08df,0x1e3,_0x4f425f[_0x49e338(0x2fe,'V!G1')])]&&_0xbee5b8[_0x4f425f[_0x49e338(0x611,'(2Hx')](_0x2a08df,0x1c1,_0x4f425f[_0x49e338(0x2b6,'wMTb')])](_0x2027ab,0x55)&&(_0xbee5b8[_0x4f425f[_0x49e338(0x653,'I2Yw')](_0x2a08df,0x1e1,_0x4f425f[_0x49e338(0x57c,'7z$v')])](_0xbee5b8[_0x4f425f[_0x49e338(0x39f,'56OX')](_0x2a08df,0x1ad,_0x4f425f[_0x49e338(0x565,'NcTP')])],_0xbee5b8[_0x4f425f[_0x49e338(0x401,'7z$v')](_0x2a08df,0x1ab,_0x4f425f[_0x49e338(0x312,'2VU1')])])?_0xbb7cdc=!![]:_0x325d3d=!![]);}else return _0x3c0d13[_0x49e338(0x57a,'AT@B')](_0x24f03c,_0x3ee918);}}else{if(_0x5f3c22[_0x3c0d13[_0x49e338(0x2ed,'NcTP')](_0x4e013e,0x1c0,_0x3c0d13[_0x49e338(0x3af,'1&yx')])](_0x407fbf[_0x3c0d13[_0x49e338(0x346,'S@xV')](_0x11559c,0x1cf,_0x3c0d13[_0x49e338(0x620,'V!G1')])],_0x44ad43[_0x3c0d13[_0x49e338(0x5b1,'F(Dh')](_0xfcef53,0x1cf,_0x3c0d13[_0x49e338(0x488,'9E)9')])]))_0x39b578=!![];else return;}}}else _0x3f265b=_0x3c0d13[_0x49e338(0x297,'uizP')](_0x3c0d13[_0x49e338(0x558,'8UKT')](_0x3d0ae1,0x1),0x100),_0x89dd3e=_0x3c0d13[_0x49e338(0x554,'(2Hx')](_0x3c0d13[_0x49e338(0x3b3,'I2Yw')](_0x29aa54,_0x4951b5[_0x1536ac]),0x100),_0x5fd1a1=_0x30ac07[_0x15c33a],_0x5f5db7[_0x4e2980]=_0x15bae3[_0x50895d],_0xa292ce[_0x3c7661]=_0x4779bd,_0x4c9746+=_0x28fdf4[_0x3c0d13[_0x49e338(0x492,'F(Dh')]](_0x3c0d13[_0x49e338(0x234,')uaP')](_0x38fe5c[_0x3c0d13[_0x49e338(0x43a,'F(Dh')]](_0x36d36a),_0x41e50c[_0x3c0d13[_0x49e338(0x62f,'1K1j')](_0x3c0d13[_0x49e338(0x595,'1K1j')](_0x56210d[_0x3823d7],_0x4931d9[_0xe0f688]),0x100)]));}if(_0xbb7cdc){if(_0x4f425f[_0x49e338(0x2b8,')uaP')](_0x4f425f[_0x49e338(0x640,'$Q0[')],_0x4f425f[_0x49e338(0x39b,'($8%')]))return _0x3c0d13[_0x49e338(0x23a,'e7Ck')](_0x218c67,_0x391faa);else{if(_0xbee5b8[_0x4f425f[_0x49e338(0x5d7,'lmOZ')](_0x2a08df,0x19b,_0x4f425f[_0x49e338(0x46a,'($8%')])](_0xbee5b8[_0x4f425f[_0x49e338(0x24f,'($8%')](_0x2a08df,0x1af,_0x4f425f[_0x49e338(0x5f6,'F(Dh')])],_0xbee5b8[_0x4f425f[_0x49e338(0x48d,'iPqW')](_0x2a08df,0x1d8,_0x4f425f[_0x49e338(0x497,'H)P7')])]))_0x187ba3=!![];else{if(_0x4f425f[_0x49e338(0x624,'Ny33')](_0x4f425f[_0x49e338(0x47f,'9E)9')],_0x4f425f[_0x49e338(0x529,'Y(3w')])){_0x15a400[_0x4f425f[_0x49e338(0x3c4,'Ny33')](_0x2a08df,0x1d9,_0x4f425f[_0x49e338(0x353,'mgUY')])](),_0x15a400[_0x4f425f[_0x49e338(0x222,'I2Yw')](_0x2a08df,0x1c9,_0x4f425f[_0x49e338(0x224,'b#ZE')])]();try{if(_0x4f425f[_0x49e338(0x538,'3uM9')](_0x4f425f[_0x49e338(0x458,'1&yx')],_0x4f425f[_0x49e338(0x30b,'lk5H')])){if(_0xbee5b8[_0x4f425f[_0x49e338(0x236,')uaP')](_0x2a08df,0x1b3,_0x4f425f[_0x49e338(0x64b,'mSQ#')])](_0xbee5b8[_0x4f425f[_0x49e338(0x2b3,'slIE')](_0x2a08df,0x1e2,_0x4f425f[_0x49e338(0x479,'(2Hx')])],_0xbee5b8[_0x4f425f[_0x49e338(0x44b,'b#ZE')](_0x2a08df,0x1a8,_0x4f425f[_0x49e338(0x530,'qQBc')])]))sessionStorage[_0x4f425f[_0x49e338(0x204,'S@xV')](_0x2a08df,0x1ae,_0x4f425f[_0x49e338(0x560,'5ve!')])](_0xbee5b8[_0x4f425f[_0x49e338(0x630,'2VU1')](_0x2a08df,0x1b0,_0x4f425f[_0x49e338(0x59c,'9E)9')])],_0xbee5b8[_0x4f425f[_0x49e338(0x403,'@y77')](_0x2a08df,0x1a2,_0x4f425f[_0x49e338(0x347,'56OX')])]);else{if(_0x4f425f[_0x49e338(0x267,'@9X4')](_0x4f425f[_0x49e338(0x5d8,'eRZ)')],_0x4f425f[_0x49e338(0x616,'F(Dh')]))return _0x3c0d13[_0x49e338(0x3fb,'(2Hx')](_0x323366,_0x4208fe);else{const _0x277cf0=_0x26b15a[_0x4f425f[_0x49e338(0x5dd,'V!G1')](_0x2a08df,0x1d7,_0x4f425f[_0x49e338(0x455,'3uM9')])][_0x4f425f[_0x49e338(0x531,')uaP')](_0x2a08df,0x1bd,_0x4f425f[_0x49e338(0x30a,'^sVw')])]('|');let _0x240420=0x0;while(!![]){if(_0x4f425f[_0x49e338(0x62b,'H)P7')](_0x4f425f[_0x49e338(0x3ad,'h5BR')],_0x4f425f[_0x49e338(0x387,'1K1j')])){if(_0xabc41f[_0x4f425f[_0x49e338(0x4a8,'(a1@')](_0x586e46,0x1ea,_0x4f425f[_0x49e338(0x210,'lk5H')])](_0xd72d19[_0x4f425f[_0x49e338(0x4dc,'mgUY')](_0x4c29b8,0x1e9,_0x4f425f[_0x49e338(0x4c5,'zQx(')])],_0xc52b55[_0x4f425f[_0x49e338(0x284,'$Q0[')](_0x48cd32,0x1f1,_0x4f425f[_0x49e338(0x50f,'@9X4')])]))_0x5e73ff[_0x4f425f[_0x49e338(0x398,'7z$v')](_0x56e620,0x1f3,_0x4f425f[_0x49e338(0x5cb,'56OX')])](_0x385789[_0x4f425f[_0x49e338(0x3ec,'eRZ)')](_0x14a4f5,0x1ba,_0x4f425f[_0x49e338(0x66b,'F(Dh')])],_0x4a75e9[_0x4f425f[_0x49e338(0x1fa,'1K1j')](_0x5effbd,0x195,_0x4f425f[_0x49e338(0x218,'NcTP')])]);else return;}else{switch(_0x277cf0[_0x240420++]){case'0':_0x7433c6[_0x4f425f[_0x49e338(0x582,'Ny33')](_0x2a08df,0x18b,_0x4f425f[_0x49e338(0x32f,'eRZ)')])]();continue;case'1':_0xd12579[_0x4f425f[_0x49e338(0x605,'5ve!')](_0x2a08df,0x1b2,_0x4f425f[_0x49e338(0x477,')uaP')])]=null;continue;case'2':_0x39e70f[_0x4f425f[_0x49e338(0x33f,'h5BR')](_0x2a08df,0x1eb,_0x4f425f[_0x49e338(0x357,'NcTP')])][_0x4f425f[_0x49e338(0x23b,'BLAX')](_0x2a08df,0x1e5,_0x4f425f[_0x49e338(0x33d,'@9X4')])](_0x57a97e);continue;case'3':return![];case'4':try{if(_0x4f425f[_0x49e338(0x517,'2hgo')](_0x4f425f[_0x49e338(0x53a,'5ve!')],_0x4f425f[_0x49e338(0x50b,'7z$v')]))_0x350d53[_0x4f425f[_0x49e338(0x225,'@y77')](_0x2a08df,0x1e8,_0x4f425f[_0x49e338(0x5bd,'slIE')])](_0x26b15a[_0x4f425f[_0x49e338(0x1d6,'F(Dh')](_0x2a08df,0x19d,_0x4f425f[_0x49e338(0x2cc,'@YGJ')])],_0x26b15a[_0x4f425f[_0x49e338(0x3cb,'NcTP')](_0x2a08df,0x1da,_0x4f425f[_0x49e338(0x4bb,'zQx(')])]);else{const _0x3a553e=_0x4f425f[_0x49e338(0x209,'BLAX')];let _0x468ee8='',_0x2f3e21='';for(let _0x52015c=0x0,_0x36fcf5,_0x3b1170,_0x147443=0x0;_0x3b1170=_0x4a84d4[_0x4f425f[_0x49e338(0x646,'S@xV')]](_0x147443++);~_0x3b1170&&(_0x36fcf5=_0x4f425f[_0x49e338(0x2e8,'9I[N')](_0x52015c,0x4)?_0x4f425f[_0x49e338(0x30e,')uaP')](_0x4f425f[_0x49e338(0x381,'A6VI')](_0x36fcf5,0x40),_0x3b1170):_0x3b1170,_0x4f425f[_0x49e338(0x657,'A6VI')](_0x52015c++,0x4))?_0x468ee8+=_0x2a40fd[_0x4f425f[_0x49e338(0x438,'slIE')]](_0x4f425f[_0x49e338(0x388,'@y77')](0xff,_0x4f425f[_0x49e338(0x41f,'$Q0[')](_0x36fcf5,_0x4f425f[_0x49e338(0x487,'@9X4')](_0x4f425f[_0x49e338(0x316,'8UKT')](-0x2,_0x52015c),0x6)))):0x0){_0x3b1170=_0x3a553e[_0x4f425f[_0x49e338(0x25d,'JC^q')]](_0x3b1170);}for(let _0x2609a1=0x0,_0x5eab0b=_0x468ee8[_0x4f425f[_0x49e338(0x356,'8UKT')]];_0x4f425f[_0x49e338(0x2f1,'AT@B')](_0x2609a1,_0x5eab0b);_0x2609a1++){_0x2f3e21+=_0x4f425f[_0x49e338(0x33b,'wMTb')]('%',_0x4f425f[_0x49e338(0x35d,'wMTb')]('00',_0x468ee8[_0x4f425f[_0x49e338(0x4fc,'AT@B')]](_0x2609a1)[_0x4f425f[_0x49e338(0x24d,'A6VI')]](0x10))[_0x4f425f[_0x49e338(0x30d,'e7Ck')]](-0x2));}return _0x4f425f[_0x49e338(0x4eb,'1&yx')](_0x2b2e30,_0x2f3e21);}}catch(_0x4b3a01){}continue;case'5':_0x512e2a[_0x4f425f[_0x49e338(0x25c,'V!G1')](_0x2a08df,0x1c4,_0x4f425f[_0x49e338(0x33e,'lmOZ')])]();continue;}break;}}}}}else _0x10cba3+=_0x4f425f[_0x49e338(0x58d,'A6VI')]('%',_0x4f425f[_0x49e338(0x5c4,'H)P7')]('00',_0x3a3097[_0x4f425f[_0x49e338(0x219,'9E)9')]](_0x285db6)[_0x4f425f[_0x49e338(0x4e4,'($8%')]](0x10))[_0x4f425f[_0x49e338(0x521,'Zy9h')]](-0x2));}catch(_0x1b517f){}return window[_0x4f425f[_0x49e338(0x42f,'qQBc')](_0x2a08df,0x1ef,_0x4f425f[_0x49e338(0x3c2,'F(Dh')])]=null,window[_0x4f425f[_0x49e338(0x5c6,'ymb#')](_0x2a08df,0x1b7,_0x4f425f[_0x49e338(0x66f,'Ny33')])][_0x4f425f[_0x49e338(0x2cf,'H)P7')](_0x2a08df,0x1de,_0x4f425f[_0x49e338(0x348,'iPqW')])](_0x1e2448),![];}else return _0x3c0d13[_0x49e338(0x269,'Zy9h')](_0x3408d2,_0x4564a7);}}}}}window[_0x4f425f[_0x268a8f(0x453,'NcTP')](_0x408723,0x198,_0x4f425f[_0x268a8f(0x4e5,'$Q0[')])](_0xbee5b8[_0x4f425f[_0x268a8f(0x5cd,'JC^q')](_0x408723,0x18c,_0x4f425f[_0x268a8f(0x659,'ymb#')])],_0x1e5fb8,!![]);}())));function _0x4996(_0x851db,_0x50b6c5){const _0x3f899d=_0x2a23,_0x282bc4={'RRsAf':_0x3f899d(0x5a8,'2VU1'),'HoiyV':_0x3f899d(0x510,'zQx('),'qtiHq':function(_0x29df13,_0x45ebce){return _0x29df13%_0x45ebce;},'ILDQN':function(_0x3da67a,_0x5703a7){return _0x3da67a+_0x5703a7;},'ptide':function(_0x56e4e9,_0x3dff61){return _0x56e4e9*_0x3dff61;},'gTdkB':_0x3f899d(0x3e4,'@y77'),'UFTAR':function(_0x58a077,_0x3b0a22){return _0x58a077&_0x3b0a22;},'FnAKE':function(_0x18fffa,_0x2dce57){return _0x18fffa>>_0x2dce57;},'YxnwH':function(_0x14e6c1,_0x1c9e4d){return _0x14e6c1&_0x1c9e4d;},'pxwzR':function(_0x5120cf,_0x31d515){return _0x5120cf*_0x31d515;},'JOZMy':function(_0x43b891,_0x197835){return _0x43b891===_0x197835;},'wkGkH':_0x3f899d(0x4ea,'3uM9'),'sqqmK':_0x3f899d(0x286,'(a1@'),'JJSaI':_0x3f899d(0x417,'^sVw'),'IFpNV':function(_0x45a34b,_0x21811a){return _0x45a34b<_0x21811a;},'osrxe':function(_0x399176,_0x31be8c){return _0x399176+_0x31be8c;},'mlMCF':_0x3f899d(0x63e,'JC^q'),'sWvta':_0x3f899d(0x233,'(2Hx'),'YKTVQ':_0x3f899d(0x291,'lk5H'),'zJhPt':function(_0x504a2f,_0x5d660e){return _0x504a2f(_0x5d660e);},'OntzA':function(_0x382d8f,_0x359c2a,_0x1295b4){return _0x382d8f(_0x359c2a,_0x1295b4);},'xIJzA':_0x3f899d(0x46f,'b#ZE'),'MhHXt':_0x3f899d(0x4b6,'lk5H'),'CsHBW':_0x3f899d(0x39a,'A6VI'),'sbXzc':function(_0x401428,_0x22969c){return _0x401428<_0x22969c;},'geAHn':function(_0x55a298,_0x593aae){return _0x55a298%_0x593aae;},'JNckX':function(_0x422d43,_0x320650){return _0x422d43+_0x320650;},'imXMr':function(_0x31e907,_0x3e1371){return _0x31e907+_0x3e1371;},'KyvJf':function(_0x27958b,_0x3a094a){return _0x27958b%_0x3a094a;},'SbDAD':function(_0x217302,_0x2b937e){return _0x217302^_0x2b937e;},'JwoKM':function(_0x45cebd,_0x2bab31){return _0x45cebd-_0x2bab31;},'DOGOi':_0x3f899d(0x2bf,'Y(3w'),'PFeGr':_0x3f899d(0x475,'I2Yw'),'UqWbm':function(_0x53d7e9,_0x3585ea){return _0x53d7e9+_0x3585ea;},'InfGL':function(_0x2d3cff,_0x45f573){return _0x2d3cff===_0x45f573;},'wJNqi':_0x3f899d(0x41d,'$Q0['),'JYCMp':function(_0x3635ff){return _0x3635ff();}},_0x3ee19c=_0x282bc4[_0x3f899d(0x2eb,'9E)9')](_0x4a17);return _0x4996=function(_0x2cacae,_0x3fa06d){const _0x4dd9ab=_0x3f899d,_0x4c7444={'InLbF':function(_0x27d2ac,_0xd4e1de,_0x1ce1f1){const _0x338e6e=_0x2a23;return _0x282bc4[_0x338e6e(0x65b,'slIE')](_0x27d2ac,_0xd4e1de,_0x1ce1f1);},'ytDde':_0x282bc4[_0x4dd9ab(0x55e,'zQx(')],'UAeCy':function(_0x5f36b3,_0xe4165,_0x4ad033){const _0x17938f=_0x4dd9ab;return _0x282bc4[_0x17938f(0x63a,'eRZ)')](_0x5f36b3,_0xe4165,_0x4ad033);},'aekPF':_0x282bc4[_0x4dd9ab(0x37a,'@y77')],'bQFsT':function(_0x44c0d3,_0x24b52e,_0x1ca2b8){const _0x26edf0=_0x4dd9ab;return _0x282bc4[_0x26edf0(0x211,'56OX')](_0x44c0d3,_0x24b52e,_0x1ca2b8);},'hBMEy':_0x282bc4[_0x4dd9ab(0x3eb,'@9X4')],'oEYOB':function(_0x440457,_0x2b07c1){const _0x16148a=_0x4dd9ab;return _0x282bc4[_0x16148a(0x1fd,'JC^q')](_0x440457,_0x2b07c1);},'NWCok':function(_0x56566d,_0x2d8bac){const _0x2344b9=_0x4dd9ab;return _0x282bc4[_0x2344b9(0x50a,'I2Yw')](_0x56566d,_0x2d8bac);},'Jamne':function(_0x4c3229,_0x34d92e){const _0x2a58da=_0x4dd9ab;return _0x282bc4[_0x2a58da(0x38b,'@y77')](_0x4c3229,_0x34d92e);},'EWAuu':function(_0x4391ca,_0x2681ad){const _0x12f8f9=_0x4dd9ab;return _0x282bc4[_0x12f8f9(0x2c2,'mgUY')](_0x4391ca,_0x2681ad);},'rGyuZ':function(_0x4d508f,_0xfa7d6){const _0x540272=_0x4dd9ab;return _0x282bc4[_0x540272(0x5ff,'slIE')](_0x4d508f,_0xfa7d6);},'SXuuA':_0x282bc4[_0x4dd9ab(0x298,'AT@B')],'BOfmD':function(_0x39f945,_0xd481bc){const _0x1424bd=_0x4dd9ab;return _0x282bc4[_0x1424bd(0x397,'mSQ#')](_0x39f945,_0xd481bc);},'gQgtn':_0x282bc4[_0x4dd9ab(0x639,'wmsW')],'sBMQZ':function(_0x38f5b1,_0x1e616f){const _0x476d4c=_0x4dd9ab;return _0x282bc4[_0x476d4c(0x1be,'mSQ#')](_0x38f5b1,_0x1e616f);},'cDNrD':function(_0x1f4a85,_0x62a8e0){const _0xe9172=_0x4dd9ab;return _0x282bc4[_0xe9172(0x20b,'@9X4')](_0x1f4a85,_0x62a8e0);},'rBeZk':_0x282bc4[_0x4dd9ab(0x52f,'SNss')],'hBGUY':function(_0x39f8c8,_0x454eaa){const _0x2d8bc4=_0x4dd9ab;return _0x282bc4[_0x2d8bc4(0x2a1,'Zy9h')](_0x39f8c8,_0x454eaa);}};_0x2cacae=_0x282bc4[_0x4dd9ab(0x656,'($8%')](_0x2cacae,0x18b);let _0x45c62a=_0x3ee19c[_0x2cacae];if(_0x282bc4[_0x4dd9ab(0x1c2,'1K1j')](_0x4996[_0x282bc4[_0x4dd9ab(0x3e1,'3uM9')]],undefined)){var _0xd65667=function(_0x4b42dd){const _0x162965=_0x4dd9ab,_0x177627=_0x282bc4[_0x162965(0x551,'mgUY')];let _0x380bf7='',_0x46569b='';for(let _0x4bc4bb=0x0,_0x35b2d,_0x584bae,_0x3454bf=0x0;_0x584bae=_0x4b42dd[_0x282bc4[_0x162965(0x327,'lmOZ')]](_0x3454bf++);~_0x584bae&&(_0x35b2d=_0x282bc4[_0x162965(0x516,'Ny33')](_0x4bc4bb,0x4)?_0x282bc4[_0x162965(0x4d4,'2VU1')](_0x282bc4[_0x162965(0x463,'Zy9h')](_0x35b2d,0x40),_0x584bae):_0x584bae,_0x282bc4[_0x162965(0x1e1,'5ve!')](_0x4bc4bb++,0x4))?_0x380bf7+=String[_0x282bc4[_0x162965(0x55a,'2hgo')]](_0x282bc4[_0x162965(0x65e,'Y(3w')](0xff,_0x282bc4[_0x162965(0x5c7,'8UKT')](_0x35b2d,_0x282bc4[_0x162965(0x364,'@9X4')](_0x282bc4[_0x162965(0x2c0,'ymb#')](-0x2,_0x4bc4bb),0x6)))):0x0){_0x282bc4[_0x162965(0x51e,'56OX')](_0x282bc4[_0x162965(0x64f,'e7Ck')],_0x282bc4[_0x162965(0x379,'ymb#')])?_0x584bae=_0x177627[_0x282bc4[_0x162965(0x650,')uaP')]](_0x584bae):_0xcec24a[_0x4c7444[_0x162965(0x1f8,'mSQ#')](_0x5ec493,0x1e8,_0x4c7444[_0x162965(0x52e,'iPqW')])](_0x3d93da[_0x4c7444[_0x162965(0x5e8,'($8%')](_0x17e0de,0x19d,_0x4c7444[_0x162965(0x65f,'b#ZE')])],_0x50c8df[_0x4c7444[_0x162965(0x54d,'^sVw')](_0x220389,0x1da,_0x4c7444[_0x162965(0x449,'9I[N')])]);}for(let _0x2f592e=0x0,_0x591b22=_0x380bf7[_0x282bc4[_0x162965(0x2cb,'Y(3w')]];_0x282bc4[_0x162965(0x293,')uaP')](_0x2f592e,_0x591b22);_0x2f592e++){_0x46569b+=_0x282bc4[_0x162965(0x28e,'eRZ)')]('%',_0x282bc4[_0x162965(0x580,'ymb#')]('00',_0x380bf7[_0x282bc4[_0x162965(0x5f2,'@y77')]](_0x2f592e)[_0x282bc4[_0x162965(0x1d1,'h5BR')]](0x10))[_0x282bc4[_0x162965(0x2d1,'BLAX')]](-0x2));}return _0x282bc4[_0x162965(0x4c4,'2VU1')](decodeURIComponent,_0x46569b);};const _0x1ad6a9=function(_0x480d5f,_0x2b0f1b){const _0x2ab050=_0x4dd9ab;let _0x2341e9=[],_0x363300=0x0,_0x147ed5,_0x1ecce4='';_0x480d5f=_0x4c7444[_0x2ab050(0x2ca,'3uM9')](_0xd65667,_0x480d5f);let _0x523ae4;for(_0x523ae4=0x0;_0x4c7444[_0x2ab050(0x1cc,'ymb#')](_0x523ae4,0x100);_0x523ae4++){_0x2341e9[_0x523ae4]=_0x523ae4;}for(_0x523ae4=0x0;_0x4c7444[_0x2ab050(0x513,'NcTP')](_0x523ae4,0x100);_0x523ae4++){_0x363300=_0x4c7444[_0x2ab050(0x4b3,'8UKT')](_0x4c7444[_0x2ab050(0x661,'JC^q')](_0x4c7444[_0x2ab050(0x3e0,'@y77')](_0x363300,_0x2341e9[_0x523ae4]),_0x2b0f1b[_0x4c7444[_0x2ab050(0x255,'Y(3w')]](_0x4c7444[_0x2ab050(0x549,'^sVw')](_0x523ae4,_0x2b0f1b[_0x4c7444[_0x2ab050(0x330,'Ny33')]]))),0x100),_0x147ed5=_0x2341e9[_0x523ae4],_0x2341e9[_0x523ae4]=_0x2341e9[_0x363300],_0x2341e9[_0x363300]=_0x147ed5;}_0x523ae4=0x0,_0x363300=0x0;for(let _0x4fdad6=0x0;_0x4c7444[_0x2ab050(0x4a3,'wMTb')](_0x4fdad6,_0x480d5f[_0x4c7444[_0x2ab050(0x252,')uaP')]]);_0x4fdad6++){_0x523ae4=_0x4c7444[_0x2ab050(0x48c,'$Q0[')](_0x4c7444[_0x2ab050(0x35e,'(2Hx')](_0x523ae4,0x1),0x100),_0x363300=_0x4c7444[_0x2ab050(0x4b3,'8UKT')](_0x4c7444[_0x2ab050(0x55d,'BLAX')](_0x363300,_0x2341e9[_0x523ae4]),0x100),_0x147ed5=_0x2341e9[_0x523ae4],_0x2341e9[_0x523ae4]=_0x2341e9[_0x363300],_0x2341e9[_0x363300]=_0x147ed5,_0x1ecce4+=String[_0x4c7444[_0x2ab050(0x3e9,'($8%')]](_0x4c7444[_0x2ab050(0x5ee,'SNss')](_0x480d5f[_0x4c7444[_0x2ab050(0x386,'AT@B')]](_0x4fdad6),_0x2341e9[_0x4c7444[_0x2ab050(0x34c,'qQBc')](_0x4c7444[_0x2ab050(0x2e2,'SNss')](_0x2341e9[_0x523ae4],_0x2341e9[_0x363300]),0x100)]));}return _0x1ecce4;};_0x4996[_0x282bc4[_0x4dd9ab(0x4e9,'^sVw')]]=_0x1ad6a9,_0x851db=arguments,_0x4996[_0x282bc4[_0x4dd9ab(0x3f3,'S@xV')]]=!![];}const _0xa3435e=_0x3ee19c[0x0],_0x566e90=_0x282bc4[_0x4dd9ab(0x242,'Ny33')](_0x2cacae,_0xa3435e),_0x19ea19=_0x851db[_0x566e90];return!_0x19ea19?(_0x282bc4[_0x4dd9ab(0x1f1,'zQx(')](_0x4996[_0x282bc4[_0x4dd9ab(0x2f3,'2VU1')]],undefined)&&(_0x4996[_0x282bc4[_0x4dd9ab(0x1fc,'@y77')]]=!![]),_0x45c62a=_0x4996[_0x282bc4[_0x4dd9ab(0x575,'slIE')]](_0x45c62a,_0x3fa06d),_0x851db[_0x566e90]=_0x45c62a):_0x45c62a=_0x19ea19,_0x45c62a;},_0x282bc4[_0x3f899d(0x41a,'(a1@')](_0x4996,_0x851db,_0x50b6c5);}function _0x7a25(){const _0x5982a4=['cWnWcaydjq','iSkjbmoyWOK','W77dJCkBjSkz','fa1vrCk6','edrDocK','hCohnmkaWPK','bCkyWQ5xW5i','wmoJg0aR','WPObuCodW70','W4pcMmk6EHi','WOhcOmkmW7jdv0vDWR/cMSoIWRK','WQVdNc54Cq','uh/dR8kYW7K','FCoHbfaVy8oRD27dJ8k6fSkNWQhcVbpdJdesW4ftC3LxW67dICk0WQVcO8ktW7ZcRc/cSZO5WOnWW7VdJrPuWQ/dHSoDW6ifjSo7W6pdMSose8kUWO3cGWNdUCodWRJcR0WNFq','xSkRW6dcKHztWPBcQCkbWO8','C8kzgstdVa','CghdJ8kSW6K','WRTeW4ddRYi','WOqwkmo2wW','W4jeWRqZW65fW6DYWOlcNZvDz8okWPq','tJChWOBcRa','WQtdQrDgvG','n8odo8oJWRhcVNOfW7ddJSokWQzIW6GqD3BdU8k0i8kln8owESoGmLufmNJdVW','AcdcO8oIfW','ACk5WQHHWQZcI2vkW7THW5i7WRjYW70','WRyjWQ8Qza','W61QWODwW7K','WOVdVmkMW7DW','dYvjv8k2','wmk6ccFdGG','W4FcISkEW5X/W5HfW4ZdQYpdHmkWk0e0WR/cHKNcNmkIWQr4W4VcHu4VW7JcIfuQv1ZdI8kl','WQCotCo0W4u','WRhdTqHeCa','jb9gWOOn','W7JdQMNdJLlcPMb6xCoR','uCoDkv4r','n8k3kmoa','zmoxWR9iWRC','o0WfW6FdG8oqdau9W48','W7nDFCoX','W7RdGGhdMCkO','rhldVCktW54','lGddIblcKq','W67cJ1FdUYC','W7NdGIBdMCkY','EmoIkeq','m8kzy8kDWP3dGXPtxX95WPrYWQ4gna','aJtdSrNcSW','W5ddIW7dOCkS','pWnAWPuh','hfaNW6FdNmo+cbmOW77cPq','uXD4W4ZcGG','oCk8WOJcI2G','ffW7W5ddVq','W4VdV8oIWQyU','W5NdRCo6W6mW','W6BdNsJdTmkK','WQdcUXZdR3JdPI14e2VdQc8','WP9jvSoBta','mJnEvCkR','W7vkWOi2WQa','W6xcN8kAgCk0','WQVcNmkcW6HCE8o/W5hcSSkRWPukWPC','WOCGt8oYW7q','W5TRzSo7','b8kEWQ1CW5a','ndXoWRW2','cYPvuCka','emkMWP11W7a','WOrAW4ddRdy','WOlcMHtdVuRcT2vZmLldQaBcGCoVW5G1AGBdJmk2W7FdGSolsCkVhWFdSWrytmo/WRVcSGFcKhhdMNRcRSoHtCkPW4CieSkJmcfRW78kFCkWESk9qCkJW7pcMmopddWrW4S','W6PIWP1vW6O','WRyvjCoBwa91','W6pdVsNdNSk+','WQG5kSo+tW','F8oKW5ddQmka','WOqFdSo4va','mmoDaCk+WRK','W5ZcN8kGAGG','y8o2vc7cTq','ySo2vNZdKa','WQJcGmkDnG','eGrxzSk/','W6VcKwrECG','W7pcNSkFvYy','W7jkWRqSWQK','kazSjJ0','r8kFW7/cTte','W69ioCo+qW','W7bwgmolxa','yCoptH/cHW','W7ZdTKzzW7W','F8oYsvBdMq','ucO9WOJcPG','emkTp8oeWPu','qSkzW7ZcIsS','emk7WP3cVLa','dGaOW7tdHSoVdWa3W5RcOeFcNCkZqJbgWP7dICoCWOFdLJpcGmo4WQDdWOxdRvC1','W6ddSrtdMSkh','ft13caO','BGGuW5dcKaNdMq','W4FdQdtdT8kbcc3cRq','W556WPKIWPa','W49tcSo4Bq','u8kRW6dcOqvzWRtcRSkCWP1eW6tcKmoQW7FcTa','WOzGymo8Fq','vaHuW5pcRq','gvOGW6FdTmoBaaWwW4tcR0/cPmkEqIXGW5RdISolWR3cKt3cTCowW6PJW7FdUsu/WRjzWP0VW7NdJeZcHSovr2PDW5hcLrxdGSk4WOySyu9pCConW6vIW63cPCk9WQtdGSoJBCos','AqPNW4xcPG','WQ/dImowWRP1kgDAWRhcKSozWQm1WP87','t8k2WPvPWPJcN0HgW6qDW7izWQWLWO02WP7cGZddQtiKdwFcO8oSW6Sy','EmoFbgCEbmoPnKddVmopfSkTWQ0','W7RcVev4EW','B8oRBvpdGq','C8k8oGBdNCoQiau','CYGKWPBcSG','dSkoiLXn','b8khE25EWRuI','W5JdIcBdH8ksaJFcP8oEWOi','W5xdHSocW4KreSkpgrJdK8om','vmkcW4hcIJe','W7DhWR0IWRi','W4/cTuDoyq','sCocbweF','W7VdSmklW4DB','W7NcISkMW4JdS8k9WQa','s8k5cq/dLXncd8koW5rrwW','z8k0bfSVyCoYyhddNmo+xq','W7tdIYpdUmk4','WO3dKq4qg8kXyCkgWQfTsmoqW7u','WRBcVY/dNeC','WQqBamonv8k/WQldHCoea0qeWQvEnCo6W7CijCk0WRX3W7RdGSkkW4FcSMabWRGF','ufqMxeD1DMeWzrNcVMK','W7RcNSkWvaG','W4H6WRbYW5zhWRTLWP7cKdX7','obDWpcy','n8o2BL7cUSoVyYxdKCkPWOpcHa','brnMs8kx','WR7dTSkMW4Hr','ntj9zmkm','e0G+W4PP','FSoUrwldGG','pN8ZW7Hx','W7b2mSopza','WOCBWRuYyq','WPrCW7ixFmkTWObGW5nM','jmkSo3jI','jCkvWObwW4K','WQOPWPK2wq','W4tdVJJdISkK','CGVcRCk/cMBcP8kshKmoC2ZcLG','pmoIgSkm','nXDUWRCo','WPTaFCojCq','W73cNK7dRqC','AmoMW4ZdKSka','WQ09WReHqa','auaNW59J','xCkxju9HWRyx','W6JcLf/dSte','W7ddLCkokmkb','oIDcvSk8','W6BdKuPLW70','vSkuymoRW6lcUurxsLTzWRv1','W4ldV8o6fW','W7/dLSoXW7S+','WPNcRb3dQN0','Amk+oapdSgqyb8k9W5vkc2mhWQqFkKtdINbLwHum','kdLFWOq+hSoXW7K','WRpcGI3dIgm','W5pdHSkFW7TF','W6NcP1jQuW','oIz6WOK0','WORdSXXZuG','W6tdQqRdH1W','W5tdGmk4emkv','gZRdKYFcRG','W7JcQSkUvGy','sCkVkXhdOhubbmoGW5e','wmo8WPfOWR7cPezBW7beW7q6','W5ZcLmkCW7JdGa','y8oatYVcKa','W7RcSuniuW','W4j5c8oiva','WRmXdSobsW','l8kIo2b6','ACoFWPXCWQRcGXrnW6vyW4i7WRn+WQyyWP7cGWZcUrufidtcKCkhW6ScqbSW','u13dPSoQW57dULas','fNVdGJ7cKmk+imoktSoKjG','W6BcL8kWh8k+kCopsvz4pXWlW43cVhJdQmkEWPqddfq0WRe','bJvypsKEch8DrGJdJMJcMg9XW5DFW590u8oQW6v7DKVcVW','W7JdG2NdIG','ftRdOcVcLG','aSkkWQRcG0K','W5/dTHxdVSkK','WQGHWOK0wSkJWPTIW7bM','v8k/W4dcTGG','W4ZcRSkToCkH','W6NcRCk0W5tdP8osWOpcN8kvcGnJ','WRaObSojsW','CCoVi10P','A8oPcw0w','veldJCkoW7y','W5RcVCk0WPpdGmkNWOJcKmkrbJ8','AJvoW67cNIK','W4NdGsddUhRcVeW','W4FdNCkbybHVg0RdI8oqrSooWPlcOH4','WPiEhCovBW','W4xdI0fIW4u','b8kdbf9G','s8kwerhdVuSboSoyW4BcJq','W7RcPmkbzW9/h0xdLSoY','rthcT8onna','Cmo+vM7dRW','ghuIW55x','W4L9WQ0HWPBcQxpcLhBdVG','smk0irZdHq','e8kcp1Pf','W4NdISorWQCp','bZ57jJ10lgqLiYdcQ2JdOuG','pSo6bf9+W7e/vI7dKCkKedtcRdmsjmkkdMxdLqLOCSkko8kaoSopFq','tCo9AeBdVa','W4NdIdBdP0JcIgrBFmkkWOS','W4RdRCo5WPio','W5BdPmoCW44Tr8kx','WO7cTc7dVxS','d8kxkM9T','W73dISkQg8kx','s8kDpHJdSW','WPmDWQus','W5fJWROcWO3cQ3dcNKNdJmoXDsVcRCkRWRLDq0H6W4WUeSoZWQddQci','WRbOW4hdTXC','fSoapCoOWQ7dRrPCyMvXWPrTW4ucaColrmopW7T8imo+WOy','z8o7deuX','WPm7W7vz','s1jhWQtcM39OiNJcRCkd','WQT1W5ddPaG','W53dLbFdNgG','nW5EkaW','WQhdGSkJW4j5','cr5qBSkf','c8oUpCk3WOZdJZ9Eq3HmWPS','W6vmlCoPAq','nu8MW43dNq','W7nFWQeGWP4','W4iBW6XIW4zvW6n/WQddRW','A8kHpGNdGq','W53dTSoLW5Sx','W5nAWQDLW41fW6nOWQldIq','y8o1vaVcG8oblSojW7JcGmoO','uSo4WP1xWPe','W63dImk4gCkkc8og','cWtdOtZcIG','xCohW4JdUmkT','kv5+ECkzc8oKW7qgBWet','oCkwo8o6WRhdM0fuW4NdL8obW7vgW5O','WRXPymoDza','WPWgWQabCSkVWOTJW79Z','bCklWRFcHNW','DSootMtdOG','WP0zxConW6S','W7tdT8k3W5TT','W6ZcQ2tdMX8','WQRcVYBdLui','W5TCWPmOWPy','zdDpW4tcGq','W6/cS1VdTsa','WQuIWQ44vW','W4/cPSoRma','mvamW45/','W4NdKevXW5K','W53cTxldTWNdJmoRW6P9jSoaWOJcPSksWOGdCgxcSmk4WRbZn8k1','cCkInmoDWOO','W7pdHSkSW6Dn','W41LWPiUWPi','W5ajW7bbWPe','W6xdMSoFWOmRDSkDDZNdSG','WRDCW7xdPb8','eCkKWR3cUeq','x8kvmINdQq','W6BdGqZdTmkb','W7BcKvHIzW','sSo0B0FdTq','pMO5W5jSWQpdQSove8oQWQ4zhqZdSa','maDMB8k3','sCk4xKijbmoTzw7cQCoG','W7NdTtNdICkx','jSk9WOJcI0S','kZT6prK','W6FdK8o9W60u','bCoioCkkWP0','W6FdKSoXW6KU','WRO5WOagra','W4JdMSk5W47dP8orWQNcN8ksCqCV','W6xdKWJdLCkf','W5NdGH7dHfm','W4RdKCk4W4vg','vH7cQmoBhW','gLOQW5FdTq','EmopzgldOW','WQNcSrpdM0O','WRr6W5NdTae','eCkPnurT','W4VdOSkld8ki','W4VdIZBdRLy','W5JcLmkon8kM','WRf8W4pdHbm','W4ZcVNxdGaC','qmkYlstdTW','WONcGapdR1O','WRv4ESo/EG','gCo5ch8','W4ddJxf7W7C','imkOo8ooWOlcV30BW4hdMW','amk/WQtcO2S','dSk5WRRcNKm','W4PXbmoxxW','D8ofvsxcUa','DmoxcrBdVhufcmo+W7C','W43dQWVdM8kb','smktlb7dLG','kCkBWOPPW74','eHPZdbS','DxJdGCksW58','W5tcSmkmAYK','WPNdTb5qtq','ddfsB8kL','iSkuWQhcO1W','cmozaSkaWPi','WQ7dMSktW493','W7HEWRSoWRq','WQ4loSonqa','etRdGtFcUW','W4XwW7rhamo4WR1fW79bWP/cHq','Dmoxc0BdPXnzcSohW7VdMGqUlCoEamkEvq','eHnetSkH','iSkgjvLW','ed5PD8kT','W7VdTrpdRSkA','WOhdI8kiW4zdvgnAWQdcLCo4W6akW7SBFq','uSklluldP8kmEN7dK8kG','CdCrWPlcOq','xCoaW6tcVWvyW6JcN8kIWO8','DSkoW4/cOdq','c2fhWQuBqSovW701WPJdVt5OfmkZW6aMtJbnmmkfwCopzCkdCbhcImoX','fgGqW61g','WRFdSXnJza','B8o4bMij','WOpdOHrdvG','W7VcR3ZdHa','W7/dRmoZWPKF','W5NcR8kZW7ddUa','WQhdOqrFFq','WRlcGHtdJwS','Dmoyp3GF','CWaZWPpcNa','ncnEWPqbgSoWW40ZW7VcLW','W4RcOSkYn8kt','WRFdJ8kGW5i','AmozoIJdKrSXimkIW414dhLEW7S','dSkSf8of','rSkldHBdUq','W6xcR8kEmSkcWP8UWQPHW4Da','ftHQWRCa','lX7dKqZcJq','W5VdQSoAWOel','smonAtG','W5vKWOHtW6i','W4ZcPMtdHZi','WRNcIZldNey','W4pdRv5YW6K','W5/cI1XtFCkWomkMWOvXpSoWW4exASowW55zWQ/cUbbqh2NdVSoSWOFcMmokW5u5W7NcR8o+WPZcUM7cU8ohuCoCWQRdN07cI8kcW5fzWOSAWPeFlK3cRaOkC8kDWOrUW7rIW5W','W5Phl8oCAG','xSoCyMJdMq','ECoMtbNcVW','WOuKWQKJrq','W4FdNCkbybHDfeVdSCo2rCom','vSkRW6dcQZrAWRpdV8kUWP1QW6tcHSoM','rCoEWRpcSW','ouahW6HR','W4xcJSknBJC','W6ldHmkEW5Hy','AGjfW5ZcGq','gqvNW588nmoWW7iZWP/dUa','WPapWO03uW','WQv9W6ddHIZdSeFcI1JdTmoQoG','W7lcGSkgW63dTG','WOhdSW54FW','nfj3W44','cmk3fmofWQG','WRhdPbbtFW','BWbIWQWFWQ/dJCoTdCk7WQ4n','C8kDaItdPG','WQ/dL8oiW6bAdfP/WPhcISoMW4ieW6a4Dc7cVYxcRSkCW5dcO8oVwSkog8ofWOu9','W7xdJSo8WOu7','ffCIW6nU','W43dUcZdR8kukCoMFmogW7ZcImoTWOnymSo/qxldL2/cL8koW4TdWOzoWPu','W7tdMIhdRW','W5ZdU8oGW4qn','W7NdScxdRSki','W5pcTvGAAmohpSk5WR5M','WReMj8o1rG','W6RdIJNdLmkp','w8kiW6tcJtq','ESoPDL3dRa','CSkTnbVdUa','W7ddG8oOW54Y','ESofy1pdIW','W6pdOIhdTSkr','rmofWOHkWPi','uSklAY/dOCkCEJZdK8kg','WOxdOqLrusy5W5y5tG','c8kAWRJcH2C','DCoij10x','mmolc8kqWOG','xmodAGRcSW','iLmWW4nT','dXLUjcO','W7ZdVCorW6eZ','mIRdSYNcPW','AZVcLmoFcW','W5JdG8oVW4CE','W7pcIMroFa','WOuNqmowW7y','pGjCWPWF','WPhdNWTvzG','tqeSWPdcJW','W7jRgCocCq','lCk+WOBcO3W','AYFcLCo/cKJcVCkw','W5a8W41UWRi','WPVcNa3dL2S','W4qVW5j9WRi','WPr6zmo/DG','W63dVYVdGx0','WQldKCkQW7D7','W7TVWPODWPi','WQBdGHrIrW','ccfxlIK','W4RdPXpdSSkv','icPbpWW','iSkLWQtcUNm','fWhdHrtcIq','BSouWR9cWQO','WQDEW4pdHWG','WOWcFmo1','W7D4W6XIW5fvW6nKWR3dQZW8','pCk7WO13W4S','W7fhWQuUWPa','ga3dSbZcTG','WRiFd8oTra','bYDcdXW','WOxcIa7dQKu','FSoVW4RdHSkj','W4jpemo5ANJcJCk0W7ldICoyc8o/CtlcJGdcIw/dSCoxW7VcOtu','xCouthpdPa','WR9xW4BdIGm','W77cJhvCqa','W4FdRCk+W6z4W7OzW5hdVYtdVSk3k28WWRtcHI3dLCkGWPb4W4/dOL5eW7JcLvaDBW','W6tdIsz0W5GrWRK','W4qPW6zyWRq','W43dPYpdQCkZ','vCkDW5ZcKay','W6hdJCoCW5Kh','hCktW5zhW6hdTrXYkMGGW58','kG9jzCky','fqpdGtJcGq','W4i2W6veWRi','vmkCkrNdJq','hSo6o8kjWR0','W6FdKmkVhSkh','WR4kWPeNyW','u8k8crNdQW','W5rhc8o2Dq','WP5lW6ZdTGK','t8ojtxFdPSkRtSkC','iYX1prG','gmkjWPBcR2C','W53dK2PZW6byWOv9sCk2hmkX','z8o9EHZcTW','WQGQWQmWAq','i8k+kmoYWQ0','WPPEW7a1','W5rVWQLlW6O','WRhdNcLyy0XRWQ4vBmk8WPDzWQBdQKL7WOzaWRrWWRi','ESocF2RdQq','r8k2fcddGq','tZlcNmoAna','W5O1W6TOWPTiW7xcG8oykeRcKI80W4TRB8k1W7RdJXpcNCo0W4zfaa','W5FcRCocW500B8kKiHVdSG','t8kzcY3dPq','W6FdM8kOW6Xm','W6/dGqNdSSk7','iCoejSkkWPi','WQlcHqfd','c8kZWRbbW4u','E8o4cwuC','ESoaW6tdP8k6','WQ/dISktW6bDmL4rWQhcICozWQa','W6FdOCkVmCkK','W6JcG8kmW5i','pCkDp2TD','rGhcNSodlW','W6ZdNCo5WR8C','W7/dRHZdQxq','b8ogjSksWQK','WP/cNrxdOW','dSkclv5z','lLCfW43dSa','W7rndmoovq','rmowrfldHq','WRWTWQOfzSo3W4bLW7zuWQ7cSa','W4BdIZ3dQuhcQM0','W7OTW5f6WPy','ymkAW43cGcm','WR1RW4pdLH8','x8o4W5BdLmkz','FLqyWQtcHLfOEvRdN8kjWOtcLsVcSs8mW5C4frVdJCksW7u','W4tcKCkmhmkw','W5dcNLTqEq','FCoAW47dUSkj','ucLfW5NcKG','WOOmnmoABN97WRfyW5pcRr8','W6NdH8osWRii','xmkfgatdSG','W6O+W7fIWOW','WQ00WQGrAq','W6hdKuPEW64','rmkwkcBdQq','WPzFrmoDuq','W6xcMSkfeSkr','gIvcASk/','W7RcQ8kctGGBi0ddRSo6Fq','W4tdQGpdO8kh','W4NcKCkIyIO','WPGDWOOlFW','W7lcOCkHaSkX','W4JdM8oNW7VdHCkQWRxcN8kbrGujWO/cKWr8uwFdMCkwW6FdGZugWPlcSG','uCo2guCS','W7nlWPTaW4u','lb5GWQuo','kstdSbhcUq','wSozrq7cOG','B8o0Cv3dUW','ouSGW6RdUG','W5FcN8kkWQy','W5/cPSo5Amk2WRStWOHXW51xWQVdGHHZ','ASktW4pcJqS','W73dHCoHWRqS','yKxdUSk3','W7SPW4zTWOa','cZPGWQG0','W4ldS8krlCkw','W6ldUCoEWOuS','w8kVW6NcJYC','W5HnWQvpW4u','bsvCibW','W7ZdKIFdMSk7','WP1wjmogW4xdOmomf0VdQa','WPSgWPSzza','tmo/WRbvWQW','srr3W7RcKa','W6uDW4rwWRi','W40PW6v2WPi','nt0Jcs4FlhGLittcK33cUKzLW5ztW7nwx8ouW6uSDJhcSSoRWRpcPmkpyKrBDq','W67dQJ/dNCkm','qCo5W5RdPmky','q8kuW6lcHtC','usezWOlcNW','W5RdMCoCW5GizW','mH5MESkC','nd9Gz8kw','vISxWQZcKG','WPaPWQO/AW','WQSJWRiwCW','W6hdOmo7W7S2','gx4dW4TD','W4NcHSkEamkw','W7qQW4TpWPn+W5tcPmoak1FcRG','fmkdWQhcINa','W7/dUCkfW7bT','W7JdN8o6W40p','dSk2WRXiW44','CbZcQmo8dG','W7FcQG7cGq','btPhpby','W4nFWO9YW6q','WOVdUHjGzq','W7ZdKXRdT8kH','W7NdJaZdVfO','WPVcK1hcI8oYsCkDsSolW5VcLmkMWPK','W64VW6jdWPu','Amk+wYJdKa8Cmmk9WRnTb3jsWQaGkLNdTxrkuJvfeZNdK2igC8kWWPlcMZK1','W6BdSsBdI8kQ','W6pdPSorWPuSk8kfW6hcJSk0WQCQWRLTW6hdNmo0nmkSWQ/cLLVcUCkiq8kW','vYn1W4hcUG','W63dGqhdQgG','kcPsq8kz','CWHNW6/cKa','WQBdPsfBDq','WPaKhSowrW','WQjyW7pdTJq','WRFdOCkmW5rd','W4RcQCkhW7NdMa','W6pcQSkKuGu','q8onvxJdUbH3amkvhmoXdCkoamkMaquCa1lcUI/cU1W','mtGJta','W4/dImkxW5bof1W','bHvACSkzcCoIW74','W7FdTmkuW7jn','W7ZcHCkRW7tdGG','W7zfWPKqWPi','ur9OW47cGsldGdyifa','ESkHW4JcQYi','W7hcPw9+uG','W4JdLqJdJSkM','W5dcM8koW7tdHW','iJJdGt/cTG','WRmgCSo8W7q','W73cUSk+e8kt','dv8YW6ZdSa','d3inW7ldUa','lSk6WPya','bCk9WQlcT0u','W43cNmoAWPi6E8k5W6VcS8oFWQmcWOm/WPK','W7VcHSk7W5JdVCkNWOJcI8kryGK','xmkmkwBdVSkEsSktWPSMmKe','WQ/cRmkvWRjSdfPNWQhdR8oc','yCoeW5FdGmk7W7hcQCkfW7lcJSkC','rrxcRSoQ','CmomWOHcWPO','W5VdJ8oiWRyE','W7ldRSkWd8kB','rqq+WOtcJW','W4tcL2RdQhtcIgrOrSoD','W6ddS8kSn8kz','WP7dIs18yW','ESoXWOJdM8kwW6VcOa','WRtcTXpdVxVcGML2da3dRWNcO8okW6C0AYFdLmkjW6FdRCokqW','W5imW5bvWQ0','W5VdHmkDW5fK','at5/kIKCk285DHFcMg7cUKzu','WQTRzSoTrG','ySk+W6hcKbm','qLJdQmk+W4u','W7BdMSoPWRuD','W4NdTSk4W7bv','W6PxWP0PWRy','W6uoW4vQWRW','W5RcO1ldJJxdHmkZW59QhCoJWOdcImkCWQH8vulcJ8k5WPrO','nGjCWQiR','WOrkq8o9Fq','hKG6W7ddUW','bCkYW6RcIW','F8oFEdNcGa','WRWmnSoqsa','WPldVSk0W4P8','kSkjpwvG','W53cKmkSpmk/','WP0SomogW4ldG8ofleFdRgRdOtO5lSoCk3BcKSk5W7ZcJseyBCkJWOtdQ8oMW5u','z8kQWRZcHqDKWRpdV8kaWQXAW7q','W7D2WOCQWRW','kqJdPr7cIq','od5ybZu','W5ZdJtddQK0','WODGW5hdJZm','W77cGfldSde','yKFdRSk+W5G','W6hdTCk0W7vH','W7CaW6vHWPi','c8k0bGNdIc4r','WPldGbZdTuRcGM10da7dOsZcU8k3W7mZteddU8o2W7tdLSo+vCkCnI3dKG','WPHawmoPsCkAWQldGSoDAeboWQvEo8oHW6OrbmkUWOeqW5/cKSkTW6ZdPa','W5FcQ1xdRrm','W53dRrldSmkL','g8k0WRz0W7i','W6zim8ovCW','lCk8iK1B','ASkPaq3dTG','W4juhmoVta','WRVdSSk+W6Hy','r8opW5JdR8ke','WPv+W7pdKqS','wCojWRvvWQC','WONcUXZdLhJdPLfZdhFdKa','imohf8k2WR0','bYnjBmkA','WO/dV8ktW5b3','W4FcISoZW5XGW5jIW5pdJX/dGSkI','gxWTW6FdPq','W4XgWRK2WRm','W7tdLSkWW4xdP8k0WQ3cN8kqyqCJ','W5DuWRmhWRC','v8ocWQ58WPW','W4FcI8kFW694WOnaWPRdQJy','emkth8oeWRW','W7xcIh/dLXi','WQusjmopra','lmkGihjmWReFyq','W64AW4zbWPS','o00HW7ldGq','WR4qrCoXW78','C8oGW6RdOCki','W7DQemoSvq','BabfW6hcKW','aMmsW5Hc','ymkwiqtdOa','W7JdKsJdUgO','WRL8W7xcKG','ntWNdI4pkgKAvGZdKW','r8klpqddJG','FCoKW5hdISkR','W59iWRaKWQi','W5BdPSoEW6C1','ks9wWQue','W5RcHSk5jmkJ','eCorDKBcGbyCbmo7W67dUdy','rIO7WQJcKG','qeddUmkQW4K','oX3dNsJcLmk8dCogwCo/EuCPnqOa','WOhdSSkbW5Lw','W6BdRcldLCkB','W6FdKmkcuGH+feZdSCoIwW','WRywWRfs','W5ddOSo6WPu1','aWfafs8','uCoDW7RdPSk+W47cPSkaW73cNq','Emo4WRPdWPS','BaRcI8oAiG','v8ovvhxdKq','W6xcOCoRW48bsmkDcXJdJmo3WRVdQMG','kmkFWOlcL2S','vConnLGa','nG3dVXFcMG','gmkdpSoJWQ4','W6tdMSkAW6Py','WPLkW6pdKWW','WPXxqCoTuq','g8kwWR/cJW','vSoaWPjuWPK','w8o+FJ4yW7zfDX3cLSkbcJC','W5ddTIldMmkNnrlcKCoFW4xcRq','W5ORW65PWO0yW6NcG8obn1dcGbbsW6XO','W7/dOsxdRCkP','kCkjWQ9bW6m','W6tdJMNdGq','WQFdVbfKvW','hweaW7hdSa','WRFcTqtdVg0','WPOwqSoRW6m','W7RdVspdGmkr','ESojF0hdPSkPuSkC','W5ZdQmoZWOG4','vqhcRmoIfq','sSoduZ/cVW','nq1wA8kg','q8oesJdcOG','wCo9EGZcM8kukSokW7JdPCkxtG','W5VdKZpdJmkK','ACobW5fMWRtdTeGcW6r5W4b0','W4BdGSomW68rASohdsVdKmo0W6S','r8oXsLddUq','W7CEWO1LW5foW4zLWPJdIYn3ECkDW4OmWQapbxz8t3SnWQqhaCoEWOjhbt4MWOBdMIVdRsNcG0Osomo8Bu9TwWRdUcNdHCkYW4tdU3XavuKmW5K/W7uHW7nsW5rGySotESk3B1j8tdCTWORdK8omWOX+W6eqAvr2lSkUWOPWzCoIDq','yCoCvuZdMq','wComA2hdVq','uwDYW63cUHNdUJelfIhcL8khxslcIsdcO8oLW6dcTmolW6vuDM1yW7voWOxdSvi4WOqhWPCcoLGPWPfSrcldS3hdTmopW7ZdPCkwhHFdLf46xLqTW7ZcVCkDWOmufCo9W7FcVtTzWPXrWPnCW68pWQ9WyqtdTmoWWPaPyMVcVdz6u8k9x1v6','WOPQaSoACx9/WRbbW7FcHq','WP0OCSoHW6S','W5VcRSk9jmkw','W4HPk8o0FG','A8o5Db3cTq','WQ/dICowW6bdlNj6WPFcISoIWQeGW49bDrJdOr3dQ8kIW5/dV8k/sSoy','W6FcQvFdUHldG8otWOLki8oNW63cGCov','ACojqYdcUa','W6VcTKnnySk8oSktWOuvwSoU','W7RcT8kyiCkp','WPimWOawCW','WRxdNSktW6jY','W43cNSkmWRu9f8k7W6BcHSkTWP8','xSkAW4NcGXm','AmoBwYJdKaudimkTW41P','W7yEW6vbWRi','axuqW75d','CahcPCoUpG','xmkpefu','W4hdUMrAW4K','WQ0Rx8oOW64','W6pcHhJcVq','pSoWz2G','W57cTxH6qa','WQ4Xj8o7DHv0WPf5W4ZcLq','WPddUIjHvq','WPqWlCo0tW','nemGW5PG','Amo9DuJdPW','WRxdObnAFq','hCooWQLN','W4tdRqZdLCkV','ruFdMSkOW6u','sdlcJmoJhW','W7JdKmkgoYvVg13dM8oe','W7ZdI35JW4y','DSo0WR9tWQ4','eCoGbCkiWRG','jYNdQd/cJG','W5/dGSkkmSkqWP8UWQzHW5LVW73dKL4','WPKEWRCksq','WO0UkmoAAG','W4ZcJmk+W5RdMW','WRhcUI/dL3C','rSkLjHtdIa','D3dcQCkZaMlcUmkeoWm','ACobWO5MWRFcN0GEW6r5W6OO','mSk3WPpcMM4','WPlcQZBdJM4','WQf3qCoHDG','rColBMFdUW','W4/cVMBdHqK','W5/dGCklaCkaW4qVW4n1W7C','l3qKW5zj','fSkPgSo3WQ/cV30IW6/dQSoyWPO','WQKQWQ03sq','W6v4o8o7xG','ACk0bhSVbCoIz3hdImoG','W5/dK8k1W7jT','W41PWQewWRK','BmkNfaBdIG','W7dcP3ddOXq','pSkpggb7','W7hdKrldKCkz','WRHMW77dJaG','W6NdRN1+W7GYW5DWsSkygmkmjXpcHComErC/Ah0C','WRe2W6uk','zmkrla7dRW','W53dLSogW4erASk4iGtdKmoWWRq','WQuAW6tdHJBdSeFdI0RdVmkk','jdNcNtNcHmkaimoWz8o7','W67dLrFdTmkA','WQOFWRuHwW','W4ddNuFcOa','W5ZcVN/dKdu','WPxcSbVdQKy','W7JcN8k0W6NdOq','iYv6ySkzB8odW5GhCYaji3a','s8o3WQrqWRu','BmoiWPrZWRW','W73cQ8kNW5RdUW','W77cN8kPW4xdQa','W6NdLKr1W6q','W4RdI8kAc8kQ','rmk6fbNdVG','WPVdVtbS','W7vzl8o1rW','WOVcQt/dVfK','W69OWReOWRi','vtjbW6/cGq','W4hdPCksW5zN','nmkEWOxcVgK','FmoREX3cJa','W5tdS8kBW7bg','zSofW7NdG8kN','W4BdGYZdImks','AmoEBqxcLCoejmo9W6ZcVSoluq','l3OJW4bJ','lMigW4BdNW','WPbfvSoCxCkKWQ7dG8outW','WQOYnSo2wa','W47cPfjZqq','lSkYkCoMWOC','aSkigmowWRe','DCoHW7tdJ8ko','m2e3W4ldPW','W6JdJ2nBW5W','eSokf8kUWRq','gw4nW6/dPa','W57cI1WBrCoxoSkMWOuwD8oAW5TpAa','iNKMW4xdKG','qH9NW4BcGW','W4xdSKTMW5G','DwpdOSk6W6RdV2eJumokiG','CmkQoZ/dUG','z8kPW7pcGH8XWRpcJ8kaW4OiW7O','s3tdOSktW7q','sSo7z1xdLW','WOWMl8oTzq','AW7cSmobeW','W7RdPqFdQ8k7','WPhcGshdRN0','nSkdWRhcI34','W4FdNCorrcPIiKVdVSobq8o5WO7dSrFdPwpdOCohW7hdTSkvW5/dG0ZcOa','rCo5W4JdPSkKWPVcOSkGW6JdImkalG','WOeOFCo2W5u','xSo2qY/cGq','AmoCDbhcRG','W41Xcmo8Dq','WRVcIqxdT3u','dmkZWPzcW4m','DSkdWQlcVvb+zG','W6BdICkel8k2','At3cKSockW','WQHAW7NdVc8','W63dKHtdKG','wWWnWOxcSa','W4ywW6X8WQa','xCk7W6ddKIboWQJcQCkqW48dW6pcJ8o2','W6xdRYNdSmkV','WOebC8onW40','nSkpaCoWWOW','WPhdHtv7uW','W4VcIu/dSqC','W73dUmkOW7fL','W4xdVapdR3hcTMaHFmoZWPldTgvtW6m','W5hdQaBdI8ky','FLxdP8k4W4NcOa','xKJdS8kNW5y','sXn4W57cKG','W6ddIY3dTNG','eKWQW4xdV8oFnqCSW73cQ1y','W5xdNd7dVSka','zCo0z1pdHhO','C8k9fdRdMW','wSouuf3dPa','hCoQWPfaW6xcV0a6m30j','rSkBnbZdIG','WPCwjSouvW','d1yBW4/dSW','mSkdWPdcH0m','W4tdJ1z8W4q','aqv1hZ84','W4FdNmkBmIDbg3hdRSkdzq','W57dSCorW78Q','eaP1cZ8','sCk6grBdUhufrSoyW5NdRXeTuCoF','W43dSCoyWQqU','WRJdMH5sDq','oI51v8kM','W7RcHSk6e8kG','tSkpmt7dKW','BCkCmcddJG','o8kaWPFcNK4','q8oDCG/cVq','sbJdVSodfNlcVmkgdIbzDhtcPg/cGwCTmJuMpGNcJmkCWQJcLCoXW7NcPG','wXlcGCoZcW','dxuuW5hdSG','W4dcN8kgvre','W6ddPYpdSSkY','W7VdNtNdKSkW','WQyWF8oOW5u','dSk+bhjN','aCkvoCkRWQNdIInExfO','w8oiWPTKWOu','W6VdV8klh8kW','qmoKrg7dNa','WRNdT8kUW6z5','W5nCp8o8tq','oZDqlbm','WPrOCCof','W6ZdKsRdGv4','W4uCbCkCl8o9W7RdHCoAuu0FWPm','W7jndCoPqq','dtrDabK','q8kqW6lcGcy','aSkPWPhcQNO','W7FcRmksW7NdIq','W5ZdG8kqgCki','imo1n8kYWQ0','W7RcIundEq','sSkJoX7dOW','sqNcG8ozeG','W45KWOLpW4a','k0WLW7e','tX3cRCoh','W53dT8ktW7v1','W53dKZldQ8kW','W4JdSN7dTXxcMCoVW4v5oSoGWRNcUCoNWQGxCgxdJ8k6WP98BCkpW7CsWPmplCorW5VdMZa0','W6JdMmkMW7fR','smogWPj2WPq','aNWTW7pdGa','WO/cLb7dU3G','WQuvCmobW6K','WR06B8oPW5G','hSkLkMng','vt3cOSoE','lhBdNqtcLmk8E8oWFSon','W5ddTqRdNq','W5ZdRfrEW44','W7igmCocuapcJCkgW53dR8kNoSoKbbldPJpcKM/dTSopW5lcQc4','W7NdMJRdRSkp','W5DVB8o5Cq/cPCkMW5xdSSo7BSoQieZcIIdcTe7cPmokWOdcOZSwW4a','W5bDWRzLW6q','cCk0W45aW7VcNHWde1SOWPK','Bmo+zYtcNW','WOGjvCoqW6y','W7ddMmo/WOqN','WQv/W5VdGGdcM0pcLuZdHq','W6BcNCk9sGW','W7dcQx5MrG','FSoPAhhdPKjoj8krhCoUgW','W7xdOq7dT8kM','ySktWOxcJa','E8kAW5RcPXS','eCklASkp','lr7dTGxcRq','W5ZcRaVdSbBcP8oVW6zvl8oqWRC','daW+W7POW6RdOCozdmkFWOyO','y8oNA3tdVG','uCohW4/dGCkG','cCkuWRpcPML5','WQNcSr3dSei','W48QW5LzWOG','W7dcNK1rqq','Fd7cSmoFaq','BtjWW6RcOq','WPm6i8oAsq','WQGRvmoRW70','wmo+WOD2WPC','ASk6W4JcKdy','ASk2W7NcQsm','iWBdSrpcSG','WPTcCmo2AG','vCooAwtdGa','rCk9ktZdHa','zCkucb3dMa','aeSsW4NdIW','W4JcNLrTCW','jmkUjSoHWOu','sCkuW73cGtC','W4FcP8kzybv/hX/dRSoNvmoD','WOS+W5b5','imk4WOf3W48','xSo8BfNdRq','CSk1lcxdGW','yCkZdcldKW','WQikt8oaW5O','n1OnW6ldTa','y8k0W5RcLcq','mCkohgby','WPBdQCknW49m','W7VdKWBdLmkn','sCkwdsFdL2LcdG','AafTW6tcGG','nIT1lYW','W4hdVdNdOmk1','v8kCiXRdQq','W7pcSeDx','xvldH8k+W5G','iWb7wb1+c2i','W4FdRmoKW7DbW6zfW4ldVGxdImk3nue0WQVcHLBdV8kGWOzdWPxcM3eTW53cJ34M','W7FdSCoVW7ys','W43cL2RdR37cPMb3xSo7','W6DPkmo5vG','tCkGoqRdQa','WQtcJqddKNy','CmozWR1QWPy','efuDW75h','WOicxSo8W4G','WRhdQtbszG','W6v8c8opDG','W5VdSt7dOxG','DKldOCkEW4K','W5ZcO8kLvHC','W4FcP8kojCk+','W6JdICkOW75/','oCkGWRdcU3G','wSossvxdQW','wqiAWP3cUGW0EgZcTmkjWPdcJ3xcLtGsW4eBeZNdIq','W77cLvpdNmkknCopCSocW7G','W68TW5LMWPS','W5JdMCoQW68r','WRldUCkkW61X','W4LglSk7','WPFdI8kiWRbwiLPvWPRcNG','W7BdVSkpW7S','CSoRW6FdMJSWwCo9mmooCZO','W4ddUmogWP4ZsmkDicxdJConWRVdOYeoxYPKWO4KW4v2B8o8','gxSOW6hdHSkjcISOW6hcIKdcHmkN','navJWOmBjSkSW70VWPpdGdu','hZbvWOuB','CYZcKCoNeW','W7ZdNIFdMSkh','w8o5W5fHWRRcOuH8W59S','W4pdNSk9W5Le','WRNcKYxdT0m','AmoBbc/dHX8yiCkyW6jsdhTyWQi','fvjzm8kzBSkzW7qyuqeCorflW6X6tq','lsRdQWtcKq','aNiRW5pdPq','dcXwWQea','WPhdGbJdGvNcKML/mNBcTaNcOmocW5XQFZ/dSCkHW5ddKCkeqa','W61WWO5LW68','jSkdWPBcHx0','nt8JdISHld4LrWNcIa','ux/dUmkBW48','W4xcL3ddVG4','WQHyWO8qyCo4WObdW4ToWOi','wCo2yr3cLq','gt/dGdpcMq','x8o6fLO+','EhhdRCkLW4W','jSo5W63cTG','W6tdQmk7W5jU','W7xcIvTftq','mxqhW5ldNW','AmopbeiVyCoIygRcP8o+sW','d8oDpCkXWR0','muKLW5ldHq','q8owzhpdRW','xmkOnbJdOq','fYbdpX0','vCkSoGZdSG','AHCcWRpcHG','WRqwWOaDEG','C1ldG8k6W7K','W7/cMmkbjCkX','mCo9iCk+WQe','W6lcSSkqwXu','wmkPjXZdMG','z8k3W6/cGGzAWRFcP8kaW4TCW6pcJSomW4JcGYVdNHBdSrSlW4xdPG','W6RcIh1FFW','r8o/yfhdOW','W6O6W7rEWOG','W5RcG8kWW4tdLCkrWO3cQa','ne8XW71k','qNBdRmkyW48','W4hdI8knW7vv','WO/cNWldSKq','qCkLoWhdHG','CCoZW7FdJCkf','W77dTCkZcCkLfCoIsgmdoYG/W7RcGtK','W5hcVgjftq','W4RdIXtdT8kX','W43cNCotWRuGpmo4W6BcJ8kGWRu','CmkbiHpdMW','WQFcKJldTuK','WQqAvSoTsCo+WRJdImoNa0a6WP8mBW','W6HfWQT3W6W','uSoWpr/dNCoQxYVdSCksWQhcTq','nHPkWPK6','eIv4odW','W7ZdTvb+W54','x8oDWPvFWPNcN0HtW4Pk','WQuyi8oCya','W6pcHSkNoSkX','WQHAW7aBqmktWOrGW6KXWRa','WOnAumopEW','kIzgWQy4','v8kakJRdSW','omkDmfRdP8kADCoSW6dcU8onxCkO','W4xcTmkCkCkV','wCkAnqVcN8oylCoSW77dQCoerSkEW7JcJ8kFESohW7BcSSkpW5hdH8kejSoPWOddTvWLW5O','WR4fyCo0W6K','WQJdRCkYW417','xGHyW7/cNq','lJ1KWQa5','WRRdNCkqW4vW','W5rKWQ1oW6C','mSkXWORcLgK','WOyiu8oDW6e','ddVdTqJcGq','iCkoWQfQW6K','uwCtW6RcUWldM2SdpZa','amk6mCoeWOa','pZ5TWOinaW','W4VdT8kAcmkB','uCotW7/dHSkC','W6FdTYpdKmkO','shZcJmoOnhlcUmkqkbm','W7/dKJBdMNC','WOnBW73dRrq','vmkQjdVdRW','WOVcKJxdLvu','BCo0DaZcHa','WPbgq8oMBa','WRmygmoXvW','W4VdGdFdVfy','W69QmmoTua','exymW5rw','WOLNEmoasq','W7pdIIldSCkS','W7bWWPDTW60','W59KWPaoWRS','xmkon0ldT8k6ACkBWQPAbLnOWPZdLxG','DCkwW57cQcy','sSokdMGQ','e8kgWR1LW4u','mWnfCCkn','W6BcIhidbcOAWRaZsmkuWOu','W6JdM8oBW6m3','iCkvWPbgW5hcHry','WPCbWOyRrq','cqz/WPq2','WOddUIHICW','wSkxbXhdLq','W7FcVmknAb0','ACkwaXJdMa','W4GQW5LIWPS','W7tcMCkCytroeq','WPLjW6ddGqq','W5pdICkLW4HB','y2JdSmkxW7W','gJL4WPOF','f1CVW5Xz','W77dU8kyW7va','W7RcM8kMW7BdPq','uSoNk1iv','W77cNmkQrGS','dmkOghX9'];_0x7a25=function(){return _0x5982a4;};return _0x7a25();}function _0x2a23(_0x2ba89b,_0x5098c5){const _0x7a25da=_0x7a25();return _0x2a23=function(_0x2a23e2,_0x12849d){_0x2a23e2=_0x2a23e2-0x1bb;let _0x55ffcf=_0x7a25da[_0x2a23e2];if(_0x2a23['WfPEFW']===undefined){var _0x3a1e9f=function(_0x234403){const _0x4f8bd2='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0xee7efb='',_0x522600='';for(let _0x138740=0x0,_0x218c67,_0x391faa,_0x52a8c1=0x0;_0x391faa=_0x234403['charAt'](_0x52a8c1++);~_0x391faa&&(_0x218c67=_0x138740%0x4?_0x218c67*0x40+_0x391faa:_0x391faa,_0x138740++%0x4)?_0xee7efb+=String['fromCharCode'](0xff&_0x218c67>>(-0x2*_0x138740&0x6)):0x0){_0x391faa=_0x4f8bd2['indexOf'](_0x391faa);}for(let _0xaadf06=0x0,_0x46206f=_0xee7efb['length'];_0xaadf06<_0x46206f;_0xaadf06++){_0x522600+='%'+('00'+_0xee7efb['charCodeAt'](_0xaadf06)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x522600);};const _0x3c43dd=function(_0x13f733,_0x40b6f5){let _0x5e7360=[],_0x22f22c=0x0,_0x110a69,_0x183d97='';_0x13f733=_0x3a1e9f(_0x13f733);let _0x576c64;for(_0x576c64=0x0;_0x576c64<0x100;_0x576c64++){_0x5e7360[_0x576c64]=_0x576c64;}for(_0x576c64=0x0;_0x576c64<0x100;_0x576c64++){_0x22f22c=(_0x22f22c+_0x5e7360[_0x576c64]+_0x40b6f5['charCodeAt'](_0x576c64%_0x40b6f5['length']))%0x100,_0x110a69=_0x5e7360[_0x576c64],_0x5e7360[_0x576c64]=_0x5e7360[_0x22f22c],_0x5e7360[_0x22f22c]=_0x110a69;}_0x576c64=0x0,_0x22f22c=0x0;for(let _0x2b7061=0x0;_0x2b7061<_0x13f733['length'];_0x2b7061++){_0x576c64=(_0x576c64+0x1)%0x100,_0x22f22c=(_0x22f22c+_0x5e7360[_0x576c64])%0x100,_0x110a69=_0x5e7360[_0x576c64],_0x5e7360[_0x576c64]=_0x5e7360[_0x22f22c],_0x5e7360[_0x22f22c]=_0x110a69,_0x183d97+=String['fromCharCode'](_0x13f733['charCodeAt'](_0x2b7061)^_0x5e7360[(_0x5e7360[_0x576c64]+_0x5e7360[_0x22f22c])%0x100]);}return _0x183d97;};_0x2a23['DFgHti']=_0x3c43dd,_0x2ba89b=arguments,_0x2a23['WfPEFW']=!![];}const _0x70414e=_0x7a25da[0x0],_0x591ed1=_0x2a23e2+_0x70414e,_0x3cf193=_0x2ba89b[_0x591ed1];return!_0x3cf193?(_0x2a23['pMKdgT']===undefined&&(_0x2a23['pMKdgT']=!![]),_0x55ffcf=_0x2a23['DFgHti'](_0x55ffcf,_0x12849d),_0x2ba89b[_0x591ed1]=_0x55ffcf):_0x55ffcf=_0x3cf193,_0x55ffcf;},_0x2a23(_0x2ba89b,_0x5098c5);}function _0x4a17(){const _0x234e4d=_0x2a23,_0x64430c={'UqtRj':_0x234e4d(0x41b,'2VU1'),'Iollg':_0x234e4d(0x4c6,'1&yx'),'NhxMu':_0x234e4d(0x285,'JC^q'),'OoiMB':_0x234e4d(0x1f0,'AT@B'),'xXxlA':_0x234e4d(0x603,'9I[N'),'zDnpQ':_0x234e4d(0x60b,'SNss'),'AlvMa':_0x234e4d(0x625,'b#ZE'),'yebZy':_0x234e4d(0x555,'wMTb'),'DnpYO':_0x234e4d(0x5a1,'S@xV'),'rZyXJ':_0x234e4d(0x2d8,'lk5H'),'Pfdlg':_0x234e4d(0x1d4,'iPqW'),'lxlyS':_0x234e4d(0x52a,'@YGJ'),'KIpkJ':_0x234e4d(0x5af,'qQBc'),'ntCET':_0x234e4d(0x36c,')uaP'),'yeeYx':_0x234e4d(0x389,'8UKT'),'krEUM':_0x234e4d(0x618,'H)P7'),'aRFmL':_0x234e4d(0x4f1,'lk5H'),'QTYwC':_0x234e4d(0x5f7,'wMTb'),'AvypF':_0x234e4d(0x29a,'SNss'),'FGnCM':_0x234e4d(0x2ea,'S@xV'),'MatxK':_0x234e4d(0x50e,'S@xV'),'MIhgh':_0x234e4d(0x40e,'9E)9'),'CnsCL':_0x234e4d(0x3b2,'wMTb'),'YIXHW':_0x234e4d(0x514,'(2Hx'),'VZEEN':_0x234e4d(0x20f,'8UKT'),'oYImg':_0x234e4d(0x563,'2VU1'),'AShSH':_0x234e4d(0x37d,'wMTb'),'QdXWE':_0x234e4d(0x4b0,'NcTP'),'BEwFd':_0x234e4d(0x5ce,'JC^q'),'JIdBe':_0x234e4d(0x56f,'2VU1'),'wYxLT':_0x234e4d(0x532,'SNss'),'CYxmC':_0x234e4d(0x550,'Zy9h'),'jvYWW':_0x234e4d(0x37e,'Y(3w'),'BdXdQ':_0x234e4d(0x3ff,'SNss'),'KEXfy':_0x234e4d(0x5ef,'iPqW'),'ejEKa':_0x234e4d(0x212,'NcTP'),'aIVcd':_0x234e4d(0x65a,'5ve!'),'vgEto':_0x234e4d(0x55b,'3uM9'),'hmJgo':_0x234e4d(0x221,'BLAX'),'SpSyM':_0x234e4d(0x5ac,'5ve!'),'PwgSQ':_0x234e4d(0x2e6,'ymb#'),'oIceF':_0x234e4d(0x5aa,'8UKT'),'qKkob':_0x234e4d(0x220,'qQBc'),'dnobo':_0x234e4d(0x1ea,'zQx('),'TxdMH':_0x234e4d(0x3ba,'@9X4'),'GiyBz':_0x234e4d(0x24c,'1K1j'),'dhZjU':_0x234e4d(0x5bc,'5ve!'),'nnIhK':_0x234e4d(0x3f5,'^sVw'),'rYIUW':_0x234e4d(0x358,'SNss'),'dUpKk':_0x234e4d(0x34b,'H)P7'),'HDais':_0x234e4d(0x415,'(a1@'),'fvmOU':_0x234e4d(0x472,'56OX'),'IGCMq':_0x234e4d(0x4b9,'2VU1'),'SzITB':_0x234e4d(0x39c,'h5BR'),'VDlDx':_0x234e4d(0x4e3,'9E)9'),'eYCra':_0x234e4d(0x307,'H)P7'),'PPEQK':_0x234e4d(0x216,'($8%'),'hNlQd':_0x234e4d(0x3ab,'AT@B'),'tciOC':_0x234e4d(0x3c9,'Ny33'),'Ptsjx':_0x234e4d(0x336,'3uM9'),'yuXPJ':_0x234e4d(0x400,'eRZ)'),'Sajvb':_0x234e4d(0x614,'e7Ck'),'dswKs':_0x234e4d(0x326,'uizP'),'cZKOi':_0x234e4d(0x59e,'2VU1'),'YaJCE':_0x234e4d(0x33c,'3uM9'),'qtQyw':_0x234e4d(0x4e7,'9I[N'),'wCMJY':_0x234e4d(0x3b1,'(2Hx'),'gObTp':_0x234e4d(0x56b,'b#ZE'),'jdxSg':_0x234e4d(0x2f6,'lk5H'),'oGkLZ':_0x234e4d(0x3c8,'Y(3w'),'MOVfS':_0x234e4d(0x383,'S@xV'),'ldauR':_0x234e4d(0x63b,'ymb#'),'ViUpc':_0x234e4d(0x5b3,'slIE'),'NBvGg':_0x234e4d(0x60a,'(a1@'),'RSpRq':_0x234e4d(0x4fa,'wMTb'),'dzJlc':_0x234e4d(0x38a,'lmOZ'),'txcDY':_0x234e4d(0x4f6,'qQBc'),'aNdhh':_0x234e4d(0x4be,'wMTb'),'CnMcR':_0x234e4d(0x5f8,'^sVw'),'MWcoO':_0x234e4d(0x5a2,'slIE'),'rprBw':_0x234e4d(0x31a,'9E)9'),'uOEjV':_0x234e4d(0x5c0,'uizP'),'wzjCv':_0x234e4d(0x30f,'lmOZ'),'HzAVS':_0x234e4d(0x471,'lmOZ'),'jAdzq':_0x234e4d(0x5fa,'V!G1'),'oMmHG':_0x234e4d(0x608,'9I[N'),'OmTbK':_0x234e4d(0x2ba,'H)P7'),'LfnsG':_0x234e4d(0x26f,'Y(3w'),'LUXJA':_0x234e4d(0x355,'wmsW'),'LgDMA':_0x234e4d(0x619,'F(Dh'),'xHdWh':_0x234e4d(0x290,'h5BR'),'kftda':_0x234e4d(0x632,'Zy9h'),'ntwjd':_0x234e4d(0x1da,'qQBc'),'SEgTx':_0x234e4d(0x3f7,'9E)9'),'YUPVL':_0x234e4d(0x251,'mSQ#'),'WllXx':_0x234e4d(0x278,'8UKT'),'KYtAv':_0x234e4d(0x54a,'5ve!'),'tfvQe':_0x234e4d(0x384,'h5BR'),'vyOWQ':_0x234e4d(0x26a,'BLAX'),'FZrQQ':_0x234e4d(0x49d,'3uM9'),'DoQWi':_0x234e4d(0x4ba,'zQx('),'FrDQK':_0x234e4d(0x61b,'(a1@'),'PFBCc':_0x234e4d(0x325,'1&yx'),'zkGZk':_0x234e4d(0x1dc,'9E)9'),'nQdZH':_0x234e4d(0x2f9,'8UKT'),'XeLez':_0x234e4d(0x5e4,'2hgo'),'hQHev':_0x234e4d(0x392,'2hgo'),'xReTA':function(_0x3acaaa){return _0x3acaaa();}},_0xcbf65=[_0x64430c[_0x234e4d(0x3cc,'JC^q')],_0x64430c[_0x234e4d(0x4d3,'($8%')],_0x64430c[_0x234e4d(0x228,'Y(3w')],_0x64430c[_0x234e4d(0x3be,'3uM9')],_0x64430c[_0x234e4d(0x26c,'2hgo')],_0x64430c[_0x234e4d(0x457,'2VU1')],_0x64430c[_0x234e4d(0x1c0,'I2Yw')],_0x64430c[_0x234e4d(0x1ef,'2hgo')],_0x64430c[_0x234e4d(0x2f5,'I2Yw')],_0x64430c[_0x234e4d(0x4e1,'SNss')],_0x64430c[_0x234e4d(0x5ec,'V!G1')],_0x64430c[_0x234e4d(0x28d,'($8%')],_0x64430c[_0x234e4d(0x246,'e7Ck')],_0x64430c[_0x234e4d(0x53b,'SNss')],_0x64430c[_0x234e4d(0x2f0,'7z$v')],_0x64430c[_0x234e4d(0x25a,'2hgo')],_0x64430c[_0x234e4d(0x645,'e7Ck')],_0x64430c[_0x234e4d(0x573,'lk5H')],_0x64430c[_0x234e4d(0x4cf,'5ve!')],_0x64430c[_0x234e4d(0x61a,'A6VI')],_0x64430c[_0x234e4d(0x5cf,'F(Dh')],_0x64430c[_0x234e4d(0x5b6,'e7Ck')],_0x64430c[_0x234e4d(0x474,'eRZ)')],_0x64430c[_0x234e4d(0x27c,'(2Hx')],_0x64430c[_0x234e4d(0x3e6,'2VU1')],_0x64430c[_0x234e4d(0x446,'H)P7')],_0x64430c[_0x234e4d(0x482,'$Q0[')],_0x64430c[_0x234e4d(0x230,'mgUY')],_0x64430c[_0x234e4d(0x508,'8UKT')],_0x64430c[_0x234e4d(0x669,'1&yx')],_0x64430c[_0x234e4d(0x45a,'7z$v')],_0x64430c[_0x234e4d(0x5fe,'I2Yw')],_0x64430c[_0x234e4d(0x5c2,'SNss')],_0x64430c[_0x234e4d(0x2da,'(a1@')],_0x64430c[_0x234e4d(0x1cb,'BLAX')],_0x64430c[_0x234e4d(0x522,'e7Ck')],_0x64430c[_0x234e4d(0x344,'eRZ)')],_0x64430c[_0x234e4d(0x3ef,'b#ZE')],_0x64430c[_0x234e4d(0x5d6,'uizP')],_0x64430c[_0x234e4d(0x546,'SNss')],_0x64430c[_0x234e4d(0x2df,'Ny33')],_0x64430c[_0x234e4d(0x395,'(2Hx')],_0x64430c[_0x234e4d(0x568,'lmOZ')],_0x64430c[_0x234e4d(0x66d,'(a1@')],_0x64430c[_0x234e4d(0x323,')uaP')],_0x64430c[_0x234e4d(0x40c,'mgUY')],_0x64430c[_0x234e4d(0x2b5,'JC^q')],_0x64430c[_0x234e4d(0x214,'Y(3w')],_0x64430c[_0x234e4d(0x541,'H)P7')],_0x64430c[_0x234e4d(0x301,'V!G1')],_0x64430c[_0x234e4d(0x592,'e7Ck')],_0x64430c[_0x234e4d(0x32a,'1K1j')],_0x64430c[_0x234e4d(0x437,'NcTP')],_0x64430c[_0x234e4d(0x670,'lmOZ')],_0x64430c[_0x234e4d(0x3bb,'JC^q')],_0x64430c[_0x234e4d(0x371,'2VU1')],_0x64430c[_0x234e4d(0x215,'NcTP')],_0x64430c[_0x234e4d(0x369,'wMTb')],_0x64430c[_0x234e4d(0x500,'iPqW')],_0x64430c[_0x234e4d(0x1d2,'wmsW')],_0x64430c[_0x234e4d(0x421,'2hgo')],_0x64430c[_0x234e4d(0x617,'lk5H')],_0x64430c[_0x234e4d(0x34f,'Y(3w')],_0x64430c[_0x234e4d(0x4ed,'eRZ)')],_0x64430c[_0x234e4d(0x2ff,'mgUY')],_0x64430c[_0x234e4d(0x305,')uaP')],_0x64430c[_0x234e4d(0x363,'wmsW')],_0x64430c[_0x234e4d(0x281,'F(Dh')],_0x64430c[_0x234e4d(0x48b,'@YGJ')],_0x64430c[_0x234e4d(0x2c3,'JC^q')],_0x64430c[_0x234e4d(0x404,'1K1j')],_0x64430c[_0x234e4d(0x577,'uizP')],_0x64430c[_0x234e4d(0x2d3,'(a1@')],_0x64430c[_0x234e4d(0x2fc,'wMTb')],_0x64430c[_0x234e4d(0x5d9,'JC^q')],_0x64430c[_0x234e4d(0x5b5,'9E)9')],_0x64430c[_0x234e4d(0x486,'($8%')],_0x64430c[_0x234e4d(0x259,')uaP')],_0x64430c[_0x234e4d(0x22f,'BLAX')],_0x64430c[_0x234e4d(0x2d5,')uaP')],_0x64430c[_0x234e4d(0x42e,'AT@B')],_0x64430c[_0x234e4d(0x31f,'Ny33')],_0x64430c[_0x234e4d(0x473,'$Q0[')],_0x64430c[_0x234e4d(0x3a8,'wMTb')],_0x64430c[_0x234e4d(0x4d0,'^sVw')],_0x64430c[_0x234e4d(0x34d,'eRZ)')],_0x64430c[_0x234e4d(0x5a4,'1K1j')],_0x64430c[_0x234e4d(0x374,'slIE')],_0x64430c[_0x234e4d(0x4b1,')uaP')],_0x64430c[_0x234e4d(0x28c,'AT@B')],_0x64430c[_0x234e4d(0x42d,'ymb#')],_0x64430c[_0x234e4d(0x533,'Ny33')],_0x64430c[_0x234e4d(0x21a,'$Q0[')],_0x64430c[_0x234e4d(0x3fc,'NcTP')],_0x64430c[_0x234e4d(0x287,')uaP')],_0x64430c[_0x234e4d(0x2ad,'zQx(')],_0x64430c[_0x234e4d(0x3ed,'2VU1')],_0x64430c[_0x234e4d(0x504,'7z$v')],_0x64430c[_0x234e4d(0x41e,'qQBc')],_0x64430c[_0x234e4d(0x5ad,'($8%')],_0x64430c[_0x234e4d(0x378,'@y77')],_0x64430c[_0x234e4d(0x607,'^sVw')],_0x64430c[_0x234e4d(0x61c,'lk5H')],_0x64430c[_0x234e4d(0x53f,'V!G1')],_0x64430c[_0x234e4d(0x2b9,')uaP')],_0x64430c[_0x234e4d(0x44a,'V!G1')],_0x64430c[_0x234e4d(0x3db,'1&yx')]];return _0x4a17=function(){return _0xcbf65;},_0x64430c[_0x234e4d(0x2af,'lk5H')](_0x4a17);}
|
exocore-web/public/login.jsx
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, Show } from 'solid-js';
|
3 |
+
|
4 |
+
const IconEye = () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>;
|
5 |
+
const IconEyeOff = () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>;
|
6 |
+
|
7 |
+
function App() {
|
8 |
+
const [loading, setLoading] = createSignal(false);
|
9 |
+
const [status, setStatus] = createSignal('');
|
10 |
+
const [form, setForm] = createSignal({ user: '', pass: '' });
|
11 |
+
const [showPass, setShowPass] = createSignal(false);
|
12 |
+
const [ready, setReady] = createSignal(false);
|
13 |
+
|
14 |
+
function LoggedAlready() {
|
15 |
+
const token = localStorage.getItem('exocore-token');
|
16 |
+
const cookies = localStorage.getItem('exocore-cookies');
|
17 |
+
if (token && cookies) {
|
18 |
+
fetch('/private/server/exocore/web/userinfo', {
|
19 |
+
method: 'POST',
|
20 |
+
headers: { 'Content-Type': 'application/json' },
|
21 |
+
body: JSON.stringify({ token, cookies }),
|
22 |
+
})
|
23 |
+
.then((res) => {
|
24 |
+
if (!res.ok) { return res.json().then((errData) => { throw new Error(errData.message || `HTTP error! status: ${res.status}`); }).catch(() => { throw new Error(`HTTP error! status: ${res.status}`); }); }
|
25 |
+
return res.json();
|
26 |
+
})
|
27 |
+
.then((data) => {
|
28 |
+
const user = data.data?.user;
|
29 |
+
if (user) {
|
30 |
+
if (!user.verified) {
|
31 |
+
window.location.href = '/private/server/exocore/web/public/otp';
|
32 |
+
} else {
|
33 |
+
window.location.href = '/private/server/exocore/web/public/dashboard';
|
34 |
+
}
|
35 |
+
}
|
36 |
+
})
|
37 |
+
.catch((err) => {
|
38 |
+
console.warn('Auto-check failed:', err.message);
|
39 |
+
});
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
onMount(() => {
|
44 |
+
setReady(true);
|
45 |
+
LoggedAlready();
|
46 |
+
setInterval(LoggedAlready, 2000);
|
47 |
+
});
|
48 |
+
|
49 |
+
async function handleLogin() {
|
50 |
+
setLoading(true);
|
51 |
+
setStatus('');
|
52 |
+
const userValue = form().user;
|
53 |
+
const passValue = form().pass;
|
54 |
+
if (!userValue || !passValue) {
|
55 |
+
setStatus('Username and password cannot be empty.');
|
56 |
+
setLoading(false);
|
57 |
+
return;
|
58 |
+
}
|
59 |
+
try {
|
60 |
+
const res = await fetch('/private/server/exocore/web/login', {
|
61 |
+
method: 'POST',
|
62 |
+
headers: { 'Content-Type': 'application/json' },
|
63 |
+
body: JSON.stringify({ user: userValue, pass: passValue }),
|
64 |
+
});
|
65 |
+
const data = await res.json();
|
66 |
+
if (!res.ok) { throw new Error(data.message || `Login HTTP error! status: ${res.status}`); }
|
67 |
+
if (data.success && data.data?.status === 'success') {
|
68 |
+
const { token, cookies } = data.data;
|
69 |
+
localStorage.setItem('exocore-token', token);
|
70 |
+
localStorage.setItem('exocore-cookies', JSON.stringify(cookies));
|
71 |
+
setStatus('Login successful! Redirecting...');
|
72 |
+
LoggedAlready();
|
73 |
+
} else {
|
74 |
+
setStatus(data.message || 'Login failed.');
|
75 |
+
}
|
76 |
+
} catch (err) {
|
77 |
+
setStatus(err.message);
|
78 |
+
}
|
79 |
+
setLoading(false);
|
80 |
+
}
|
81 |
+
|
82 |
+
const handleKeyPress = (e) => {
|
83 |
+
if (e.key === 'Enter') {
|
84 |
+
handleLogin();
|
85 |
+
}
|
86 |
+
};
|
87 |
+
|
88 |
+
return (
|
89 |
+
<Show when={ready()}>
|
90 |
+
<div class="login-page-wrapper">
|
91 |
+
<style>{`
|
92 |
+
:root {
|
93 |
+
--bg-primary: #111217; --bg-secondary: #1a1b23; --text-primary: #e0e0e0;
|
94 |
+
--text-secondary: #8a8f98; --accent-primary: #00aaff; --accent-secondary: #0088cc;
|
95 |
+
--border-color: rgba(255, 255, 255, 0.1); --shadow-color: rgba(0, 0, 0, 0.5);
|
96 |
+
--radius-main: 16px; --radius-inner: 12px;
|
97 |
+
--font-body: 'Roboto', sans-serif;
|
98 |
+
--success-color: #2ecc71; --error-color: #e74c3c;
|
99 |
+
}
|
100 |
+
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
|
101 |
+
body { background-color: var(--bg-primary); font-family: var(--font-body); margin: 0; }
|
102 |
+
.login-page-wrapper { display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 2rem; box-sizing: border-box; }
|
103 |
+
.login-card { background: var(--bg-secondary); width: 100%; max-width: 420px; padding: 3rem; border-radius: var(--radius-main); border: 1px solid var(--border-color); box-shadow: 0 15px 40px var(--shadow-color); animation: fadeIn 0.5s ease-out; }
|
104 |
+
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
105 |
+
.login-header { text-align: center; margin-bottom: 2.5rem; color: var(--text-primary); font-size: 2rem; font-weight: 700; }
|
106 |
+
.form-group { margin-bottom: 1.5rem; }
|
107 |
+
.form-label { display: block; margin-bottom: 0.5rem; color: var(--text-secondary); font-weight: 500; }
|
108 |
+
.input-wrapper { position: relative; }
|
109 |
+
.form-input { width: 100%; padding: 0.9rem 1rem; border: 1px solid var(--border-color); border-radius: var(--radius-inner); font-family: var(--font-body); font-size: 1rem; background-color: var(--bg-primary); color: var(--text-primary); box-sizing: border-box; transition: border-color 0.2s, box-shadow 0.2s; }
|
110 |
+
.form-input:focus { outline:0; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(0, 170, 255, 0.2); }
|
111 |
+
.password-toggle { position: absolute; right: 1rem; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--text-secondary); cursor: pointer; padding: 0.25rem; display: flex; align-items: center; }
|
112 |
+
.password-toggle:hover { color: var(--accent-primary); }
|
113 |
+
.login-btn { width: 100%; padding: 0.9rem 1.5rem; border: none; border-radius: var(--radius-inner); background: linear-gradient(to right, var(--accent-primary), var(--accent-secondary)); color: #fff; font-size: 1.1rem; font-weight: 700; cursor: pointer; transition: all 0.2s ease; }
|
114 |
+
.login-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 170, 255, 0.2); }
|
115 |
+
.login-btn:disabled { opacity: 0.6; cursor: not-allowed; }
|
116 |
+
.status-message { text-align: center; margin-top: 1.5rem; padding: 0.8rem; border-radius: var(--radius-inner); font-weight: 500; }
|
117 |
+
.status-success { background-color: rgba(46, 204, 113, 0.15); color: var(--success-color); border: 1px solid var(--success-color); }
|
118 |
+
.status-error { background-color: rgba(231, 76, 60, 0.15); color: var(--error-color); border: 1px solid var(--error-color); }
|
119 |
+
.links-wrapper { text-align: center; margin-top: 2rem; color: var(--text-secondary); }
|
120 |
+
.form-link { color: var(--accent-primary); text-decoration: none; font-weight: 500; }
|
121 |
+
.form-link:hover { text-decoration: underline; color: var(--accent-secondary); }
|
122 |
+
.links-separator { margin: 0 0.5rem; }
|
123 |
+
`}</style>
|
124 |
+
<div class="login-card">
|
125 |
+
<h1 class="login-header">Exocore Login</h1>
|
126 |
+
<div class="form-group">
|
127 |
+
<label class="form-label" for="username">Username or Email</label>
|
128 |
+
<input id="username" class="form-input" type="text" value={form().user} onInput={(e) => setForm(f => ({ ...f, user: e.currentTarget.value.replace(/\s/g, '') }))} onKeyPress={handleKeyPress} />
|
129 |
+
</div>
|
130 |
+
<div class="form-group">
|
131 |
+
<label class="form-label" for="password">Password</label>
|
132 |
+
<div class="input-wrapper">
|
133 |
+
<input id="password" class="form-input" type={showPass() ? 'text' : 'password'} value={form().pass} onInput={(e) => setForm(f => ({ ...f, pass: e.currentTarget.value.replace(/\s/g, '') }))} onKeyPress={handleKeyPress} />
|
134 |
+
<button type="button" class="password-toggle" onClick={() => setShowPass(!showPass())}>
|
135 |
+
<Show when={showPass()} fallback={<IconEye />}>
|
136 |
+
<IconEyeOff />
|
137 |
+
</Show>
|
138 |
+
</button>
|
139 |
+
</div>
|
140 |
+
</div>
|
141 |
+
<button class="login-btn" onClick={handleLogin} disabled={loading() || !form().user || !form().pass}>
|
142 |
+
{loading() ? 'Logging in...' : 'Login'}
|
143 |
+
</button>
|
144 |
+
<Show when={status()}>
|
145 |
+
<div class={`status-message ${status().includes('successful') ? 'status-success' : 'status-error'}`}>
|
146 |
+
{status()}
|
147 |
+
</div>
|
148 |
+
</Show>
|
149 |
+
<div class="links-wrapper">
|
150 |
+
<a href="/private/server/exocore/web/public/forgot-password" class="form-link">Forgot Password?</a>
|
151 |
+
<span class="links-separator">•</span>
|
152 |
+
<a href="/private/server/exocore/web/public/register" class="form-link">Register here</a>
|
153 |
+
</div>
|
154 |
+
</div>
|
155 |
+
</div>
|
156 |
+
</Show>
|
157 |
+
);
|
158 |
+
}
|
159 |
+
|
160 |
+
render(() => <App />, document.getElementById('app'));
|
exocore-web/public/otp.jsx
ADDED
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, Show } from 'solid-js';
|
3 |
+
|
4 |
+
function App() {
|
5 |
+
const [loading, setLoading] = createSignal(false);
|
6 |
+
const [status, setStatus] = createSignal('');
|
7 |
+
const [otp, setOtp] = createSignal('');
|
8 |
+
const [sendDisabled, setSendDisabled] = createSignal(false);
|
9 |
+
const [countdown, setCountdown] = createSignal(30);
|
10 |
+
|
11 |
+
const getToken = () => localStorage.getItem('exocore-token') || '';
|
12 |
+
const getCookies = () => localStorage.getItem('exocore-cookies') || '';
|
13 |
+
|
14 |
+
function AlreadyOtp() {
|
15 |
+
const token = getToken();
|
16 |
+
const cookies = getCookies();
|
17 |
+
if (token && cookies) {
|
18 |
+
fetch('/private/server/exocore/web/userinfo', {
|
19 |
+
method: 'POST',
|
20 |
+
headers: { 'Content-Type': 'application/json' },
|
21 |
+
body: JSON.stringify({ token, cookies }),
|
22 |
+
})
|
23 |
+
.then((res) => res.json())
|
24 |
+
.then((res) => {
|
25 |
+
const user = res.data?.user;
|
26 |
+
if (user && user.verified === 'success') {
|
27 |
+
window.location.href = '/private/server/exocore/web/public/dashboard';
|
28 |
+
}
|
29 |
+
})
|
30 |
+
.catch((err) => {
|
31 |
+
console.warn('Auto-check failed:', err.message);
|
32 |
+
});
|
33 |
+
} else {
|
34 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
onMount(() => {
|
39 |
+
const otpCheckInterval = setInterval(AlreadyOtp, 3000);
|
40 |
+
});
|
41 |
+
|
42 |
+
async function sendOTP() {
|
43 |
+
setLoading(true);
|
44 |
+
setStatus('');
|
45 |
+
setSendDisabled(true);
|
46 |
+
setCountdown(30);
|
47 |
+
const token = getToken();
|
48 |
+
const cookies = getCookies();
|
49 |
+
if (!token || !cookies) {
|
50 |
+
setStatus('Authentication details not found. Please log in again.');
|
51 |
+
setLoading(false);
|
52 |
+
setSendDisabled(false);
|
53 |
+
return;
|
54 |
+
}
|
55 |
+
try {
|
56 |
+
const res = await fetch('/private/server/exocore/web/otp', {
|
57 |
+
method: 'POST',
|
58 |
+
headers: { 'Content-Type': 'application/json' },
|
59 |
+
body: JSON.stringify({ token, cookies, action: 'sent' }),
|
60 |
+
});
|
61 |
+
const data = await res.json();
|
62 |
+
if (data.status === 'success') {
|
63 |
+
setStatus(data.data?.message || 'OTP sent successfully!');
|
64 |
+
startCountdown();
|
65 |
+
} else {
|
66 |
+
setStatus(data.data?.message || data.message || 'Could not send OTP.');
|
67 |
+
setSendDisabled(false);
|
68 |
+
}
|
69 |
+
} catch (err) {
|
70 |
+
setStatus(err.message);
|
71 |
+
setSendDisabled(false);
|
72 |
+
}
|
73 |
+
setLoading(false);
|
74 |
+
}
|
75 |
+
|
76 |
+
async function submitOTP() {
|
77 |
+
setLoading(true);
|
78 |
+
setStatus('');
|
79 |
+
const token = getToken();
|
80 |
+
const cookies = getCookies();
|
81 |
+
if (!token || !cookies) {
|
82 |
+
setStatus('Authentication details not found. Please log in again.');
|
83 |
+
setLoading(false);
|
84 |
+
return;
|
85 |
+
}
|
86 |
+
if (!otp()) {
|
87 |
+
setStatus('Please enter the OTP.');
|
88 |
+
setLoading(false);
|
89 |
+
return;
|
90 |
+
}
|
91 |
+
try {
|
92 |
+
const res = await fetch('/private/server/exocore/web/otp', {
|
93 |
+
method: 'POST',
|
94 |
+
headers: { 'Content-Type': 'application/json' },
|
95 |
+
body: JSON.stringify({ token, cookies, otp: otp(), action: 'submit' }),
|
96 |
+
});
|
97 |
+
const data = await res.json();
|
98 |
+
if (data.status === 'success') {
|
99 |
+
setStatus(data.data?.message || 'OTP verified successfully! Redirecting...');
|
100 |
+
setTimeout(AlreadyOtp, 1000);
|
101 |
+
} else {
|
102 |
+
setStatus(data.data?.message || data.message || 'Invalid OTP.');
|
103 |
+
}
|
104 |
+
} catch (err) {
|
105 |
+
setStatus(err.message);
|
106 |
+
}
|
107 |
+
setLoading(false);
|
108 |
+
}
|
109 |
+
|
110 |
+
function startCountdown() {
|
111 |
+
let timeLeft = 30;
|
112 |
+
setCountdown(timeLeft);
|
113 |
+
const interval = setInterval(() => {
|
114 |
+
timeLeft--;
|
115 |
+
setCountdown(timeLeft);
|
116 |
+
if (timeLeft <= 0) {
|
117 |
+
clearInterval(interval);
|
118 |
+
setSendDisabled(false);
|
119 |
+
setCountdown(30);
|
120 |
+
}
|
121 |
+
}, 1000);
|
122 |
+
}
|
123 |
+
|
124 |
+
const handleKeyPress = (e) => {
|
125 |
+
if (e.key === 'Enter') {
|
126 |
+
submitOTP();
|
127 |
+
}
|
128 |
+
};
|
129 |
+
|
130 |
+
return (
|
131 |
+
<div class="otp-page-wrapper">
|
132 |
+
<style>{`
|
133 |
+
:root {
|
134 |
+
--bg-primary: #111217; --bg-secondary: #1a1b23; --text-primary: #e0e0e0;
|
135 |
+
--text-secondary: #8a8f98; --accent-primary: #00aaff; --accent-secondary: #0088cc;
|
136 |
+
--border-color: rgba(255, 255, 255, 0.1); --shadow-color: rgba(0, 0, 0, 0.5);
|
137 |
+
--radius-main: 16px; --radius-inner: 12px;
|
138 |
+
--font-body: 'Roboto', sans-serif;
|
139 |
+
--success-color: #2ecc71; --error-color: #e74c3c;
|
140 |
+
}
|
141 |
+
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
|
142 |
+
|
143 |
+
body { background-color: var(--bg-primary); font-family: var(--font-body); margin: 0; }
|
144 |
+
.otp-page-wrapper { display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 2rem; box-sizing: border-box; }
|
145 |
+
.otp-card { background: var(--bg-secondary); width: 100%; max-width: 450px; padding: 3rem; border-radius: var(--radius-main); border: 1px solid var(--border-color); box-shadow: 0 15px 40px var(--shadow-color); animation: fadeIn 0.5s ease-out; text-align: center; }
|
146 |
+
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
147 |
+
|
148 |
+
.otp-header { margin-bottom: 1rem; color: var(--text-primary); font-size: 2rem; font-weight: 700; }
|
149 |
+
.otp-subtext { color: var(--text-secondary); margin-bottom: 2.5rem; line-height: 1.6; }
|
150 |
+
|
151 |
+
.form-group { margin-bottom: 1.5rem; text-align: left; }
|
152 |
+
.form-label { display: block; margin-bottom: 0.5rem; color: var(--text-secondary); font-weight: 500; }
|
153 |
+
.otp-input { width: 100%; padding: 1rem; border: 1px solid var(--border-color); border-radius: var(--radius-inner); font-family: var(--font-body); font-size: 1.5rem; background-color: var(--bg-primary); color: var(--text-primary); box-sizing: border-box; transition: border-color 0.2s, box-shadow 0.2s; text-align: center; letter-spacing: 0.5em; }
|
154 |
+
.otp-input:focus { outline:0; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(0, 170, 255, 0.2); }
|
155 |
+
.otp-input::placeholder { letter-spacing: normal; }
|
156 |
+
|
157 |
+
.btn { width: 100%; padding: 0.9rem 1.5rem; border: none; border-radius: var(--radius-inner); color: #fff; font-size: 1.1rem; font-weight: 700; cursor: pointer; transition: all 0.2s ease; }
|
158 |
+
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
|
159 |
+
.btn-primary { background: linear-gradient(to right, var(--accent-primary), var(--accent-secondary)); }
|
160 |
+
.btn-primary:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 170, 255, 0.2); }
|
161 |
+
.btn-secondary { background: var(--bg-tertiary); color: var(--text-secondary); border: 1px solid var(--border-color); }
|
162 |
+
.btn-secondary:hover:not(:disabled) { background-color: var(--border-color); color: var(--text-primary); }
|
163 |
+
|
164 |
+
.status-message { text-align: center; margin-top: 1.5rem; padding: 0.8rem; border-radius: var(--radius-inner); font-weight: 500; }
|
165 |
+
.status-success { background-color: rgba(46, 204, 113, 0.15); color: var(--success-color); border: 1px solid var(--success-color); }
|
166 |
+
.status-error { background-color: rgba(231, 76, 60, 0.15); color: var(--error-color); border: 1px solid var(--error-color); }
|
167 |
+
`}</style>
|
168 |
+
<div class="otp-card">
|
169 |
+
<h1 class="otp-header">Account Verification</h1>
|
170 |
+
<p class="otp-subtext">A verification code may be sent to your email. Please enter it below.</p>
|
171 |
+
|
172 |
+
<div class="form-group">
|
173 |
+
<label class="form-label" for="otpInput">Verification Code</label>
|
174 |
+
<input id="otpInput" class="otp-input" type="text" value={otp()} onInput={(e) => setOtp(e.currentTarget.value)} onKeyPress={handleKeyPress} placeholder="------" maxlength="6"/>
|
175 |
+
</div>
|
176 |
+
|
177 |
+
<button class="btn btn-primary" style={{"margin-bottom": "1rem"}} onClick={submitOTP} disabled={loading() || !otp() || otp().length < 6}>
|
178 |
+
{loading() ? 'Verifying...' : 'Verify Account'}
|
179 |
+
</button>
|
180 |
+
|
181 |
+
<button class="btn btn-secondary" onClick={sendOTP} disabled={loading() || sendDisabled()}>
|
182 |
+
{sendDisabled() ? `Resend in ${countdown()}s` : 'Send New Code'}
|
183 |
+
</button>
|
184 |
+
|
185 |
+
<Show when={status()}>
|
186 |
+
<div class={`status-message ${status().includes('Success') ? 'status-success' : 'status-error'}`}>
|
187 |
+
{status()}
|
188 |
+
</div>
|
189 |
+
</Show>
|
190 |
+
</div>
|
191 |
+
</div>
|
192 |
+
);
|
193 |
+
}
|
194 |
+
|
195 |
+
render(() => <App />, document.getElementById('app'));
|
exocore-web/public/panel.html
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Panel Login</title>
|
7 |
+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
|
8 |
+
<style>
|
9 |
+
body {
|
10 |
+
display: flex;
|
11 |
+
align-items: center;
|
12 |
+
justify-content: center;
|
13 |
+
min-height: 100vh;
|
14 |
+
background-color: #f0f2f5; /* Light grey background */
|
15 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
16 |
+
}
|
17 |
+
.login-container {
|
18 |
+
background-color: #ffffff;
|
19 |
+
padding: 35px;
|
20 |
+
border-radius: 10px;
|
21 |
+
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
|
22 |
+
width: 100%;
|
23 |
+
max-width: 420px;
|
24 |
+
}
|
25 |
+
.login-container h2 {
|
26 |
+
margin-bottom: 25px;
|
27 |
+
text-align: center;
|
28 |
+
color: #333;
|
29 |
+
font-weight: 600;
|
30 |
+
}
|
31 |
+
.form-control:focus {
|
32 |
+
border-color: #0d6efd;
|
33 |
+
box-shadow: 0 0 0 0.2rem rgba(13,110,253,.25);
|
34 |
+
}
|
35 |
+
.btn-primary {
|
36 |
+
background-color: #0d6efd;
|
37 |
+
border-color: #0d6efd;
|
38 |
+
transition: background-color 0.2s;
|
39 |
+
}
|
40 |
+
.btn-primary:hover {
|
41 |
+
background-color: #0b5ed7;
|
42 |
+
border-color: #0a58ca;
|
43 |
+
}
|
44 |
+
.alert {
|
45 |
+
margin-top: 20px;
|
46 |
+
font-size: 0.9rem;
|
47 |
+
border-radius: 6px;
|
48 |
+
}
|
49 |
+
label {
|
50 |
+
font-weight: 500;
|
51 |
+
color: #555;
|
52 |
+
}
|
53 |
+
</style>
|
54 |
+
</head>
|
55 |
+
<body>
|
56 |
+
<div class="login-container">
|
57 |
+
<h2>Panel Login</h2>
|
58 |
+
<form id="loginForm">
|
59 |
+
<div class="mb-3">
|
60 |
+
<label for="username" class="form-label">Username</label>
|
61 |
+
<input type="text" class="form-control" id="username" name="user" required>
|
62 |
+
</div>
|
63 |
+
<div class="mb-4">
|
64 |
+
<label for="password" class="form-label">Password</label>
|
65 |
+
<input type="password" class="form-control" id="password" name="pass" required>
|
66 |
+
</div>
|
67 |
+
<button type="submit" class="btn btn-primary w-100 py-2">Login</button>
|
68 |
+
</form>
|
69 |
+
<div id="message" class="alert d-none mt-3" role="alert"></div>
|
70 |
+
</div>
|
71 |
+
|
72 |
+
<script>
|
73 |
+
const loginForm = document.getElementById('loginForm');
|
74 |
+
const messageDiv = document.getElementById('message');
|
75 |
+
|
76 |
+
loginForm.addEventListener('submit', async (event) => {
|
77 |
+
event.preventDefault();
|
78 |
+
messageDiv.classList.add('d-none');
|
79 |
+
messageDiv.textContent = '';
|
80 |
+
messageDiv.className = 'alert d-none mt-3'; // Reset classes
|
81 |
+
|
82 |
+
const formData = new FormData(loginForm);
|
83 |
+
const data = Object.fromEntries(formData.entries());
|
84 |
+
|
85 |
+
try {
|
86 |
+
const response = await fetch('/private/server/exocore/web/panel', {
|
87 |
+
method: 'POST',
|
88 |
+
headers: {
|
89 |
+
'Content-Type': 'application/json',
|
90 |
+
},
|
91 |
+
body: JSON.stringify(data),
|
92 |
+
});
|
93 |
+
|
94 |
+
const result = await response.json();
|
95 |
+
|
96 |
+
if (response.ok && result.status === 'success') {
|
97 |
+
messageDiv.textContent = result.message || 'Login successful!';
|
98 |
+
messageDiv.classList.add('alert-success');
|
99 |
+
localStorage.setItem('panelLogin', 'success');
|
100 |
+
window.location.href = "/private/server/exocore/web/public/login"
|
101 |
+
console.log('Login status saved to localStorage: panelLogin = success');
|
102 |
+
} else {
|
103 |
+
messageDiv.textContent = result.message || `Login failed (Status: ${response.status})`;
|
104 |
+
messageDiv.classList.add('alert-danger');
|
105 |
+
}
|
106 |
+
} catch (error) {
|
107 |
+
console.error('Login submission error:', error);
|
108 |
+
messageDiv.textContent = 'An error occurred while trying to log in. Please check the console and try again.';
|
109 |
+
messageDiv.classList.add('alert-danger');
|
110 |
+
}
|
111 |
+
messageDiv.classList.remove('d-none');
|
112 |
+
});
|
113 |
+
</script>
|
114 |
+
</body>
|
115 |
+
</html>
|
exocore-web/public/plans.jsx
ADDED
@@ -0,0 +1,418 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, For, Show } from 'solid-js';
|
3 |
+
|
4 |
+
const PixelIcon = ({ color }) => (
|
5 |
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="24" height="24" style={{ "image-rendering": "pixelated", fill: color || "currentColor" }}>
|
6 |
+
<path d="M2 0H14V2H16V14H14V16H2V14H0V2H2V0ZM4 4V12H12V4H4Z" />
|
7 |
+
<path d="M6 6H10V10H6V6Z" />
|
8 |
+
</svg>
|
9 |
+
);
|
10 |
+
|
11 |
+
const planStylesConfig = {
|
12 |
+
"Core Access": {
|
13 |
+
textGrad1: '#D0A9F5', textGrad2: '#E8D4F7', cardGrad1: '#6A0DAD', cardGrad2: '#A74AC7',
|
14 |
+
cardBorder: '#4B0082', textColor: '#FFFFFF', iconFill: '#E8D4F7', glowColor: '#E0BBE4'
|
15 |
+
},
|
16 |
+
"Prime Core": {
|
17 |
+
textGrad1: '#FFEB3B', textGrad2: '#FFF59D', cardGrad1: '#FBC02D', cardGrad2: '#FFD700',
|
18 |
+
cardBorder: '#B98B00', textColor: '#1A1A1A', iconFill: '#424242', glowColor: '#FFFACD'
|
19 |
+
},
|
20 |
+
"Alpha Core": {
|
21 |
+
textGrad1: '#00BCD4', textGrad2: '#80DEEA', cardGrad1: '#03A9F4', cardGrad2: '#4FC3F7',
|
22 |
+
cardBorder: '#0277BD', textColor: '#FFFFFF', iconFill: '#B2EBF2', glowColor: '#80DEEA'
|
23 |
+
},
|
24 |
+
"EXO Elite": {
|
25 |
+
textGrad1: '#F44336', textGrad2: '#FF8A80', cardGrad1: '#D32F2F', cardGrad2: '#E57373',
|
26 |
+
cardBorder: '#9A0007', textColor: '#FFFFFF', iconFill: '#FFCDD2', glowColor: '#FF8A80'
|
27 |
+
},
|
28 |
+
"Hacker Core": {
|
29 |
+
textGrad1: '#4CAF50', textGrad2: '#A5D6A7', cardGrad1: '#388E3C', cardGrad2: '#66BB6A',
|
30 |
+
cardBorder: '#1B5E20', textColor: '#FFFFFF', iconFill: '#C8E6C9', glowColor: '#A5D6A7'
|
31 |
+
}
|
32 |
+
};
|
33 |
+
const defaultPlanStyle = {
|
34 |
+
textGrad1: '#B0BEC5', textGrad2: '#ECEFF1', cardGrad1: '#455A64', cardGrad2: '#607D8B',
|
35 |
+
cardBorder: '#263238', textColor: '#FFFFFF', iconFill: '#ECEFF1', glowColor: '#90A4AE'
|
36 |
+
};
|
37 |
+
|
38 |
+
const countryCurrencyMap = {
|
39 |
+
"Afghanistan": "AFN", "Albania": "ALL", "Algeria": "DZD", "Angola": "AOA",
|
40 |
+
"Argentina": "ARS", "Armenia": "AMD", "Australia": "AUD", "Austria": "EUR", "Azerbaijan": "AZN",
|
41 |
+
"Bahamas": "BSD", "Bahrain": "BHD", "Bangladesh": "BDT", "Barbados": "BBD", "Belarus": "BYN",
|
42 |
+
"Belgium": "EUR", "Belize": "BZD", "Benin": "XOF", "Bhutan": "BTN", "Bolivia": "BOB",
|
43 |
+
"Bosnia and Herzegovina": "BAM", "Botswana": "BWP", "Brazil": "BRL", "Brunei": "BND",
|
44 |
+
"Bulgaria": "BGN", "Burkina Faso": "XOF", "Burundi": "BIF", "Cambodia": "KHR", "Cameroon": "XAF",
|
45 |
+
"Canada": "CAD", "Cape Verde": "CVE", "Central African Republic": "XAF", "Chad": "XAF",
|
46 |
+
"Chile": "CLP", "China": "CNY", "Colombia": "COP", "Comoros": "KMF", "Congo, Dem. Rep.": "CDF",
|
47 |
+
"Congo, Rep.": "XAF", "Costa Rica": "CRC", "Cote d'Ivoire": "XOF", "Croatia": "EUR",
|
48 |
+
"Cuba": "CUP", "Cyprus": "EUR", "Czech Republic": "CZK", "Denmark": "DKK", "Djibouti": "DJF",
|
49 |
+
"Dominican Republic": "DOP", "Ecuador": "USD", "Egypt": "EGP", "El Salvador": "USD",
|
50 |
+
"Equatorial Guinea": "XAF", "Eritrea": "ERN", "Estonia": "EUR", "Eswatini": "SZL", "Ethiopia": "ETB",
|
51 |
+
"Fiji": "FJD", "Finland": "EUR", "France": "EUR", "Gabon": "XAF", "Gambia": "GMD",
|
52 |
+
"Georgia": "GEL", "Germany": "EUR", "Ghana": "GHS", "Greece": "EUR", "Guatemala": "GTQ",
|
53 |
+
"Guinea": "GNF", "Guinea-Bissau": "XOF", "Guyana": "GYD", "Haiti": "HTG", "Honduras": "HNL",
|
54 |
+
"Hong Kong": "HKD", "Hungary": "HUF", "Iceland": "ISK", "India": "INR", "Indonesia": "IDR",
|
55 |
+
"Iran": "IRR", "Iraq": "IQD", "Ireland": "EUR", "Israel": "ILS", "Italy": "EUR", "Jamaica": "JMD",
|
56 |
+
"Japan": "JPY", "Jordan": "JOD", "Kazakhstan": "KZT", "Kenya": "KES", "Kiribati": "AUD",
|
57 |
+
"Korea, North": "KPW", "Korea, South": "KRW", "Kuwait": "KWD", "Kyrgyzstan": "KGS", "Laos": "LAK",
|
58 |
+
"Latvia": "EUR", "Lebanon": "LBP", "Lesotho": "LSL", "Liberia": "LRD", "Libya": "LYD",
|
59 |
+
"Liechtenstein": "CHF", "Lithuania": "EUR", "Luxembourg": "EUR", "Macao": "MOP", "Madagascar": "MGA",
|
60 |
+
"Malawi": "MWK", "Malaysia": "MYR", "Maldives": "MVR", "Mali": "XOF", "Malta": "EUR",
|
61 |
+
"Mauritania": "MRU", "Mauritius": "MUR", "Mexico": "MXN", "Micronesia": "USD", "Moldova": "MDL",
|
62 |
+
"Monaco": "EUR", "Mongolia": "MNT", "Montenegro": "EUR", "Morocco": "MAD", "Mozambique": "MZN",
|
63 |
+
"Myanmar": "MMK", "Namibia": "NAD", "Nauru": "AUD", "Nepal": "NPR", "Netherlands": "EUR",
|
64 |
+
"New Zealand": "NZD", "Nicaragua": "NIO", "Niger": "XOF", "Nigeria": "NGN", "North Macedonia": "MKD",
|
65 |
+
"Norway": "NOK", "Oman": "OMR", "Pakistan": "PKR", "Palau": "USD", "Panama": "PAB",
|
66 |
+
"Papua New Guinea": "PGK", "Paraguay": "PYG", "Peru": "PEN", "Philippines": "PHP",
|
67 |
+
"Poland": "PLN", "Portugal": "EUR", "Puerto Rico": "USD", "Qatar": "QAR", "Romania": "RON",
|
68 |
+
"Russia": "RUB", "Rwanda": "RWF", "Samoa": "WST", "San Marino": "EUR", "Sao Tome and Principe": "STN",
|
69 |
+
"Saudi Arabia": "SAR", "Senegal": "XOF", "Serbia": "RSD", "Seychelles": "SCR", "Sierra Leone": "SLL",
|
70 |
+
"Singapore": "SGD", "Slovakia": "EUR", "Slovenia": "EUR", "Solomon Islands": "SBD", "Somalia": "SOS",
|
71 |
+
"South Africa": "ZAR", "South Sudan": "SSP", "Spain": "EUR", "Sri Lanka": "LKR", "Sudan": "SDG",
|
72 |
+
"Suriname": "SRD", "Sweden": "SEK", "Switzerland": "CHF", "Syria": "SYP", "Taiwan": "TWD",
|
73 |
+
"Tajikistan": "TJS", "Tanzania": "TZS", "Thailand": "THB", "Timor-Leste": "USD", "Togo": "XOF",
|
74 |
+
"Tonga": "TOP", "Trinidad and Tobago": "TTD", "Tunisia": "TND", "Turkey": "TRY", "Turkmenistan": "TMT",
|
75 |
+
"Tuvalu": "AUD", "Uganda": "UGX", "Ukraine": "UAH", "United Arab Emirates": "AED",
|
76 |
+
"United Kingdom": "GBP", "United States": "USD", "Uruguay": "UYU", "Uzbekistan": "UZS",
|
77 |
+
"Vanuatu": "VUV", "Venezuela": "VES", "Vietnam": "VND", "Yemen": "YER", "Zambia": "ZMW", "Zimbabwe": "ZWL"
|
78 |
+
};
|
79 |
+
|
80 |
+
const currencySymbolsMap = {
|
81 |
+
"AFN": "؋", "ALL": "L", "DZD": "د.ج", "AOA": "Kz", "ARS": "$", "AMD": "֏", "AUD": "A$",
|
82 |
+
"AZN": "₼", "BSD": "B$", "BHD": ".د.ب", "BDT": "৳", "BBD": "Bds$", "BYN": "Br", "EUR": "€",
|
83 |
+
"BZD": "BZ$", "XOF": "CFA", "BTN": "Nu.", "BOB": "Bs.", "BAM": "KM", "BWP": "P", "BRL": "R$",
|
84 |
+
"BND": "B$", "BGN": "лв", "BIF": "FBu", "KHR": "៛", "XAF": "FCFA", "CAD": "C$", "CVE": "Esc",
|
85 |
+
"CLP": "CLP$", "CNY": "¥", "COP": "COL$", "KMF": "CF", "CDF": "FC", "CRC": "₡", "CUP": "$MN",
|
86 |
+
"CZK": "Kč", "DKK": "kr.", "DJF": "Fdj", "DOP": "RD$", "USD": "$", "EGP": "E£", "ERN": "Nfk",
|
87 |
+
"SZL": "L", "ETB": "Br", "FJD": "FJ$", "GMD": "D", "GEL": "₾", "GHS": "₵", "GTQ": "Q",
|
88 |
+
"GNF": "FG", "GYD": "G$", "HTG": "G", "HNL": "L", "HKD": "HK$", "HUF": "Ft", "ISK": "kr",
|
89 |
+
"INR": "₹", "IDR": "Rp", "IRR": "﷼", "IQD": "ع.د", "ILS": "₪", "JMD": "J$", "JPY": "¥",
|
90 |
+
"JOD": "JD", "KZT": "₸", "KES": "KSh", "KPW": "₩", "KRW": "₩", "KWD": "KD", "KGS": "сом",
|
91 |
+
"LAK": "₭", "LBP": "ل.ل", "LSL": "M", "LRD": "L$", "LYD": "LD", "CHF": "Fr.", "MOP": "MOP$",
|
92 |
+
"MGA": "Ar", "MWK": "MK", "MYR": "RM", "MVR": ".ރ", "MRU": "UM", "MUR": "₨", "MXN": "Mex$",
|
93 |
+
"MDL": "L", "MNT": "₮", "MAD": "د.م.", "MZN": "MT", "MMK": "K", "NAD": "N$", "NPR": "₨",
|
94 |
+
"NZD": "NZ$", "NIO": "C$", "NGN": "₦", "MKD": "ден", "NOK": "kr", "OMR": "﷼", "PKR": "₨",
|
95 |
+
"PAB": "B/.", "PGK": "K", "PYG": "₲", "PEN": "S/.", "PHP": "₱", "PLN": "zł", "QAR": "﷼",
|
96 |
+
"RON": "lei", "RUB": "₽", "RWF": "RF", "WST": "WS$", "STN": "Db", "SAR": "﷼", "RSD": "дин.",
|
97 |
+
"SCR": "₨", "SLL": "Le", "SGD": "S$", "SBD": "SI$", "SOS": "Sh.So.", "ZAR": "R", "SSP": "£",
|
98 |
+
"LKR": "Rs", "SDG": "ج.س.", "SRD": "$", "SEK": "kr", "SYP": "£S", "TWD": "NT$", "TJS": "ЅМ",
|
99 |
+
"TZS": "TSh", "THB": "฿", "TOP": "T$", "TTD": "TT$", "TND": "د.ت", "TRY": "₺", "TMT": "m",
|
100 |
+
"UGX": "USh", "UAH": "₴", "AED": "د.إ", "GBP": "£", "UYU": "$U", "UZS": "сўм", "VUV": "VT",
|
101 |
+
"VES": "Bs.S.", "VND": "₫", "YER": "﷼", "ZMW": "ZK", "ZWL": "$"
|
102 |
+
};
|
103 |
+
|
104 |
+
function App() {
|
105 |
+
const [loading, setLoading] = createSignal(true);
|
106 |
+
const [status, setStatus] = createSignal('');
|
107 |
+
const [userData, setUserData] = createSignal(null);
|
108 |
+
const [plans, setPlans] = createSignal([]);
|
109 |
+
const [initialLoadComplete, setInitialLoadComplete] = createSignal(false);
|
110 |
+
|
111 |
+
const [targetCurrency, setTargetCurrency] = createSignal('USD');
|
112 |
+
const [exchangeRate, setExchangeRate] = createSignal(1);
|
113 |
+
const [currencySymbol, setCurrencySymbol] = createSignal('$');
|
114 |
+
|
115 |
+
const getToken = () => localStorage.getItem('exocore-token') || '';
|
116 |
+
const getCookies = () => localStorage.getItem('exocore-cookies') || '';
|
117 |
+
|
118 |
+
async function fetchExchangeRatesForUser(countryName) {
|
119 |
+
const currencyCode = countryCurrencyMap[countryName] || 'USD';
|
120 |
+
const symbol = currencySymbolsMap[currencyCode] || (currencyCode + ' ');
|
121 |
+
|
122 |
+
setTargetCurrency(currencyCode);
|
123 |
+
setCurrencySymbol(symbol);
|
124 |
+
|
125 |
+
if (currencyCode === 'USD') {
|
126 |
+
setExchangeRate(1);
|
127 |
+
return;
|
128 |
+
}
|
129 |
+
try {
|
130 |
+
const response = await fetch(`https://api.frankfurter.app/latest?from=USD&to=${currencyCode}`);
|
131 |
+
if (!response.ok) throw new Error(`API error: ${response.status}`);
|
132 |
+
const data = await response.json();
|
133 |
+
if (data.rates && data.rates[currencyCode]) {
|
134 |
+
setExchangeRate(data.rates[currencyCode]);
|
135 |
+
} else {
|
136 |
+
setExchangeRate(1); setTargetCurrency('USD'); setCurrencySymbol('$');
|
137 |
+
}
|
138 |
+
} catch (error) {
|
139 |
+
setStatus('Could not load local currency. Displaying prices in USD.');
|
140 |
+
setExchangeRate(1); setTargetCurrency('USD'); setCurrencySymbol('$');
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
async function fetchPlans() {
|
145 |
+
try {
|
146 |
+
const proxiedUrl = `https://api.allorigins.win/raw?url=${encodeURIComponent('https://pastebin.com/raw/zddjxUGr')}`;
|
147 |
+
const res = await fetch(proxiedUrl);
|
148 |
+
if (!res.ok) throw new Error(`Failed to fetch plans: ${res.status}`);
|
149 |
+
const data = await res.json();
|
150 |
+
if (Array.isArray(data)) {
|
151 |
+
setPlans(data);
|
152 |
+
} else {
|
153 |
+
setPlans([]);
|
154 |
+
}
|
155 |
+
} catch (err) {
|
156 |
+
setStatus('Failed to load subscription plans. Please try refreshing.');
|
157 |
+
setPlans([]);
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
async function fetchUserInfo() {
|
162 |
+
setLoading(true); setStatus('');
|
163 |
+
const token = getToken(); const cookies = getCookies();
|
164 |
+
|
165 |
+
if (!token || !cookies) {
|
166 |
+
setLoading(false); setInitialLoadComplete(true);
|
167 |
+
window.location.href = '/private/server/exocore/web/public/login'; return;
|
168 |
+
}
|
169 |
+
try {
|
170 |
+
const res = await fetch('/private/server/exocore/web/userinfo', {
|
171 |
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
172 |
+
body: JSON.stringify({ token, cookies }),
|
173 |
+
});
|
174 |
+
if (!res.ok) {
|
175 |
+
let errorMsg = `Server error: ${res.status}`;
|
176 |
+
try { const errorData = await res.json(); errorMsg = errorData.message || errorMsg; } catch (e) {}
|
177 |
+
throw new Error(errorMsg);
|
178 |
+
}
|
179 |
+
const data = await res.json();
|
180 |
+
|
181 |
+
if (data.data?.user && data.data.user.verified === 'success') {
|
182 |
+
setUserData(data.data.user);
|
183 |
+
setStatus('');
|
184 |
+
if (data.data.user.country) {
|
185 |
+
await fetchExchangeRatesForUser(data.data.user.country);
|
186 |
+
} else {
|
187 |
+
setTargetCurrency('USD'); setExchangeRate(1); setCurrencySymbol('$');
|
188 |
+
}
|
189 |
+
await fetchPlans();
|
190 |
+
} else {
|
191 |
+
setUserData(null); setPlans([]);
|
192 |
+
setStatus(data.message || 'User verification failed. Redirecting to login...');
|
193 |
+
localStorage.removeItem('exocore-token'); localStorage.removeItem('exocore-cookies');
|
194 |
+
setTimeout(() => { window.location.href = '/private/server/exocore/web/public/login'; }, 2500);
|
195 |
+
}
|
196 |
+
} catch (err) {
|
197 |
+
setUserData(null); setPlans([]);
|
198 |
+
setStatus('Failed to fetch user info: ' + (err.message || 'Unknown error') + '. Redirecting...');
|
199 |
+
localStorage.removeItem('exocore-token'); localStorage.removeItem('exocore-cookies');
|
200 |
+
setTimeout(() => { window.location.href = '/private/server/exocore/web/public/login'; }, 2500);
|
201 |
+
} finally {
|
202 |
+
setLoading(false); setInitialLoadComplete(true);
|
203 |
+
}
|
204 |
+
}
|
205 |
+
|
206 |
+
onMount(() => {
|
207 |
+
const fontLink = document.createElement('link');
|
208 |
+
fontLink.href = 'https://fonts.googleapis.com/css2?family=Pixelify+Sans:wght@400;700&display=swap';
|
209 |
+
fontLink.rel = 'stylesheet';
|
210 |
+
document.head.appendChild(fontLink);
|
211 |
+
|
212 |
+
document.body.style.margin = '0';
|
213 |
+
document.body.style.fontFamily = "'Pixelify Sans', sans-serif";
|
214 |
+
document.body.style.background = 'linear-gradient(160deg, #1A073C 0%, #2C0F3A 50%, #4A1B4D 100%)';
|
215 |
+
document.body.style.color = '#EAEAEA';
|
216 |
+
document.body.style.setProperty('image-rendering', 'pixelated', 'important');
|
217 |
+
document.body.style.setProperty('-webkit-font-smoothing', 'none', 'important');
|
218 |
+
document.body.style.setProperty('font-smooth', 'never', 'important');
|
219 |
+
|
220 |
+
fetchUserInfo();
|
221 |
+
});
|
222 |
+
|
223 |
+
const handleBuyClick = () => {
|
224 |
+
window.location.href = 'https://www.facebook.com/share/16TsfAhA3z/';
|
225 |
+
};
|
226 |
+
|
227 |
+
return (
|
228 |
+
<div class="main-container">
|
229 |
+
<style>
|
230 |
+
{`
|
231 |
+
* {
|
232 |
+
image-rendering: pixelated !important;
|
233 |
+
-ms-interpolation-mode: nearest-neighbor !important;
|
234 |
+
-webkit-font-smoothing: none !important;
|
235 |
+
font-smooth: never !important;
|
236 |
+
box-sizing: border-box;
|
237 |
+
}
|
238 |
+
body, input, button, textarea, select {
|
239 |
+
font-family: 'Pixelify Sans', sans-serif !important;
|
240 |
+
}
|
241 |
+
.main-container {
|
242 |
+
padding: 2vh 2vw; display: flex; flex-direction: column;
|
243 |
+
justify-content: center; align-items: center; min-height: 100vh;
|
244 |
+
animation: fadeIn 0.7s 0.1s ease forwards; opacity: 0;
|
245 |
+
}
|
246 |
+
@keyframes fadeIn { to { opacity: 1; } }
|
247 |
+
.greeting {
|
248 |
+
font-size: 2.3rem; font-weight: 700; color: #00EFFF;
|
249 |
+
margin-bottom: 1.5rem; text-shadow: 2px 2px 0px #110522;
|
250 |
+
letter-spacing: 1px;
|
251 |
+
}
|
252 |
+
.status-box {
|
253 |
+
margin-bottom: 1rem; padding: 10px 15px; border-radius: 2px;
|
254 |
+
color: #FEE2E2; background-color: #7F1D1D; border: 2px solid #5F1212;
|
255 |
+
box-shadow: 2px 2px 0px #400A0A; font-weight: 700;
|
256 |
+
max-width: 500px; width: 90%; text-align: center;
|
257 |
+
font-size: 0.8rem; line-height: 1.3; letter-spacing: 0.5px;
|
258 |
+
}
|
259 |
+
.loading-text {
|
260 |
+
font-size: 1.2rem; color: #909090; font-weight: 700; letter-spacing: 0.5px;
|
261 |
+
}
|
262 |
+
.content-box {
|
263 |
+
width: 100%; max-width: 860px; min-height: 350px;
|
264 |
+
background-color: rgba(10, 2, 20, 0.9);
|
265 |
+
border-radius: 3px; border: 2px solid #2A0B4A;
|
266 |
+
box-shadow: 3px 3px 0px #0A0314;
|
267 |
+
padding: 1.5rem; text-align: center; user-select: none;
|
268 |
+
}
|
269 |
+
.plans-outer-container { width: 100%; }
|
270 |
+
.plans-container {
|
271 |
+
display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
272 |
+
gap: 1.3rem; width: 100%; margin-top: 1rem;
|
273 |
+
}
|
274 |
+
.plan-card {
|
275 |
+
display: flex; align-items: flex-start; padding: 12px;
|
276 |
+
border-radius: 3px; border: 2px solid var(--card-border);
|
277 |
+
color: var(--card-text);
|
278 |
+
background: linear-gradient(145deg, var(--card-grad1), var(--card-grad2));
|
279 |
+
animation: cardGlow 2.5s infinite alternate;
|
280 |
+
transition: transform 0.15s ease-out;
|
281 |
+
}
|
282 |
+
@keyframes cardGlow {
|
283 |
+
from { box-shadow: 2px 2px 0px var(--card-border), 0 0 4px 0px var(--glow-color); }
|
284 |
+
to { box-shadow: 2px 2px 0px var(--card-border), 0 0 14px 3px var(--glow-color); }
|
285 |
+
}
|
286 |
+
.plan-icon-area {
|
287 |
+
margin-right: 10px; flex-shrink: 0; padding-top: 2px;
|
288 |
+
width: 24px; height: 24px;
|
289 |
+
}
|
290 |
+
.plan-details {
|
291 |
+
display: flex; flex-direction: column; flex-grow: 1; text-align: left;
|
292 |
+
}
|
293 |
+
.plan-name {
|
294 |
+
font-size: 1.3rem; font-weight: 700; line-height: 1.15; margin-bottom: 5px;
|
295 |
+
letter-spacing: 0.5px;
|
296 |
+
background: linear-gradient(60deg, var(--text-grad1, #FFFDE7), var(--text-grad2, #FFF59D));
|
297 |
+
-webkit-background-clip: text; background-clip: text; color: transparent;
|
298 |
+
padding-bottom: 1px;
|
299 |
+
}
|
300 |
+
.plan-price {
|
301 |
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
|
302 |
+
font-size: 1.05rem;
|
303 |
+
font-weight: 500; /* Medium weight for standard font */
|
304 |
+
margin-bottom: 10px;
|
305 |
+
opacity: 0.95; /* Slightly more opaque */
|
306 |
+
color: var(--card-text);
|
307 |
+
letter-spacing: 0.1px; /* More standard letter spacing */
|
308 |
+
image-rendering: auto !important;
|
309 |
+
-webkit-font-smoothing: auto !important; /* Enable smoothing for standard font */
|
310 |
+
font-smooth: auto !important; /* Enable smoothing for standard font */
|
311 |
+
}
|
312 |
+
.buy-button {
|
313 |
+
background-color: rgba(0,0,0,0.4); color: var(--card-text);
|
314 |
+
border: 2px solid var(--card-text); opacity: 0.95; padding: 7px 14px;
|
315 |
+
border-radius: 2px; box-shadow: 1px 1px 0px rgba(0,0,0,0.6);
|
316 |
+
text-transform: uppercase; font-weight: 700; font-size: 0.8rem;
|
317 |
+
letter-spacing: 0.5px; cursor: pointer; align-self: flex-start;
|
318 |
+
transition: transform 0.08s linear, background-color 0.08s linear;
|
319 |
+
}
|
320 |
+
.buy-button:hover { background-color: rgba(20,20,20,0.55); opacity: 1; }
|
321 |
+
.buy-button:active { transform: translate(1px, 1px); box-shadow: 0px 0px 0px rgba(0,0,0,0.6); }
|
322 |
+
@media (max-width: 600px) {
|
323 |
+
.greeting { font-size: 1.9rem; }
|
324 |
+
.content-box { padding: 1rem; }
|
325 |
+
.plans-container { grid-template-columns: 1fr; gap: 1rem; }
|
326 |
+
.plan-name { font-size: 1.15rem; }
|
327 |
+
.plan-price { font-size: 0.95rem; } /* Adjust if needed */
|
328 |
+
.buy-button { font-size: 0.75rem; padding: 6px 10px; }
|
329 |
+
}
|
330 |
+
`}
|
331 |
+
</style>
|
332 |
+
|
333 |
+
<Show when={status() && !loading()}>
|
334 |
+
<div class="status-box">{status()}</div>
|
335 |
+
</Show>
|
336 |
+
|
337 |
+
<div class="content-box">
|
338 |
+
<Show when={loading() && !initialLoadComplete()}>
|
339 |
+
<p class="loading-text">LOADING USER DATA...</p>
|
340 |
+
</Show>
|
341 |
+
|
342 |
+
<Show when={!loading() && initialLoadComplete() && userData()}>
|
343 |
+
<div class="greeting">
|
344 |
+
HELLO, {(userData()?.user || userData()?.user?.user || userData()?.data?.user?.user || 'USER').toUpperCase()}!
|
345 |
+
</div>
|
346 |
+
|
347 |
+
<Show when={plans().length > 0}>
|
348 |
+
<div class="plans-outer-container">
|
349 |
+
<div class="plans-container">
|
350 |
+
<For each={plans()}>
|
351 |
+
{(planItem) => {
|
352 |
+
if (!planItem || typeof planItem.plan !== 'string') {
|
353 |
+
return null;
|
354 |
+
}
|
355 |
+
const style = planStylesConfig[planItem.plan] || defaultPlanStyle;
|
356 |
+
|
357 |
+
let displayPrice = planItem.price || "$0";
|
358 |
+
const originalPriceStr = planItem.price || "$0";
|
359 |
+
const numericUsdPrice = parseFloat(originalPriceStr.replace('$', ''));
|
360 |
+
|
361 |
+
if (!isNaN(numericUsdPrice) && exchangeRate() !== null && exchangeRate() !== undefined) {
|
362 |
+
if (numericUsdPrice === 0 && targetCurrency() !== 'USD') {
|
363 |
+
displayPrice = `${currencySymbol()}0`;
|
364 |
+
} else if (numericUsdPrice === 0 && targetCurrency() === 'USD') {
|
365 |
+
displayPrice = `$0`;
|
366 |
+
}
|
367 |
+
else {
|
368 |
+
const convertedPrice = numericUsdPrice * exchangeRate();
|
369 |
+
let formattedConvertedPrice;
|
370 |
+
if (targetCurrency() === 'JPY' || targetCurrency() === 'KRW') {
|
371 |
+
formattedConvertedPrice = Math.round(convertedPrice);
|
372 |
+
} else {
|
373 |
+
formattedConvertedPrice = convertedPrice.toFixed(2);
|
374 |
+
}
|
375 |
+
displayPrice = `${currencySymbol()}${formattedConvertedPrice}`;
|
376 |
+
}
|
377 |
+
}
|
378 |
+
|
379 |
+
return (
|
380 |
+
<div
|
381 |
+
class="plan-card"
|
382 |
+
style={{
|
383 |
+
'--card-grad1': style.cardGrad1, '--card-grad2': style.cardGrad2,
|
384 |
+
'--card-border': style.cardBorder, '--card-text': style.textColor,
|
385 |
+
'--icon-color': style.iconFill, '--text-grad1': style.textGrad1,
|
386 |
+
'--text-grad2': style.textGrad2, '--glow-color': style.glowColor
|
387 |
+
}}
|
388 |
+
>
|
389 |
+
<div class="plan-icon-area">
|
390 |
+
<PixelIcon color={style.iconFill} />
|
391 |
+
</div>
|
392 |
+
<div class="plan-details">
|
393 |
+
<div class="plan-name">{(planItem.plan || "PLAN").toUpperCase()}</div>
|
394 |
+
<div class="plan-price">{displayPrice}</div>
|
395 |
+
<button class="buy-button" onClick={handleBuyClick}>BUY</button>
|
396 |
+
</div>
|
397 |
+
</div>
|
398 |
+
);
|
399 |
+
}}
|
400 |
+
</For>
|
401 |
+
</div>
|
402 |
+
</div>
|
403 |
+
</Show>
|
404 |
+
<Show when={plans().length === 0 && !status().includes('Failed to load subscription plans')}>
|
405 |
+
<p style={{color: '#A0A0A0', 'font-weight': '700', 'letter-spacing':'0.5px', 'font-size': '0.9rem'}}>NO PLANS AVAILABLE.</p>
|
406 |
+
</Show>
|
407 |
+
</Show>
|
408 |
+
|
409 |
+
<Show when={!loading() && initialLoadComplete() && !userData() && !status().includes('Redirecting')}>
|
410 |
+
<p style={{color: '#B0B0B0', 'font-weight': '700', 'letter-spacing':'0.5px', 'font-size': '0.9rem'}}>CANNOT LOAD USER. TRY LOGIN.</p>
|
411 |
+
</Show>
|
412 |
+
</div>
|
413 |
+
</div>
|
414 |
+
);
|
415 |
+
}
|
416 |
+
|
417 |
+
render(() => <App />, document.getElementById('app'));
|
418 |
+
|
exocore-web/public/profile.jsx
ADDED
@@ -0,0 +1,527 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, Show, For } from 'solid-js';
|
3 |
+
|
4 |
+
const IconPencil = () => <svg class="icon" viewBox="0 0 24 24" fill="currentColor" width="1em" height="1em"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" /></svg>;
|
5 |
+
const IconAdd = () => <svg class="icon" viewBox="0 0 24 24" fill="currentColor" width="1em" height="1em" style="vertical-align: middle; margin-right: 4px;"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" /></svg>;
|
6 |
+
const IconCode = () => <svg class="icon" viewBox="0 0 24 24" fill="currentColor" width="1em" height="1em"><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg>;
|
7 |
+
|
8 |
+
const getBasename = (filePath) => {
|
9 |
+
if (!filePath) return '';
|
10 |
+
const parts = filePath.split(/[\\/]/);
|
11 |
+
return parts[parts.length - 1] || '';
|
12 |
+
};
|
13 |
+
|
14 |
+
const getSkillIcon = (extension, displayName) => {
|
15 |
+
const iconPath = `/private/server/exocore/web/public/icons/${extension.toLowerCase()}.svg`;
|
16 |
+
return (
|
17 |
+
<img
|
18 |
+
src={iconPath}
|
19 |
+
alt={`${displayName} icon`}
|
20 |
+
class="skill-icon"
|
21 |
+
onError={(e) => {
|
22 |
+
e.currentTarget.style.display = 'none';
|
23 |
+
e.currentTarget.parentNode.querySelector('.fallback-icon').style.display = 'block';
|
24 |
+
}}
|
25 |
+
/>
|
26 |
+
);
|
27 |
+
};
|
28 |
+
|
29 |
+
const planStylesConfig = {
|
30 |
+
"Core Access": {
|
31 |
+
textGrad1: '#D0A9F5', textGrad2: '#E8D4F7', cardGrad1: '#6A0DAD', cardGrad2: '#A74AC7',
|
32 |
+
cardBorder: 'rgba(75, 0, 130, 0.8)', textColor: '#FFFFFF', iconFill: '#E8D4F7', glowColor: 'rgba(224, 187, 228, 0.3)'
|
33 |
+
},
|
34 |
+
"Prime Core": {
|
35 |
+
textGrad1: '#FFEB3B', textGrad2: '#FFF59D', cardGrad1: '#FBC02D', cardGrad2: '#FFD700',
|
36 |
+
cardBorder: 'rgba(185, 139, 0, 0.8)', textColor: '#1A1A1A', iconFill: '#424242', glowColor: 'rgba(255, 250, 205, 0.4)'
|
37 |
+
},
|
38 |
+
"Alpha Core": {
|
39 |
+
textGrad1: '#00BCD4', textGrad2: '#80DEEA', cardGrad1: '#03A9F4', cardGrad2: '#4FC3F7',
|
40 |
+
cardBorder: 'rgba(2, 119, 189, 0.8)', textColor: '#FFFFFF', iconFill: '#B2EBF2', glowColor: 'rgba(128, 222, 234, 0.3)'
|
41 |
+
},
|
42 |
+
"EXO Elite": {
|
43 |
+
textGrad1: '#F44336', textGrad2: '#FF8A80', cardGrad1: '#D32F2F', cardGrad2: '#E57373',
|
44 |
+
cardBorder: 'rgba(154, 0, 7, 0.8)', textColor: '#FFFFFF', iconFill: '#FFCDD2', glowColor: 'rgba(255, 138, 128, 0.3)'
|
45 |
+
},
|
46 |
+
"Hacker Core": {
|
47 |
+
textGrad1: '#4CAF50', textGrad2: '#A5D6A7', cardGrad1: '#000000', cardGrad2: '#388E3C',
|
48 |
+
cardBorder: 'rgba(27, 94, 32, 0.8)', textColor: '#00FF00', iconFill: '#C8E6C9', glowColor: 'rgba(165, 214, 167, 0.3)'
|
49 |
+
}
|
50 |
+
};
|
51 |
+
|
52 |
+
const defaultPlanStyle = {
|
53 |
+
textGrad1: '#B0BEC5', textGrad2: '#ECEFF1', cardGrad1: '#455A64', cardGrad2: '#607D8B',
|
54 |
+
cardBorder: 'rgba(38, 50, 56, 0.8)', textColor: '#FFFFFF', iconFill: '#ECEFF1', glowColor: 'rgba(144, 164, 174, 0.2)'
|
55 |
+
};
|
56 |
+
|
57 |
+
function App() {
|
58 |
+
const [loading, setLoading] = createSignal(true);
|
59 |
+
const [status, setStatus] = createSignal({ type: '', message: '' });
|
60 |
+
const [userData, setUserData] = createSignal(null);
|
61 |
+
const [editingBio, setEditingBio] = createSignal(false);
|
62 |
+
const [editingNickname, setEditingNickname] = createSignal(false);
|
63 |
+
const [nickname, setNickname] = createSignal('');
|
64 |
+
const [bio, setBio] = createSignal('');
|
65 |
+
const [modalOpen, setModalOpen] = createSignal(false);
|
66 |
+
const [modalAction, setModalAction] = createSignal(() => {});
|
67 |
+
const [projectSkills, setProjectSkills] = createSignal(null);
|
68 |
+
|
69 |
+
const avatarDimensions = {
|
70 |
+
mobile: { headerH: 170, avatarH: 110, overlap: 55 },
|
71 |
+
tablet: { headerH: 240, avatarH: 140, overlap: 70 },
|
72 |
+
desktop: { headerH: 280, avatarH: 160, overlap: 80 },
|
73 |
+
};
|
74 |
+
|
75 |
+
const getToken = () => localStorage.getItem('exocore-token') || '';
|
76 |
+
const getCookies = () => localStorage.getItem('exocore-cookies') || '';
|
77 |
+
|
78 |
+
async function fetchUserInfo() {
|
79 |
+
// Don't set loading to true here if it's a re-fetch,
|
80 |
+
// it will be handled by the calling function.
|
81 |
+
// setLoading(true);
|
82 |
+
const token = getToken();
|
83 |
+
const cookies = getCookies();
|
84 |
+
|
85 |
+
if (!token || !cookies) {
|
86 |
+
window.location.href = '/private/server/exocore/web/public/login';
|
87 |
+
return;
|
88 |
+
}
|
89 |
+
|
90 |
+
try {
|
91 |
+
const res = await fetch('/private/server/exocore/web/userinfo', {
|
92 |
+
method: 'POST',
|
93 |
+
headers: { 'Content-Type': 'application/json' },
|
94 |
+
body: JSON.stringify({ token, cookies }),
|
95 |
+
});
|
96 |
+
|
97 |
+
if (!res.ok) {
|
98 |
+
let errorMsg = `Server error: ${res.status}`;
|
99 |
+
try {
|
100 |
+
const errorData = await res.json();
|
101 |
+
errorMsg = errorData.message || errorMsg;
|
102 |
+
} catch (parseError) {}
|
103 |
+
throw new Error(errorMsg);
|
104 |
+
}
|
105 |
+
const data = await res.json();
|
106 |
+
if (data.data?.user && data.data.user.verified === 'success') {
|
107 |
+
setUserData(data.data.user);
|
108 |
+
// fetch skills only if user data is successfully fetched
|
109 |
+
fetchSkills();
|
110 |
+
} else {
|
111 |
+
setUserData(null);
|
112 |
+
setStatus({ type: 'error', message: data.message || 'User verification failed. Redirecting...' });
|
113 |
+
setTimeout(() => { window.location.href = '/private/server/exocore/web/public/login'; }, 2500);
|
114 |
+
}
|
115 |
+
} catch (err) {
|
116 |
+
setUserData(null);
|
117 |
+
setStatus({ type: 'error', message: 'Failed to fetch user info: ' + err.message + '. Redirecting...' });
|
118 |
+
setTimeout(() => { window.location.href = '/private/server/exocore/web/public/login'; }, 2500);
|
119 |
+
} finally {
|
120 |
+
setLoading(false);
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
async function fetchSkills() {
|
125 |
+
try {
|
126 |
+
const skillsRes = await fetch('/private/server/exocore/web/skills', {
|
127 |
+
method: 'POST',
|
128 |
+
headers: { 'Content-Type': 'application/json' },
|
129 |
+
body: JSON.stringify({})
|
130 |
+
});
|
131 |
+
|
132 |
+
if (skillsRes.ok) {
|
133 |
+
const skillsData = await skillsRes.json();
|
134 |
+
setProjectSkills(skillsData && skillsData.length > 0 ? skillsData[0] : null);
|
135 |
+
} else {
|
136 |
+
console.error("Failed to fetch skills:", skillsRes.status);
|
137 |
+
setProjectSkills(null);
|
138 |
+
}
|
139 |
+
} catch (skillsErr) {
|
140 |
+
console.error("Error fetching skills:", skillsErr);
|
141 |
+
setProjectSkills(null);
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
async function handleUpdate(field, value, endEditStateFn) {
|
146 |
+
setLoading(true);
|
147 |
+
setModalOpen(false); // Close modal if open
|
148 |
+
|
149 |
+
const token = getToken();
|
150 |
+
const cookies = getCookies();
|
151 |
+
|
152 |
+
try {
|
153 |
+
const res = await fetch('/private/server/exocore/web/userinfoEdit', {
|
154 |
+
method: 'POST',
|
155 |
+
headers: { 'Content-Type': 'application/json' },
|
156 |
+
body: JSON.stringify({ token, cookies, field, edit: value }),
|
157 |
+
});
|
158 |
+
|
159 |
+
const data = await res.json();
|
160 |
+
|
161 |
+
// Check if the response is NOT OK or if there's an explicit error message
|
162 |
+
if (!res.ok || data.success === false) {
|
163 |
+
throw new Error(data.message || 'An unknown error occurred.');
|
164 |
+
}
|
165 |
+
|
166 |
+
// SUCCESS!
|
167 |
+
setStatus({ type: 'success', message: data.message || 'Update successful!' });
|
168 |
+
setTimeout(() => setStatus({ type: '', message: '' }), 3000);
|
169 |
+
|
170 |
+
// Re-fetch the single source of truth to ensure UI is in sync.
|
171 |
+
await fetchUserInfo();
|
172 |
+
|
173 |
+
if (endEditStateFn) {
|
174 |
+
endEditStateFn(false);
|
175 |
+
}
|
176 |
+
|
177 |
+
} catch (err) {
|
178 |
+
setStatus({ type: 'error', message: 'Update failed: ' + err.message });
|
179 |
+
setTimeout(() => setStatus({ type: '', message: '' }), 3000);
|
180 |
+
} finally {
|
181 |
+
// Loading is set to false inside fetchUserInfo's finally block
|
182 |
+
// setLoading(false);
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
function openImageModal(field) {
|
187 |
+
setModalAction(() => () => {
|
188 |
+
const input = document.createElement('input');
|
189 |
+
input.type = 'file';
|
190 |
+
input.accept = 'image/*,.heic,.heif';
|
191 |
+
input.onchange = (e) => {
|
192 |
+
const file = e.target.files[0];
|
193 |
+
if (file) {
|
194 |
+
if (file.size > 10 * 1024 * 1024) { // 10MB limit
|
195 |
+
setStatus({ type: 'error', message: 'Max file size: 10MB.' });
|
196 |
+
setTimeout(() => setStatus({ type: '', message: '' }), 3000);
|
197 |
+
return;
|
198 |
+
}
|
199 |
+
const reader = new FileReader();
|
200 |
+
reader.onload = () => handleUpdate(field, reader.result);
|
201 |
+
reader.onerror = () => {
|
202 |
+
setStatus({ type: 'error', message: 'Error reading file.' });
|
203 |
+
setTimeout(() => setStatus({ type: '', message: '' }), 3000);
|
204 |
+
}
|
205 |
+
reader.readAsDataURL(file);
|
206 |
+
}
|
207 |
+
};
|
208 |
+
input.click();
|
209 |
+
});
|
210 |
+
setModalOpen(true);
|
211 |
+
}
|
212 |
+
|
213 |
+
onMount(() => {
|
214 |
+
setLoading(true);
|
215 |
+
fetchUserInfo();
|
216 |
+
});
|
217 |
+
|
218 |
+
const Spinner = () => <div class="spinner"></div>;
|
219 |
+
|
220 |
+
const activePlanStyles = () => {
|
221 |
+
const planName = userData()?.activePlan?.plan;
|
222 |
+
return planStylesConfig[planName] || defaultPlanStyle;
|
223 |
+
};
|
224 |
+
|
225 |
+
return (
|
226 |
+
<>
|
227 |
+
<style>{`
|
228 |
+
/* ... (Yung CSS mo dito, walang pagbabago) ... */
|
229 |
+
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
|
230 |
+
|
231 |
+
:root {
|
232 |
+
--bg-primary: #111217; --bg-secondary: #1a1b23; --bg-tertiary: #2a2c3b;
|
233 |
+
--text-primary: #e0e0e0; --text-secondary: #8a8f98; --accent-primary: #00aaff;
|
234 |
+
--accent-secondary: #0088cc; --success-color: #2ecc71; --error-color: #e74c3c;
|
235 |
+
--border-color: rgba(255, 255, 255, 0.1); --shadow-color: rgba(0, 0, 0, 0.5);
|
236 |
+
--radius-main: 16px; --radius-inner: 12px;
|
237 |
+
--font-body: 'Roboto', sans-serif;
|
238 |
+
|
239 |
+
--avatar-mobile-top: ${avatarDimensions.mobile.headerH - avatarDimensions.mobile.overlap}px;
|
240 |
+
--avatar-tablet-top: ${avatarDimensions.tablet.headerH - avatarDimensions.tablet.overlap}px;
|
241 |
+
--avatar-desktop-top: ${avatarDimensions.desktop.headerH - avatarDimensions.desktop.overlap}px;
|
242 |
+
}
|
243 |
+
|
244 |
+
body { background-color: var(--bg-primary); font-family: var(--font-body); color: var(--text-primary); margin: 0; }
|
245 |
+
.profile-container { display: flex; justify-content: center; align-items: flex-start; padding: 2rem 1rem; min-height: 100vh; box-sizing: border-box; }
|
246 |
+
.profile-card { background: var(--bg-secondary); border-radius: var(--radius-main); box-shadow: 0 15px 40px var(--shadow-color); width: 100%; max-width: 600px; position: relative; border: 1px solid var(--border-color); }
|
247 |
+
.profile-header { position: relative; height: ${avatarDimensions.mobile.headerH}px; border-top-left-radius: var(--radius-main); border-top-right-radius: var(--radius-main); overflow: hidden; }
|
248 |
+
.cover-photo { width: 100%; height: 100%; object-fit: cover; cursor: pointer; transition: transform 0.4s ease; }
|
249 |
+
.cover-photo:hover { transform: scale(1.05); }
|
250 |
+
.avatar { width: ${avatarDimensions.mobile.avatarH}px; height: ${avatarDimensions.mobile.avatarH}px; border-radius: 50%; object-fit: cover; background-color: var(--bg-tertiary); border: 5px solid var(--bg-secondary); box-shadow: 0 8px 25px rgba(0,0,0,0.3); position: absolute; top: var(--avatar-mobile-top); left: 50%; transform: translateX(-50%); cursor: pointer; transition: transform 0.3s ease; z-index: 3; }
|
251 |
+
.avatar:hover { transform: translateX(-50%) scale(1.1); }
|
252 |
+
.profile-body { padding: ${avatarDimensions.mobile.overlap + 15}px 1.5rem 1.5rem; text-align: center; }
|
253 |
+
|
254 |
+
.nickname-container { display: flex; align-items: center; justify-content: center; gap: .75rem; min-height: 42px; }
|
255 |
+
.nickname-text { font-size: 2rem; font-weight: 700; color: var(--text-primary); }
|
256 |
+
.user-details { color: var(--text-secondary); margin: 0.25rem 0 1.5rem 0; }
|
257 |
+
|
258 |
+
.active-plan-container {
|
259 |
+
display: inline-flex;
|
260 |
+
align-items: center;
|
261 |
+
color: #fff;
|
262 |
+
padding: 0.3rem 0.8rem;
|
263 |
+
border-radius: 15px;
|
264 |
+
font-size: 0.85rem;
|
265 |
+
font-weight: 500;
|
266 |
+
margin-top: -0.5rem;
|
267 |
+
margin-bottom: 1.5rem;
|
268 |
+
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
269 |
+
}
|
270 |
+
.active-plan-container span {
|
271 |
+
margin-left: 0.3rem;
|
272 |
+
}
|
273 |
+
|
274 |
+
.bio-section, .skills-section { margin-top: 1.5rem; padding: 1.5rem; background-color: var(--bg-tertiary); border-radius: var(--radius-inner); text-align: left; }
|
275 |
+
.bio-section h3, .skills-section h3 { margin: 0 0 1rem 0; color: var(--text-primary); display: flex; justify-content: space-between; align-items: center; font-size: 1.2rem; }
|
276 |
+
.bio-text { color: var(--text-secondary); line-height: 1.6; white-space: pre-wrap; word-wrap: break-word; font-size: 1rem; }
|
277 |
+
|
278 |
+
.edit-icon-btn { background: none; border: none; padding: .3rem; cursor: pointer; color: var(--text-secondary); display: inline-flex; align-items: center; gap: .4rem; font-size: .9rem; font-family: var(--font-body); }
|
279 |
+
.edit-icon-btn:hover { color: var(--accent-primary); }
|
280 |
+
|
281 |
+
.edit-controls { display: flex; flex-direction: column; gap: .8rem; animation: fadeIn .3s ease; }
|
282 |
+
.edit-controls input, .edit-controls textarea { width: 100%; padding: .8rem 1rem; border: 1px solid var(--border-color); border-radius: var(--radius-inner); font-family: var(--font-body); font-size: 1rem; background-color: var(--bg-primary); color: var(--text-primary); box-sizing: border-box; }
|
283 |
+
.edit-controls input:focus, .edit-controls textarea:focus { outline:0; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(0, 170, 255, 0.2); }
|
284 |
+
.edit-controls textarea { min-height: 90px; resize: vertical; }
|
285 |
+
|
286 |
+
.edit-controls-buttons { display: flex; justify-content: flex-end; gap: .6rem; }
|
287 |
+
.btn { display: inline-flex; align-items: center; justify-content: center; padding: .6rem 1.2rem; border: none; border-radius: var(--radius-inner); cursor: pointer; font-family: var(--font-body); font-size: 1rem; font-weight: 500; transition: all .2s ease; }
|
288 |
+
.btn-primary { background: var(--accent-primary); color: #fff; }
|
289 |
+
.btn-primary:hover { background: var(--accent-secondary); }
|
290 |
+
.btn-secondary { background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border-color); }
|
291 |
+
.btn-secondary:hover { background: var(--border-color); }
|
292 |
+
|
293 |
+
.status-message-container { position:fixed; bottom:20px; left:50%; transform:translateX(-50%); z-index:1001; }
|
294 |
+
.status-message { padding: .8rem 1.5rem; border-radius: var(--radius-inner); color: #fff; box-shadow: 0 5px 20px rgba(0,0,0,0.3); animation: slideInUp .5s ease, fadeOut .5s ease 2.5s forwards; }
|
295 |
+
.status-message.success { background-color: var(--success-color); }
|
296 |
+
.status-message.error { background-color: var(--error-color); }
|
297 |
+
|
298 |
+
.modal-overlay { position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,.7); display:flex; justify-content:center; align-items:center; z-index:1000; backdrop-filter:blur(5px); animation:fadeIn .3s ease; }
|
299 |
+
.modal-content { background: var(--bg-secondary); padding: 2rem; border-radius: var(--radius-main); text-align:center; max-width: 450px; width: 90%; border: 1px solid var(--border-color); }
|
300 |
+
.modal-buttons { display:flex; flex-direction:column; gap: .8rem; margin-top: 1.5rem; }
|
301 |
+
.loading-overlay { position:absolute; inset:0; background:rgba(26,27,35,.85); display:flex; justify-content:center; align-items:center; z-index:100; border-radius: var(--radius-main); }
|
302 |
+
.spinner { border: 4px solid rgba(255,255,255,.1); width: 36px; height: 36px; border-radius: 50%; border-left-color: var(--accent-primary); animation:spin .8s linear infinite; }
|
303 |
+
.initial-load-container { display:flex; flex-direction:column; justify-content:center; align-items:center; min-height:80vh; text-align:center; font-size:1.2rem; color: var(--text-secondary); }
|
304 |
+
|
305 |
+
.skills-section h3 { margin-bottom: 1.2rem; }
|
306 |
+
.skills-section .project-name { font-size: 1.1rem; color: var(--text-primary); margin-bottom: 1rem; text-align: center; font-weight: 500;}
|
307 |
+
.skills-grid {
|
308 |
+
display: grid;
|
309 |
+
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
310 |
+
gap: 1rem;
|
311 |
+
justify-content: center;
|
312 |
+
}
|
313 |
+
.skill-item {
|
314 |
+
background-color: var(--bg-primary);
|
315 |
+
padding: 0.8rem;
|
316 |
+
padding-bottom: 1.5rem;
|
317 |
+
border-radius: var(--radius-inner);
|
318 |
+
text-align: center;
|
319 |
+
display: flex;
|
320 |
+
flex-direction: column;
|
321 |
+
align-items: center;
|
322 |
+
border: 1px solid var(--border-color);
|
323 |
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
324 |
+
position: relative;
|
325 |
+
overflow: hidden;
|
326 |
+
}
|
327 |
+
.skill-item:hover {
|
328 |
+
transform: translateY(-3px);
|
329 |
+
box-shadow: 0 5px 15px rgba(0,0,0,0.4);
|
330 |
+
}
|
331 |
+
.skill-icon-container {
|
332 |
+
font-size: 2.5em;
|
333 |
+
line-height: 1;
|
334 |
+
color: var(--accent-primary);
|
335 |
+
margin-bottom: 0.5rem;
|
336 |
+
display: flex;
|
337 |
+
justify-content: center;
|
338 |
+
align-items: center;
|
339 |
+
width: 100%;
|
340 |
+
height: 50px;
|
341 |
+
position: relative;
|
342 |
+
}
|
343 |
+
.skill-icon {
|
344 |
+
max-width: 100%;
|
345 |
+
max-height: 100%;
|
346 |
+
object-fit: contain;
|
347 |
+
}
|
348 |
+
.fallback-icon {
|
349 |
+
position: absolute;
|
350 |
+
top: 50%;
|
351 |
+
left: 50%;
|
352 |
+
transform: translate(-50%, -50%);
|
353 |
+
display: none;
|
354 |
+
}
|
355 |
+
.skill-name {
|
356 |
+
font-size: 0.9rem;
|
357 |
+
font-weight: 500;
|
358 |
+
color: var(--text-primary);
|
359 |
+
margin-bottom: 0.3rem;
|
360 |
+
white-space: nowrap;
|
361 |
+
overflow: hidden;
|
362 |
+
text-overflow: ellipsis;
|
363 |
+
width: 100%;
|
364 |
+
}
|
365 |
+
.skill-percentage {
|
366 |
+
font-size: 0.85rem;
|
367 |
+
color: var(--text-secondary);
|
368 |
+
}
|
369 |
+
.skill-percentage-bar {
|
370 |
+
position: absolute;
|
371 |
+
bottom: 0;
|
372 |
+
left: 0;
|
373 |
+
height: 8px;
|
374 |
+
background-color: var(--accent-primary);
|
375 |
+
border-bottom-left-radius: var(--radius-inner);
|
376 |
+
border-bottom-right-radius: var(--radius-inner);
|
377 |
+
transition: width 0.3s ease-out;
|
378 |
+
}
|
379 |
+
|
380 |
+
@keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
|
381 |
+
@keyframes slideInUp{ from { opacity:0; transform:translateY(20px) } to { opacity:1; transform:translateY(0) } }
|
382 |
+
@keyframes fadeOut{ from { opacity:1 } to { opacity:0 } }
|
383 |
+
@keyframes spin { from { transform:rotate(0deg) } to { transform:rotate(360deg) } }
|
384 |
+
|
385 |
+
@media (min-width: 768px) {
|
386 |
+
.profile-card { max-width: 740px; }
|
387 |
+
.profile-header { height: ${avatarDimensions.tablet.headerH}px; }
|
388 |
+
.avatar { width: ${avatarDimensions.tablet.avatarH}px; height: ${avatarDimensions.tablet.avatarH}px; top: var(--avatar-tablet-top); border-width: 6px; }
|
389 |
+
.profile-body { padding: ${avatarDimensions.tablet.overlap + 20}px 2.5rem 2.5rem; }
|
390 |
+
.nickname-text { font-size: 2.2rem; }
|
391 |
+
.skills-grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); }
|
392 |
+
}
|
393 |
+
|
394 |
+
@media (min-width: 1024px) {
|
395 |
+
.profile-card { max-width: 840px; }
|
396 |
+
.profile-header { height: ${avatarDimensions.desktop.headerH}px; }
|
397 |
+
.avatar { width: ${avatarDimensions.desktop.avatarH}px; height: ${avatarDimensions.desktop.avatarH}px; top: var(--avatar-desktop-top); border-width: 7px; }
|
398 |
+
.profile-body { padding: ${avatarDimensions.desktop.overlap + 25}px 3rem 3rem; }
|
399 |
+
.nickname-text { font-size: 2.5rem; }
|
400 |
+
.skills-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
|
401 |
+
}
|
402 |
+
`}</style>
|
403 |
+
|
404 |
+
<Show when={status().message && !loading()}>
|
405 |
+
<div class="status-message-container">
|
406 |
+
<div class={`status-message ${status().type}`}>{status().message}</div>
|
407 |
+
</div>
|
408 |
+
</Show>
|
409 |
+
|
410 |
+
<div class="profile-container">
|
411 |
+
<Show when={!loading() && userData()}
|
412 |
+
fallback={
|
413 |
+
<div class="initial-load-container">
|
414 |
+
<Show when={loading()} fallback={<p>{status().message || 'Could not load profile.'}</p>}>
|
415 |
+
<Spinner />
|
416 |
+
<p>Loading Profile...</p>
|
417 |
+
</Show>
|
418 |
+
</div>
|
419 |
+
}
|
420 |
+
>
|
421 |
+
<div class="profile-card">
|
422 |
+
<Show when={loading()}><div class="loading-overlay"><Spinner/></div></Show>
|
423 |
+
|
424 |
+
<div class="profile-header">
|
425 |
+
<img class="cover-photo" src={userData()?.cover_photo || `https://source.unsplash.com/random/1600x600/?abstract,dark`} alt="Cover photo" onClick={() => openImageModal('cover_photo')} />
|
426 |
+
</div>
|
427 |
+
|
428 |
+
<img class="avatar" src={userData()?.avatar || `https://api.dicebear.com/8.x/initials/svg?seed=${encodeURIComponent(userData()?.user || 'U')}`} alt="User avatar" onClick={() => openImageModal('avatar')} />
|
429 |
+
|
430 |
+
<div class="profile-body">
|
431 |
+
<div class="nickname-container">
|
432 |
+
<Show when={editingNickname()} fallback={
|
433 |
+
<>
|
434 |
+
<h1 class="nickname-text">{userData()?.nickname || userData()?.user}</h1>
|
435 |
+
<button class="edit-icon-btn" title="Edit Nickname" onClick={() => { setNickname(userData()?.nickname || userData()?.user || ''); setEditingNickname(true); }}>
|
436 |
+
<IconPencil />
|
437 |
+
</button>
|
438 |
+
</>
|
439 |
+
}>
|
440 |
+
<div class="edit-controls">
|
441 |
+
<input type="text" value={nickname()} onInput={(e) => setNickname(e.currentTarget.value)} />
|
442 |
+
<div class="edit-controls-buttons">
|
443 |
+
<button class="btn btn-secondary" onClick={() => setEditingNickname(false)}>Cancel</button>
|
444 |
+
<button class="btn btn-primary" onClick={() => handleUpdate('nickname', nickname(), setEditingNickname)}>Save</button>
|
445 |
+
</div>
|
446 |
+
</div>
|
447 |
+
</Show>
|
448 |
+
</div>
|
449 |
+
<p class="user-details">@{userData()?.user} • ID: {userData()?.id}</p>
|
450 |
+
|
451 |
+
<Show when={userData()?.activePlan?.plan}>
|
452 |
+
<div class="active-plan-container" style={{
|
453 |
+
backgroundColor: activePlanStyles().cardGrad1,
|
454 |
+
color: activePlanStyles().textColor,
|
455 |
+
border: `1px solid ${activePlanStyles().cardBorder}`,
|
456 |
+
boxShadow: `0 2px 8px ${activePlanStyles().glowColor}`
|
457 |
+
}}>
|
458 |
+
{userData()?.activePlan?.plan}
|
459 |
+
</div>
|
460 |
+
</Show>
|
461 |
+
|
462 |
+
<div class="bio-section">
|
463 |
+
<h3>About Me
|
464 |
+
<Show when={!editingBio()}>
|
465 |
+
<button class="edit-icon-btn" title="Edit Bio" onClick={() => { setBio(userData()?.bio || ''); setEditingBio(true); }}>
|
466 |
+
<IconPencil /> Edit
|
467 |
+
</button>
|
468 |
+
</Show>
|
469 |
+
</h3>
|
470 |
+
<Show when={editingBio()} fallback={
|
471 |
+
<p class="bio-text">{userData()?.bio || 'No bio yet. Click edit to add one!'}</p>
|
472 |
+
}>
|
473 |
+
<div class="edit-controls">
|
474 |
+
<textarea rows="4" value={bio()} onInput={(e) => setBio(e.currentTarget.value)}></textarea>
|
475 |
+
<div class="edit-controls-buttons">
|
476 |
+
<button class="btn btn-secondary" onClick={() => setEditingBio(false)}>Cancel</button>
|
477 |
+
<button class="btn btn-primary" onClick={() => handleUpdate('bio', bio(), setEditingBio)}>Save Bio</button>
|
478 |
+
</div>
|
479 |
+
</div>
|
480 |
+
</Show>
|
481 |
+
</div>
|
482 |
+
|
483 |
+
<Show when={projectSkills() && projectSkills().skills && projectSkills().skills.length > 0}>
|
484 |
+
<div class="skills-section">
|
485 |
+
<h3>Project Skills</h3>
|
486 |
+
<p class="project-name">Analyzing: {getBasename(projectSkills().project)}</p>
|
487 |
+
<div class="skills-grid">
|
488 |
+
<For each={projectSkills().skills}>
|
489 |
+
{(skill) => (
|
490 |
+
<div class="skill-item">
|
491 |
+
<div class="skill-icon-container">
|
492 |
+
{getSkillIcon(skill.extension, skill.name)}
|
493 |
+
<span class="fallback-icon">
|
494 |
+
<IconCode />
|
495 |
+
</span>
|
496 |
+
</div>
|
497 |
+
<div class="skill-name" title={skill.name}>{skill.name}</div>
|
498 |
+
<div class="skill-percentage">{skill.skill}</div>
|
499 |
+
<div class="skill-percentage-bar" style={{ width: skill.skill }}></div>
|
500 |
+
</div>
|
501 |
+
)}
|
502 |
+
</For>
|
503 |
+
</div>
|
504 |
+
</div>
|
505 |
+
</Show>
|
506 |
+
|
507 |
+
</div>
|
508 |
+
</div>
|
509 |
+
</Show>
|
510 |
+
|
511 |
+
<Show when={modalOpen()}>
|
512 |
+
<div class="modal-overlay" onClick={() => setModalOpen(false)}>
|
513 |
+
<div class="modal-content" onClick={(e) => e.stopPropagation()}>
|
514 |
+
<h2 style={{margin: "0 0 1.5rem 0"}}>Update Image</h2>
|
515 |
+
<div class="modal-buttons">
|
516 |
+
<button class="btn btn-primary" onClick={modalAction()}><IconAdd /> Upload New</button>
|
517 |
+
<button class="btn btn-secondary" style={{'margin-top': '1rem'}} onClick={() => setModalOpen(false)}>Cancel</button>
|
518 |
+
</div>
|
519 |
+
</div>
|
520 |
+
</div>
|
521 |
+
</Show>
|
522 |
+
</div>
|
523 |
+
</>
|
524 |
+
);
|
525 |
+
}
|
526 |
+
|
527 |
+
render(() => <App />, document.getElementById('app'));
|
exocore-web/public/project.jsx
ADDED
@@ -0,0 +1,483 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, createResource, onMount, Show, For } from 'solid-js';
|
3 |
+
import { Alert, Spinner } from 'solid-bootstrap';
|
4 |
+
|
5 |
+
const BASE_URL = '/private/server/exocore/web';
|
6 |
+
|
7 |
+
const fetchTemplates = async () => {
|
8 |
+
const res = await fetch(`${BASE_URL}/templates`, { method: 'POST' });
|
9 |
+
if (!res.ok) throw new Error('Failed to fetch templates');
|
10 |
+
return res.json();
|
11 |
+
};
|
12 |
+
|
13 |
+
const checkProjectStatus = async () => {
|
14 |
+
try {
|
15 |
+
const res = await fetch(`${BASE_URL}/project/status`, { method: 'POST' });
|
16 |
+
const json = await res.json();
|
17 |
+
if (json.exists) window.location.href = `${BASE_URL}/public/dashboard`;
|
18 |
+
} catch (err) {
|
19 |
+
console.error('Error checking project status:', err);
|
20 |
+
}
|
21 |
+
};
|
22 |
+
|
23 |
+
function App() {
|
24 |
+
const [templates] = createResource(fetchTemplates);
|
25 |
+
const [step, setStep] = createSignal(1); // 1 for source, 2 for project name
|
26 |
+
const [projectName, setProjectName] = createSignal('');
|
27 |
+
const [selectedTemplateId, setSelectedTemplateId] = createSignal('');
|
28 |
+
const [selectedTemplateGitUrl, setSelectedTemplateGitUrl] = createSignal('');
|
29 |
+
const [customGitUrl, setCustomGitUrl] = createSignal('');
|
30 |
+
const [projectSourceType, setProjectSourceType] = createSignal('template');
|
31 |
+
|
32 |
+
const [status, setStatus] = createSignal('');
|
33 |
+
const [loading, setLoading] = createSignal(false);
|
34 |
+
|
35 |
+
onMount(() => {
|
36 |
+
checkProjectStatus();
|
37 |
+
document.body.style = `
|
38 |
+
margin: 0;
|
39 |
+
font-family: 'Inter', sans-serif;
|
40 |
+
background: #0a0a0a;
|
41 |
+
color: #e0e0e0;
|
42 |
+
line-height: 1.6;
|
43 |
+
overflow-x: hidden;
|
44 |
+
`;
|
45 |
+
const link = document.createElement('link');
|
46 |
+
link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap';
|
47 |
+
link.rel = 'stylesheet';
|
48 |
+
document.head.appendChild(link);
|
49 |
+
});
|
50 |
+
|
51 |
+
const inputStyle = {
|
52 |
+
background: '#2a2a2a',
|
53 |
+
color: '#fff',
|
54 |
+
border: '1px solid #444',
|
55 |
+
padding: '0.8rem 1rem',
|
56 |
+
'border-radius': '8px',
|
57 |
+
width: '100%',
|
58 |
+
'font-family': 'inherit',
|
59 |
+
'font-size': '1rem',
|
60 |
+
'box-shadow': 'inset 0 1px 3px rgba(0,0,0,0.3)',
|
61 |
+
'transition': 'border-color 0.2s ease, box-shadow 0.2s ease',
|
62 |
+
};
|
63 |
+
|
64 |
+
const inputFocusStyle = {
|
65 |
+
'border-color': '#007bff',
|
66 |
+
'box-shadow': '0 0 0 3px rgba(0, 123, 255, 0.25)',
|
67 |
+
};
|
68 |
+
|
69 |
+
const buttonPrimaryColor = '#007bff';
|
70 |
+
const buttonHoverColor = '#0056b3';
|
71 |
+
const buttonSecondaryColor = '#555';
|
72 |
+
const buttonSecondaryHoverColor = '#777';
|
73 |
+
|
74 |
+
const customRadioContainerStyle = {
|
75 |
+
'display': 'flex',
|
76 |
+
'align-items': 'center',
|
77 |
+
'cursor': 'pointer',
|
78 |
+
'user-select': 'none',
|
79 |
+
'margin-right': '1.5rem',
|
80 |
+
};
|
81 |
+
|
82 |
+
const hiddenRadioInputStyle = {
|
83 |
+
'position': 'absolute',
|
84 |
+
'opacity': '0',
|
85 |
+
'width': '0',
|
86 |
+
'height': '0',
|
87 |
+
};
|
88 |
+
|
89 |
+
const customRadioIndicatorStyle = {
|
90 |
+
'display': 'inline-block',
|
91 |
+
'width': '20px',
|
92 |
+
'height': '20px',
|
93 |
+
'border': '2px solid #666',
|
94 |
+
'border-radius': '50%',
|
95 |
+
'margin-right': '0.8rem',
|
96 |
+
'position': 'relative',
|
97 |
+
'transition': 'all 0.2s ease-in-out',
|
98 |
+
'flex-shrink': 0,
|
99 |
+
};
|
100 |
+
|
101 |
+
const customRadioIndicatorCheckedStyle = {
|
102 |
+
'border-color': buttonPrimaryColor,
|
103 |
+
'background-color': buttonPrimaryColor,
|
104 |
+
'box-shadow': `0 0 0 4px rgba(0, 123, 255, 0.3)`,
|
105 |
+
};
|
106 |
+
|
107 |
+
const customRadioInnerDotStyle = {
|
108 |
+
'position': 'absolute',
|
109 |
+
'top': '50%',
|
110 |
+
'left': '50%',
|
111 |
+
'transform': 'translate(-50%, -50%)',
|
112 |
+
'width': '10px',
|
113 |
+
'height': '10px',
|
114 |
+
'border-radius': '50%',
|
115 |
+
'background': '#fff',
|
116 |
+
'opacity': '0',
|
117 |
+
'transition': 'opacity 0.2s ease-in-out',
|
118 |
+
};
|
119 |
+
|
120 |
+
const customRadioInnerDotCheckedStyle = {
|
121 |
+
'opacity': '1',
|
122 |
+
};
|
123 |
+
|
124 |
+
const templateCardStyle = (isSelected) => ({
|
125 |
+
padding: '1.2rem',
|
126 |
+
border: `1px solid ${isSelected ? buttonPrimaryColor : '#333'}`,
|
127 |
+
'border-radius': '10px',
|
128 |
+
cursor: 'pointer',
|
129 |
+
background: isSelected ? '#2a2a3a' : '#1f1f1f',
|
130 |
+
'transition': 'all 0.2s ease-in-out',
|
131 |
+
'display': 'flex',
|
132 |
+
'flex-direction': 'column',
|
133 |
+
'align-items': 'flex-start',
|
134 |
+
'gap': '0.8rem',
|
135 |
+
'&:hover': {
|
136 |
+
background: '#252525',
|
137 |
+
'border-color': isSelected ? buttonPrimaryColor : '#666'
|
138 |
+
},
|
139 |
+
'box-shadow': isSelected ? `0 0 10px rgba(0, 123, 255, 0.4)` : 'none'
|
140 |
+
});
|
141 |
+
|
142 |
+
const templateImageStyle = {
|
143 |
+
'width': '70px',
|
144 |
+
'height': '70px',
|
145 |
+
'object-fit': 'contain',
|
146 |
+
'border-radius': '8px',
|
147 |
+
'background': '#3a3a3a',
|
148 |
+
'padding': '5px',
|
149 |
+
};
|
150 |
+
|
151 |
+
const templateDescriptionStyle = {
|
152 |
+
'font-size': '0.9rem',
|
153 |
+
'color': '#bbb',
|
154 |
+
'line-height': '1.4'
|
155 |
+
};
|
156 |
+
|
157 |
+
const isNextDisabledStep1 = () => {
|
158 |
+
if (projectSourceType() === 'template' && !selectedTemplateId()) return true;
|
159 |
+
if (projectSourceType() === 'gitUrl' && !customGitUrl().trim()) return true;
|
160 |
+
return false;
|
161 |
+
};
|
162 |
+
|
163 |
+
const isCreateDisabledStep2 = () => {
|
164 |
+
return loading() || !projectName().trim();
|
165 |
+
};
|
166 |
+
|
167 |
+
|
168 |
+
const handleProceedToNameStep = () => {
|
169 |
+
if (isNextDisabledStep1()) return;
|
170 |
+
setStep(2);
|
171 |
+
};
|
172 |
+
|
173 |
+
const handleBackToSourceStep = () => {
|
174 |
+
setStep(1);
|
175 |
+
setStatus('');
|
176 |
+
};
|
177 |
+
|
178 |
+
const handleCreateProject = async () => {
|
179 |
+
setLoading(true);
|
180 |
+
setStatus('');
|
181 |
+
|
182 |
+
const finalName = projectName().trim();
|
183 |
+
if (!finalName) {
|
184 |
+
setStatus('Project name cannot be empty');
|
185 |
+
setLoading(false);
|
186 |
+
return;
|
187 |
+
}
|
188 |
+
|
189 |
+
let gitToUse = '';
|
190 |
+
if (projectSourceType() === 'template') {
|
191 |
+
const chosenTemplate = templates()?.find(t => t.id === selectedTemplateId());
|
192 |
+
if (chosenTemplate) {
|
193 |
+
gitToUse = chosenTemplate.git;
|
194 |
+
} else {
|
195 |
+
setStatus('Error: Selected template not found.');
|
196 |
+
setLoading(false);
|
197 |
+
return;
|
198 |
+
}
|
199 |
+
} else { // 'gitUrl'
|
200 |
+
gitToUse = customGitUrl().trim();
|
201 |
+
if (!gitToUse) {
|
202 |
+
setStatus('Git URL cannot be empty.');
|
203 |
+
setLoading(false);
|
204 |
+
return;
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
try {
|
209 |
+
const payload = {
|
210 |
+
name: finalName,
|
211 |
+
gitUrl: gitToUse,
|
212 |
+
};
|
213 |
+
const res = await fetch(`${BASE_URL}/project`, {
|
214 |
+
method: 'POST',
|
215 |
+
headers: { 'Content-Type': 'application/json' },
|
216 |
+
body: JSON.stringify(payload),
|
217 |
+
});
|
218 |
+
const text = await res.text();
|
219 |
+
if (res.ok) {
|
220 |
+
setStatus(`Success: ${text}`);
|
221 |
+
setTimeout(() => window.location.href = `${BASE_URL}/public/dashboard`, 1500);
|
222 |
+
} else {
|
223 |
+
setStatus(`Failed: ${text || 'Unknown error'}`);
|
224 |
+
}
|
225 |
+
} catch (err) {
|
226 |
+
setStatus(`Error: ${err.message}`);
|
227 |
+
} finally {
|
228 |
+
setLoading(false);
|
229 |
+
}
|
230 |
+
};
|
231 |
+
|
232 |
+
|
233 |
+
return (
|
234 |
+
<div style={{ display: 'flex', 'justify-content': 'center', 'align-items': 'center', 'min-height': '100vh', padding: '2vh 1vw' }}>
|
235 |
+
<div style={{
|
236 |
+
width: '100%',
|
237 |
+
'max-width': '600px',
|
238 |
+
background: '#1a1a1a',
|
239 |
+
padding: '2.5rem',
|
240 |
+
'border-radius': '16px',
|
241 |
+
'box-shadow': '0 10px 30px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.05)',
|
242 |
+
'border': '1px solid rgba(255,255,255,0.08)'
|
243 |
+
}}>
|
244 |
+
<h2 style={{
|
245 |
+
'text-align': 'center',
|
246 |
+
'margin-bottom': '2.5rem',
|
247 |
+
'font-size': '2rem',
|
248 |
+
'color': '#fff',
|
249 |
+
'text-shadow': '0 0 8px rgba(255,255,255,0.1)'
|
250 |
+
}}>✨ Create New Project ✨</h2>
|
251 |
+
|
252 |
+
<Show when={step() === 1}>
|
253 |
+
<h3 style={{ 'margin-bottom': '1.5rem', 'font-size': '1.5rem', 'color': '#fff' }}>Choose Project Source</h3>
|
254 |
+
|
255 |
+
<div style={{ marginBottom: '2rem' }}>
|
256 |
+
<div style={{ 'display': 'flex', 'gap': '1.5rem' }}>
|
257 |
+
<label style={customRadioContainerStyle}>
|
258 |
+
<input
|
259 |
+
type="radio"
|
260 |
+
name="projectSource"
|
261 |
+
checked={projectSourceType() === 'template'}
|
262 |
+
onChange={() => setProjectSourceType('template')}
|
263 |
+
style={hiddenRadioInputStyle}
|
264 |
+
/>
|
265 |
+
<span style={{
|
266 |
+
...customRadioIndicatorStyle,
|
267 |
+
...(projectSourceType() === 'template' && customRadioIndicatorCheckedStyle)
|
268 |
+
}}>
|
269 |
+
<div style={{
|
270 |
+
...customRadioInnerDotStyle,
|
271 |
+
...(projectSourceType() === 'template' && customRadioInnerDotCheckedStyle)
|
272 |
+
}}></div>
|
273 |
+
</span>
|
274 |
+
Template
|
275 |
+
</label>
|
276 |
+
<label style={customRadioContainerStyle}>
|
277 |
+
<input
|
278 |
+
type="radio"
|
279 |
+
name="projectSource"
|
280 |
+
checked={projectSourceType() === 'gitUrl'}
|
281 |
+
onChange={() => setProjectSourceType('gitUrl')}
|
282 |
+
style={hiddenRadioInputStyle}
|
283 |
+
/>
|
284 |
+
<span style={{
|
285 |
+
...customRadioIndicatorStyle,
|
286 |
+
...(projectSourceType() === 'gitUrl' && customRadioIndicatorCheckedStyle)
|
287 |
+
}}>
|
288 |
+
<div style={{
|
289 |
+
...customRadioInnerDotStyle,
|
290 |
+
...(projectSourceType() === 'gitUrl' && customRadioInnerDotCheckedStyle)
|
291 |
+
}}></div>
|
292 |
+
</span>
|
293 |
+
Git URL
|
294 |
+
</label>
|
295 |
+
</div>
|
296 |
+
</div>
|
297 |
+
|
298 |
+
<Show when={projectSourceType() === 'template'}>
|
299 |
+
<label style={{ 'display': 'block', 'margin-bottom': '1rem', 'font-weight': '500', 'color': '#ccc' }}>Select a Template</label>
|
300 |
+
<div style={{
|
301 |
+
'max-height': '400px',
|
302 |
+
'overflow-y': 'auto',
|
303 |
+
'padding-right': '10px',
|
304 |
+
'margin-bottom': '2rem',
|
305 |
+
'display': 'grid',
|
306 |
+
'grid-template-columns': 'repeat(auto-fill, minmax(200px, 1fr))',
|
307 |
+
'gap': '1rem',
|
308 |
+
}}>
|
309 |
+
<Show when={templates.loading}>
|
310 |
+
<p style={{ 'color': '#aaa', 'text-align': 'center', 'grid-column': '1 / -1' }}>Loading templates...</p>
|
311 |
+
</Show>
|
312 |
+
<Show when={templates.error}>
|
313 |
+
<p style={{ 'color': '#f8d7da', 'text-align': 'center', 'grid-column': '1 / -1' }}>Error loading templates: {templates.error.message}</p>
|
314 |
+
</Show>
|
315 |
+
<For each={templates()}>{tpl => (
|
316 |
+
<div
|
317 |
+
style={templateCardStyle(selectedTemplateId() === tpl.id)}
|
318 |
+
onClick={() => {
|
319 |
+
setSelectedTemplateId(tpl.id);
|
320 |
+
setSelectedTemplateGitUrl(tpl.git);
|
321 |
+
}}
|
322 |
+
>
|
323 |
+
<img src={tpl.image} alt={tpl.name} style={templateImageStyle} />
|
324 |
+
<h4 style={{ 'margin': '0', 'color': '#fff', 'font-size': '1.1rem' }}>{tpl.name}</h4>
|
325 |
+
<p style={templateDescriptionStyle}>{tpl.describe}</p>
|
326 |
+
</div>
|
327 |
+
)}</For>
|
328 |
+
<Show when={!templates.loading && !templates.error && templates()?.length === 0}>
|
329 |
+
<p style={{ 'color': '#aaa', 'text-align': 'center', 'grid-column': '1 / -1' }}>No templates available.</p>
|
330 |
+
</Show>
|
331 |
+
</div>
|
332 |
+
</Show>
|
333 |
+
|
334 |
+
<Show when={projectSourceType() === 'gitUrl'}>
|
335 |
+
<div style={{ marginBottom: '2rem' }}>
|
336 |
+
<label style={{ 'display': 'block', 'margin-bottom': '0.8rem', 'font-weight': '500', 'color': '#ccc' }}>Git Repository URL</label>
|
337 |
+
<input
|
338 |
+
type="text"
|
339 |
+
placeholder="https://github.com/user/repo.git"
|
340 |
+
value={customGitUrl()}
|
341 |
+
onInput={e => setCustomGitUrl(e.currentTarget.value)}
|
342 |
+
style={{ ...inputStyle, ...(customGitUrl() && inputFocusStyle) }}
|
343 |
+
onFocus={e => e.currentTarget.style.borderColor = inputFocusStyle['border-color']}
|
344 |
+
onBlur={e => e.currentTarget.style.borderColor = inputStyle.border.split(' ')[2]}
|
345 |
+
disabled={loading()}
|
346 |
+
/>
|
347 |
+
</div>
|
348 |
+
</Show>
|
349 |
+
|
350 |
+
<div style={{ 'display': 'flex', 'justify-content': 'flex-end', 'gap': '0.8rem' }}>
|
351 |
+
<button
|
352 |
+
onClick={() => { /* Implement close/cancel logic, e.g., redirect or reset form */ alert("Close/Cancel action not yet implemented."); }}
|
353 |
+
style={{
|
354 |
+
padding: '0.7rem 1.4rem',
|
355 |
+
background: buttonSecondaryColor,
|
356 |
+
color: 'white',
|
357 |
+
border: 'none',
|
358 |
+
'border-radius': '8px',
|
359 |
+
'font-size': '1rem',
|
360 |
+
cursor: 'pointer',
|
361 |
+
'transition': 'background 0.3s ease'
|
362 |
+
}}
|
363 |
+
onMouseEnter={(e) => e.currentTarget.style.background = buttonSecondaryHoverColor}
|
364 |
+
onMouseLeave={(e) => e.currentTarget.style.background = buttonSecondaryColor}
|
365 |
+
>
|
366 |
+
Close
|
367 |
+
</button>
|
368 |
+
<button
|
369 |
+
onClick={handleProceedToNameStep}
|
370 |
+
disabled={isNextDisabledStep1()}
|
371 |
+
style={{
|
372 |
+
padding: '0.7rem 1.4rem',
|
373 |
+
background: !isNextDisabledStep1() ? buttonPrimaryColor : buttonSecondaryColor,
|
374 |
+
color: 'white',
|
375 |
+
border: 'none',
|
376 |
+
'border-radius': '8px',
|
377 |
+
'font-size': '1rem',
|
378 |
+
cursor: !isNextDisabledStep1() ? 'pointer' : 'not-allowed',
|
379 |
+
opacity: !isNextDisabledStep1() ? 1 : 0.6,
|
380 |
+
'transition': 'background 0.3s ease'
|
381 |
+
}}
|
382 |
+
onMouseEnter={(e) => e.currentTarget.style.background = !isNextDisabledStep1() ? buttonHoverColor : buttonSecondaryColor}
|
383 |
+
onMouseLeave={(e) => e.currentTarget.style.background = !isNextDisabledStep1() ? buttonPrimaryColor : buttonSecondaryColor}
|
384 |
+
>
|
385 |
+
Next »
|
386 |
+
</button>
|
387 |
+
</div>
|
388 |
+
</Show>
|
389 |
+
|
390 |
+
<Show when={step() === 2}>
|
391 |
+
<h3 style={{ 'margin-bottom': '1.5rem', 'font-size': '1.5rem', 'color': '#fff' }}>Name Your Project</h3>
|
392 |
+
|
393 |
+
<div style={{ marginBottom: '3rem' }}>
|
394 |
+
<label style={{ 'display': 'block', 'margin-bottom': '0.8rem', 'font-weight': '500', 'color': '#ccc' }}>Project Name</label>
|
395 |
+
<input
|
396 |
+
type="text"
|
397 |
+
placeholder="e.g. my-awesome-app"
|
398 |
+
value={projectName()}
|
399 |
+
onInput={e => setProjectName(e.currentTarget.value)}
|
400 |
+
style={{ ...inputStyle, ...(projectName() && inputFocusStyle) }}
|
401 |
+
onFocus={e => e.currentTarget.style.borderColor = inputFocusStyle['border-color']}
|
402 |
+
onBlur={e => e.currentTarget.style.borderColor = inputStyle.border.split(' ')[2]}
|
403 |
+
disabled={loading()}
|
404 |
+
/>
|
405 |
+
</div>
|
406 |
+
|
407 |
+
<div style={{ 'display': 'flex', 'justify-content': 'space-between', 'align-items': 'center', 'gap': '0.8rem' }}>
|
408 |
+
<button
|
409 |
+
onClick={handleBackToSourceStep}
|
410 |
+
style={{
|
411 |
+
padding: '0.7rem 1.4rem',
|
412 |
+
background: buttonSecondaryColor,
|
413 |
+
color: 'white',
|
414 |
+
border: 'none',
|
415 |
+
'border-radius': '8px',
|
416 |
+
'font-size': '1rem',
|
417 |
+
cursor: 'pointer',
|
418 |
+
'transition': 'background 0.3s ease'
|
419 |
+
}}
|
420 |
+
onMouseEnter={(e) => e.currentTarget.style.background = buttonSecondaryHoverColor}
|
421 |
+
onMouseLeave={(e) => e.currentTarget.style.background = buttonSecondaryColor}
|
422 |
+
>
|
423 |
+
« Back
|
424 |
+
</button>
|
425 |
+
<button
|
426 |
+
onClick={handleCreateProject}
|
427 |
+
disabled={isCreateDisabledStep2()}
|
428 |
+
style={{
|
429 |
+
padding: '1rem',
|
430 |
+
background: buttonPrimaryColor,
|
431 |
+
color: 'white',
|
432 |
+
border: 'none',
|
433 |
+
'border-radius': '10px',
|
434 |
+
'font-size': '1.1rem',
|
435 |
+
'font-weight': '700',
|
436 |
+
cursor: isCreateDisabledStep2() ? 'not-allowed' : 'pointer',
|
437 |
+
opacity: isCreateDisabledStep2() ? 0.6 : 1,
|
438 |
+
'box-shadow': `0 4px 15px rgba(0, 123, 255, 0.4)`,
|
439 |
+
'transition': 'background 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease',
|
440 |
+
'&:hover': {
|
441 |
+
background: buttonHoverColor,
|
442 |
+
transform: isCreateDisabledStep2() ? 'none' : 'translateY(-2px)',
|
443 |
+
'box-shadow': isCreateDisabledStep2() ? `0 4px 15px rgba(0, 123, 255, 0.4)` : `0 6px 20px rgba(0, 123, 255, 0.6)`
|
444 |
+
},
|
445 |
+
'&:active': {
|
446 |
+
transform: isCreateDisabledStep2() ? 'none' : 'translateY(0)',
|
447 |
+
'box-shadow': isCreateDisabledStep2() ? `0 2px 10px rgba(0, 123, 255, 0.3)` : `0 2px 10px rgba(0, 123, 255, 0.3)`
|
448 |
+
}
|
449 |
+
}}
|
450 |
+
>
|
451 |
+
{loading() ? (
|
452 |
+
<span style={{ display: 'flex', 'align-items': 'center', 'justify-content': 'center', 'gap': '0.5rem' }}>
|
453 |
+
<Spinner animation="border" size="sm" /> Creating...
|
454 |
+
</span>
|
455 |
+
) : '🚀 Create Project'}
|
456 |
+
</button>
|
457 |
+
</div>
|
458 |
+
</Show>
|
459 |
+
|
460 |
+
<Show when={status()}>
|
461 |
+
<Alert
|
462 |
+
class="mt-4"
|
463 |
+
variant={status().startsWith('Success') ? 'success' : 'danger'}
|
464 |
+
style={{
|
465 |
+
'text-align': 'center',
|
466 |
+
marginTop: '1.5rem',
|
467 |
+
'border-radius': '8px',
|
468 |
+
'padding': '0.8rem 1rem',
|
469 |
+
'font-size': '0.95rem',
|
470 |
+
'background-color': status().startsWith('Success') ? 'rgba(0, 128, 0, 0.3)' : 'rgba(255, 0, 0, 0.3)',
|
471 |
+
'color': status().startsWith('Success') ? '#a0ffa0' : '#ffafaf',
|
472 |
+
'border-color': status().startsWith('Success') ? 'rgba(0, 128, 0, 0.5)' : 'rgba(255, 0, 0, 0.5)'
|
473 |
+
}}
|
474 |
+
>
|
475 |
+
{status()}
|
476 |
+
</Alert>
|
477 |
+
</Show>
|
478 |
+
</div>
|
479 |
+
</div>
|
480 |
+
);
|
481 |
+
}
|
482 |
+
|
483 |
+
render(() => <App />, document.getElementById('app'));
|
exocore-web/public/register.jsx
ADDED
@@ -0,0 +1,338 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, Show } from 'solid-js';
|
3 |
+
import flatpickr from 'flatpickr';
|
4 |
+
import 'flatpickr/dist/themes/dark.css';
|
5 |
+
|
6 |
+
// SVG Icon Components
|
7 |
+
const IconEye = () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>;
|
8 |
+
const IconEyeOff = () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>;
|
9 |
+
const IconUpload = () => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>;
|
10 |
+
|
11 |
+
function App() {
|
12 |
+
// State signals for form data and UI status
|
13 |
+
const [loading, setLoading] = createSignal(false);
|
14 |
+
const [status, setStatus] = createSignal('');
|
15 |
+
const [showPassword, setShowPassword] = createSignal(false);
|
16 |
+
const [passwordWarning, setPasswordWarning] = createSignal('');
|
17 |
+
const [form, setForm] = createSignal({ user: '', pass: '', email: '', avatar: '', bio: '', nickname: '', dob: '', cover_photo: '', country: '', timezone: '' });
|
18 |
+
const [avatarFileName, setAvatarFileName] = createSignal('');
|
19 |
+
const [coverPhotoFileName, setCoverPhotoFileName] = createSignal('');
|
20 |
+
const [validationErrors, setValidationErrors] = createSignal({});
|
21 |
+
|
22 |
+
// Refs for file input elements
|
23 |
+
let avatarInputRef, coverPhotoInputRef;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Redirects the user to the dashboard if they are already logged in.
|
27 |
+
* Checks for authentication tokens in localStorage.
|
28 |
+
*/
|
29 |
+
function LoggedAlready() {
|
30 |
+
if (localStorage.getItem('exocore-token') && localStorage.getItem('exocore-cookies')) {
|
31 |
+
window.location.href = '/private/server/exocore/web/public/dashboard';
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
// Lifecycle hook: runs once after the component mounts
|
36 |
+
onMount(() => {
|
37 |
+
fetchLocation();
|
38 |
+
initDatePicker();
|
39 |
+
LoggedAlready();
|
40 |
+
setInterval(LoggedAlready, 5000); // Periodically check login status
|
41 |
+
});
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Initializes the flatpickr date picker on the date of birth input.
|
45 |
+
*/
|
46 |
+
function initDatePicker() {
|
47 |
+
setTimeout(() => {
|
48 |
+
const dobInput = document.getElementById('dob');
|
49 |
+
if (dobInput) {
|
50 |
+
flatpickr(dobInput, {
|
51 |
+
dateFormat: 'Y-m-d',
|
52 |
+
maxDate: 'today',
|
53 |
+
altInput: true,
|
54 |
+
altFormat: 'F j, Y',
|
55 |
+
appendTo: window.document.body,
|
56 |
+
onChange: (_, dateStr) => updateField('dob', dateStr),
|
57 |
+
});
|
58 |
+
}
|
59 |
+
}, 100);
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Fetches the user's country and timezone based on their IP address.
|
64 |
+
*/
|
65 |
+
async function fetchLocation() {
|
66 |
+
try {
|
67 |
+
const res = await fetch('https://ipwho.is/');
|
68 |
+
const data = await res.json();
|
69 |
+
if (data.success) {
|
70 |
+
setForm((prev) => ({ ...prev, country: data.country || '', timezone: data.timezone?.id || '' }));
|
71 |
+
}
|
72 |
+
} catch (err) {
|
73 |
+
console.error('Error fetching location:', err);
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Handles file selection for avatar and cover photo, updating the form state.
|
79 |
+
* @param {string} field - The form field to update ('avatar' or 'cover_photo').
|
80 |
+
* @param {Event} event - The file input change event.
|
81 |
+
*/
|
82 |
+
function handleFileChange(field, event) {
|
83 |
+
const file = event.currentTarget.files[0];
|
84 |
+
const targetSignal = field === 'avatar' ? setAvatarFileName : setCoverPhotoFileName;
|
85 |
+
if (!file) {
|
86 |
+
targetSignal('');
|
87 |
+
setForm((prev) => ({ ...prev, [field]: '' }));
|
88 |
+
return;
|
89 |
+
}
|
90 |
+
targetSignal(file.name);
|
91 |
+
const reader = new FileReader();
|
92 |
+
reader.onload = () => updateField(field, reader.result);
|
93 |
+
reader.readAsDataURL(file);
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Validates and submits the registration form data to the server.
|
98 |
+
* @param {Event} e - The form submission event.
|
99 |
+
*/
|
100 |
+
async function handleSubmit(e) {
|
101 |
+
e.preventDefault();
|
102 |
+
setLoading(true);
|
103 |
+
setStatus('');
|
104 |
+
setValidationErrors({});
|
105 |
+
|
106 |
+
const currentForm = form();
|
107 |
+
// All fields are now required
|
108 |
+
const requiredFields = ['user', 'email', 'pass', 'nickname', 'dob', 'country', 'timezone', 'bio', 'avatar', 'cover_photo'];
|
109 |
+
const errors = {};
|
110 |
+
|
111 |
+
// Check for empty required fields
|
112 |
+
requiredFields.forEach(field => {
|
113 |
+
if (!currentForm[field]) {
|
114 |
+
const fieldName = {
|
115 |
+
user: 'Username',
|
116 |
+
pass: 'Password',
|
117 |
+
dob: 'Date of Birth',
|
118 |
+
bio: 'Short Bio',
|
119 |
+
avatar: 'Avatar',
|
120 |
+
cover_photo: 'Cover Photo'
|
121 |
+
}[field] || field.charAt(0).toUpperCase() + field.slice(1);
|
122 |
+
errors[field] = `${fieldName} is required.`;
|
123 |
+
}
|
124 |
+
});
|
125 |
+
|
126 |
+
// If there are validation errors, update state and stop submission
|
127 |
+
if (Object.keys(errors).length > 0) {
|
128 |
+
setValidationErrors(errors);
|
129 |
+
setStatus('Please complete all required fields.');
|
130 |
+
setLoading(false);
|
131 |
+
return;
|
132 |
+
}
|
133 |
+
|
134 |
+
// Check for password strength issues
|
135 |
+
if (passwordWarning()) {
|
136 |
+
setStatus('Please correct the password issues before submitting.');
|
137 |
+
setLoading(false);
|
138 |
+
return;
|
139 |
+
}
|
140 |
+
|
141 |
+
// Attempt to submit the form data
|
142 |
+
try {
|
143 |
+
const res = await fetch('/private/server/exocore/web/register', {
|
144 |
+
method: 'POST',
|
145 |
+
headers: { 'Content-Type': 'application/json' },
|
146 |
+
body: JSON.stringify(currentForm),
|
147 |
+
});
|
148 |
+
const responseData = await res.json();
|
149 |
+
if (!res.ok) throw new Error(responseData?.message || `Server error: ${res.status}`);
|
150 |
+
setStatus('Registration successful! Redirecting to login...');
|
151 |
+
setTimeout(() => { window.location.href = '/private/server/exocore/web/public/login'; }, 2000);
|
152 |
+
} catch (err) {
|
153 |
+
setStatus(err.message);
|
154 |
+
}
|
155 |
+
setLoading(false);
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Updates a form field's value in the state and performs validation.
|
160 |
+
* @param {string} field - The name of the field to update.
|
161 |
+
* @param {string} value - The new value for the field.
|
162 |
+
*/
|
163 |
+
function updateField(field, value) {
|
164 |
+
let processedValue = (field === 'user' || field === 'email' || field === 'pass')
|
165 |
+
? value.replace(/\s/g, '')
|
166 |
+
: value;
|
167 |
+
|
168 |
+
// Password strength validation
|
169 |
+
if (field === 'pass') {
|
170 |
+
const warnings = [];
|
171 |
+
if (processedValue.length > 0) {
|
172 |
+
if (processedValue.length < 8) warnings.push('be at least 8 characters');
|
173 |
+
if (!/\d/.test(processedValue)) warnings.push('include a number');
|
174 |
+
if (!/[!@#$%^&*(),.?":{}|<>]/.test(processedValue)) warnings.push('include a symbol');
|
175 |
+
}
|
176 |
+
setPasswordWarning(warnings.length > 0 ? 'Password must ' + warnings.join(', ') + '.' : '');
|
177 |
+
}
|
178 |
+
|
179 |
+
setForm((prev) => ({ ...prev, [field]: processedValue }));
|
180 |
+
|
181 |
+
// Clear the validation error for the field being edited
|
182 |
+
if (validationErrors()[field]) {
|
183 |
+
setValidationErrors(prev => {
|
184 |
+
const newErrors = { ...prev };
|
185 |
+
delete newErrors[field];
|
186 |
+
return newErrors;
|
187 |
+
});
|
188 |
+
}
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Determines if the submit button should be disabled based on form completion and validity.
|
193 |
+
* @returns {boolean} True if the button should be disabled.
|
194 |
+
*/
|
195 |
+
const isSubmitDisabled = () => {
|
196 |
+
const f = form();
|
197 |
+
const requiredFields = ['user', 'email', 'pass', 'nickname', 'dob', 'country', 'timezone', 'bio', 'avatar', 'cover_photo'];
|
198 |
+
const hasEmptyFields = requiredFields.some(field => !f[field]);
|
199 |
+
return loading() || !!passwordWarning() || hasEmptyFields;
|
200 |
+
};
|
201 |
+
|
202 |
+
return (
|
203 |
+
<div class="register-page-wrapper">
|
204 |
+
<style>{`
|
205 |
+
:root {
|
206 |
+
--bg-primary: #111217; --bg-secondary: #1a1b23; --text-primary: #e0e0e0;
|
207 |
+
--text-secondary: #8a8f98; --accent-primary: #00aaff; --accent-secondary: #0088cc;
|
208 |
+
--border-color: rgba(255, 255, 255, 0.1); --shadow-color: rgba(0, 0, 0, 0.5);
|
209 |
+
--radius-main: 16px; --radius-inner: 12px;
|
210 |
+
--font-body: 'Roboto', sans-serif;
|
211 |
+
--success-color: #2ecc71; --error-color: #e74c3c;
|
212 |
+
}
|
213 |
+
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
|
214 |
+
body { background-color: var(--bg-primary); font-family: var(--font-body); margin: 0; }
|
215 |
+
.register-page-wrapper { display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 2rem; box-sizing: border-box; }
|
216 |
+
.register-card { background: var(--bg-secondary); width: 100%; max-width: 600px; padding: 2.5rem; border-radius: var(--radius-main); border: 1px solid var(--border-color); box-shadow: 0 15px 40px var(--shadow-color); animation: fadeIn 0.5s ease-out; }
|
217 |
+
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
218 |
+
.register-header { text-align: center; margin-bottom: 2.5rem; color: var(--text-primary); font-size: 2rem; font-weight: 700; }
|
219 |
+
.form-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
|
220 |
+
@media (min-width: 768px) { .form-grid { grid-template-columns: 1fr 1fr; } .full-width { grid-column: 1 / -1; } }
|
221 |
+
.form-group { display: flex; flex-direction: column; }
|
222 |
+
.form-label { margin-bottom: 0.5rem; color: var(--text-secondary); font-weight: 500; }
|
223 |
+
.input-wrapper { position: relative; }
|
224 |
+
.form-input, .form-textarea { width: 100%; padding: 0.9rem 1rem; border: 1px solid var(--border-color); border-radius: var(--radius-inner); font-family: var(--font-body); font-size: 1rem; background-color: var(--bg-primary); color: var(--text-primary); box-sizing: border-box; transition: border-color 0.2s, box-shadow 0.2s; }
|
225 |
+
.form-input:focus, .form-textarea:focus { outline:0; border-color: var(--accent-primary); box-shadow: 0 0 0 3px rgba(0, 170, 255, 0.2); }
|
226 |
+
.input-error { border-color: var(--error-color) !important; }
|
227 |
+
.input-error:focus { box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.2) !important; }
|
228 |
+
.form-textarea { min-height: 80px; resize: vertical; }
|
229 |
+
.password-toggle { position: absolute; right: 1rem; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--text-secondary); cursor: pointer; display: flex; align-items: center; }
|
230 |
+
.field-error-message, .password-warning { font-size: 0.875rem; color: var(--error-color); margin-top: 0.5rem; }
|
231 |
+
.file-upload-btn { display: flex; align-items: center; gap: 0.75rem; padding: 0.9rem 1rem; background-color: var(--bg-primary); border: 1px solid var(--border-color); border-radius: var(--radius-inner); cursor: pointer; transition: background-color 0.2s, border-color 0.2s; overflow: hidden; }
|
232 |
+
.file-upload-btn:hover { background-color: #2a2c3b; }
|
233 |
+
.file-name { color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; text-align: left; }
|
234 |
+
.register-btn { width: 100%; padding: 1rem 1.5rem; border: none; border-radius: var(--radius-inner); background: linear-gradient(to right, var(--accent-primary), var(--accent-secondary)); color: #fff; font-size: 1.1rem; font-weight: 700; cursor: pointer; transition: all 0.2s ease; margin-top: 1.5rem; }
|
235 |
+
.register-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 170, 255, 0.2); }
|
236 |
+
.register-btn:disabled { opacity: 0.6; cursor: not-allowed; }
|
237 |
+
.status-message { text-align: center; margin-top: 1.5rem; padding: 0.8rem; border-radius: var(--radius-inner); font-weight: 500; }
|
238 |
+
.status-success { background-color: rgba(46, 204, 113, 0.15); color: var(--success-color); border: 1px solid var(--success-color); }
|
239 |
+
.status-error { background-color: rgba(231, 76, 60, 0.15); color: var(--error-color); border: 1px solid var(--error-color); }
|
240 |
+
.login-link-wrapper { text-align: center; margin-top: 2rem; color: var(--text-secondary); }
|
241 |
+
.login-link { color: var(--accent-primary); text-decoration: none; font-weight: 500; }
|
242 |
+
`}</style>
|
243 |
+
<div class="register-card">
|
244 |
+
<h1 class="register-header">Create Your Account</h1>
|
245 |
+
<form onSubmit={handleSubmit} novalidate>
|
246 |
+
<div class="form-grid">
|
247 |
+
{/* Username */}
|
248 |
+
<div class="form-group">
|
249 |
+
<label class="form-label" for="user">Username</label>
|
250 |
+
<input id="user" class="form-input" classList={{ 'input-error': !!validationErrors().user }} type="text" value={form().user} onInput={(e) => updateField('user', e.currentTarget.value)} />
|
251 |
+
<Show when={validationErrors().user}><div class="field-error-message">{validationErrors().user}</div></Show>
|
252 |
+
</div>
|
253 |
+
{/* Email */}
|
254 |
+
<div class="form-group">
|
255 |
+
<label class="form-label" for="email">Email Address</label>
|
256 |
+
<input id="email" class="form-input" classList={{ 'input-error': !!validationErrors().email }} type="email" value={form().email} onInput={(e) => updateField('email', e.currentTarget.value)} />
|
257 |
+
<Show when={validationErrors().email}><div class="field-error-message">{validationErrors().email}</div></Show>
|
258 |
+
</div>
|
259 |
+
{/* Nickname */}
|
260 |
+
<div class="form-group">
|
261 |
+
<label class="form-label" for="nickname">Display Name (Nickname)</label>
|
262 |
+
<input id="nickname" class="form-input" classList={{ 'input-error': !!validationErrors().nickname }} type="text" value={form().nickname} onInput={(e) => updateField('nickname', e.currentTarget.value)} />
|
263 |
+
<Show when={validationErrors().nickname}><div class="field-error-message">{validationErrors().nickname}</div></Show>
|
264 |
+
</div>
|
265 |
+
{/* Password */}
|
266 |
+
<div class="form-group">
|
267 |
+
<label class="form-label" for="password">Password</label>
|
268 |
+
<div class="input-wrapper">
|
269 |
+
<input id="password" class="form-input" classList={{ 'input-error': !!validationErrors().pass || !!passwordWarning() }} type={showPassword() ? 'text' : 'password'} value={form().pass} onInput={(e) => updateField('pass', e.currentTarget.value)} />
|
270 |
+
<button type="button" class="password-toggle" onClick={() => setShowPassword(!showPassword())}>
|
271 |
+
<Show when={showPassword()} fallback={<IconEye />}><IconEyeOff /></Show>
|
272 |
+
</button>
|
273 |
+
</div>
|
274 |
+
<Show when={validationErrors().pass}><div class="field-error-message">{validationErrors().pass}</div></Show>
|
275 |
+
<Show when={passwordWarning()}><div class="password-warning">{passwordWarning()}</div></Show>
|
276 |
+
</div>
|
277 |
+
{/* Date of Birth */}
|
278 |
+
<div class="form-group">
|
279 |
+
<label class="form-label" for="dob">Date of Birth</label>
|
280 |
+
<input id="dob" class="form-input" classList={{ 'input-error': !!validationErrors().dob }} type="text" placeholder="Select your birth date..." readOnly />
|
281 |
+
<Show when={validationErrors().dob}><div class="field-error-message">{validationErrors().dob}</div></Show>
|
282 |
+
</div>
|
283 |
+
{/* Country */}
|
284 |
+
<div class="form-group">
|
285 |
+
<label class="form-label" for="country">Country</label>
|
286 |
+
<input id="country" class="form-input" classList={{ 'input-error': !!validationErrors().country }} type="text" value={form().country} onInput={(e) => updateField('country', e.currentTarget.value)} />
|
287 |
+
<Show when={validationErrors().country}><div class="field-error-message">{validationErrors().country}</div></Show>
|
288 |
+
</div>
|
289 |
+
{/* Timezone */}
|
290 |
+
<div class="form-group">
|
291 |
+
<label class="form-label" for="timezone">Timezone</label>
|
292 |
+
<input id="timezone" class="form-input" classList={{ 'input-error': !!validationErrors().timezone }} type="text" value={form().timezone} onInput={(e) => updateField('timezone', e.currentTarget.value)} />
|
293 |
+
<Show when={validationErrors().timezone}><div class="field-error-message">{validationErrors().timezone}</div></Show>
|
294 |
+
</div>
|
295 |
+
{/* Bio */}
|
296 |
+
<div class="form-group full-width">
|
297 |
+
<label class="form-label" for="bio">Short Bio</label>
|
298 |
+
<textarea id="bio" class="form-textarea" classList={{ 'input-error': !!validationErrors().bio }} value={form().bio} onInput={(e) => updateField('bio', e.currentTarget.value)} />
|
299 |
+
<Show when={validationErrors().bio}><div class="field-error-message">{validationErrors().bio}</div></Show>
|
300 |
+
</div>
|
301 |
+
{/* File Uploads */}
|
302 |
+
<div class="form-group full-width">
|
303 |
+
<label class="form-label">Profile Images</label>
|
304 |
+
<div class="form-grid">
|
305 |
+
<button type="button" class="file-upload-btn" classList={{ 'input-error': !!validationErrors().avatar }} onClick={() => avatarInputRef?.click()}>
|
306 |
+
<IconUpload />
|
307 |
+
<span class="file-name" title={avatarFileName()}>{avatarFileName() || 'Choose Avatar'}</span>
|
308 |
+
</button>
|
309 |
+
<button type="button" class="file-upload-btn" classList={{ 'input-error': !!validationErrors().cover_photo }} onClick={() => coverPhotoInputRef?.click()}>
|
310 |
+
<IconUpload />
|
311 |
+
<span class="file-name" title={coverPhotoFileName()}>{coverPhotoFileName() || 'Choose Cover Photo'}</span>
|
312 |
+
</button>
|
313 |
+
</div>
|
314 |
+
<Show when={validationErrors().avatar}><div class="field-error-message">{validationErrors().avatar}</div></Show>
|
315 |
+
<Show when={validationErrors().cover_photo && !validationErrors().avatar}><div class="field-error-message">{validationErrors().cover_photo}</div></Show>
|
316 |
+
<input type="file" accept="image/*" ref={el => avatarInputRef = el} onInput={(e) => handleFileChange('avatar', e)} style={{ display: 'none' }} />
|
317 |
+
<input type="file" accept="image/*" ref={el => coverPhotoInputRef = el} onInput={(e) => handleFileChange('cover_photo', e)} style={{ display: 'none' }} />
|
318 |
+
</div>
|
319 |
+
</div>
|
320 |
+
{/* Submit Button */}
|
321 |
+
<button type="submit" class="register-btn" disabled={isSubmitDisabled()}>
|
322 |
+
{loading() ? 'Creating Account...' : 'Sign Up'}
|
323 |
+
</button>
|
324 |
+
{/* Status Message */}
|
325 |
+
<Show when={status()}>
|
326 |
+
<div class={`status-message ${status().includes('success') ? 'status-success' : 'status-error'}`}>{status()}</div>
|
327 |
+
</Show>
|
328 |
+
{/* Login Link */}
|
329 |
+
<div class="login-link-wrapper">
|
330 |
+
Already have an account? <a href="/private/server/exocore/web/public/login" class="login-link">Login here</a>
|
331 |
+
</div>
|
332 |
+
</form>
|
333 |
+
</div>
|
334 |
+
</div>
|
335 |
+
);
|
336 |
+
}
|
337 |
+
|
338 |
+
render(() => <App />, document.getElementById('app'));
|
exocore-web/public/shell.jsx
ADDED
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { render } from 'solid-js/web';
|
2 |
+
import { createSignal, onMount, Show } from 'solid-js';
|
3 |
+
|
4 |
+
const FullscreenIcon = () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" /></svg>;
|
5 |
+
const ExitFullscreenIcon = () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" /></svg>;
|
6 |
+
const KillIcon = () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18.36 6.64a9 9 0 1 1-12.73 0" /><line x1="12" y1="2" x2="12" y2="12" /></svg>
|
7 |
+
|
8 |
+
function App() {
|
9 |
+
const [loading, setLoading] = createSignal(true);
|
10 |
+
const [status, setStatus] = createSignal('');
|
11 |
+
const [userData, setUserData] = createSignal(null);
|
12 |
+
const [wsStatus, setWsStatus] = createSignal('Disconnected');
|
13 |
+
const [isFullScreen, setIsFullScreen] = createSignal(false);
|
14 |
+
const [promptText, setPromptText] = createSignal('$ ');
|
15 |
+
|
16 |
+
let consoleRef, logOutputRef, inputLineRef;
|
17 |
+
let ansiUpInstance = null;
|
18 |
+
|
19 |
+
async function fetchUserInfo() {
|
20 |
+
setLoading(true);
|
21 |
+
// User info logic is assumed to be correct and unchanged
|
22 |
+
setLoading(false);
|
23 |
+
}
|
24 |
+
|
25 |
+
function appendToLog(line, isCommand = false) {
|
26 |
+
if (!logOutputRef) return;
|
27 |
+
const html = ansiUpInstance ? ansiUpInstance.ansi_to_html(line) : line;
|
28 |
+
const logEntry = document.createElement('div');
|
29 |
+
logEntry.innerHTML = isCommand ? `<span style="color: var(--accent-secondary);">${promptText()}</span>${html}` : html;
|
30 |
+
logOutputRef.appendChild(logEntry);
|
31 |
+
|
32 |
+
while (logOutputRef.children.length > 250) {
|
33 |
+
logOutputRef.removeChild(logOutputRef.firstChild);
|
34 |
+
}
|
35 |
+
if (consoleRef) {
|
36 |
+
requestAnimationFrame(() => consoleRef.scrollTop = consoleRef.scrollHeight);
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
async function sendCommand() {
|
41 |
+
if (!inputLineRef) return;
|
42 |
+
const cmd = inputLineRef.innerText.trim();
|
43 |
+
if (!cmd) return;
|
44 |
+
appendToLog(cmd, true);
|
45 |
+
inputLineRef.innerText = '';
|
46 |
+
try {
|
47 |
+
await fetch('/private/server/exocore/web/shell/sent', {
|
48 |
+
method: 'POST',
|
49 |
+
headers: { 'Content-Type': 'application/json' },
|
50 |
+
body: JSON.stringify({ command: cmd }),
|
51 |
+
});
|
52 |
+
} catch (err) {
|
53 |
+
appendToLog(`\x1b[31mFailed to send command: ${err.message}\x1b[0m`);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
async function handleKillShellCommand() {
|
58 |
+
appendToLog('\x1b[33mINFO: Sending kill command...\x1b[0m');
|
59 |
+
try {
|
60 |
+
await fetch('/private/server/exocore/web/shell/kill', { method: 'POST' });
|
61 |
+
} catch (err) {
|
62 |
+
appendToLog(`\x1b[31mERROR: Could not send kill command: ${err.message}\x1b[0m`);
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
function toggleFullScreen() {
|
67 |
+
const el = document.querySelector('.console-wrapper');
|
68 |
+
if (!el) return;
|
69 |
+
if (!document.fullscreenElement) {
|
70 |
+
el.requestFullscreen().catch(err => appendToLog(`\x1b[31mFullscreen Error: ${err.message}\x1b[0m`));
|
71 |
+
} else {
|
72 |
+
document.exitFullscreen();
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
onMount(() => {
|
77 |
+
const fontLink = document.createElement('link');
|
78 |
+
fontLink.href = 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&family=Fira+Code:wght@400;500&display=swap';
|
79 |
+
fontLink.rel = 'stylesheet';
|
80 |
+
document.head.appendChild(fontLink);
|
81 |
+
|
82 |
+
const ansiScript = document.createElement('script');
|
83 |
+
ansiScript.src = 'https://cdn.jsdelivr.net/npm/[email protected]/ansi_up.min.js';
|
84 |
+
ansiScript.onload = () => {
|
85 |
+
if (typeof AnsiUp !== 'undefined') {
|
86 |
+
ansiUpInstance = new AnsiUp();
|
87 |
+
ansiUpInstance.use_classes = false;
|
88 |
+
}
|
89 |
+
};
|
90 |
+
document.head.appendChild(ansiScript);
|
91 |
+
|
92 |
+
fetchUserInfo();
|
93 |
+
|
94 |
+
const wsUrl = `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.host}/private/server/exocore/web/ws/shell`;
|
95 |
+
function connectWebSocket() {
|
96 |
+
const ws = new WebSocket(wsUrl);
|
97 |
+
ws.onopen = () => setWsStatus('Connected');
|
98 |
+
ws.onclose = () => {
|
99 |
+
setWsStatus('Disconnected');
|
100 |
+
setTimeout(connectWebSocket, 2000);
|
101 |
+
};
|
102 |
+
ws.onerror = () => setWsStatus('Error');
|
103 |
+
ws.onmessage = (e) => {
|
104 |
+
try {
|
105 |
+
const message = JSON.parse(e.data);
|
106 |
+
if (message.type === 'prompt') {
|
107 |
+
setPromptText(message.data);
|
108 |
+
} else {
|
109 |
+
appendToLog(message.data);
|
110 |
+
}
|
111 |
+
} catch (err) {
|
112 |
+
appendToLog(e.data);
|
113 |
+
}
|
114 |
+
};
|
115 |
+
}
|
116 |
+
connectWebSocket();
|
117 |
+
document.addEventListener('fullscreenchange', () => setIsFullScreen(!!document.fullscreenElement));
|
118 |
+
consoleRef?.addEventListener('click', (e) => {
|
119 |
+
if (inputLineRef && e.target !== inputLineRef) {
|
120 |
+
inputLineRef.focus();
|
121 |
+
}
|
122 |
+
});
|
123 |
+
});
|
124 |
+
|
125 |
+
return (
|
126 |
+
<div class="main-wrapper-shell">
|
127 |
+
<style>{`
|
128 |
+
:root {
|
129 |
+
--bg-primary: #111217; --bg-secondary: #1a1b23; --bg-tertiary: #0D0E12;
|
130 |
+
--text-primary: #e0e0e0; --text-secondary: #8a8f98; --accent-primary: #00aaff;
|
131 |
+
--accent-secondary: #0088cc; --danger-primary: #e74c3c; --danger-secondary: #c0392b;
|
132 |
+
--border-color: rgba(255, 255, 255, 0.1); --shadow-color: rgba(0, 0, 0, 0.5);
|
133 |
+
--font-body: 'Roboto', sans-serif; --font-console: 'Fira Code', monospace;
|
134 |
+
--radius-main: 16px; --radius-inner: 10px;
|
135 |
+
}
|
136 |
+
body { background-color: var(--bg-primary); color: var(--text-primary); font-family: var(--font-body); margin: 0; }
|
137 |
+
.main-wrapper-shell { display: flex; justify-content: center; align-items: center; padding: 4vh 2vw; min-height: 100vh; }
|
138 |
+
.app-container-shell { background: var(--bg-secondary); padding: 2rem; width: 100%; max-width: 900px; border-radius: var(--radius-main); border: 1px solid var(--border-color); box-shadow: 0 15px 40px var(--shadow-color); display: flex; flex-direction: column; gap: 1.5rem; }
|
139 |
+
.greeting-header-shell { display: flex; justify-content: space-between; align-items: center; }
|
140 |
+
.greeting-shell { font-size: 1.75rem; font-weight: 700; color: #fff; }
|
141 |
+
.user-welcome-shell { font-size: 0.9rem; color: var(--text-secondary); }
|
142 |
+
.console-wrapper { border-radius: var(--radius-inner); background: var(--bg-tertiary); box-shadow: inset 0 4px 15px rgba(0,0,0,0.4); overflow: hidden; display: flex; flex-direction: column; height: 500px; border: 1px solid var(--border-color); }
|
143 |
+
.console-wrapper:fullscreen { width: 100vw; height: 100vh; border-radius: 0; border: none; }
|
144 |
+
.console-header { background: var(--bg-secondary); padding: 0.6rem 1rem; display: flex; align-items: center; border-bottom: 1px solid var(--border-color); position: relative; }
|
145 |
+
.console-header-dots { display: flex; gap: 8px; }
|
146 |
+
.console-header-dots span { width: 12px; height: 12px; border-radius: 50%; }
|
147 |
+
.console-header-dots .red-dot { background-color: #ff5f57; }
|
148 |
+
.console-header-dots .yellow-dot { background-color: #ffbd2e; }
|
149 |
+
.console-header-dots .green-dot { background-color: #28c940; }
|
150 |
+
.fullscreen-btn { position: absolute; top: 50%; right: 1rem; transform: translateY(-50%); background: none; border: none; color: var(--text-secondary); cursor: pointer; padding: 4px; border-radius: 4px; display: flex; align-items: center; justify-content: center; transition: color 0.2s ease, background-color 0.2s ease; }
|
151 |
+
.fullscreen-btn:hover { color: var(--text-primary); background-color: rgba(255,255,255,0.1); }
|
152 |
+
.console-container { flex-grow: 1; padding: 1rem; font-family: var(--font-console); font-size: 14px; line-height: 1.6; overflow-y: auto; cursor: text; display: flex; flex-direction: column; }
|
153 |
+
.log-output { flex-grow: 1; white-space: pre-wrap; word-break: break-word; }
|
154 |
+
.input-area { display: flex; margin-top: 4px; }
|
155 |
+
.prompt-text-display { color: var(--accent-primary); margin-right: 8px; user-select: none; }
|
156 |
+
.input-line { flex-grow: 1; outline: none; color: var(--text-primary); caret-color: var(--text-primary); }
|
157 |
+
.bottom-bar { display: flex; justify-content: space-between; align-items: center; gap: 1rem; }
|
158 |
+
.ws-box { padding: 0.4rem 1rem; border-radius: 99px; font-weight: 500; font-size: 0.8rem; transition: all 0.3s ease; font-family: var(--font-console); }
|
159 |
+
.ws-box.connected { background-color: rgba(46, 204, 113, 0.15); color: #2ecc71; }
|
160 |
+
.ws-box.disconnected, .ws-box.error { background-color: rgba(231, 76, 60, 0.15); color: var(--danger-primary); }
|
161 |
+
.controls-area { display: flex; gap: 0.75rem; }
|
162 |
+
.btn-shell { display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 1.2rem; font-size: 0.9rem; font-weight: 500; color: #fff; border: 1px solid var(--border-color); border-radius: var(--radius-inner); background-color: var(--bg-secondary); cursor: pointer; transition: all 0.2s ease; }
|
163 |
+
.btn-shell:hover { background-color: var(--border-color); border-color: rgba(255,255,255,0.2); transform: translateY(-2px); }
|
164 |
+
.btn-shell.danger { border-color: var(--danger-primary); color: var(--danger-primary); }
|
165 |
+
.btn-shell.danger:hover { background-color: var(--danger-primary); color: #fff; }
|
166 |
+
`}</style>
|
167 |
+
|
168 |
+
<Show when={!loading()} fallback={<div>Loading Shell...</div>}>
|
169 |
+
<div class="app-container-shell">
|
170 |
+
<div class="greeting-header-shell">
|
171 |
+
<h2 class="greeting-shell">Interactive Shell</h2>
|
172 |
+
</div>
|
173 |
+
|
174 |
+
<div class="console-wrapper">
|
175 |
+
<div class="console-header">
|
176 |
+
<div class="console-header-dots">
|
177 |
+
<span class="red-dot"></span><span class="yellow-dot"></span><span class="green-dot"></span>
|
178 |
+
</div>
|
179 |
+
<button class="fullscreen-btn" onClick={toggleFullScreen} title={isFullScreen() ? 'Exit Fullscreen' : 'Enter Fullscreen'}>
|
180 |
+
<Show when={isFullScreen()} fallback={<FullscreenIcon />}>
|
181 |
+
<ExitFullscreenIcon />
|
182 |
+
</Show>
|
183 |
+
</button>
|
184 |
+
</div>
|
185 |
+
<div class="console-container" ref={consoleRef}>
|
186 |
+
<div class="log-output" ref={logOutputRef}></div>
|
187 |
+
<div class="input-area">
|
188 |
+
<span class="prompt-text-display">{promptText()}</span>
|
189 |
+
<div class="input-line"
|
190 |
+
contenteditable="true"
|
191 |
+
ref={inputLineRef}
|
192 |
+
onKeyDown={e => e.key === 'Enter' && (e.preventDefault(), sendCommand())}
|
193 |
+
spellcheck="false"
|
194 |
+
/>
|
195 |
+
</div>
|
196 |
+
</div>
|
197 |
+
</div>
|
198 |
+
|
199 |
+
<div class="bottom-bar">
|
200 |
+
<div class="ws-box" classList={{ connected: wsStatus() === 'Connected', disconnected: wsStatus() !== 'Connected' }}>
|
201 |
+
{wsStatus()}
|
202 |
+
</div>
|
203 |
+
<div class="controls-area">
|
204 |
+
<button class="btn-shell danger" onClick={handleKillShellCommand}>
|
205 |
+
<KillIcon/> Kill Session
|
206 |
+
</button>
|
207 |
+
</div>
|
208 |
+
</div>
|
209 |
+
|
210 |
+
</div>
|
211 |
+
</Show>
|
212 |
+
</div>
|
213 |
+
);
|
214 |
+
}
|
215 |
+
render(() => <App />, document.getElementById('app'));
|