From 4211692312bc0f58c5dfbebfb5ca48409eb776bd Mon Sep 17 00:00:00 2001 From: Georgiy Syralev Date: Sun, 12 Oct 2025 15:20:39 +0300 Subject: [PATCH] =?UTF-8?q?ssh!=20=D0=B8=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/copilot-instructions.md | 45 +- node_modules/.package-lock.json | 21 + ospabhost/README.md | 1 + ospabhost/backend/package-lock.json | 361 ++++----- ospabhost/backend/package.json | 12 +- ospabhost/backend/prisma/schema.prisma | 24 + ospabhost/backend/proxmox/proxmoxApi.ts | 1 + ospabhost/backend/src/index.ts | 39 +- ospabhost/backend/src/modules/os/os.routes.ts | 6 +- .../backend/src/modules/server/proxmoxApi.ts | 16 + .../src/modules/server/server.console.ts | 70 ++ .../src/modules/server/server.controller.ts | 21 +- .../src/modules/tariff/tariff.routes.ts | 2 +- ospabhost/backend/tsconfig.json | 2 +- ospabhost/frontend/index.html | 4 +- ospabhost/frontend/package-lock.json | 491 +----------- ospabhost/frontend/package.json | 3 +- .../public/android-chrome-192x192.png | Bin 0 -> 12554 bytes .../public/android-chrome-512x512.png | Bin 0 -> 39920 bytes .../frontend/public/apple-touch-icon.png | Bin 0 -> 11276 bytes ospabhost/frontend/public/favicon-16x16.png | Bin 0 -> 455 bytes ospabhost/frontend/public/favicon-32x32.png | Bin 0 -> 1148 bytes ospabhost/frontend/public/favicon.ico | Bin 0 -> 15406 bytes ospabhost/frontend/public/me.jpg | Bin 0 -> 51854 bytes ospabhost/frontend/public/site.webmanifest | 1 + ospabhost/frontend/public/vite.svg | 1 - ospabhost/frontend/src/assets/logo.svg | 80 ++ ospabhost/frontend/src/assets/react.svg | 1 - .../frontend/src/components/ServerConsole.tsx | 120 +++ .../src/components/dashboardtempl.tsx | 3 +- ospabhost/frontend/src/components/footer.tsx | 4 + ospabhost/frontend/src/components/header.tsx | 10 +- .../frontend/src/components/pagetempl.tsx | 2 +- ospabhost/frontend/src/pages/about.tsx | 37 +- .../frontend/src/pages/dashboard/billing.tsx | 2 +- .../frontend/src/pages/dashboard/checkout.tsx | 10 +- .../src/pages/dashboard/checkverification.tsx | 8 +- .../frontend/src/pages/dashboard/mainpage.tsx | 11 +- .../src/pages/dashboard/serverpanel.tsx | 724 +++++------------- .../frontend/src/pages/dashboard/servers.tsx | 5 +- .../src/pages/dashboard/ticketresponse.tsx | 6 +- .../frontend/src/pages/dashboard/tickets.tsx | 10 +- ospabhost/frontend/src/pages/login.tsx | 2 +- ospabhost/frontend/src/pages/register.tsx | 2 +- ospabhost/frontend/src/pages/tariffs.tsx | 48 +- ospabhost/package.json | 4 +- ospabhost/postcss.config.js | 6 + ospabhost/tailwind.config.js | 10 + package-lock.json | 24 +- package.json | 3 +- 50 files changed, 920 insertions(+), 1333 deletions(-) create mode 100644 ospabhost/README.md create mode 100644 ospabhost/backend/src/modules/server/server.console.ts create mode 100644 ospabhost/frontend/public/android-chrome-192x192.png create mode 100644 ospabhost/frontend/public/android-chrome-512x512.png create mode 100644 ospabhost/frontend/public/apple-touch-icon.png create mode 100644 ospabhost/frontend/public/favicon-16x16.png create mode 100644 ospabhost/frontend/public/favicon-32x32.png create mode 100644 ospabhost/frontend/public/favicon.ico create mode 100644 ospabhost/frontend/public/me.jpg create mode 100644 ospabhost/frontend/public/site.webmanifest delete mode 100644 ospabhost/frontend/public/vite.svg create mode 100644 ospabhost/frontend/src/assets/logo.svg delete mode 100644 ospabhost/frontend/src/assets/react.svg create mode 100644 ospabhost/frontend/src/components/ServerConsole.tsx create mode 100644 ospabhost/postcss.config.js create mode 100644 ospabhost/tailwind.config.js diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b8c0baf..756cd90 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,27 +1,31 @@ # Copilot Instructions for Ospabhost 8.1 -## Архитектура проекта -- **Монорепозиторий**: две основные части — `backend` (Express, TypeScript, Prisma) и `frontend` (React, Vite, TypeScript). + +## Архитектура и основные компоненты +- **Монорепозиторий**: две части — `backend` (Express, TypeScript, Prisma) и `frontend` (React, Vite, TypeScript). - **Backend**: - - Основной сервер: `backend/src/index.ts` — точка входа, маршрутизация, CORS, логирование. - - Модули: `backend/src/modules/*` — бизнес-логика по доменам (auth, ticket, check, os, server, tariff). - - Интеграция с Proxmox: через API, см. `backend/src/modules/server/proxmoxApi.ts`. - - ORM: Prisma, схема — `backend/prisma/schema.prisma`. - - Статические файлы чеков: `backend/uploads/checks`. + - Точка входа: `backend/src/index.ts` (Express, маршруты `/api/*`, CORS, логирование). + - Модули: `backend/src/modules/*` — домены (auth, ticket, check, os, server, tariff), каждый экспортирует маршруты и сервисы. + - Интеграция с Proxmox: через API, см. `backend/src/modules/server/proxmoxApi.ts` (создание/управление контейнерами, смена пароля root, статистика). + - ORM: Prisma, схема — `backend/prisma/schema.prisma`, миграции и seed-скрипты — в `backend/prisma/`. + - Статические файлы чеков: `backend/uploads/checks` (доступны по `/uploads/checks`). - **Frontend**: - SPA на React + Vite, точка входа: `frontend/src/main.tsx`. - Страницы: `frontend/src/pages/*`, компоненты: `frontend/src/components/*`. - - Контекст авторизации: `frontend/src/context/authcontext.tsx`, `useAuth.ts`. + - Авторизация: `frontend/src/context/authcontext.tsx`, `useAuth.ts` (контекст, хуки). + - Дашборд: `frontend/src/pages/dashboard/mainpage.tsx` — реализует сайдбар, вкладки, загрузку данных пользователя, обработку токена, обновление данных через кастомное событие `userDataUpdate`. -## Важные паттерны и конвенции -- **Маршруты API**: начинаются с `/api/`, см. `backend/src/index.ts`. -- **Модули backend**: каждый домен — отдельная папка, экспортирует маршруты и сервисы. -- **Работа с Proxmox**: все операции (создание контейнера, управление, статистика) через функции из `proxmoxApi.ts`. -- **Статусные поля**: для сущностей (Server, Check, Ticket) используются строковые статусы (`creating`, `running`, `pending`, `open` и т.д.). +## Ключевые паттерны и конвенции +- **API**: все маршруты backend — с префиксом `/api/`. +- **Модули backend**: каждый домен — отдельная папка, экспортирует маршруты и сервисы (см. пример: `server/proxmoxApi.ts`). +- **Работа с Proxmox**: все операции через функции из `proxmoxApi.ts`, параметры берутся из `.env`. +- **Статусные поля**: для Server, Check, Ticket — строковые статусы (`creating`, `running`, `pending`, `open` и др.). - **Пароли**: генерируются через `generateSecurePassword` (см. `proxmoxApi.ts`). - **Описание тарифа**: парсится для выделения ресурсов (ядра, RAM, SSD) при создании контейнера. +- **Frontend**: авторизация через контекст, проверка токена, автоматический logout при ошибке 401. +- **Дашборд**: вкладки и права оператора определяются по полю `operator` в userData, обновление данных через событие `userDataUpdate`. -## Сборка и запуск +## Сборка, запуск и workflow - **Backend**: - `npm run dev` — запуск с hot-reload (ts-node-dev). - `npm run build` — компиляция TypeScript. @@ -32,9 +36,9 @@ - `npm run preview` — предпросмотр production-сборки. - `npm run lint` — проверка ESLint. -## Взаимодействие компонентов -- **Frontend ↔ Backend**: через REST API, адреса `/api/*`. -- **Backend ↔ Proxmox**: через HTTP API, параметры берутся из `.env`. +## Интеграции и взаимодействие +- **Frontend ↔ Backend**: через REST API (`/api/*`), авторизация через JWT-токен в localStorage. +- **Backend ↔ Proxmox**: через HTTP API, параметры из `.env`. - **Prisma**: миграции и seed-скрипты — в `backend/prisma/`. ## Внешние зависимости @@ -45,15 +49,16 @@ - `backend/src/index.ts` — точка входа, маршрутизация. - `backend/src/modules/server/proxmoxApi.ts` — интеграция с Proxmox. - `backend/prisma/schema.prisma` — схема данных. -- `frontend/src/pages/*` — страницы SPA. +- `frontend/src/pages/dashboard/mainpage.tsx` — дашборд, обработка токена, сайдбар, вкладки. - `frontend/src/context/authcontext.tsx` — авторизация. -## Особенности +## Особенности и conventions - **CORS**: разрешены только локальные адреса для разработки. - **Логирование**: каждый запрос логируется с датой и методом. - **Статические файлы**: чеки доступны по `/uploads/checks`. - **Пароли root**: генерируются и меняются через API Proxmox. +- **Frontend**: сайдбар и вкладки строятся динамически, права оператора определяются по userData. --- -_Обновите этот файл при изменении архитектуры или ключевых паттернов. Для уточнения разделов — дайте обратную связь!_ \ No newline at end of file +_Обновляйте этот файл при изменении архитектуры, workflow или паттернов. Для уточнения разделов — дайте обратную связь!_ \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index e77f371..6e14c05 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -2606,6 +2606,18 @@ "node": ">= 0.6.0" } }, + "node_modules/proxmox-api": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/proxmox-api/-/proxmox-api-1.1.1.tgz", + "integrity": "sha512-2qH7pxKBBHa7WtEBmxPaBY2FZEH2R04hqr9zD9PmErLzJ7RGGcfNcXoS/v5G4vBM2Igmnx0EAYBstPwwfDwHnA==", + "license": "GPL-3.0", + "dependencies": { + "undici": "^6.19.8" + }, + "funding": { + "url": "https://github.com/sponsors/urielch" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3450,6 +3462,15 @@ "node": ">=14.17" } }, + "node_modules/undici": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.22.0.tgz", + "integrity": "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/undici-types": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.11.0.tgz", diff --git a/ospabhost/README.md b/ospabhost/README.md new file mode 100644 index 0000000..4ce7e00 --- /dev/null +++ b/ospabhost/README.md @@ -0,0 +1 @@ +Ospab.host site version 8 diff --git a/ospabhost/backend/package-lock.json b/ospabhost/backend/package-lock.json index ff582fd..d786f14 100644 --- a/ospabhost/backend/package-lock.json +++ b/ospabhost/backend/package-lock.json @@ -10,6 +10,8 @@ "license": "ISC", "dependencies": { "@prisma/client": "^6.16.2", + "@types/ssh2": "^1.15.5", + "@types/ws": "^8.18.1", "axios": "^1.12.2", "bcrypt": "^6.0.0", "bcryptjs": "^2.4.3", @@ -18,8 +20,10 @@ "express": "^4.21.2", "jsonwebtoken": "^9.0.2", "multer": "^2.0.2", - "nodemailer": "^6.9.16", - "socket.io": "^4.8.1" + "proxmox-api": "^1.1.1", + "ssh2": "^1.17.0", + "ws": "^8.18.3", + "xterm": "^5.3.0" }, "devDependencies": { "@types/bcrypt": "^6.0.0", @@ -29,7 +33,7 @@ "@types/jsonwebtoken": "^9.0.10", "@types/multer": "^2.0.0", "@types/node": "^20.12.12", - "@types/nodemailer": "^6.4.17", + "@types/xterm": "^2.0.3", "prisma": "^6.16.2", "ts-node-dev": "^2.0.0", "typescript": "^5.4.5" @@ -161,12 +165,6 @@ "@prisma/debug": "6.16.2" } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "license": "MIT" - }, "node_modules/@standard-schema/spec": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", @@ -244,6 +242,7 @@ "version": "2.8.19", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -326,16 +325,6 @@ "undici-types": "~6.21.0" } }, - "node_modules/@types/nodemailer": { - "version": "6.4.17", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.17.tgz", - "integrity": "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -373,6 +362,30 @@ "@types/send": "*" } }, + "node_modules/@types/ssh2": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.5.tgz", + "integrity": "sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==", + "license": "MIT", + "dependencies": { + "@types/node": "^18.11.18" + } + }, + "node_modules/@types/ssh2/node_modules/@types/node": { + "version": "18.19.127", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.127.tgz", + "integrity": "sha512-gSjxjrnKXML/yo0BO099uPixMqfpJU0TKYjpfLU7TrtA2WWDki412Np/RSTPRil1saKBhvVVKzVx/p/6p94nVA==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/ssh2/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" + }, "node_modules/@types/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", @@ -387,6 +400,22 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/xterm": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/xterm/-/xterm-2.0.3.tgz", + "integrity": "sha512-Owlz29ThHtn2RQry87juaNYeIc4Dr8ykLLX0JKKt4SdO6ujwJnsXCpBAr6bwo/f4L3xSfM9KA7OnPPf9Xit6tA==", + "dev": true, + "license": "MIT" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -459,6 +488,15 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -483,15 +521,6 @@ "dev": true, "license": "MIT" }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "license": "MIT", - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, "node_modules/bcrypt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", @@ -506,6 +535,15 @@ "node": ">= 18" } }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -585,6 +623,15 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, + "node_modules/buildcheck": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", + "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -789,6 +836,20 @@ "node": ">= 0.10" } }, + "node_modules/cpu-features": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", + "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "~0.0.6", + "nan": "^2.19.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -948,67 +1009,6 @@ "node": ">= 0.8" } }, - "node_modules/engine.io": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", - "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", - "license": "MIT", - "dependencies": { - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/engine.io/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -1767,6 +1767,13 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/nan": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz", + "integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==", + "license": "MIT", + "optional": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -1803,15 +1810,6 @@ "node-gyp-build-test": "build-test.js" } }, - "node_modules/nodemailer": { - "version": "6.9.16", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz", - "integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==", - "license": "MIT-0", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1989,6 +1987,18 @@ } } }, + "node_modules/proxmox-api": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/proxmox-api/-/proxmox-api-1.1.1.tgz", + "integrity": "sha512-2qH7pxKBBHa7WtEBmxPaBY2FZEH2R04hqr9zD9PmErLzJ7RGGcfNcXoS/v5G4vBM2Igmnx0EAYBstPwwfDwHnA==", + "license": "GPL-3.0", + "dependencies": { + "undici": "^6.19.8" + }, + "funding": { + "url": "https://github.com/sponsors/urielch" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2308,116 +2318,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/socket.io": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", - "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.6.0", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", - "license": "MIT", - "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" - } - }, - "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io-adapter/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/socket.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -2439,6 +2339,23 @@ "source-map": "^0.6.0" } }, + "node_modules/ssh2": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.17.0.tgz", + "integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==", + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.10", + "nan": "^2.23.0" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -2667,6 +2584,12 @@ "strip-json-comments": "^2.0.0" } }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -2700,6 +2623,15 @@ "node": ">=14.17" } }, + "node_modules/undici": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.22.0.tgz", + "integrity": "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -2754,9 +2686,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -2783,6 +2715,13 @@ "node": ">=0.4" } }, + "node_modules/xterm": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz", + "integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==", + "deprecated": "This package is now deprecated. Move to @xterm/xterm instead.", + "license": "MIT" + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/ospabhost/backend/package.json b/ospabhost/backend/package.json index 4f02ecb..fea0902 100644 --- a/ospabhost/backend/package.json +++ b/ospabhost/backend/package.json @@ -5,7 +5,7 @@ "main": "dist/index.js", "scripts": { "dev": "ts-node-dev --respawn --transpile-only src/index.ts", - "start": "node dist/index.js", + "start": "node dist/src/index.js", "build": "tsc" }, "keywords": [], @@ -13,6 +13,8 @@ "license": "ISC", "dependencies": { "@prisma/client": "^6.16.2", + "@types/ssh2": "^1.15.5", + "@types/ws": "^8.18.1", "axios": "^1.12.2", "bcrypt": "^6.0.0", "bcryptjs": "^2.4.3", @@ -21,8 +23,10 @@ "express": "^4.21.2", "jsonwebtoken": "^9.0.2", "multer": "^2.0.2", - "nodemailer": "^6.9.16", - "socket.io": "^4.8.1" + "proxmox-api": "^1.1.1", + "ssh2": "^1.17.0", + "ws": "^8.18.3", + "xterm": "^5.3.0" }, "devDependencies": { "@types/bcrypt": "^6.0.0", @@ -32,7 +36,7 @@ "@types/jsonwebtoken": "^9.0.10", "@types/multer": "^2.0.0", "@types/node": "^20.12.12", - "@types/nodemailer": "^6.4.17", + "@types/xterm": "^2.0.3", "prisma": "^6.16.2", "ts-node-dev": "^2.0.0", "typescript": "^5.4.5" diff --git a/ospabhost/backend/prisma/schema.prisma b/ospabhost/backend/prisma/schema.prisma index 2346b28..c4a58c7 100644 --- a/ospabhost/backend/prisma/schema.prisma +++ b/ospabhost/backend/prisma/schema.prisma @@ -17,8 +17,12 @@ model Tariff { description String? createdAt DateTime @default(now()) servers Server[] + +@@map("tariff") } + + model OperatingSystem { id Int @id @default(autoincrement()) name String @unique @@ -26,6 +30,8 @@ model OperatingSystem { template String? // путь к шаблону для контейнера createdAt DateTime @default(now()) servers Server[] + + @@map("operatingsystem") } model Server { @@ -60,6 +66,8 @@ model Server { diskUsage Float? @default(0) networkIn Float? @default(0) networkOut Float? @default(0) + + @@map("server") } model User { @@ -76,6 +84,8 @@ model User { balance Float @default(0) servers Server[] notifications Notification[] + + @@map("user") } model Check { @@ -86,6 +96,8 @@ model Check { fileUrl String createdAt DateTime @default(now()) user User @relation("UserChecks", fields: [userId], references: [id]) + +@@map("check") } model Plan { @@ -98,6 +110,8 @@ model Plan { userId Int owner User @relation("UserPlans", fields: [userId], references: [id]) services Service[] @relation("PlanServices") + +@@map("plan") } model Service { @@ -106,6 +120,8 @@ model Service { price Float planId Int? plan Plan? @relation("PlanServices", fields: [planId], references: [id]) + +@@map("service") } model Ticket { @@ -118,6 +134,8 @@ model Ticket { updatedAt DateTime @updatedAt responses Response[] @relation("TicketResponses") user User? @relation("UserTickets", fields: [userId], references: [id]) + +@@map("ticket") } model Response { @@ -128,6 +146,10 @@ model Response { createdAt DateTime @default(now()) ticket Ticket @relation("TicketResponses", fields: [ticketId], references: [id]) operator User @relation("OperatorResponses", fields: [operatorId], references: [id]) + +@@map("response") + + } model Notification { id Int @id @default(autoincrement()) @@ -136,4 +158,6 @@ model Notification { title String message String createdAt DateTime @default(now()) + +@@map("notification") } \ No newline at end of file diff --git a/ospabhost/backend/proxmox/proxmoxApi.ts b/ospabhost/backend/proxmox/proxmoxApi.ts index ec79e7e..7aae82f 100644 --- a/ospabhost/backend/proxmox/proxmoxApi.ts +++ b/ospabhost/backend/proxmox/proxmoxApi.ts @@ -43,3 +43,4 @@ export async function createContainer({ vmid, hostname, password, ostemplate, st throw new Error('Ошибка создания контейнера: ' + (err instanceof Error ? err.message : err)); } } + diff --git a/ospabhost/backend/src/index.ts b/ospabhost/backend/src/index.ts index 3b8ea4e..99947b1 100644 --- a/ospabhost/backend/src/index.ts +++ b/ospabhost/backend/src/index.ts @@ -1,8 +1,6 @@ import express from 'express'; import cors from 'cors'; import dotenv from 'dotenv'; -import http from 'http'; -import { Server as SocketIOServer } from 'socket.io'; import authRoutes from './modules/auth/auth.routes'; import ticketRoutes from './modules/ticket/ticket.routes'; import checkRoutes from './modules/check/check.routes'; @@ -10,25 +8,18 @@ import proxmoxRoutes from '../proxmox/proxmox.routes'; import tariffRoutes from './modules/tariff'; import osRoutes from './modules/os'; import serverRoutes from './modules/server'; -import { MonitoringService } from './modules/server/monitoring.service'; dotenv.config(); const app = express(); -const server = http.createServer(app); - -// Настройка Socket.IO с CORS -const io = new SocketIOServer(server, { - cors: { - origin: ['http://localhost:3000', 'http://localhost:5173'], - methods: ['GET', 'POST'], - credentials: true - } -}); // ИСПРАВЛЕНО: более точная настройка CORS app.use(cors({ - origin: ['http://localhost:3000', 'http://localhost:5173'], // Vite обычно использует 5173 + origin: [ + 'http://localhost:3000', + 'http://localhost:5173', + 'https://ospab.host' + ], // Vite обычно использует 5173 credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization'] @@ -78,13 +69,19 @@ app.use('/api/server', serverRoutes); const PORT = process.env.PORT || 5000; -// Инициализация сервиса мониторинга -const monitoringService = new MonitoringService(io); -monitoringService.startMonitoring(); +import { setupConsoleWSS } from './modules/server/server.console'; +import https from 'https'; +import fs from 'fs'; -server.listen(PORT, () => { - console.log(`🚀 Сервер запущен на порту ${PORT}`); +const sslOptions = { + key: fs.readFileSync('/etc/apache2/ssl/ospab.host.key'), + cert: fs.readFileSync('/etc/apache2/ssl/ospab.host.crt'), +}; + +const httpsServer = https.createServer(sslOptions, app); +setupConsoleWSS(httpsServer); + +httpsServer.listen(PORT, () => { + console.log(`🚀 HTTPS сервер запущен на порту ${PORT}`); console.log(`📊 База данных: ${process.env.DATABASE_URL ? 'подключена' : 'НЕ НАСТРОЕНА'}`); - console.log(`🔌 WebSocket сервер запущен`); - console.log(`📡 Мониторинг серверов активен`); }); \ No newline at end of file diff --git a/ospabhost/backend/src/modules/os/os.routes.ts b/ospabhost/backend/src/modules/os/os.routes.ts index ae2d675..bb8410a 100644 --- a/ospabhost/backend/src/modules/os/os.routes.ts +++ b/ospabhost/backend/src/modules/os/os.routes.ts @@ -1,10 +1,14 @@ + import { Router } from 'express'; import { PrismaClient } from '@prisma/client'; +import { authMiddleware } from '../auth/auth.middleware'; const router = Router(); const prisma = new PrismaClient(); -// GET /api/os — получить все ОС +router.use(authMiddleware); + +// GET /api/os — получить все ОС (только для авторизованных) router.get('/', async (req, res) => { try { const oses = await prisma.operatingSystem.findMany(); diff --git a/ospabhost/backend/src/modules/server/proxmoxApi.ts b/ospabhost/backend/src/modules/server/proxmoxApi.ts index 4399b6b..a75af12 100644 --- a/ospabhost/backend/src/modules/server/proxmoxApi.ts +++ b/ospabhost/backend/src/modules/server/proxmoxApi.ts @@ -1,3 +1,19 @@ +// Смена root-пароля через SSH (для LXC) +import { exec } from 'child_process'; + +export async function changeRootPasswordSSH(vmid: number): Promise<{ status: string; password?: string; message?: string }> { + const newPassword = generateSecurePassword(); + return new Promise((resolve) => { + exec(`ssh -o StrictHostKeyChecking=no root@${process.env.PROXMOX_NODE} pct set ${vmid} --password ${newPassword}`, (err, stdout, stderr) => { + if (err) { + console.error('Ошибка смены пароля через SSH:', stderr); + resolve({ status: 'error', message: stderr }); + } else { + resolve({ status: 'success', password: newPassword }); + } + }); + }); +} import axios from 'axios'; import crypto from 'crypto'; import dotenv from 'dotenv'; diff --git a/ospabhost/backend/src/modules/server/server.console.ts b/ospabhost/backend/src/modules/server/server.console.ts new file mode 100644 index 0000000..16f49cc --- /dev/null +++ b/ospabhost/backend/src/modules/server/server.console.ts @@ -0,0 +1,70 @@ +import { Server as WebSocketServer, WebSocket } from 'ws'; +import { Client as SSHClient } from 'ssh2'; +import dotenv from 'dotenv'; +import { IncomingMessage } from 'http'; +import { Server as HttpServer } from 'http'; +dotenv.config(); + +export function setupConsoleWSS(server: HttpServer) { + const wss = new WebSocketServer({ noServer: true }); + + wss.on('connection', (ws: WebSocket, req: IncomingMessage) => { + const url = req.url || ''; + const match = url.match(/\/api\/server\/(\d+)\/console/); + const vmid = match ? match[1] : null; + if (!vmid) { + ws.close(); + return; + } + + // Получаем IP и root-пароль из БД (упрощённо) + // Здесь можно добавить реальный запрос к Prisma + const host = process.env.PROXMOX_IP || process.env.PROXMOX_NODE; + const username = 'root'; + const password = process.env.PROXMOX_ROOT_PASSWORD; + + const ssh = new SSHClient(); + const port = process.env.PROXMOX_SSH_PORT ? Number(process.env.PROXMOX_SSH_PORT) : 22; + ssh.on('ready', () => { + ssh.shell((err: Error | undefined, stream: any) => { + if (err) { + ws.send('Ошибка запуска shell: ' + err.message); + ws.close(); + ssh.end(); + return; + } + ws.on('message', (msg: string | Buffer) => { + stream.write(msg.toString()); + }); + stream.on('data', (data: Buffer) => { + ws.send(data.toString()); + }); + stream.on('close', () => { + ws.close(); + ssh.end(); + }); + }); + }).connect({ + host, + port, + username, + password, + hostVerifier: (hash: string) => { + console.log('SSH fingerprint:', hash); + return true; // всегда принимаем fingerprint + } + }); + + ws.on('close', () => { + ssh.end(); + }); + }); + + server.on('upgrade', (request: IncomingMessage, socket: any, head: Buffer) => { + if (request.url?.startsWith('/api/server/') && request.url?.endsWith('/console')) { + wss.handleUpgrade(request, socket, head, (ws: WebSocket) => { + wss.emit('connection', ws, request); + }); + } + }); +} diff --git a/ospabhost/backend/src/modules/server/server.controller.ts b/ospabhost/backend/src/modules/server/server.controller.ts index bf2e1a1..08833e5 100644 --- a/ospabhost/backend/src/modules/server/server.controller.ts +++ b/ospabhost/backend/src/modules/server/server.controller.ts @@ -66,13 +66,13 @@ export async function createServer(req: Request, res: Response) { }); } - // Сохраняем сервер в БД с реальным статусом + // Сохраняем сервер в БД, статус всегда 'running' после покупки const server = await prisma.server.create({ data: { userId, tariffId, osId, - status: result.containerStatus || 'creating', + status: 'running', proxmoxId: Number(result.vmid), ipAddress: result.ipAddress, rootPassword: result.rootPassword, @@ -146,10 +146,11 @@ async function handleControl(req: Request, res: Response, action: 'start' | 'sto const result = await controlContainer(server.proxmoxId, action); // Polling статуса VM после управления let newStatus = server.status; + let actionSuccess = false; + let status = ''; + let attempts = 0; + const maxAttempts = 10; if (result.status === 'success') { - let status = ''; - let attempts = 0; - const maxAttempts = 10; while (attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, 3000)); const stats = await getContainerStats(server.proxmoxId); @@ -158,6 +159,7 @@ async function handleControl(req: Request, res: Response, action: 'start' | 'sto if ((action === 'start' && status === 'running') || (action === 'stop' && status === 'stopped') || (action === 'restart' && status === 'running')) { + actionSuccess = true; break; } } @@ -178,6 +180,11 @@ async function handleControl(req: Request, res: Response, action: 'start' | 'sto } await prisma.server.update({ where: { id }, data: { status: newStatus } }); } + // Если статус изменился, считаем действие успешным даже если result.status !== 'success' + if (newStatus !== server.status) { + return res.json({ status: 'success', newStatus, message: 'Статус сервера изменён успешно' }); + } + // Если не удалось, возвращаем исходный ответ res.json({ ...result, status: newStatus }); } catch (error: any) { res.status(500).json({ error: error?.message || 'Ошибка управления сервером' }); @@ -208,7 +215,9 @@ export async function changeRootPassword(req: Request, res: Response) { const id = Number(req.params.id); const server = await prisma.server.findUnique({ where: { id } }); if (!server || !server.proxmoxId) return res.status(404).json({ error: 'Сервер не найден или нет VMID' }); - const result = await proxmoxChangeRootPassword(server.proxmoxId); + // Используем SSH для смены пароля + const { changeRootPasswordSSH } = require('./proxmoxApi'); + const result = await changeRootPasswordSSH(server.proxmoxId); if (result?.status === 'success' && result.password) { await prisma.server.update({ where: { id }, data: { rootPassword: result.password } }); } diff --git a/ospabhost/backend/src/modules/tariff/tariff.routes.ts b/ospabhost/backend/src/modules/tariff/tariff.routes.ts index ad90acd..e2f5671 100644 --- a/ospabhost/backend/src/modules/tariff/tariff.routes.ts +++ b/ospabhost/backend/src/modules/tariff/tariff.routes.ts @@ -1,10 +1,10 @@ + import { Router } from 'express'; import { PrismaClient } from '@prisma/client'; const router = Router(); const prisma = new PrismaClient(); -// GET /api/tariff — получить все тарифы router.get('/', async (req, res) => { try { const tariffs = await prisma.tariff.findMany(); diff --git a/ospabhost/backend/tsconfig.json b/ospabhost/backend/tsconfig.json index 3da1428..31e046f 100644 --- a/ospabhost/backend/tsconfig.json +++ b/ospabhost/backend/tsconfig.json @@ -10,7 +10,7 @@ "forceConsistentCasingInFileNames": true, "moduleResolution": "node16", "resolveJsonModule": true, - "noEmit": true, + "outDir": "./dist", "verbatimModuleSyntax": false }, "include": ["src/**/*.ts"], diff --git a/ospabhost/frontend/index.html b/ospabhost/frontend/index.html index b2a40d0..97fe878 100644 --- a/ospabhost/frontend/index.html +++ b/ospabhost/frontend/index.html @@ -2,7 +2,9 @@ - + + + diff --git a/ospabhost/frontend/package-lock.json b/ospabhost/frontend/package-lock.json index a835f85..519e3da 100644 --- a/ospabhost/frontend/package-lock.json +++ b/ospabhost/frontend/package-lock.json @@ -13,8 +13,7 @@ "react-dom": "^19.1.1", "react-icons": "^5.5.0", "react-qr-code": "^2.0.18", - "recharts": "^2.15.0", - "socket.io-client": "^4.8.1" + "xterm": "^5.3.0" }, "devDependencies": { "@eslint/js": "^9.33.0", @@ -281,15 +280,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -1404,12 +1394,6 @@ "win32" ] }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "license": "MIT" - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1455,69 +1439,6 @@ "@babel/types": "^7.28.2" } }, - "node_modules/@types/d3-array": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", - "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", - "license": "MIT" - }, - "node_modules/@types/d3-color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", - "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", - "license": "MIT" - }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", - "license": "MIT" - }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", - "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", - "license": "MIT", - "dependencies": { - "@types/d3-color": "*" - } - }, - "node_modules/@types/d3-path": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", - "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", - "license": "MIT" - }, - "node_modules/@types/d3-scale": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", - "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", - "license": "MIT", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-shape": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", - "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", - "license": "MIT", - "dependencies": { - "@types/d3-path": "*" - } - }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", - "license": "MIT" - }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", - "license": "MIT" - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -2200,15 +2121,6 @@ "node": ">= 6" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2307,129 +2219,9 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, "license": "MIT" }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2448,12 +2240,6 @@ } } }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", - "license": "MIT" - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2484,16 +2270,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -2529,45 +2305,6 @@ "dev": true, "license": "MIT" }, - "node_modules/engine.io-client": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", - "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1", - "xmlhttprequest-ssl": "~2.1.1" - } - }, - "node_modules/engine.io-client/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -2856,12 +2593,6 @@ "node": ">=0.10.0" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "license": "MIT" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2869,15 +2600,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-equals": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.3.2.tgz", - "integrity": "sha512-6rxyATwPCkaFIL3JLqw8qXqMpIZ942pTX/tbQFkRsDGblS8tNGtlUauA/+mt6RUfqn/4MoEr+WDkYoIQbibWuQ==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", @@ -3312,15 +3034,6 @@ "node": ">=0.8.19" } }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -3552,12 +3265,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3668,6 +3375,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/mz": { @@ -4234,37 +3942,6 @@ "react-dom": ">=18" } }, - "node_modules/react-smooth": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", - "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", - "license": "MIT", - "dependencies": { - "fast-equals": "^5.0.1", - "prop-types": "^15.8.1", - "react-transition-group": "^4.4.5" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "license": "BSD-3-Clause", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -4288,44 +3965,6 @@ "node": ">=8.10.0" } }, - "node_modules/recharts": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.0.tgz", - "integrity": "sha512-cIvMxDfpAmqAmVgc4yb7pgm/O1tmmkl/CjrvXuW+62/+7jj/iF9Ykm+hb/UJt42TREHMyd3gb+pkgoa2MxgDIw==", - "license": "MIT", - "dependencies": { - "clsx": "^2.0.0", - "eventemitter3": "^4.0.1", - "lodash": "^4.17.21", - "react-is": "^18.3.1", - "react-smooth": "^4.0.0", - "recharts-scale": "^0.4.4", - "tiny-invariant": "^1.3.1", - "victory-vendor": "^36.6.8" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/recharts-scale": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", - "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", - "license": "MIT", - "dependencies": { - "decimal.js-light": "^2.4.1" - } - }, - "node_modules/recharts/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "license": "MIT" - }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -4492,68 +4131,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/socket.io-client": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", - "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.6.1", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-client/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4791,12 +4368,6 @@ "node": ">=0.8" } }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "license": "MIT" - }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -4977,28 +4548,6 @@ "dev": true, "license": "MIT" }, - "node_modules/victory-vendor": { - "version": "36.9.2", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", - "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", - "license": "MIT AND ISC", - "dependencies": { - "@types/d3-array": "^3.0.3", - "@types/d3-ease": "^3.0.0", - "@types/d3-interpolate": "^3.0.1", - "@types/d3-scale": "^4.0.2", - "@types/d3-shape": "^3.1.0", - "@types/d3-time": "^3.0.0", - "@types/d3-timer": "^3.0.0", - "d3-array": "^3.1.6", - "d3-ease": "^3.0.1", - "d3-interpolate": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-shape": "^3.1.0", - "d3-time": "^3.0.0", - "d3-timer": "^3.0.1" - } - }, "node_modules/vite": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", @@ -5226,34 +4775,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xmlhttprequest-ssl": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", - "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", - "engines": { - "node": ">=0.4.0" - } + "node_modules/xterm": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz", + "integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==", + "deprecated": "This package is now deprecated. Move to @xterm/xterm instead.", + "license": "MIT" }, "node_modules/yallist": { "version": "3.1.1", diff --git a/ospabhost/frontend/package.json b/ospabhost/frontend/package.json index 180bc64..2f0b6db 100644 --- a/ospabhost/frontend/package.json +++ b/ospabhost/frontend/package.json @@ -15,8 +15,7 @@ "react-dom": "^19.1.1", "react-icons": "^5.5.0", "react-qr-code": "^2.0.18", - "recharts": "^2.15.0", - "socket.io-client": "^4.8.1" + "xterm": "^5.3.0" }, "devDependencies": { "@eslint/js": "^9.33.0", diff --git a/ospabhost/frontend/public/android-chrome-192x192.png b/ospabhost/frontend/public/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..c25f9a3f09caea7b5badfa13678eb5586312708b GIT binary patch literal 12554 zcmX|IRa9I}vmM;s-95Ow2X}W17Tg^McXxLSn&9rP0Rq7X3G%@(g9Hf>E_wLx!|7A2 zS5>WD)xFN??%Ex%sjh&5N{R{q05Fsk<+R`5!~Y&+#P?Qv#~BF#zy>JEN$dKrX!`0OhODUmc7*!nivnok@V#9xu*1Q2kDlSqBvo?H-i%9Hk z4woM>+aMsoOXP7JYN_2n`h7w4<*I4>bNi_VRcp*o z2zletrEL;iX#~_NBUL9-`amVK7vWnYm~ZH+pWihQ^45Np@Jfz`Hv;IArgLXz-i6Gz z9j|5up)>-^D4ZuAVc~bdGbd>AH!{*U*d#7%Z8J~13-W1HO?&yl{G@k*i$q2Iv}f_% z(ntTeaAx|Si?3^5CI7F4PVTU1qYt!8Io{7qfHQ(&)blu<7x1EHlj2plfhbM98{ir2 zu&Eb|_ylEykx2BR9KHjMw|d!Dx=#@HI#Hz}C+|;qCV+0L0gxEeVO0Ts3QWS&OVzci z`8SR)l{;aUS35n42VJ0t*LK9hYiI6Y-=lvpj;1a#>cK5iAdT`9i!yGb&>@sCxCD31 zrTxUxge6z<_ZZ6p89Bo(OXHyyDNr{c)#vQ0C9Q~5Jau`YD6Sr7OPL=WygeeAoXB^^ z$afUT_u~n$dvEg!kMUkPg$TxnYk9zZs z3UJwbPEyIETO7XJY?G9Fxfl^nF$_pU$NS=L1heAhqeAUgu`Wq0-MM~h&#mzCYvk!e zg1aa(W=3K%MqH7Z)B6ZIEad*Iy}ACqw$6*aP8QeCDv{l)E{mg&w7m{O197BkL}RQS z`x5RPpGZCJaH@udXu!XH{Cr`CvtDwt3AnFSI>kJ^Ot2s>HB)-`$UHUNMV%(N zY9Wbt5X_{ReUr(D2z6sxXoGH~?_EGQvq4hT2>KDt=Bd5#@K_cD9$r=F zuv?5(Z{o(KyGs5Z!M+IZ8Kh2eytxp+n_7~6a>$FUJIhe;Ca@H^^n-H)DU(FnXw4{BX%!kO?AX zt`~?sQW9OPNmUT0i4SZ!pUc5Ed}ghu+4wtE&fir&Zg1j3E2r><1ZsVG2CAUTZ^6T(Dor zuuC$b_0G3p(ko2M{7=LiZXl( z*V72N75d6I>VYyUNfGW*Ion^$@D^DswY@8hQTH|x+x;eI31)Qp_%bC!3m^4;*4rh^ zU1avR?dT9}DFu1nC2A{k#1MPLJ^bibywM?gF_w!H-~$^x7#n)IA~c)~UU|Ww9aMWs z?k-7v6PJiKf&I1Od?X5t7jH)MuiEr-{l*FmdF{Yn@xqBq#A(-UV`v-c$A3>?M-6yw z7X>F~ALk6u-zDtoKm^ZXOM0J7OM42@9#C^YnLBgNSPA_;b%y1u?MLY&qxW|BCC!)XJtb8p%zqu2BITH-X zC{^yv0b?R;e}eIqd(^FYf{!d}kqSTNkcy0=#l<>6jo*lQD9E3D%(}n77nj!6FTo1*;V@xn{N5v zSj&4vHW;<46iz}8CtAWtyKFKK9?;9cw7t|)$nMJ*z=;#X=Qc0q|GIVaOU@c}t+rRdp$s?%dB!bdur643F(Wc%pi1a{`atKD|S*^MH zJqhp^+UfJamR#6JVEW2+o zzO;Xj{HLhGPK~!l67@idd>e$z+FjPwj!6h-_6X3j&BPh#CjPwfBfUbj=J3*yB*q@5 zrPH^|h;=t?L$nZ`lHG_0l3Z=|10#wZUg;k6(!j_*K9Q@RaLx~WFY!)}NESQcC$L)` zz#fcDmABqdJs<(jiVAi~u~o>I>>Z-v{z6!DxSh6PdERIfyU_?I?xa>-N2iZ?e%1!hVs-&*tUklfuy~|A(hz;R>RA2o@3z0Zp zPycAa?9Br&ap8Y#31yePh|1eHxmo>9dRD)JFi+RZ%E}g2A{*dB5rQ2RLUW|bIEF2F zzKsm<+2IZ2RUMq<9Vs5=*Z4(;MsxuTPsd`zV5xs}qt#t|z19HMUo5Po?zIfp=wHO* z{W!J#dE-tzVu;*3I*(U&7m9>$x$&iC`HA{Ncf~(GV58!PqTTpWcn6>sO|^KZ5>t*+ zIFwkmQ$_^wekU~%3Y`=^`yEF}v~OMiR-8`XwP%_Tg#kPJp z>5bEsBi=bYBkx~rF`&`?%b`+;<}fFn`|2y$-A7ya&DZDa9I$0Tq2(HM>d=a zLpOGj50r(K(Q0|Fcu!FN3b&XC;F}$97 z0IPZhs)n}O1-#(pP%1JLj$Sw7ket7ECefX>LpGjBU*yp|BJHxk2PM1z!Vk^|2Yazl zchS2lS_#Mfs6(Irbk)KfZWH066}2kOE-p}J=R>f$Yl0-x*QVj>2rp9a^-?*oa{r#- z;!)6Y0~CTV9MwFS8QOY*gy3H0!zy!espvjQ`aVyzeqvPs|AwEs@_t}10=0V$Md-7$ znx*qM>9%pO(Ulpjy0rZW93GhAU;B;{8Ww_i8fK(e2cxBWKL3Zru|rHn+!VqEMbv5rPv<6TVGf@bqijhi zUl!(rR3N@`{rTPr-oN;ATiKB1AbsWrfYV&TS`Zjf&Lea5ncpm3oOyW(`#Sb9OFeKM zq1B{x$B2QbcRePhs0^ErT#s1K7S`7Bv* z+yl-2bLG&Duv7T*1!^lgpXe_Vc_suX8oX`DpJNNU(Ale$!s#yfHBTt8)6^!>?lq+OepzWBHs{nzrBf zDwcYPBLeW+)gr0<`_n5)o85vZD-S{CjvU19?xG&YuhNo?sP;0YKl`+nj@lr-jLfau z+gp7XsIzgqALNuL)6Y3?QCK_9$R5{y`8q1U)T!Kfdct z;b9)3ogW!;KPH(fofJkrloOp&sm1XOfpt!FTgfpj3-6gBdvYeE)T>=9LwYGVF9|%eJNtMY+kSwA+|}qAz)Tq6H_AkKeX6 zJ+piG%3DgJfKxj$2(DpA$fSDK855qz2^Er zKkYp3dD)y3p&v#Gva2;}+dyNZ5lM1tf^e0rHmobqohkgbQNfSC@lcrXfsB3;y^E4a z`qRH@HMKgygcF{!sWFkZbH=^xj6Ms1$L2-C84O95)Y$U^2WQ|n)p#{d#{M=o?t>=j zH#SBYSwpAC4Vp*$GWjcp&I=oib!_@8!fL)}rEnB%{6`kMK&1UyV!i zrYZ|}@inL5Dn_1Witv-@)blZ3Q9q(k!b8}ANGdpcw|U)nH5axB4&=_hzbHqYhPs@( z31M=`NlCZVXrv#pCjBlt+kpc=$B8?`j=pz#@Yf?6Y+ct9772>UNy@hLJ4jdcY_H6EnTL;t!S=sH%Auiw=hSo9o|27uYyuga7j+ z>KruLkGczJP7Cr*fYT6+cm8P1;hqfh0SaOtI(FSe+yAZnVVd`G7a;wzK zz0z9Jem4D4qV-0qBa8Tjj-N}-)Dj8niw3_G1Kr{WqeEVjR$ZXC9L9|2O4<^;4t2^f zEpa~`TbBG@^g--B!%&0PkPB2;yTFQ{>Ti%$wTepH=aZ~!1oObz<_5NUJ z@y9i6?x=bRygVbM-Wc3@P9x}>|FV9~U*$)~K3W3rYn7#9oU0Af_**a*B+6WbHyyQ` zl=ZmlX&x{l1xz@aOi!MvTrHG;z=hKrT}WhQFEKghW-qzZwA-aNggIdlcYQNcH6b&9 zeuX8v(=H5U5+>6f31Z+sj7J_i_5A#1_v8rUs4973%AP@d?0c#27UR0 zrl*8hN%ttviQ24F!=!W2kCgU&Ek8db8(=RaK9f{R=avYPj7tiEgZ#xL`k8^P*%{+I z{ud|eNCa67*5dQ;_D?A?w-w80kr{MuoWpl>Guw7+a_TNIivkD-Oz6j~;Cm1YHH+Fv zc<{_ftcL;6_&?}Agri6`-#;t)UcK58g`j{GV_}1W`s0D(z2o;2c-XK)tZZ&Be}692 zmoTfB)3}4b<{aW+Q(2Fc-B*tnA)jQ3Rs>P87Y;*@(%yeOAA@q2m5+bNF<+ z0`@bH0XlFAd{^b3N|El5c?1yxxRCM|2i>=c7W;eZ#cK+Qj6-ACSb3H5V|NBp63$_> zhT(u{4`K1U>4z43E zMTvSq>8Q64xOV;$iKIIe zDLX&Gi6z1DT0nWFV^iE61dHyOa2ozoj!Fxz80bsj1N1ZAO(4FClf28d_#e}tKzo4~ zsfn(*N0*l|I`eJsE{VV&vBoUMfI!P{Y{TJH*i$@dr(5DZmemh?H?2v02;bv0WTg!J zu^3Zo$V00%>BJKhD1$t-wNR&mGNFnToR;>;@Y=m7nqpMK7k*n|b z)6u-51?^KS<{I&PW7__y)$OACVSDF{axi?3K3{a47S#>Gd-a=J^Uf-a;w%f*K|@~K z9KoCtrN}Vn@)EkznF*kgem`2Oi{(}5wp}N#M5;O#`UBO^Xv~ZaSJYPWj{9g}?^l`v zV%lzp;|=}B-(akpy1Kb*T48LR%=?6hw|r7lgjP<-&(^wtsY&LHfu!aS7gYcqm`#EM zKe>H^I$=P<5h4Ln`~9_8q(qHW!2#n<*JydEBIy_PzKxp)GoF5?8$U!(T{&0N53Bkr zks@VVed?%CyQqD-hl<)9>a9u?amMWtSDfvvdwh-gLUX*dX45kCKPe|QssVhJh1C-B z=0!q|fxAyk-};EJ#d152x;u(th4$Sfzic}q+SE~hr{cx!dg_VHm2b~=5I_B+o`(%A zv9Xqp;9%suVvE;@UAdhT_Z`~Ku~0#PI+Nr2e8T+LE&EtXzvudI(e+^9KTgiWkF-VT z|6kN3%#u$8$#iy&pcVnE2ceDX!Km3bj0YQnq4)je<`kZA=fy2~h(PMns;&@%#mm-o zAIz74g%GlkBQFD5woNYSKd6}{+bEtB8Oi0sx~=V9#u%RK<9%UW#Sa6u&W0bG*Kqr@ zbWp@f*H*jjlw#fy+DKUrzFCdc||Lvrx@V68_bn8*#z5mFoIwdA~qWXvHI6 zuKDEdwCS1_c={BdbxlL&E>FMA2u2KL(@hLVV0s}u&k5x`7qO?x3mc5;DKd;m-%1wx zYg^(7@J(z=HY$unsq1tg<$Oz!P3qF#B@~ID705Q2e&>y`$M)*&Bo<;2@hl{@bkc&M z(LviWw|nyY=ag<>39we_wJtXq6-xN|Hd|o;{CCXdeb4WQMM72aO@^lQ>zeLIl@B!K z2WZFK_#y(P?i+l#Ki%42nQ2o97n;#i3$j1!0#cdKCnHC^j5wFq`@R&2bfW22r|HL2 z%-`k#*ZjFh8gR88>rl5N10giwmQRsP>PsmiwO^V6$ae~WM32<3AU!=WCq*_3APHM? zjqPPb6%(OJsEF@^P2EoBpxDD(neXSfJWoIL)=zXl_z^VOcIsCjn~%gTU9IB@R#NiR zIBmYlqV15@=Rj)cP5$C{?c)z8DRymOb85(pPFSu(6UOT&z`j20XMVe|KlXHHwqHHC zOoR9|@uCE2m$?fQ#4}f#5`4-~U9AbqU~&IT(<8JNPnYOU$NFPV^V=xu&$Xs?nnz@B z>E=ai3ky)8aNODRf%@mqiMRv!u{Vry9+7s!MCx)%zMP!Eag_e}a^WmL>;Gii2=D~( zy>x}}L7^{o_Qj#t>mE|#ifS%O5k^kk z3a_99q7O-%c=6?qdOW75$*3T#DL}cxr^38MY`ytcS(Duf-|%@AanCPg%BIY>mmQ`3 zzettcRDWvDU!y*-;i6I^PjrNH@03W>n9KWZHp2uUGP@6bz+3gW3)Q<|HG4M$y4&8d%Pt>VZ??5;s z|MFsjz>mlv5R5Hg1Kc>Q%{)zxqaNzky-XP6L@gGTg%E{ndi22eDEkX$-1sveT6|nV z9eDhaf6z);$1XKLbtuNRkAXS{Ao!ceo|R`Tp66U(AZX|&WWQK6SMRt}3H=W=eMGkG z#%DTSw!HehLyb@8&uwMn$I20 zhf@d~(mgC!>C@_yP&Ac{Bwcl(SGHZ0-o<1-#nRLs!opS~@?fKLEdtuuR#TcIxOXy~ z93w`D#d}N}7EceiTbm?F{ro;sC$0YxWryIm?Or!ngVIx!W|7W`Bc_A|`He@Oh1xYc zpbob$$CkOC)Jz!vs438Egx-zKSktna8)<40g@mr44 zUUz8e0a{fUg=A+$NuIoFMUsbaiH{9N_`8BtCDhvYL#Y@LqTc zpbNfxHsu!mFNy4sz*A#JC|~-@rRw~kMFK5;n?0%FkDni!?qLY4$aZ=wpg)!SxP1;{ zR5j+$I&AtG&jgsq5heO+W0w+x*YIdj2ixuUgzvD4IVnEY(Jo6Z9%9Mx=ntFc2YZI- z95CmC+eI*I>vsWI@l>NlsQU$Wm5`JlMfN@2}<%n!TAEfwMq079c^cf@FBtao1}3-2)He_+)I*#lX9x5V6VQ` zM?6(_Z&v7Ox4I^gR1vQIS_<=^Q|9lm7UquO@;YOVUMStXCyaxgnV|4(V{8L|IQ7fZ zM9!Z?4nfyqRXw~871o^9uLo)y;tQo9JBzG8G|d93rnACPKGHAJmV1+Q2;{d$s&@3e!@AjjkzQHX!eMY#g%ZA|0%Q2AfrW#%v7XW%FrTJq_eFCuyyZn z;0UC~%G>|_WdbWn{&CJ>|^y`6jADu0MW!_*uuYD+%x$}G~9h6%?2Hp)a>^*zO){Yp8>+m}! z4HNXDpA+)R`Cc$|@Hcy0KX4M7Tv9{EUX{CuGhifCp%h7^uF-GR0A+AcV{ zbd@qYp*+2t^n2I`0W|X)9+{99^)u_i>!Um!BG-&5`Vl&rY7iiLF(Cl^A_lq9qTAyu z7q#&zHPl(jIC22Ay^w@)Pk+Y)+9rBKeb8dM!5OTE+jjfz9ve(obmlPjx{zWsv5R*URB%wF|*8gy$(`bQc0UpGhQRg?kNzz->RsU z#x;)5`n*vY#x%aAkRJ*AjmW(5ZICx>IKz58{cZiX@aX z7tNfErq!Hs!<^s7=8F{Y18_yJSvr~P3+l;m<~1i(0T4r(^Ge5^um!)AUOdD9{RQ3N zwJe5B4Nqj5(%k7v-;bPja_~2iw-=$bT>7~LWKCyBdaVB^bOVX~MXo?^bl^(sh;if0U@21G zW+cP>qV>z6iX+s@K{)bda=9Eg2g-4~fQQAe`KRJ9gwX$H6H-xM%d=Ddz3{8F@Zm2^?wo$CTYvfYHvbhM>?$R-8nuA{PtJpg?OV8fanh- zLCu{Sz`Dn_-S-lttukyzs%dZI|Cu*$5#Q?2=jNnI+72_kwLTVJ?BWqR1U=M-v)eGa zx#jmCU_f<^#iRYPoBETNvwN(>6 zvAu+IxRq;dp{ZItc32=q`_BI2rr9p8IEBGOxm92+6$XGgtifh3``Dv*Fn5le&q%|T z7OTaX_yTZZ+`F!7XmO!|H5Yom3m6SxhRJ1qAh-1-;4Y#(;aTs{1w_moXHEkn#X@65 z^9)4gtxT*t#!mGN{HSO;%Pj|yDY#<-<(w|eF+)h}>vvKxwh%u&%GeIXcW=u+a4&;V zCSOz!*I`!k(fbN)AGZ|I2NLQz=6B=EE>YZ^5lHumdYSga#=;QAYNv}0S)ydCqN$;@ z?!HrfXsHTX>Y5>e1n9zz|nHu=7EivVbbC4-Wg<8GxnauZcE-Mw(H_5Wv zb}8v?-TvF@2VlKX#O+q`qZDC9k@s89i_`qcsc=(=N(;U0Eq0z;6jHAAgEw;^-XQbt zWDuH=1;TA`t2im|1nuE|IRpl}htT}$Dp)d&rI_rQBKo27dHA}I;QJ^RMX3DbwUNT! zT%2##0`0X5z|*D7EU$CPY82O>orcrW6!h7{3UQUe3k~!K6cP>(M)P{F50cV{mC}X@ zmRYXrepkgT8+J|9uPI0xZ)|Cgj=4f83(`1yFNPF&PPxWxyc|j$I(hWc`A5%1-;ot3 zz8@soht8=Y|3n4Dg&0J32n=#3FF#9`?QBW8*L<-!A9Ic%K$OdV#L#Z}N(vY;)2K)^tvg&o_`qILj+?-U<5~`GYqCpc1 z%w$Yx$FVgm3t}BfyZOF62b44~B2{@69bReA_%AD4Yig2`h=RT+i_IzQc|j_=6-ecf z$VYv~qhUY4W38ahRb&!A*DT>E@PC6SP>)CL&f`zcC{bW$cgpu=_pEo+ft0rImaeQo z{>T!w{mG!5BGOE51W|{(LVphCA9I8dqKF4QSZ83WFnc)2Y?quhVophcZS_{E7JMmZ zP!$6Ju_Nb9RXL!37lP}ehW*dVToC$~YjgtIO%wgS%W`w#5!e4BlPZ9K?vb@r6qUVi zDg5#~M@nYr!Jw`mdM{-Rqy0g|hJp+MNFLq>5hU1W#7uO|9%#ysevvvhr&?&if(N$S~cFR=$?Ect;;QiLmtY{njIi~*vLqU=p}^cpuG8wY$5O1DDCGYsiXyo-tC0@T`zN7PFQxIjuOsfpHip! zh7Z5Oc!TGjnL}e(0o`!xy>`aW{*Vy;bvDyEsYf#CB00Ir$D)tziTK8rOFC$~GA~_~ z$hk6UXj-gDUD3tL-F$ha;Ux;vU(*_Uy46njN*_fW`-yssUA(Yl9NnSsuq4kq``Uzu zD0Fis5kL>ij{7^QEL-oqjF>62;@$k@vQtKfO=1Y)BthJ-%d+5;&LX&HC3mn|w-hk~ zVI_bcRN4LY*$T$9a6LVJVP;v4Ynx>)Z}b_DKf&XkdXQ{K1rL#(($9Lqhy6|n5GL!m z{1p%ebVXa5K^*EmHy-_|nXXYK&Z9gBf@)XxiJmEgQHvMt97DEvoL6O|g9si^YQ5c} zN?84CvupX^B&wR!@NnpNxEBX)ux8)D|=s8G-vvc>TpLc89~!wmL#JKcw`XeO+qeo!Raj2`qy~}^5E)h7p|Wkm-emVXmNNimUFaZ?>3#( zf{HtMaQZh#+@lb>m+U}<0eqzmIW#vieH94_sh!(%lG(dPDzM$Ai%}%h-JQ#Bcs+;l z%)@S)H|VOOte7YHyryHqC3s|XU%cul#!aJDhlSL_AP}pxga&+cU6`JR7GN4t6ztKv zljAITxQ&3CKumIG^yvDlMoIBJKJ^=_W!Mip2LqmKqdfbExb1dKyKk2KmM)O-03?wzTiN4ce*8(_Es@l7)6303x?l1Gl|VmOVA1tET13p0%r)gnMC6Utssl=T z2S-!nWC(RLqHFmbPJf$9HK2yJe9^ia`{?eVi^h25){F-W53vqrZ=&o{Bx;m|C3OmU z!jCC;wVQB#A~F(g>n3*6g$%QRaH^C?NXTC}{8FT=dj^vFc@{n zCRoxCC}3NT;xm7a-pc$_nEx`Jdpk3wQ+y_f*p5E0U>GQ%_PIenm_u_jRaY3c(huun zxUhJSn5xIn7Zai4S}d@a@oiu3eOiwf5??(tf7}->G&K%6muZNKmTDiiR$*uS#-bxu z80GA*o551q&qN%L!iK&~d_I0irHDT2_~TjMQ!M>0A&V!XLI>gD;jUIA{Bakm>HSN2Cqe8ql?EqciRD(Q=@{bKOTDD>9k}B zMz;1b$S&wwuZ|PWZ+$DC37BipwBD4gT5O0L$VV}hAMBFIsW3kbBq)0g zR0E3({hXb1&0B3&fV=W|HT~kp)AvXBq`E9^8`j~)TP$_Q@4tFPS5l+GeSseFbCLw)<&c&qYzf||D@^< z(o{vt+kJfHS@9E4Bcps^mJ7SaDM|9Ea%+N2@fQjD&5HP9*XJkTVN>oj%(U&(+&?2N z>?Qw6-h24#%m0&v-5|s4^42i(LC2hQcyj`0>BqBf6O@>;J!rW}YHNb+*)*KDZR_z3 zo~sXy(yF5A`v~%ayP1qPi%IZS)j&&(|v5j)>#MyGUo3ZoIQN5Jw+Z`Fyora8zb)k`>nr_8G%_N zpaXed2Dz!&8H0STO7Zxx$6O$&^jJVW>r_y z$V=;>`$klfS_yk6<6G(Ao_#F`Kiw8BhRPie2(Jwo&Tr@HL}bms-C9qx^_}~{i`dL7 z7W&tb?Q_TiaZz@|(2`)~KZ-J+WI@=bK`42-55bm~f>|+p6Eev0^mw+NDQ6&A4h-wT z^6P~9WeN0vw0~~)@QaaTF010p6rDW+G8=XBo4Qo1sZ?J$^PFH zC&qX`K72*_5ANMdNG<_&b1+5Yc9@?<3tV^iPlBkLNk6-$PVN8tdm^7uwF@L^+F-|X z8|H2)NiQ(@4A^W=R*!U?sE#<1hk~d~oxO;5<-UI}8I|zQBq;Nz=>c|P-9C5d?ceje zUGq(j%bnRDh(8UdTD{Q0WE2U)FIIUQ!ORjoTjcL|@w*eO%9koP@;lMfKDug%<$R5d zfW%6f+O`ZVZovLyV*?%8D_)3}Fe~|&eW#+u?Nj};=HnkQ;NQg2JH zuIzeX?z0#ecy?qfb%Gdn&f{P2O55So*QokI( zE3o!#Q*NtKmvjywHAV1>Q%oU(t!@gxk=JR$%w`DePx;v?^i@1bR1Or4Gy(=pMe;jm z-=|rbC*di4VE#Ljz#eZNm+XHe_Fo?sQSNx&$?>{cA|!2Y|48L-39NX=2>-f9ek5%Q zzK_qcpnNt;Q^dRB7trU)OS1PYpA}a8hb8lzJlhC()wj-%Zu}(iepR6G-yMOys&|vL ztYVVJ{eSNEl|QT&X1&{HeB+J$P4@2h&LrM8Fw>K|9G1SCEz%Y<3GE*_AFa@fc3}3M z_ Fli%!d@E)dzm6v*z!9U~%DvYcA9RK`AERa;X{p)f|5%OrI z|Bh^|pRRUNQy<95P7$fAso~Nf(o^b-OT)oNV?UPC!-L?EVv#Mx)G^gVQ*kjtT4FSG zqx|Ij8*3F0K|uj$WPW}mCRy312lY={4nHPx59;r=qYl}Gw;8WLAQA#2gQ?7*KSrs{ z(8XNe@ibMeV<5=C61WiW0*k{(VT|^`Yb@ zW$phyG>_%27~}?6@9$4U{U2>sm~04?M4GuJ|NXCOYBoLS8TeB3k$>-b^LkHov9j{N z_hcDE&%7TQnELk~n%8@fICE3~{~j&qnaDR5d;i`8e7z?)MOpg)@6m*w*&Q6L{};U( zYAAY;w>)tFMNdQ4jPGd@h7cXE^ZoxYmP!of2c(cJ&vSzQd0&n!WDCl>nYYpLr~jZ4 zOohn}+yzKEm}pMDiU5kK2S{cXieXA})6u^K4MGXRY;sZN{+A#^eJDXP!^45>|GAnC zR3hC=8VpvpizWJxfXfnl!S}haY{UZBx&J=K@cNjop62-fKehyYZ02v1>AzY)j|D|Y z;d740|09&~ybFkrNPcqsm$PUnXIR7wS{(m!*7VAmef%-{e`thqA^??q^i)|z^1qVj zD(T?|BotZQ{0n2ss}fqlb9?+(KpL_|>`)lNsC1qGrLh+?8X3k7P{L8kVELctlLdeY zhfe5XrE)(5{)I^D6`~Y&WxRhO0vkagA|4q#<@y&Q@mGkHY-0cWd|9FxClsP-R0Ge3 ze<4D8g~&oqbKqZya^|2A?VdMx{y#*oN`%argZ(c=)3s2DxZ<+boc@I<_!T0;8LfZB z+KUMl{_d;d`%D}o{STrd2$X6yU!0u(*<>~KbS(6ume3qwOT>>PA!JxDp58Xg-=VZ% zzsgq%&B>N7MhvemNV87oM=qbsZ-e~&d<@raPJ1ip!{stX+*?re(0KjEFzHEvW*f38IB916R3U?0S8=+D{{D>N&GsKNhq`h;@FG=YS(y_{VDX6cn-v;k@ZjSZ#_A*s_ z)Y@^Igja_gwVP4{Kc6$1C^3bAbtqN9jr+OlGU$upk-Z&|-xMFJUK$Gu3Xl^zcJE12)v1Bp1-W~y zR#Ka9$@3_9pb8j*_^PoIr8x@nZ`fe!RLlPMMBF_N@h$%94z19egYgxkn(Dn@u)P`2 z3xZiR00OC@bRi;zcv`U|6p=xW^(84$LF+05L84vPu=CqzM@MdMPqu@GSV@r^3B>gE z>+1!`E`{NmF1#+x2qaMR5~F!lwiqhq1RAVqJAb-4z709c9^5<>#8`qo3tCc`I)+>P z825o!o;Jxsu0d=FMZ%BAHj=#rz_TLpz|`TpOYEX`yCs*!+BR-tF@t=RvAvN%Oldi7r5)NV$%0K!- zD+!f;D$&HCGIog1zC)qB<%5&&dfePOJWMDlhIhAZ>ph)S2YNAnRKhD!n4lHaLDJxB z_7+0a5FxDP5E;|1W8sz#(^_)x0wf;duRGIn!7^{0K|KB9KG7d~(EkAo32H1wAQ=v< zG$}K4-v!;d%NNd-&Pi{+JvO6$q^#i2t~9P9!5?dSU*Sr|0qRTHp^M?u8<0kdeL*A@ zbGpYOp1)c2`-#l|gC{-Sat<7v1=j6#X-_)`wW0hYf55B!#Y(f}M&C3N=WHl$`@Bhb z`bCd;~>>L1F7V+3HL-w)N@0L>D!zu7@KvYV)pqYYb4@?5EoFM)}r)D@hE9m>b2r`-Tq zu?Ex?c!?SP6*`|o<1h`j*57=Pwy=%(~ zBCAU+NeK&Tj_XG@_0%&^itN=x1e0vI*#KUYE%`7KdX9){qJ$R1*dJMh%RgUp>>nJ= z=)wn~;eRb&ZT`oQapR$m2@ckAlr}~T!N5t<@&;A%nSyF(UXG6qyZJ3O)e7&XAf-mc ztH{l8LCue&q`^!xEp4bF{8(8@k*CPS?Qyp@&nsiz=m}idMOZL0l92R1r_i~8qGtGi z)C!Ig>eOK<4Y5bxoU;=@Gn_w&i zCrzq1Y}TyKCL~7b^JDlP=;jtD$(gnhVT7hHsel? z`V=BKTw2eL6)rEt%OXrx{$l(em|9*#5p(eSBpN6aw-ibZFCxSR3*o_$6?nvcl4cTK zUN;yn@TW4N>1I&n(g0nkkCO)bJGbg>OPIkCKXs}d@c9-S+ujc4k@!f6QNuKctbgf+ z(Zd^2y1t|O4fc)vCzK3JK-p-*Y~Ik65la}Q+8#+-GJ0X;gJH15sy%gu$E;sjSh%vz zgK?m2f!ULZ6yrkNDUap{_)yvX%^-t8W7v=^4XWMEJGkp)y-7E&?z@=NLlm2d22Ht&NP~AS@M;#8OVYeEwQ3cU9U@QGWYn)trgdwY30#gcS{Ma*5YCLinnJ zVZDt5R#;hu!)HIZ!gX;}VzJ;LpV-n}V9BEnqGE&fdh26z=w&C77k9PdP_;JMdq zE`JMgG_;IA*|Iq|^9{pEK(rr!Vx6&Ed@_m+n_dktcV20+nLSc+f8@gg_v9BzM7jTRi#~Ii1DZ)YFOWOS=;~@LrWGII3bb;M55u~v$DRq>9*XX%B^jU z_LyO1$@QEcLBs((p+bP0{kS~JK*rjSQWay z7s;A*bEwkEzg7ve$D@pOW6$KoUrKEd-&UzdqanE;TCYDug{RG&!0UDSg;wnIoSLNY zL&9P{FizMANe!?f$WKjM3kl;ONAuNUY>go)%FNFy<+aU>goa05H42oxl3qs6OC=Y~1 zTh{36>Z)J*(S-68GjB2m88!wXyV$!wI*|rj^YdX%r3J!yjwkn~n|<241d}rG11y|B zsvv|Oh3&UfLA{$)0#pmtb9wdu@Ejc;`X)pkYI1$d=Q5fBP#I6l-+xmny&{_07#RKR zj0F*jv6qp&Bbp7Abd7GuN0X=UMv{qd$v^+0HX#EG=&SMu#mdc)2ES4J!WAoF#)5tS z4($bR;%rJ%^3OWVo&j#SiDQIl!gG0}?{=lH#<5m;5{@%7TDk9J!QgiheRtO*AeV*I zaiJyGrh5O?t8D*U2goy)`F|5kzjA{-idHEI$>2^O@ss9al;-kW`J_zKb&35Zxq(2A z6F7?|!}${8dJU&0OZZH9i+`$a#k?9W060Wb9Q!%zBNLt^B?ag$yOkfa|68;fBd+A~ zf^7;^EP?iR&pcw|XYPBO`WK0O&|oE1+&b=U<<20IX6b181&(*;3?PA~crtKV(ofcY z0_xx~;a;R2+pBXZoi8*9(ZbARZ~~ z-SS7Z;e{q&A+v9wmTaS(S+jG}e4a4EbFGO?vrinai&+Zvl9x+gja)<>u~P z>=7r@M8k7@+>RciU1KH?K~Qx|?uK!=bwy9n`0W0*tlq$$^`bS;&l$VL6+m9z$!Mmk zb6ADwt6#Wy4fj6w>7UB(H8u{knu98TFX*0F44T7V?&(6VuUSG|M+Ul_Q6a=CE2ro9 z@n9iI%W9hhLWrw?90eKX6tt8HQmw)Yk#?V4#suSqyeZ^FD3WVou6vKQoU*=+b6&tj z>Gsf)L))3LVyt^ zC{{3B8Aqj;VY8wd)_eU(w?y}Ap@GfJAt_YT^uVF@59ne|-iEf8)aUw)(@|T@3+HoY zRmG$a)!6IelD8Oxfp{u0^KA8@4mVIkbhV=ZGnGzL_)Qs*1WO#16w1IR{(;H?5gQu4 zLb()EC77ipol%6JHKzj|iKD?Jfe^Qj;v+hK5!A)KSfteAKrUgTJx38e70gN(b>^4f zu*JV^V!3}{}?d9!J3p1uQTlHOHolY-&>u&a&IGnX0D-P(C|$;kz9*uS9Axf zm3Rne_d!%8t!%+Ln9Il?v{HF{)jsYF#1By&`g=qNifogcLYp)2!xo8pzuKpB0}P!p z1I3DdQPLCI&9Eph8Gg1Rel~=$gkuc2F$s#t6TMH6o7L@jS9^tvfq=sgT)Foe+R9v%W~s)xGTZA}zNW)QL>O zKJ@9J1E@SMilH3{5j9oL$vc~0EEO)D@y=LR-V2-xII&x;_~cyvjA8BdMBHyU0 z%_tX_JWx``Yr@Hax!{4DTohS0G-4F6v$7$>-fubz3#Ciz!1P|d?7rDTxRXF}h--L4 z`5ZDIpI6C-yipz^32js`MZ_e`d6*w#wMxZ}=R3Sr8;IkGW=iLJ9b=ak0IaQQE>*gB z-jC!>;7{Q~hF&SRmll)}8l-HZ5k>?D-`u44r{wEbUEcs0Sus1Yb+U-i3aRtglJ#4R z0z;8bGlk^#3w`=^PWe0~W$}Vs@3spt(ad&}N@{K-6fw1gclvscPdYa=L}%8Gn84hU z-#_j*$SCZ6PsCnm0=8IhX6!EDRzhUm{cBm~HDSWSi@JViyGmZLcPq0P=N27)0nJy^ z<-`1oZ9bKhXC(ab?UxzZn7dC_Oy(m&JOB~X%o`l&ZHX%P=^ zq?|2)asts-0+!xlo>!*u1D+d`82$`^lgW$UtjEXd4`lf+jJhZ(M3$hS6%G)7%M5ms zs=wUCjf!h1ZZd)qNj#_kU!(PA)E|F`T50c{(#IMlmCuHKa%fm^Z77sQiE|T3Z zCY7cYf>FT+6)J>viBx^2_MEN^_ma$*AA`8NKO+z9*8KLjEvBh-!TORefx@0vx4)dxv`Pym#+FRzIR^KGi1-ktRa;_MGZ zu4@TuXSZ|+61~Wlsfk{Tk#Sc65%VHKr46X$8*_7?K`IB_!B~ye1_WpbX5D|cM+)Nt zbukrVr^szbBm%G0B2IOIid{_5$|%B3IQ>TQfgS+d-WR^%khYUZDrNO4S#v>!tM{&L8CCZW+ zzhH?^UqsUP2O#&nl=FelqakWC5lssmT$nFZ^Nbg`dkH@*xy&5%Nras&7qQXWG@dz~)^vzNi_BE}*nf)Y_DXiXM#szn#$f^mO}gim6&T4`n3xT!%J?zT+|12IU&D$JcZyg7eu zR}kVuttv8tb~MhZQo}!bY?}lu8lsR&Y2cebcA*KrVbSY6z~a;RaZah_Q@mpj)*ZTznZCJ5=HCW)wW{#^HPoZ zYU!n-Gc^Rkc?R68J;)C0xRb517G|k6^o&rNTLHJooPPcj(T@|YLWKL#vg8OBVGogh zM+n)1Sk>AO!+lm_`cJ9aCx}9LaWIDrVQLnxG_^AyUOyU5hhD(<v1eq7Kb$V{^xh z28wj&9`teHTEDCM4ZAI4Pi|IU#<;290(~b~(CVe7_ZMRv{YpRb%*y|L7xn@h_QyFo z2n0VihFMwHANjXdmc?$Lfe23-U z!h6-z?}5c<8uK2dmmy^l9?WG% z=IjjZ)4V}`nvtD@`Gm47Lstj4!h<}d6jSl)dKuajd@kSPp4U|OUbQc4FtX)LYgxI^ z-mCOA&C~?EY?(|h;owRr91)kJy#NuU&}68P2(l3g(*gu|toa^^X4i035?Y*9>|hh& zl>jxoN(MOegKs|wVysu@oaav!nn@^m&VV^O)442cWA2btWN^! zx5j_C&7wTKIbplecV2w2kfbQWsBPM8Rlt&%;2S$8xjm{{Il!AD7rTlSgvPYk`{joH zH}2#|0C|gj4Tr~DPvt8=tf~TN#|^V#lDA5y=0&255e-LNNQzb|f5D4}_#l7x1uIhG zYgj9f<~=!3xw4otI*#aN0GsO%|?HKznsRXe8 z4%>hK5d~;2ZHq3Zcl})~Z;_IyU%WGomWGzSK46>+z>zS!?*u$H-f}zJ7i;lB`{Y&t^#Oe!=i= z#*7PLNNb+``)a@@5&|s4sx3n_+0DQL0T`8&bnyTWCrSHn7<%6#pB)V-fr7dRVn$IS zihVLfZ!itCb^+njd;i+(+Rqal2YK+dMM-u=tk@{^J#{ABsNAjUFz*o(epAgom=vaM{AZ! zB6!fL*z*02BtkvNe+nWu}Ozr~L`tV&WWv&UsNMaNpD4-5R zG{D0}5HdFs(Nfp=z+4>k0t)-nyMy@0^3R7cYlekFXxzWp&p@QO@Ff}Kw8ew+U?9y> zyO&YiFZ`A%B`32&M_okL$;Yx_onSGe8>F7nEp=<|8%rVajtoajYet}6>OAUcCwxj0 zwh9BqMsaJ1TCIi%uSI_Tt8;Y55LR1jHiG0g0=nJY@2$l4^YB0_5vX=W>)4o7pj3es z{+cHlP>U)`=4O>jmI1ZEGy=hl!k(a=4s9s2`5F`~@k;JIyAEaA@RTdOdx|x1zW{&cwri zPu>4>@m3|#H+6ir=vV*MMt?bBlf+c5+?@Ws#Ghfa^Rh93xsJ;oe$sK&2}!d`Weq37FxdOlyuQ%^pNrvMS1OdFt@` zl4a~D!Bb)U8Z=7eCzUOY_CAa4PCE;m$$N=ts;+cOFz!r?N`}eU`Mh74`Kjx;zqJxtqtR(&w%ncX(p~ zP?3$<47zCHSN2(_K1=%w-}~1`J`^&gZIWAQ!@9inW(F3@4%N6}SnOn$U9fa8P&g&L zI<>V6Mdsx!3fX2f=ifK*C|}bk_r!60)KNTNf|D0L0TPzDr^fFGogFxHtPD9ncH|&$ zgL&^BmGOk|IvG)7T$q||v1Zx@*c}OBlu?cc*UmuWm5uGbW_cNf-!U9_J~cF`Zh;_z zaRrSg*@n%JE8KN`HbPBYS$VMNj$FZ)n}~N-@0eHegJv0@j9KqVKnu!?DQx%Q~1#)2psgp zN^MUEbqAr%oo0J=y<6=a33#!0%!CpmqZgb{oa7`S$!E~w#_9-_byb!=IBt%xO~LKf zFt$^m&9$G?rHi1SeCL75wLXCcqgUo93EY?s1U5ix2YBs55_y8{7E zH$<~^yw{QlB8o<8Ttb(K0T1>e_C68Jy5kkQZjhefsZ z$KUkV{uV26{4IdXLktr#&5E#)6^@?q;cl1u>87{dt8AK1^L7DNtzk!;k)HdRIOm!{ zBgKYQw&6jA?G`VFMd9p$Qm?_?VWb_S1Dj+Y#ocjzISSxY9%I7Nv%N_l6W|OA|GX}} zDxYR>FL}?iMyF<-OmL@aAW-h9x8L=3wuJwfJBDA3 z`Sya58Lz&^o&MJ8`sSvG%-kf(l5Uc}P%6R?2klejPvfK@uJU%LP*S*4AJoMo4N$}^ zm&OAlj{#0@`x0A9jN)HRA2m%iC&>nsY4yTS0fs^=3Du)M@sPaW^?D&j(#sf9C(5UU zXp=wTy;X@~L=sRhWLB;qJH#>V;)eGnpQrYnCvo-t86YMHhBX6s^mn9v>`e{hb= z$8l^^ylWLL9$D%^H|O{k8oUEEuE!n;RWuvhPtJ!sBQX;7Mg7 zx;SD)g6nf+_t?lk@dMqqK#$mdCNb~hdfDfy_x(Ga;QD;2tfs#cLEYDD`^R6==geiv zH-5!kX0rQ_Y?r+Jy=_@wC}3`@Iql-%dLM$DuqLZsvCr?FnwPeNNIAEfd|)5g z1!IEEk_xRaQPKXy!otG7NM^j5W1(T@H{Rz>kx?il?#`52Q%MYOnm*b0PGVh6ane$q zz{sjTnTj6!teHKfMU^4HK5u0lDj`hHV&tSv6E8A9mtcMxB<_AMDDXs7j$g)3i5O*z z2Zkf!6_dHr3OW`S2v{usc zC2T+_?ao}I2SIaS%Ge_sXbp~~Iqy1coz(@1FP;&XOg+{hSfcCkc>5P&3lV%MUD${& zU}}~ovu{DVTD@GC;>X#AKzj7IPE%BllPPmiT8HV6#9LIG4Mpj^@gs0TRb?#b*^&AN z-uDMKbk^m))dMr1N|CF(UI|WS|J$APS~qs9C%RjeGGlm_R1?}J4C;}$Tp2kWe`h~S zMNY_H>zZVVtlhPy_1+Zjd*dV7I3SAK9MIDAc&S-V*s#+mrL(9U=?s;DtF1zy+M{2T zWlCySt@elDDU1E+UC>g3kFGZ_SnuYD>-pYnW<^V3OMW?Aic6=aI1K8mtc>2Pj^6ePfPxaYFu_%Fy1zQ7s<`z`sSOUObzo% z@7=yTX2LwqF9>;?-0Yh^*ij6-UdLi0LRs!Nl(jHg4XCycd*gfs1T56~?^bUy^S%{Z z5iE&ryS{#fwd{G(75CGrKk@_5ftGop3bhZ4u5P{dKIyRJEYgTQm7Zyj;Y8T``{p7Z z%zM$SZDz0(H(bd{cxxoh5*KHpQK!ukU%v6ZE^qs_1 zu6M&}Wn-lUsn?nIM4CJZltwj^H45J|y|qqn9uzwJ+;2*wt})T39;(lO8MQMW!xu6S zIqd6TmG0&4e}R>7fFYD+vH?(3YMw1` zBxu|xV~bC_cm3#qwXz2RFvrB8rMO+W{HJjL7}*4`nueAUIbFQ-mtkmDp~=|Z9+Bc5 z|3Tr3)3-g6q6^-6@VUPwQifMz|0*fGR0iNFHZ=+6D$IDKUemicdZ)qC61V9!O&!hZ z{$|7(g6ShmEi>?>GuR4Rg29EcyS9P0Htfpq3LpOQbfy97XB@>+=YQz8OF2y=-&_3TuIbI z7$ORI7{#o!-zpngqAEJ!2nt|xpAO7Dw*bz>1PdM#JtntNjor{OLqZ5kVD`uS*v7(v z5PyU_F9l=PdTB`|pDHh5B-u^hj{-ymBvig~CsedSxu+Hc4Z0PZDp4FU;OpK_wf>2BRx?xcM_00<3#?{nMyWGvsKLYl)t%Qgmt7Th_K>Jh%w9J>_W z$F%(;o0i}67;i5bsoes;Of+0Jv){|@l#l^V+O7qOpI`dNHIdq4wL=GocZjMXOm}~} zNRQ!qfFscPE0M_903S%Vw2u;L-0WC`1>}I3x873K-7jTZwSR006p<ZXtRc!MAlodY^LD+$~ov9(ZwtmSCdz#hDZV;#~uWb?@#ks z#fIGzw1jtj4@iO_spy|-{oIWx8xX(v&4@`|sfglblAz-yYMC6;GXBU@GSSbldkNJn z9Z~m&g}l&Q2Ws9rlfxCKjiF!X7dr#*pWvTbl0Wau*ao{Ro&o4J=Z|zEt~x^0L;sSV zMdCP<5!%U4D7M{%HL9mU3oSMwGlTL5^Pf0(chbmnLEpg?RCA*^+FQG>dExc8jq_pq z%z6XuS|Rv(@6AV%bg?^=gvz)nA6#k|EECD*>;J?fGklji~JhNeUNLs!1^YfaHo!PYAndSb!+%w#C#W)?~+i0=n6Sae)edZ6vQ@thVfq2Zoks zp4z24r1;3!0psi{@OJE(x_J*`p|o_%+iV-sY@6MNgQunQ;=Eu9ZiE|&xpB^>92QtD zH3BxPc6ytGNlfKBXD}BiBuJx}75yde$V9gxty?_?ixR^Ixhc$`W(Yt6>bz)APD{2VsU?9^2NT@pXCVarzjC?ysmjy&Ff!aW-|VS zNc&;>Uk;7kP9@S`%NLmyw=_KfZ#A31>V+n(KjS0>Oo$@w^eqfm+HCo7PXQnC8^uG@ zGJUJv6KRbS#|;2FT!}P>wjFWJZEvXQqS7!bGYxQXL=Zvram0AZl0~X|FX#wQ%AmPn z`xS8ffKK(}kMdmrSa3{quG1SZ7Z4u1a&=MdY*ZEBf3*`6yMzE=?k{Sjmr}?GVVR$6 z3lS>If7EJUb`J7u-HFD3V zq$GHEH$|%&a?t5AFPcE1OJ^Ni-2y^j_=%;dhheEnl&RN z;!?s>g+7>N1nTj*2O+$eRsBQ->0vLoCw4-1J2EZ4=ETn-w+dH_A;cvHKOh})~$>Ruo z^iDuMDz!ho!F?V&27nj#x*)f$KU(~PMB&0R^hWwO1i<+3xbMSm;fMpf`oD1h1uyXe zOG&Z3v$s}HHXY=*BRa_Vc!=R)20jp~$+XjaD5|Xdz#s$50@oSjT+@9d!G=BLA}oVo z29yzsiZoqKsGpdw6%rcZa3y^orx91w$)tsRnjaXkQ@Xv+4=$w-m}FA01l7))rZ^DU zI}`u;by7>8>&z_oX;i1pO|iolk3~*N0yp+?M<&CWje7_Zc#$Ck+Z|V{-XlPm3wur# ziD=rJC8#c*L_HWN!~8}KLTZtW4#2Bs1R+ofKMRiPzH`06)4PlW$&h1C!%O&CVg&FV zvSS=%QjM03I}x$j$jP*le7yY22eVNmto}UfnD|+kWL%yJy;q2EhY{5iCNdYrQ#i1m zs5LT}5yQn!_3O2ka~y!-vHtG}Qr7TaIyFVZco8`;E*qZgF*7bC6dFP}s^m8y{y z^NiyyN6J{U5(0Fmypk(_ed8EaD#lLNtd}Kl#RYeu;3kxgnTtY`%TEwKzGuBEhhh!jH^Z*}V3P5YmlQ)0H+Vnzklz7Z3Q(HuMms3;o^q4JBKJh6Ncy^|O?Qf#PvfB;90yE)|`?nr!%iH)6DF z4KoGiLGhO*dBJ?#C`#}Cyt~Mhspzz+X%XCq35nq=;gi1UVspD@U+S`6# zlEyi`w)TW|IH%|{)zvCPNE)#Nm=K0;f#r&WjkzCP0pADni1A{A*$C2hx!Tk|l^cR{ zGW3WM)vzjy_m!9zZcAM?M1Cku!rnD>)K-o#zgx*eKjDtnjtDDNBMpWV-{o;V9s?#? zQey&=`gz%^%d3Y?O^qaDt-jliw<+hR25{$O93h(26@ckS=Fha3r(wm{=X2C-e-NTA z7eS{U{NQk(-Y;ZHL~Q~lq=(xI)?bhTe?a))Q_9~#`^Usy5&QK+)B-`-mr-gD$hY3k ze1P@1?WA6caNaQ9kXE=qE8%v1cKvp}E95@f{pkoz>xy-sJ=+XJHZn*C$K7h}kcZx- zt}{0NX7qjWyE4EWfeyiv!(6oJ*nFUH$zs1QY8Y!i4AsU|H}86^$zvUF9X+3I{PN8t zwQ)*-;ONG>t^QuZBm59+s8rxR+HX@79pM)Cn<|r)L}%XH%kz};yLoFbOc5m22<@Ip ziv^#K3}9H=MZw`o+%#_$Hw;v_PENgqiL7b$C__~9Xr2bal{YDcbecx6FPQ77BOkEm z$X7bt#HX~ETd3Elem&saqTc>Er#(+^j7)Q+)7qN#tMqbt6ul+CHMxBje*}zpEPk;6 zV}Xx!$f$OMV%uv0&sXIt`nNh+>Aj3c(qXY(yX@8MQ24#v6hnB_fS_7tby_p-mQiE3 zS{vck;(61&kMFL{X|72P0Y7TyN_zagv0tDejZ{n7;X5{jg+&7?ztbjf^ln@^aw!KH@g_nVS`q58+ieh z!g7@WEst6OU60)Y4Q%wpZb6NM)6-{uWPikK1rez0eep*f5TN{KyJ7KrEc{BAKM>0p z5+UJJPvUIsW?o%aBXAS=9E%~f_sGLr%6XEXt@%8MAw zcQ;zLf0lO5c%b)Fd`8mvjl(SV3+}G<{U&Gl4;!uE6sv%Qq`3>sDWwQ3^ikt{=#uG` zTsPZsM65etU1s1;_v2aF45Y;VUCgJMB{$?PB0koyr2~F#6-$ba z$dEwlrjFhV@_pu|8W!Rz0BvasQ!~`+ti4tFnliH&r5ZL!D^WO>c)oLk z+~vE#fm?N2D{o)M@=_hnbTnW@zcNkH|GP4@!_U4Krl8@pNf}0~8?^rM5xTf6 zreIya8(vPzdm|>}wKUuMEgh@CQtHxgCEL31(YYemPdhWoB?wcLx?vR|Y6ivOv4V^M zCGDLPf|ws=P#sfbRj~*e>xCbobnX@SM%byaWBFnEf4zX}x>3szsG7GV1taXO0SYf!X|?3ui{inP5MfUlxyo zI4t28t^nLKT5m45rH_nK+3#_xx$nmaHC?o>r5C-hqpnBZvMHd#kW?s7Y{GrA^QjSQ zM4&BKFAP%us(N^I)QKo-Hmzz&ao;A%G3&A()3O1xr(#=mDYt{;ZRD#x<=`zgkRwa% zFvL(~hb1HjKl3i2r#9a(nGo3eXp`SYvUz%T1*CIlt|t6nV>B`@?W$#5+fZqXVHf zHSwP<-VBRP%BJL%r`Z?N4}yRF`uFd?#jEW-|LL6|1B7=QOwTkjBF0*~%e-wF z>mj%kiFLl`NHd|{nx=PoU0@P|&AOMTJm)f~moaqa>9TKy%ZrredUnJGRC`7(MY@&N zk_9Kt_SPq4rswva$S4iGFajD>g@S@#cP)D{zmveYv0Tcuwcq-I5j;;$P8Rl-A6(#f zy#>NiT1r>M6gnq&->PIlGk9p9UrTIKd0B@#BjnG?-^Xo26G7RvQRqes8(|33c>kvN z2_FDNm<{=f_@E>RfP~>~MYSMwDhRY6?5AXqUJ}rKIk3OzgRm&)Resqfi-0KDx z<55~ILrZ_dWYvV8$(yf0i^m^U+W5a^$GEsazs1Flfa|KTi|^9sb==*<|1?nLnkbrz zU06@*Yx|yo_`2M(Tm2n|M%<;!J3Bi=GrbtF91vB*68fcj_ZS_hQnmHfjD|y~iaLVP z#mqFa`9dg*o^02pN${ijoMMWF;$Ybbn)5Ff7mgD-sv(%?NnFj@gX#IUc-)Wo$G_Wy z+qnM)43fBa>lE_KQnhxA>N(b%K5V{on@bet`8at`x zk)10(N|#qg;En_G9-7rFW?KofQT6I_07~-%xhqWv?f<`14>&N;S>Z zVx1oY^w!5#itYw)L|51y;BVfd)$jfv04qV%zTfjnrO8;yyXwelH2b_JA06}db{&9u z7-IhxppBVOkvA}0f-};8IdW-7CEL=sNbt*>mQ~W_wVg?B2xNpn6Jje!IqV-m9`uJ8rmazdwb{e+;f`+hUCy{|Nj2||6ssvX8m9XWk3Lv*+^*_3{_GY z&A}_F;XH_aD~;`klrC*tFe3qyhc+(L*Vo%|0OmrN10@tSw*v2sJo>ESg9!3|*yj8J z!Kh&btbu44s#4zQ)4t}}mL$sz67y1=fKSo34Zwpg`#VG)C9XHwKA?jvxE%-JQ~@K- zLXdXjsCjCyA_Oy&Rxh4S%fg`+YEOi0p2k3Z4E=9PY|p|m(A!W#pN3qVaMBRg zHL*5{XomGnorgZRBxx)KF9R7baox zBDHWKLe(ilS=YrwuMa)fJ$0_fyC`vrRZppoQr)6DWHQ%FNOOoRyM2zUH^V`Y@)OhC z%OlMD;I^qH2Y|-^LUyAenR?B&OMLt+oOQ^F1S!4PZgTpki=Rl3q#_t z(?Ag*Z~K%?4M~yd??B!0EIL0&SyqSWY0C98@RY%fKswj;XLJnDI*t+;#3({iM1@b;w=(R&)n~By*!Ji1{^iB=ApkbTta_i!3B*rP7;=gx&Uu zo-1s`m`RL8T*6T<8zm607sANZ-rin0HZFZ(Ek;*&O~+!L4`!ZozYh&{uXymiI@UEM zpl}dtthB1@1@fB(re#T`hk){QDq25F+3tW{U4YUW5$K`;n~iDE-F5w5`>jeHP}Q-n ziHV~Mch#BS-LdWwQ_r|`xb8k+qmbu{t~*GweHtZ(7tw25@EYZoVt)dAjRL&4-Bep~ z0Dh`O0YpLJjN&fMddSJk@Q!d)gnqMLUli7Zc{oMuzYq7@aM$Yh*F)W-V}%rU1u0dS z($_d*1Sn4;Um6Y+obanE!zer}S(R;F8_K#qnDxNm^ZK!_i*;TP>&H45>s+j3IJWxZ zUpPBImlGgHKW`)(Dsk+4lEQYlSqET#l;4eEp?1=2>)AmWtb!a`p}9Q~Mz`n>oQtkB zfYC3Jp?wNa^f0YYU6V_DaJ}I{`J(eypURSFojt(ZPLd5hdmxx<>Z75X^SlW;G!3vO zX{-ddOwBp~`;yXJeSLid{z#cyspFAdK=>~>Is)UOD~;$dG=&U-Is)o7snV>U7aSH{ zmenyTSj8lgn@S#X)8BN^yefr#<%(oX`_#7UY8IyXWm@6%Bpr)R1El(Gnw~9`0I5QVs ze+(x?9@iL6`YiFfw*qSR<+ON0j(VbQL%#Y+GhxFH0E&LAnTYec7df=r^iJacBOEQE zX9$J3P<%shEDKfG5=#Yvq8q~y>W&a(XfS^@ecLNcKOYuCeI*$tOqj4g8Z_LNbMGu_ z^r6LRkTU%U!7K@yI6ww>H=fVV?jYiSGHk@^4Xc`TuG@In8|@2I=cO+T8}|>W=~I#HgRid^QDFy0F>OTTCI*#Vy%nX-jiw=#K>?iG2IKtPQKp) zD7x1YyFE=mL!c-GLMXc-$j}hpt=>div5T! zXb{3OK(NxZC7A5$z8L5eZ#w95ZpWj^YH(B3hy(Bq&xOY+)Y<7iex&{W-FX84l)1d9 zDQC+|!k!YX6<+T{d7jiyB3bG%QQ^9hsM0LDEEk=gbR5bWmL7U7#&dla;ZHslQyvo| z!`I-ZXeV=#3Zg|G11q86Uo+`XStfi~8 z3*}n6HUdy6>cu9eI!s(_suc~*R`@GCZz)gv&=+0nl#&yoQGhFjd0qLUL#54Bz(SKQjnChkZ(7BeTZ->jLty4%FGZ&tv<#_nO){Cw_6b&rR%NfOd74{-le}8{P zbtsAN05?RVIRJafqi86W9BxwD0|PU(>i@4fL|=v|`^z9?mNLrbS;p67T*=|xBtE6S zT`i*L{8c1=_9f9V(az$dN&ETkM)e-a0qCw) ztE>1@gpyjpladbK)xSj9pBp(7aNp_Al%lx*<^U9jb>S&dDSB)D3s<&M@%<@r4=Oj8 zWR7>=Li_cS&$g4a^*Z2ujp#U%1F$d+@Z2cUNF15pQ%mPYj*c# zZ*u^AAzw_oMd#;Yv>HB@5OfVehT+l4|LS=(!oJpjC|zv}ykaA2j^qHWhyo3-By1$1 zX78afIKA0tBD>$W15h-ao!GqSGzX`b8s39-kN&v7zu#wrRQMEt=du)de#%|EpLBMP z(-d~@2@RJ(&GrpV1B~PVc-#IL$D=ZCoD=IO!zq{0HE;U>_`+DWFFI|dDJET?4Ft&> z<%s|`_Gw>Nq2;OHkhllXcgQ6>Ef9hG2L@(%UAu<;Ki-JGBW28O^>EFT&|%U1A_+bM zr%cu(E!O&mcd>XEni_SPPY0k-T}jO8N+ZCb(NF{mIDeB7r`vqtPhOXbZA}3zQHw+o z70Lo_U|>L7|9V>mU#P+(C)V%F1~rk29=5C{TWlbV#iVKu03gIl)GMx0j8(rOdXc4P zcpHL77GW*sFj+dEJm*Du+E1msp#F`;!;Jvw+Pq^unAh**Tt$6>{w2=#Do?Q)AoU8X zShUkht!QW3oY@icS7AT=L2a2YC!nU~;(jq_1u&QROBAW^LR@sE<=ZsA@%F91rJo-HMdvL#pEFXQLLJtcMP9@R zw=2C`W30oXd6Tgc9L@pQ$d|xM7tm6E_kXaximo(V+TdTGJ1pD*P})w20{a>=o04DnoSO`gI(mqqi#uaOjip>OG z9Ij$jwA2iNlo2Rg_e%>;v6dhs>H0F@%C*xGgE>4?8sQb-5g*9&2O57xf4Tk{`*8pU z+1^W!sc5?^&xuLb8~{Lwm9TLV`8ihml~k|CySlo12GyyBs(}-rHvzgvOLV9Mpqm$@ zu#EOhp1*0{>d8D4C{f&Awx%6qd#f-@lvzyFF%j^YpM9o1CNMeO5S&Aulb)kR`%-^@ z{~Lqq)Y0zE^f#qBZrnI+2|U+m5f60$Ch#vc8=3$B5CBO;K~&(x(H_Y2H$0{3#Q!R6 zRPi$cAmGUZ3WnwlU5lBm!iw3tm5P@}m^!WE;m`822hfK}vX5T)lb-T`#OdarMga(h zr=gYnJP2Ebhrc_=t4foG=QWa$6F`tWc^Ls1g!<6DG3cj!4wVP;iMgRz-)!hEyQ!=Q zcyRz~VEIhDCPM0gAN^_5Zil@jPP)o>i;kA~&`Mrk0POTp5hJWtpWi#0u!;TV+lyD` zNepsRH(~^+*1Touq7yDUy@<0-+p76)(-s&_gP{(^_tff_!bPa1yU=I}4|M<*(?jZwkM>ZGzrB!S++~Y8 zwFb%C)K4wHr-pag%0s*IrexogbZs|Z?_}moB8=^t(XlwOPF|VAW-y(RvV()quCKLYbHy7NbDd{JLtpN;SoYtLXtT#8kDj?`ZD=y+Dh`)`{=qCppiIsi)z z`mNAIDqyAey#5&nfq?JV5DNi8g;UNa4TQX9ZJ&8qS6A1AB>ryLsJsa5Mz8--9DrS= zLVte}*;%R@2Zn&^7#|`jU3gT-cQywAZ^5kr@F6T|E7>>n&)6YQcn{pA`qn?+>AxjO zK}T`~#1xt(a7eGA@z8fEMtzN@Aki$D#t~4D=VI!UvwC`Z7QmKzy}0qG?as&$@UISe z(TfnZbUQ~&d^QJw8@=rUSo6?*zxoCQMl}SIa{%g%h4P}90<;JGICvZY8-+=c(rwBC(AI%@$~0o!wM;YO@AgCC2o&y& z)iP}1iVl~c@}our2pG}sbKMp;g?dCjBRM`@L6*iiQfHzyrOy1wO2x{qj4ODo<%9mnZ|;=~Ei zqOy6ry1FhSQt^C*M#Uj8k$iFiPS~|1xuhC?y}_YS%(W0{XgwREjG4)V9n|~k%s?yF#ixX7zgK=RHjjTEy$T_(s*Rvb#7eLT<@IEXFl!d zsEqpl>ue4Hf~qpp<^j1PGBomzjt)E(*WN5K^tXi1JFtgO^_@YA6u`5-4XY|Sxf_x*eH7h^eX1R!TCIf`{x34w`W84$z&g+WF^+w>RHZHAaej_TG>r& zQ$Nf+EBHU@_KcR~(2RNeXgBBeTdj~NdYb|e3Nv}AZDw9A?tfo#NzF`&%sTU+g#YQ8 zz5}rzC$!N3fXIk6s&XI=|4YQTv79dOt#=lWZOO>8a263jzO`K;Gy zTVELsiJ^_mJ-V5P6!>84LHR&^_%sXuI-e@|;YA7is^r!@G!2z@-O^~lO-Q^rY}7ge zt5b2_)z#H`g7B?J!w5kAuuNf64ghv5lWp>rbt$!{;=B_Y8o$!S77q`-KKOj712BaL z3ZDXyKuVX;8~{KFgbJSm2t@Ce#ZZB(HCF533_L|dUxw9-B`|6b0c}QhEIoaVMy^t+ zbX00}L#4!jMLPg0yJDY^b@)s?ptP6qB@1v z0eFoYd)0d(ER2v!r zQt~iP(uY+Ch=p4$y4EV;qNe~tSSV>7IWjT%dJO_ERLgr!IRJ0)P!H@yU<$sr0(P%W zcoD!7^@+fA8px@>@?M^bldoNcOgIVsu7=Mhz0@}lS`rLy?C$RVDUJTzV51R0F2zIG zxvrDeGZd*<(aw93x{aAuKsR)euYJDRrhK3`Xhwu&=m@}c1fB|y_&}aN&|A`isfF@P z!{Qzr0aaYwrOZQ69MKT0OxpM2H5Zp?0V%0Gk+-!V$2kJ%w=>Spqa^(?I7K=fJ3j!w zy{D(gVIq8lQw(5W-wO6syH+kKc zP;Zj(GHt)FdwU-vKCza7~%fXT}Cf0_!Pf@ZX2V3 zMt4T7e7Pqtnjv}eirnID7=d-k3vPs~;U_Y@k@EF8(KWsmFgJ@dG^x-FlX2Jdl5lv5 z`W{B}=>W(YFVIMC+Sk|jaZcPfD##nrjRsIi<#czU+X3jQ1v?rt<}eCU9)2&nJ&rT? z<>}L>SEX+hn$?s*w|buJqq08<)&@}jsr_t0!3czu9C>3epB)&=+9PA(F~Lyk6nDz2n6^RcQ5UuF zd#MQ>D-$P9+>8RO4|8c$K;@xqI(-uPpQnM`7JY`RW6Gw_Z1Sqn7o*#B_-o|N6}jPl zI22OZ6^9~EL2?9@OebYvN%DqIq0S#G@!<;R)5_dqJ($<;HNdvdD}IZ&VFW^~K>kMl z(8d~PE02mB)}{nEqMKV6Fm>uw7cv@fB0AoJ=w)$;mqg|}koh+>j1!o?LG<{Did{<+_Q8*$G=K%C0xSMkw@u?hspwe)$)+&w7 z-AUU2`s`hjRcl z$69#Cra)=p%Gr<#eG?8;sSp@>LLl^B#I-n!+GqP{8XjeMXr!nq6nrevk_FsmE~BVn6@pqq;Ud)x-=dnL!a3*r950SH&P6eOdp ze#n=e%CD5gCmTtBSOD^w4wIEL&9$w4bInkdwZ87RO6_| z(s4*aW+4musbO6OPe88>eu+4JuMN<9{Kp~BojB|(BTsasid0N}I2HW&BU~3HNBy`8 zzZ-c$AgDwaAiqpj-ti?BX*ab0#IOzkLjR3IO;9{h$W+m(a!Y;Bbl(nu@AR9=e2?<_7KSIYF5L~aE5fn}vb$54bTH;{j>4cqpg-elR zf?(_%N%GX?@MMxY87>RW7#N7`!y08lex{sj(SFK7o_SXA|7x|WwFhT4lI%zh!2JUQ z1ASC7jl_}HJ%{BLvBldE0-;X<3{^sNURr#%7ba1_n>6ax*pVN2*@PJ=YL1-kBJnkWVeMKqd4+D8?fNOU5mVTT0=@p*W{M!d;pr%L{LN3Ka z^hjOhLfDONze2~G(M})NA;^t(rDyRNY3)h6>R~v}Ej14jgQZ4SeV$c#ne?@(7{TZ?k^|6-hkx7XkLLTUh80OcbDac9lDs&diu+E#9o;4SmE@tN zsmOl>_tJ2wVs9tT;GRV<=LpbntqnhcfQQ0aFP>e5IIo2NNUvr=r70{qkBX!dx;;g` z_a5}z1LgF#2|+1I`CnX0;hPsas3$g|EY43J@*-3%AM5)feT@h(k^`V;ucAOGES#0D z6oL08@uG$|Nh&DPmz=x^B>YLZtRn!3K8v&~+kxn#4@})Y>uN*?=;qc2sKV*$>N=V- zqs5R~sh)+FUnIVVVArF;p>lC5O?ME%KXlU@B>m|0JuqAWmHrKvoviWqXTh(Kj|xv+ z`B+>__|LU)%wRMJ;Fp6U95bRkZore$FkE!+6*q{L??N1d15k%rTeYr3C9g$-uPI-P z>p#X4s)44=tin*e=KsEnURAgiT8@Wqz@hjtq2~Pw;vv~y3|1OJxt$7IZ!vrw4SjvQ zhom#78PYNHSR0S9u==ZUk#fIt0rJ!ba!+NL1gP8O$ks^7L5CBO;K~$BU8ZVE2ccIj=@K~=U z>9t!`9tY6ykJs}&6AgjGtR4~$()rkbVU#-qj%lO|bsYIFyGmc|gvs|`FtK-%$G%Cv z@=}+mypq1s{&h2mjOqXo(TOy`1pbJ^s>FYwf2pyI>O*HTlAMniE5^Za{+q(8MS_RX zz=|^#9OIx??#2dcElNTH$FX-nQ?p zE2Olky!1Zq+uDw_ToL#zKuWuzRix#DbPj2y z9G&Y>L)+Nahbi}6)Z#s z-%8ff*O&i}sU3R>RCdYlFOvBEaKki~1MnupfnHt*ltR*iLaWM4!s>19(hWQzj$mZgG{z>ZU)DSdAV>tkd z&zyPe(LJUnKZ8 z^wY}ss2YCN6Jm4|cF*|zP0%M1gf}dDW~*CfVX)(GBYOc)MgTTf4&BNQo$E+1hf<7 zeE{LDU}ueZy&Nf|R~%L2FRWA%%3kR99dy+G{V}}LFV&jmiRiCIY0W;D<^6I3vWzd( zxb`F8O=6^6qfK69Bz=`-ja)W8z14^VKwa2>sS*);(U3$b)LP8*Q4W`aQy|K)pE4w@ z;e~Jnw0X`K06WFanC=CGRml7YlJBR&z+e;-0-RI5%!h?@cUMhZo~mlW8hedi>(i$-t?5*GQs;|PPxFH9C z7;hsHy+6&NU!t(<>s(%TTPj#{?*#~(JCzBw*Zeb_Xpi(p^9;8~Lr;Ujd*P2!;Aib5 z$Z<3ZmQfM#A7F&$udrTURL4MzSIekMyE3m177yYK9R?O!zte7fSv;R}{gs7?ZN;%X zZP9^@IJFf?yANY`MWI)GAJ9Rw+-POqOXc^+T4K$nk=gyo;1)3fyf*Ndm|4VOM&x}F zjqp}aq8`$_IFmf^58#>~PLZ@~elmER2No&n?_Fo|pQZxE&yhFflx>Glufi#kc5XbG z`tVk8S)RsUqqUBGfM?`OiDn0vfxYs<0Jq)B#Z3ht&+LV{c4m*P<*9 zM|*wm(i;Gt5~hN2&KKdPG=6$*PNM;yr16@pw#VM7x3^ax$a%h&AC)J)3KetWR^nfzDm`3P}M5#hR5GA2zICUGsIB%DVSF2seGu)`rfSW*G z&KN;*bTybPgVx7at5x+#IW)=x0abKj;=TvW^=*UwIqrp1ByHk!A?5E{lwVxs5lmd! zrRR>FMcNk?VACOMA$cpiCi0-^V^PCYyWSq_>h zT5JEC%|!npnP*|IgyL>Ens6~H-4nbDlV9S&E@%SxiWa|6F*`e8gP#I}UOmz)SR5ut z4}!^B;PC}2h92-p4uC8b2Ez&sU43}-A7HC@`hS#V8YPQsDe~0qU~(2%Or+9x<*sBp z#2~K9_oh-rHoz7-^ukJ;`sQvD{~z2kHR}NMljw0Ope?7E(Sw6z_#9DcK9(RV^0|{& z!$2w{im9B|#3t&UeS?R);nYa>`WfXz!?M~p!}Wl`#CuPnEQSzPG;|IxD%e-yUC3LT zBmZ-7iqwVD`mD3IZe9yKH2voA;dQ2{#jhOaBegU0WSx?zz(X@yd*w2QSyX4#Thx&9kltc z6$d~`{(?d}t>&%k+#6#UhQ(&664Ac(zwstW4hh$dokP^QL@9a2v7!0fPU@XWZ>QsCKjF#tSt!^hsk~XEM`3Tq?Kn3s0kVe+P zrHo+AD5KEB$b0}c*-Q2q<~J{w$PaRkwHHp?>9^_tyaFJZ2++0$M9{&k44}vf*pt(} z;TWjY1*oH=!!1;z0@F7IuIT9K&~R0%8whE8)@5-7zDLIFtB(eN38(3i^sbdxHF9^- z>(}DZqd+31Pf(-oESeuo&ZD8ZiaauD*42_8pi6F&7aZ|M*yMO@;*wRKbqAjQ30E=l z{2UQle)W%MXHlyTfFjU)_zJzUj53%RmG~tBy$3e(h=6ROv4@S#UcJz%+VyKbBA`&{+u6ZX7i^z^L<5;#v_d zGcm4FX7S&WokCP^rmMrLVle_W=#eI^sT?zcL#Ywqe1G) z1pB&c&W2f-`2PVWr;!)t>FteUUnBI%v9ScPVrVh+xQTK)p_t?vO9h#9qejXy%Pj3U z01`&?cCYIo1jb-)*qLx5UbS|qQy~jMv{q#3tr@(PXM=l&O0Ghs@0dpKz3_tw`B^ws zI-Y#G0=QfglbuI0rgX&lQ~CTY`CxtSOLhN#RIlts{(l%u-cKHI4JMfAdg-~QPnoAL z=fW=6!E#WYZ9*{$b;WCRx{uCMo^~C8*D&}GvlOV^xRA#gjRG|vaoq?zLlTya{!1pD zRyLsTpb18kzjl<;VDKy>$JoY7Yjx;vsFg~i4OU+vzfOgt5fgm|j z&+;ldC%?na^Teh-<=IW`pqsXh&#aeP$EkpDUedT8`87@F+7ZsZ6Y{tbRLYR{{CD+4 zRzkJw07#DS@Xx*POc(?KlrtU~QhT+_2`J;MXt&ZZEQj$gr?=oTKoH<&AVl3h3bE0K z%zr*Yw3-hlNRqT}WiocYxU+LyRJI;$&2i(#sduFvBi9~$J(1&m$mb7Io;Rfz=XTOm z{*Og>^r}zqoQ+;#+h8hj{8F}$KcnLT~dI>vk*Vos- z4R(GJjtT?mqw+|&96jLMQ0`c`jE*^CH$__2uW6oN^!4@4t^D59(*fU%EnR&?-LLS; z-rn9du<@>l{0f{g{W#C|Id+8VNt^x`}i0#ohzzXt+kzFsB^2LQP$ms5G&pp2lC z5Lkwk9LS~2IT_isJDuJ$*5$JC-^m2apwkIdp7I9ECjYSVqL1^m(M?kV(rY91)7pRo zhkYQ8i+=-;$y7qW01M^aD72QX(aYIcA&&VW@B=8f1sp3KIDY(i_4?mk*I!{Q%92Oj zHyg0$SK(#RtF3+MdEN(2qHVZ`ytradPmjx=0ov%l0CPE;%_TXm3y$(2>Z@Nq&AiyTgu7-kW^Cu@!Jww zCm}HguJ<(6xLkv52g7BhyTDm%8;%gxR5JC#SXOWhXKBIDd}8A;yuxA4A~rxMlFh6<(QGAc7vW-`62I0+|Us~^G|xmjiCeTkfF zHML$DT!s+=4F%4qR}Knez(C~^J?6&Y`#Cyk(XKuO#HCV^Miw7NheOau`}w;(Tq+Gl z5Eh%b#)xt#=ltK)Ig7(uxSIK#^zb5NdbOL_G`;p)%F}r27*2yFwWS(e$xXnl9e`dk z{}#$Hxk=n+#4{aCU831H0DWBLNhRY#^3&?{s_w){ zS~#X&7Kh1^rhVRp)}K;E3?>d6&Pz{qds87xr?-=rA3~|4;4+Xli}?dGYoXuLH65f! z8DwurM&&ndoJL*q5yDO37vM6|66kU#yidJuL8svKKt9)*L&hx;F4yg`vvvTGw{kzA zeoGY;mA1}g+sDJ-0h$FFMB* z{9VtVy!Kz5G_BFlXV;Yn3pGXtiK(622Yqt$i8lZM5CBO;K~$8VRzjByqRb}>WOU9W z`AM(*-Iq@)Z^bHL-a53m;(IG?(S|4x4b=vWQvON84}tMee@d6 zo9N^UFV{*<=;I2+pl~UATQ{SWUK=DxlJqsO4}i%wX#a*P4Zdfq<>F>!qBnBaAcF+(a5WmR1PzPkA641tz0eF|E<6f( z=jV{Y7siA9BjErxh{6#Vj3l~g9mnUG#?kx6seWo$km!}cMX~YO@PH~0U5tfQE(Zo? zsAs(^`aOqUABFR(vxs_3QraIymMJtSTMY~hsIqoE=94A30li#ZK{!C&aWT^w>h=G{ zujnnOUggOH(dBXYUFg#Rb17UxPUR&H`M)123t3;G3{6_O&>K|L@1s)cr?BLbKvt0| zV<4;Z4jBp9b^Q48j}i9|;Ih(G1m7Kg2bt>0(D6skhDo-nGZpZB=ynAU{|(kQo&?F! zo8Yh;n5dF_3VXXsJO&idi3(9ZZG~{gT-f^e=%=@Me7qjIENN@6lQWQOZq*lrk}C$N zU7o?A)|AqV=q0E6Lnv0(UjGMacOD|YoPf===+D*d=o2*20hOGpw+mZik*5P7uy3St z`YstN_;=RHD6TN~_V!koPgiC06%3+=RIdzb$WQu|jc*43rSRmBM!!C|Z1RsOFZ!v{ z+L{8dkINjy17%&yf#@xhcHz{N+hoexSF!Un@NkuS%P|J{Ai7DXjnGXFy1pq;gsnC8 za2#oB)1vi}0eIv1P$!BwD=UP1srQb@v003Z`dX**6o-DP$<#OC{@bzDUkR5&7gwia zGfu-LuvfmW(DwWUDYedmpcu;A0gx8op_2ZKj37mIAw-sZgISq}hEuPh9fu>J71-LG zrmT*@*U(Kpm|G|uYA{1IK~plJkEU&00VjXC5Z#U^k7?WI^_q$-o|`pncno-~06tfP zh10Aax|0(BLofA^q(PP5-HGU>1-#4YLQcF3X*@!{I+(OO!PMn5g*l~HXtd~7uM2KK zKkbrw2m)wPF+r(FBhB|CKK^vdRsV!98A{+oIv>OHXo-!32 zGLqzW83<=!KF$xsP%m@wR9L%T5tNFaq+n=slD)CRtLWpr&QfVGim>S9e#J&B;;?Cv z;Avba>z5!Ay)AkQJl==Bcf-!FfJt<=MnCDa8Yt%CnvdWHbdMk(x{JVuZ5ks;{o#bl>-AaR)IM!4OoNr_kYH_+Q-cUbt*@8u~1a(C45- zy&~YW{6s-=qXG&s)F;qSL&f@tM){R%O@lwl)>JNkr0l7|Y%P|+ocm(m?Pu_WdJspLuMi|m_^*n%n!tdwcwP&4ClK_fzmW z=(GZQAiriTX1ER;C#4`{cMbsg>pckUWxYjF4gmU9v?y>Rl%9&=bY4oPGF9Q}Cev+# zE?1+=3$UgKRze|FAOykFt7N)enBvfC(<#XB90BwRUhqZ)L^s(;&cJ-=b|!jV%X4KM zwL$E*Nv{m`0FC3}#HY=DqQMDg z#_2*i0Gi4(>Wp!q&u<6)mKHMBN#Bgn@c4b`pw8C;*!yj;`<-hpEXzO1E2b>=_w@9r z4%UWrUc@ib0g!?Z(dg*iWgVA}mEnfrx1q>^R6h4nd1znkKXAS^T*Lw;l4*;sqG4DL z{;?{FwqgqCVc7_soJ0yKZ11A5=_`X@bQjb7cNw@$M)lu=g>(2gj)Kt3_57$?)X;r_ za;Ry6Mu$|@*q=xK|1bGuS;e9FZ~|PMQ2>Mz=qIQ68|bFdzni!eI%!(sWa`yNu*;+5 zS*`hSoA}gigD%cS3PV?Buzcv_zM_aD_8G2U1$(2S9RMk+MrSV!8pV6d%6w{MFs2IF zA{cjfbo(2ut$Fn&x8I<&zUH(7VJkfo9?O;Vro)$ze{FQpe41+<&?DDGJw!eMoqkNZ zS|51I&h zew_oYQzGz3J{$mPdj=KJw_-7>6cVG8^GFqn(N8ODKZ()LrdRR+Uih;dYn0$R?*9fH z5^47-eR=M13ZZiXkToRvT9!q&5MvMZ5ZA*F+D`b;mLn|xgI9xvMt)9~jm70xsUip5 zl|OWIA!TkibkjPJ?T6^6UjO+t{+H0exUa$KcRi;t2CkLi9(3B9yuU6wg|x_TQ|xjl zGCm7yUD#uU|ACK2-ghAD1j0G&scZaJT0&>lKa&5q{5u-<@8;YJs-|;^)k`5Md}?KNpENptWRaO6J~~(G;X!>;16GWT65T zkQjQZKBbzO@lW!(Hcax~%N(S(+8cew{3--o1J+K1^CIW0S1ffe*DDHRW7&p0`A78K z8{KB^aK(X7l0kf?{{<3vdjt?hNA-+6IMgv2prXo$2I#|N3cbs$A+V72pMo$OAnUGF zo^Dea&Z8i7Qln7k)o{e*1n4V+WmvP3hYkKsew<7`{3TfEE17CQ@<^xfIP12i(pB19 zlb0Xv?(V(_T^H1a`tJ&LUUo(=H*$wQyP=B~m%T(73Tf2k5=LDPM?P2nB-r3%oyW$q zNu4QY>hOImBprP_0NQhUM*z7Lj;7*~E{!l5Lbt7oBcRPjp4bzRXK*1gm%K$|9IF`h4*Bsi8r~aX8*_Y~wcw zaoI`Cr5ni4TJvx=$3gTkkwdgT^@pZEx4;HEAA{riS+*hn{T1E;&9qq;K^WxQ0jQ&} z9S4_nb*0w{BU5N2axC`WOR)K$E7CWKA2HvX>`+G z?`LwXg-Ha-(e-G&BDnkvEI5pd&`V`)R_`+g?PMqF&FSd2JFJ!SUfw4k0ZZ+}{~Kh~ z7acX!uUB)U!hZz4-DNfW=q`OP=EBf*C|vSSp*R4Vd)|uP$Atn->>rw9C7^*-f~%8Z zv_S2voP;zQpj|euq=K1*oTp)*e&me85dddL=%#|I@~{UL>hoNDADkj-ZNL}kNv;Pb z8kur-#^x?e5s=VyR@oC{lNpr9OQ|4lM>z$~eFjx6~Fu0Y3wE+e}Fr-gaYE|*ukw`0d z3F4taHkbz+T#07q!J4}yNRE{MRwh4w4~Hl@_!}bI0g47WHz&*Xd!dhMgbg z*ex>SSck?1At1cThpv2atli^Ir|jvgeOf!E(Yb;o88ewxk?($F{bFBVUnj?7J}~DE z<-H<(#ppi+{eMP1@)5KNYR(^dW~0y?fVyx;0N%%_fa{sQem#j0-Rq+PU0`qwj(}FG zYpdbV^#2O7u7OYwD&rGILFlBRJI5T)LxH{k{r-+}seWAO9vYlg!Qz`>&__sMR3rlA zLDhv%g1tuHK2F-x;gIMD)oN9r;?)`wSAQXENb=<_3w4BZkeNQyCO`Y-o?r$Egz5lD zwX^V|l-Xa@Nv#0rFd0?>qT*FUv=aK?2Op2}A?+K0IF zyJK@IIK3YEiD(pSP7zK2d>1>f&ST1p&dvbiLarHQj6fY*%2Ypf;g7*yUn#sT<7C>6 zPNPHW0DOgpuk9WC+7-sf^Vr9g0Xl2F*h#NoejhnP8ks?y;VEPXKoZ|freBeQ;69c> zsB6hE4UZP4IR*#meGsDonikkdCjqgBxxR_Kt02=IDiDNG5IW7m9~+FPke`MPR0(Tq z)hKjqQVEsCHNfKAU{U{?S(8!N?PDRJx{iFN+a97}U5kS+!J*Mn$f!4$mRC6;PbAs% zuhn-iF;%9oQT{13BaJ3c=njBne~FB>Cj1wj2y7J&9jC^%LZ+PrwUw~GF%a6f1s=gp zYg1wEkB#1p%~t5%Ggp8BnOJytM3{b@8MM57p8c+|>>u_RG z<-8tYiu5RDa$WcnU=iA!bm{Ctqw406$zS)utD%6V)ik=sVGyLo{zvrs<@Bvg<3FoB z1R-64LdaH14mw48DfU zd&26V5|oe1<^TxcYsi4h(V+Yt)_HPFMXSc&jRuej)oa)uEHosottLam<2+=X44+R0 zqJrZ%G$C7&r)~#53;z4kGkTEYP2m(t`_6BT;#76<>U(C-|; zUl>k}wDS3K@R-Diz$xI+Tk9>QhQp}(f{UxKgbg&1wr%#`Rw0FRzr?R{O)hYl05CBO;K~y>bb>L6IA}et60GU)h zVGh%y8I(($A?KN+{Z{n8G#cvvu}$03l0B+fv_>ydW} z%Bve~R6P@da7D|YwuLmOVXIvUHOloSVH8w$2S7%63d5{Q#jEXeOFI`MMcQEss&fEp zg>^0p@6WiVw*{7LC*B;MeSM3YWm&4>pdqn6B zp8e7MP4Xi_B^ow4Q2mvib(km&ea&oH-N0=0mL7fAjP)-1u zRu%0=j0R|4S|1k*4Ug-QaT(-2LH1IC<2W=KTarh5$Od9`TN7vOP9pjVoGP7!;>(j4 z?*a>#PdQJDl)uRf>PcTszR)XUS~MCG2J<50CD`b1gbN~LNU{|w3;L_>tboNE;P4?5 ze=l6hRsP65D#hXe)Rok*>v|YXL$7bt4O#y&#SkpCdCm99%<74THX5KW&mD{-pp9i7 zR0S!H#ZJn9at6?^3%&NI@p~2B^jT$s$m@W`55UEJO)>=p(AD)K$p^2a`^O0N zl}UYHA|&5`=Y-lTXlB2=J3B@p|vZYM(JsA)Z{ddR71U%v=4J_`lRU%ot>RCWaK(W zs`IdFNoN&oGPZi6M{%yrYnC1MW`7s8yWEeEQHzeQkiEu@8%OV{!&RdG#L6yZ*+5LC zyB#)oo|yFxam-~973UyrCZkPmW;sW5+)?ri*tVW$^}5)O*!;t&^a>mbDbMXo8GDId z?pkX2B^YulD4cyIC_8}xb&TMsJl)sVzbzPSh&=beNs!Y#a!oY{z7Y+JhTiUz!DaZ! zb)Kaj8CpG0SJ~=VjQ*>F!@b;e2pk%zVcY_HX{h|gapO8eldmm#RM}GLDvk*ZyZ(-Y zYhb-rL=ZjAgNFYk|81>&$Z>Qu&N;2)RNnr8j!U4RHt8Y=hBT~wEl%jqDPvA3hpw>|#qeoW|J3J!qGsg;}m#K^1k_4Vz-g{M_el>x+@CqrQ1 z3Oj|rn+E9E&d$yoP(HK}-1l?d^PcmZ^Pc<8ojd1|F0af(j3$36 z9D2Kv!M!65e6cD#rdS&Z0T^yI?;qFEUH1Q#(c5WKQKNadX8-F0e4sr*Ojar8Le>um z^~VJ%dS9F;V`R$DBk0`H3WSs{=rr)2ha>*u2e$#zy_^B*ZKW}H?n-1cg-Yp`(ltQ| z=|E<*7|L2*M>N6jf&7}2dE8m;_UuM4PH{thX;&7yJ|wMFe`rRE_cLT4g=%9tVurV6 zcfLu&t}w+yAV=}1JWu}1LzA2~{`TgF6ULGTYF*HnchgIUgus_8{Sq9aHu^3Vlp+JY z+|vEdZINSz(DYcNEGM6{{foA(!L?jZef; z%_v7^#&YH^;zcN8Zo#c!IMkH@84o0E)!m_rnc1G`#9AZrJj1hZeuR#0%6#TwP~7kH z3vNqiFEL;U8&Bt=4DLC5_<{aD0eFq_lu)CK@Ym*TRE(>X{*~AyLd^S(Ah`wEcJs9f z=tloWLj#ucwu2I{iIhl_lK~%j=a+LS`6LQD_Z|KKOd)}iitk@ z($xAr$Q3nPaFAtDlRlj&z4t~yhoh%!)6$b)vmf7qS9Iw_Gz!L(u3R|kaPee{x5CL- zEg5g!Yd6W{aE(`uS8MxV^CVpT(U4x3!Ftz_&NbG{6dL1~i=U2NKBjch)Kg+gz%R9+ zuGU7RrFgjXBH{eWb`nDz$pgp`i>Ld(EiDU!d0}WO4brOK6^mql`CD3ZiHsL%c`+7G za6hLREFZIqkR2HNS+qpDUEFKF5Jf(^&ec#(QdM@TmpfrAs7vAkno?*^{3H!ay z+7%FZ{ERwNuX{|>lX6z@%{v-bCeFM%tlq%AjB_T)YKAlRjV01sjoMAIp^myrH*4q> z^~(a?%q~rc7Gp_2c6rqnINp>|-Ict)W)W*3+m5$#&__=Tw*(*)8+lNR^`F;^#Y=$A zse6B!t;Xi3mCxvzFDkL`*a9DPx4skq)z#Qgnrh&Pz|{~Ubs`0&T_M=AJULqz(XzRE zE-K;ZawfXrZK>G62|4(+2A!U z=z*2cOYWLt+30?VMT=#h`U;$R`t_1A{YC5hh{p-n?CN z7D^F4b9N}v)64nBKT5Q(fE*{3wxTIryxoh!~CXai8S=atSmwWwZ`R{u7#|#>DJ4u#4_K=LE zW#j2VIyi4%xXjp>S?L)mWoeeS-yFwo8Xf%xv*t-xm|A2+BFK)j_rGo0Z6?NyGjj}A z=t{ddD2%oq(ehFf$PA+j&gjhl2ol_t|BfkWVPW*4JuJQH+Dg*bJ=Z}4u)GXu_t?*o z_MhTP@w?TsKkW3`4o{ii9_2`O zS2yS^w_rZ|V^*?XIovSULfF~HxzwWFs7b79h^K!sII28*e50~XT5Gc60?PKyZ`CN) zU{<`N@*Vp&4}rAljO%kR)d(*0vX3`c6z|#j=Q;x!xjUqts9vdlZb7!m z^^mS{|M}!?T#=Gw{JIi+HuNfYQxs3{x|1BMjQqfbOFoR-xNoZpOm?C#4cgr8m-5zw zKW*E)&s3Lv*(=CNHo;qDrAhW#^vIMTo!&m{EJs-h(FYdfX)jHD#5k_7>CKb>mvA2ZnI4i~++jVOCRA-I5uQKgN zhxVz=#2cGAXT&b9W+b|KGmpxt9et;U_5uyfR88uSB2YOCWbgXTxzC2V7kXbKe}>$7 z`RO6Er;ew!eh;sA&$LU_G@FfO-<@BiSQ^VS7#ePgln|sI|9$N#PI3j7s*tL$Ycru1 zhuQmN@002B^-@34=1|7{7!WE?Ot!(ujONdN3%@aYT4v_(6_xI4t#zJW4&~VA>kJfl zP1}Nz*Mg@9L+NQcZJvdwh^m==wDH9rl(|}+LNdp4HEKUyBa1Vp&L21q&3z$iMeR=m zkgAx%On~#E_*sPSH>1~>E9duMmhFR~5 z-{;j+n=%#U$?^(S>PMZi6CbDaqtO1^zHt4vG?2Q1`<0N?8g@bf*^-sF;inZi^BNMh zuKB)r2bVe;2B9eYkEu#rZkMI;?X&FABef!v{cXE%9}-<|B7t8ZhFnWz_i*Sb-Hq-Q zHy4uts{gpSv{r%2aT8#&PM3!n*8{I2jg`zi{4m(O3F)KXInOiv0@ub19B1}Ebq+YW zm2%%MDiTWwTL?5NH!x{EV5>5p)%_X}y@3dfV5+tLGM_Z}26tZLiL;F^jN}zo5}sQd ziXy0*!)XI+U!q^M{-Az+*N!?|^+T#I@DtXs+K0PFWc?#m;zdY1xF0*R(a*!fBUwpO za8MFQ7dx2r;()cHT;jpasp}g(hR3Iw7#T>KK`zviY%ODFe#-;us*%&z6pGL^y1k-q zhEFDO30MNbKGzc#Iq$L=vYS5fDP>#2af;LnM8j3RP%OE2%1t5ewcxh<8mj#l7B z7!9f(zeD;xa6`EsE^MZRY4$IY2X!|6q&N$7*spv4M3t6>WQhB|opiacqcpC~QK-Fs~$49zh^f zQmWUl=>`F9qY+!^Jqh4N@HXYOoI2!Nb|K31(C56@0Ziasyj(g>aNtWm3w*}`$!;HS z*F%EWru8ou-<(fdJ(jG5&M#PK!N4|~oqQn0Yed|rBfRbUgg2Iit6tf8C<6x-(*$}! zM&gUD7L?w#PmJF-m3y+{Hkb==9mSb}2^;4joY&%yVKw&+OrBF)@oR%Z2uv!U0*bK4 z9vmaDFBu1bZShhy0DElCV;+qlAi!Uelx_rQL1#$%`V%nS}F^nvC@IWtA_8EKC^9cuz&Mb#$-PJa>BJ z3DQ*4ll);5zN;Gofmeo+78{wEjDOrPHVH7&dbNnPU`q`#@pMj<8(Y8PWEg3&Zz;(3 zB3^yV383s?GaQbyoW@QRNkX6FdVMpngyNB*pL|t9-MJKmqov}lcfTEHD^hp-4-acLN-pJ7b!n~q+h$j+pBRjt4qX*DyuG#j^njv>h>>X~YwK>ZEDqyk$Gk!z;TrwDMECPMjdV19V?ZB7aBPoHG8Aj4!{dggF+lZj8Eno}zvwT4(=GFV znEe#^Ga)5~*pVc+7AmEBsO(~$MksL;z`*+v2`WCU88Cgr3tbvf7u!tHS&CO+ZQ?c( z7U`T{-WMhupKEd!1@c*!myR@z51ex0M*Qm#Ojf$o=35)5vLKUfXqfi_@Z?{0ymjL% zlF5exU_GbyKL>6{3ZOH^<>=aRprK%JN9M)fasrtwUdFlH4#K$GDz4sIS{-_DJxk8r<#_Tn(-yNuHJ%8+6{1j+W z`hp1%R&&6dm-m7>WNRBIVD}zLLVEgcTyBHWenWA!577S}Pg0QxNdY!Ja7rj{wF0@= zMGRUk#b6=I7=R;=S=saylYc(0IJ74JNxtol*tnL@EMobV%$_npn=J(604Ib+;@(_} zu6>RkT+S$~MyXWx7NAnGCLLj3N8hWf!~btl?{~&9gmlhH1|DFmODA5Osb9bqWV2RsdNOz3G!(R#ui# zQ{yM!SzPXm5wg7qeN-I@>cQs6w*fwy0);RHlL(A-a^bf=5wG)5rhBpHL6~q7&xZh* ziJeMqK;VV~I#|TPYc_Y7`f&-ELk9fTE{r69RM~?kGscPU8N}<%DEz#MF$iMOlDZ4f z?Ubl0)e0D~VUT{*310j6(g+>4Mgo=F>SJ=V185FtRcRP7!cSry4eT^LdyF(mwqH5O zEjqF#I)55$oC;2T1^AlEIrxj6czsK`c0=$gP*7fs25{B<-!tG=MFNbJLK0-niJmUN z`Qod;EAG3fFd+S+$hmT45-K% z^p?p3%}<;LT9gf1#PjLb{S%9#PXVx*zssCA`|BDSJQQi*t;&!muE_xSBck~=&Yxgp z24Y0d`?>1`BMUIs;|g#Ue-NT4ISs-ei1}`R0ygVKz{amuT0IT_hq@MF0|%Bz1~fYm z8$c7I26WRQXA_S|kRwh5!%qr^AEM$BaT5N%j8D>?Mr(dHit=B@rh6d3?4 zpMkfK{}=sA5TYV`4bi_4nSzHFdK%>Zmwym}VT^lgS3#TxrZx(QP%XT6(CXh}K*L?g zkB>z->%WUpM*xe}*O^}=<`psc9-wEVb=fH=o>2pyQIm!n{ey7_JP7zQCWiclv6cxi zQHcDK$3KH~z;aJp@IaavYS17>0DMz8n};p9Ix&fGU=krc#Q9Is`a38iF8K@C%76BU z4)`cQm(Sk&L{A_ngP`}YIngr@>XH5^u5qHr0JMjS@+vXSiJ^Z1hMvN0+{ivgMr-?Lg$n?{1t@%! z)b;@$<)OCI$>a^}9e1vX3S4WCBYmZoOoHNLGNOeB;}Z#}hXQdVk&~s9wa_t85%4jg zp`m`vXa(Ig>x%evS^63wz0%|UpSy!WXpZftx5wj0?dU5yCZeZf?SF5}z$;oN*VRG) z4)tbrULN$W>kY5<6h46zpa@rQevJNLY%oOL2O(=IA`n7Lv^{kr$^a(jpA`Qyr~MeO z_=P!82ZHx%Oh{`DgW%Fyv%MPd|6Oh{bh5SgLjxHC!D!6BSuy%RaMr6l{J+Uri2LUF zGCFf*)FB{vM|Gd4oSfVQ^*4r1mU#g4n3_6Cy+#Sew?o9n$ zqHrtqwB5$^OA>h>pBeuXC4xjX;@~6VT)LDzzKhWL+Q-&!3PE&sKWccTCs0_#CHAE_l-wpjEeUbET?=Tp4O1hyNIu#uyq<@cOUkzYX~V@?@KN1CYZPxA$d z7*ux*>C}O(GSnpEdWg0*2)itR)m@VF6iUf9Sqop_y|G;&t{+jSTL^wBAdj8Vs-6?@ zh$7)f9P9@UOu2fyeW`un$8f)j*r2zy6Q;CNOQ(*`q$Jdk({T|6n56(X<{g!G_$qd) z(Y(BbKK!}c+e+;}EXtp%Lh#5uuySh@m3W}<*v1RCm(8>#z*l~Lk(d2}($()t<-gPV zy3#A3o`pxz%$h?x<#BQr@u-36bEcD9x@V#1#5+3FpYzb<0N^uQj-dN4y~6Ke+f5Lh zh1p9e$OXuuH_1}o^Hb0GyuO>FzEh!A^t^4uY~a+zUBxXJjP!hC(EMdX4{(D@ty^}7 zE488%Toq5j)Q+;=oMn3N576otxW<7C6B$;2g#TE79>1m!bdkPOSbjn8dSf=zLR~mH zt-zDQLQ_jAcCCUC-Q#T+O!;&%f$-@R;SE3h@L0uF_Ke9Hc-4s%@&_)QefZhG&Pd|U z6=}i3Or?_vIv1+;$ptmfXmEb@VF*rX&p#S$ih=8o8XS-XabMAX1Nb3>X@DKF+6i~F ztqFHvVEB66;LR{59DRl+Hq`UNJ$Q>WTu7L|^-Kp2%k_B+>|iDgqWjc}g=_maW08eD zbX6wU-XiitJ`i&yc(l+p;V3g#dQkPQdXuWRL||aC)4D_3OmTsXt^7!QNQ^6PzhVHE2dgC;ux67_(N19Rol zAFfr9qMyBo2$%L`Ja)VC2{H0d5jmcB`Bo$k%Yyr&Ewj0v2y;8oT@nKr=IKxqbBY6# zE|%n<-$yJ!i&*Qp9?C{QrDeW39x{if6H0^Tnu4p4&4F?|`Yp*x?91AtFV%SpPNl>!Ct3DjO zM0!V;I0Dn~4hp$hx~n0+qL>p{-L>Il_?cbb+U))>j)WUKWSHPwYg~m_qFRaFgFr$c z7UWT5F2x+z4v~SJqR#vnGd28NY_D7u^2`PoBmKm#SX8+R4$vi;2%X!3=irV=USxCd z>i{ZsatWU)z%XLkj@l^Vq*2dlz_k!yNA@%LXB^fr3`ab5#R4vd{HY71IKQqHa*UmQ zY)2>F-9-Ub>rq4J-w&pQ$*smJwnT!&LqI_Xmh&KyW`&y-fFET$1)8{32&pEoj_aeV zJM~r20Phe@ozBK>;hCMwaY_(=N1(h&X|R`ZJEa6f>AP_#yM<;WQqpMDZb|7|)@_7= zir>!Oos09kPOg+ZD^IPQ8p8-TVQ{yCM@8F5KDcT)^fR`^MCgPQ^jdWInX(k~Ds+?@ z0Zbn%9s~NRCl(A+U_-1&`f1-GYD?Z3dP_H|Cw%>Fcijbtu@pxv$056s=vLCt#+DML zx@#k68`^;1+4;CkJ2Gq^tl-~AuZkk=7#V$@udp+Q=)pky#Fa2@h}5wJz2>?Tq6iW< zy=DDnIugGa+~ua?IT5l)K*NReqU>+r=H24Y)-L4beJ^6?h?S?&F4`q*ITP_nAHLG# zYK89gPO+V4y$vZum{V~a$56bWL>v=*GXLmH9GXu`K|#0x(YW==6yWSRdE1rgpGc#T zz4cFyX+R74Sp_ zJBqig{92qhO=@i?-?473%7=&9BC&zL7%eBCiYK4eoP9x!?<)kw5Rm0xnD2w@7s_Fk z=!bVD=UqpYYlxLwTdAt1F_M5Qd%$0EdbYAyBGrpPiQa|$m^G?oVQ0R$C1Zwtc0k;> zUnAe|ie`n~$ReV6nWjYmTk5|zwA`d4s&?*q>u(El?WIoMDVy+R`pEg}oKnd4rVa#s zE#Ww40)zJPW4J*+Jd3_E?<(a03Boeghy}4Qt3LN=FL7APTIj8EtC?(xvjQNG0oYl% zajXc~&uVxtyOICKy~g5j1$z9`Tv9{vOh0TvqsZIcnIs-tv%~!#rtQJ!#WuzVhcg-E zdjYIXHgJ~7f6kwA3}t$hr#NppUf4?t%#gx}T~A%uBJ#XO$$&W+nbUPmY~`kb3N48d z+)?&T?yQy&MFX36a!wU_aH--T6NAu08T1uyZ;oFdK7Iq;5dwVq|2CPEKgCOZtR)ad z(_dAbI5?Aeh%h@Isl!`%{B_HF7Jy{V2LHm;7eLJ1wr+C9bY(4>aM+s}kI41!@PP#0 zxe3ve@QB50-&$z^*5xldk$`kAYDrdFErWyiFiD45zx<@{{BVnk z7C^peG-dlFB75}>}sQkp+D$QR3j zCf(_@fzWk!gMJ5VpS;Og)pzEnKp^X-&I{STivpsD=cxAj=czpVJEV& zm|DSnnhz7!neqN9n$sSkN@A^x!k*95AJ&?OT^n%(LqBV*FQE}1zdwZz`y!&ZvL>A| z4!8U~V~6MAn5gX#>qA`kG>og57ahE5_vy}+ik332s#fpYjFywW=-8Y@%y5k(XO~7o zl0)P^EMw&_$`4%4I1?;Uhn*CO9mxGx0na92nm`^LEhZQGXZABI0jD407&KVHbCG;a z7OG*idQ74<@|SRi_z16;TiU6UG5tG=Gkr77Q%d1I^!lgpK38~clh<`^>23*c$*JU0 zi>!lB(;Byr!!i7L!!qiY7CJA-*mKjOeWvrEeS z)#pX}iQ?R#qan2)Blx($rpakVRL9#9*QNOEb6tm@sFR&>=p)M5AXS8v$l)VaZ(d8I2(EF0&lE08SlQ zxu`5tZKRUd>xQZ|`P;cWZPj5i@eoT~2H>L2`U@QGE0HBuC_?=SPD>eiL6RNV>FfCQ zM2<2f6focz%zR#r(=j1qsjyk3q*t2I-EXG?(>8n& zp9)c&bP%JSaB^Vn52Ah2DQJI{hYlzEJY8H&cbPr@YY}fgf3U3fN~EH%cKX(eZ?eCt z+~#+7UJBic(d*Qvd5ld|>J|%HMrW;}Sp!fP5=THnj4yiUUyT|g+kd1&kKGe3>bUjB zTzMUrLCMxQq#*4Os z`F?BvYhuZ*4qG+9+dkIjNzvIj#qeQhb^a9WSamsuZ_&QZX{(nsFn@k6C6? zee{#rM=Wi`Zb63uoaD=I z(MX5`@kM;zRf82~WfbFx9sFYKb78%WL#!TkH+puejGy0Z66d=82==pa(z!6F>J7GS zEL>1R-8*pVeVYHwM0t8Gty_;3i)H0~&p^^_hfn2`W5o+nG=x3-76iZP@4Pr7JRVYo z&Y$Ug%pP_{)7(G}iEf_6Dn`sq;AAhn{S#m711P}yAzi;sJx~LAI`v}qTv0$`YWpkA zusE#kl4I$z>Vq@jG494d(Ic1Lb=QweHFPD6$4CaJ zML^(7;Tddj!aOEc`8(!6LlR~T_|)Y3KVwsVz3H$rAMfVL95cHvJax>Pf{i;%NBzp!X|Ll7@4NDs5W6nzd>5>%z8*9zri z08r9ZNd{_&+Tw|Yf(ek`n!v6OC~ew=Ki%Xe)E<3|Nz+J<iAyZpgRfG3Odsl6z&x5|G5h&5g-ymgQGE{!P5r( zXFed^?$c)>y--`l)R<#i)u2%#*ha}nKC@d^6`U+L6<(8N{AAK~1a_bE@IxSD4h8Cw zD!wJFpec2yFjwiz*l03EclAvb@E_oHs$B&e+(*CT;h6DH9{`NRL!}nU0JKiu)*!L^ z=r!d|TyLVS-qj}TI@=2#zqDR{6hvP`dQiEm^e!y!lFrPrV79L%W0o29o{?m~6N$}D zFX!@N@{* zsQEt<+%uj{_5;XOdEeaL%@M0hMqNCttRA^(Hnhflt$$Jk2{wWA!dKL$fg?LQRaa|IC!jp}hpx&v9pd#?BSR zQ_r8sT8zkA?m~I>-~D11%<_x-^~}&Wed41BsQ58K>+tA#fm|MN{7|`pzRprM z-xNYH0hq)cwU`FoF2m0)%UXhk7H)));AFtxWYo@ThDDK7D5ID1FP}k=)wn-zuj9T3 zmgDM^k;~=%<{;CY;Jm8cG^{4oH&M!K(`@Ixu69yPT2Wy!=cp4RkcpoQ9gVpJJ-o>h zBq)%HB!Q&DNDAAE|H(q6BXk2F&%MtMD=~Ltr=Y4a^m+Rp&INF;iLqbUW(Aie<~|97 zf^?&^_B+4_>aS(Q;ks#B$JgjnhPd8LYTGHUZwe{i;UGabmLN$Z5&{gT&ZP_Z&H>Wy z(e9uAV*QA{)bvE=*&-rVHMSosoP2l!nnpp!cD;&fvHk7F3NyPQ+N`E zm(#==yETBt=^|}%OG9ig#4BdpFZgf2qgwi0$Qe#bwqsAoE{365FI0U$fo8}~h~~+5 z1@kmkB!(ptbPwbCtZj4tHIr}2i}F;N#)AjDF`#T7khRe}1_0cH=<9mr_izi>OrtoT zFp<;&G7f~8Q!ZU?`$;qIkDuvd7XwFOQ0ME-sS_cfAq(R%Nhm{T@O^dgy?S?rbFFA* zGw$Uq!1&ZT!`YPZGkf-Oh*IR((Aey(o(;lWC%9R04!d;v`py7l ze0!FYTIvmyj(!WQfOcPwB$g~E4MX5R%y(_13q&Xy|m(eU==W#eDIan9B_6gx1PuTPlQvP&LW- z&-OfGU6TtL-Yn22hS~v)dYPj)00K}qj#6t+omQG@R0M)hWMa~AB5XdjneT`aH-Xj9 z;G&D*!@X}J{N0~Y?1MKgB=AD$YSnU$R!MWEIa{v4v#XZPVcoATJN4exZ$ud;vcL49 z)=39Lw2OQAQNmpb(39Uko#Kl~;C0YNA{yGTF1)n>FV3xLOt*NsRIL5L>ZeF(@j|>A zk$_0OvWGt}*b@gvmH9f}ncvK5dHRToGT~zEh!OF={s?7}faZ*kHP4xDtTvLYVKFAf zc&w5r!#FgzxN3`I33FdL!js$Auz!k#+nQWOpB+5?R^qyV|5zp)SLbilRqbUzYo4`b znTcq7D37G41p9Gxxz}$xgWZGIKWR^J&SWk8>7|L?xS2z7Hbt!#kG7O!#3D*pLfHj> z8k$kZ$&?ANMde0C3EjG3EUU~3pfjhVmghuRrn2Mr_Ej%Jv@H*0u* zVmvY8zWyT3IfL*EE@eCcVkfS|z*O9j*&^(jCbE7$O19X%t$A+$=RvTka2nt|FzR+) zhE3F!GZa)=`d0S8uh9yWLa@FcTZ_0~y%9DnC!!|cbO@WrQtbGU@;HukU2C@Ul89%o zE+bR>b{hIl;q|^$5guD>v%_ybLBwu)1nKJwApsxQZOy#*vkf?7b2bcTz-TF^$};n) ze=9NK=Yb-Kj`A5(g{1fclxb=0Ekav-?2@CLNY97Tfp?&rAO`q3a_p9*Io>dz_0jklNxSGn0q}>aVBJh&Oj{(9 zONxXVW$+#Q+ftYaN1z|N)zva?QZ(HFjh+oCDJ{oK)1hpdnDe{e^>v7e2y{SaNHQQrvV=vJ3*K~QPI0ftc)hE;8 zo6Ta!9GSnoXDk9v=xlmP-maG>&JI}AhJO-A7a=!EdNYx4 z5R#a4akA6z0BM=NfF#6@ahhDT+HuSJk3IC z0}>6GK_YiPjeeBnDXKc9M)9$?^%FjoAq+LSnu;Dw?9T&+A@~**9cScS7oFaSFy&tK zW8RXI;sO5&R2RV;+*NKu`2lq4j2~Rt{r0V~c^HF$>#djuV>>+uccy|pO{Bg7A(-Re zKd;zZik{c~)M_A1Y0jrl?8I~Tl~wI`oll$333VIXcy9miZK5sU=tept4AN#kh}0uI zC9LMBa2vJGRLY@Je-tk~( zR;NE-YLKiVj%f`Q#!dJ!l666M>}0Ci8+PaaHrWY9sCi@!+@N&mB&9dXI5$#kX-N3F zC%#CDAl!00S?PS1&oFRx%rlrcoTw=EV{A7&5DMv*jos}mb-&!7!;}m}4zW0sA-gAq z3nW~vNrcs7i_9H{L#4*~PmX!8yK+6L--uLx9g%3ENRkfQ$o-aozRcxb7LO&^j{ZDM zK=MaAb22Q;g@OG}D8d^Q8}0BQw{I}3zhLA?t!f*_;UtG6I)N&f5EV?B;|AdqUn$o5!4nO&3DLW3iLHm#qQ>?dlyQHe!}r=-2( zRb@?5aFF)z!>`4L(Mo^WWJ}{S41zHx^dA}jisUX$Fr$G2iM#>Bh^;0`Epe-0IYx9- zHmm{pPY*^(`9GRzzq;(bo({KB3@K?g6!cWznV>OC_49DL@xK=MjKTMV`U$n{P~c;7 z3CgLbgs|T&A>r`$kE@TTXz}DE>?r!2u5C50>^M(3!Kn-psfyE=^Nmt))wdL6e(Ftb zfqaBt1Uv3*N;%Yux#B8f1#MY>zu+2HSwev6Tyg!R-NCDt0*O;U!_W^tFm){oilb69P9(lOar7Pc!)5ZfwUwbb?I8Jk9fjwj z=OqVjXoKXx#t<6H&k2bCKI_O|tqW-DCMA94$9nNa%Phn2I`ZYRTEbprs&-j0+=Vv0 zPv2(xhD9)7r3U(EhLkiBzRR-zccOaMKEB3+#(s;S3=xN-ZB7eiR!7ureD>jrOhocp z;om|T1ZT{(cidXS4|3U1iFda$7B4juMlqthfs7ulm|iWqu>tNcx5o&*%Ag-U-+j^A zKm90zv%pq}>PVp^Ei^3H-kc7+qvXLJ7&$QA;f|5d97OOn+V(+wjyKu#0I{(I*|Fp! zHvf4;bzpqrEG$+*0>`ga2aP=9cA<+#t~I8@lI~hu0V&ea%RaKyRh3uouXHoJqw=F! z>RkU^OuWy}v*XC%9CQx9`z|E0ThQajbV!*t?b_m>o<5M8^v$a6&4ba#NCBCWjn1&I zkMi^H+nK6Her*=0$)^_1G_to}W*x=B*y(qb^-@Fi{TL`7qBQ;@*^t9epuci4jWq4% zR3iZ~shRn#hV}bv)U^zz_i5;i@?M^a8jxx&K0j8^ks+m96~VEBaj%fhSQWO7HvPFP zf&Dp3L#j7|v{TBYvz%$%{hg0$Gfn-Uoh+9m&^8JgOX~(22lEiVR)<`li;#J*qjtr% z{*nsK#9IHyjAU7@RSZlPDYIX~TYQo1S=Jl+&Y!?lN+uqDQ5vIUTII6gCOyoNx%&KW zzdFIiR|F<5nrf)@D}f=}YYXY#KhfqOza`GwDR}pMLVmrhU^!ASycS#PfvZMG!!=t3 zm0b;b-ANc2h)wLb(O|lz8Pi6!i10u-xIds?kGiJ`2|L+I>oNUIIteb~XOqCN0ra>>L=RTxlhB7h#d5*CL!Pelm6t@Cb=Td3i- zN{Mq%AfVt+z=-R`xG6-jKOLI`rKRH446Agk&v@XIz)#xAj8y67!*4)r#nNsE) zU&*N6My#%L81Z(=?qGHs23JpqZkWVleDziD#xZ#NC;L?@8E^eb@Ob&q0i8b{L)L9b zJ_d}yfxwcXoJL>Iz#H-EGuIn^<|>PCZiR~dZq3H;xs}#N%U@hXIWb68iVoN11UyMB` z$~3gr1MzU69mVji6cC;lVi$1I`e;)dcxuIGPFm{ilrA#idBzh;eH&5Df*04i4BeSE z{x$MW1mwg}&?fm>K$$mjUAdXHDmjCERG#OrjFOA7cnYBmX$(!NrcPUbA4wC&M zfy&u9MMpn=ryNT`FDKycQE?~_H*p3B@?`r;O!JjRf;sh8S??EE96o;c+&O;3adT{8 z;il?|?_ZYvrG}XZG2u^;jIZ*ya+6`&1jmeAtSm90^rS>6y0}dn%EwL#uoEeHzmG%% zvW!@dGY!v^a$Q6#z_9ZmjG#$2JVO-9H_5NwsO3vJjfgKgKUR3ONav4h>dr!wNLnwV zzYF&HN9Rfw_2Y|~w|zD_#6-zht)V)Kxb@d%?>28^X?TVINdHvLMh6jTXT#BoIKV7I z2;1kJEGy8yZ3(Y!%Vz|!KAB3=<}dU3_h-gUrZ~~9Sln?=j(r-oTTOjGNc?SqtcM zWE(H45Q>kvjPXF8Me=&ejd&q4aMT&RT}qg14cDk=?cQgtNRPb)7EsqN#Wvm(+i}?y z)-@un6$vmj?6hAUh-Yy%1__6V#)npg&Et>tR*K^2Q#7LLMd9jpn-yLxKX2c0HK3+3 zFvK@$;N8gTN}y4}TzSry$rq^#LQ}|S+}sh%essh_1vA(7XfeFU!Y`&-Ar@PSl81t& zea5W1<13qUy~lB01;&@>2NAQbRA_4UEufHQ)vWU7J3zfyU%*ccgCW`+5<)&ph~t8V7_8uxFY7d?l|kK@k78rIbqiG-F#~ z^NyQX{S(V_AHeWOSCp$>_Oj5MsZbSyO`Y3H1Y;#?Df~TEVL;e9^>OH^bN>X9-0RZEf&9{K_9Jyf-~!q*BZCWM4OqloVoKX z%so#j6;HhCw#`-DozJeQpKZI3taot(b5i;Fh7vGF?>ENLy0Ugyv{R>Z_cs#pDp({@ zHK}zRqLQbEkTZ>M-y*vG;QF zZ=WFk6yFx{j^dYdzeIQ;aoYk82CE}qD$l=PfXoslE^&Q?Dj7ElIuaija@Wz{>5azh zt}*5HCS5bl3@}15Xbx(m@9KHmSUwW2MHgX-Vf`Q=h@@HeY#xs4{m_6xILoQeq?v^awu!V}oQpdGYdWe7Fm8S8y3b~#G$a0j=X@za*3u?1b{=1=~rET!_ z;5wwm_^AHllJ&)I{{(Y(R7V1`*ZM|6Y1y<-_rx9|v^&KT9$FP5o(IYocbKbyCz1`l z7M7)N9#IK#ag03otVghGa^@LAfst}^O>;vE{6MNj)P#hD&J3HIIpbmXv=^E?Z=3?7 z-5HE1eD8{iene5X%D9Le*ZW_YHuiVLUwpDLt)oj23`xOi91SIZFaaiLg`6eXIbzdV zBqv3yK0TqxO;T%48Za-wO>kr2tTl0B+zjQ&DB}w(wSO-@E>1x81$R=K?5&3Tiqwo% z727j4zqL=e+{QKOHiNA(qpLnq%HnjcD*Z9P!lAkY9i7G}a^Y`}rEa!OBufy28-M~b`C zH{p-XuBw|Dp6L70!$7>@myYkT^m}2COMQgFVnH8wY*&u(r{4Ahqr_6vz|4^N;iPj%%>?%mM;xyFkb`{ti-Y$5RQ^9T;DQ$-5z)=Hkc? z$`xS4$*ZrH6`GB9evC2cd0(C|&L7HB%r9-U(%F_XW76hEy4Wp*e?qi?A;G_QZNzMc z4VY=}8!C)Kg-GwL$kO>G{fY=JCNf&gG8VDu$Hcm$A=%y@GS!*g3PSxp_!Wuj2kDyf z8=ZJQ4nLQ`T_GGD*FP(=)?41vQqBc&XsQo9)QdRT4(~}o+u0xJTKrE){BDN%YU3Qa zs0{MEN&*|i^%C2uY8twHc}M0U;r4k1Gs5!@67zz3&7dWBo@JIMLL8(bX2JMA(TKl{ zhBdpo7hZ>6Gi@c$q`$V4>d!>_i zx!&~5fvBsZXh+BCoMq|CbscoaJa(>->*g)mY?{bP$07aI>Yj1=pPUBhg#%{v3 zIn?;vc2^gT$`OP!_D-n(gvYSwPF{o`xVVHS?0KTG9dl-ggF2gwp-|4sxn#DKks*$PgkpA;c5HHcV!uLg8Tr3As6#7Irf5`tx@>FsO*IsK~N zB$YaH??2nF0xF$0Zao%G@0-&^Q2M`vygz|RhZ$QxIgyKK%l4A-(!vyk z`w@L0IGg5dmA#1x=XD6cS`?Ki$!Ud3>7t5#>H7)_xHMB_qm*!?w|_H+!_CyT_u?1rX908qh8!pe)N!}AY)-OaNNVB2J9z=cKklk5WL zEBzK%pV3F?fdl383XGpQb{de`zp%jj8o>sO@ig|w5hXOMG*Xi0rnK<-e{!l0;y9HORJW>vW|eCnX}FI zw1bV6+dxZiqqgMR^s58X7i|nWv>(cPz*c2Dw!-hT`NG^HOXCxMcfRN$M~$@JNk01p zet&a~*_1T?v8%jhBpg$lCc)shC_G{91JhZ?F5MJaYesNm+B{Y+Lh!I@Nh1N{^kVSO zv=R=jwkaxs{_G5534sjWnTRlA!+_2cYL)`9zB#dyCh5SK#ivK z#97d<(vg@YZgo7hM~f6+amXJ?Hq)$ literal 0 HcmV?d00001 diff --git a/ospabhost/frontend/public/favicon-16x16.png b/ospabhost/frontend/public/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..971d4124787092ce10f814efe5a975d19b229c25 GIT binary patch literal 455 zcmV;&0XY7NP)M)BYrn1;oCKgp%^`=LOxcpgIs(^XoECXTTzKu^q~lGIKTW)uq6ytN#v8noA#$`0+9`}w4pVrI+?|}f zpb?2MVmy5MsxvuvCQsyE6x)Ctu)EovHOI*|99}7T77GXsuX(q@467Y*mn*Wva|YGa z1DJq=^>@wG&MBVUf*BihQ8;xk-lATFL&_p&V-S<@?;R!I;{y8_vB5J%8FH`--vR3a z>UHE{12&u|FT+{XlY@^y4u*H&&JUbj!Z*;j(c5+ox2(xcZm5Id9R!OAhjG^3l@vby xY7qXakktz6fPyhTrex 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 literal 0 HcmV?d00001 diff --git a/ospabhost/frontend/public/me.jpg b/ospabhost/frontend/public/me.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69231949f5375ba9aa000874ef8d09d2fd58ec2a GIT binary patch literal 51854 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 literal 0 HcmV?d00001 diff --git a/ospabhost/frontend/public/site.webmanifest b/ospabhost/frontend/public/site.webmanifest new file mode 100644 index 0000000..45dc8a2 --- /dev/null +++ b/ospabhost/frontend/public/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/ospabhost/frontend/public/vite.svg b/ospabhost/frontend/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/ospabhost/frontend/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ospabhost/frontend/src/assets/logo.svg b/ospabhost/frontend/src/assets/logo.svg new file mode 100644 index 0000000..d5b8a04 --- /dev/null +++ b/ospabhost/frontend/src/assets/logo.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ospabhost/frontend/src/assets/react.svg b/ospabhost/frontend/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/ospabhost/frontend/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ospabhost/frontend/src/components/ServerConsole.tsx b/ospabhost/frontend/src/components/ServerConsole.tsx new file mode 100644 index 0000000..9d66cc4 --- /dev/null +++ b/ospabhost/frontend/src/components/ServerConsole.tsx @@ -0,0 +1,120 @@ +import React, { useEffect, useRef } from 'react'; +import { useParams } from 'react-router-dom'; +import { Terminal } from 'xterm'; +import 'xterm/css/xterm.css'; + +const ServerConsole: React.FC = () => { + const { id } = useParams(); + const termRef = useRef(null); + const wsRef = useRef(null); + const xtermRef = useRef(null); + const reconnectAttempts = useRef(0); + + // Логгер ошибок + const logError = (msg: string, err?: unknown) => { + console.error('[Console]', msg, err); + }; + + useEffect(() => { + let disposed = false; + if (!termRef.current) return; + let term: Terminal | null = null; + try { + term = new Terminal({ + rows: 24, + cols: 80, + fontSize: 16, + theme: { + background: '#18181b', + foreground: '#e5e7eb', + }, + cursorBlink: true, + }); + term.open(termRef.current); + xtermRef.current = term; + } catch (err) { + logError('Ошибка инициализации xterm', err); + return; + } + + // Resize обработка + const handleResize = () => { + try { + term?.resize( + Math.floor(termRef.current?.offsetWidth ? termRef.current.offsetWidth / 9 : 80), + Math.floor(termRef.current?.offsetHeight ? termRef.current.offsetHeight / 20 : 24) + ); + } catch (err) { + logError('Ошибка resize терминала', err); + } + }; + window.addEventListener('resize', handleResize); + setTimeout(handleResize, 100); + + // WebSocket с авто-подключением + const connectWS = () => { + if (disposed) return; + const ws = new WebSocket(`wss://ospab.host:5000/api/server/${id}/console`); + wsRef.current = ws; + + ws.onopen = () => { + reconnectAttempts.current = 0; + term?.write('\x1b[32mПодключено к серверу\x1b[0m\r\n'); + }; + ws.onmessage = (event) => { + try { + term?.write(event.data); + } catch (err) { + logError('Ошибка вывода данных в терминал', err); + } + }; + ws.onclose = (event) => { + logError('WebSocket закрыт', event); + term?.write('\r\n\x1b[31mОтключено от сервера\x1b[0m\r\n'); + // Авто-подключение (до 5 попыток) + if (!disposed && reconnectAttempts.current < 5) { + reconnectAttempts.current++; + setTimeout(connectWS, 1000 * reconnectAttempts.current); + } + }; + ws.onerror = (event) => { + logError('WebSocket ошибка', event); + term?.write('\r\n\x1b[31mОшибка соединения\x1b[0m\r\n'); + }; + + term?.onData((data: string) => { + try { + if (ws.readyState === WebSocket.OPEN) { + ws.send(data); + } + } catch (err) { + logError('Ошибка отправки данных по WebSocket', err); + } + }); + }; + connectWS(); + + return () => { + disposed = true; + try { + wsRef.current?.close(); + } catch (err) { + logError('Ошибка закрытия WebSocket', err); + } + try { + term?.dispose(); + } catch (err) { + logError('Ошибка dispose терминала', err); + } + window.removeEventListener('resize', handleResize); + }; + }, [id]); + + return ( +

+
+
+ ); +}; + +export default ServerConsole; diff --git a/ospabhost/frontend/src/components/dashboardtempl.tsx b/ospabhost/frontend/src/components/dashboardtempl.tsx index d8b4b25..171838a 100644 --- a/ospabhost/frontend/src/components/dashboardtempl.tsx +++ b/ospabhost/frontend/src/components/dashboardtempl.tsx @@ -10,7 +10,8 @@ const DashboardTempl: React.FC = ({ children }) => { return (
-
+
+
{children}
diff --git a/ospabhost/frontend/src/components/footer.tsx b/ospabhost/frontend/src/components/footer.tsx index 56c839c..dc000c8 100644 --- a/ospabhost/frontend/src/components/footer.tsx +++ b/ospabhost/frontend/src/components/footer.tsx @@ -1,4 +1,5 @@ import { Link } from 'react-router-dom'; +import logo from '../assets/logo.svg'; const Footer = () => { const currentYear = new Date().getFullYear(); @@ -9,6 +10,9 @@ const Footer = () => {
{/* About Section */}
+
+ Логотип +

О нас

ospab.host - это надежный хостинг для ваших проектов. Мы предлагаем высокую производительность и круглосуточную поддержку. diff --git a/ospabhost/frontend/src/components/header.tsx b/ospabhost/frontend/src/components/header.tsx index d6d7ba3..efa4f0a 100644 --- a/ospabhost/frontend/src/components/header.tsx +++ b/ospabhost/frontend/src/components/header.tsx @@ -1,5 +1,6 @@ import { Link } from 'react-router-dom'; import useAuth from '../context/useAuth'; +import logo from '../assets/logo.svg'; const Header = () => { const { isLoggedIn, logout } = useAuth(); @@ -9,10 +10,13 @@ const Header = () => { }; return ( -

+
-
- ospab.host +
+ + Логотип + ospab.host +
Тарифы diff --git a/ospabhost/frontend/src/components/pagetempl.tsx b/ospabhost/frontend/src/components/pagetempl.tsx index 7dd5eb3..58d4658 100644 --- a/ospabhost/frontend/src/components/pagetempl.tsx +++ b/ospabhost/frontend/src/components/pagetempl.tsx @@ -10,7 +10,7 @@ const PageTmpl: React.FC = ({ children }) => { return (
-
+
{children}