diff --git a/.env.mac-docker.example b/.env.mac-docker.example index 86d11875..6fe6204f 100644 --- a/.env.mac-docker.example +++ b/.env.mac-docker.example @@ -69,6 +69,13 @@ ADMIN_DEFAULT_USERS_JSON=[{"username":"admin","password":"dev-admin-123456","rol KAQUAN91_USER_ID= KAQUAN91_SECRET= +# 半自动履约默认使用 order_site 内置真实 Connector;只有选择 external 时才填写远程地址 +SEMI_AUTO_DEFAULT_CONNECTOR_MODE=embedded +SEMI_AUTO_CONNECTOR_BASE_URL= +SEMI_AUTO_CONNECTOR_API_KEY= +SEMI_AUTO_CONNECTOR_TIMEOUT_MS=15000 +SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY=dev-semi-auto-credential-encryption-key + # 快手行业电子凭证 KUASHOU_INDUSTRY_APP_KEY= KUASHOU_INDUSTRY_APP_SECRET= diff --git a/.env.server.example b/.env.server.example index 7f0c4de0..005e490c 100644 --- a/.env.server.example +++ b/.env.server.example @@ -134,6 +134,14 @@ CORS_ALLOWED_ORIGINS=https://order.khhao.com,https://worker.khhao.com KAQUAN91_USER_ID= KAQUAN91_SECRET= +# 半自动履约 Connector(虎牙登录/绑定/CK 注入票据) +# 默认使用 order_site 内置真实 Connector;只有切到 external 时才需要填写地址和密钥。 +SEMI_AUTO_CONNECTOR_BASE_URL= +SEMI_AUTO_CONNECTOR_API_KEY= +SEMI_AUTO_DEFAULT_CONNECTOR_MODE=embedded +SEMI_AUTO_CONNECTOR_TIMEOUT_MS=15000 +SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY=change-me-semi-auto-credential-encryption-key + # 快手行业电子凭证 KUASHOU_INDUSTRY_APP_KEY= KUASHOU_INDUSTRY_APP_SECRET= diff --git a/.gitignore b/.gitignore index fbac5312..c0e60876 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ send_code/ /.deploy-state artifacts/ +har/ diff --git a/.prettierignore b/.prettierignore index f41d57bf..347db5a9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,4 +5,5 @@ **/data **/package-lock.json **/.env* +**/services/semi-auto/huya-native/assets/fingerprint/*-min.js diff --git a/README.md b/README.md index c5bd35a6..07bcb60f 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,37 @@ cp .env.server.example .env | `ADMIN_SESSION_SECRET` | 后台登录态签名密钥 | | `ADMIN_DEFAULT_USERS_JSON` | 默认后台用户 | | `KAQUAN91_USER_ID` / `KAQUAN91_SECRET` | 91 卡券开放接口凭据 | +| `SEMI_AUTO_CONNECTOR_BASE_URL` | 可选的远程真实 Connector 基址;默认使用 order_site 内置实现 | +| `SEMI_AUTO_CONNECTOR_API_KEY` | 使用远程 Connector 时的内部鉴权密钥 | +| `SEMI_AUTO_DEFAULT_CONNECTOR_MODE` | 新任务默认 Connector:`embedded` / `external` / `mock`,默认 `embedded` | +| `SEMI_AUTO_CONNECTOR_TIMEOUT_MS` | Connector 请求超时,默认 15000 毫秒 | + +### 本地半自动履约测试 + +开发 Mock 只负责生成订单,登录、绑定、浏览器票据注入和完成确认都走真实流程。 +默认使用 order_site 内置真实 Connector,不需要启动 live-hub-py,也不需要配置外部地址。 +只有显式选择远程 Connector 时,才需要设置 `SEMI_AUTO_CONNECTOR_BASE_URL` 和 +`SEMI_AUTO_CONNECTOR_API_KEY`。 + +真实登录 / 绑定验证流程: + +1. 打开后台 `/admin/dev-mock`,Mock 范围选择“仅 Mock 订单(内置真实登录 / 绑定 / 注入)”。 +2. 生成测试单,打开客户链接,使用虎牙 App 扫码并确认登录。 +3. 页面创建绑定二维码,等待 Connector 识别角色,核对账号和区服后确认绑定。 +4. 打开后台“任务 → 半自动履约”,确认任务 Connector 显示“内置真实”,领取并生成浏览器注入票据。 +5. 扩展消费票据后完成履约,核对任务、履约、成本快照和财务确认。 + +只联调页面、不调用虎牙接口时,可在同一个表单选择“订单 + 登录绑定都 Mock”; +该模式使用 order_site 内置 Mock Connector。开发 Mock 路由在非开发环境返回 404。 + +半自动履约真实 PostgreSQL 集成测试需要独立库,避免写入生产 dump: + +```bash +cd apps/backend +DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/order_site_it npm run db:migrate +SEMI_AUTO_TASK_TEST_DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/order_site_it \ + npx tsx --test src/services/semi-auto/semi-auto-task.integration.test.ts +``` ## 运行数据 @@ -227,6 +258,7 @@ bash deploy/ubuntu-deploy.sh 生产入口示例: - 前端与领取页:`https://你的域名/` +- 客户半自动履约入口:`https://你的域名/c/<平台订单号>` - 健康检查:`https://你的域名/health` - API:`https://你的域名/api/v1/...` diff --git a/apps/backend/package.json b/apps/backend/package.json index 6220a827..99cf09cd 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "cleanup:dev-data": "tsx scripts/cleanup-dev-data.ts", - "build": "tsc -p tsconfig.build.json && rm -rf dist/db/migrations && mkdir -p dist/db && cp -R src/db/migrations dist/db/migrations && mkdir -p dist/services/platforms/pdd && cp src/services/platforms/pdd/pdd_anti.cjs dist/services/platforms/pdd/pdd_anti.cjs", + "build": "tsc -p tsconfig.build.json && rm -rf dist/db/migrations && mkdir -p dist/db && cp -R src/db/migrations dist/db/migrations && mkdir -p dist/services/platforms/pdd && cp src/services/platforms/pdd/pdd_anti.cjs dist/services/platforms/pdd/pdd_anti.cjs && rm -rf dist/services/semi-auto/huya-native/assets/fingerprint && mkdir -p dist/services/semi-auto/huya-native/assets && cp -R src/services/semi-auto/huya-native/assets/fingerprint dist/services/semi-auto/huya-native/assets/fingerprint", "db:migrate": "tsx src/db/migrate.ts", "db:migrate:create": "tsx scripts/create-migration.ts", "db:migrate:status": "tsx scripts/migration-status.ts", diff --git a/apps/backend/scripts/start-dev-container.sh b/apps/backend/scripts/start-dev-container.sh index 69990b1c..fa08c45d 100644 --- a/apps/backend/scripts/start-dev-container.sh +++ b/apps/backend/scripts/start-dev-container.sh @@ -1,5 +1,8 @@ #!/bin/sh set -eu -npm install --no-fund --no-audit +if [ ! -f node_modules/.package-lock.json ] \ + || [ package-lock.json -nt node_modules/.package-lock.json ]; then + npm install --no-fund --no-audit +fi exec npm run dev diff --git a/apps/backend/src/app.ts b/apps/backend/src/app.ts index 13b2d67c..0445e72e 100644 --- a/apps/backend/src/app.ts +++ b/apps/backend/src/app.ts @@ -7,6 +7,8 @@ import affiliateDashRouter from './routes/affiliate-dash.js' import orderServiceRouter from './routes/order-service.js' import filesRouter from './routes/files.js' import claimsRouter from './routes/claims.js' +import customerFulfillmentRouter from './routes/customer-fulfillment.js' +import devMockConnectorRouter from './routes/dev-mock-connector.js' import dcAuthRouter from './routes/dcauth.js' import douyinMashidaRouter from './routes/douyin-mashida.js' import kuaishouIndustryRouter from './routes/kuaishou-industry.js' @@ -14,6 +16,7 @@ import open91Router from './routes/open-91.js' import pddExtensionRouter from './routes/pdd-extension.js' import redeemRouter from './routes/redeem.js' import shortLinksRouter from './routes/short-links.js' +import semiAutoInjectionsRouter from './routes/semi-auto-injections.js' import workerRouter from './routes/worker.js' import { accessLogMiddleware } from './middleware/access-log.js' import { createCorsMiddleware } from './middleware/cors.js' @@ -52,6 +55,9 @@ export function createApp({ startupState, isShutdownStarted, config }: CreateApp ) app.use(express.urlencoded({ extended: true })) + // 本地开发用内置 Connector;生产环境由路由内部直接返回 404。 + app.use('/api/v1/dev-mock/connector', devMockConnectorRouter) + app.get('/health', (_req, res) => { res.json( buildSuccessPayload( @@ -112,6 +118,8 @@ export function createApp({ startupState, isShutdownStarted, config }: CreateApp app.use('/api/v1/open/kuaishou-industry', kuaishouIndustryRouter) app.use('/api/v1/redeem', redeemRouter) app.use('/api/v1/claim', claimsRouter) + app.use('/api/v1/customer-fulfillment', customerFulfillmentRouter) + app.use('/api/v1/semi-auto/injections', semiAutoInjectionsRouter) app.use('/api/v1/o', orderServiceRouter) app.use('/api/v1/pdd/extension', pddExtensionRouter) app.use('/api/v1/files', filesRouter) diff --git a/apps/backend/src/config/defaults.ts b/apps/backend/src/config/defaults.ts index a41d38fb..02154954 100644 --- a/apps/backend/src/config/defaults.ts +++ b/apps/backend/src/config/defaults.ts @@ -61,6 +61,19 @@ export function createDefaultRuntimeConfig(projectRoot: string): RuntimeConfig { tokenTtlHours: 0, }, + semiAuto: { + defaultConnectorMode: 'embedded', + connectorBaseUrl: '', + connectorApiKey: '', + connectorTimeoutMs: 15_000, + credentialEncryptionKey: '', + huya: { + bindActId: 9271, + outerActId: '17096', + roomPid: '1199650619883', + }, + }, + admin: { sessionSecret: '', // 后台:24h 空闲过期,登录后最多 7 天必须重新登录。 diff --git a/apps/backend/src/config/env-documentation.test.ts b/apps/backend/src/config/env-documentation.test.ts index 65a8dd84..15c3b361 100644 --- a/apps/backend/src/config/env-documentation.test.ts +++ b/apps/backend/src/config/env-documentation.test.ts @@ -21,7 +21,10 @@ const DEPLOYMENT_ONLY_ENV_NAMES = [ 'DB_BACKUP_OSS_PREFIX', 'KUASHOU_INDUSTRY_RATE_LIMIT_MAX', 'MINIO_API_PORT', + 'MINIO_API_PORT_NUMBER', + 'MINIO_BROWSER', 'MINIO_CONSOLE_PORT', + 'MINIO_CONSOLE_PORT_NUMBER', 'MINIO_ROOT_PASSWORD', 'MINIO_ROOT_USER', 'NPM_CONFIG_REGISTRY', diff --git a/apps/backend/src/config/env-overrides.ts b/apps/backend/src/config/env-overrides.ts index 6410c2df..9d5f1c2c 100644 --- a/apps/backend/src/config/env-overrides.ts +++ b/apps/backend/src/config/env-overrides.ts @@ -51,6 +51,14 @@ export const ENV_OVERRIDES: readonly EnvOverride[] = [ stringEnv('STORAGE_OSS_SECRET_ACCESS_KEY', ['storage', 'oss', 'secretAccessKey']), stringEnv('STORAGE_OSS_REGION', ['storage', 'oss', 'region']), integerEnv('CLAIM_TOKEN_TTL_HOURS', ['orders', 'tokenTtlHours']), + stringEnv('SEMI_AUTO_CONNECTOR_BASE_URL', ['semiAuto', 'connectorBaseUrl']), + stringEnv('SEMI_AUTO_CONNECTOR_API_KEY', ['semiAuto', 'connectorApiKey']), + integerEnv('SEMI_AUTO_CONNECTOR_TIMEOUT_MS', ['semiAuto', 'connectorTimeoutMs']), + stringEnv('SEMI_AUTO_DEFAULT_CONNECTOR_MODE', ['semiAuto', 'defaultConnectorMode']), + stringEnv('SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY', ['semiAuto', 'credentialEncryptionKey']), + integerEnv('HUYA_BIND_ACT_ID', ['semiAuto', 'huya', 'bindActId']), + stringEnv('HUYA_OUTER_ACT_ID', ['semiAuto', 'huya', 'outerActId']), + stringEnv('HUYA_ROOM_PID', ['semiAuto', 'huya', 'roomPid']), stringEnv('ADMIN_SESSION_SECRET', ['admin', 'sessionSecret']), // 兼容旧变量:固定 TTL 时代按“绝对上限”理解,空闲窗口仍用新默认值并被绝对上限钳制。 integerEnv('ADMIN_SESSION_TTL_HOURS', ['admin', 'sessionAbsoluteTtlHours']), diff --git a/apps/backend/src/config/runtime-validation.test.ts b/apps/backend/src/config/runtime-validation.test.ts index 6b06989b..361c517a 100644 --- a/apps/backend/src/config/runtime-validation.test.ts +++ b/apps/backend/src/config/runtime-validation.test.ts @@ -126,6 +126,38 @@ test('validateRuntimeConfig accepts zero claim token TTL for permanent links', ( assert.deepEqual(issues, []) }) +test('validateRuntimeConfig rejects unknown semi-auto connector mode', () => { + const issues = validateRuntimeConfig( + createRuntimeConfig({ + semiAuto: { + defaultConnectorMode: 'remote', + }, + }), + { env: { NODE_ENV: 'development' } }, + ) + + assert.deepEqual( + issues.map((issue) => issue.path), + ['semiAuto.defaultConnectorMode'], + ) +}) + +test('validateRuntimeConfig requires a strong semi-auto credential key in production', () => { + const issues = validateRuntimeConfig( + createRuntimeConfig({ + semiAuto: { + credentialEncryptionKey: 'short-key', + }, + }), + { env: { NODE_ENV: 'production' } }, + ) + + assert.deepEqual( + issues.map((issue) => issue.path), + ['semiAuto.credentialEncryptionKey'], + ) +}) + test('assertRuntimeConfigValid throws a readable validation error', () => { assert.throws( () => { @@ -187,6 +219,18 @@ function createRuntimeConfig(overrides: Record = {}): RuntimeCo claimBaseUrl: 'https://order.example.test/#/claim', tokenTtlHours: 24, }, + semiAuto: { + defaultConnectorMode: 'embedded', + connectorBaseUrl: '', + connectorApiKey: '', + connectorTimeoutMs: 15000, + credentialEncryptionKey: '0123456789abcdef0123456789abcdef', + huya: { + bindActId: 9271, + outerActId: '17096', + roomPid: '1199650619883', + }, + }, admin: { sessionSecret: '0123456789abcdef0123456789abcdef', sessionIdleTtlHours: 24, diff --git a/apps/backend/src/config/runtime-validation.ts b/apps/backend/src/config/runtime-validation.ts index 2688fb82..ec39e76c 100644 --- a/apps/backend/src/config/runtime-validation.ts +++ b/apps/backend/src/config/runtime-validation.ts @@ -77,6 +77,27 @@ export function validateRuntimeConfig( config.database?.slowQueryThresholdMs, { min: 0 }, ) + validateOptionalHttpUrl(issues, 'semiAuto.connectorBaseUrl', config.semiAuto?.connectorBaseUrl) + const connectorMode = String(config.semiAuto?.defaultConnectorMode || '').trim() + if (!['embedded', 'external', 'mock'].includes(connectorMode)) { + issues.push({ + path: 'semiAuto.defaultConnectorMode', + message: '仅支持 embedded、external 或 mock', + }) + } + const credentialEncryptionKey = String(config.semiAuto?.credentialEncryptionKey || '').trim() + if (!productionLike && credentialEncryptionKey && credentialEncryptionKey.length < 32) { + issues.push({ + path: 'semiAuto.credentialEncryptionKey', + message: '长度不能少于 32 个字符', + }) + } + requireOptionalInteger( + issues, + 'semiAuto.connectorTimeoutMs', + config.semiAuto?.connectorTimeoutMs, + { min: 1 }, + ) requireInteger(issues, 'storage.maxUploadSizeMb', config.storage?.maxUploadSizeMb, { min: 1, max: 100, @@ -120,6 +141,12 @@ export function validateRuntimeConfig( } validateRequiredHttpUrl(issues, 'orders.claimBaseUrl', config.orders?.claimBaseUrl) validateSecret(issues, 'admin.sessionSecret', config.admin?.sessionSecret, { minLength: 32 }) + validateSecret( + issues, + 'semiAuto.credentialEncryptionKey', + config.semiAuto?.credentialEncryptionKey, + { minLength: 32 }, + ) validateAdminDefaultUsers(issues, config.admin?.defaultUsers) const allowedOrigins = config.cors?.allowedOrigins if (Array.isArray(allowedOrigins)) { diff --git a/apps/backend/src/db/migrations/153_semi_auto_fulfillment.sql b/apps/backend/src/db/migrations/153_semi_auto_fulfillment.sql new file mode 100644 index 00000000..67b5270a --- /dev/null +++ b/apps/backend/src/db/migrations/153_semi_auto_fulfillment.sql @@ -0,0 +1,108 @@ +-- 153_semi_auto_fulfillment.sql +-- +-- 人工履约渠道下的半自动任务: +-- 1. 人工 SKU 配置可显式启用虎牙/微博等半自动平台; +-- 2. 半自动任务绑定订单项和正式履约,不另建接单平台工单; +-- 3. 登录、绑定、执行状态正交保存,客户链接只按订单号展示必要信息; +-- 4. CK 不进入 order_site;由外部 Connector 加密托管,任务只保存平台账号快照。 + +ALTER TABLE manual_fulfillment_configs + ADD COLUMN IF NOT EXISTS semi_auto_enabled BOOLEAN NOT NULL DEFAULT FALSE, + ADD COLUMN IF NOT EXISTS semi_auto_platform TEXT NOT NULL DEFAULT '', + ADD COLUMN IF NOT EXISTS semi_auto_config_json JSONB NOT NULL DEFAULT '{}'::jsonb; + +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint + WHERE conname = 'chk_manual_fulfillment_configs_semi_auto_platform' + ) THEN + ALTER TABLE manual_fulfillment_configs + ADD CONSTRAINT chk_manual_fulfillment_configs_semi_auto_platform + CHECK (semi_auto_platform IN ('', 'huya', 'weibo')); + END IF; +END $$; + +CREATE TABLE IF NOT EXISTS semi_auto_tasks ( + id BIGSERIAL PRIMARY KEY, + order_id BIGINT NOT NULL REFERENCES orders(id) ON DELETE CASCADE, + order_item_id BIGINT NOT NULL UNIQUE REFERENCES order_items(id) ON DELETE CASCADE, + fulfillment_id BIGINT REFERENCES fulfillments(id) ON DELETE SET NULL, + manual_fulfillment_config_id BIGINT + REFERENCES manual_fulfillment_configs(id) ON DELETE SET NULL, + platform TEXT NOT NULL CHECK (platform IN ('huya', 'weibo')), + login_status TEXT NOT NULL DEFAULT 'waiting_login' + CHECK (login_status IN ( + 'waiting_login', 'qr_pending', 'scanned', 'authenticated', 'failed', 'expired' + )), + binding_status TEXT NOT NULL DEFAULT 'not_started' + CHECK (binding_status IN ( + 'not_started', 'qr_pending', 'scanned', 'role_ready', 'confirmed', 'failed', 'expired' + )), + execution_status TEXT NOT NULL DEFAULT 'waiting_customer' + CHECK (execution_status IN ( + 'waiting_customer', 'waiting_operator', 'processing', 'completed', 'failed', 'cancelled' + )), + connector_session_id TEXT NOT NULL DEFAULT '', + huya_uid TEXT NOT NULL DEFAULT '', + platform_nickname TEXT NOT NULL DEFAULT '', + bind_game_account TEXT NOT NULL DEFAULT '', + bind_game_role TEXT NOT NULL DEFAULT '', + bind_game_channel TEXT NOT NULL DEFAULT '', + target_quantity INTEGER NOT NULL DEFAULT 1 CHECK (target_quantity > 0), + completed_quantity INTEGER NOT NULL DEFAULT 0 + CHECK (completed_quantity >= 0 AND completed_quantity <= target_quantity), + assigned_admin_user_id BIGINT REFERENCES admin_users(id) ON DELETE SET NULL, + customer_link_opened_at TIMESTAMPTZ, + auth_started_at TIMESTAMPTZ, + authenticated_at TIMESTAMPTZ, + binding_started_at TIMESTAMPTZ, + bound_at TIMESTAMPTZ, + completed_at TIMESTAMPTZ, + completion_note TEXT NOT NULL DEFAULT '', + external_order_no TEXT NOT NULL DEFAULT '', + completion_evidence_json JSONB NOT NULL DEFAULT '{}'::jsonb, + last_error TEXT NOT NULL DEFAULT '', + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_semi_auto_tasks_status + ON semi_auto_tasks (execution_status, platform, updated_at DESC, id DESC); +CREATE INDEX IF NOT EXISTS idx_semi_auto_tasks_order + ON semi_auto_tasks (order_id, id); +CREATE INDEX IF NOT EXISTS idx_semi_auto_tasks_operator + ON semi_auto_tasks (assigned_admin_user_id, execution_status, updated_at DESC) + WHERE assigned_admin_user_id IS NOT NULL; +CREATE INDEX IF NOT EXISTS idx_semi_auto_tasks_connector + ON semi_auto_tasks (connector_session_id) + WHERE connector_session_id <> ''; + +CREATE TABLE IF NOT EXISTS semi_auto_task_events ( + id BIGSERIAL PRIMARY KEY, + task_id BIGINT NOT NULL REFERENCES semi_auto_tasks(id) ON DELETE CASCADE, + event_type TEXT NOT NULL, + actor_type TEXT NOT NULL DEFAULT 'system' + CHECK (actor_type IN ('system', 'customer', 'admin', 'connector')), + actor_id TEXT NOT NULL DEFAULT '', + from_login_status TEXT, + to_login_status TEXT, + from_binding_status TEXT, + to_binding_status TEXT, + from_execution_status TEXT, + to_execution_status TEXT, + detail_json JSONB NOT NULL DEFAULT '{}'::jsonb, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_semi_auto_task_events_task + ON semi_auto_task_events (task_id, id DESC); + +COMMENT ON TABLE semi_auto_tasks IS + '人工履约渠道下的半自动任务;绑定订单项和正式履约,不承载平台 CK'; +COMMENT ON COLUMN semi_auto_tasks.connector_session_id IS + '外部平台 Connector 的短期登录/绑定会话 ID;CK 仅保存在 Connector 加密凭证域'; +COMMENT ON COLUMN semi_auto_tasks.completion_evidence_json IS + '可选交付证据(截图 object_key、备注、外部单号等),不得保存 Cookie 或令牌'; +COMMENT ON COLUMN manual_fulfillment_configs.semi_auto_config_json IS + '半自动履约展示与目标页配置;不得保存平台 CK 或运行时状态'; diff --git a/apps/backend/src/db/migrations/154_semi_auto_connector_mode.sql b/apps/backend/src/db/migrations/154_semi_auto_connector_mode.sql new file mode 100644 index 00000000..6930e067 --- /dev/null +++ b/apps/backend/src/db/migrations/154_semi_auto_connector_mode.sql @@ -0,0 +1,23 @@ +-- 154_semi_auto_connector_mode.sql +-- +-- 半自动任务记录登录/绑定/票据注入使用的 Connector 来源: +-- external:配置的远程 Connector,作为首版默认值; +-- mock:order_site 内置开发 Mock Connector,仅开发环境可用。 + +ALTER TABLE semi_auto_tasks + ADD COLUMN IF NOT EXISTS connector_mode TEXT NOT NULL DEFAULT 'external'; + +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint + WHERE conname = 'chk_semi_auto_tasks_connector_mode' + ) THEN + ALTER TABLE semi_auto_tasks + ADD CONSTRAINT chk_semi_auto_tasks_connector_mode + CHECK (connector_mode IN ('external', 'mock')); + END IF; +END $$; + +COMMENT ON COLUMN semi_auto_tasks.connector_mode IS + 'Connector 来源;external 为远程真实实现,mock 仅开发环境可用'; diff --git a/apps/backend/src/db/migrations/155_semi_auto_connector_mode_embedded.sql b/apps/backend/src/db/migrations/155_semi_auto_connector_mode_embedded.sql new file mode 100644 index 00000000..4367698f --- /dev/null +++ b/apps/backend/src/db/migrations/155_semi_auto_connector_mode_embedded.sql @@ -0,0 +1,25 @@ +-- 155_semi_auto_connector_mode_embedded.sql +-- +-- 内置真实 Connector 成为默认实现,不再依赖外部 live-hub-py 进程: +-- embedded:order_site 进程内真实虎牙 Connector,默认值; +-- external:显式配置的远程 Connector,保留用于隔离部署; +-- mock:order_site 内置开发 Mock Connector,仅开发环境可用。 + +ALTER TABLE semi_auto_tasks + ALTER COLUMN connector_mode SET DEFAULT 'embedded'; + +ALTER TABLE semi_auto_tasks + DROP CONSTRAINT IF EXISTS chk_semi_auto_tasks_connector_mode; + +-- 154 时代创建的存量任务均由远程 Connector 完成;切换到内置实现后仍需继续可操作。 +UPDATE semi_auto_tasks +SET connector_mode = 'embedded', + updated_at = NOW() +WHERE connector_mode = 'external'; + +ALTER TABLE semi_auto_tasks + ADD CONSTRAINT chk_semi_auto_tasks_connector_mode + CHECK (connector_mode IN ('embedded', 'external', 'mock')); + +COMMENT ON COLUMN semi_auto_tasks.connector_mode IS + 'Connector 来源;embedded 为内置真实实现,external 为远程实现,mock 仅开发环境可用'; diff --git a/apps/backend/src/db/migrations/156_semi_auto_credentials.sql b/apps/backend/src/db/migrations/156_semi_auto_credentials.sql new file mode 100644 index 00000000..4363583d --- /dev/null +++ b/apps/backend/src/db/migrations/156_semi_auto_credentials.sql @@ -0,0 +1,65 @@ +-- 156_semi_auto_credentials.sql +-- +-- 半自动履约平台账号凭证: +-- 1. CK 是账号级凭证,挂到平台 UID,而不是只保存在进程内存或单次任务上; +-- 2. 数据库只保存加密后的 Cookie 集合,任务仅引用 credential_id; +-- 3. 记录凭证来源、更新时间和健康状态,供执行器失效判定与人工重登使用。 + +CREATE TABLE IF NOT EXISTS semi_auto_credentials ( + id BIGSERIAL PRIMARY KEY, + platform TEXT NOT NULL CHECK (platform IN ('huya', 'weibo')), + platform_uid TEXT NOT NULL, + platform_nickname TEXT NOT NULL DEFAULT '', + credential_ciphertext TEXT NOT NULL, + credential_source TEXT NOT NULL DEFAULT '' + CHECK (credential_source IN ('', 'qr', 'sms', 'web', 'app', 'import')), + credential_status TEXT NOT NULL DEFAULT 'unknown' + CHECK (credential_status IN ('unknown', 'valid', 'invalid', 'error')), + credential_updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + last_checked_at TIMESTAMPTZ, + last_check_error TEXT NOT NULL DEFAULT '', + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (platform, platform_uid) +); + +ALTER TABLE semi_auto_tasks + ADD COLUMN IF NOT EXISTS credential_id BIGINT + REFERENCES semi_auto_credentials(id) ON DELETE SET NULL; + +CREATE INDEX IF NOT EXISTS idx_semi_auto_credentials_status + ON semi_auto_credentials (platform, credential_status, updated_at DESC); +CREATE INDEX IF NOT EXISTS idx_semi_auto_tasks_credential + ON semi_auto_tasks (credential_id) + WHERE credential_id IS NOT NULL; + +COMMENT ON TABLE semi_auto_credentials IS + '半自动履约平台账号级加密凭证;原始 CK 不得进入接口响应、日志或页面'; +COMMENT ON COLUMN semi_auto_credentials.credential_ciphertext IS + 'AES-256-GCM 加密后的 Cookie JSON;密钥来自 SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY'; +COMMENT ON COLUMN semi_auto_credentials.credential_source IS + '凭证来源:qr / sms / web / app / import'; +COMMENT ON COLUMN semi_auto_credentials.credential_status IS + '执行器最近一次检查结论:unknown / valid / invalid / error'; +COMMENT ON COLUMN semi_auto_tasks.credential_id IS + '该订单当前使用的平台账号凭证;task 不保存 CK 明文'; + +INSERT INTO admin_permissions ( + permission_key, permission_name, permission_group, description +) VALUES ( + 'semi_auto.credential.export', + '导出半自动履约账号 CK', + '半自动履约', + '受控导出单个半自动履约任务的账号级 Cookie;导出动作写入审计但不记录 CK' +) +ON CONFLICT (permission_key) DO UPDATE SET + permission_name = EXCLUDED.permission_name, + permission_group = EXCLUDED.permission_group, + description = EXCLUDED.description, + updated_at = NOW(); + +INSERT INTO admin_role_permissions (role_key, permission_key) +SELECT 'admin', 'semi_auto.credential.export' +FROM admin_roles +WHERE role_key = 'admin' +ON CONFLICT DO NOTHING; diff --git a/apps/backend/src/routes/admin.ts b/apps/backend/src/routes/admin.ts index e59ecb5a..fe90009e 100644 --- a/apps/backend/src/routes/admin.ts +++ b/apps/backend/src/routes/admin.ts @@ -16,6 +16,7 @@ import ordersRouter from './admin/orders.js' import notificationsRouter from './admin/notifications.js' import realtimeRouter from './admin/realtime.js' import rbacRouter from './admin/rbac.js' +import semiAutoRouter from './admin/semi-auto.js' import platformConfigRouter from './admin/platform-config.js' import { requireAdminSession } from './admin/session.js' import tasksRouter from './admin/tasks.js' @@ -36,6 +37,7 @@ router.use(fulfillmentChannelRouter) router.use(fundRouter) router.use(usersRouter) router.use(rbacRouter) +router.use(semiAutoRouter) router.use(auditLogsRouter) router.use(platformConfigRouter) router.use(kuaishouIndustryRouter) diff --git a/apps/backend/src/routes/admin/dev-mock.ts b/apps/backend/src/routes/admin/dev-mock.ts index 9fb3f979..ea4e9352 100644 --- a/apps/backend/src/routes/admin/dev-mock.ts +++ b/apps/backend/src/routes/admin/dev-mock.ts @@ -4,6 +4,7 @@ import { buildOpen91QueryMock, createAffiliateDashMockClaim, createKuaishouIndustryVoucherMockData, + createSemiAutoMock, getDevMockStatus, isDevMockEnabled, } from '../../services/dev-mock/dev-mock-service.js' @@ -75,6 +76,26 @@ router.post( }), ) +router.post( + '/dev-mock/semi-auto', + createJsonHandler((req) => createSemiAutoMock(req.body || {}), { + successMessage: '半自动履约 Mock 已生成', + errorMessage: '生成半自动履约 Mock 失败', + scope: '[admin/dev-mock/semi-auto]', + audit: (_req, data) => ({ + action: 'dev_mock_create_semi_auto', + targetType: 'dev_mock', + targetId: String((data as { orderNo?: string })?.orderNo || ''), + data: { + platform: 'semi_auto', + orderNo: (data as { orderNo?: string })?.orderNo, + skuKey: (data as { skuKey?: string })?.skuKey, + connectorMode: (data as { connectorMode?: string })?.connectorMode, + }, + }), + }), +) + router.post( '/dev-mock/open91/query', createJsonHandler((req) => buildOpen91QueryMock(req.body || {}), { diff --git a/apps/backend/src/routes/admin/semi-auto.ts b/apps/backend/src/routes/admin/semi-auto.ts new file mode 100644 index 00000000..51dccb47 --- /dev/null +++ b/apps/backend/src/routes/admin/semi-auto.ts @@ -0,0 +1,157 @@ +import { Router } from 'express' + +import { + cancelAdminSemiAutoTask, + claimAdminSemiAutoTask, + completeAdminSemiAutoTask, + consumeSemiAutoInjectionTicket, + createAdminBrowserSession, + exportAdminSemiAutoCredential, + getAdminSemiAutoTask, + listAdminSemiAutoTasks, + syncAdminSemiAutoTask, +} from '../../services/semi-auto/semi-auto-task-service.js' +import { bodyOf, sessionOf } from './request-helpers.js' +import { createJsonHandler, requireAdminPermission, requireAdminRoles } from './session.js' + +const router = Router() + +router.use('/semi-auto', requireAdminRoles(['admin', 'operator', 'support'])) + +router.get( + '/semi-auto/tasks', + createJsonHandler((req) => listAdminSemiAutoTasks(req.query as Record), { + successMessage: 'ok', + errorMessage: '读取半自动履约任务失败', + scope: '[admin/semi-auto/tasks]', + }), +) + +router.get( + '/semi-auto/tasks/:taskId', + createJsonHandler((req) => getAdminSemiAutoTask(req.params.taskId), { + successMessage: 'ok', + errorMessage: '读取半自动履约任务详情失败', + scope: '[admin/semi-auto/tasks/:taskId]', + }), +) + +router.post( + '/semi-auto/tasks/:taskId/credential/export', + requireAdminPermission('semi_auto.credential.export'), + createJsonHandler( + (req, res) => { + res.setHeader('Cache-Control', 'no-store, max-age=0') + res.setHeader('Pragma', 'no-cache') + res.setHeader('Expires', '0') + return exportAdminSemiAutoCredential(req.params.taskId, sessionOf(req)) + }, + { + successMessage: '账号 CK 已导出', + errorMessage: '导出半自动履约账号 CK 失败', + scope: '[admin/semi-auto/tasks/:taskId/credential/export]', + audit: (req, data) => { + const result = + data && typeof data === 'object' ? (data as Record) : undefined + return { + action: 'semi_auto_credential_exported', + targetType: 'semi_auto_task', + targetId: String(req.params.taskId || ''), + data: { + credentialId: Number(result?.credentialId || 0), + platform: String(result?.platform || ''), + }, + } + }, + }, + ), +) + +router.post( + '/semi-auto/tasks/:taskId/claim', + createJsonHandler((req) => claimAdminSemiAutoTask(req.params.taskId, sessionOf(req)), { + successMessage: '任务已领取', + errorMessage: '领取半自动履约任务失败', + scope: '[admin/semi-auto/tasks/:taskId/claim]', + audit: (req) => ({ + action: 'semi_auto_task_claimed', + targetType: 'semi_auto_task', + targetId: String(req.params.taskId || ''), + data: {}, + }), + }), +) + +router.post( + '/semi-auto/tasks/:taskId/sync', + createJsonHandler((req) => syncAdminSemiAutoTask(req.params.taskId), { + successMessage: '状态已刷新', + errorMessage: '刷新半自动履约状态失败', + scope: '[admin/semi-auto/tasks/:taskId/sync]', + }), +) + +router.post( + '/semi-auto/tasks/:taskId/browser-session', + createJsonHandler( + (req) => createAdminBrowserSession(req.params.taskId, bodyOf(req).targetUrl, sessionOf(req)), + { + successMessage: '注入票据已生成', + errorMessage: '生成浏览器登录态失败', + scope: '[admin/semi-auto/tasks/:taskId/browser-session]', + audit: (req) => ({ + action: 'semi_auto_browser_session_created', + targetType: 'semi_auto_task', + targetId: String(req.params.taskId || ''), + data: {}, + }), + }, + ), +) + +router.get( + '/semi-auto/injections/:ticket', + createJsonHandler((req) => consumeSemiAutoInjectionTicket(req.params.ticket), { + successMessage: 'ok', + errorMessage: '消费浏览器注入票据失败', + scope: '[admin/semi-auto/injections/:ticket]', + }), +) + +router.post( + '/semi-auto/tasks/:taskId/complete', + createJsonHandler( + (req) => completeAdminSemiAutoTask(req.params.taskId, bodyOf(req), sessionOf(req)), + { + successMessage: '半自动履约已完成', + errorMessage: '完成半自动履约失败', + scope: '[admin/semi-auto/tasks/:taskId/complete]', + audit: (req) => ({ + action: 'semi_auto_task_completed', + targetType: 'semi_auto_task', + targetId: String(req.params.taskId || ''), + data: {}, + }), + }, + ), +) + +router.post( + '/semi-auto/tasks/:taskId/cancel', + createJsonHandler( + (req) => cancelAdminSemiAutoTask(req.params.taskId, bodyOf(req), sessionOf(req)), + { + successMessage: '半自动履约任务已取消', + errorMessage: '取消半自动履约任务失败', + scope: '[admin/semi-auto/tasks/:taskId/cancel]', + audit: (req) => ({ + action: 'semi_auto_task_cancelled', + targetType: 'semi_auto_task', + targetId: String(req.params.taskId || ''), + data: {}, + }), + }, + ), +) + +export default router diff --git a/apps/backend/src/routes/customer-fulfillment.ts b/apps/backend/src/routes/customer-fulfillment.ts new file mode 100644 index 00000000..a9ac63b0 --- /dev/null +++ b/apps/backend/src/routes/customer-fulfillment.ts @@ -0,0 +1,163 @@ +import { Router } from 'express' + +import { + confirmPublicBinding, + getPublicWeiboCountryCodes, + listPublicSemiAutoTasks, + loginPublicWeiboSms, + markCustomerLinkOpened, + pollPublicBinding, + pollPublicLogin, + pollPublicWeiboQrLogin, + sendPublicWeiboSmsCode, + startPublicBinding, + startPublicLogin, + startPublicWeiboQrLogin, +} from '../services/semi-auto/semi-auto-task-service.js' +import { createRateLimitMiddleware, getParamRateLimitKey } from '../middleware/rate-limit.js' +import { createRouteHandler } from '../utils/http.js' + +const router = Router() + +const readLimit = createRateLimitMiddleware({ + scope: 'customer-fulfillment:read', + windowMs: 60_000, + max: 240, + key: getParamRateLimitKey('orderNo'), +}) +const writeLimit = createRateLimitMiddleware({ + scope: 'customer-fulfillment:write', + windowMs: 60_000, + max: 60, + key: getParamRateLimitKey('orderNo'), +}) + +router.get( + '/:orderNo', + readLimit, + createRouteHandler((req) => listPublicSemiAutoTasks(req.params.orderNo), { + errorMessage: '读取订单履约信息失败', + scope: '[customer-fulfillment/:orderNo]', + }), +) + +router.post( + '/:orderNo/tasks/:taskId/open', + writeLimit, + createRouteHandler((req) => markCustomerLinkOpened(req.params.orderNo, req.params.taskId), { + successMessage: 'ok', + errorMessage: '记录客户访问失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/open]', + }), +) + +router.post( + '/:orderNo/tasks/:taskId/login/start', + writeLimit, + createRouteHandler((req) => startPublicLogin(req.params.orderNo, req.params.taskId), { + successMessage: '登录会话已创建', + errorMessage: '开始平台登录失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/login/start]', + }), +) + +router.get( + '/:orderNo/tasks/:taskId/login/status', + readLimit, + createRouteHandler((req) => pollPublicLogin(req.params.orderNo, req.params.taskId), { + errorMessage: '刷新平台登录状态失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/login/status]', + }), +) + +router.post( + '/:orderNo/tasks/:taskId/binding/start', + writeLimit, + createRouteHandler((req) => startPublicBinding(req.params.orderNo, req.params.taskId, req.body), { + successMessage: '绑定会话已创建', + errorMessage: '开始账号绑定失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/binding/start]', + }), +) + +router.get( + '/:orderNo/tasks/:taskId/binding/status', + readLimit, + createRouteHandler((req) => pollPublicBinding(req.params.orderNo, req.params.taskId), { + errorMessage: '刷新账号绑定状态失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/binding/status]', + }), +) + +router.post( + '/:orderNo/tasks/:taskId/binding/confirm', + writeLimit, + createRouteHandler((req) => confirmPublicBinding(req.params.orderNo, req.params.taskId), { + successMessage: '绑定已确认', + errorMessage: '确认账号绑定失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/binding/confirm]', + }), +) + +router.get( + '/:orderNo/tasks/:taskId/weibo/config', + readLimit, + createRouteHandler((req) => getPublicWeiboCountryCodes(req.params.orderNo, req.params.taskId), { + errorMessage: '获取微博国家码列表失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/weibo/config]', + }), +) + +router.post( + '/:orderNo/tasks/:taskId/weibo/sms/send', + writeLimit, + createRouteHandler( + (req) => + sendPublicWeiboSmsCode( + req.params.orderNo, + req.params.taskId, + req.body?.mobile, + req.body?.countryCode, + req.body?.mfaId, + ), + { + successMessage: '验证码请求已处理', + errorMessage: '发送微博短信验证码失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/weibo/sms/send]', + }, + ), +) + +router.post( + '/:orderNo/tasks/:taskId/weibo/sms/login', + writeLimit, + createRouteHandler( + (req) => loginPublicWeiboSms(req.params.orderNo, req.params.taskId, req.body || {}), + { + successMessage: '微博登录成功', + errorMessage: '微博短信登录失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/weibo/sms/login]', + }, + ), +) + +router.get( + '/:orderNo/tasks/:taskId/weibo/qrcode', + writeLimit, + createRouteHandler((req) => startPublicWeiboQrLogin(req.params.orderNo, req.params.taskId), { + successMessage: '登录二维码已生成', + errorMessage: '获取微博登录二维码失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/weibo/qrcode]', + }), +) + +router.get( + '/:orderNo/tasks/:taskId/weibo/qrcode/status', + readLimit, + createRouteHandler((req) => pollPublicWeiboQrLogin(req.params.orderNo, req.params.taskId), { + errorMessage: '刷新微博扫码登录状态失败', + scope: '[customer-fulfillment/:orderNo/tasks/:taskId/weibo/qrcode/status]', + }), +) + +export default router diff --git a/apps/backend/src/routes/dev-mock-connector.ts b/apps/backend/src/routes/dev-mock-connector.ts new file mode 100644 index 00000000..ac520578 --- /dev/null +++ b/apps/backend/src/routes/dev-mock-connector.ts @@ -0,0 +1,141 @@ +import type { Request, Response } from 'express' +import { Router } from 'express' + +import { DEV_MOCK_CONNECTOR_API_KEY } from '../services/dev-mock/connector-endpoint.js' +import { isDevMockEnabled } from '../services/dev-mock/dev-mock-enabled.js' +import { + confirmMockBinding, + consumeMockBrowserTicket, + createMockBrowserTicket, + createMockLoginSession, + getMockBinding, + getMockLoginSession, + listMockSessions, + resetMockSessions, + revokeMockSession, + setMockBindingStatus, + setMockLoginStatus, + startMockBinding, +} from '../services/dev-mock/mock-semi-auto-connector.js' + +const router = Router() + +function bodyOf(req: Request): Record { + return req.body && typeof req.body === 'object' && !Array.isArray(req.body) + ? (req.body as Record) + : {} +} + +function sendDetail(res: Response, statusCode: number, detail: string) { + res.status(statusCode).json({ detail }) +} + +function handle(action: (req: Request) => unknown) { + return (req: Request, res: Response) => { + try { + res.json(action(req)) + } catch (error) { + const statusCode = + error && typeof error === 'object' && 'statusCode' in error + ? Number((error as { statusCode?: unknown }).statusCode) || 500 + : 500 + const detail = + error instanceof Error ? error.message : String(error || 'Mock Connector 请求失败') + sendDetail(res, statusCode, detail) + } + } +} + +router.use((req, res, next) => { + if (!isDevMockEnabled()) { + sendDetail(res, 404, '开发 Mock Connector 未启用') + return + } + const key = String(req.header('x-semi-auto-key') || '').trim() + if (!key || key !== DEV_MOCK_CONNECTOR_API_KEY) { + sendDetail(res, 401, '半自动履约 Connector 鉴权失败') + return + } + next() +}) + +router.post( + '/api/internal/huya-semi-auto/sessions', + handle((req) => { + const body = bodyOf(req) + return createMockLoginSession({ + taskId: body.task_id ?? body.taskId, + orderNo: body.order_no ?? body.orderNo, + }) + }), +) + +router.get( + '/api/internal/huya-semi-auto/sessions/:sessionId', + handle((req) => getMockLoginSession(req.params.sessionId)), +) + +router.delete( + '/api/internal/huya-semi-auto/sessions/:sessionId', + handle((req) => revokeMockSession(req.params.sessionId)), +) + +router.post( + '/api/internal/huya-semi-auto/sessions/:sessionId/binding', + handle((req) => startMockBinding(req.params.sessionId)), +) + +router.get( + '/api/internal/huya-semi-auto/sessions/:sessionId/binding', + handle((req) => getMockBinding(req.params.sessionId)), +) + +router.post( + '/api/internal/huya-semi-auto/sessions/:sessionId/binding/confirm', + handle((req) => confirmMockBinding(req.params.sessionId)), +) + +router.post( + '/api/internal/huya-semi-auto/sessions/:sessionId/browser-ticket', + handle((req) => { + const body = bodyOf(req) + return createMockBrowserTicket({ + sessionId: req.params.sessionId, + targetUrl: body.targetUrl, + }) + }), +) + +router.get( + '/api/internal/huya-semi-auto/browser-tickets/:ticket', + handle((req) => consumeMockBrowserTicket(req.params.ticket)), +) + +// 测试辅助:不经过轮询直接推进状态,方便验证失败、过期和异常分支。 +router.get( + '/__control/sessions', + handle(() => listMockSessions()), +) + +router.post( + '/__control/sessions/:sessionId/login', + handle((req) => { + const body = bodyOf(req) + return setMockLoginStatus(req.params.sessionId, body.status) + }), +) + +router.post( + '/__control/sessions/:sessionId/binding', + handle((req) => { + const body = bodyOf(req) + return setMockBindingStatus(req.params.sessionId, body.status) + }), +) + +router.post( + '/__control/reset', + handle(() => resetMockSessions()), +) + +export default router diff --git a/apps/backend/src/routes/semi-auto-injections.ts b/apps/backend/src/routes/semi-auto-injections.ts new file mode 100644 index 00000000..c94ab2c5 --- /dev/null +++ b/apps/backend/src/routes/semi-auto-injections.ts @@ -0,0 +1,23 @@ +import { Router } from 'express' + +import { consumeSemiAutoInjectionTicket } from '../services/semi-auto/semi-auto-task-service.js' +import { createRateLimitMiddleware } from '../middleware/rate-limit.js' +import { createRouteHandler } from '../utils/http.js' + +const router = Router() + +router.get( + '/:ticket', + createRateLimitMiddleware({ + scope: 'semi-auto-injection-consume', + windowMs: 60_000, + max: 30, + }), + createRouteHandler((req) => consumeSemiAutoInjectionTicket(req.params.ticket), { + successMessage: 'ok', + errorMessage: '消费浏览器注入票据失败', + scope: '[semi-auto-injections/:ticket]', + }), +) + +export default router diff --git a/apps/backend/src/services/admin/admin-rbac-service.ts b/apps/backend/src/services/admin/admin-rbac-service.ts index f286b21c..e520f356 100644 --- a/apps/backend/src/services/admin/admin-rbac-service.ts +++ b/apps/backend/src/services/admin/admin-rbac-service.ts @@ -35,6 +35,7 @@ export const ADMIN_PERMISSION_KEYS = [ 'consignment.manage', 'consignment.review', 'consignment.fulfill', + 'semi_auto.credential.export', ] as const export type AdminPermissionKey = (typeof ADMIN_PERMISSION_KEYS)[number] diff --git a/apps/backend/src/services/cost-center/manual-fulfillment-config-service.ts b/apps/backend/src/services/cost-center/manual-fulfillment-config-service.ts index dc4bdf72..be29c078 100644 --- a/apps/backend/src/services/cost-center/manual-fulfillment-config-service.ts +++ b/apps/backend/src/services/cost-center/manual-fulfillment-config-service.ts @@ -41,6 +41,8 @@ import { productSourceFilterSql } from './cost-center-mappers.js' export const MANUAL_PLATFORM_KEYS = ['nanhang', 'lewan', 'rock', 'fund_cash', 'on_account'] as const export type ManualPlatformKey = (typeof MANUAL_PLATFORM_KEYS)[number] +export const SEMI_AUTO_PLATFORM_KEYS = ['huya', 'weibo'] as const +export type SemiAutoPlatform = (typeof SEMI_AUTO_PLATFORM_KEYS)[number] /** * 积分换算率(分/积分),**按平台不同**: @@ -109,6 +111,9 @@ type ManualSkuRow = { config_canonical_product_id: number | null config_enabled: boolean | null config_channels_json: unknown + config_semi_auto_enabled: boolean | null + config_semi_auto_platform: string | null + config_semi_auto_config_json: unknown } type ManualChannelConfig = { @@ -344,7 +349,10 @@ export async function listManualSkus(input: Record = {}) { cfg.cost_mode AS config_cost_mode, COALESCE(cfg.canonical_product_id, p.id) AS config_canonical_product_id, cfg.enabled AS config_enabled, - cfg.channels_json AS config_channels_json + cfg.channels_json AS config_channels_json, + cfg.semi_auto_enabled AS config_semi_auto_enabled, + cfg.semi_auto_platform AS config_semi_auto_platform, + cfg.semi_auto_config_json AS config_semi_auto_config_json FROM product_catalog p JOIN internal_skus product_sku ON product_sku.id = p.internal_sku_id LEFT JOIN LATERAL ( @@ -458,6 +466,7 @@ export async function saveManualFulfillmentConfig(payload: JsonObject) { ) const enabled = payload.enabled === false ? false : true const note = optionalText(payload.note, 300) + const semiAuto = normalizeSemiAutoConfig(payload) // 消耗积分为 0 = 成本不固定,客服确认履约时手填。 const costMode = primaryChannel.costMode @@ -546,7 +555,11 @@ export async function saveManualFulfillmentConfig(payload: JsonObject) { `UPDATE manual_fulfillment_configs SET sku_key = $2, canonical_product_id = $3, platform_key = $4, credit_quantity = $5, cost_mode = $6, enabled = $7, note = $8, - channels_json = $9::jsonb, updated_at = $10 + channels_json = $9::jsonb, + semi_auto_enabled = $10, + semi_auto_platform = $11, + semi_auto_config_json = $12::jsonb, + updated_at = $13 WHERE id = $1 RETURNING *`, [ @@ -559,14 +572,22 @@ export async function saveManualFulfillmentConfig(payload: JsonObject) { enabled, note, JSON.stringify(channels), + semiAuto.enabled, + semiAuto.platform, + JSON.stringify(semiAuto.config), now, ], ) : await client.query( `INSERT INTO manual_fulfillment_configs ( sku_key, canonical_product_id, platform_key, credit_quantity, - cost_mode, enabled, note, channels_json, created_at, updated_at - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $9) + cost_mode, enabled, note, channels_json, + semi_auto_enabled, semi_auto_platform, semi_auto_config_json, + created_at, updated_at + ) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8::jsonb, + $9, $10, $11::jsonb, $12, $12 + ) RETURNING *`, [ skuKey, @@ -577,6 +598,9 @@ export async function saveManualFulfillmentConfig(payload: JsonObject) { enabled, note, JSON.stringify(channels), + semiAuto.enabled, + semiAuto.platform, + JSON.stringify(semiAuto.config), now, ], ) @@ -1046,6 +1070,9 @@ export async function getManualFulfillmentConfig(skuKey: string) { enabled: boolean note: string channels_json: unknown + semi_auto_enabled: boolean + semi_auto_platform: string + semi_auto_config_json: unknown created_at: string updated_at: string }>( @@ -1174,6 +1201,9 @@ function mapManualSku(row: ManualSkuRow, unitPrices: Record +} { + const enabled = payload.semiAutoEnabled === true || payload.semi_auto_enabled === true + const platform = String(payload.semiAutoPlatform ?? payload.semi_auto_platform ?? '') + .trim() + .toLowerCase() + if (!enabled) { + return { enabled: false, platform: '', config: {} } + } + if (!(SEMI_AUTO_PLATFORM_KEYS as readonly string[]).includes(platform)) { + throw createHttpError('半自动履约平台无效', { + statusCode: 400, + errorCode: 'manual_config_semi_auto_platform_invalid', + }) + } + const rawConfig = payload.semiAutoConfig ?? payload.semi_auto_config + const config = + rawConfig && typeof rawConfig === 'object' && !Array.isArray(rawConfig) + ? (rawConfig as Record) + : {} + return { + enabled: true, + platform: platform as SemiAutoPlatform, + config: { + pageTitle: String(config.pageTitle || '') + .trim() + .slice(0, 60), + pageDescription: String(config.pageDescription || '') + .trim() + .slice(0, 500), + loginInstructions: String(config.loginInstructions || '') + .trim() + .slice(0, 1000), + bindingInstructions: String(config.bindingInstructions || '') + .trim() + .slice(0, 1000), + browserTargets: Array.isArray(config.browserTargets) + ? config.browserTargets + .filter((item): item is Record => + Boolean(item && typeof item === 'object'), + ) + .slice(0, 10) + .map((item) => ({ + key: String(item.key || '') + .trim() + .slice(0, 40), + label: String(item.label || '') + .trim() + .slice(0, 60), + url: String(item.url || '') + .trim() + .slice(0, 1000), + })) + .filter((item) => item.key && item.url) + : [], + }, + } +} + +function normalizeStoredSemiAutoConfig(value: unknown): Record { + if (!value || typeof value !== 'object' || Array.isArray(value)) return {} + return value as Record +} + function normalizePlatformKey(value: unknown): ManualPlatformKey { const text = String(value || '').trim() if (!MANUAL_PLATFORM_KEYS.includes(text as ManualPlatformKey)) { diff --git a/apps/backend/src/services/dev-mock/connector-endpoint.ts b/apps/backend/src/services/dev-mock/connector-endpoint.ts new file mode 100644 index 00000000..ebaac9e4 --- /dev/null +++ b/apps/backend/src/services/dev-mock/connector-endpoint.ts @@ -0,0 +1,20 @@ +import { runtimeConfig } from '../../config/runtime.js' +import { createHttpError } from '../../utils/http.js' +import { isDevMockEnabled } from './dev-mock-enabled.js' + +export const DEV_MOCK_CONNECTOR_PATH = '/api/v1/dev-mock/connector' +export const DEV_MOCK_CONNECTOR_API_KEY = 'local-semi-auto-connector-key' + +export function devMockConnectorBaseUrl() { + const port = Math.trunc(Number(runtimeConfig.server.port || 3000)) + return `http://127.0.0.1:${port}${DEV_MOCK_CONNECTOR_PATH}` +} + +export function assertDevMockConnectorEnabled() { + if (!isDevMockEnabled()) { + throw createHttpError('内置 Mock Connector 仅在开发环境可用', { + statusCode: 503, + errorCode: 'dev_mock_connector_disabled', + }) + } +} diff --git a/apps/backend/src/services/dev-mock/dev-mock-enabled.ts b/apps/backend/src/services/dev-mock/dev-mock-enabled.ts new file mode 100644 index 00000000..8d7e0b31 --- /dev/null +++ b/apps/backend/src/services/dev-mock/dev-mock-enabled.ts @@ -0,0 +1,21 @@ +import { isProductionLike } from '../../config/runtime-validation.js' +import { createHttpError } from '../../utils/http.js' + +export function isDevMockEnabled(env: NodeJS.ProcessEnv = process.env): boolean { + const flag = String(env.ENABLE_DEV_MOCK || '') + .trim() + .toLowerCase() + if (flag === '1' || flag === 'true') { + return true + } + return !isProductionLike(env) +} + +export function assertDevMockEnabled() { + if (!isDevMockEnabled()) { + throw createHttpError('当前环境未开启开发 Mock(仅非 production 或 ENABLE_DEV_MOCK=1)', { + statusCode: 403, + errorCode: 'dev_mock_disabled', + }) + } +} diff --git a/apps/backend/src/services/dev-mock/dev-mock-service.ts b/apps/backend/src/services/dev-mock/dev-mock-service.ts index d3f08e21..8e22fc23 100644 --- a/apps/backend/src/services/dev-mock/dev-mock-service.ts +++ b/apps/backend/src/services/dev-mock/dev-mock-service.ts @@ -8,22 +8,37 @@ import { createOrder, findOrderByPlatformOrderId } from '../../repositories/orde import { replaceOrderItems } from '../../repositories/order-item-repo.js' import { createTask, updateTask } from '../../repositories/task-repo.js' import { upsertKuaishouIndustryVoucher } from '../../repositories/kuaishou-industry-voucher-repo.js' +import { query, withTransaction } from '../../db/client.js' import { getFulfillmentProfileByKey, upsertFulfillmentProfile, } from '../../repositories/fulfillment-profile-repo.js' import { buildOrderClaimUrl, createTaskClaimToken } from '../claim/claim-service.js' import { assertValidClaimUid, normalizeClaimUid } from '../claim/claim-identity.js' +import { saveManualFulfillmentConfig } from '../cost-center/manual-fulfillment-config-service.js' +import { + assignFulfillmentChannelsWithExecutor, + attachFulfillmentConfigurationsWithExecutor, +} from '../fulfillment/fulfillment-state-service.js' +import { containsCjk } from '../fulfillment/internal-sku-resolver.js' import { OPEN_91_PLATFORM, OPEN_91_PROVIDER, assertOpen91Config } from '../open-91/config.js' import { getKuaishouIndustrySourceConfig, listKuaishouIndustryShopConfigs, } from '../platforms/kuaishou-industry/source-config-service.js' -import { isProductionLike } from '../../config/runtime-validation.js' import { createHttpError } from '../../utils/http.js' import { nowIso } from '../../utils/time.js' import { randomId } from '../../utils/random.js' import { TASK_STATUS } from '../../domain/task-status.js' +import { ensureSemiAutoTasksForOrder } from '../semi-auto/semi-auto-task-service.js' +import { + defaultSemiAutoConnectorMode, + isExternalSemiAutoConnectorConfigured, + type SemiAutoConnectorMode, +} from '../semi-auto/huya-connector-client.js' +import { assertDevMockEnabled, isDevMockEnabled } from './dev-mock-enabled.js' + +export { assertDevMockEnabled, isDevMockEnabled } export type DevMockCreateResult = { platform: 'affiliate_dash' @@ -51,27 +66,21 @@ export type DevMockKuaishouIndustryVoucherResult = { }> } -export function isDevMockEnabled(env: NodeJS.ProcessEnv = process.env): boolean { - if (String(env.ENABLE_DEV_MOCK || '').trim() === '1') { - return true - } - if ( - String(env.ENABLE_DEV_MOCK || '') - .trim() - .toLowerCase() === 'true' - ) { - return true - } - return !isProductionLike(env) -} - -export function assertDevMockEnabled() { - if (!isDevMockEnabled()) { - throw createHttpError('当前环境未开启开发 Mock(仅非 production 或 ENABLE_DEV_MOCK=1)', { - statusCode: 403, - errorCode: 'dev_mock_disabled', - }) - } +export type DevMockSemiAutoResult = { + platform: 'semi_auto' + semiAutoPlatform: 'huya' | 'weibo' + orderId: number + orderNo: string + orderItemId: number + fulfillmentId: number + configId: number + taskId: number + skuKey: string + connectorMode: SemiAutoConnectorMode + connectorConfigured: boolean + customerPath: string + adminPath: string + tips: string[] } export function getDevMockStatus() { @@ -87,9 +96,22 @@ export function getDevMockStatus() { description: '本站 claim + mock 绑定二维码/提交发货(不调真实 affiliate-dash 平台)', steps: ['uid', 'bind', 'submitted', 'completed', 'failed'], }, + { + key: 'semi_auto', + name: '半自动履约', + description: + '创建人工渠道半自动测试单;可选择仅 Mock 订单,登录、绑定和票据注入走真实 Connector', + steps: ['create_order', 'login', 'binding', 'browser_ticket', 'complete'], + }, ] : [], defaultUid: '10001', + semiAuto: { + defaultConnectorMode: defaultSemiAutoConnectorMode(), + externalConnectorConfigured: isExternalSemiAutoConnectorConfigured(), + mockConnectorAvailable: enabled, + platform: 'huya', + }, } } @@ -284,9 +306,260 @@ export async function createAffiliateDashMockClaim( } /** - * 生成电子凭证列表测试数据,不调用快手接口。 - * 覆盖未使用、已核销、已销毁和发码失败等运营页面常见状态。 + * 生成半自动履约测试单:人工 SKU 配置、订单、履约和半自动任务都走真实领域服务。 + * 平台登录、绑定和浏览器票据按 connectorMode 选择真实 Connector 或内置 Mock。 */ +export async function createSemiAutoMock( + input: { + platform?: unknown + orderNo?: unknown + skuName?: unknown + quantity?: unknown + pageTitle?: unknown + pageDescription?: unknown + browserTargetUrl?: unknown + connectorMode?: unknown + } = {}, +): Promise { + assertDevMockEnabled() + + const platform = normalizeMockSemiAutoPlatform(input.platform) + const orderNo = String( + input.orderNo || `${platform === 'weibo' ? 'MOCKWB' : 'MOCKSA'}${Date.now()}`, + ).trim() + const skuKey = normalizeMockSemiAutoSku(input.skuName, platform) + const quantity = normalizeMockSemiAutoQuantity(input.quantity) + // 微博目前只支持内置 Connector,忽略其他模式,避免生成必然失败的测试单。 + const connectorMode = + platform === 'weibo' ? 'embedded' : normalizeMockSemiAutoConnectorMode(input.connectorMode) + const pageTitle = String( + input.pageTitle || (platform === 'weibo' ? '微博发帖授权测试' : '虎牙账号授权测试'), + ) + .trim() + .slice(0, 60) + const pageDescription = String( + input.pageDescription || + (platform === 'weibo' + ? '开发 Mock:完成微博登录即视为授权,客服在后台完成发帖履约。' + : '开发 Mock:完成登录和角色绑定后,客服在后台完成履约。'), + ) + .trim() + .slice(0, 500) + const browserTargetUrl = String( + input.browserTargetUrl || + (platform === 'weibo' ? 'https://weibo.com/' : 'https://www.huya.com/'), + ) + .trim() + .slice(0, 1000) + + await assertOrderNoAvailable(orderNo) + + const config = await saveManualFulfillmentConfig({ + skuKey, + enabled: true, + note: '开发 Mock 半自动履约', + channels: [{ platformKey: 'fund_cash', creditQuantity: 100, enabled: true }], + semiAutoEnabled: true, + semiAutoPlatform: platform, + semiAutoConfig: { + pageTitle, + pageDescription, + loginInstructions: + platform === 'weibo' + ? '真实登录:使用微博绑定手机号接收验证码登录,或使用微博 App 扫码登录。登录仅用于本次订单履约,不会在页面展示账号 Cookie。' + : connectorMode === 'mock' + ? 'Mock 登录:点击获取二维码后,页面轮询两次会自动模拟登录成功。' + : '真实登录:点击获取二维码后,请使用虎牙 App 扫码并在手机上确认登录。', + bindingInstructions: + platform === 'weibo' + ? '微博登录成功即完成授权,无需再绑定游戏角色。' + : connectorMode === 'mock' + ? 'Mock 绑定:页面轮询两次后会自动识别角色,点击确认即可。' + : '真实绑定:扫码后等待 Connector 识别角色,核对账号和区服后点击确认绑定。', + ...(platform === 'weibo' ? { loginMethods: ['sms', 'qr'] } : {}), + browserTargets: [ + { + key: platform, + label: platform === 'weibo' ? '微博' : '虎牙', + url: browserTargetUrl, + }, + ], + }, + }) + const configId = Number(config.id || 0) + const canonicalProductId = config.canonicalProductId ? Number(config.canonicalProductId) : null + if (!configId) { + throw createHttpError('半自动履约 Mock 配置创建失败', { + statusCode: 500, + errorCode: 'dev_mock_semi_auto_config_failed', + }) + } + + const now = nowIso() + const order = await createBaseOrder({ + orderNo, + productNo: skuKey, + productName: skuKey, + now, + platformTag: 'semi-auto', + totalAmount: 100 * quantity, + }) + const [orderItem] = await replaceOrderItems(order.id, [ + { + skuCode: skuKey, + skuName: skuKey, + quantity, + specJson: JSON.stringify({ + source: 'dev_mock', + skuNick: skuKey, + semiAuto: { platform, mock: true }, + }), + itemSnapshotJson: JSON.stringify({ + source: 'dev_mock', + skuKey, + platform, + mock: true, + }), + createdAt: now, + updatedAt: now, + }, + ]) + const orderItemId = Number(orderItem?.id || 0) + if (!orderItemId) { + throw createHttpError('半自动履约 Mock 订单项创建失败', { + statusCode: 500, + errorCode: 'dev_mock_semi_auto_item_failed', + }) + } + + const fulfillmentResult = await query<{ id: number }>( + 'SELECT id FROM fulfillments WHERE order_item_id = $1 LIMIT 1', + [orderItemId], + ) + const fulfillmentId = Number(fulfillmentResult.rows[0]?.id || 0) + if (!fulfillmentId) { + throw createHttpError('半自动履约 Mock 履约单创建失败', { + statusCode: 500, + errorCode: 'dev_mock_semi_auto_fulfillment_failed', + }) + } + + await withTransaction(async (client) => { + await assignFulfillmentChannelsWithExecutor(client, { + assignments: [{ orderItemId, channel: 'manual', source: 'manual_confirm' }], + eventType: 'dev_mock_semi_auto_channel_assigned', + reason: 'dev_mock', + actor: { type: 'system' }, + }) + await attachFulfillmentConfigurationsWithExecutor(client, { + mappings: [ + { + orderItemId, + configId, + ...(canonicalProductId ? { canonicalProductId } : {}), + }, + ], + expected: { status: 'assigned', channel: 'manual' }, + onlyWhenConfigNull: true, + }) + }) + + const ensured = await ensureSemiAutoTasksForOrder(orderNo) + let taskId = Number(ensured.createdIds[0] || 0) + if (!taskId) { + const existing = await query<{ id: number }>( + 'SELECT id FROM semi_auto_tasks WHERE order_item_id = $1 LIMIT 1', + [orderItemId], + ) + taskId = Number(existing.rows[0]?.id || 0) + } + if (!taskId) { + throw createHttpError('半自动履约 Mock 任务创建失败', { + statusCode: 500, + errorCode: 'dev_mock_semi_auto_task_failed', + }) + } + + await query('UPDATE semi_auto_tasks SET connector_mode = $2, updated_at = NOW() WHERE id = $1', [ + taskId, + connectorMode, + ]) + + const connectorConfigured = + connectorMode === 'external' ? isExternalSemiAutoConnectorConfigured() : true + return { + platform: 'semi_auto', + semiAutoPlatform: platform, + orderId: Number(order.id), + orderNo, + orderItemId, + fulfillmentId, + configId, + taskId, + skuKey, + connectorMode, + connectorConfigured, + customerPath: `/c/${encodeURIComponent(orderNo)}`, + adminPath: `/admin/semi-auto-tasks?keyword=${encodeURIComponent(orderNo)}`, + tips: + platform === 'weibo' + ? [ + '完成履约仍走真实确认流程,会写入成本快照和财务确认。', + '微博使用内置 Connector:短信验证码会真实发送到客户手机号;扫码登录需在微博 App 中确认。', + '后台领取任务后生成 weibo-ticket-* 浏览器票据,扩展消费票据后写入微博 Cookie。', + '微博登录成功即视为授权完成,任务会直接进入等待客服处理。', + ] + : [ + '完成履约仍走真实确认流程,会写入成本快照和财务确认。', + connectorMode === 'mock' + ? '当前使用内置 Mock Connector:打开客户页点击登录,轮询两次后自动登录;绑定同样自动识别角色。' + : connectorMode === 'external' + ? connectorConfigured + ? '当前使用远程真实 Connector:订单是 Mock 的,登录、绑定和浏览器票据都走外部服务。' + : '当前选择远程真实 Connector,但 SEMI_AUTO_CONNECTOR_BASE_URL / API_KEY 未配置,登录会失败。' + : '当前使用 order_site 内置真实 Connector:无需启动 live-hub-py,扫码登录、绑定和票据都在本进程完成。', + connectorMode === 'mock' + ? '后台领取任务后生成浏览器票据;扩展消费票据后写入 Mock Cookie。' + : connectorMode === 'external' + ? '请确保远程 Connector 已启动,并保证两边 SEMI_AUTO_CONNECTOR_API_KEY 一致。' + : '登录凭据只保存在当前进程内存中,重启后端会要求客户重新扫码。', + ], + } +} + +function normalizeMockSemiAutoPlatform(value: unknown): 'huya' | 'weibo' { + return String(value || '') + .trim() + .toLowerCase() === 'weibo' + ? 'weibo' + : 'huya' +} + +function normalizeMockSemiAutoConnectorMode(value: unknown): SemiAutoConnectorMode { + const mode = String(value || '') + .trim() + .toLowerCase() + if (mode === 'external' || mode === 'mock') return mode + return 'embedded' +} + +function normalizeMockSemiAutoSku(value: unknown, platform: 'huya' | 'weibo' = 'huya') { + const prefix = platform === 'weibo' ? '微博半自动' : '虎牙半自动' + const raw = String(value || '').trim() + const withCjk = raw + ? containsCjk(raw) + ? raw + : `${prefix}-${raw}` + : `${prefix}测试-${Date.now()}` + return withCjk.slice(0, 48) +} + +function normalizeMockSemiAutoQuantity(value: unknown) { + const parsed = Math.trunc(Number(value || 1)) + if (!Number.isFinite(parsed) || parsed < 1) return 1 + return Math.min(10, parsed) +} + export async function createKuaishouIndustryVoucherMockData( input: { sellerId?: unknown @@ -499,7 +772,9 @@ async function createBaseOrder(input: { productName: string now: string platformTag: string + totalAmount?: number }) { + const totalAmount = input.totalAmount ?? 100 const order = await createOrder({ provider: OPEN_91_PROVIDER, platform: OPEN_91_PLATFORM, @@ -511,7 +786,7 @@ async function createBaseOrder(input: { buyerId: 'mock-buyer', buyerName: 'mock 领取客户', receiverContact: '', - totalAmount: 100, + totalAmount, currency: 'CNY', rawPayloadJson: JSON.stringify({ source: OPEN_91_PROVIDER, @@ -523,7 +798,7 @@ async function createBaseOrder(input: { productNo: input.productNo, productName: input.productName, buyNum: 1, - maxAmount: '1.00', + maxAmount: (totalAmount / 100).toFixed(2), }, }), paidAt: input.now, diff --git a/apps/backend/src/services/dev-mock/mock-semi-auto-connector.test.ts b/apps/backend/src/services/dev-mock/mock-semi-auto-connector.test.ts new file mode 100644 index 00000000..1d656d81 --- /dev/null +++ b/apps/backend/src/services/dev-mock/mock-semi-auto-connector.test.ts @@ -0,0 +1,79 @@ +import assert from 'node:assert/strict' +import test from 'node:test' + +import { + confirmMockBinding, + consumeMockBrowserTicket, + createMockBrowserTicket, + createMockLoginSession, + getMockBinding, + getMockLoginSession, + resetMockSessions, + revokeMockSession, + setMockBindingStatus, + setMockLoginStatus, + startMockBinding, +} from './mock-semi-auto-connector.js' + +test.beforeEach(() => resetMockSessions()) + +test('Mock Connector 可按轮询自动完成登录、绑定和一次性票据消费', () => { + const created = createMockLoginSession({ taskId: 101, orderNo: 'MOCK-SA-1' }) + assert.equal(created.status, 'waiting_scan') + assert.equal(created.hasCredential, false) + assert.match(created.qrContent, /^mock-huya-login:\/\//) + + const scanned = getMockLoginSession(created.sessionId) + assert.equal(scanned.status, 'scanned') + assert.equal(scanned.hasCredential, false) + + const authenticated = getMockLoginSession(created.sessionId) + assert.equal(authenticated.status, 'authenticated') + assert.equal(authenticated.hasCredential, true) + assert.ok(authenticated.huyaUid) + + const binding = startMockBinding(created.sessionId) + assert.equal(binding.status, 'qr_pending') + assert.ok(binding.qrImage.startsWith('data:image/svg+xml;base64,')) + + assert.equal(getMockBinding(created.sessionId).status, 'scanned') + const roleReady = getMockBinding(created.sessionId) + assert.equal(roleReady.status, 'role_ready') + assert.ok(roleReady.bindGameRole) + + const confirmed = confirmMockBinding(created.sessionId) + assert.equal(confirmed.status, 'confirmed') + + const ticket = createMockBrowserTicket({ + sessionId: created.sessionId, + targetUrl: 'https://www.huya.com/mock', + }) + assert.equal(ticket.targetUrl, 'https://www.huya.com/mock') + + const payload = consumeMockBrowserTicket(ticket.ticket) + assert.equal(payload.platform, 'huya') + assert.ok(payload.cookies.length >= 1) + assert.equal(payload.cookies[0]?.domain, '.huya.com') + + assert.throws(() => consumeMockBrowserTicket(ticket.ticket), /已被消费/) +}) + +test('Mock Connector 支持控制状态、撤销会话和重置', () => { + const created = createMockLoginSession({ taskId: 202, orderNo: 'MOCK-SA-2' }) + + const authenticated = setMockLoginStatus(created.sessionId, 'authenticated') + assert.equal(authenticated.status, 'authenticated') + assert.equal(authenticated.hasCredential, true) + + const confirmed = setMockBindingStatus(created.sessionId, 'confirmed') + assert.equal(confirmed.status, 'confirmed') + assert.ok(confirmed.bindGameRole) + + revokeMockSession(created.sessionId) + assert.throws(() => getMockLoginSession(created.sessionId), /不存在或已失效/) + + const second = createMockLoginSession({ taskId: 203, orderNo: 'MOCK-SA-3' }) + const reset = resetMockSessions() + assert.equal(reset.cleared, 1) + assert.throws(() => getMockLoginSession(second.sessionId), /不存在或已失效/) +}) diff --git a/apps/backend/src/services/dev-mock/mock-semi-auto-connector.ts b/apps/backend/src/services/dev-mock/mock-semi-auto-connector.ts new file mode 100644 index 00000000..dd4d598b --- /dev/null +++ b/apps/backend/src/services/dev-mock/mock-semi-auto-connector.ts @@ -0,0 +1,405 @@ +/** + * 开发环境内置的半自动履约 Connector。 + * + * 只用于本地和测试环境:模拟虎牙登录、角色绑定、一次性浏览器注入票据, + * 不接触真实平台 Cookie。生产环境由 `isDevMockEnabled()` 拦截。 + */ +import crypto from 'node:crypto' + +import type { + ConnectorBindingSession, + ConnectorBrowserTicket, + ConnectorInjectionPayload, + ConnectorLoginSession, +} from '../semi-auto/huya-connector-client.js' +import { createHttpError } from '../../utils/http.js' + +const LOGIN_QR_TTL_MS = 5 * 60 * 1000 +const CREDENTIAL_TTL_MS = 24 * 60 * 60 * 1000 +const BINDING_QR_TTL_MS = 5 * 60 * 1000 +const BROWSER_TICKET_TTL_MS = 2 * 60 * 1000 + +type MockLoginStatus = ConnectorLoginSession['status'] +type MockBindingStatus = ConnectorBindingSession['status'] + +type MockTicket = { + ticket: string + targetUrl: string + expiresAtMs: number + consumed: boolean +} + +type MockSession = { + sessionId: string + taskId: number + orderNo: string + createdAtMs: number + loginStatus: MockLoginStatus + loginPolls: number + loginExpiresAtMs: number + credentialExpiresAtMs: number + qrContent: string + huyaUid: string + nickname: string + hasCredential: boolean + bindingStatus: MockBindingStatus + bindingPolls: number + bindingQrExpiresAtMs: number + bindGameAccount: string + bindGameRole: string + bindGameChannel: string + message: string + tickets: Map +} + +const sessions = new Map() + +function buildMockUid(sessionId: string) { + return `mock-huya-${sessionId.slice(-8)}` +} + +function buildMockBindingQr(sessionId: string) { + const svg = ` + + + + MOCK BIND + ${escapeXml(sessionId.slice(-12))} + 虎牙角色绑定测试二维码 + + `.trim() + return `data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}` +} + +function escapeXml(value: string) { + return value.replace(/[<>&'"]/g, (char) => { + const entities: Record = { + '<': '<', + '>': '>', + '&': '&', + "'": ''', + '"': '"', + } + return entities[char] || char + }) +} + +function requireSession(sessionIdInput: unknown): MockSession { + const sessionId = String(sessionIdInput || '').trim() + const session = sessions.get(sessionId) + if (!session) { + throw createHttpError('Mock Connector 会话不存在或已失效', { + statusCode: 404, + errorCode: 'mock_semi_auto_session_not_found', + }) + } + expireSessionIfNeeded(session) + return session +} + +function expireSessionIfNeeded(session: MockSession) { + const now = Date.now() + if (session.loginStatus === 'authenticated') { + if (session.credentialExpiresAtMs <= now) { + session.loginStatus = 'expired' + session.hasCredential = false + session.message = 'Mock 登录凭证已过期' + } + return + } + if (session.loginExpiresAtMs <= now && session.loginStatus !== 'expired') { + session.loginStatus = 'expired' + session.hasCredential = false + session.message = 'Mock 登录二维码已过期' + } +} + +function loginView(session: MockSession): ConnectorLoginSession { + return { + sessionId: session.sessionId, + status: session.loginStatus, + qrContent: session.qrContent, + expiresAt: new Date(session.loginExpiresAtMs).toISOString(), + huyaUid: session.huyaUid, + nickname: session.nickname, + hasCredential: session.hasCredential, + message: session.message, + } +} + +function bindingView(session: MockSession): ConnectorBindingSession { + return { + sessionId: session.sessionId, + status: session.bindingStatus, + qrImage: session.bindingStatus === 'not_started' ? '' : buildMockBindingQr(session.sessionId), + qrExpiresAt: new Date(session.bindingQrExpiresAtMs).toISOString(), + bindGameAccount: session.bindGameAccount, + bindGameRole: session.bindGameRole, + bindGameChannel: session.bindGameChannel, + message: session.message, + } +} + +function markAuthenticated(session: MockSession) { + session.loginStatus = 'authenticated' + session.hasCredential = true + session.huyaUid = buildMockUid(session.sessionId) + session.nickname = 'Mock虎牙用户' + session.credentialExpiresAtMs = Date.now() + CREDENTIAL_TTL_MS + session.message = 'Mock 登录成功' +} + +function markRoleReady(session: MockSession) { + session.bindingStatus = 'role_ready' + session.bindGameAccount = `mock-account-${session.sessionId.slice(-6)}` + session.bindGameRole = 'Mock测试角色' + session.bindGameChannel = '虎牙' + session.message = 'Mock 已识别游戏角色,请确认绑定' +} + +export function createMockLoginSession(input: { + taskId?: unknown + orderNo?: unknown +}): ConnectorLoginSession { + const sessionId = crypto.randomUUID() + const now = Date.now() + const session: MockSession = { + sessionId, + taskId: Number(input.taskId || 0), + orderNo: String(input.orderNo || '').trim(), + createdAtMs: now, + loginStatus: 'waiting_scan', + loginPolls: 0, + loginExpiresAtMs: now + LOGIN_QR_TTL_MS, + credentialExpiresAtMs: 0, + qrContent: `mock-huya-login://${sessionId}`, + huyaUid: '', + nickname: '', + hasCredential: false, + bindingStatus: 'not_started', + bindingPolls: 0, + bindingQrExpiresAtMs: 0, + bindGameAccount: '', + bindGameRole: '', + bindGameChannel: '', + message: 'Mock 登录二维码已生成,轮询后会自动模拟扫码成功', + tickets: new Map(), + } + sessions.set(sessionId, session) + return loginView(session) +} + +export function getMockLoginSession(sessionIdInput: unknown): ConnectorLoginSession { + const session = requireSession(sessionIdInput) + if (session.loginStatus === 'waiting_scan' || session.loginStatus === 'scanned') { + session.loginPolls += 1 + if (session.loginPolls >= 2) { + markAuthenticated(session) + } else if (session.loginPolls >= 1) { + session.loginStatus = 'scanned' + session.message = 'Mock 已扫码,等待确认登录' + } + } + return loginView(session) +} + +export function startMockBinding(sessionIdInput: unknown): ConnectorBindingSession { + const session = requireSession(sessionIdInput) + if (session.loginStatus !== 'authenticated') { + throw createHttpError('Mock 登录尚未完成,不能开始绑定', { + statusCode: 409, + errorCode: 'mock_semi_auto_login_required', + }) + } + const now = Date.now() + session.bindingStatus = 'qr_pending' + session.bindingPolls = 0 + session.bindingQrExpiresAtMs = now + BINDING_QR_TTL_MS + session.bindGameAccount = '' + session.bindGameRole = '' + session.bindGameChannel = '' + session.message = 'Mock 绑定二维码已生成,轮询后会自动识别角色' + return bindingView(session) +} + +export function getMockBinding(sessionIdInput: unknown): ConnectorBindingSession { + const session = requireSession(sessionIdInput) + if (session.bindingStatus === 'qr_pending' || session.bindingStatus === 'scanned') { + if (session.bindingQrExpiresAtMs <= Date.now()) { + session.bindingStatus = 'expired' + session.message = 'Mock 绑定二维码已过期' + return bindingView(session) + } + session.bindingPolls += 1 + if (session.bindingPolls >= 2) { + markRoleReady(session) + } else if (session.bindingPolls >= 1) { + session.bindingStatus = 'scanned' + session.message = 'Mock 已扫码,正在识别角色' + } + } + return bindingView(session) +} + +export function confirmMockBinding(sessionIdInput: unknown): ConnectorBindingSession { + const session = requireSession(sessionIdInput) + if (session.bindingStatus !== 'role_ready') { + throw createHttpError('Mock 角色尚未就绪,不能确认绑定', { + statusCode: 409, + errorCode: 'mock_semi_auto_binding_not_ready', + }) + } + session.bindingStatus = 'confirmed' + session.message = 'Mock 角色绑定已确认' + return bindingView(session) +} + +export function createMockBrowserTicket(input: { + sessionId?: unknown + targetUrl?: unknown +}): ConnectorBrowserTicket { + const session = requireSession(input.sessionId) + if (session.bindingStatus !== 'confirmed') { + throw createHttpError('Mock 角色尚未绑定,不能生成浏览器票据', { + statusCode: 409, + errorCode: 'mock_semi_auto_binding_required', + }) + } + const ticket = `mock-ticket-${crypto.randomUUID()}` + const targetUrl = String(input.targetUrl || 'https://www.huya.com/').trim() + const expiresAtMs = Date.now() + BROWSER_TICKET_TTL_MS + session.tickets.set(ticket, { ticket, targetUrl, expiresAtMs, consumed: false }) + return { + ticket, + expiresAt: new Date(expiresAtMs).toISOString(), + targetUrl, + } +} + +export function consumeMockBrowserTicket(ticketInput: unknown): ConnectorInjectionPayload { + const ticket = String(ticketInput || '').trim() + for (const session of sessions.values()) { + const item = session.tickets.get(ticket) + if (!item) continue + if (item.consumed) { + throw createHttpError('Mock 注入票据已被消费', { + statusCode: 410, + errorCode: 'mock_semi_auto_ticket_consumed', + }) + } + if (item.expiresAtMs <= Date.now()) { + throw createHttpError('Mock 注入票据已过期', { + statusCode: 410, + errorCode: 'mock_semi_auto_ticket_expired', + }) + } + item.consumed = true + return { + platform: 'huya', + targetUrl: item.targetUrl, + expiresAt: new Date(item.expiresAtMs).toISOString(), + cookies: [ + { + name: 'mock_huya_uid', + value: session.huyaUid || buildMockUid(session.sessionId), + domain: '.huya.com', + path: '/', + secure: true, + }, + { + name: 'mock_huya_session', + value: session.sessionId, + domain: '.huya.com', + path: '/', + secure: true, + }, + ], + } + } + throw createHttpError('Mock 注入票据不存在', { + statusCode: 404, + errorCode: 'mock_semi_auto_ticket_not_found', + }) +} + +export function revokeMockSession(sessionIdInput: unknown) { + const sessionId = String(sessionIdInput || '').trim() + sessions.delete(sessionId) + return { ok: true } +} + +export function setMockLoginStatus( + sessionIdInput: unknown, + statusInput: unknown, +): ConnectorLoginSession { + const session = requireSession(sessionIdInput) + const status = String(statusInput || '').trim() as MockLoginStatus + if (!['waiting_scan', 'scanned', 'authenticated', 'expired', 'failed'].includes(status)) { + throw createHttpError('Mock 登录状态无效', { + statusCode: 400, + errorCode: 'mock_semi_auto_login_status_invalid', + }) + } + session.loginStatus = status + if (status === 'authenticated') { + markAuthenticated(session) + } else { + session.hasCredential = false + session.message = `Mock 登录状态已切换为 ${status}` + } + return loginView(session) +} + +export function setMockBindingStatus( + sessionIdInput: unknown, + statusInput: unknown, +): ConnectorBindingSession { + const session = requireSession(sessionIdInput) + const status = String(statusInput || '').trim() as MockBindingStatus + if ( + ![ + 'not_started', + 'qr_pending', + 'scanned', + 'role_ready', + 'confirmed', + 'expired', + 'failed', + ].includes(status) + ) { + throw createHttpError('Mock 绑定状态无效', { + statusCode: 400, + errorCode: 'mock_semi_auto_binding_status_invalid', + }) + } + session.bindingStatus = status + if (status === 'role_ready' || status === 'confirmed') { + if (!session.bindGameRole) markRoleReady(session) + session.bindingStatus = status + } else { + session.bindGameAccount = '' + session.bindGameRole = '' + session.bindGameChannel = '' + } + session.message = `Mock 绑定状态已切换为 ${status}` + return bindingView(session) +} + +export function listMockSessions() { + return [...sessions.values()].map((session) => ({ + sessionId: session.sessionId, + taskId: session.taskId, + orderNo: session.orderNo, + loginStatus: session.loginStatus, + bindingStatus: session.bindingStatus, + hasCredential: session.hasCredential, + ticketCount: session.tickets.size, + createdAt: new Date(session.createdAtMs).toISOString(), + })) +} + +export function resetMockSessions() { + const count = sessions.size + sessions.clear() + return { cleared: count } +} diff --git a/apps/backend/src/services/finance/manual-fulfillment-integrity.test.ts b/apps/backend/src/services/finance/manual-fulfillment-integrity.test.ts index 3bfffe4b..7696577d 100644 --- a/apps/backend/src/services/finance/manual-fulfillment-integrity.test.ts +++ b/apps/backend/src/services/finance/manual-fulfillment-integrity.test.ts @@ -66,10 +66,19 @@ test('人工确认必须单事务:扣款与快照同事务,且使用 with-cl const end = source.indexOf('async function resolveFundAccountId') const body = source.slice(start, end) - assert.ok(body.includes('withTransaction('), '人工确认必须包在事务里') + const executeStart = body.indexOf('const execute = async (client: PoolClient)') + const executeEnd = body.indexOf('const result = options.client', executeStart) + const transactionalBody = body.slice(executeStart, executeEnd) + assert.ok(executeStart >= 0 && executeEnd > executeStart, '人工确认必须抽出事务执行体') assert.ok( - body.indexOf('withTransaction(') < body.indexOf('writeFundExpense(client'), - '备用金扣款必须在同一事务内执行', + body.includes( + 'options.client ? await execute(options.client) : await withTransaction(execute)', + ), + '默认路径必须包在事务里,外部事务必须复用调用方 client', + ) + assert.ok( + transactionalBody.includes('writeFundExpense(client'), + '备用金扣款必须在调用方事务内执行', ) assert.ok( body.includes('consumePlatformCreditWithClient(client'), diff --git a/apps/backend/src/services/finance/manual-fulfillment-service.ts b/apps/backend/src/services/finance/manual-fulfillment-service.ts index da462153..ce11b8fe 100644 --- a/apps/backend/src/services/finance/manual-fulfillment-service.ts +++ b/apps/backend/src/services/finance/manual-fulfillment-service.ts @@ -65,10 +65,13 @@ type ManualConfiguredChannel = { enabled: boolean } -async function loadManualPlatformUnitPrices(): Promise> { - const result = await query<{ profile_key: string; config_json: Record }>( - `SELECT profile_key, config_json FROM fulfillment_profiles WHERE profile_key LIKE 'manual_%'`, - ) +async function loadManualPlatformUnitPrices( + client?: Pick, +): Promise> { + const sql = `SELECT profile_key, config_json FROM fulfillment_profiles WHERE profile_key LIKE 'manual_%'` + const result = client + ? await client.query<{ profile_key: string; config_json: Record }>(sql) + : await query<{ profile_key: string; config_json: Record }>(sql) const prices: Record = { nanhang: 1, lewan: 1, @@ -299,17 +302,26 @@ export async function listManualFulfillmentPending( * 固定成本(消耗积分 > 0):直接用配置值,零输入。 * 成本不固定(消耗积分 = 0):客服必须填实际成本金额。 */ -export async function confirmManualFulfillment(payload: JsonObject, session: AdminSession) { +export type ConfirmManualFulfillmentOptions = { + /** 由调用方提供事务连接;此时调用方负责提交/回滚和提交后的报表刷新。 */ + client?: PoolClient +} + +export async function confirmManualFulfillment( + payload: JsonObject, + session: AdminSession, + options: ConfirmManualFulfillmentOptions = {}, +) { const orderItemId = normalizeRequiredId( payload.orderItemId ?? payload.order_item_id, '请选择订单项', ) - const now = nowIso() - const platformUnitPrices = await loadManualPlatformUnitPrices() // 钱与成本必须同一事务:先锁订单项、复查未履约,再扣款、最后写快照。 // 任何一步失败(余额不足、成本版本缺失、重复快照)都整体回滚,不会留下「扣了钱没记成本」。 - const result = await withTransaction(async (client) => { + const execute = async (client: PoolClient) => { + const now = nowIso() + const platformUnitPrices = await loadManualPlatformUnitPrices(client) // 配置可能晚于订单创建:确认前按 SKU 再匹配一次(与定时 rematch 同口径), // 保证「配置好之后的新单」不需要人工再点一次「重新匹配」。 await matchManualFulfillmentConfigWithClient(client, orderItemId) @@ -716,14 +728,26 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm onAccountBillId, costPending: onAccountCostPending, } - }) + } - await scheduleVoucherConsumeForOrderItems([orderItemId], 'order_received').catch(() => undefined) - // 成本已落快照,立刻重算该业务日的事实与总账;失败不阻断确认(定时任务会兜底)。 - await refreshFactsForOrderItem(orderItemId) + const result = options.client ? await execute(options.client) : await withTransaction(execute) + if (!options.client) { + await runManualFulfillmentPostCommit(orderItemId) + } return result } +/** + * 成本事务提交后的非关键旁路动作。 + * + * 调用方若把 confirmManualFulfillment 纳入更大的事务,必须在提交后显式调用本函数。 + * 这里的失败只影响报表时效,不反写已经提交的成本事实。 + */ +export async function runManualFulfillmentPostCommit(orderItemId: number): Promise { + await scheduleVoucherConsumeForOrderItems([orderItemId], 'order_received').catch(() => undefined) + await refreshFactsForOrderItem(orderItemId) +} + /** * 人工确认后按「订单业务日期」重算销售事实与总账。 * diff --git a/apps/backend/src/services/fulfillment/carrier-creation-service.ts b/apps/backend/src/services/fulfillment/carrier-creation-service.ts index bc1a790e..c188636b 100644 --- a/apps/backend/src/services/fulfillment/carrier-creation-service.ts +++ b/apps/backend/src/services/fulfillment/carrier-creation-service.ts @@ -191,8 +191,13 @@ export async function ensureCarrierForOrderItem(input: { } if (channel === 'manual') { - const config = await query<{ id: number; canonical_product_id: number | null }>( - `SELECT id, canonical_product_id + const config = await query<{ + id: number + canonical_product_id: number | null + semi_auto_enabled: boolean + semi_auto_platform: string + }>( + `SELECT id, canonical_product_id, semi_auto_enabled, semi_auto_platform FROM manual_fulfillment_configs WHERE canonicalize_internal_sku(sku_key) = resolve_internal_sku($1, $2, $3) AND enabled = TRUE @@ -213,6 +218,14 @@ export async function ensureCarrierForOrderItem(input: { ], onlyWhenCanonicalProductNull: true, }) + if ( + row.semi_auto_enabled === true && + ['huya', 'weibo'].includes(String(row.semi_auto_platform || '')) + ) { + const { ensureSemiAutoTasksForOrder } = + await import('../semi-auto/semi-auto-task-service.js') + await ensureSemiAutoTasksForOrder(order.platform_order_id) + } return { ready: true, created: false, reason: 'manual_config_ready', message: '' } } return { diff --git a/apps/backend/src/services/semi-auto/huya-connector-client.test.ts b/apps/backend/src/services/semi-auto/huya-connector-client.test.ts new file mode 100644 index 00000000..4bc68322 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-connector-client.test.ts @@ -0,0 +1,73 @@ +import assert from 'node:assert/strict' +import test from 'node:test' + +process.env.SEMI_AUTO_CONNECTOR_BASE_URL = 'http://connector.test' +process.env.SEMI_AUTO_CONNECTOR_API_KEY = 'test-key' + +const connector = await import('./huya-connector-client.js') + +test('浏览器注入票据按 Mock 前缀选择 Connector', () => { + assert.equal(connector.inferSemiAutoConnectorModeFromTicket('mock-ticket-0123456789'), 'mock') + assert.equal( + connector.inferSemiAutoConnectorModeFromTicket('native-ticket-0123456789'), + 'embedded', + ) + assert.equal(connector.inferSemiAutoConnectorModeFromTicket('real-ticket-0123456789'), 'external') +}) + +test('创建登录会话按真实 Connector 协议发送蛇形字段', async () => { + const originalFetch = globalThis.fetch + let requestUrl = '' + let requestBody: Record = {} + globalThis.fetch = (async (url: string | URL | Request, init?: RequestInit) => { + requestUrl = String(url) + requestBody = JSON.parse(String(init?.body || '{}')) as Record + return new Response( + JSON.stringify({ + sessionId: 'session-1', + status: 'waiting_scan', + qrContent: 'https://example.com/qr', + expiresAt: '2026-11-09T00:00:00Z', + huyaUid: '', + nickname: '', + hasCredential: false, + message: '等待扫码', + }), + { status: 200, headers: { 'Content-Type': 'application/json' } }, + ) + }) as typeof fetch + try { + await connector.createHuyaLoginSession({ taskId: 123, orderNo: 'ORDER-1' }, 'external') + assert.equal(requestUrl, 'http://connector.test/api/internal/huya-semi-auto/sessions') + assert.deepEqual(requestBody, { task_id: 123, order_no: 'ORDER-1' }) + } finally { + globalThis.fetch = originalFetch + } +}) + +test('重新扫码换绑会向 Connector 传递 force_rebind', async () => { + const originalFetch = globalThis.fetch + let requestBody: Record = {} + globalThis.fetch = (async (_url: string | URL | Request, init?: RequestInit) => { + requestBody = JSON.parse(String(init?.body || '{}')) as Record + return new Response( + JSON.stringify({ + sessionId: 'session-1', + status: 'qr_pending', + qrImage: 'data:image/png;base64,AA==', + qrExpiresAt: '2026-11-09T00:00:00Z', + bindGameAccount: '', + bindGameRole: '', + bindGameChannel: '', + message: '请扫码换绑', + }), + { status: 200, headers: { 'Content-Type': 'application/json' } }, + ) + }) as typeof fetch + try { + await connector.startHuyaBinding('session-1', 'external', { forceRebind: true }) + assert.deepEqual(requestBody, { force_rebind: true }) + } finally { + globalThis.fetch = originalFetch + } +}) diff --git a/apps/backend/src/services/semi-auto/huya-connector-client.ts b/apps/backend/src/services/semi-auto/huya-connector-client.ts new file mode 100644 index 00000000..cdf5ea30 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-connector-client.ts @@ -0,0 +1,310 @@ +import { runtimeConfig } from '../../config/runtime.js' +import { createHttpError } from '../../utils/http.js' +import { + assertDevMockConnectorEnabled, + DEV_MOCK_CONNECTOR_API_KEY, + devMockConnectorBaseUrl, +} from '../dev-mock/connector-endpoint.js' +import { isDevMockEnabled } from '../dev-mock/dev-mock-enabled.js' +import { + HUYA_NATIVE_TICKET_PREFIX, + huyaNativeConnector, +} from './huya-native/huya-native-connector.js' + +export type ConnectorLoginSession = { + sessionId: string + status: 'waiting_scan' | 'scanned' | 'authenticated' | 'expired' | 'failed' + qrContent: string + qrImage?: string + expiresAt: string + huyaUid: string + nickname: string + hasCredential: boolean + message: string +} + +export type ConnectorBindingSession = { + sessionId: string + status: + | 'not_started' + | 'qr_pending' + | 'scanned' + | 'role_ready' + | 'confirmed' + | 'expired' + | 'failed' + qrImage: string + qrExpiresAt: string + bindGameAccount: string + bindGameRole: string + bindGameChannel: string + hasExistingBinding?: boolean + rebindRequested?: boolean + message: string +} + +export type ConnectorBrowserTicket = { + ticket: string + expiresAt: string + targetUrl: string +} + +export type ConnectorInjectionPayload = { + platform: 'huya' | 'weibo' + targetUrl: string + expiresAt: string + cookies: Array<{ + name: string + value: string + domain: string + path: string + secure: boolean + }> +} + +type ConnectorRequestOptions = { + method?: 'GET' | 'POST' | 'DELETE' + body?: unknown +} + +export type SemiAutoConnectorMode = 'embedded' | 'external' | 'mock' + +type RemoteConnectorMode = Exclude + +type ConnectorEndpoint = { + baseUrl: string + apiKey: string +} + +function externalConnectorBaseUrl() { + return String(runtimeConfig.semiAuto?.connectorBaseUrl || '') + .trim() + .replace(/\/+$/, '') +} + +function externalConnectorApiKey() { + return String(runtimeConfig.semiAuto?.connectorApiKey || '').trim() +} + +export function isExternalSemiAutoConnectorConfigured() { + return Boolean(externalConnectorBaseUrl() && externalConnectorApiKey()) +} + +export function getSemiAutoConnectorStatus() { + return { + defaultConnectorMode: runtimeConfig.semiAuto?.defaultConnectorMode || ('embedded' as const), + embeddedConnectorAvailable: true, + externalConnectorConfigured: isExternalSemiAutoConnectorConfigured(), + mockConnectorAvailable: isDevMockEnabled(), + } +} + +export function defaultSemiAutoConnectorMode(): SemiAutoConnectorMode { + const mode = String(runtimeConfig.semiAuto?.defaultConnectorMode || 'embedded').trim() + return mode === 'external' || mode === 'mock' ? mode : 'embedded' +} + +function resolveConnectorEndpoint(mode: RemoteConnectorMode): ConnectorEndpoint { + if (mode === 'mock') { + assertDevMockConnectorEnabled() + return { + baseUrl: devMockConnectorBaseUrl(), + apiKey: DEV_MOCK_CONNECTOR_API_KEY, + } + } + const baseUrl = externalConnectorBaseUrl() + const apiKey = externalConnectorApiKey() + if (!baseUrl || !apiKey) { + throw createHttpError('半自动履约 Connector 尚未配置', { + statusCode: 503, + errorCode: 'semi_auto_connector_not_configured', + }) + } + return { baseUrl, apiKey } +} + +async function callConnector( + path: string, + options: ConnectorRequestOptions = {}, + mode: RemoteConnectorMode = 'external', +): Promise { + const endpoint = resolveConnectorEndpoint(mode) + + const timeoutMs = Math.max(1000, Number(runtimeConfig.semiAuto?.connectorTimeoutMs || 15_000)) + const controller = new AbortController() + const timer = setTimeout(() => controller.abort(), timeoutMs) + try { + const requestInit: RequestInit = { + method: options.method || 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + 'X-Semi-Auto-Key': endpoint.apiKey, + }, + signal: controller.signal, + } + if (options.body !== undefined) requestInit.body = JSON.stringify(options.body) + const response = await fetch(`${endpoint.baseUrl}${path}`, requestInit) + const text = await response.text() + let payload: unknown = null + try { + payload = text ? JSON.parse(text) : null + } catch { + payload = null + } + if (!response.ok) { + const detail = + payload && typeof payload === 'object' + ? String((payload as Record).detail || '') + : '' + throw createHttpError(detail || `半自动履约 Connector 请求失败(${response.status})`, { + statusCode: 502, + errorCode: 'semi_auto_connector_request_failed', + }) + } + return payload as T + } catch (error) { + if (error && typeof error === 'object' && 'statusCode' in error) throw error + if (error instanceof Error && error.name === 'AbortError') { + throw createHttpError('半自动履约 Connector 请求超时', { + statusCode: 504, + errorCode: 'semi_auto_connector_timeout', + }) + } + throw createHttpError( + error instanceof Error ? error.message : '半自动履约 Connector 请求失败', + { + statusCode: 502, + errorCode: 'semi_auto_connector_request_failed', + }, + ) + } finally { + clearTimeout(timer) + } +} + +export async function createHuyaLoginSession( + input: { + taskId: number + orderNo: string + }, + mode: SemiAutoConnectorMode = defaultSemiAutoConnectorMode(), +): Promise { + if (mode === 'embedded') { + return huyaNativeConnector.createLoginSession(input) + } + return callConnector( + '/api/internal/huya-semi-auto/sessions', + { + method: 'POST', + body: { + task_id: input.taskId, + order_no: input.orderNo, + }, + }, + mode, + ) +} + +export async function getHuyaLoginSession( + sessionId: string, + mode: SemiAutoConnectorMode = defaultSemiAutoConnectorMode(), +): Promise { + if (mode === 'embedded') return huyaNativeConnector.getLoginSession(sessionId) + return callConnector( + `/api/internal/huya-semi-auto/sessions/${encodeURIComponent(sessionId)}`, + {}, + mode, + ) +} + +export async function startHuyaBinding( + sessionId: string, + mode: SemiAutoConnectorMode = defaultSemiAutoConnectorMode(), + options: { forceRebind?: boolean } = {}, +): Promise { + if (mode === 'embedded') { + return huyaNativeConnector.startBinding( + sessionId, + options.forceRebind ? { forceRebind: true } : {}, + ) + } + return callConnector( + `/api/internal/huya-semi-auto/sessions/${encodeURIComponent(sessionId)}/binding`, + { method: 'POST', body: { force_rebind: Boolean(options.forceRebind) } }, + mode, + ) +} + +export async function getHuyaBinding( + sessionId: string, + mode: SemiAutoConnectorMode = defaultSemiAutoConnectorMode(), +): Promise { + if (mode === 'embedded') return huyaNativeConnector.pollBinding(sessionId) + return callConnector( + `/api/internal/huya-semi-auto/sessions/${encodeURIComponent(sessionId)}/binding`, + {}, + mode, + ) +} + +export async function confirmHuyaBinding( + sessionId: string, + mode: SemiAutoConnectorMode = defaultSemiAutoConnectorMode(), +): Promise { + if (mode === 'embedded') return huyaNativeConnector.confirmBinding(sessionId) + return callConnector( + `/api/internal/huya-semi-auto/sessions/${encodeURIComponent(sessionId)}/binding/confirm`, + { method: 'POST', body: {} }, + mode, + ) +} + +export async function createHuyaBrowserTicket( + input: { + sessionId: string + targetUrl?: string + }, + mode: SemiAutoConnectorMode = defaultSemiAutoConnectorMode(), +): Promise { + if (mode === 'embedded') return huyaNativeConnector.createBrowserTicket(input) + return callConnector( + `/api/internal/huya-semi-auto/sessions/${encodeURIComponent(input.sessionId)}/browser-ticket`, + { method: 'POST', body: { targetUrl: input.targetUrl || '' } }, + mode, + ) +} + +export function inferSemiAutoConnectorModeFromTicket(ticket: string): SemiAutoConnectorMode { + const normalized = ticket.trim() + if (normalized.startsWith('mock-ticket-')) return 'mock' + if (normalized.startsWith(HUYA_NATIVE_TICKET_PREFIX)) return 'embedded' + return 'external' +} + +export async function consumeHuyaBrowserTicket( + ticket: string, + mode: SemiAutoConnectorMode = inferSemiAutoConnectorModeFromTicket(ticket), +): Promise { + if (mode === 'embedded') return huyaNativeConnector.consumeBrowserTicket(ticket) + return callConnector( + `/api/internal/huya-semi-auto/browser-tickets/${encodeURIComponent(ticket)}`, + {}, + mode, + ) +} + +export async function revokeHuyaSession( + sessionId: string, + mode: SemiAutoConnectorMode = defaultSemiAutoConnectorMode(), +): Promise { + if (mode === 'embedded') { + await huyaNativeConnector.revokeSession(sessionId) + return + } + await callConnector<{ ok: boolean }>( + `/api/internal/huya-semi-auto/sessions/${encodeURIComponent(sessionId)}`, + { method: 'DELETE' }, + mode, + ) +} diff --git a/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/env.js b/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/env.js new file mode 100644 index 00000000..5237b909 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/env.js @@ -0,0 +1,560 @@ +// Android WebView 环境仿真 (默认 M2102J2SC; 可传设备覆盖参数实现一号一设备) +// overrides = {model, androidVer, vendor, appVer, screenWidth, screenHeight} +function makeEnv(overrides) { + const ov = overrides || {} + const MODEL = ov.model || 'M2102J2SC' + const ANDROID_VER = ov.androidVer || '11' + const VENDOR = ov.vendor || 'xiaomi' + const APP_VER = ov.appVer || '13.4.22' + const UA = + ov.userAgent || + 'Mozilla/5.0 (Linux; Android ' + + ANDROID_VER + + '; ' + + MODEL + + ' Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 ' + + 'Chrome/149.0.7827.159 Mobile Safari/537.36 huya adr/' + + APP_VER + + '/' + + VENDOR + + '/30' + // 视口按物理分辨率/3 仿真 (393x851 ≈ 1080x2120 / 2.75) + const VW = ov.screenWidth ? Math.round(ov.screenWidth / 2.75) : 393 + const VH = ov.screenHeight ? Math.round(ov.screenHeight / 2.75) : 851 + const W = globalThis + W.self = W + // Node 18/20 do not expose a browser navigator; create one before defining + // the properties consumed by hydevice. Newer Node versions already expose + // a Navigator instance, which is retained. + W.navigator = W.navigator || {} + W.screen = { + width: VW, + height: VH, + availWidth: VW, + availHeight: VH, + colorDepth: 24, + pixelDepth: 24, + availLeft: 0, + availTop: 0, + orientation: { type: 'portrait-primary', angle: 0 }, + } + W.devicePixelRatio = 2.75 + W.innerWidth = VW + W.innerHeight = Math.max(VH - 114, 500) + W.outerWidth = VW + W.outerHeight = VH + W.location = { + href: 'https://aq.huya.com/p/safe_auth/pt_auth.html', + protocol: 'https:', + host: 'aq.huya.com', + hostname: 'aq.huya.com', + port: '', + pathname: '/p/safe_auth/pt_auth.html', + search: '', + hash: '', + origin: 'https://aq.huya.com', + toString() { + return this.href + }, + } + W.history = { length: 2, state: null, pushState() {}, replaceState() {}, back() {}, go() {} } + const navProps = { + userAgent: UA, + appName: 'Netscape', + appVersion: UA.replace(/^Mozilla\//, ''), + platform: 'Linux armv8l', + language: 'zh-CN', + languages: ['zh-CN', 'zh', 'en'], + cookieEnabled: true, + doNotTrack: null, + maxTouchPoints: 5, + hardwareConcurrency: 8, + deviceMemory: 8, + vendor: 'Google Inc.', + productSub: '20030107', + webdriver: false, + pdfViewerEnabled: false, + javaEnabled() { + return false + }, + getBattery() { + return Promise.resolve({ charging: true, level: 0.9 }) + }, + userAgentData: { + brands: [ + { brand: 'Chromium', version: '149' }, + { brand: 'Google Chrome', version: '149' }, + { brand: 'Not?A_Brand', version: '24' }, + ], + mobile: true, + platform: 'Android', + getHighEntropyValues() { + return Promise.resolve({ + architecture: 'arm', + bitness: '64', + model: MODEL, + platformVersion: ANDROID_VER + '.0.0', + uaFullVersion: '149.0.7827.159', + }) + }, + }, + connection: { effectiveType: '4g', downlink: 10, rtt: 50, saveData: false }, + mediaDevices: { + enumerateDevices() { + return Promise.resolve([]) + }, + getUserMedia() { + return Promise.reject(new Error('not supported')) + }, + }, + plugins: { + length: 0, + item() { + return null + }, + namedItem() { + return null + }, + }, + mimeTypes: { length: 0 }, + } + for (const [k, v] of Object.entries(navProps)) { + try { + Object.defineProperty(W.navigator, k, { value: v, configurable: true }) + } catch (e) { + try { + W.navigator[k] = v + } catch (_) {} + } + } + // canvas 2d/webgl 最小仿真 + const glConsts = { + RENDERER: 0x1f01, + VENDOR: 0x1f00, + VERSION: 0x1f02, + SHADING_LANGUAGE_VERSION: 0x8b8c, + MAX_TEXTURE_SIZE: 0x0d33, + MAX_RENDERBUFFER_SIZE: 0x84e8, + MAX_VIEWPORT_DIMS: 0x0d3a, + } + function fakeGL() { + return new Proxy( + { + getExtension() { + return { UNMASKED_VENDOR_WEBGL: 0x9245, UNMASKED_RENDERER_WEBGL: 0x9246 } + }, + getParameter(p) { + if (p === 0x9245) return 'Qualcomm' + if (p === 0x9246) return 'Adreno (TM) 650' + if (p === glConsts.MAX_TEXTURE_SIZE) return 16384 + if (p === glConsts.MAX_VIEWPORT_DIMS) return new Int32Array([16384, 16384]) + return 'WebKit WebGL' + }, + getContextAttributes() { + return { alpha: true, antialias: true, depth: true } + }, + createBuffer() { + return {} + }, + bindBuffer() {}, + bufferData() {}, + createProgram() { + return {} + }, + attachShader() {}, + linkProgram() {}, + useProgram() {}, + createShader() { + return {} + }, + shaderSource() {}, + compileShader() {}, + getShaderParameter() { + return true + }, + getProgramParameter() { + return true + }, + getSupportedExtensions() { + return ['WEBGL_debug_renderer_info'] + }, + readPixels(x, y, w, h, t, f, buf) { + if (buf) buf.fill(128) + }, + }, + { + get(t, p) { + if (p in t) return t[p] + if (typeof p === 'string' && p.startsWith('on')) return null + if (typeof p === 'string') return () => null + return undefined + }, + }, + ) + } + const ctx2d = new Proxy( + { + fillRect() {}, + clearRect() {}, + getImageData(x, y, w, h) { + return { data: new Uint8ClampedArray(w * h * 4).fill(128), width: w, height: h } + }, + putImageData() {}, + createImageData(w, h) { + return { data: new Uint8ClampedArray(w * h * 4), width: w, height: h } + }, + setTransform() {}, + transform() {}, + translate() {}, + scale() {}, + rotate() {}, + save() {}, + restore() {}, + beginPath() {}, + closePath() {}, + moveTo() {}, + lineTo() {}, + stroke() {}, + fill() {}, + arc() {}, + rect() {}, + clip() {}, + createLinearGradient() { + return { addColorStop() {} } + }, + createRadialGradient() { + return { addColorStop() {} } + }, + fillText() {}, + strokeText() {}, + measureText(t) { + return { width: String(t).length * 7 } + }, + isPointInPath() { + return false + }, + drawImage() {}, + arcTo() {}, + bezierCurveTo() {}, + quadraticCurveTo() {}, + createPattern() { + return {} + }, + setLineDash() {}, + getLineDash() { + return [] + }, + }, + { + get(t, p) { + if (p in t) return t[p] + if (p === 'canvas') return {} + return undefined + }, + }, + ) + const canvasProto = { + getContext(type) { + if (type === '2d') return ctx2d + if (type === 'webgl' || type === 'webgl2' || type === 'experimental-webgl') return fakeGL() + return null + }, + toDataURL() { + return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==' + }, + toBlob(cb) { + cb && cb(null) + }, + addEventListener() {}, + removeEventListener() {}, + setAttribute() {}, + getBoundingClientRect() { + return { left: 0, top: 0, width: 300, height: 150 } + }, + style: {}, + width: 300, + height: 150, + } + // hydevice writes browser device state through document.cookie. Keep a small + // in-memory jar so Node has the same read/append semantics as a WebView. + const cookieJar = {} + const document = { + createElement(tag) { + const el = Object.assign({}, canvasProto, { + tagName: String(tag || 'div').toUpperCase(), + style: {}, + children: [], + setAttribute() {}, + getAttribute() { + return null + }, + appendChild(c) { + this.children.push(c) + }, + removeChild() {}, + addEventListener() {}, + removeEventListener() {}, + classList: { + add() {}, + remove() {}, + contains() { + return false + }, + }, + attachShadow() { + return { appendChild() {} } + }, + getBoundingClientRect() { + return { left: 0, top: 0, right: 100, bottom: 30, width: 100, height: 30 } + }, + }) + return el + }, + createEvent() { + return { initEvent() {} } + }, + createElementNS(ns, tag) { + return this.createElement(tag) + }, + createTextNode(t) { + return { textContent: t } + }, + createDocumentFragment() { + return { appendChild() {} } + }, + getElementById() { + return null + }, + querySelector() { + return null + }, + querySelectorAll() { + return [] + }, + getElementsByTagName(t) { + if (String(t).toLowerCase() === 'head') return [this.head] + return [] + }, + documentElement: { + setAttribute() {}, + getAttribute() { + return null + }, + style: {}, + removeChild() {}, + }, + head: { appendChild() {}, removeChild() {} }, + body: { + appendChild() {}, + removeChild() {}, + insertBefore() {}, + contains() { + return false + }, + }, + referrer: '', + title: 'pt_auth', + domain: 'aq.huya.com', + readyState: 'complete', + visibilityState: 'visible', + addEventListener() {}, + removeEventListener() {}, + } + document.location = W.location + Object.defineProperty(document, 'cookie', { + configurable: true, + get() { + return Object.entries(cookieJar) + .map(([k, v]) => `${k}=${v}`) + .join('; ') + }, + set(value) { + const first = String(value || '').split(';', 1)[0] + const index = first.indexOf('=') + if (index > 0) cookieJar[first.slice(0, index).trim()] = first.slice(index + 1).trim() + }, + }) + W.__huyaCookieJar = cookieJar + W.document = document + W.localStorage = (() => { + const m = {} + return { + getItem: (k) => m[k] ?? null, + setItem: (k, v) => (m[k] = String(v)), + removeItem: (k) => delete m[k], + clear: () => {}, + key: (i) => Object.keys(m)[i] ?? null, + get length() { + return Object.keys(m).length + }, + } + })() + W.sessionStorage = (() => { + const m = {} + return { + getItem: (k) => m[k] ?? null, + setItem: (k, v) => (m[k] = String(v)), + removeItem: (k) => delete m[k], + clear: () => {}, + key: (i) => null, + get length() { + return 0 + }, + } + })() + W.indexedDB = { + open() { + return { + onsuccess: null, + onerror: null, + onupgradeneeded: null, + result: { + objectStoreNames: { + contains() { + return false + }, + }, + createObjectStore() { + return { createIndex() {} } + }, + }, + set onsuccess(f) { + setTimeout(() => {}, 0) + }, + } + }, + } + W.performance = W.performance || { + now: () => Date.now(), + timeOrigin: Date.now(), + timing: { navigationStart: Date.now() }, + getEntriesByType() { + return [] + }, + mark() {}, + measure() {}, + } + W.AudioContext = class { + constructor() { + this.sampleRate = 48000 + this.destination = {} + } + createOscillator() { + return { + type: '', + frequency: { value: 0, setValueAtTime() {} }, + connect() {}, + start() {}, + stop() {}, + } + } + createDynamicsCompressor() { + return { + threshold: { value: 0 }, + knee: { value: 0 }, + ratio: { value: 0 }, + attack: { value: 0 }, + release: { value: 0 }, + connect() {}, + } + } + createAnalyser() { + return { + frequencyBinCount: 1024, + getFloatFrequencyData(a) { + a && a.fill(-100) + }, + } + } + createGain() { + return { gain: { value: 1, setValueAtTime() {} }, connect() {} } + } + createScriptProcessor() { + return { connect() {}, onaudioprocess: null } + } + decodeAudioData() { + return Promise.resolve({ + getChannelData() { + return new Float32Array(5000) + }, + }) + } + resume() { + return Promise.resolve() + } + close() { + return Promise.resolve() + } + } + W.webkitAudioContext = W.AudioContext + W.OfflineAudioContext = W.AudioContext + W.WebGLRenderingContext = { + RENDERER: glConsts.RENDERER, + VENDOR: glConsts.VENDOR, + VERSION: glConsts.VERSION, + SHADING_LANGUAGE_VERSION: glConsts.SHADING_LANGUAGE_VERSION, + MAX_TEXTURE_SIZE: glConsts.MAX_TEXTURE_SIZE, + } + W.RTCPeerConnection = class { + createDataChannel() { + return {} + } + createOffer() { + return Promise.resolve({}) + } + setLocalDescription() { + return Promise.resolve() + } + close() {} + } + W.webkitRTCPeerConnection = W.RTCPeerConnection + W.Notification = { permission: 'default' } + W.permissions = { + query() { + return Promise.resolve({ state: 'prompt' }) + }, + } + W.matchMedia = () => ({ + matches: false, + media: '', + addListener() {}, + removeListener() {}, + addEventListener() {}, + removeEventListener() {}, + }) + W.getComputedStyle = () => + new Proxy( + { getPropertyValue: () => '' }, + { + get(t, p) { + if (p in t) return t[p] + return () => '' + }, + }, + ) + W.requestAnimationFrame = (cb) => setTimeout(() => cb(Date.now()), 16) + W.cancelAnimationFrame = clearTimeout + W.requestIdleCallback = (cb) => + setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 16 }), 1) + W.cancelIdleCallback = clearTimeout + W.chrome = W.chrome || { + runtime: {}, + app: { isInstalled: false }, + csi() { + return {} + }, + loadTimes() { + return {} + }, + } + W.HTMLCanvasElement = W.HTMLCanvasElement || function HTMLCanvasElement() {} + W.HTMLElement = W.HTMLElement || function HTMLElement() {} + W.Element = W.Element || function Element() {} + W.addEventListener = () => {} + W.removeEventListener = () => {} + W.dispatchEvent = () => true + W.crypto = require('crypto').webcrypto + W.TextEncoder = require('util').TextEncoder + W.TextDecoder = require('util').TextDecoder +} +module.exports = { makeEnv } diff --git a/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/hydevice-prod-1.2.45-min.js b/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/hydevice-prod-1.2.45-min.js new file mode 100644 index 00000000..15d52a00 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/hydevice-prod-1.2.45-min.js @@ -0,0 +1 @@ +function _0x7f58(u,n){u-=251;var r=_0x6c4c(),f=r[u];if(void 0===_0x7f58.FKoLxs){_0x7f58.JukukB=function(u){for(var n,r,f="",A="",t=0,e=0;r=u.charAt(e++);~r&&(n=t%4?64*n+r:r,t++%4)?f+=String.fromCharCode(255&n>>(-2*t&6)):0)r="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=".indexOf(r);for(var i=0,c=f.length;in},FODMM:function(u,n){return un},Gfhgc:e(997)};f=this,A=function(u){"use strict";var n=e,r={HjVHY:i.Uqxdq,OUoWs:function(u,n){return i[_0x7f58(1308)](u,n)},lPNVf:"1|2|4|3|0",trwtq:function(u,n){return i.BRAdW(u,n)},bmuzW:n(10292),ikeqO:function(u,r){return i[n(2645)](u,r)},HCBZF:n(10366),XaUzo:function(u,n){return u!==n},TlKBO:i[n(1638)],LNOHg:n(6904),sbCoZ:i.FEVlv,yvkmZ:function(u,r){return i[n(2507)](u,r)},JiiLd:i[n(8342)],kTdBZ:function(u,r,f){return i[n(1445)](u,r,f)},moTtr:function(u,n){return i.QVxem(u,n)},mUvYO:i[n(864)],fdNAy:function(u,n){return i.vbJmT(u,n)},saTCV:n(2183),Jadwz:function(u,r){return i[n(3207)](u,r)},ZUwTS:function(u,r,f){return i[n(791)](u,r,f)},HeQpi:function(u,r){return i[n(7035)](u,r)},Olsyv:function(u,n,r){return u(n,r)},IBbfu:function(u,r){return i[n(451)](u,r)},IVMAj:i[n(275)],VwavR:i.YIYKU,ALOqn:n(3535),ParZB:i.seyWw,RoZzi:i[n(5348)],vfxUL:function(u,r,f){return i[n(10442)](u,r,f)},MMgMV:function(u,n){return i.mwXCc(u,n)},jcyAA:i[n(8384)],RytNP:function(u,r){return i[n(2507)](u,r)},bMbRF:function(u,r,f,A){return i[n(1939)](u,r,f,A)},ivpBt:function(u,n){return u(n)},jpLjn:function(u,r){return i[n(1750)](u,r)},IqsUO:function(u,n){return u!==n},yKNdg:function(u,n){return i.TqWNN(u,n)},QzCGr:i[n(8019)],SMCTQ:i[n(2730)],lRRWA:function(u,r){return i[n(1689)](u,r)},DBoJS:function(u,n){return u+n},TqraM:function(u,r){return i[n(7839)](u,r)},RqoRU:function(u,n){return i.VxQmA(u,n)},twexM:function(u,n){return u!==n},WRtsW:function(u,r,f){return i[n(791)](u,r,f)},MjFUd:function(u,n){return u===n},PIlHD:function(u,n,r){return u(n,r)}};if(n(6788)===i[n(5347)])return[_0x54e62f.screenLeft,_0x6f43b[n(8932)]];{const f=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,A=u=>{var A=n,t={AjTBh:r[A(9819)],INLbo:function(u,n){return r[A(1393)](u,n)},ngsLN:r.lPNVf,FbApF:function(u,n){return r[A(3222)](u,n)},EPevh:r[A(4071)]};if(r[A(4121)](r[A(5257)],r[A(5257)])){if(r[A(1683)](typeof u,r.TlKBO)){if(!r[A(1683)](r[A(4091)],r[A(4091)]))throw new TypeError(r.sbCoZ);_0x3dfb25[A(2781)](t[A(9166)])}const n=u[A(4343)](f);if(!n){if(!r[A(3889)](r[A(1079)],A(1051)))throw new Error(A(7610)+u+"' received)");for(var e=0;t.INLbo(e,_0x19c292.length);e++)for(var i=t[A(1580)][A(7897)]("|"),c=0;;){switch(i[c++]){case"0":_0x384244[A(4594)](_0x495e2f,o[A(6290)],o);continue;case"1":var o=_0x95b252[e];continue;case"2":o.enumerable=o[A(3851)]||!1;continue;case"3":t[A(6637)](t[A(602)],o)&&(o.writable=!0);continue;case"4":o[A(8441)]=!0;continue}break}}return n[A(9728)](),n}_0x4f1d2a=_0xa9d680.call(_0x2ba085)},t=u=>"*"===u||"x"===u||"X"===u,e=u=>{var r=n,f={CGNxT:i[r(375)]};if(!i[r(8055)](i[r(9338)],i[r(7491)])){const n=i[r(791)](parseInt,u,10);return i.QVxem(isNaN,n)?u:n}_0x167214[r(9569)](f[r(8940)])},c=(u,n)=>typeof u!=typeof n?[String(u),String(n)]:[u,n],o=(u,r)=>{var f=n;if(t(u)||i[f(2627)](t,r))return 0;const[A,o]=i[f(1445)](c,i[f(2627)](e,u),i[f(4582)](e,r));return i.BVTsv(A,o)?1:i[f(1308)](A,o)?-1:0},q=(u,f)=>{var A=n;for(let n=0;n{var t=n,e={SbNQZ:t(7074),spGty:function(u,n){return r[t(7820)](u,n)}};if(r[t(4121)](t(2183),r[t(3572)])){const n=r[t(1426)](A,u),v=r[t(1426)](A,f),b=n[t(7948)](),s=v[t(7948)](),a=r[t(1616)](q,n,v);if(0!==a)return a;if(r[t(4716)](b,s))return r.Olsyv(q,b[t(7897)]("."),s.split("."));if(r[t(6234)](b,s)){if(!r[t(1683)](r[t(5240)],r.IVMAj))return b?-1:1;for(var i=e.SbNQZ.split("|"),c=0;;){switch(i[c++]){case"0":e[t(4271)](t(10292),o)&&(o[t(594)]=!0);continue;case"1":_0xe08b6f[t(4594)](_0x8d4aeb,o.key,o);continue;case"2":var o=_0x580c74[_0x145187];continue;case"3":o.configurable=!0;continue;case"4":o[t(3851)]=o[t(3851)]||!1;continue}break}}return 0}var v={QCruz:function(u,n){return r[t(4772)](u,n)},miZGw:r[t(4040)]};return _0x4dcb81[t(4099)](function(u){for(var n=t,r={UlTzw:function(u,n){return v[_0x7f58(2412)](u,n)}};;)switch(u[n(2519)]=u[n(6460)]){case 0:return u.abrupt(v[n(3654)],new _0x1d3f24(function(u,f){var A=n,t=new(_0x2abc6e[A(6818)]);t.encryptVersion=_0x27c6d9[A(3470)],t.fingerprintVersion=_0x1f7917[A(921)],r[A(10403)](u,t)}));case 1:case n(8961):return u[n(9572)]()}},_0x8bba6f,this)},b=(u,n,r)=>{x(r);const f=v(u,n);return s[r].includes(f)},s={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]},a=Object.keys(s),x=u=>{var r=n;if(i[r(7311)](typeof u,"string")){if(!i[r(2645)](r(7529),i[r(3431)]))throw new TypeError("Invalid operator type, expected string but got "+typeof u);_0x575617=!0,_0x1a8284=_0x58aae2}if(-1===a.indexOf(u))throw new Error(r(6950)+a[r(6309)]("|"))},w=(u,f)=>{var t=n,e={GVLrh:function(u,n){return r[_0x7f58(4121)](u,n)},IkgMH:r[t(3976)],rFQhY:r.ALOqn};if((f=f[t(5506)](/([><=]+)\s+/g,"$1"))[t(2019)]("||"))return r[t(1683)](t(6551),r[t(4097)])?f.split("||")[t(631)](n=>w(u,n)):_0x3a9732[t(1686)];if(f.includes(t(8429))){const[n,A]=f[t(7897)](r[t(7794)],2);return r[t(7726)](w,u,">="+n+t(2332)+A)}if(f[t(2019)](" "))return r[t(4258)](t(7848),r[t(1553)])?f[t(4272)]()[t(5506)](/\s{2,}/g," ")[t(7897)](" ")[t(6248)](n=>w(u,n)):e[t(1663)](_0x5884f7[t(3935)][t(5353)],_0x3db24e)?t(2841):_0x32bd33[t(3935)][t(5353)]?e[t(9607)]:e.rFQhY;const i=f[t(4343)](/^([<>=~^]+)/),c=i?i[1]:"=";if("^"!==c&&r[t(7442)](c,"~"))return r[t(4958)](b,u,f,c);const[o,v,s,,a]=A(u),[x,g,C,,B]=r[t(1955)](A,f),D=[o,v,s],L=[x,r[t(1073)](g,null)&&r[t(1305)](g,void 0)?g:"x",r[t(8455)](C,null)&&r[t(1305)](C,void 0)?C:"x"];if(B)if(r[t(6933)]!==r.SMCTQ){if(!a)return!1;if(0!==r[t(1616)](q,D,L))return!1;if(r[t(3703)](q(a[t(7897)]("."),B[t(7897)](".")),-1))return!1}else _0x5a0684(_0x26b047.CryptoJS);const z=r[t(1944)](L[t(1417)](u=>"0"!==u),1),E=r[t(10380)](c,"~")?2:r[t(2293)](z,1)?z:1;return!r.twexM(r[t(3098)](q,D.slice(0,E),L[t(781)](0,E)),0)&&!r[t(10417)](r.PIlHD(q,D[t(781)](E),L[t(781)](E)),-1)},g=u=>typeof u===n(7158)&&/^[v\d]/[n(2785)](u)&&f.test(u),C=u=>typeof u===n(7158)&&/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(u);u.compare=b,u[n(3656)]=v,u.satisfies=w,u.validate=g,u[n(929)]=C}},t=e,i.xhLpL(typeof r,i.EYBcq)&&i[t(7311)](typeof n,i[t(1502)])?i[t(5381)](A,r):i[t(8055)](typeof define,i[t(6662)])&&define[t(4388)]?i[t(7623)](define,[i[t(7532)]],A):(f=typeof globalThis!==i[t(1502)]?globalThis:f||self,i[t(5381)](A,f.compareVersions={}))},{}],2:[function(u,n,r){var f=_0x7f58,A={Juqsv:function(u,n){return u>>n},EbYOw:function(u,n){return u-n},oVAfU:f(6859),XoREK:function(u,n){return u^n},tLMZe:function(u,n){return u>>>n},uGyqd:function(u,n){return u<>>n},jTEtY:function(u,n){return u!==n},bkysf:"chbzg",NafBY:f(6031)};!function(t,e,i){var c=f;if(A.DrKNY(typeof r,A[c(9344)]))n[c(8018)]=r=e(u("./core"),A.BDblM(u,A.nMzta),A.OwkpH(u,A.enFiP),A[c(9030)](u,A[c(10428)]),A[c(2885)](u,"./cipher-core"));else if("function"==typeof define&&define[c(4388)]){if(!A.QfLBQ(A[c(9901)],c(6814)))return[];A[c(1715)](define,[c(3251),c(7470),A.enFiP,A[c(10428)],A[c(5239)]],e)}else A[c(4347)](e,t[c(3080)])}(this,function(u){var n=f,r={yeGSL:A[n(2721)],eNlNU:function(u,r){return A[n(331)](u,r)},jmPQa:function(u,r){return A[n(331)](u,r)},ZHmMA:function(u,n){return A.xJtyI(u,n)},bhUFh:A[n(2849)],qTWng:function(u,n,r,f,t){return A.rzzQv(u,n,r,f,t)},DsAOG:A.AUtSm,XjfsS:function(u,n){return u===n},nsyPN:A[n(5576)],onXIH:function(u,r){return A[n(5490)](u,r)},GsCgt:function(u,n){return u===n},Wwfay:A.zrMSn,wiiZL:function(u,r){return A[n(2118)](u,r)},rLaXk:function(u,n){return u>>>n},JoDuq:function(u,r){return A[n(9409)](u,r)},qElaP:function(u,n){return u^n},DdnsJ:function(u,r){return A[n(8453)](u,r)},iwjmj:function(u,r){return A[n(6062)](u,r)},yuSQq:function(u,n){return u<>>n},kJvso:function(u,n){return r[f(8031)](u,n)},okcmb:function(u,n){return r[f(8415)](u,n)},kQpSg:function(u,n){return r[f(7837)](u,n)},ocbRN:function(u,n){return r[f(6947)](u,n)},Lmfct:function(u,n){return r[f(8031)](u,n)},pQJxC:function(u,n){return r[f(2187)](u,n)},HURZV:function(u,n){return r.ezeer(u,n)},gVROC:function(u,n){return r.cEOTv(u,n)},ZKhZa:function(u,n){return r[f(6709)](u,n)},tXchT:function(u,n){return u|n},LjWUQ:function(u,n){return r[f(4660)](u,n)},GLEiG:r[f(8467)],AdskD:f(3982),yxdhQ:function(u,n){return r.aYrxB(u,n)},uIJwa:function(u,n){return u+n},SMFjp:function(u,n){return r[f(2187)](u,n)},LWbkr:function(u,n){return r[f(1460)](u,n)},Ttlfn:function(u,n){return u===n},DYcwL:r[f(8515)],CuLmY:function(u,n){return r[f(2927)](u,n)},AzKqF:r[f(5468)],qIZyc:function(u,n){return r[f(9831)](u,n)},YHtNp:function(u,n){return r[f(9878)](u,n)},VLiyS:function(u,n){return r[f(1473)](u,n)},YoMEt:f(9671),nPmoJ:function(u,n){return u>>>n},OsCYE:function(u,n){return r[f(5689)](u,n)},zZwrD:function(u,n){return u&n},jwPRd:function(u,n){return u|n},liadP:function(u,n){return r[f(742)](u,n)},GhwCj:function(u,n){return r.UQrut(u,n)},qjQZy:function(u,n){return u<>>n},WmIaJ:function(u,n){return r[f(4557)](u,n)},uYIbh:function(u,n){return r[f(7957)](u,n)},CJfDg:function(u,n){return u>>n},zSwnM:function(u,n){return r[f(933)](u,n)},ZpFbc:function(u,n){return r.hSBGH(u,n)},mLkhx:function(u,n){return r[f(8476)](u,n)},cYgWO:function(u,n){return u&n},fBsUE:function(u,n){return u%n},QHgUo:function(u,n){return r.mxqqZ(u,n)},gQACz:function(u,n){return u>>>n},ZqWMy:function(u,n){return r[f(8415)](u,n)},pdOnh:r.RFOgq,OArlX:function(u,n){return r[f(9688)](u,n)},ruLlQ:function(u,n){return r[f(8476)](u,n)},nWNTy:function(u,n){return r[f(3455)](u,n)},lscic:function(u,n){return u^n},yffUt:function(u,n){return r[f(7957)](u,n)},QMioE:function(u,n){return r[f(6947)](u,n)},gXjvS:function(u,n){return r[f(6947)](u,n)},hurCF:function(u,n){return r.eqawQ(u,n)},kNfNf:function(u,n){return u&n},sNsjd:function(u,n){return r.eqawQ(u,n)},OpdXq:function(u,n){return r[f(4557)](u,n)},oYEVl:function(u,n){return r[f(3937)](u,n)},dmRqG:function(u,n){return r[f(7791)](u,n)},CADcF:function(u,n){return u^n},LMAkb:function(u,n){return u|n},lydiy:function(u,n){return r[f(4459)](u,n)},CLcCu:function(u,n){return r.eqawQ(u,n)},oRyEk:function(u,n){return r[f(2280)](u,n)},UeDfP:function(u,n){return r[f(9255)](u,n)},tLssS:function(u,n){return r[f(3937)](u,n)},avlnL:function(u,n){return r[f(9012)](u,n)},UnBJd:function(u,n){return u^n},dpEpD:function(u,n){return r[f(6403)](u,n)},bNEMq:function(u,n){return r[f(7791)](u,n)},qSnJL:function(u,n){return r[f(6947)](u,n)},llZmM:function(u,n){return r[f(7837)](u,n)},iPmuY:function(u,n){return r.AijPV(u,n)},WXWSy:function(u,n){return u^n},maFmv:function(u,n){return u|n},bbCZs:function(u,n){return r[f(4480)](u,n)},OZJKo:function(u,n){return u<>>16);continue;case"14":L=A.gVROC(A[u(10421)](L>>>8,A[u(10046)](L,255)),99);continue;case"15":var E=n[z];continue;case"16":v[t]=A[u(5120)](A[u(9795)](D,16),D>>>16);continue;case"17":s[t]=D;continue}break}}();var C=[0,1,2,4,8,16,32,64,128,27,54],B=i[f(6007)]=e[f(6491)]({_doReset:function(){var u=f,n={YOmHP:u(8496),iXIeb:function(u,n){return u+n},DquxZ:function(u,n){return A.LjWUQ(u,n)},TKFAK:A.GLEiG,jiHIK:A.AdskD};if(!this._nRounds||!A.noMCj(this[u(4661)],this._key)){for(var r=this[u(4661)]=this[u(3370)],t=r[u(7992)],e=A[u(3258)](r[u(7822)],4),i=this[u(6855)]=A[u(7354)](e,6),o=A[u(7629)](A[u(7354)](i,1),4),q=this[u(10022)]=[],v=0;A[u(6349)](v,o);v++)if(A.YSHjH(v,e)){if(A[u(1104)](A.DYcwL,"RZmgV"))throw _0x4478c5[u(5469)];q[v]=t[v]}else if(A[u(4027)](A[u(7505)],"BDQAu")){var b={type:n[u(4226)],appid:n[u(9724)]("",_0x1f1e5f[u(6818)][u(3266)]()),hdid:(0,_0x110673.getData)(_0x781e39[u(6818)].HDID_NAME),qimei:_0x1cf1d5[u(6818)].qimei,time:(new _0x3146dc)[u(7744)](),action:{clientXY:_0x5636d4[u(5614)]([_0x542d40[u(5758)],_0x5544b1[u(8755)]]),screenXY:_0x35b4ef[u(5614)]([_0xcd26d6.screenX,_0x4dcb3d.screenY]),isTrusted:_0x36cacf[u(5614)](_0x50b2e0.isTrusted),stack:_0x26ccd4}},s=_0x20b7f0.stringify(b);_0x9bfdd3[u(1889)](s)}else{var B=q[A.qIZyc(v,1)];A[u(2698)](v,e)?e>6&&A.liadP(A[u(2698)](v,e),4)&&(B=A[u(10407)](A.wOrsE(A.GhwCj(A.qjQZy(c[A.rNYlQ(B,24)],24),c[A[u(1518)](A[u(4436)](B,16),255)]<<16),c[A[u(3577)](A[u(10468)](B,8),255)]<<8),c[A[u(10046)](B,255)])):A.VLiyS(A[u(6703)],A[u(6703)])?_0x52ca90[u(995)](_0x3aefb2):(B=A[u(4484)](B<<8,B>>>24),B=A.tXchT(A.tXchT(A.wOrsE(c[A[u(10468)](B,24)]<<24,c[A[u(10046)](B>>>16,255)]<<16),A.OsCYE(c[A.zZwrD(A[u(10468)](B,8),255)],8)),c[A.zZwrD(B,255)]),B^=A[u(9795)](C[A.jwPRd(v/e,0)],24)),q[v]=A[u(6047)](q[A.qIZyc(v,e)],B)}for(var D=this[u(6708)]=[],L=0;A[u(1946)](L,o);L++){v=A[u(5352)](o,L);if(A.YHtNp(L,4))B=q[v];else if(A.VLiyS(u(2813),A[u(1146)]))B=q[A.iftog(v,4)];else n.DquxZ(_0x8eebef,_0x581082[n[u(712)]](_0x79d2c8));if(A[u(4081)](L,4)||A[u(4902)](v,4))D[L]=B;else if(A[u(774)](u(2510),A[u(3831)]))D[L]=A[u(6783)](A[u(3697)](A[u(2344)](a[c[A[u(5107)](B,24)]],x[c[A[u(3577)](A[u(6251)](B,16),255)]]),w[c[A[u(4949)](A[u(5815)](B,8),255)]]),g[c[A[u(6258)](B,255)]]);else for(var z=n[u(6870)][u(7897)]("|"),E=0;;){switch(z[E++]){case"0":var d=K[u(8364)];continue;case"1":var I=K.enc;continue;case"2":var j=d[u(1564)];continue;case"3":var K=_0xd9933e;continue;case"4":var y=K[u(7852)];continue;case"5":y[u(2982)]={stringify:function(n){var r=u;return n[r(9003)][r(9965)](h)},parse:function(n){var r=u,f=h[r(8333)](n);return j[r(4703)]({ciphertext:f})}};continue;case"6":var h=I[u(2982)];continue}break}}}},encryptBlock:function(u,n){var r=f;this._doCryptBlock(u,n,this[r(10022)],q,v,b,s,c)},decryptBlock:function(u,n){for(var A=f,t=r.yeGSL[A(7897)]("|"),e=0;;){switch(t[e++]){case"0":this[A(2924)](u,n,this[A(6708)],a,x,w,g,o);continue;case"1":u[r[A(1786)](n,1)]=u[r[A(1482)](n,3)];continue;case"2":u[n+3]=i;continue;case"3":u[r.eNlNU(n,3)]=i;continue;case"4":u[r[A(4986)](n,1)]=u[r[A(1482)](n,3)];continue;case"5":var i=u[r[A(4986)](n,1)];continue;case"6":i=u[n+1];continue}break}},_doCryptBlock:function(u,n,r,t,e,i,c,o){for(var q=f,v={YZMNi:function(u,n){return A.fBsUE(u,n)},kCvKH:function(u,n){return A.QHgUo(u,n)},RlcJw:function(u,n){return u*n},rBLTs:function(u,n){return A[_0x7f58(4836)](u,n)},obqvA:function(u,n){return A[_0x7f58(7592)](u,n)}},b=this[q(6855)],s=u[n]^r[0],a=A[q(6047)](u[A[q(7354)](n,1)],r[1]),x=A[q(4899)](u[A.uIJwa(n,2)],r[2]),w=A[q(3697)](u[n+3],r[3]),g=4,C=1;C>>24],e[255&A[q(4223)](x,16)]),i[A[q(6258)](A.AZjsA(w,8),255)]),c[A[q(10046)](s,255)]),r[g++]);continue;case"2":var y=A[q(8734)](A[q(722)](A.gVROC(t[x>>>24],e[255&A[q(3153)](w,16)]),i[A[q(4949)](s>>>8,255)])^c[255&a],r[g++]);continue;case"3":s=j;continue;case"4":var h=A[q(2201)](A[q(10421)](A[q(6783)](t[A[q(9054)](w,24)],e[A[q(10046)](A[q(4842)](s,16),255)]),i[A[q(6258)](A.PGfdH(a,8),255)]),c[A[q(4949)](x,255)])^r[g++];continue;case"5":x=y;continue;case"6":w=h;continue;case"7":a=K;continue}break}}j=A[q(5120)](A[q(4484)](A[q(5270)](A[q(603)](o[A[q(8519)](s,24)],24),A[q(8096)](o[A[q(3892)](A[q(6704)](a,16),255)],16)),A.qjQZy(o[A[q(5223)](A.oYEVl(x,8),255)],8)),o[A[q(1536)](w,255)])^r[g++],K=A.CADcF(A[q(9115)](A[q(3604)](A[q(9795)](o[A[q(4816)](a,24)],24)|A[q(7398)](o[A[q(1536)](A[q(1261)](x,16),255)],16),o[255&A[q(7495)](w,8)]<<8),o[A[q(2194)](s,255)]),r[g++]),y=A[q(1011)](A[q(5270)](A[q(5120)](A[q(7457)](o[A[q(6704)](x,24)],24),A[q(7683)](o[A.bNEMq(A[q(10074)](w,16),255)],16)),A[q(984)](o[A[q(10046)](A.ocbRN(s,8),255)],8))|o[A.iPmuY(a,255)],r[g++]),h=A[q(505)](A.maFmv(A[q(5270)](A.bbCZs(A.OZJKo(o[A[q(694)](w,24)],24),A.JQKkV(o[A[q(6258)](s>>>16,255)],16)),A.dpEpD(o[A[q(2459)](a>>>8,255)],8)),o[255&x]),r[g++]);u[n]=j,u[n+1]=K,u[n+2]=y,u[n+3]=h},keySize:r[f(3002)](256,32)});t.AES=e[f(5404)](B)}(),u[n(6007)];_0x3c1e4a=-1})},{"./cipher-core":3,"./core":4,"./enc-base64":5,"./evpkdf":8,"./md5":13}],3:[function(u,n,r){var f=_0x7f58,A={AQDon:f(6706),gnHab:function(u,n){return u(n)},JCXoq:function(u,n){return u!==n},MKDtx:f(1757),nIzIO:function(u,n){return u===n},KPcIf:function(u,n){return u!==n},yIeEg:"iDiDk",VeYrR:function(u,n,r){return u(n,r)},VheNM:function(u,n){return u(n)},ucDPm:"./evpkdf",ZjcKM:f(4261),adTlw:function(u,n){return u!==n},VDMHe:f(7150),fdJDx:function(u,n,r){return u(n,r)},FsGGp:"mMhuH",SxXxs:function(u,n){return u(n)},LXkxw:"BRYxh",tanwN:function(u,n){return u!==n},bLwxr:f(7158),cAhwI:f(10491),ZzAYT:function(u,n){return u-n},WhPsW:function(u,n){return u%n},OGCCF:function(u,n){return u>>n},hPbYk:function(u,n){return u!==n},vHpCN:"CKbfn",NxFBt:function(u,n){return u===n},tWPEw:f(3129),ZxKLc:function(u,n){return u^n},dLDei:function(u,n){return u!==n},zKpuj:function(u,n){return u!==n},NmpQk:f(1207),xVVme:f(750),nDSuE:function(u,n){return u*n},bOwzJ:function(u,n){return u+n},AWTVI:f(6169),UzBMR:"eJgja",zwNoF:f(5651),ZOfCD:"4|1|2|3|0|5",RghDk:function(u,n,r){return u(n,r)},pDRak:f(4431),kJMiD:f(4465),fJyCo:f(585),PadvC:f(652),InlOI:f(1495),Nmvnn:"object",nOWUI:f(3251),eEPbZ:"type",rJWYV:function(u,n){return u/n},MthMK:function(u,n){return u/n}};!function(t,e,i){var c=f,o={adEOT:function(u,n){return A[_0x7f58(2549)](u,n)}};if(A[c(294)](c(2477),A[c(3675)]))if(A[c(4765)](typeof r,c(7186))){if(A.KPcIf(A[c(5803)],A[c(5803)]))return _0x43de2b[c(409)];n.exports=r=A.VeYrR(e,A[c(2549)](u,c(3251)),A[c(1291)](u,A[c(4893)]))}else if(typeof define===A[c(5011)]&&define[c(4388)])if(A.adTlw("LZzDn",A[c(7693)]))A[c(8101)](define,[c(3251),A[c(4893)]],e);else{_0xd8201c;this[c(1545)]=_0x3947b4}else{if(!A[c(4765)](A[c(7655)],A[c(7655)]))throw new _0x268af4(A[c(10172)]);A.SxXxs(e,t[c(3080)])}else o[c(359)](_0x48551e,_0x29d1bc.next(_0x55ff6f))}(this,function(u){var n,r,t,e,i,c,o,q,v,b,s,a,x,w,g,C,B,D,L,z,E,d=f,I={PHOaB:function(u,n){return A[_0x7f58(4765)](u,n)},hcBoc:A[d(5255)],BNycd:function(u,n){return A.tanwN(u,n)},IoZPT:function(u,n){return u==n},faCNP:A.bLwxr,eLVAi:function(u,n){return A[d(1291)](u,n)},wLZQu:A[d(4454)],xFOXp:"flush",YecAh:function(u,n){return u!==n},LBLTL:d(9685),Eaihk:d(1880),HfPvt:function(u,n){return A.ZzAYT(u,n)},InHMY:function(u,n){return A.WhPsW(u,n)},gPKGB:function(u,n){return u*n},cPtXp:function(u,n){return A[d(5159)](u,n)},phtzm:function(u,n){return A.rNsYV(u,n)},cXtDT:function(u,n){return u|n},mEjSH:function(u,n){return A[d(6588)](u,n)},AOfRr:function(u,n){return u<>>n},NcAjd:function(u,n){return u<=n},WfmkZ:function(u,n){return u in n},gCuqb:f(7702),Eefnp:function(u,n){return u in n},RbIdv:function(u,n){return u(n)},mWuyv:f(2173),ikJya:f(6848),ueKdw:function(u,n){return u!==n},WtcdL:"./cipher-core",RMziM:"YhlmO",Senxd:function(u,n){return u!=n},MWeBy:f(8883),BFsxU:function(u,n){return u%n},xecIE:function(u,n){return u+n},queZi:function(u,n){return u*n},EoPQx:function(u,n){return un},subii:function(u,n){return u|n},UOIZy:f(5443),rAGEo:function(u,n){return u&n},DnlGw:function(u,n,r){return u(n,r)},FMCmm:f(3251),cyYvO:f(5473),hwYBc:"yKElS",YMtVq:"ILuNN",FlpIY:function(u,n){return u/n}};!function(u,t){var e=f,i={WKmdk:function(u,n){return A.cfFdy(u,n)}};if(A[e(9510)](typeof r,A[e(1345)]))n[e(8018)]=r=A.ANzAe(t);else if(A[e(4098)](typeof define,A[e(3713)])&&define[e(4388)])if(A.PCgsM(e(5996),e(4760))){_0x5661ac=this[e(2188)]=[];for(var c=0;i[e(7582)](c,_0x5f24f1[e(7855)]);c++)_0x58bbca[_0x69304a[e(252)](c)]=c}else A.ZOVYo(define,[],t);else u[e(3080)]=A[e(309)](t)}(this,function(){var u=f,n={bJvaG:function(u,n){return A[_0x7f58(2367)](u,n)},hIHHL:function(u,n){return A[_0x7f58(4870)](u,n)},CFUvL:function(u,n){return A[_0x7f58(1572)](u,n)},jMYTe:function(u,n){return A[_0x7f58(7170)](u,n)},GKvrf:function(u,n){return A.OCGik(u,n)},RkGwl:function(u,n){return u!==n},OjZmh:A[u(10305)],FQQNx:function(n,r){return A[u(4978)](n,r)},yMQlA:function(n,r){return A[u(3878)](n,r)},Hrnzp:u(9174),HJqdU:function(u,n){return u>>>n},PiZkl:function(n,r){return A[u(4870)](n,r)},vxMgE:function(n,r){return A[u(9822)](n,r)},hHbGk:function(n,r){return A[u(5842)](n,r)},QbWmd:function(u,n){return u%n},dYWtB:function(u,n){return u*n},cAqra:function(u,n){return A.mOoWU(u,n)},jZmGS:function(n,r){return A[u(4165)](n,r)},ahTts:A[u(3365)],tefvt:A[u(9105)],OaBVt:A[u(9481)],legvx:function(n,r){return A[u(9065)](n,r)},yeFmV:function(n,r){return A[u(3107)](n,r)},UKdIu:A[u(2169)],JmcoW:function(u,n){return A.Eefnp(u,n)},oIyBE:u(9965),lrkAr:function(n,r){return A[u(9417)](n,r)},yAdOh:A[u(6334)],GLzKn:function(u,n){return u===n},bdcsQ:A.ikJya,vfPbY:function(u,n){return A.ueKdw(u,n)},YpSIf:A[u(2548)],YBfTN:A[u(9049)],jYNlW:function(n,r){return A[u(2852)](n,r)},bgJGa:u(2858),zuTuX:A[u(638)],NsPfA:function(u,n){return u||n},awotl:function(u,n){return A.BFsxU(u,n)},mMJqd:u(5610),micvc:function(n,r){return A[u(2367)](n,r)},JAlss:function(n,r){return A[u(4924)](n,r)},IUQtq:function(n,r){return A[u(5611)](n,r)},dQcmS:function(n,r){return A[u(6623)](n,r)},JwJsc:A[u(4883)],HMPyV:function(u,n,r,f){return u(n,r,f)},nyeTL:A[u(2699)],JUSgm:function(u,n){return u>>n},hnxkb:function(n,r){return A[u(2370)](n,r)},LpmWW:function(n,r){return A[u(9510)](n,r)},rkFPN:function(n,r){return A[u(2610)](n,r)},TVlXF:function(u){return A.qcVhv(u)},CZJlj:A[u(4895)],EtGxB:function(u,n){return A.rAGEo(u,n)},FszQz:function(u,n,r){return A.DnlGw(u,n,r)},QXOjT:A[u(1830)],vrHax:A.cyYvO,MVpHL:A.hwYBc,erQeq:A[u(1137)],KsIxn:u(3696),dXLmZ:function(u,n){return A.FlpIY(u,n)}},r=r||function(r,f){var A,t,e=u,i={krnQJ:"0|1|3|4|2",yoGde:"tXwgC",Uweeb:n.oIyBE,rVpJf:function(u,r){return n[_0x7f58(1230)](u,r)},Klkli:n[e(9343)],uJMxY:function(u,r){return n[e(267)](u,r)},ffnSQ:e(3204),APDZM:n.bdcsQ,dVNTb:function(u,r){return n[e(548)](u,r)},VmSkH:e(5554),XmMus:n[e(529)],fNSye:n[e(6408)],QaqID:function(u,r){return n[e(6337)](u,r)},yOEDy:n[e(348)],CkCPu:n[e(10512)],yGAZj:function(u,r){return n[e(6541)](u,r)},zIPsS:function(u,n){return u(n)},APWZl:e(4003),aGxTB:function(u,r){return n.awotl(u,r)},zIWzT:n.mMJqd,ZJccF:function(u,r){return n[e(10082)](u,r)},dReBT:function(u,n){return u>>>n},bTzBf:function(u,r){return n[e(2877)](u,r)},oosgc:function(u,r){return n[e(9729)](u,r)},qGmrK:function(u,r){return n.micvc(u,r)},MKxHP:function(u,r){return n[e(580)](u,r)},ijVAE:function(u,r){return n[e(9107)](u,r)},fwUAy:function(u,r){return n[e(6348)](u,r)},hxIHY:function(u,r){return n[e(8317)](u,r)},iKPOv:function(u,r){return n[e(8147)](u,r)},byPBy:n[e(4419)],WegZA:function(u,n,r,f,A){return u(n,r,f,A)},stasR:function(u,n){return u!==n},Waokd:function(u,r,f,A){return n[e(1967)](u,r,f,A)},GNiuC:function(u,n){return u^n},DedYf:n.nyeTL,EGWch:e(2872),OgmOj:function(u,r){return n.JUSgm(u,r)},nAeVA:function(u,n){return u+n},IYhjn:function(u,r){return n.hnxkb(u,r)},YfhSi:function(u,r){return n.LpmWW(u,r)},maLiT:"oQLMk",GhPsm:function(u,n){return u(n)},nleRX:function(u,r){return n[e(382)](u,r)},yBPyR:function(u){return n[e(6178)](u)},YnAWL:function(u,r){return n[e(1230)](u,r)},BfLaa:function(u,r){return n[e(8147)](u,r)},dFaQC:"XVZld",afFyl:function(u,n){return u&n},ExPBF:function(u,r){return n.HJqdU(u,r)},oXMfB:n.CZJlj,MPnQn:function(u,r){return n[e(1724)](u,r)},pYtkx:function(u,n){return u%n},PUYWU:function(u){return n[e(6178)](u)},QtMUB:function(u,r,f){return n[e(310)](u,r,f)},XIpxC:n[e(9010)],vTrHv:function(u,r){return n[e(1230)](u,r)},ewKYh:e(9438),ssZMa:function(u,n){return u===n},FqNxw:"VreYZ",uipjY:function(u,n){return u==n},elYhe:e(7158),hNXbB:e(6289),lWTFw:n[e(7497)],SArVT:function(u,n){return u!==n},DKpVZ:n.MVpHL,QOKmt:n[e(7421)]};if(n.GLzKn(n[e(3113)],n[e(3113)])){var c=Object[e(4703)]||function(){function u(){}return function(n){for(var r=_0x7f58,f=i[r(7270)][r(7897)]("|"),A=0;;){switch(f[A++]){case"0":var t;continue;case"1":u[r(10129)]=n;continue;case"2":return t;case"3":t=new u;continue;case"4":u[r(10129)]=null;continue}break}}}(),o={},q=o[e(8364)]={},v=q[e(3085)]=(t={iKnxe:function(u,n){return i[_0x7f58(7178)](u,n)},BovyJ:i[(A=e)(3514)],eoyoH:function(u,n){return i[A(9982)](u,n)},nGXIZ:i[A(7816)],zeljv:i[A(8403)],kcFnB:function(u,n){return i[A(10503)](u,n)},bMkkm:i[A(7444)]},{extend:function(u){var n=A,r={EmOkw:t[n(4215)]};if(t[n(5174)](n(8251),n(8251))){var f=t[n(3681)](c,this);return u&&(t[n(5174)](t[n(831)],t[n(831)])?f.mixIn(u):_0x12b967[_0x3a0130]=_0x4184cf[n(252)](_0x1aaf8f)),(!f.hasOwnProperty(t[n(3329)])||t[n(5174)](this[n(6848)],f[n(6848)]))&&(t.kcFnB(n(5554),t[n(5596)])?t.iKnxe(_0x409bd2,_0x4a546e):f[n(6848)]=function(){var u=n;f[u(4651)][u(6848)][u(6346)](this,arguments)}),f[n(6848)][n(10129)]=f,f.$super=this,f}return r[n(7588)]},create:function(){var u=A,n=this[u(6491)]();return n.init[u(6346)](n,arguments),n},init:function(){},mixIn:function(u){var n=A;for(var r in u){if(i[n(954)]!==i.yoGde)return _0x2cda75[n(9662)][n(8350)](_0x384c25);u.hasOwnProperty(r)&&(this[r]=u[r])}u[n(7423)](i[n(3453)])&&(this.toString=u[n(9965)])},clone:function(){var u=A;return this[u(6848)].prototype[u(6491)](this)}}),b=q[e(8122)]=v[e(6491)]({init:function(u,n){var r=e,f={Drjfw:function(u,n,r){return u(n,r)},rFqSx:function(u,n){return i.rVpJf(u,n)},vPRbK:r(3251),MZSbC:function(u,n){return u(n)},fuWKW:i[r(3197)]};if(i[r(9982)](i[r(5682)],i[r(5682)]))if(u=this[r(7992)]=u||[],i[r(3823)](n,void 0)){if(i[r(10453)]===i[r(8714)])return!1;this[r(7822)]=n}else this.sigBytes=4*u[r(7855)];else _0x184228[r(8018)]=_0x3d0d0e=f[r(5982)](_0x4461da,f[r(3925)](_0x4bb75d,f[r(373)]),f[r(1095)](_0x251f23,f[r(4440)]))},toString:function(u){var n=e;return i[n(9537)](u,a)[n(5614)](this)},concat:function(u){var n=e,r={VsAGW:function(u,n){return i.zIPsS(u,n)}};if(i[n(10503)](n(982),i.APWZl)){var f=this[n(7992)],A=u.words,t=this.sigBytes,c=u[n(7822)];if(this[n(9757)](),i[n(2153)](t,4))if(i[n(10503)](i[n(4029)],"hnQrr"))_0x2191f2(!0,_0x13eab0);else for(var o=0;o>>2],i[n(9937)](24,i.oosgc(o%4,8))),255);f[i.qGmrK(i.MKxHP(t,o),2)]|=i[n(9596)](q,i[n(9937)](24,i[n(8809)](i.hxIHY(i[n(7117)](t,o),4),8)))}else if(i[n(10503)]("FbSSk",n(5228)))_0x3f72c6=!0,_0x503289=_0x19b7ae;else for(o=0;i[n(5201)](o,c);o+=4)i.dVNTb(n(7500),i[n(6874)])?r[n(1024)](_0x33d776,{isPrivate:_0x5d2d9d,browserName:_0xe3a94a}):f[i[n(7117)](t,o)>>>2]=A[i[n(1875)](o,2)];return this[n(7822)]+=c,this}try{i[n(7178)](_0x1077ba,_0xb75cb[n(10009)](_0x306429))}catch(u){i[n(4148)](_0x16c975,u)}},clamp:function(){var u=e,n=this.words,f=this[u(7822)];n[i[u(1875)](f,2)]&=4294967295<<32-f%4*8,n[u(7855)]=r[u(6426)](f/4)},clone:function(){var u=e;if(!i[u(5953)](u(9014),u(9014))){var n=v[u(6429)][u(2210)](this);return n[u(7992)]=this.words[u(781)](0),n}i[u(8104)](_0x7ef9e3,_0x5fe4bb,_0x30a743,_0x5f02ec,_0x288f81)},random:function(u){var n=e,f={YXVYU:function(u,n,r,f){return i[_0x7f58(3064)](u,n,r,f)},wqqmw:function(u,n){return u-n},ZHvhX:function(u,n){return i[_0x7f58(5679)](u,n)},vjEKQ:i[n(6817)],tJvtB:i[n(9700)],kyBfX:function(u,n){return u+n},LNeOU:function(u,n){return i.fwUAy(u,n)},MGASu:function(u,n){return u>>n},kFmYl:function(u,n){return i.ZJccF(u,n)},EsAjn:function(u,n){return u*n},fwmcl:function(u,n){return u&n},BpYwE:function(u,r){return i[n(9715)](u,r)},IKAdH:function(u,r){return i[n(10383)](u,r)},MEaWw:function(u,r){return i[n(5114)](u,r)},oCKlk:function(u,n){return i.IYhjn(u,n)}};if(!i[n(2541)](n(8593),n(7549))){for(var A,t=[],c=function(u){u=u;var n=987654321;return function(){var A=_0x7f58,t={mAEoG:function(u,n){return f[_0x7f58(5786)](u,n)},qzTst:function(u,n){return f[_0x7f58(8478)](u,n)}};if(f[A(1646)]==f[A(1646)])for(var e=f[A(7188)].split("|"),i=0;;){switch(e[i++]){case"0":n=4294967295&f[A(10236)](f[A(944)](36969,65535&n),f[A(1592)](n,16));continue;case"1":c+=.5;continue;case"2":u=f[A(5196)](f[A(7127)](18e3,f.fwmcl(u,65535))+f.BpYwE(u,16),4294967295);continue;case"3":var c=f[A(7712)](f[A(768)](n<<16,u),4294967295);continue;case"4":return f.LNeOU(c,f.oCKlk(r[A(4874)](),.5)?1:-1);case"5":c/=4294967296;continue}break}else _0x4120cb+=t[A(7366)](t[A(9209)](t[A(9209)](_0x4fe6e6,_0x32d457),_0x5e9629),899497514)}},o=0;i[n(5201)](o,u);o+=4)if(i[n(2541)](n(5128),i.maLiT))_0x4575b0.defineProperty(_0x42f0bb,"default",{enumerable:!0,value:_0x2bff8c});else{var q=i[n(6097)](c,4294967296*(A||r.random()));A=i[n(8809)](q(),987654071),t[n(7606)](i[n(745)](4294967296*i[n(7961)](q),0))}return new(b[n(6848)])(t,u)}f[n(7806)](_0x5f2caa,{},"",{})}}),s=o.enc={},a=s[e(2982)]={stringify:function(u){for(var n=e,r=function(u,n){return i[_0x7f58(7204)](u,n)},f=u.words,A=u.sigBytes,t=[],c=0;i[n(2059)](c,A);c++)if(i[n(9982)](n(2221),i.dFaQC))r(_0x1e45da,_0x414473);else{var o=i[n(2402)](f[i[n(903)](c,2)]>>>24-i[n(8809)](i.hxIHY(c,4),8),255);t[n(7606)](i[n(1875)](o,4)[n(9965)](16)),t.push(i[n(10383)](o,15)[n(9965)](16))}return t[n(6309)]("")},parse:function(u){for(var r=e,f=u[r(7855)],A=[],t=0;t>>n},HStKC:function(u,n){return u-n},pWDLl:function(u,n){return u*n},MKuHk:function(u,n){return u%n},iuZNp:function(u,n){return u-n},OQkru:function(u,n){return u+n},Qifsg:f(5733),YaGUo:function(u,n){return u(n)},BfWLb:function(u,n){return u!==n},gEZvM:"pspcm",cXCrL:function(u,n){return u===n},BjFTw:"vKGmj",QroVD:function(u,n,r,f){return u(n,r,f)},tYBml:function(u,n){return u*n},dbfkL:f(1323)};!function(t,e){var i=f;if(typeof r===i(7186))A[i(4373)](A[i(6111)],A.YSoGS)?_0x107c9a(_0x53b5d9[i(10009)](_0x14beb9)):n[i(8018)]=r=A[i(725)](e,A[i(725)](u,i(3251)));else if(typeof define===A[i(7009)]&&define[i(4388)])if(A[i(7776)](A.nyrJi,i(7741)))A[i(9643)](define,[A[i(4729)]],e);else try{_0x615f5d(_0x564fe5[i(6460)](_0x49b65d))}catch(u){A[i(3830)](_0x484b30,u)}else A[i(725)](e,t.CryptoJS)}(this,function(u){var n=f;return function(){var n=_0x7f58,r={uaJcd:function(u,n){return A[_0x7f58(8113)](u,n)},Gcjxw:A.rehHM,WoWGJ:function(u,n){return u|n},tkmse:function(u,n){return u<>>n},owrxv:function(u,n){return A[_0x7f58(8947)](u,n)},QDOaH:function(u,n){return A[_0x7f58(5988)](u,n)},cejgK:function(u,n){return A.MKuHk(u,n)},mJMbr:function(u,n){return A.iuZNp(u,n)},SOadX:function(u,n){return u+n},FnMKd:function(u,n){return A[_0x7f58(8113)](u,n)},qdyuO:function(u,n){return A.OQkru(u,n)},PDRUe:function(u,n){return u>>>n},LrlOa:function(u,n){return u-n},bpILA:function(u,n){return A[_0x7f58(9693)](u,n)},fktid:A.Qifsg,HwafA:function(u,n){return A[_0x7f58(5702)](u,n)},MnfUp:function(u,n){return A[_0x7f58(4947)](u,n)},aQCBQ:A[n(1854)],snEbo:function(u,r){return A[n(8113)](u,r)},LrABv:n(7508),LHtXC:function(u,r){return A[n(6630)](u,r)},gizQu:"DQZit",NNoPR:A[n(4456)],UCFnY:function(u,r,f,t){return A[n(6081)](u,r,f,t)},OJGYG:function(u,r){return A[n(3764)](u,r)},oFJba:function(u,n){return A.iuZNp(u,n)},GBHkt:function(u,n){return u%n},siLQp:function(u,n){return A.fpYYL(u,n)},TOxyO:function(u,n){return u-n},gEOtU:function(u,n){return u-n},WIQFA:function(u,n){return A.tYBml(u,n)}},f=u,t=f.lib[n(8122)];f[n(8963)][n(6396)]={stringify:function(u){for(var f=n,A=f(10109).split("|"),t=0;;){switch(A[t++]){case"0":var e=g[f(9348)](64);continue;case"1":for(var i=0;r[f(4294)](i,w);i+=3)for(var c=r.Gcjxw[f(7897)]("|"),o=0;;){switch(c[o++]){case"0":var q=r[f(5884)](r[f(9557)](v,16),r[f(9557)](a,8))|b;continue;case"1":var v=r[f(6798)](r[f(7960)](x[r[f(7905)](i,2)],r[f(5297)](24,r.QDOaH(r[f(10041)](i,4),8))),255);continue;case"2":var b=r[f(6798)](x[r[f(7960)](i+2,2)]>>>r.mJMbr(24,8*r[f(10041)](r[f(8845)](i,2),4)),255);continue;case"3":for(var s=0;r[f(3747)](s,4)&&r[f(4294)](r[f(2592)](i,.75*s),w);s++)C.push(g.charAt(63&r.PDRUe(q,6*r[f(4124)](3,s))));continue;case"4":var a=r[f(4300)](r[f(7960)](x[i+1>>>2],r[f(4124)](24,r.QDOaH(r[f(10041)](r[f(8845)](i,1),4),8))),255);continue}break}continue;case"2":var x=u[f(7992)];continue;case"3":u.clamp();continue;case"4":return C[f(6309)]("");case"5":var w=u[f(7822)];continue;case"6":var g=this[f(5346)];continue;case"7":if(e)for(;C[f(7855)]%4;)f(5733)===r.fktid?C.push(e):_0x148e3f[f(1407)](_0x148553)[f(781)](0,2e3)[f(7565)](function(u){_0x584254[f(7606)](u)});continue;case"8":var C=[];continue}break}},parse:function(u){var f=n,A={qyQKm:function(u,n){return r.HwafA(u,n)}},t=u[f(7855)],i=this[f(5346)],c=this[f(2188)];if(!c)if(r.MnfUp(r.aQCBQ,"aQKXe")){c=this[f(2188)]=[];for(var o=0;r[f(2215)](o,i.length);o++)c[i[f(252)](o)]=o}else _0x66ce31[f(8018)]=_0x218647=_0x54d48a(_0x234c2f(f(3251)));var q=i[f(9348)](64);if(q)if(r.LrABv!==f(7508))_0x520433[f(8379)]?A[f(4961)](_0x22ccf0,_0x58fe73[f(10292)]):A[f(4961)](_0x25d349,_0x51c81f[f(10292)])[f(591)](_0x48619c,_0x6fc2e4);else{var v=u[f(4579)](q);if(-1!==v){if(r[f(9075)](r.gizQu,r.NNoPR))return _0x52f384[f(4703)](_0x3a5104)[f(7752)](_0x62ca66,_0xa6e5c2);t=v}}return r[f(7947)](e,u,t,c)},_map:A.dbfkL};function e(u,f,A){for(var e=n,i=[],c=0,o=0;r[e(4294)](o,f);o++)if(r[e(1437)](o,4)){var q=A[u.charCodeAt(r[e(1022)](o,1))]<>>n},JihJq:function(u,n){return u%n},bhqUI:function(u,n){return u>>n},uxRyQ:function(u,n){return u-n},tOwQH:f(9230)};!function(t,e){var i=f,c={JMacQ:function(u,n){return u!==n},SggTk:i(6818),lZDtM:function(u,n){return A[i(7e3)](u,n)},EseFQ:A[i(7929)]};if(A.mhLZU(A[i(8339)],A[i(621)]))typeof r===A[i(6923)]?n[i(8018)]=r=A[i(7632)](e,A[i(5949)](u,A.hyOOn)):typeof define===A.mHmuK&&define.amd?A.SMAWb(A[i(810)],"cmpvk")?c[i(7045)](_0x35f32c,c[i(7468)])&&!_0x520eef.prototype[i(7423)][i(2210)](_0x3fcbdb,_0x50c8aa)&&_0x2d377f(_0x18dc1f,_0x589ffb,_0x56c709):A[i(2622)](define,[A[i(8205)]],e):A[i(5949)](e,t.CryptoJS);else if(!c[i(1375)](_0x3405a0,_0x51cfed))throw new _0x20de0e(c.EseFQ)}(this,function(u){var n=f,r={ZOjUb:function(u,n){return A[_0x7f58(1045)](u,n)},xAyGv:A[n(353)],PqjkT:A[n(7001)],skdSx:A[n(8846)],HiFGG:function(u,n){return u>>n},nPXLR:function(u,n){return A.sCgbe(u,n)},tGRfH:function(u,n){return A.KmvBs(u,n)},oLMSz:function(u,n){return A[_0x7f58(10451)](u,n)},ZhrUD:function(u,n){return A.CurgP(u,n)},wBwHt:A[f(545)],BCVMq:A.hFmXw,dLMry:function(u,n){return A[f(9622)](u,n)},VMmPw:function(u,n){return A[f(10125)](u,n)}},e=u,i=e[f(8364)].WordArray,c=e.enc;c[f(475)]=c[f(6757)]={stringify:function(u){for(var n=f,r=u[n(7992)],A=u[n(7822)],e=[],i=0;t[n(6073)](i,A);i+=2){var c=t[n(3410)](t[n(10497)](r[t[n(10497)](i,2)],16-8*t.uBFaY(i,4)),65535);e[n(7606)](String[n(7805)](c))}return e[n(6309)]("")},parse:function(u){for(var n=f,r=u[n(7855)],A=[],e=0;t[n(7478)](e,r);e++)A[t.YKUMF(e,1)]|=t.nPXLR(u.charCodeAt(e),t[n(7187)](16,t[n(8968)](e%2,16)));return i[n(4703)](A,t[n(2467)](r,2))}};function o(u){var n=f,r={QJzGH:t[n(5021)]};return t.BCVMq!==n(3352)?t[n(341)](t[n(6265)](t[n(10149)](u,8),4278255360),16711935&t[n(10497)](u,8)):r.QJzGH}c[f(7793)]={stringify:function(u){var n=f;if(r.ZOjUb(r[n(3694)],r[n(673)]))_0x924193=_0x3d7934[n(6264)][n(7855)];else for(var A=r[n(2042)][n(7897)]("|"),t=0;;){switch(A[t++]){case"0":return e.join("");case"1":var e=[];continue;case"2":for(var i=0;r[n(5912)](i,q);i+=2){var c=r[n(4574)](o,r.xrRbv(r[n(8807)](v[r.AxnOH(i,2)],r[n(4822)](16,i%4*8)),65535));e[n(7606)](String[n(7805)](c))}continue;case"3":var q=u.sigBytes;continue;case"4":var v=u[n(7992)];continue}break}},parse:function(u){var n=f;if(r[n(5715)](r[n(4339)],r.KpvqR)){for(var A=u[n(7855)],t=[],e=0;r[n(9260)](e,A);e++)r[n(10043)](n(9230),r[n(2135)])?t[e>>>1]|=r.onCdG(o,u[n(252)](e)<n},emLmg:f(3655)};!function(t,e){var i=f,c={RsIcc:function(u,n){return A[_0x7f58(7675)](u,n)},yiYZk:function(u,n){return u>n},MIPtX:function(u,n){return u>2]=q,_0x51e8e4+=A[f(2483)](A[f(1958)](_0x2f4918,c,q,_0x476dcc),1),_0x1d5f6e+=4}else r=u.finalize(r);r[f(9757)]();for(var v=this._oKey=r[f(6429)](),b=this[f(7402)]=r[f(6429)](),s=v[f(7992)],a=b.words,x=0;x>>n},rkAuX:function(u,n){return u<>>n},CgtmQ:function(u,n){return u<>>n},xsUpN:function(u,n){return u-n},sRdit:function(u,n){return u!==n},lcFVB:"KLRLj",bWRwV:function(u,n){return u+n},TTaFA:function(u,n){return u>>>n},SgDQg:function(u,n){return u^n},ISIzV:function(u,n){return u+n},HxtUq:function(u,n){return u<>>n},lAaCL:function(u,n){return u+n},bwbHa:function(u,n){return A[_0x7f58(1891)](u,n)},SXrIA:function(u,n){return A[_0x7f58(4997)](u,n)},wDsca:function(u,n){return A.yMzYW(u,n)},pAPDD:function(u,n){return A[_0x7f58(4170)](u,n)},RnQxN:function(u,n){return A.ASlUF(u,n)},SUbOI:function(u,n){return u/n},ZhNld:function(u,n){return A[_0x7f58(988)](u,n)},PHYoS:function(u,n){return A[_0x7f58(7326)](u,n)},OWDqN:function(u,n){return A[_0x7f58(2682)](u,n)},LtljE:n(8509),QPVaW:A[n(8876)],SPhlf:function(u,r){return A[n(5823)](u,r)},znNfA:function(u,r){return A[n(4997)](u,r)},dfCmi:function(u,n){return u|n},PvXHv:function(u,r){return A[n(1992)](u,r)},xmdiG:function(u,r){return A[n(7326)](u,r)},UCJsw:function(u,r){return A[n(5823)](u,r)},BnQXo:function(u,n){return u-n},bfRMG:function(u,n){return u+n},GBuCK:function(u,r){return A[n(8605)](u,r)},zpsGy:function(u,n){return A.oMkaq(u,n)},GRZpQ:function(u,r){return A[n(730)](u,r)},EhFWO:function(u,n){return A.HxtUq(u,n)},KVwri:function(u,r){return A[n(988)](u,r)},vPAWk:function(u,r){return A[n(7326)](u,r)},ggQiV:function(u,r,f,t,e,i,c,o){return A[n(9138)](u,r,f,t,e,i,c,o)},sfdAa:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},mSefk:function(u,n){return A.oMkaq(u,n)},Ffgjs:function(u,n){return u>>n},bnBbe:function(u,r){return A[n(7066)](u,r)},oePkt:function(u,n){return u===n}};return function(f){var A=n,t={tLvpC:A(1115),Focpg:function(u,n){return r[A(952)](u,n)},rRkSO:function(u,n,f,t,e,i,c,o){return r[A(5952)](u,n,f,t,e,i,c,o)},efEye:function(u,n,f,t,e,i,c,o){return r[A(5952)](u,n,f,t,e,i,c,o)},OZVWB:function(u,n){return u+n},mBnWm:function(u,n){return r[A(8312)](u,n)},fcTlP:function(u,n,f,A,t,e,i,c){return r.sfdAa(u,n,f,A,t,e,i,c)},YbQwV:function(u,n){return r[A(8312)](u,n)},HuTnH:function(u,n){return r[A(6804)](u,n)},yMOyb:function(u,n){return u+n},VdiCa:function(u,n){return r[A(1857)](u,n)},KtSsW:function(u,n){return r.XJwPq(u,n)},jiXXL:function(u,n){return r[A(744)](u,n)},UOgYi:function(u,n){return u>>>n},CRPGS:function(u,n){return u|n},vFPEq:function(u,n){return r.KVwri(u,n)},OKqHw:function(u,n,f,t,e,i,c,o){return r[A(9333)](u,n,f,t,e,i,c,o)},tCdbo:function(u,n){return r[A(4641)](u,n)},KWpkh:function(u,n,f,A,t,e,i,c){return r.sfdAa(u,n,f,A,t,e,i,c)},aWoVJ:function(u,n,f,t,e,i,c,o){return r[A(5739)](u,n,f,t,e,i,c,o)},RgcxV:function(u,n){return r[A(599)](u,n)},tyzCE:function(u,n){return u+n},OcRPc:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},mlSzM:function(u,n,f,A,t,e,i,c){return r.zgGpE(u,n,f,A,t,e,i,c)},kleWJ:function(u,n,f,t,e,i,c,o){return r[A(10278)](u,n,f,t,e,i,c,o)},SMFAh:function(u,n,f,t,e,i,c,o){return r[A(5739)](u,n,f,t,e,i,c,o)},zCAvi:function(u,n,f,t,e,i,c,o){return r[A(2286)](u,n,f,t,e,i,c,o)},gWRYm:function(u,n,f,t,e,i,c,o){return r[A(5993)](u,n,f,t,e,i,c,o)},ajMPV:function(u,n,f,A,t,e,i,c){return r.NMBSg(u,n,f,A,t,e,i,c)},jtGaV:function(u,n,f,t,e,i,c,o){return r[A(5739)](u,n,f,t,e,i,c,o)},WlPTr:function(u,n,f,t,e,i,c,o){return r[A(7790)](u,n,f,t,e,i,c,o)},GCiWd:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},PPgVo:function(u,n){return r[A(7613)](u,n)},xBwZH:function(u,n){return r[A(8127)](u,n)},NvxdM:function(u,n){return r[A(10269)](u,n)},gaJzj:function(u,n){return r[A(7281)](u,n)},yGmnv:function(u,n){return r[A(3136)](u,n)},Qxqjc:"EfjEY",YPVCW:function(u,n){return u|n}},e=u,i=e[A(8364)],c=i[A(8122)],o=i.Hasher,q=e[A(329)],v=[];!function(){for(var u=A,n=0;r[u(7086)](n,64);n++)v[n]=r.AYFpM(r[u(6564)](f[u(2842)](f[u(10174)](r[u(4641)](n,1))),4294967296),0)}();var b=q[A(10294)]=o.extend({_doReset:function(){var u=A;this[u(8810)]=new(c[u(6848)])([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(u,n){for(var r=A,f=t[r(9365)].split("|"),e=0;;){switch(f[e++]){case"0":var i=u[t[r(3487)](n,14)];continue;case"1":M=x(M,l,q,N,h,23,v[47]);continue;case"2":l=t.rRkSO(w,l,q,N,M,y,15,v[58]);continue;case"3":var c=u[t[r(3487)](n,0)];continue;case"4":l=w(l,q,N,M,K,15,v[54]);continue;case"5":var o=u[n+13];continue;case"6":M=t[r(2403)](w,M,l,q,N,o,21,v[59]);continue;case"7":N=t[r(2403)](s,N,M,l,q,z,7,v[8]);continue;case"8":M=t[r(5671)](a,M,l,q,N,b,20,v[23]);continue;case"9":var q=L[3];continue;case"10":q=t[r(2403)](s,q,N,M,l,j,12,v[1]);continue;case"11":var b=u[t[r(3487)](n,4)];continue;case"12":l=t[r(5671)](x,l,q,N,M,C,16,v[34]);continue;case"13":var g=u[t.OZVWB(n,7)];continue;case"14":var C=u[t[r(2713)](n,11)];continue;case"15":l=t[r(2403)](a,l,q,N,M,_,14,v[22]);continue;case"16":l=t.rRkSO(x,l,q,N,M,_,16,v[46]);continue;case"17":q=t[r(596)](s,q,N,M,l,Q,12,v[9]);continue;case"18":var B=u[n+5];continue;case"19":q=t[r(2403)](w,q,N,M,l,m,10,v[53]);continue;case"20":N=t[r(2403)](s,N,M,l,q,c,7,v[0]);continue;case"21":l=t[r(596)](s,l,q,N,M,K,17,v[10]);continue;case"22":var D=u[t[r(2812)](n,12)];continue;case"23":M=a(M,l,q,N,c,20,v[19]);continue;case"24":N=t[r(5671)](x,N,M,l,q,o,4,v[40]);continue;case"25":N=a(N,M,l,q,j,5,v[16]);continue;case"26":q=t.efEye(x,q,N,M,l,b,11,v[37]);continue;case"27":l=t[r(2403)](a,l,q,N,M,C,14,v[18]);continue;case"28":M=t[r(5671)](s,M,l,q,N,g,22,v[7]);continue;case"29":M=t[r(5671)](s,M,l,q,N,m,22,v[3]);continue;case"30":var L=this._hash[r(7992)];continue;case"31":var z=u[t[r(3487)](n,8)];continue;case"32":L[0]=t[r(1943)](t[r(2812)](L[0],N),0);continue;case"33":q=w(q,N,M,l,g,10,v[49]);continue;case"34":L[1]=0|t.yMOyb(L[1],M);continue;case"35":N=a(N,M,l,q,Q,5,v[24]);continue;case"36":L[2]=L[2]+l|0;continue;case"37":q=t.rRkSO(a,q,N,M,l,K,9,v[21]);continue;case"38":for(var E=0;t[r(9081)](E,16);E++){var d=t[r(2713)](n,E),I=u[d];u[d]=t[r(3192)](t[r(7329)](I,8)|t[r(3623)](I,24),16711935)|4278255360&t[r(8190)](I<<24,t[r(5037)](I,8))}continue;case"39":l=t[r(8065)](a,l,q,N,M,m,14,v[26]);continue;case"40":var j=u[t[r(4889)](n,1)];continue;case"41":var K=u[t[r(2713)](n,10)];continue;case"42":l=t[r(6441)](s,l,q,N,M,y,17,v[6]);continue;case"43":N=t[r(5401)](s,N,M,l,q,b,7,v[4]);continue;case"44":L[3]=t[r(9827)](L[3]+q,0);continue;case"45":M=t[r(5401)](x,M,l,q,N,y,23,v[43]);continue;case"46":var y=u[t[r(255)](n,6)];continue;case"47":q=a(q,N,M,l,y,9,v[17]);continue;case"48":q=x(q,N,M,l,c,11,v[41]);continue;case"49":q=t[r(5763)](w,q,N,M,l,_,10,v[57]);continue;case"50":q=t[r(596)](a,q,N,M,l,i,9,v[25]);continue;case"51":q=t[r(5296)](s,q,N,M,l,B,12,v[5]);continue;case"52":N=t.efEye(w,N,M,l,q,D,6,v[52]);continue;case"53":N=t[r(596)](w,N,M,l,q,z,6,v[56]);continue;case"54":var h=u[t[r(9093)](n,2)];continue;case"55":var _=u[n+15];continue;case"56":var Q=u[n+9];continue;case"57":N=t[r(8065)](x,N,M,l,q,Q,4,v[44]);continue;case"58":M=t[r(5671)](w,M,l,q,N,j,21,v[55]);continue;case"59":N=t.rRkSO(w,N,M,l,q,c,6,v[48]);continue;case"60":l=t[r(8065)](w,l,q,N,M,h,15,v[62]);continue;case"61":N=w(N,M,l,q,b,6,v[60]);continue;case"62":N=a(N,M,l,q,o,5,v[28]);continue;case"63":M=t.kleWJ(s,M,l,q,N,_,22,v[15]);continue;case"64":q=t.efEye(x,q,N,M,l,z,11,v[33]);continue;case"65":N=t.kleWJ(s,N,M,l,q,D,7,v[12]);continue;case"66":q=a(q,N,M,l,h,9,v[29]);continue;case"67":var N=L[0];continue;case"68":N=x(N,M,l,q,j,4,v[36]);continue;case"69":M=t.SMFAh(x,M,l,q,N,K,23,v[39]);continue;case"70":M=a(M,l,q,N,z,20,v[27]);continue;case"71":l=t[r(8462)](x,l,q,N,M,g,16,v[38]);continue;case"72":l=s(l,q,N,M,i,17,v[14]);continue;case"73":l=w(l,q,N,M,i,15,v[50]);continue;case"74":N=t[r(4982)](a,N,M,l,q,B,5,v[20]);continue;case"75":M=t[r(5907)](w,M,l,q,N,B,21,v[51]);continue;case"76":var M=L[1];continue;case"77":q=w(q,N,M,l,C,10,v[61]);continue;case"78":M=t[r(4146)](a,M,l,q,N,D,20,v[31]);continue;case"79":l=t[r(6356)](a,l,q,N,M,g,14,v[30]);continue;case"80":q=s(q,N,M,l,o,12,v[13]);continue;case"81":q=t[r(5843)](x,q,N,M,l,D,11,v[45]);continue;case"82":M=x(M,l,q,N,i,23,v[35]);continue;case"83":l=t[r(1171)](s,l,q,N,M,h,17,v[2]);continue;case"84":M=w(M,l,q,N,Q,21,v[63]);continue;case"85":var l=L[2];continue;case"86":N=x(N,M,l,q,B,4,v[32]);continue;case"87":M=t.WlPTr(s,M,l,q,N,C,22,v[11]);continue;case"88":var m=u[t[r(8417)](n,3)];continue;case"89":l=t[r(5907)](x,l,q,N,M,m,16,v[42]);continue}break}},_doFinalize:function(){for(var u=A,n="11|9|2|1|12|10|5|4|7|6|13|14|0|3|8".split("|"),t=0;;){switch(n[t++]){case"0":var e=x[u(7992)];continue;case"1":var i=r[u(6564)](a[u(7822)],8);continue;case"2":var c=r[u(8915)](this._nDataBytes,8);continue;case"3":for(var o=0;o<4;o++){var q=e[o];e[o]=r[u(4588)](r[u(10485)](q,8)|r[u(5364)](q,24),16711935)|4278255360&(r.YaZJF(q,24)|r.aqxIn(q,8))}continue;case"4":b[r.rojIi(r[u(5364)](r[u(8209)](i,64),9),4)+15]=r[u(7688)](r[u(1754)](r[u(9306)](r[u(5069)](s,8),s>>>24),16711935),4278255360&r[u(9306)](s<<24,r[u(4340)](s,8)));continue;case"5":var v=c;continue;case"6":a.sigBytes=r[u(8915)](r[u(952)](b[u(7855)],1),4);continue;case"7":b[14+(r.KpCov(i+64,9)<<4)]=r.bwbHa(r.SXrIA(r[u(3624)](v,8),r[u(4340)](v,24)),16711935)|4278255360&(r[u(770)](v,24)|r[u(9202)](v,8));continue;case"8":return x;case"9":var b=a[u(7992)];continue;case"10":var s=f[u(4727)](r.SUbOI(c,4294967296));continue;case"11":var a=this[u(4269)];continue;case"12":b[r[u(8265)](i,5)]|=r.pAPDD(128,r[u(2971)](24,i%32));continue;case"13":this[u(3595)]();continue;case"14":var x=this._hash;continue}break}},clone:function(){var u=A;if(r[u(6962)](r[u(3034)],r[u(10093)])){var n=o.clone[u(2210)](this);return n[u(8810)]=this[u(8810)][u(6429)](),n}_0x452133[u(2525)]()}});function s(u,n,f,t,e,i,c){var o=A,q=r[o(3963)](u+r[o(1525)](n&f,r[o(4588)](~n,t))+e,c);return r[o(599)](r[o(3624)](q,i),r.PvXHv(q,r.xmdiG(32,i)))+n}function a(u,n,r,f,e,i,c){var o=A;if(!t.yGmnv(t[o(9103)],o(7544))){var q=t.yMOyb(t[o(8417)](u,n&f|t[o(9556)](r,~f)),e)+c;return t[o(2812)](t[o(8920)](t[o(3834)](q,i),t[o(3623)](q,32-i)),n)}var v=t[o(9556)](t[o(8137)](this[o(2906)],_0x27c305)^this[o(8009)],_0x2597a2);this[o(8009)]^=v,this._rBlock^=t[o(3834)](v,_0x40e38f)}function x(u,n,f,t,e,i,c){var o=A,q=r.UCJsw(r[o(952)](u+(n^f^t),e),c);return r[o(8209)](r[o(599)](r[o(5853)](q,i),r[o(4340)](q,r.BnQXo(32,i))),n)}function w(u,n,f,t,e,i,c){var o=A,q=r.bfRMG(r[o(4641)](u,r.GBuCK(f,r[o(6625)](n,~t)))+e,c);return r[o(8312)](r[o(1525)](r[o(3797)](q,i),r.KVwri(q,r[o(2003)](32,i))),n)}e[A(10294)]=o._createHelper(b),e[A(2918)]=o[A(2281)](b)}(Math),u[n(10294)]})},{"./core":4}],14:[function(u,n,r){var f,A,t,e=_0x7f58,i={nJIDg:e(7186),hzmlk:function(u,n,r){return u(n,r)},ArOna:function(u,n){return u(n)},mFJCT:e(3251),sLMba:e(2666),bhqOy:function(u,n){return u===n},BarjW:e(4261),bODOs:e(5578),IabzS:e(357),EXFGi:function(u,n){return u!==n},GhESy:e(6250),GGaLA:function(u,n){return u>n},vbauw:function(u,n){return u&n},qeOVU:function(u,n){return u===n},xENZz:f(9069),wLNcy:function(u,n){return u!==n},wrzwF:f(4774),DiviC:"LUaJv",wmBhT:f(9264),FnTOl:function(u,n){return u<>16&255,e=r[n(7232)](r[n(9839)](u,8),255),i=r.btcnm(u,255);if(r[n(3260)](t,255))if(r[n(5444)](n(7876),r[n(3492)]))_0x5c83ca[n(7606)](_0x18dc23);else if(t=0,255===e){if(!r.YbDND(r[n(5062)],r[n(337)]))return A[n(10431)](A[n(2071)](_0x30706a,~_0x118208),_0x29aff3);e=0,255===i?i=0:++i}else++e;else r[n(8806)](n(9264),r.kJmDU)?_0x3f2acf[n(2210)](this):++t;u=0,u+=r[n(968)](t,16),u+=r[n(968)](e,8),u+=i}else{if(!r.aBTYK(r.koFEY,r[n(9028)]))return _0x42769d[n(5325)];u+=1<<24}return u}function i(u){var n=f;if(A[n(8389)]!==n(1568))return A[n(1412)](u[0]=e(u[0]),0)&&(u[1]=A[n(2680)](e,u[1])),u;_0x3b2098=_0x30a2af}var c=t.Encryptor=t[f(6491)]({processBlock:function(u,n){var A=f,t=this._cipher,e=t[A(2315)],c=this[A(1545)],o=this[A(9073)];if(c){if(r[A(6417)]===r[A(3053)])return"/";o=this[A(9073)]=c[A(781)](0),this[A(1545)]=void 0}r.RStYv(i,o);var q=o.slice(0);t.encryptBlock(q,0);for(var v=0;r.pmJKe(v,e);v++)u[r[A(3438)](n,v)]^=q[v]}});return t[f(4805)]=c,t}(),u[n(5322)].CTRGladman})},{"./cipher-core":3,"./core":4}],16:[function(u,n,r){var f,A,t,e,i=_0x7f58,c={ePCQV:function(u,n,r){return u(n,r)},vvWdY:i(3251),xsxZF:i(2666),hWSqI:function(u,n){return u===n},iZTek:function(u,n){return u===n},hMvLn:i(7186),grdSu:function(u,n){return u(n)},KLhIA:i(4261),nkOGH:i(7859),WGqml:function(u,n,r){return u(n,r)},igJYB:i(8143),YMqqu:"uRsLX",TNhHo:function(u,n){return u!==n},nSiYG:i(10322),eaKRi:function(u,n){return u|n},GCliF:function(u,n){return u+n},jBUqQ:function(u,n){return u-n},MiMso:function(u,n){return u>>n}};!function(t,e,i){var c=f,o={OrSlS:function(u,n){return A[_0x7f58(7061)](u,n)}};if(A[c(9872)](A[c(2729)],A[c(2729)])){o[c(8866)](_0xc0df57,_0x5cbf1c);const u=_0x15de05(_0x76a188,_0x2c06e4);return _0x4a34af[_0x3fbad8].includes(u)}typeof r===A[c(6858)]?n[c(8018)]=r=A[c(9148)](e,A.nFoFA(u,c(3251)),u(A[c(2611)])):typeof define===A[c(7430)]&&define[c(4388)]?A.lNtbt(define,[A[c(2028)],A[c(2611)]],e):A[c(2817)](e,t[c(3080)])}(this,function(u){var n=f;return u[n(4128)].AnsiX923={pad:function(u,r){for(var f=n,t=A[f(872)][f(7897)]("|"),e=0;;){switch(t[e++]){case"0":u[f(9757)]();continue;case"1":var i=A[f(7901)](c,A[f(2229)](o,c));continue;case"2":var c=A[f(6286)](r,4);continue;case"3":u[f(7992)][q>>>2]|=A[f(2650)](i,24-A.BIyJG(A.DqzLi(q,4),8));continue;case"4":u[f(7822)]+=i;continue;case"5":var o=u[f(7822)];continue;case"6":var q=A.vqeHQ(o+i,1);continue}break}},unpad:function(u){var r=n,f=255&u[r(7992)][A[r(868)](A.vqeHQ(u[r(7822)],1),2)];u[r(7822)]-=f}},u[n(4128)][n(4586)]})},{"./cipher-core":3,"./core":4}],20:[function(u,n,r){var f=_0x7f58,A={YiRln:function(u,n){return u===n},pHDEX:f(7186),WJjKu:function(u,n){return u!==n},Zggnu:f(6458),BPpnq:function(u,n){return u(n)},fGDFa:"./core",CMzzz:function(u,n){return u(n)},WhTUZ:"function",pcqIL:function(u,n,r){return u(n,r)},iMebi:function(u,n){return u===n},pZmCc:f(6789),xNkxR:"CykWS",DohhW:function(u,n){return u*n},dYJQk:function(u,n){return u%n},JsfFf:function(u,n){return u-n},FEOYR:function(u,n){return u<>>n},JXxUC:function(u,n){return u-n}};!function(t,e,i){var c=f;if(A[c(7530)](typeof r,A[c(1410)])){if(A.WJjKu(A[c(1783)],c(738)))n[c(8018)]=r=e(A[c(8353)](u,A.fGDFa),A[c(6961)](u,c(2666)));else if(_0x5bf0b9[c(2210)](_0x2ba96a,_0x3ef44e))_0x1d5755[c(10292)]=_0x37198b[_0x1534a2],_0x457760[c(8379)]=!1,_0xd29bb1}else if(A[c(7530)](typeof define,A.WhTUZ)&&define[c(4388)])A[c(8497)](define,[A.fGDFa,c(2666)],e);else if(A[c(552)](A[c(4932)],A[c(9544)])){if(!(_0x37b3b7 instanceof _0x2db3fb))throw new _0x515463(c(10354))}else A[c(8353)](e,t[c(3080)])}(this,function(u){var n=f;return u[n(4128)][n(7460)]={pad:function(r,f){var t=n,e=A.DohhW(f,4),i=e-A[t(5869)](r[t(7822)],e);r[t(4189)](u[t(8364)][t(8122)][t(4874)](A[t(10065)](i,1)))[t(4189)](u.lib.WordArray[t(4703)]([A[t(9215)](i,24)],1))},unpad:function(u){var r=n,f=255&u[r(7992)][A.mJxAF(A[r(1416)](u.sigBytes,1),2)];u[r(7822)]-=f}},u[n(4128)][n(7460)]})},{"./cipher-core":3,"./core":4}],21:[function(u,n,r){var f=_0x7f58,A={xyUjy:f(1684),UuHWa:function(u,n){return u===n},NdvKt:function(u,n){return u!==n},TjVHc:f(5029),yysAh:function(u,n,r){return u(n,r)},qqlqK:function(u,n){return u(n)},mGNpx:f(3251),LXBwu:function(u,n){return u===n},OyVjV:"function",GHVlV:function(u,n){return u!==n},UTpth:f(8568),LTdwn:function(u,n,r){return u(n,r)},ktGMI:f(2666),wuldh:function(u,n){return u(n)},XsvFt:function(u,n){return u%n},LzCsb:f(3954)};!function(t,e,i){var c=f,o={LtKiD:A[c(5612)]};if(A[c(6960)](typeof r,c(7186))){if(!A[c(4078)](A[c(3296)],"ZJSfX"))return _0x5b8e6c&&_0x271180.__esModule?_0x27d200:{default:_0x21e302};n[c(8018)]=r=A[c(6213)](e,A[c(1092)](u,A[c(5693)]),A[c(1092)](u,c(2666)))}else if(A[c(9705)](typeof define,A.OyVjV)&&define[c(4388)]){if(!A[c(9600)](A[c(7537)],c(407)))return o[c(7234)];A[c(7860)](define,[A[c(5693)],A[c(9412)]],e)}else e(t[c(3080)])}(this,function(u){var n=f,r={KQpIx:function(u,n){return A[_0x7f58(4367)](u,n)},UnVHh:n(10015),NQVuT:function(u,r){return A[n(6143)](u,r)},lkGoy:function(u,n){return u===n},iEsuE:A[n(4293)]};return u[n(4128)][n(3043)]={pad:function(f,A){var t=n;r[t(6807)]!=r[t(6807)]?r[t(7080)](_0x1d7a1c,_0x2b4201[t(6460)](_0x56e7aa)):(f[t(4189)](u.lib[t(8122)][t(4703)]([2147483648],1)),u[t(4128)][t(4381)][t(4128)](f,A))},unpad:function(f){var A=n;r[A(4720)](r[A(7149)],r[A(7149)])?(u[A(4128)].ZeroPadding[A(4196)](f),f[A(7822)]--):_0x39fb4e[A(3351)]=_0x497cc7=r[A(6958)](++_0x53a9f0,2)}},u[n(4128)][n(3043)]})},{"./cipher-core":3,"./core":4}],22:[function(u,n,r){var f=_0x7f58,A={YqvPy:function(u,n){return u(n)},IJcMK:function(u,n,r){return u(n,r)},APQpU:f(3251),wTBln:function(u,n){return u!==n},KmxeJ:f(2490),gHafN:function(u,n){return u===n},NsVOh:f(7186),DNJmR:function(u,n){return u===n},ImiuF:function(u,n,r){return u(n,r)},fWiFs:"function",rjQXM:function(u,n,r){return u(n,r)},UZJUI:"./cipher-core",opPPo:f(9862),vrgZc:f(9385)};!function(t,e,i){var c=f;if(A[c(2557)](A[c(6291)],"nxAxV")){var o=_0x513415[c(8333)](_0x34b4cd);A[c(4736)](_0x27987b,o)}else A[c(8954)](typeof r,A.NsVOh)?A.DNJmR("Tzoxc",c(5522))?n[c(8018)]=r=A.ImiuF(e,A.YqvPy(u,A[c(5398)]),A.YqvPy(u,c(2666))):_0x4b9e16[c(8018)]=_0x2421b8=A[c(8833)](_0x3e1475,_0x286c6a(A[c(5398)]),_0x28f05b(c(3917))):typeof define===A.fWiFs&&define[c(4388)]?A[c(9550)](define,[A.APQpU,A[c(3256)]],e):A[c(5329)]!==A[c(3979)]?A[c(4736)](e,t[c(3080)]):(_0x442dc2=!0,_0x4aae7c=_0x239081[c(9180)],_0x12f807=null)}(this,function(u){var n=f;return u[n(4128)][n(7226)]={pad:function(){},unpad:function(){}},u[n(4128)][n(7226)]})},{"./cipher-core":3,"./core":4}],23:[function(u,n,r){var f=_0x7f58,A={OOeYB:f(10514),KZOsT:function(u,n){return u===n},YjGRT:f(7186),bUrNv:function(u,n,r){return u(n,r)},bWmNe:"./core",GAaki:function(u,n){return u(n)},cIUbq:f(2666),SoKrU:function(u,n,r){return u(n,r)},rCJmW:function(u,n){return u(n)},AsLcw:function(u,n){return u!==n}};!function(t,e,i){var c=f;if(A[c(3812)]!=A[c(3812)])throw _0x4145fc;A[c(4942)](typeof r,A[c(4375)])?n[c(8018)]=r=A[c(6861)](e,u(A[c(7298)]),A[c(5117)](u,A[c(9301)])):A.KZOsT(typeof define,c(4261))&&define[c(4388)]?A[c(3149)](define,[c(3251),A.cIUbq],e):A.rCJmW(e,t[c(3080)])}(this,function(u){var n=f;if(!A[n(1282)]("bujmD",n(7409)))return u[n(4128)][n(446)];_0x3c1b67=!0,_0x3e0e6a=_0x3e5a03})},{"./cipher-core":3,"./core":4}],24:[function(u,n,r){var f=_0x7f58,A={loaBf:f(3773),cxZAl:function(u,n){return u+n},iyslA:function(u,n){return u!==n},OCzRs:f(5066),DdrVV:function(u,n){return u===n},AxNZZ:function(u,n){return u===n},UuwTv:f(7379),uRlao:function(u,n,r){return u(n,r)},RuhBY:function(u,n){return u(n)},HlniD:f(3251),GFDYS:f(2666),RKjzs:function(u,n){return u===n},NChtP:f(919),PbNlq:function(u,n,r){return u(n,r)},CsQzg:function(u,n,r){return u(n,r)},hvhgv:function(u,n){return u-n},iJNHH:function(u,n){return u%n},NzGbG:function(u,n){return u&n}};!function(t,e,i){var c=f,o={NkSEx:function(u,n){return A[_0x7f58(3886)](u,n)}};if(A[c(3636)](A.OCzRs,c(5066)))_0x59fbfc[o[c(10414)](_0x554d58,5*_0xe335a)]=o.NkSEx(_0x2ac76c,o.NkSEx(2*_0x166f12,3*_0x210e0f)%5*5);else if(A.DdrVV(typeof r,"object"))A[c(3270)](A[c(4073)],A[c(4073)])?n[c(8018)]=r=A.uRlao(e,A.RuhBY(u,A[c(6536)]),A[c(10178)](u,A[c(1800)])):_0x5056be=new _0x2c8a32(_0x568e1f);else if(typeof define===c(4261)&&define.amd){if(!A[c(6811)](A[c(7405)],A[c(7405)]))throw new _0x204bea(A.loaBf);A.PbNlq(define,["./core",A[c(1800)]],e)}else e(t[c(3080)])}(this,function(u){var n=f,r={xyvJX:function(u,n,r){return A[_0x7f58(9164)](u,n,r)},dbUbq:function(u,n){return A[_0x7f58(3636)](u,n)},zLqHG:n(1167),RezPc:function(u,n){return u*n},hhher:function(u,r){return A[n(3626)](u,r)},SiwWs:function(u,r){return A[n(3287)](u,r)},Xmtwm:function(u,n){return A.hvhgv(u,n)},zTNqk:function(u,r){return A[n(9373)](u,r)},dXQMC:function(u,n){return u>>>n},siwgR:function(u,r){return A[n(3886)](u,r)}};return u.pad.ZeroPadding={pad:function(u,f){var A=n,t={Paamo:function(u,n){return u(n)},OHIWw:function(u,n){return u!==n},ciIgi:A(2841),UPwNM:function(u,n,f){return r[A(7780)](u,n,f)}};if(r.dbUbq(r[A(2989)],A(4103))){var e=r.RezPc(f,4);u[A(9757)](),u[A(7822)]+=r.hhher(e,r[A(10274)](u[A(7822)],e)||e)}else{var i={cvzSk:function(u,n){return t[A(4113)](u,n)}};t[A(7085)](typeof _0x2dc6e9[A(10525)][A(9483)],t.ciIgi)?_0x19fa7b():t[A(4285)](_0x449895,function(){return i[A(3268)](_0x253571,_0x4a4a62+1)},_0x288119)}},unpad:function(u){for(var f=n,A=u[f(7992)],t=r[f(10147)](u.sigBytes,1);!r[f(10107)](r[f(5601)](A[r.dXQMC(t,2)],r[f(7815)](24,r[f(1810)](r.SiwWs(t,4),8))),255);)t--;u[f(7822)]=r[f(263)](t,1)}},u[n(4128)][n(4381)]})},{"./cipher-core":3,"./core":4}],25:[function(u,n,r){var f,A,t,e=_0x7f58,i={aLJGE:function(u,n){return u+n},cBisX:"object",CxRYg:function(u,n,r,f){return u(n,r,f)},vppJr:function(u,n){return u(n)},cNwUP:"./core",EwEwJ:e(4632),ueIIO:"./hmac",OiHHX:e(4261),rWJCI:function(u,n,r){return u(n,r)},CVhFB:function(u,n){return u!==n},fOqae:e(9670),epDUx:function(u,n){return u(n)},jaBHo:function(u,n){return u(n)},iDbXn:function(u,n){return u instanceof n},JDWJV:e(4873),Ugqdi:"fsABA",ZAvuY:e(9672),gGkVX:function(u,n){return u>>n},WNAnR:function(u,n){return u<>>n},qCXpx:function(u,n){return u<>>n},YYqdb:function(u,n){return u|n},DLrRK:function(u,n){return u>>>n},qWqtu:function(u,n){return u>>>n},wuSYj:function(u,n){return u&n},eOwJK:function(u,n){return u&n},ryXmD:function(u,n){return u|n},iznaP:function(u,n){return u&n},FAioo:function(u,n){return u<>>n},jhPpz:function(u,n){return u+n},pYFQa:function(u,n){return u>>n},qJkTy:function(u,n){return u+n},wMyuM:function(u,n){return u|n},kQgRO:function(u,n){return u+n},CsKDP:function(u,n){return u>>>n},ThGer:"neqbn",bHsyq:f(5519),acwkN:function(u,n){return u+n},MiyWU:function(u,n){return u*n},lNCaE:function(u,n){return u^n},FCjKp:function(u,n){return u>>>n},EaoGM:function(u,n){return u<>>n},IJGAN:function(u,n){return u+n}};!function(t,e,i){var c=f,o={Zrjvl:function(u,n){return A.TiqoB(u,n)}};if(A.moihM(A[c(9437)],A[c(8749)]))if(A.KTWms(typeof r,A[c(5286)]))n[c(8018)]=r=A[c(7557)](e,u("./core"),A[c(8933)](u,A[c(2633)]),A[c(8046)](u,A[c(7798)]),A[c(9885)](u,A[c(2237)]),u(A[c(1190)]));else if(typeof define===A[c(9647)]&&define[c(4388)])if(A[c(5480)](c(5542),A[c(1543)]))for(var q=A[c(4817)].split("|"),v=0;;){switch(q[v++]){case"0":_0x404027[A[c(9553)]]&&(_0x5ed57a=_0x1d1869[A[c(9553)]]);continue;case"1":_0x3c8683[A.YoSPc]&&(_0x2e8276=_0x4ffadc[A[c(2449)]]);continue;case"2":_0xcc8e74[A.ldbio]&&(_0x347cad=_0x514a91[A[c(5068)]]);continue;case"3":_0x1da704[c(6915)]&&(_0x55d7aa=_0x3cbac1[c(6915)]);continue;case"4":_0x15f3a4[A[c(442)]]&&(_0x1e8dd6=_0x2dc623[c(7076)]);continue;case"5":_0x4c3e4f[A[c(7407)]]&&(_0x48975a=_0x70765e[A[c(7407)]]);continue}break}else A[c(3608)](define,[A[c(9395)],c(7470),"./md5",A.OKEXi,A[c(1190)]],e);else A[c(8933)](e,t.CryptoJS);else o[c(10471)](_0x93ac1b,_0x41f9c8)}(this,function(u){var n=f,r={VOIyu:function(u,n){return A.sIqIP(u,n)},sTZLo:n(8729),WWDzn:function(u,n){return A.ncKZp(u,n)},suHyO:function(u,r){return A[n(2754)](u,r)},dTvpU:function(u,r){return A[n(4730)](u,r)},uZUWS:function(u,r){return A[n(7570)](u,r)},lCDpb:function(u,r){return A[n(3316)](u,r)},OMmLR:function(u,n){return A.qWqtu(u,n)},lihzC:function(u,n){return u&n},eqasN:function(u,r){return A[n(4407)](u,r)},mDVoK:function(u,n){return A.wuSYj(u,n)},tUPMG:function(u,r){return A[n(9992)](u,r)},EFTEh:function(u,r){return A[n(4730)](u,r)},ZPrOd:function(u,r){return A[n(4730)](u,r)},EVEgE:function(u,r){return A[n(8485)](u,r)},jfItb:function(u,r){return A[n(6829)](u,r)},bIrZZ:function(u,r){return A[n(1180)](u,r)},PgRyj:function(u,r){return A[n(5111)](u,r)},NvrTB:function(u,r){return A[n(4407)](u,r)},XsJPR:function(u,n){return A.iznaP(u,n)},bBzHR:function(u,n){return A.qCXpx(u,n)},fTBWq:function(u,r){return A[n(2754)](u,r)},zimeE:function(u,n){return u>>n},oQyrT:function(u,n){return A.DwcXf(u,n)},ROSvO:function(u,r){return A[n(6596)](u,r)},Vetrv:function(u,r){return A[n(7570)](u,r)},hRBFj:function(u,r){return A[n(2092)](u,r)},dyQft:function(u,r){return A[n(10105)](u,r)},iHtZy:function(u,r){return A[n(7148)](u,r)},ushhP:function(u,r){return A[n(7148)](u,r)},hzuhA:function(u,r){return A[n(8436)](u,r)},gEfZN:function(u,n){return A.CsKDP(u,n)},DsrZR:function(u,n){return u>>n},MHZqF:function(u,n){return u+n},hqHbd:function(u,r){return A[n(7456)](u,r)},ebBsR:function(u,n){return A.nFDYF(u,n)},YaAzv:function(u,r){return A[n(8037)](u,r)},FkrmW:function(u,n){return u<>>n}};return function(){var f=n,t={SjXro:function(u,n){return A.TuQxW(u,n)},jnpcB:A[f(6185)],beDPh:function(u,n){return A[f(9296)](u,n)},KxOZg:A[f(8935)],IAMKp:A[f(3752)],rWBkg:function(u,n){return A[f(598)](u,n)},pwbHi:function(u,n){return A.LfdLq(u,n)},lTBSt:function(u,n){return A[f(4065)](u,n)},RaQCE:function(u,n){return A.pryDA(u,n)},NqUHe:function(u,n){return A[f(4407)](u,n)},Jezun:function(u,n){return A[f(4065)](u,n)},zZuBg:function(u,n){return A[f(7927)](u,n)},ggPgs:function(u,n){return A[f(1711)](u,n)},SOAKs:function(u,n){return A[f(9992)](u,n)},JQmuU:function(u,n){return A.ncKZp(u,n)},FYcVe:function(u,n){return A[f(4991)](u,n)},JDSCv:function(u,n){return A.SngWt(u,n)},dedal:function(u,n){return A[f(8485)](u,n)},WPgNk:function(u,n){return A[f(6596)](u,n)},wnHeg:function(u,n){return A[f(9554)](u,n)}},e=u,i=e[f(8364)][f(2832)],c=e[f(329)],o=[],q=[],v=[],b=c[f(8929)]=i[f(6491)]({_doReset:function(){var u=f,n={VnhTT:function(u,n){return r[_0x7f58(2052)](u,n)}};if("QGsdf"===r[u(4361)])return _0x174c69 instanceof _0x2675b2?_0x5acf2b:new _0x454c01(function(r){n[u(4093)](r,_0x13f76a)});for(var A=u(6008)[u(7897)]("|"),t=0;;){switch(A[t++]){case"0":var e=this._C=[r[u(7335)](B[2]<<16,r[u(8208)](B[2],16)),r[u(7335)](r.dTvpU(B[0],4294901760),r[u(6261)](B[1],65535)),r[u(1093)](B[3]<<16,r[u(7716)](B[3],16)),4294901760&B[1]|65535&B[2],r[u(7335)](B[0]<<16,r[u(5683)](B[0],16)),r[u(6463)](B[2],4294901760)|r[u(6463)](B[3],65535),r[u(1093)](B[1]<<16,r.eqasN(B[1],16)),r.mDVoK(B[3],4294901760)|r[u(6261)](B[0],65535)];continue;case"1":if(C)for(var i=u(2346)[u(7897)]("|"),c=0;;){switch(i[c++]){case"0":var o=r[u(3417)](w,16)|r.EFTEh(q,65535);continue;case"1":var q=r[u(1093)](r[u(558)](r[u(4634)](r.tUPMG(b,8),b>>>24),16711935),r[u(6936)](b<<24|r[u(489)](b,8),4278255360));continue;case"2":e[1]^=a;continue;case"3":var v=C.words;continue;case"4":e[2]^=w;continue;case"5":e[7]^=o;continue;case"6":e[5]^=a;continue;case"7":e[3]^=o;continue;case"8":var b=v[0];continue;case"9":var a=r.uZUWS(r[u(2586)](q,16),4294901760&w);continue;case"10":var x=v[1];continue;case"11":var w=r.EVEgE(16711935&r[u(6922)](r[u(3417)](x,8),r[u(8212)](x,24)),r.XsJPR(r[u(9079)](x,24)|r.fTBWq(x,8),4278255360));continue;case"12":e[6]^=w;continue;case"13":for(var g=0;g<4;g++)s[u(2210)](this);continue;case"14":e[4]^=q;continue;case"15":e[0]^=q;continue}break}continue;case"2":var C=this.cfg.iv;continue;case"3":for(g=0;r[u(7517)](g,8);g++)e[g]^=D[g+4&7];continue;case"4":var B=this._key.words;continue;case"5":for(g=0;r.zimeE(g,4);g++)s[u(2210)](this);continue;case"6":this._b=0;continue;case"7":var D=this._X=[B[0],r[u(1093)](r[u(1028)](B[3],16),r[u(8212)](B[2],16)),B[1],r[u(7335)](B[0]<<16,r.suHyO(B[3],16)),B[2],r.nBssW(B[1],16)|r[u(7716)](B[0],16),B[3],r.cqZUk(r.pwktM(B[2],16),r[u(4573)](B[1],16))];continue}break}},_doProcessBlock:function(u,n){var r=f;if(t[r(8891)](t[r(508)],r(3499))){t.SjXro(_0x134f83,_0x24e388)&&(_0x3a59fc=_0x1c943f);var A=_0x231ee0.getOwnPropertyDescriptor(_0xf8df31,_0xaae26b);(!A||(t[r(4612)]in A?!_0xcc39a2[r(861)]:A[r(594)]||A.configurable))&&(A={enumerable:!0,get:function(){return _0x58d2f4[_0x425ee3]}}),_0x12290f[r(4594)](_0x20f22b,_0x302850,A)}else for(var e=t[r(617)][r(7897)]("|"),i=0;;){switch(e[i++]){case"0":o[1]=t[r(998)](c[2],t[r(4422)](c[7],16))^t.lTBSt(c[5],16);continue;case"1":s.call(this);continue;case"2":o[2]=t[r(1060)](c[4],t.pwbHi(c[1],16))^t[r(9961)](c[7],16);continue;case"3":o[0]=t.rWBkg(c[0]^t[r(8912)](c[5],16),t[r(7935)](c[3],16));continue;case"4":o[3]=t[r(1677)](t[r(998)](c[6],t[r(8662)](c[3],16)),t[r(1758)](c[1],16));continue;case"5":var c=this._X;continue;case"6":for(var q=0;q<4;q++)o[q]=t[r(856)](t.FYcVe(t.JQmuU(t[r(1758)](o[q],8),t[r(4422)](o[q],24)),16711935),t[r(434)](t.dedal(t.SOAKs(o[q],24),t[r(4422)](o[q],8)),4278255360)),u[t.WPgNk(n,q)]^=o[q];continue}break}},blockSize:A[f(9036)](128,32),ivSize:A[f(9414)](64,32)});function s(){for(var u=f,n=this._X,A=this._C,e=0;e<8;e++)q[e]=A[e];A[0]=r[u(1093)](r.GJIPe(A[0],1295307597)+this._b,0),A[1]=r[u(7490)](r[u(7654)](A[1],3545052371)+(r[u(1952)](A[0]>>>0,r[u(7716)](q[0],0))?1:0),0),A[2]=r.ZinaW(r[u(7856)](r[u(346)](A[2],886263092),r[u(8306)](A[1],0)>>0,r[u(1884)](q[2],0))?1:0),0),A[4]=r.EVEgE(r[u(5507)](A[4]+3545052371,A[3]>>>0>>0?1:0),0),A[5]=r.Vetrv(r[u(7088)](r[u(8477)](A[5],886263092),r[u(8208)](A[4],0)>>0)?1:0),0),A[7]=r.otKZN(r.ushhP(r[u(4596)](A[7],3545052371),A[6]>>>0>>0?1:0),0),this._b=A[7]>>>0>>17)+r[u(6847)](a,x)>>>15,r.GqDxX(x,x));continue;case"1":var b=(0|r[u(6847)](4294901760&s,s))+r.otKZN(r[u(6847)](r.MBdvN(s,65535),s),0);continue;case"2":var s=n[e]+A[e];continue;case"3":v[e]=r[u(3997)](o,b);continue;case"4":var a=r[u(2397)](s,65535);continue;case"5":var x=r.gEfZN(s,16);continue}break}else for(var w=0;t.wnHeg(w,_0x57c094);w+=4)_0x47d050[t[u(4422)](t[u(9589)](_0x417f31,w),2)]=_0x52bc3a[t[u(8912)](w,2)];n[0]=r[u(7356)](r[u(346)](r[u(8477)](v[0],r.pwktM(v[7],16)|r[u(3898)](v[7],16)),r[u(9337)](r[u(3417)](v[6],16),r.gEfZN(v[6],16))),0),n[1]=r[u(6922)](r[u(8477)](v[1],r.DZUzi(r[u(7825)](v[0],8),r[u(4607)](v[0],24)))+v[7],0),n[2]=r[u(9549)](r[u(293)](r[u(8477)](v[2],r.vMWFn(v[1],16)|v[1]>>>16),r[u(4399)](r[u(10307)](v[0],16),r[u(8962)](v[0],16))),0),n[3]=r[u(4634)](r[u(7088)](r[u(9342)](v[3],r.ULETb(v[2]<<8,r[u(8962)](v[2],24))),v[1]),0),n[4]=0|r[u(8477)](r[u(346)](v[4],v[3]<<16|v[3]>>>16),r.BNLiK(r[u(7968)](v[2],16),r.CvlTh(v[2],16))),n[5]=r[u(6117)](r.GJIPe(r[u(3942)](v[5],r[u(4399)](r[u(7936)](v[4],8),r[u(7800)](v[4],24))),v[3]),0),n[6]=r[u(1641)](r[u(10446)](r[u(293)](v[6],v[5]<<16|v[5]>>>16),r[u(7490)](r[u(1598)](v[4],16),v[4]>>>16)),0),n[7]=r[u(7758)](r[u(5293)](v[7]+(r[u(1028)](v[6],8)|r[u(680)](v[6],24)),v[5]),0)}e[f(8929)]=i[f(5404)](b)}(),u[n(8929)]})},{"./cipher-core":3,"./core":4,"./enc-base64":5,"./evpkdf":8,"./md5":13}],27:[function(u,n,r){var f=_0x7f58,A={uvpWE:function(u,n,r){return u(n,r)},puToe:function(u,n){return u===n},imZMl:f(8237),uVwSg:f(6072),SYjwX:function(u,n){return u===n},HwqoL:f(7186),MWfkj:function(u,n,r,f,A,t){return u(n,r,f,A,t)},gfJNe:f(3251),iFzvU:function(u,n){return u(n)},dkQck:f(7470),CRCjh:function(u,n){return u(n)},eAYlC:"./md5",VdgCw:function(u,n){return u(n)},Bgrlr:f(2666),emIiK:"function",tqxiI:"./evpkdf",jmuJZ:f(4350),fzNSP:function(u,n){return u+n},aHUWU:function(u,n,r,f){return u(n,r,f)},RFafE:function(u,n){return u-n},fFaNt:f(1139),gOtBD:function(u,n){return u>>n},iWxaG:function(u,n){return u|n},FigTX:function(u,n){return u|n},xqkMt:function(u,n){return u>>>n},peAhM:function(u,n){return u<>>n},AMAoQ:function(u,n){return u|n},proWg:function(u,n){return u|n},szrwf:function(u,n){return u>>>n},NCDGt:function(u,n){return u&n},NDhoI:function(u,n){return u|n},cBibq:function(u,n){return u&n},mejij:function(u,n){return u&n},sXVcf:function(u,n){return u>>n},srheX:function(u,n){return u>>n},owUVg:function(u,n){return u>>>n},sCLbM:function(u,n){return u!==n},tYLuJ:function(u,n){return u*n},AsKnD:function(u,n){return u*n},ZuxMp:function(u,n){return u+n},eHxuE:function(u,n){return u>>>n},SalCT:function(u,n){return u*n},TmhHX:function(u,n){return u^n},cyFfC:function(u,n){return u|n},YWgkk:function(u,n){return u<>>n},BbGBV:function(u,n){return u>=n},Glgvi:function(u,n){return u+n},TeYBn:function(u,n){return u===n},nDUXa:f(4037),gZEhR:function(u,n){return u^n},NDSQZ:function(u,n){return u>>>n},jdPQa:function(u,n){return u<>>n},pjhDp:function(u,n){return A.gOtBD(u,n)},bCoNu:A[n(9838)],ptbQZ:function(u,n){return u|n},yosFF:function(u,n){return u|n},TKPdL:function(u,n){return A.cBibq(u,n)},XfoDd:function(u,n){return A.cyFfC(u,n)}};return function(){var f=n,t={hPimj:function(u,n){return A[_0x7f58(7245)](u,n)},ZaJkI:function(u,n,r,f){return A[_0x7f58(3948)](u,n,r,f)},OnbpV:function(u,n){return A[_0x7f58(7930)](u,n)},PkzfT:A[f(5593)],pABUg:function(u,n){return A[f(8565)](u,n)},dYNXx:function(u,n){return A[f(3465)](u,n)},FCkdp:A[f(4525)],cqeIO:function(u,n){return A[f(1841)](u,n)},rvsJr:function(u,n){return A[f(9456)](u,n)},BDjcz:function(u,n){return u>>>n},HhLjk:function(u,n){return A[f(9456)](u,n)},Kqxwz:function(u,n){return A[f(8598)](u,n)},hxITp:function(u,n){return A[f(2235)](u,n)},QBjhO:function(u,n){return A.iWxaG(u,n)},gqwxw:function(u,n){return A.EuKAT(u,n)},pdNVK:function(u,n){return u|n},Aeadm:function(u,n){return A[f(4067)](u,n)},DdgHD:function(u,n){return u&n},iOepG:function(u,n){return A[f(282)](u,n)},YGQre:function(u,n){return A[f(1841)](u,n)},BXGQa:function(u,n){return A[f(9456)](u,n)},zpVPj:function(u,n){return A[f(4916)](u,n)},soAcY:function(u,n){return A[f(282)](u,n)},ObqeD:function(u,n){return A[f(9694)](u,n)},DTzxi:function(u,n){return A[f(8049)](u,n)},gfbuS:function(u,n){return A[f(8565)](u,n)},Stfvs:function(u,n){return u+n},pRjBT:function(u,n){return u&n},YxMKU:function(u,n){return A[f(1379)](u,n)},ImboZ:function(u,n){return A[f(8598)](u,n)},enBoi:function(u,n){return A[f(4916)](u,n)},RIBHk:function(u,n){return A[f(4067)](u,n)},czcJU:function(u,n){return A[f(547)](u,n)},zxBmM:function(u,n){return A[f(5349)](u,n)},UdFEx:function(u,n){return A.NCDGt(u,n)},RLEBA:function(u,n){return A[f(6733)](u,n)},mHLPL:function(u,n){return A.cBibq(u,n)},seRqe:function(u,n){return A[f(5914)](u,n)},jaOdf:function(u,n){return A[f(5349)](u,n)},cjFBT:function(u,n){return u+n},MHNdG:function(u,n){return A[f(7245)](u,n)},zVAWa:function(u,n){return A[f(7581)](u,n)},irGVc:function(u,n){return A[f(7011)](u,n)},PBYZv:function(u,n){return A.AMAoQ(u,n)},ERqPi:function(u,n){return u>>n},usGOr:function(u,n){return A[f(7245)](u,n)},nAHhn:function(u,n){return A[f(487)](u,n)},nZVaH:function(u,n){return A.mCfSg(u,n)},syphx:function(u,n){return A[f(4067)](u,n)},YNSny:function(u,n){return A[f(7245)](u,n)},racTZ:function(u,n){return A[f(7371)](u,n)},UupWA:function(u,n){return A[f(9866)](u,n)},DROoC:f(5541),mnRha:function(u,n){return A.fzNSP(u,n)},FevEd:function(u,n){return A[f(8890)](u,n)},dDdah:function(u,n){return A[f(6982)](u,n)},BeReI:function(u,n){return A[f(8860)](u,n)},wjMlX:function(u,n){return A[f(4698)](u,n)},gFjOr:function(u,n){return A[f(3775)](u,n)},lFsbV:function(u,n){return u*n},wfMFX:function(u,n){return u&n},RalKM:function(u,n){return A[f(3126)](u,n)},GmeJl:function(u,n){return A[f(10210)](u,n)},PieQC:function(u,n){return u+n},dyWPt:function(u,n){return A[f(264)](u,n)},VNgHD:function(u,n){return A.TjoKb(u,n)},ArlWY:function(u,n){return A[f(7011)](u,n)},DdTke:function(u,n){return u|n},CROqr:function(u,n){return A[f(8860)](u,n)},dAzrF:function(u,n){return A.VYkkg(u,n)},VycbO:function(u,n){return A.AMAoQ(u,n)},dBdvD:function(u,n){return A[f(10210)](u,n)},kgbZG:function(u,n){return A[f(3734)](u,n)},OJpwX:function(u,n){return A[f(5980)](u,n)},xpKiA:function(u,n){return u|n},FTpXg:function(u,n){return A[f(6321)](u,n)},htNfs:function(u,n){return A[f(1002)](u,n)},vQdAA:function(u,n){return A.RqjdK(u,n)},iHmZT:function(u,n){return A[f(282)](u,n)},lrTIB:function(u,n){return u|n},GlIJU:function(u,n){return u>>>n},UHCNy:function(u,n){return A[f(8860)](u,n)},RVppf:function(u,n){return A[f(5188)](u,n)},NlyDi:function(u,n){return A[f(6121)](u,n)},WNMNK:function(u,n){return A[f(6205)](u,n)},gLXSp:function(u,n){return A.zJlNr(u,n)}},e=u,i=e[f(8364)][f(2832)],c=e[f(329)],o=[],q=[],v=[],b=c[f(7099)]=i[f(6491)]({_doReset:function(){var u=f,n={otJgl:function(u,n){return u/n},uEiJA:function(u,n){return u+n},RPRHu:function(u,n){return t[_0x7f58(8539)](u,n)}};if(t.PkzfT!==t[u(3524)])for(_0x225761.s();!(_0xf11a31=_0x3a3aa1.n())[u(8379)];){var r=_0x434834[u(10292)],A=t[u(1991)](_0x271d0b,_0x30fd43);_0x4f882d[t[u(1991)](_0x46e3fb,_0x37072a)>>2]=A,_0x2f7fb8+=t[u(1991)](t[u(9102)](_0x3f0a34,r,A,_0x18b3b1),1),_0x51984f+=4}else{for(var e=this[u(3370)].words,i=this[u(7063)].iv,c=0;t.pABUg(c,4);c++){if(!t[u(5726)](t[u(3750)],t.FCkdp))return _0x611206[u(2781)](n[u(4959)](n[u(9167)](1,_0x1a2b4b),n[u(9787)](1,_0x458027)))/2;e[c]=t[u(2756)](t[u(9478)](e[c]<<8,t[u(8135)](e[c],24)),16711935)|4278255360&t[u(9125)](e[c]<<24,t.BDjcz(e[c],8))}var o=this._X=[e[0],e[3]<<16|t.BDjcz(e[2],16),e[1],e[0]<<16|t.BDjcz(e[3],16),e[2],t[u(2673)](e[1],16)|t[u(9719)](e[0],16),e[3],t[u(1926)](t.Kqxwz(e[2],16),t[u(6089)](e[1],16))],q=this._C=[t[u(8298)](t[u(2673)](e[2],16),e[2]>>>16),t[u(4188)](t[u(2106)](e[0],4294901760),t[u(2106)](e[1],65535)),t[u(2673)](e[3],16)|t.iOepG(e[3],16),t[u(8298)](4294901760&e[1],t[u(5753)](e[2],65535)),t[u(8941)](t[u(3496)](e[0],16),t.soAcY(e[0],16)),t[u(2756)](e[2],4294901760)|t.DdgHD(e[3],65535),t[u(3496)](e[1],16)|t[u(3545)](e[1],16),t.DTzxi(4294901760&e[3],t.cqeIO(e[0],65535))];this._b=0;for(c=0;t[u(1984)](c,4);c++)s[u(2210)](this);for(c=0;c<8;c++)q[c]^=o[7&t[u(7601)](c,4)];if(i)for(var v=u(5139)[u(7897)]("|"),b=0;;){switch(v[b++]){case"0":q[1]^=g;continue;case"1":q[3]^=D;continue;case"2":var a=t.pRjBT(t[u(2942)](t[u(1508)](w,8),t[u(6089)](w,24)),16711935)|4278255360&(t[u(9658)](w,24)|w>>>8);continue;case"3":var x=i[u(7992)];continue;case"4":q[6]^=C;continue;case"5":var w=x[0];continue;case"6":var g=t.RIBHk(t[u(1431)](a,16),t[u(5753)](C,4294901760));continue;case"7":var C=t[u(3279)](t[u(3444)](t[u(5484)](B<<8,t.czcJU(B,24)),16711935),t[u(3557)](t[u(1508)](B,24)|t[u(6089)](B,8),4278255360));continue;case"8":q[0]^=a;continue;case"9":for(c=0;t[u(5574)](c,4);c++)s[u(2210)](this);continue;case"10":var B=x[1];continue;case"11":var D=t[u(5484)](t[u(1508)](C,16),t[u(7221)](a,65535));continue;case"12":q[5]^=g;continue;case"13":q[7]^=D;continue;case"14":q[4]^=a;continue;case"15":q[2]^=C;continue}break}}},_doProcessBlock:function(u,n){var A=f,t={ELUAM:function(u,n){return r[_0x7f58(1400)](u,n)},UMUmm:function(u,n){return r[_0x7f58(371)](u,n)},ILXZO:function(u,n){return r.NxWey(u,n)},tfkDt:r[A(1837)],CWsqk:function(u,n){return r[A(8706)](u,n)},KziCF:function(u,n){return r[A(3187)](u,n)},nzrDJ:function(u,n){return r.ZizsW(u,n)},ODoOt:function(u,n){return r[A(3187)](u,n)},SBKWu:r[A(1533)]},e=this._X;s[A(2210)](this),o[0]=r[A(5943)](r[A(5943)](e[0],r[A(4014)](e[5],16)),r.KmDtM(e[3],16)),o[1]=r[A(3613)](e[2],r[A(4014)](e[7],16))^r[A(6562)](e[5],16),o[2]=r[A(3613)](e[4]^r[A(7143)](e[1],16),e[7]<<16),o[3]=r.vzaql(r[A(5943)](e[6],r[A(4014)](e[3],16)),r.KmDtM(e[1],16));for(var i=0;r[A(7849)](i,4);i++){if(!r.ZizsW("wPrCt",r.bCoNu))return t[A(2963)]((0,_0x5b3622[A(10117)])([!t[A(9201)](A(6587),_0x330143),t.ILXZO(t[A(6869)],_0x23f072),t[A(3087)](t[A(837)]("",_0x40adfc[A(2517)]),A(9467)),t.nzrDJ(t[A(8360)]("",_0x3c0c1e[A(8798)]),t.SBKWu)]),3);o[i]=r[A(3505)](16711935&r[A(9957)](o[i]<<8,r[A(7143)](o[i],24)),r[A(5105)](r[A(9170)](r[A(9471)](o[i],24),r[A(7143)](o[i],8)),4278255360)),u[r.WRpRt(n,i)]^=o[i]}},blockSize:4,ivSize:2});function s(){for(var u=f,n=this._X,r=this._C,A=0;A<8;A++)q[A]=r[A];r[0]=t[u(4681)](t[u(7601)](t[u(7601)](r[0],1295307597),this._b),0),r[1]=0|t[u(6395)](t[u(2445)](r[1],3545052371),t.zVAWa(t[u(8135)](r[0],0),t[u(1463)](q[0],0))?1:0),r[2]=t[u(4446)](t[u(1991)](t[u(2445)](r[2],886263092),t.ERqPi(t.soAcY(r[1],0),t[u(6089)](q[1],0))?1:0),0),r[3]=0|t.hPimj(t[u(649)](r[3],1295307597),t.KKHuL(t[u(8135)](r[2],0),t[u(1431)](q[2],0))?1:0),r[4]=t[u(9400)](t.Stfvs(t.HkDQB(r[4],3545052371),t[u(8153)](t.ObqeD(r[3],0),q[3]>>>0)?1:0),0),r[5]=t.QBjhO(t[u(649)](r[5],886263092)+(t.KKHuL(t[u(9033)](r[4],0),t[u(1463)](q[4],0))?1:0),0),r[6]=0|t.hPimj(t[u(3819)](r[6],1295307597),t[u(2763)](t.nZVaH(r[5],0),q[5]>>>0)?1:0),r[7]=t[u(8067)](t[u(6557)](r[7]+3545052371,t[u(2447)](t.soAcY(r[6],0),q[6]>>>0)?1:0),0),this._b=t[u(1984)](t[u(2422)](r[7],0),t[u(2742)](q[7],0))?1:0;for(A=0;t[u(8153)](A,8);A++)if(t[u(9396)](t[u(2027)],t[u(2027)]))_0x5cd524(_0x53039e);else for(var e=u(1772)[u(7897)]("|"),i=0;;){switch(e[i++]){case"0":var c=t.HkDQB(n[A],r[A]);continue;case"1":var o=t.mnRha(t[u(4681)](t[u(6833)](t[u(3557)](c,4294901760),c),0),t.Aeadm(t[u(6483)](t.pRjBT(c,65535),c),0));continue;case"2":var b=t.hxITp(t[u(1834)](t[u(9968)](t.gFjOr(s,s),17),t[u(1957)](s,a)),15)+a*a;continue;case"3":var s=t[u(8829)](c,65535);continue;case"4":v[A]=t.RalKM(b,o);continue;case"5":var a=t[u(6022)](c,16);continue}break}n[0]=t.GmeJl(t[u(3819)](t[u(6803)](v[0],t[u(2673)](v[7],16)|t[u(9968)](v[7],16)),t[u(9478)](t[u(7900)](v[6],16),t[u(9033)](v[6],16))),0),n[1]=t[u(1991)](v[1],t[u(9292)](v[0],8)|t[u(3498)](v[0],24))+v[7]|0,n[2]=t[u(568)](t[u(4418)](t.PieQC(v[2],t[u(8668)](v[1]<<16,v[1]>>>16)),t[u(2204)](t[u(9292)](v[0],16),t[u(8135)](v[0],16))),0),n[3]=t[u(1571)](t[u(6641)](t[u(6557)](v[3],t.OJpwX(t.dyWPt(v[2],8),t[u(2742)](v[2],24))),v[1]),0),n[4]=t[u(6566)](t[u(6395)](t[u(4418)](v[4],t[u(1730)](t.enBoi(v[3],16),v[3]>>>16)),t.htNfs(t[u(4336)](v[2],16),t[u(1704)](v[2],16))),0),n[5]=t.lrTIB(t[u(649)](t[u(520)](v[5],t.ImboZ(v[4],8)|t[u(10454)](v[4],24)),v[3]),0),n[6]=t[u(9400)](t[u(8378)](t.PieQC(v[6],t[u(589)](v[5],16)|v[5]>>>16),t[u(9455)](t[u(9611)](v[4],16),t[u(5877)](v[4],16))),0),n[7]=t[u(6502)](t[u(6803)](v[7],v[6]<<8|t[u(1431)](v[6],24))+v[5],0)}e[f(7099)]=i[f(5404)](b)}(),u[n(7099)]})},{"./cipher-core":3,"./core":4,"./enc-base64":5,"./evpkdf":8,"./md5":13}],28:[function(u,n,r){var f=_0x7f58,A={Fwxro:function(u,n){return u===n},EqlHJ:"ddZOS",uoozx:function(u,n,r,f,A,t){return u(n,r,f,A,t)},JDaCz:function(u,n){return u(n)},zkifM:"./core",aIEXx:f(7470),FLUmB:f(2666),ESQFS:function(u,n,r){return u(n,r)},iboKF:f(9369),AvZPM:function(u,n){return u&n},hlpeC:function(u,n){return u>>>n},PoQXs:function(u,n){return u*n},aeOMf:function(u,n){return u%n},GZKmw:function(u,n){return u+n},MCZIz:"2|0|4|3|5|1",tdgwn:function(u,n){return u<n},ENJFn:"rVIMC",wicZw:f(3809)};!function(t,e,i){var c=f;if(A.Fwxro(A[c(10163)],A[c(10163)]))"object"==typeof r?n.exports=r=A[c(372)](e,A[c(7656)](u,A.zkifM),u(A.aIEXx),u(c(2038)),A.JDaCz(u,"./evpkdf"),A[c(7656)](u,A[c(3048)])):A.Fwxro(typeof define,c(4261))&&define[c(4388)]?A[c(1811)](define,["./core","./enc-base64","./md5",c(4234),A[c(3048)]],e):e(t.CryptoJS);else this[c(7377)]}(this,function(u){var n=f,r={QBChw:A[n(727)],GzSIJ:function(u,n){return u+n},oFgER:function(u,r){return A[n(3817)](u,r)},GzIvp:function(u,r){return A[n(1457)](u,r)},eNIPG:function(u,n){return A.dPbMK(u,n)},tlvol:function(u,r){return A[n(3418)](u,r)},JiMrV:function(u,r){return A[n(5992)](u,r)},jguUl:A[n(10531)],ZxgdG:A[n(6862)],HLrmk:function(u,r){return A[n(10166)](u,r)},XftZc:A[n(2993)],VFrWk:A[n(9906)]};return function(){var f=n,t={ZUWSt:function(u,n){return u>>n},pGQip:function(u,n){return A[_0x7f58(3245)](u,n)},Ilzlb:function(u,n){return u-n},hcCcL:function(u,n){return A[_0x7f58(1558)](u,n)},iGdGC:function(u,n){return A[_0x7f58(1132)](u,n)},cgPmQ:function(u,n){return A.GZKmw(u,n)},EndWE:function(u,n){return A[_0x7f58(5388)](u,n)},wNBVo:function(u,n){return A.aeOMf(u,n)}},e=u,i=e[f(8364)].StreamCipher,c=e[f(329)],o=c[f(6569)]=i[f(6491)]({_doReset:function(){for(var u=f,n=this[u(3370)],r=n[u(7992)],A=n[u(7822)],e=this._S=[],i=0;i<256;i++)e[i]=i;i=0;for(var c=0;t.ZUWSt(i,256);i++)for(var o=t.XDhhE[u(7897)]("|"),q=0;;){switch(o[q++]){case"0":var v=e[i];continue;case"1":e[c]=v;continue;case"2":var b=t[u(8216)](t.nIjPw(r[t[u(3148)](s,2)],t[u(5657)](24,t[u(4447)](s%4,8))),255);continue;case"3":e[i]=e[c];continue;case"4":c=t[u(9327)](t[u(2855)](t[u(9703)](c,e[i]),b),256);continue;case"5":var s=t.wNBVo(i,A);continue}break}this._i=this._j=0},_doProcessBlock:function(u,n){var r=f;u[n]^=q[r(2210)](this)},keySize:8,ivSize:0});function q(){for(var u=f,n="4|1|3|5|7|2|0|6"[u(7897)]("|"),A=0;;){switch(n[A++]){case"0":this._j=e;continue;case"1":var t=this._i;continue;case"2":this._i=t;continue;case"3":var e=this._j;continue;case"4":var i=this._S;continue;case"5":var c=0;continue;case"6":return c;case"7":for(var o=0;o<4;o++)for(var q=r[u(8231)][u(7897)]("|"),v=0;;){switch(q[v++]){case"0":e=r[u(6032)](e,i[t])%256;continue;case"1":c|=r[u(1895)](i[(i[t]+i[e])%256],r[u(7389)](24,r[u(2460)](o,8)));continue;case"2":t=r.tlvol(r[u(6032)](t,1),256);continue;case"3":i[t]=i[e];continue;case"4":var b=i[t];continue;case"5":i[e]=b;continue}break}continue}break}}e[f(6569)]=i[f(5404)](o);var v=c.RC4Drop=o[f(6491)]({cfg:o.cfg[f(6491)]({drop:192}),_doReset:function(){var u=f;if(r[u(7973)](r.jguUl,r[u(2969)]))(-1)[u(1493)](-1);else{o[u(9976)][u(2210)](this);for(var n=this[u(7063)][u(5656)];r[u(7307)](n,0);n--)r[u(6701)]===r.VFrWk?this.cfg=this[u(7063)][u(6491)](_0x23726a):q[u(2210)](this)}}});e.RC4Drop=i._createHelper(v)}(),u[n(6569)]})},{"./cipher-core":3,"./core":4,"./enc-base64":5,"./evpkdf":8,"./md5":13}],29:[function(u,n,r){var f,A,t,e=_0x7f58,i={CqPam:function(u,n){return u===n},lQTYM:e(7186),ZOByp:"./core",rJgYx:e(4261),xlFfE:function(u,n,r){return u(n,r)},JmIUC:function(u,n){return u(n)},cWpEX:e(10354),JcikH:function(u,n){return u!==n},oLnct:function(u,n){return u>>n},kkzHN:function(u,n){return u|n},rFzBX:function(u,n){return u+n},NGOLc:function(u,n){return u+n},PvTmg:function(u,n){return u|n},eILpa:function(u,n){return u^n},HOyba:e(2525),XYsAC:e(7671),zxrlU:e(7443),rTYkj:function(u,n){return u-n}};f=this,A=function(u){var n=e,r={ITKho:function(u,n){return u!==n},eiVsN:i[n(7299)],XjgNQ:function(u,r){return i[n(4498)](u,r)},qSAKB:function(u,n){return i.NomVO(u,n)},wMbuY:function(u,n){return u<>>n},Kqjai:function(u,r){return i[n(1654)](u,r)},WUbkY:function(u,n){return i.oTQcv(u,n)},BCaBf:function(u,r){return i[n(5438)](u,r)},JyVxX:function(u,r){return i[n(8300)](u,r)},GWNLp:function(u,n){return u^n},ExbhA:function(u,n){return i.eILpa(u,n)},hSHsU:function(u,r){return i[n(1654)](u,r)},zHavO:function(u,r){return i[n(5061)](u,r)},LWVXQ:i.HOyba,ukdAA:i[n(1211)],ZjxsF:function(u,n){return u^n},rXghL:function(u,n){return u|n},aLgwR:i[n(3510)],iKnfJ:function(u,r){return i[n(7650)](u,r)}};return function(f){var A=n,t={ZIwZI:i[A(4008)],EEvOT:function(u,n){return u(n)},wlqLO:function(u,n){return i[A(6224)](u,n)},hPWad:function(u,n){return i[A(6224)](u,n)},MzDNn:function(u,n){return i[A(8580)](u,n)},BGUcf:i[A(2560)],UexfX:function(u,n){return i[A(1185)](u,n)},EiJFX:function(u,n){return i[A(2238)](u,n)},AhgfJ:function(u,n){return u*n},dpcEt:function(u,n){return i[A(5061)](u,n)},VYgpt:A(2746),BJWUB:function(u,n){return u+n},UGZXm:function(u,n){return u|n},rlMlB:function(u,n){return i[A(3058)](u,n)},ORXLB:function(u,n){return i[A(5438)](u,n)},MNCnb:function(u,n){return i.ZXush(u,n)},itDGh:function(u,n){return u>>>n},KoKDL:i[A(4428)],NUXwv:i[A(3873)],GTPhF:function(u,n,r,f){return i[A(8682)](u,n,r,f)},pcogG:function(u,n){return u>>24),16711935),4278255360&t[r(1587)](t[r(3506)](c,24),t[r(3461)](c,8)))}var o,q,v,C,I,j,K,y,h,_,Q,N=this._hash[r(7992)],M=w[r(7992)],l=g[r(7992)],m=b[r(7992)],H=s[r(7992)],P=a[r(7992)],G=x[r(7992)];j=o=N[0],K=q=N[1],y=v=N[2],h=C=N[3],_=I=N[4];for(e=0;t.MzDNn(e,80);e+=1)if(t[r(8116)]!==t.NUXwv){if(Q=t[r(1587)](t[r(457)](o,u[n+m[e]]),0),e<16)Q+=t[r(457)](t.GTPhF(B,q,v,C),M[0]);else if(t[r(3272)](e,32))Q+=t[r(1062)](D,q,v,C)+M[1];else if(t.PSsZJ(e,48)){if(t[r(7524)]("LErkj",t[r(4800)]))throw new _0x1f1a2d(t.ZIwZI);Q+=t[r(1062)](L,q,v,C)+M[2]}else t[r(9429)](e,64)?Q+=t[r(3543)](z,q,v,C)+M[3]:Q+=t[r(3543)](E,q,v,C)+M[4];if(Q=t[r(10388)](Q,0),Q=t[r(4049)](d,Q,P[e]),Q=t[r(10388)](t[r(7984)](Q,I),0),o=I,I=C,C=t[r(4049)](d,v,10),v=q,q=Q,Q=t[r(8657)](t.UexfX(j,u[t[r(8796)](n,H[e])]),0),e<16)Q+=t.XwQUV(t[r(4327)](E,K,y,h),l[0]);else if(e<32){if(!t[r(1586)](t[r(1010)],r(2689))){var Y=_0x1a2cf2.clone.call(this);return Y[r(8810)]=this._hash.clone(),Y}Q+=t.mYljC(t[r(4686)](z,K,y,h),l[1])}else if(t.VIGgX(e,48)){if(t[r(4064)]===t[r(2184)])return _0x2722e6[r(631)](function(u,n){var A=r;return f[A(9989)](_0x563c7c[n][A(3682)],_0x26f717[u])||f[A(7539)](_0x4ad690[n][A(9766)],_0x28ad83[u])});Q+=t[r(8634)](t[r(1163)](L,K,y,h),l[2])}else if(t.PimRz(e,64))Q+=t[r(8444)](D(K,y,h),l[3]);else if(t.yVbty(r(4122),t[r(8286)]))Q+=t[r(8444)](t[r(6427)](B,K,y,h),l[4]);else for(var J=0;f[r(5820)](J,5);J++)for(var S=f.gMIAG.split("|"),W=0;;){switch(S[W++]){case"0":var X=_0x3bcd47[R];continue;case"1":var O=_0xf6576[f[r(1966)](f[r(10198)](f[r(1966)](_0x49b987,2),5),f[r(10033)](5,J))];continue;case"2":X.high=k[r(2659)]^f[r(8871)](~p[r(2659)],O.high);continue;case"3":X[r(3227)]=f[r(8760)](k[r(3227)],f[r(8068)](~p.low,O[r(3227)]));continue;case"4":var R=_0x18e8db+5*J;continue;case"5":var k=_0x1950ea[R];continue;case"6":var p=_0x4e2dea[f.QHzZt(f[r(10198)](f[r(3017)](_0x1b4f9e,1),5),f[r(2552)](5,J))];continue}break}Q=t[r(1587)](Q,0),Q=t[r(5855)](d,Q,G[e]),Q=0|t[r(8796)](Q,_),j=_,_=h,h=t[r(6518)](d,y,10),y=K,K=Q}else t.EEvOT(_0x1e037f,_0x264b2b.CryptoJS);Q=0|t.NBViw(N[1]+v,h),N[1]=t.oQyZo(t[r(9565)](t[r(1649)](N[2],C),_),0),N[2]=t[r(2172)](N[3]+I+j,0),N[3]=t.OwcpT(t[r(2165)](t[r(8554)](N[4],o),K),0),N[4]=t[r(8410)](t.HkPEq(N[0],q)+y,0),N[0]=Q},_doFinalize:function(){for(var u=A,n=r[u(3181)].split("|"),f=0;;){switch(n[f++]){case"0":var t=i[u(7992)];continue;case"1":var e=r[u(9742)](b[u(7822)],8);continue;case"2":var i=this[u(8810)];continue;case"3":var c=r[u(9742)](this[u(6568)],8);continue;case"4":var o=b[u(7992)];continue;case"5":o[r.qSAKB(e,5)]|=r[u(9581)](128,24-e%32);continue;case"6":this._process();continue;case"7":for(var q=0;r[u(6469)](q,5);q++){var v=t[q];t[q]=r.RhUEh(16711935&(r[u(9581)](v,8)|v>>>24),4278255360&(v<<24|r[u(1129)](v,8)))}continue;case"8":b[u(7822)]=r[u(9742)](r[u(6336)](o.length,1),4);continue;case"9":o[r.PhGIh(r[u(9324)](r.oNENh(e,64),9)<<4,14)]=16711935&r.eUovt(c<<8,r[u(5816)](c,24))|r[u(7333)](r[u(3974)](r[u(7359)](c,24),r[u(8110)](c,8)),4278255360);continue;case"10":return i;case"11":var b=this[u(4269)];continue}break}},clone:function(){var u=A;if(t[u(3559)]===t.itDui){var n=q[u(6429)].call(this);return n[u(8810)]=this[u(8810)][u(6429)](),n}return _0x394b11}});function B(u,n,f){return r[A(7635)](r.ExbhA(u,n),f)}function D(u,n,f){return r[A(2501)](u,n)|r.zHavO(~u,f)}function L(u,n,r){var f=A;return t.DYsGu(t[f(8410)](u,~n),r)}function z(u,n,r){var f=A;if(t[f(7262)](t[f(4678)],t[f(4678)]))return t[f(2231)](u&r,t[f(1746)](n,~r));_0x3db853(_0x3c13c6)}function E(u,n,f){var t=A,e={vDItq:r[t(1055)]};return r[t(1144)](r[t(1183)],r[t(1183)])?_0x5e618c[t(4099)](function(u){for(var n=t;;)switch(u[n(2519)]=u[n(6460)]){case 0:return u[n(4922)](e.vDItq,(0,_0x46a9be[n(4343)])({includes:[_0x362846.isChrome],excludes:[(_0x3bab09[n(5492)]||_0x5d9ec7[n(4276)])&&_0x496fac[n(3512)]]}));case 1:case n(8961):return u[n(9572)]()}},_0x455422,this):r[t(838)](u,r[t(8820)](n,~f))}function d(u,n){var f=A;return r[f(6424)]===f(8859)?_0x3be5d6[f(5893)]:r[f(10362)](r[f(9581)](u,n),u>>>r[f(6045)](32,n))}e[A(6684)]=q[A(5404)](C),e[A(7026)]=q[A(2281)](C)}(Math),u[n(6684)]},i[(t=e)(8358)](typeof r,i.lQTYM)?n[t(8018)]=r=A(u(i[t(2010)])):i[t(8358)](typeof define,i[t(9195)])&&define[t(4388)]?i.xlFfE(define,[i[t(2010)]],A):i[t(8268)](A,f[t(3080)])},{"./core":4}],30:[function(u,n,r){var f=_0x7f58,A={sCEQm:function(u,n){return u===n},VslSI:f(7186),YlIDz:function(u,n){return u(n)},VqNeA:f(3251),IynNV:function(u,n){return u!==n},plJhk:"mFFjD",tleWy:function(u,n,r){return u(n,r)},hpPwj:function(u,n){return u(n)},uHCcZ:function(u,n,r,f,A){return u(n,r,f,A)},bItiL:f(2525),SjoGC:f(8961),yLOjw:f(10009),EVGxO:f(551),ngueG:f(8293),DFozH:function(u,n){return u>>n},SrOKT:function(u,n){return u+n},VzWGd:function(u,n){return u&n},ErjTU:function(u,n){return u+n},SptYI:function(u,n){return u>>n},GXFjF:function(u,r){return A[n(8160)](u,r)},wutgq:function(u,r){return A[n(7347)](u,r)},dsRMe:A[n(1021)],quIrR:function(u,r){return A[n(7406)](u,r)},OVBmq:A[n(4384)],rhspK:function(u,n,r){return u(n,r)},xcBbO:function(u,r){return A[n(7144)](u,r)},wvYoc:n(3467)};return A.fKIWw(A[n(8630)],A[n(7684)])?A.uHCcZ(_0x422434,this,void 0,void 0,_0x4a3c7c[n(655)](function u(){var f=n,A={ItQoe:r.hkgiA,OXZnF:r[f(314)]};return _0x1b1e90[f(4099)](function(u){for(var n=f;;)switch(u.prev=u.next){case 0:return _0x27d45d=!1,(0,_0x2cdc49[n(2781)])(_0x538a1d),u[n(4922)](A[n(4687)],_0x21756d);case 3:case A[n(6955)]:return u[n(9572)]()}},u,this)})):(function(){var f=n,A={bpVVR:function(u,n){return u==n},WfFog:function(u,n){return r[_0x7f58(10047)](u,n)},LZcwO:r[f(6452)],alXnW:function(u,n,f){return r.rhspK(u,n,f)}};if(r[f(387)](f(3467),r.wvYoc))return _0x2b721e++,"";var t=u,e=t[f(8364)],i=e[f(8122)],c=e[f(7363)],o=t.algo,q=[],v=o[f(5268)]=c[f(6491)]({_doReset:function(){var u=f;this[u(8810)]=new(i[u(6848)])([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(u,n){var t=f,e={lCLYK:r[t(2171)]};if(r[t(9993)]===r.skdFg){var i=_0x3d06cc[t(8333)](_0x2554c6),c=i[t(7992)];if(A[t(5599)](c[0],1398893684)&&1701076831==c[1]){var o=_0x2a3aa9.create(c[t(781)](2,4));c[t(8628)](0,4),i[t(7822)]-=16}return _0x3835db.create({ciphertext:i,salt:o})}for(var v=this._hash.words,b=v[0],s=v[1],a=v[2],x=v[3],w=v[4],g=0;g<80;g++){if(r.TCcBH(g,16))if(r.eTbtL(r.GufAp,r[t(7036)])){if(!A[t(3449)](_0x231542,_0x2e7659))throw new _0x42906f(A[t(5873)])}else q[g]=r[t(469)](u[n+g],0);else{var C=r[t(1697)](q[r[t(8144)](g,3)]^q[r.kzjmr(g,8)]^q[r.eltxA(g,14)],q[r[t(8144)](g,16)]);q[g]=r.vTWQg(C,1)|r.FbGfA(C,31)}var B=r[t(2209)](r[t(2209)](r[t(469)](b<<5,r[t(8198)](b,27)),w),q[g]);r.TCcBH(g,20)?t(945)!==r.TLiVF?_0x365f0d(_0x15712c[e[t(8704)]](_0x4cfc46)):B+=r[t(8802)](r.aHJsE(s,a)|r.aHJsE(~s,x),1518500249):r[t(5990)](g,40)?B+=r[t(7732)](r[t(1697)](r[t(5799)](s,a),x),1859775393):r[t(5871)](g,60)?B+=r[t(1081)](r.QLQlc(r[t(469)](r[t(2236)](s,a),r[t(9583)](s,x)),a&x),1894007588):B+=r.IJzME(r[t(1697)](s,a)^x,899497514),w=x,x=a,a=r[t(782)](r[t(2512)](s,30),r[t(1685)](s,2)),s=b,b=B}v[0]=r[t(7697)](r.cYMtQ(v[0],b),0),v[1]=r[t(469)](r[t(8802)](v[1],s),0),v[2]=r.meEpg(r.DYMcg(v[2],a),0),v[3]=r[t(7697)](r[t(5262)](v[3],x),0),v[4]=v[4]+w|0},_doFinalize:function(){for(var u=f,n=r.xlMdd[u(7897)]("|"),A=0;;){switch(n[A++]){case"0":i[14+(r[u(1685)](e+64,9)<<4)]=Math[u(4727)](r[u(8277)](t,4294967296));continue;case"1":c[u(7822)]=r[u(8189)](i[u(7855)],4);continue;case"2":i[r.vLYjw(e,5)]|=r[u(1247)](128,r.vdIPZ(24,r[u(1338)](e,32)));continue;case"3":var t=8*this._nDataBytes;continue;case"4":i[r.lyifs(r[u(2998)](r[u(7732)](e,64),9)<<4,15)]=t;continue;case"5":var e=r.GXFjF(c[u(7822)],8);continue;case"6":this[u(3595)]();continue;case"7":var i=c[u(7992)];continue;case"8":return this[u(8810)];case"9":var c=this[u(4269)];continue}break}},clone:function(){var u=f;if(!r.wutgq(u(5385),r.dsRMe)){var n=c[u(6429)][u(2210)](this);return n[u(8810)]=this[u(8810)].clone(),n}A[u(2628)](_0x20e78b,_0x2e2990,_0x4d02b0)}});t[f(5268)]=c[f(5404)](v),t.HmacSHA1=c[f(2281)](v)}(),u.SHA1)})},{"./core":4}],31:[function(u,n,r){var f=_0x7f58,A={MJLcI:f(1175),TAhhe:function(u,n){return u*n},JIiSQ:function(u,n){return u&n},PtajJ:function(u,n){return u>>n},DfHmn:function(u,n){return u+n},jmneN:function(u,n){return u>>n},poWhG:function(u,n){return u+n},cyZCE:function(u,n){return u<.5?1:-1);case"2":b+=.5;continue;case"3":_0x47cc03=A[c(3275)](18e3*(65535&_0x585526)+A[c(9936)](_0x3e84bc,16),_0x4c405b);continue;case"4":_0x100f37=A[c(3275)](A[c(947)](A.TAhhe(36969,A[c(3275)](_0x4aa1db,65535)),A.jmneN(_0x4ba202,16)),_0x10d70b);continue;case"5":var b=A[c(3275)](A.poWhG(A[c(1747)](_0x2421e9,16),_0x852b24),_0x48b795);continue}break}else if(A[c(8844)](typeof r,A[c(5888)]))n[c(8018)]=r=A[c(8858)](e,A[c(5113)](u,A[c(7561)]),A[c(5113)](u,A[c(1098)]));else if(typeof define===A.ZjAyC&&define[c(4388)])if(A.cpUxP(A[c(8352)],A[c(8352)])){if(typeof _0x43d8fb!==o.UWDDr)throw new _0x5cc147("Invalid operator type, expected string but got "+typeof _0x2d3d4e);if(o[c(2486)](_0x988bb1[c(4579)](_0x5790d5),-1))throw new _0x173dd5(c(6950)+_0x1069af[c(6309)]("|"))}else A[c(8858)](define,[A.nJHLT,A[c(1098)]],e);else A[c(5113)](e,t[c(3080)])}(this,function(u){var n=f,r={Zmjuf:n(7553),HmEqc:function(u){return A[n(3792)](u)},yVWtI:A.HkTKf,VBcLN:n(9774)};if(A[n(8816)](A[n(4824)],A[n(4824)])){var t=_0x2c4c0d[n(7764)][n(2210)](this);return t[n(7822)]-=16,t}return function(){var f=n;if(r[f(7840)]===r[f(6152)]){var A={jTFbY:function(u){return r[f(2868)](u)},rxgWH:function(u,n){return u(n)}};return _0x473968[f(4099)](function(u){for(var n=f;;)switch(u[n(2519)]=u[n(6460)]){case 0:return u[n(4922)](n(2525),new _0x3f700d(function(u){var r=A[n(4860)](_0x635e31);A.rxgWH(u,r)}));case 1:case n(8961):return u[n(9572)]()}},_0x1c1a31,this)}var t=u,e=t[f(8364)].WordArray,i=t[f(329)],c=i[f(2960)],o=i.SHA224=c[f(6491)]({_doReset:function(){var u=f;if(r.Zmjuf!==r[u(8579)])return!0;this[u(8810)]=new e.init([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428])},_doFinalize:function(){var u=f,n=c[u(7764)][u(2210)](this);return n[u(7822)]-=4,n}});t[f(5085)]=c._createHelper(o),t[f(7290)]=c[f(2281)](o)}(),u[n(5085)]})},{"./core":4,"./sha256":32}],32:[function(u,n,r){var f=_0x7f58,A={OywoQ:function(u,n,r){return u(n,r)},WJFOh:function(u,n){return u in n},XrUlm:function(u,n){return u(n)},rcWZR:function(u,n){return u!==n},PGDKF:function(u,n){return u===n},NztxC:f(7186),aDMXP:"./core",TvoaQ:function(u,n){return u===n},PLWYk:f(4261),yrGPF:function(u,n){return u===n},kMocc:f(5762),vpXKu:function(u,n,r){return u(n,r)},bwKSZ:function(u,n){return u(n)},IUgEb:f(3395),erEqh:function(u,n){return u*n},znroz:function(u,n){return u>>>n},pYDIG:function(u,n){return u<>>n}};!function(t,e){var i=f,c={aQqTi:function(u,n){return A.WJFOh(u,n)},Hrizo:function(u,n){return A[_0x7f58(8397)](u,n)},YvCod:function(u,n,r){return u(n,r)}};if(A.rcWZR(i(4157),i(4157))){if(_0x36c156[i(8259)](_0x306370))return _0x5935f6;if(c[i(6916)](_0xa58013[i(9869)],c[i(2504)](_0x2a3467,_0x5ed2e1)))return c.YvCod(_0x382c8e,_0x43ba3c,_0x378ed2);throw new _0x8333ea(i(9615))}if(A[i(8530)](typeof r,A[i(2784)]))n[i(8018)]=r=A.XrUlm(e,A[i(8397)](u,A[i(7414)]));else if(A[i(515)](typeof define,A[i(9974)])&&define[i(4388)]){if(A.yrGPF(i(7294),A[i(6493)]))return _0x95e1d0&&A[i(2482)](_0x34c6a2,_0x1cd3ba[i(10129)],_0x2896d3),_0x5b1e9d&&A.OywoQ(_0x3ae4e5,_0x353382,_0x3d43b2),_0x1e8649;A[i(4144)](define,[A[i(7414)]],e)}else A[i(1160)](e,t.CryptoJS)}(this,function(u){var n=f,r={NMbPo:A[n(8102)],MLdvu:function(u,r){return A[n(10222)](u,r)},WdBAY:function(u,r){return A[n(7976)](u,r)},crUKQ:function(u,r){return A[n(4266)](u,r)},lNVdE:function(u,r){return A[n(833)](u,r)},dGUog:function(u,r){return A[n(3836)](u,r)},TTFVO:function(u,r){return A[n(3570)](u,r)},EFDrx:function(u,n){return u+n},Lpfnf:function(u,n){return u*n},ndDAZ:function(u,r){return A[n(1160)](u,r)},BknHU:function(u,r){return A[n(4356)](u,r)},KdNjl:A[n(5156)],PBodt:A[n(2084)],lEtcT:function(u,r){return A[n(4207)](u,r)},pqwcM:A[n(1346)],StUjF:function(u,r){return A[n(10222)](u,r)},uwWht:function(u,n){return u-n},lgIeC:function(u,r){return A[n(6526)](u,r)},hOkNl:function(u,r){return A[n(8397)](u,r)},LHtji:A[n(1668)],JkICx:A[n(3825)],xTqJY:function(u,n){return A.WROlO(u,n)},BzKaq:function(u,r){return A[n(4666)](u,r)},NbsST:n(1922),steQQ:function(u,r){return A[n(8397)](u,r)},QcWwR:A[n(498)],xHUsz:n(5440),LlHmQ:function(u,r){return A[n(2049)](u,r)},bcyZj:A[n(2784)],pLdkq:function(u,n,r){return u(n,r)},MOfKD:A.aDMXP,OyNAN:n(2666),bnVRc:A[n(9974)],ybmBa:function(u,r,f){return A[n(3400)](u,r,f)},lHRds:function(u,n){return u^n},xNLkX:function(u,r){return A[n(6526)](u,r)},cLFQZ:function(u,r){return A[n(9668)](u,r)},inrur:function(u,n){return A.HQKfQ(u,n)},dhgDW:function(u,r){return A[n(2776)](u,r)},hNjBY:function(u,n){return A.evTYc(u,n)},fJbbs:function(u,n){return A.sawoo(u,n)},NLGKJ:function(u,r){return A[n(6526)](u,r)},GAQXh:function(u,r){return A[n(3836)](u,r)}};return function(f){var A=n,t={nPEky:function(u,n){return r[_0x7f58(3516)](u,n)},WPbpT:function(u,n){return r[_0x7f58(1764)](u,n)},MErbU:r[A(9475)],UJvUD:r[A(5157)],AfhHP:function(u,n){return r.lEtcT(u,n)},abCzg:function(u,n){return u!==n},PXcZU:r[A(10220)],eJwAM:function(u,n){return r[A(1614)](u,n)},tIPtu:function(u,n){return r[A(875)](u,n)},sHxJW:function(u,n){return r.uwWht(u,n)},jTxJi:function(u,n){return r[A(2725)](u,n)},CFAJs:"[object Array]",YFalF:function(u,n){return r[A(789)](u,n)},OTESo:r.LHtji,HkSTE:r[A(10436)],ShuVf:function(u,n){return r[A(3298)](u,n)},FhhMK:function(u,n){return r[A(5218)](u,n)},TasPR:r.NbsST,mLeds:function(u,n){return r[A(3298)](u,n)},tyghX:A(9351),CrpsG:function(u,n){return r[A(1905)](u,n)},KvGvF:function(u,n){return r[A(3516)](u,n)},LDcPm:r[A(3959)],ZFCIW:r[A(7792)],GRvhl:function(u,n){return r[A(6640)](u,n)},BXAVY:r.bcyZj,DFDJl:function(u,n,f){return r[A(1071)](u,n,f)},CSBbN:r[A(3529)],pTVkH:r[A(8246)],FVCsb:function(u,n){return r.LlHmQ(u,n)},ARjaT:r[A(6748)],nowYa:function(u,n,f){return r[A(9845)](u,n,f)},xGswy:function(u,n){return u>>13)),t[r(10289)](t[r(5759)](e,10),t.fikGS(e,22))),j=t[r(9020)](t[r(5284)](t[r(5792)](q,26)|q>>>6,t[r(6477)](t.oduid(q,21),t.LhUQo(q,11))),t[r(5792)](q,7)|t[r(7134)](q,25)),K=t[r(8235)](t.KJjWz(x+j,E),b[w])+s[w],y=t[r(9286)](I,d);x=a,a=v,v=q,q=t.UUHeJ(t[r(9286)](o,K),0),o=c,c=i,i=e,e=t.YFhAS(t[r(1237)](K,y),0)}f[0]=t.YFhAS(t.KJjWz(f[0],e),0),f[1]=t[r(6628)](t[r(643)](f[1],i),0),f[2]=0|t[r(8235)](f[2],c),f[3]=0|t[r(3406)](f[3],o),f[4]=0|t[r(8235)](f[4],q),f[5]=t[r(3919)](t.IRFUu(f[5],v),0),f[6]=0|t.IHUwT(f[6],a),f[7]=t[r(1041)](t[r(362)](f[7],x),0)},_doFinalize:function(){var u=A;if(r[u(5422)]===u(3395)){var n=this._data,t=n[u(7992)],e=8*this[u(6568)],i=r.MLdvu(n[u(7822)],8);return t[r[u(2616)](i,5)]|=r.crUKQ(128,24-r[u(1614)](i,32)),t[r[u(6274)](r[u(4211)](i,64)>>>9<<4,14)]=f[u(4727)](e/4294967296),t[r[u(4211)](r.crUKQ(r[u(1349)](i,64)>>>9,4),15)]=e,n.sigBytes=r[u(4599)](t[u(7855)],4),this[u(3595)](),this[u(8810)]}_0x364107(this,_0x3af2f6)},clone:function(){var u=A,n=o[u(6429)][u(2210)](this);return n[u(8810)]=this[u(8810)][u(6429)](),n}});e.SHA256=o[A(5404)](a),e[A(8939)]=o._createHmacHelper(a)}(Math),u.SHA256})},{"./core":4}],33:[function(u,n,r){var f=_0x7f58,A={MhsQN:function(u,n){return u(n)},SGKEt:"object",hmtoN:function(u,n,r){return u(n,r)},fpico:f(3917),WmnnU:function(u,n){return u===n},Xiouo:f(4261),BtGVm:f(3251),IZXZm:function(u,n){return u===n},rUZne:"jdzwL",gCiEc:f(10355),DZZUH:function(u,n){return u(n)},MWgQQ:f(2525),JEkCs:function(u,n){return u(n)},FNLdO:function(u,n){return u(n)},yIOMW:function(u,n){return u!==n},mvrNH:f(8989),OFKwj:function(u,n){return u>>n},jKnCu:function(u,n){return u>>>n},jdUMh:function(u,n){return u|n},lVijj:f(9560),sAYhO:"KHkMi",GIHae:"QoPuS",UOJrc:f(3962),wIbUV:function(u,n){return u===n},bGQlo:"bTClV",yUMuw:f(10145),VzNsq:function(u,n){return u<>>n},gVzbA:function(u,n){return u===n}};!function(t,e,i){var c=f,o=function(u,n){return A[_0x7f58(3345)](u,n)};if(typeof r===A[c(2322)])n[c(8018)]=r=A[c(4926)](e,A[c(3345)](u,c(3251)),A[c(3345)](u,A[c(9189)]));else if(A[c(6983)](typeof define,A.Xiouo)&&define[c(4388)])A[c(4926)](define,[A[c(2944)],A.fpico],e);else if(A[c(785)](A[c(7864)],A[c(477)])){var q=_0x2c05b8[c(8333)](_0x1d7684[c(5784)]),v=(q[c(5861)],q[c(569)],q.data);o(_0x377664,_0x414c83[c(5614)](v))}else A[c(8661)](e,t[c(3080)])}(this,function(u){var n=f,r={wQYPB:function(u,n,r){return A.hmtoN(u,n,r)},gZmOj:n(6679),mBrRr:function(u,n){return u(n)},wMzPV:function(u,r){return A[n(6244)](u,r)},oHDTg:A[n(5566)],JijtC:function(u,r){return A[n(8842)](u,r)},vAViH:function(u,n){return u*n},wRQPv:function(u,r){return A[n(1087)](u,r)},yvIWY:function(u,r){return A[n(10058)](u,r)},oHmKE:function(u,n){return u+n},BQQdw:function(u,n){return u%n},pNXhu:function(u,n){return A.fFYVT(u,n)},Snqkq:function(u,r){return A[n(4228)](u,r)},pINHO:function(u,r){return A[n(4107)](u,r)},cIAVW:function(u,r){return A[n(5227)](u,r)},STLSn:A.ZVhjR,jtSPy:A[n(1003)],QOGGv:A[n(4406)],SZdan:function(u,r){return A[n(2623)](u,r)},sZUYc:function(u,r){return A[n(8842)](u,r)},PiIhU:function(u,n){return A.sckSd(u,n)},zZUwD:function(u,r){return A[n(5039)](u,r)},jBEQl:A[n(2977)],AHahv:function(u,r){return A[n(1170)](u,r)},ZRjws:A[n(7083)],YjZik:function(u,n){return u&n},qpTmj:A[n(4156)],Ilbqt:function(u,n){return u-n},zHNvc:function(u,n){return u===n},tPtSx:A[n(6375)],qvOvh:function(u,n){return u<>>n},CQEMe:function(u,r){return A[n(6244)](u,r)},lskDV:A[n(2018)],rAsiS:function(u,n){return u+n},kKgei:function(u,n){return A.OFKwj(u,n)},VmDGO:A[n(6163)],sJtvj:A.UOJrc,LIjyu:function(u,r){return A[n(6244)](u,r)},SbUCe:function(u,r){return A[n(8020)](u,r)},mlVCW:A[n(7096)],sOJnK:A[n(3562)],mRvfJ:function(u,n){return u<>>24),16711935)|4278255360&r.zJJpF(r[f(2313)](B,24),B>>>8);continue}break}for(var D=0;r[f(2535)](D,24);D++){for(var L=0;L<5;L++)if(r[f(6905)](r[f(2354)],r[f(2354)]))try{var z=(0,_0x2ba7ec[f(5318)])(_0x38b3df[f(3243)]);return e[f(10055)](_0x4c41ad,z)?1:z}catch(u){return 1}else for(var E=r.jSXFn[f(7897)]("|"),d=0;;){switch(E[d++]){case"0":I[f(2659)]=K;continue;case"1":var I=w[L];continue;case"2":for(var j=0;r[f(2535)](j,5);j++){K^=(g=c[r[f(1986)](L,r[f(2649)](5,j))])[f(2659)],y^=g[f(3227)]}continue;case"3":I[f(3227)]=y;continue;case"4":var K=0,y=0;continue}break}for(L=0;r[f(7265)](L,5);L++){var h=w[r[f(3742)](L+4,5)],_=w[r.PoIoW(L+1,5)],Q=_[f(2659)],N=_.low;for(K=r.NVPnR(h[f(2659)],r[f(9709)](r.rLCyE(Q,1),r[f(1466)](N,31))),y=r[f(7129)](h[f(3227)],r[f(7536)](N,1)|r[f(4818)](Q,31)),j=0;r.CQEMe(j,5);j++){if(r[f(8880)]==r[f(8880)])(g=c[r[f(7869)](L,r[f(4566)](5,j))]).high^=K,g[f(3227)]^=y;else _0x42309d[f(8018)]=_0x4591ba=A[f(5486)](_0x5efa40,_0x1bd91b(A.MtATR),A.JqEqr(_0x202073,A[f(4901)]),A.OQuma(_0x2e377d,f(2038)),A.YuxUG(_0x2b6025,A[f(6739)]),A[f(5616)](_0x3c0814,f(2666)))}}for(var M=1;r.kKgei(M,25);M++)if(r[f(3374)](r.VmDGO,r[f(9551)]))e.DvoOa(_0x5d03cb,[e[f(4803)],e[f(8754)]],_0x532ec7);else{var l=(g=c[M])[f(2659)],m=g[f(3227)],H=s[M];if(r[f(2093)](H,32)){if(r.SbUCe(r[f(6506)],r[f(9573)]))return _0x2c7cf5 instanceof _0x2cc5f6?_0x2319f9:new _0x34e2f2(function(u){A[f(3144)](u,_0x1d9dc6)});K=r[f(9709)](r.mRvfJ(l,H),r.PdRbu(m,r[f(7042)](32,H))),y=r[f(9709)](r[f(5411)](m,H),l>>>r.ZOYkl(32,H))}else K=r.ioWfP(r[f(9094)](m,H-32),l>>>r[f(402)](64,H)),y=r[f(6457)](r[f(3267)](l,r[f(7042)](H,32)),r[f(1466)](m,64-H));var P=w[a[M]];P.high=K,P.low=y}var G=w[0],Y=c[0];G[f(2659)]=Y[f(2659)],G[f(3227)]=Y[f(3227)];for(L=0;r.yRKoV(L,5);L++)for(j=0;r.CQEMe(j,5);j++){g=c[M=r[f(9019)](L,r[f(9676)](5,j))];var J=w[M],S=w[r[f(2533)](r[f(3742)](r[f(6856)](L,1),5),5*j)],W=w[r.BQQdw(r[f(3086)](L,2),5)+5*j];g.high=r.QSDIg(J.high,r[f(9061)](~S.high,W[f(2659)])),g[f(3227)]=r.QSDIg(J[f(3227)],~S[f(3227)]&W[f(3227)])}g=c[0];var X=x[D];g[f(2659)]^=X.high,g[f(3227)]^=X[f(3227)]}},_doFinalize:function(){var u=t;if(!r.jCpfy(r[u(10391)],u(2377))){var n=_0xe1f05[u(8967)];return(e.enpOo(typeof n,e[u(10379)])?e.rDfQN:e[u(9227)](_0x121e32,n))===e[u(8013)]&&e.enpOo(typeof n[e[u(1383)]],"function")&&e.enpOo(typeof n[e[u(9794)]],u(4261))&&typeof n.Memory===u(4261)?"1":"0"}for(var A=r[u(7501)][u(7897)]("|"),i=0;;){switch(A[i++]){case"0":return new(o[u(6848)])(D,g);case"1":for(var c=0;c>>24),16711935),r[u(1443)](r[u(7778)](r[u(5411)](a,24),a>>>8),4278255360));continue}break}continue;case"2":var x=this[u(4269)];continue;case"3":var w=r.yvIWY(g,8);continue;case"4":var g=r[u(10385)](this[u(7063)][u(8202)],8);continue;case"5":x.sigBytes=r[u(9676)](z[u(7855)],4);continue;case"6":var C=r[u(4566)](x.sigBytes,8);continue;case"7":var B=this[u(4412)];continue;case"8":var D=[];continue;case"9":r[u(5650)](this[u(6568)],8);continue;case"10":this[u(3595)]();continue;case"11":z[r[u(3015)](C,5)]|=r[u(9094)](1,24-r.wRQPv(C,32));continue;case"12":var L=r[u(2251)](this[u(2315)],32);continue;case"13":var z=x.words;continue;case"14":z[r[u(593)](r[u(1529)](f[u(6426)](r[u(2921)](r[u(1986)](C,1),L))*L,5),1)]|=128;continue}break}},clone:function(){var u=t;if(r[u(5143)](r[u(5925)],r[u(2103)]))return _0x5e17c2.chrome!==_0x198c17;for(var n=q[u(6429)][u(2210)](this),f=n[u(4412)]=this[u(4412)][u(781)](0),A=0;r[u(2093)](A,25);A++)f[A]=f[A].clone();return n}});i[t(710)]=q[t(5404)](g),i[t(4486)]=q[t(2281)](g)}(Math),u[n(710)]})},{"./core":4,"./x64-core":37}],34:[function(u,n,r){var f,A,t,e=_0x7f58,i={BPMUt:function(u,n){return u===n},fSZzi:function(u,n){return u(n)},wItEH:function(u,n){return u(n)},XAPWf:e(3251),NTGxH:e(4261),fUOUI:function(u,n,r){return u(n,r)},aeLiz:"vcQXO",qKiQy:e(5339),MzImm:e(7186),jrOjc:function(u,n,r,f){return u(n,r,f)},tulvT:function(u,n){return u(n)},ttHmM:e(6970),viRAc:function(u){return u()},Islap:function(u,n){return u!==n},TtoeA:e(499),OKwlW:"hGpPb"};f=this,A=function(u){var n,r,f,A,t,c,o,q,v,b=e,s={jQuEv:function(u,n){return u===n},eLqYS:b(10135)};if(i[b(10056)](i[b(2309)],i[b(6153)]))return r={dldGf:function(u){return i[_0x7f58(5860)](u)}},A=(f=u)[(n=b)(1667)],t=A.Word,c=A[n(8122)],o=f[n(329)],q=o[n(2864)],v=o[n(9614)]=q.extend({_doReset:function(){var u=n;this[u(8810)]=new(c[u(6848)])([new(t[u(6848)])(3418070365,3238371032),new(t[u(6848)])(1654270250,914150663),new t.init(2438529370,812702999),new t.init(355462360,4144912697),new(t[u(6848)])(1731405415,4290775857),new(t[u(6848)])(2394180231,1750603025),new(t[u(6848)])(3675008525,1694076839),new(t[u(6848)])(1203062813,3204075428)])},_doFinalize:function(){var u=n;if(!s[u(5162)](s[u(7015)],"XsPaC")){var f=q[u(7764)].call(this);return f[u(7822)]-=16,f}_0xb219bc=_0x5eb08e(),r[u(6256)](_0x23c0ec)}}),f[n(9614)]=q._createHelper(v),f[n(1767)]=q[n(2281)](v),u[b(9614)];_0xf3e44b.stop()},t=e,i.aeLiz!==i.qKiQy?i[t(10179)](typeof r,i[t(2946)])?n.exports=r=i.jrOjc(A,u(i[t(7719)]),i[t(6187)](u,t(3917)),u(i[t(2537)])):typeof define===i.NTGxH&&define[t(4388)]?i[t(2984)](define,[i.XAPWf,"./x64-core",t(6970)],A):i[t(6187)](A,f[t(3080)]):i[t(10179)](typeof _0x5d8cd1,t(7186))?_0x5be7e8[t(8018)]=_0x4f47f6=i[t(4879)](_0x15fb78,i[t(5687)](_0x4cf691,i.XAPWf)):typeof _0x500fc0===i[t(8709)]&&_0x5b7da0[t(4388)]?i[t(2984)](_0x896d79,[i[t(7719)]],_0x1ec16b):i[t(4879)](_0x556edf,_0xccf841.CryptoJS)},{"./core":4,"./sha512":35,"./x64-core":37}],35:[function(u,n,r){var f=_0x7f58,A={euEFo:function(u,n){return u(n)},qlHlW:function(u,n){return u===n},YBDPO:f(7184),fhOxt:function(u,n){return u===n},gXahB:f(7186),SxHbv:function(u,n,r){return u(n,r)},rarUg:function(u,n){return u(n)},hdoFM:f(3251),JluZu:f(4261),XEpIb:function(u,n,r){return u(n,r)},eieUu:f(3917),rayDI:f(6496),VZAEq:f(2692),EsnYI:function(u,n){return u!==n},wNVxm:"zNlFe",ukQIJ:f(5298),BmtmH:"blank page",DJqif:f(2841),VnvSw:f(2366),Kafqo:function(u,n){return u*n},oAzBJ:function(u,n){return u+n},TUALW:"bKNlJ",YgtUe:function(u,n){return u^n},RAjXk:function(u,n){return u<>>n},WmZqN:function(u,n){return u<>>n},jdpSV:function(u,n){return u+n},BtxsM:function(u,n){return u>>>n},SxhdU:function(u,n){return u>>n},mSnRn:f(10034),jBOqJ:function(u,n){return u%n},mOOiZ:function(u,n){return u*n},AMXDe:function(u,n,r){return u(n,r)},DUKVd:function(u,n,r){return u(n,r)},DslnP:function(u,n,r){return u(n,r)},FcFHg:function(u,n,r){return u(n,r)},AbKtY:function(u,n,r){return u(n,r)},xEgVW:function(u,n,r){return u(n,r)},lToTq:function(u,n,r){return u(n,r)},PvJaw:function(u,n,r){return u(n,r)},kkULb:function(u,n,r){return u(n,r)},TICyL:function(u,n,r){return u(n,r)},vdbiX:function(u,n,r){return u(n,r)},ttMFM:function(u,n,r){return u(n,r)},pWuUn:function(u,n,r){return u(n,r)},RWksh:function(u,n,r){return u(n,r)},eRvVB:function(u,n,r){return u(n,r)},gfMeP:function(u,n,r){return u(n,r)}};!function(t,e,i){var c=f,o={zbigP:function(u,n){return A[_0x7f58(7279)](u,n)}};if(!A[c(10499)](c(7184),A[c(2973)]))return _0xc8f47b instanceof _0x3acf7f?_0x22b823:new _0x2b7d4c(function(u){o[c(2991)](u,_0x209dab)});A[c(3794)](typeof r,A[c(5751)])?n[c(8018)]=r=A.SxHbv(e,A[c(403)](u,A.hdoFM),A[c(403)](u,c(3917))):A.fhOxt(typeof define,A[c(1059)])&&define[c(4388)]?A[c(6461)](define,[A[c(6399)],A[c(8400)]],e):A.euEFo(e,t[c(3080)])}(this,function(u){var n=f,r={SONCc:A[n(6060)],chkmv:A[n(5295)],QNScP:function(u){return u()},MjyNn:function(u,r){return A[n(3493)](u,r)},EdTHt:A.wNVxm,qTWnN:A[n(1995)],sOImZ:A[n(3930)],qgxKA:function(u,r){return A[n(7279)](u,r)},tBKxS:A.DJqif,qBwcG:function(u,n){return u>>n},URFRl:function(u,r){return A[n(6055)](u,r)},kOjEf:function(u,n){return u>>>n},mPpAv:function(u,n){return A.EnxEw(u,n)},yHmvO:function(u,r){return A[n(4483)](u,r)},lwnDG:function(u,r){return A[n(2339)](u,r)},oHhEt:function(u,r){return A[n(1931)](u,r)},gBBOK:function(u,r){return A[n(1931)](u,r)},WyvjB:function(u,n){return u+n},hLhMz:function(u,r){return A[n(7203)](u,r)},bLPag:function(u,n){return A.JiXQk(u,n)},iAGZM:function(u,n){return A.pQNqZ(u,n)},CkOhc:function(u,r){return A[n(10128)](u,r)},XvXrG:function(u,r){return A[n(10402)](u,r)},yynMi:function(u,r){return A[n(3035)](u,r)},oTgyx:function(u,n){return u|n},AhYWN:function(u,n){return A.zXrLV(u,n)},vppkk:function(u,r){return A[n(9352)](u,r)},zRJIu:function(u,n){return A.hYPgi(u,n)},DonAP:function(u,r){return A[n(10402)](u,r)},KeGCH:function(u,r){return A[n(1931)](u,r)},YflHS:function(u,r){return A[n(1931)](u,r)},WCJOK:function(u,r){return A[n(10402)](u,r)},Allnn:function(u,n){return A.xQmFn(u,n)},YvtWy:function(u,r){return A[n(2137)](u,r)},hgYIV:function(u,r){return A[n(9232)](u,r)},SiXCd:function(u,r){return A[n(1931)](u,r)},ebKbX:function(u,r){return A[n(9232)](u,r)},ZsMUW:function(u,n){return A.jdpSV(u,n)},NYIbm:function(u,n){return A.jdpSV(u,n)},OMMbk:function(u,n){return u+n},uqWxB:function(u,r){return A[n(9234)](u,r)},qZLTz:function(u,r){return A[n(7056)](u,r)},IVVQB:function(u,r){return A[n(1142)](u,r)},ncpdd:A[n(7938)],BPAKZ:function(u,r){return A[n(991)](u,r)},HSTHg:function(u,n){return u+n},UeteL:function(u,r){return A[n(9234)](u,r)},NDahj:function(u,r){return A[n(6812)](u,r)},xYROk:function(u,r,f){return A[n(3670)](u,r,f)},Qglfj:function(u,r,f){return A[n(1362)](u,r,f)},lHdAL:function(u,n,r){return A.DUKVd(u,n,r)},auKFL:function(u,n,r){return u(n,r)},RjZtP:function(u,n,r){return A.DslnP(u,n,r)},QjAhH:function(u,n,r){return u(n,r)},DHOor:function(u,n,r){return A.DUKVd(u,n,r)},FqMPG:function(u,n,r){return u(n,r)},RPlKc:function(u,n,r){return u(n,r)},VYWae:function(u,r,f){return A[n(4171)](u,r,f)},nGqDU:function(u,r,f){return A[n(790)](u,r,f)},KwBnw:function(u,n,r){return A.DslnP(u,n,r)},BnrXg:function(u,r,f){return A[n(1130)](u,r,f)},HFmJL:function(u,n,r){return u(n,r)},hleVP:function(u,r,f){return A[n(2321)](u,r,f)},fFqOL:function(u,r,f){return A[n(1299)](u,r,f)},OglJu:function(u,r,f){return A[n(6239)](u,r,f)},zFblY:function(u,r,f){return A[n(9026)](u,r,f)},XTLBb:function(u,n,r){return u(n,r)},dHNhC:function(u,r,f){return A[n(4580)](u,r,f)},uVFLE:function(u,n,r){return A.ttMFM(u,n,r)},OLNtf:function(u,n,r){return u(n,r)},SXzBb:function(u,r,f){return A[n(2558)](u,r,f)},XazDF:function(u,r,f){return A[n(10399)](u,r,f)},QojAk:function(u,n,r){return u(n,r)},rzLMj:function(u,r,f){return A[n(8857)](u,r,f)},oDaGR:function(u,r,f){return A[n(1362)](u,r,f)},ITmyL:function(u,r,f){return A[n(1130)](u,r,f)},GAxMM:function(u,n,r){return A.vdbiX(u,n,r)},DxoUg:function(u,n,r){return A.XEpIb(u,n,r)},RgVwu:function(u,r,f){return A[n(4746)](u,r,f)}};return function(){var f=n,A={cSDlD:r[f(1450)],ZsvBL:function(u,n){return r[f(1271)](u,n)},URTTO:function(u,n){return u!==n},hHPuI:r[f(2887)],DqGZo:function(u,n){return r[f(5971)](u,n)},IeCdz:function(u,n){return r[f(5960)](u,n)},wlmJB:f(9017),pPHAc:function(u,n){return u===n},kcoQO:r.lXFbl,uclFv:function(u,n){return r.nthOj(u,n)},yLghj:function(u,n){return u+n},DkCOa:function(u,n){return r[f(10404)](u,n)},lvAqR:function(u,n){return r[f(6186)](u,n)},aZzKL:function(u,n){return r[f(3621)](u,n)},voDIY:function(u,n){return r[f(3621)](u,n)},IdIFj:r[f(5394)],yCOln:function(u,n){return r[f(2556)](u,n)},hMPXg:function(u,n){return r[f(3495)](u,n)},DxQnc:function(u,n){return r.GWIpu(u,n)},OMBSA:function(u,n){return r[f(3598)](u,n)},gGZxL:function(u,n){return r[f(2953)](u,n)},ctkmK:function(u,n){return u<>>n},dWVgR:function(u,n){return r.lwnDG(u,n)},sZCjW:function(u,n){return r.rgcQI(u,n)},IAJHc:function(u,n){return r[f(1877)](u,n)},CRnlh:function(u,n){return r[f(1877)](u,n)},xLmDK:function(u,n){return u>>>n},nsjCc:function(u,n){return r[f(9190)](u,n)},QUOvE:function(u,n){return r[f(3621)](u,n)},nqHka:function(u,n){return r.WyvjB(u,n)},tuwSI:function(u,n){return r[f(884)](u,n)},kGMnZ:function(u,n){return r.eYLhM(u,n)},HQPlI:function(u,n){return r[f(1671)](u,n)},UipMb:function(u,n){return u&n},rYQpF:function(u,n){return r[f(1671)](u,n)},ITbds:function(u,n){return r[f(5112)](u,n)},gqoPG:function(u,n){return r[f(3495)](u,n)},Ipfew:function(u,n){return r[f(1671)](u,n)},ESygc:function(u,n){return r[f(2834)](u,n)},GAySf:function(u,n){return r.XvXrG(u,n)},WZnJj:function(u,n){return r[f(8503)](u,n)},hWCLU:function(u,n){return u|n},YAgen:function(u,n){return u^n},ZxiJk:function(u,n){return r[f(2834)](u,n)},hcoKx:function(u,n){return u>>>n},OsnkE:function(u,n){return r[f(1582)](u,n)},juqfv:function(u,n){return u|n},CeDrl:function(u,n){return r.yynMi(u,n)},RURZu:function(u,n){return r[f(1582)](u,n)},nVbrc:function(u,n){return r.eYLhM(u,n)},lHkFx:function(u,n){return r[f(8503)](u,n)},YgIHq:function(u,n){return r[f(4265)](u,n)},yVFdV:function(u,n){return r[f(491)](u,n)},FpxiQ:function(u,n){return r[f(5617)](u,n)},QtpUT:function(u,n){return r[f(1434)](u,n)},ebLEk:function(u,n){return r[f(6236)](u,n)},WZipu:function(u,n){return u>>>n},dpyxx:function(u,n){return u+n},WBlHX:function(u,n){return r.eYLhM(u,n)},EjYPo:function(u,n){return u+n},OGhqJ:function(u,n){return u+n},KLVMu:function(u,n){return r.DonAP(u,n)},jDZMS:function(u,n){return u+n},twGcR:function(u,n){return r[f(884)](u,n)},DuDON:function(u,n){return r.WyvjB(u,n)},tulgK:function(u,n){return r[f(2030)](u,n)},rMSJL:function(u,n){return r[f(3621)](u,n)},nalWQ:function(u,n){return r[f(8285)](u,n)},yHZyj:function(u,n){return r[f(2219)](u,n)},SrPNX:function(u,n){return r.GWIpu(u,n)},ZOofs:function(u,n){return u+n},HRdaH:function(u,n){return u+n},rRaxz:function(u,n){return r[f(2030)](u,n)},ZKaon:function(u,n){return r[f(491)](u,n)},AFGpp:function(u,n){return u+n},xqsqL:function(u,n){return r.Allnn(u,n)},gDzTh:function(u,n){return r[f(2805)](u,n)},HGRsJ:function(u,n){return u+n},eTTUC:function(u,n){return r[f(4062)](u,n)},fLeag:function(u,n){return r[f(884)](u,n)},SjzmZ:function(u,n){return r.hgYIV(u,n)},jEkyj:function(u,n){return r.WyvjB(u,n)},kWyHY:function(u,n){return r[f(5216)](u,n)},arHiQ:function(u,n){return r[f(986)](u,n)},fWyXc:function(u,n){return u+n},gjLor:function(u,n){return r.ZsMUW(u,n)},pPhoi:function(u,n){return u>>n},qoCcq:function(u,n){return u>>>n},pinAw:function(u,n){return u+n},GyfNw:function(u,n){return r.NYIbm(u,n)},VURVc:function(u,n){return r[f(4957)](u,n)},CTPmQ:function(u,n){return r[f(4558)](u,n)},idKMP:function(u,n){return u+n},WRkdv:function(u,n){return r[f(7774)](u,n)},itqrU:function(u,n){return r[f(9711)](u,n)},yHdDp:function(u,n){return r[f(4558)](u,n)},ikApc:function(u,n){return r[f(4231)](u,n)},VUHWf:function(u,n){return r[f(5960)](u,n)},wddES:r[f(474)],KakCL:function(u,n){return r[f(10404)](u,n)},oOXJl:function(u,n){return r.fjAuu(u,n)},JlCUm:function(u,n){return u>>>n},kepjh:function(u,n){return u-n},vbjQB:function(u,n){return r[f(3288)](u,n)},NOtlO:function(u,n){return r[f(5186)](u,n)},FrRMH:function(u,n){return r[f(6414)](u,n)},gCsHk:function(u,n){return r[f(5216)](u,n)},mHcfI:function(u,n){return r.URFRl(u,n)},zaDFB:function(u,n){return r[f(8936)](u,n)}},t=u,e=t.lib[f(7363)],i=t[f(1667)],c=i.Word,o=i.WordArray,q=t.algo;function v(){var u=f;if(r[u(9642)]===u(6496))return c[u(4703)][u(6346)](c,arguments);for(var n=u(1590)[u(7897)]("|"),t=0;;){switch(n[t++]){case"0":i[u(8624)]=A[u(5363)];continue;case"1":A[u(8033)](_0x59ce63,A.URTTO(e,A.hHPuI));continue;case"2":_0x492787[u(2599)][u(5453)](i);continue;case"3":var e=_0x4abe69(i[u(7484)][u(645)]);continue;case"4":_0x34c985.body.removeChild(i);continue;case"5":var i=_0x592a8e[u(10284)](u(6793));continue}break}}var b=[r[f(7440)](v,1116352408,3609767458),r[f(7440)](v,1899447441,602891725),r[f(7205)](v,3049323471,3964484399),r[f(7205)](v,3921009573,2173295548),r[f(7440)](v,961987163,4081628472),r.lHdAL(v,1508970993,3053834265),r[f(7440)](v,2453635748,2937671579),v(2870763221,3664609560),r[f(8179)](v,3624381080,2734883394),r.auKFL(v,310598401,1164996542),r[f(5130)](v,607225278,1323610764),v(1426881987,3590304994),r[f(7440)](v,1925078388,4068182383),r.xYROk(v,2162078206,991336113),v(2614888103,633803317),r[f(8270)](v,3248222580,3479774868),r[f(5130)](v,3835390401,2666613458),r[f(1262)](v,4022224774,944711139),v(264347078,2341262773),r.FqMPG(v,604807628,2007800933),r[f(6391)](v,770255983,1495990901),r[f(6602)](v,1249150122,1856431235),r[f(5130)](v,1555081692,3175218132),v(1996064986,2198950837),r[f(7440)](v,2554220882,3999719339),v(2821834349,766784016),r[f(10266)](v,2952996808,2566594879),r[f(10302)](v,3210313671,3203337956),r[f(7205)](v,3336571891,1034457026),v(3584528711,2466948901),r[f(10302)](v,113926993,3758326383),r[f(1e4)](v,338241895,168717936),r[f(1792)](v,666307205,1188179964),r[f(8179)](v,773529912,1546045734),r.QjAhH(v,1294757372,1522805485),v(1396182291,2643833823),v(1695183700,2343527390),r[f(9155)](v,1986661051,1014477480),r.hleVP(v,2177026350,1206759142),r[f(5135)](v,2456956037,344077627),r.DHOor(v,2730485921,1290863460),r[f(4815)](v,2820302411,3158454273),r[f(8270)](v,3259730800,3505952657),r[f(8635)](v,3345764771,106217008),r[f(4815)](v,3516065817,3606008344),r.zFblY(v,3600352804,1432725776),r.nGqDU(v,4094571909,1467031594),r[f(7205)](v,275423344,851169720),r.BnrXg(v,430227734,3100823752),r[f(8270)](v,506948616,1363258195),r[f(6821)](v,659060556,3750685593),r[f(8270)](v,883997877,3785050280),v(958139571,3318307427),v(1322822218,3812723403),r[f(5421)](v,1537002063,2003034995),r.uVFLE(v,1747873779,3602036899),r[f(1699)](v,1955562222,1575990012),r[f(436)](v,2024104815,1125592928),r[f(436)](v,2227730452,2716904306),r.XazDF(v,2361852424,442776044),r[f(7911)](v,2428436474,593698344),r[f(7090)](v,2756734187,3733110249),r.xYROk(v,3204031479,2999351573),r[f(7161)](v,3329325298,3815920427),v(3391569614,3928383900),v(3515267271,566280711),v(3940187606,3454069534),r[f(4815)](v,4118630271,4000239992),r[f(9914)](v,116418474,1914138554),r[f(7911)](v,174292421,2731055270),v(289380356,3203993006),r[f(5421)](v,460393269,320620315),r.Qglfj(v,685471733,587496836),v(852142971,1086792851),r[f(8635)](v,1017036298,365543100),v(1126000580,2618297676),r.GAxMM(v,1288033470,3409855158),r[f(8279)](v,1501505948,4234509866),r[f(376)](v,1607167915,987167468),r[f(8635)](v,1816402316,1246189591)],s=[];!function(){for(var u=f,n={gdhRE:function(u,n){return u+n}},A=0;A<80;A++)r[u(5428)]!==u(2692)?_0x3d3360+=n[u(1019)](_0x1f7d1f(_0x2b2a19,_0x48d6a9,_0x1a08d5),_0x4b0b47[1]):s[A]=r.QNScP(v)}();var a=q[f(2864)]=e[f(6491)]({_doReset:function(){var u=f;this[u(8810)]=new(o[u(6848)])([new(c[u(6848)])(1779033703,4089235720),new(c[u(6848)])(3144134277,2227873595),new(c[u(6848)])(1013904242,4271175723),new c.init(2773480762,1595750129),new(c[u(6848)])(1359893119,2917565137),new(c[u(6848)])(2600822924,725511199),new(c[u(6848)])(528734635,4215389547),new(c[u(6848)])(1541459225,327033209)])},_doProcessBlock:function(u,n){for(var r=f,t=this[r(8810)][r(7992)],e=t[0],i=t[1],c=t[2],o=t[3],q=t[4],v=t[5],a=t[6],x=t[7],w=e[r(2659)],g=e.low,C=i[r(2659)],B=i[r(3227)],D=c[r(2659)],L=c[r(3227)],z=o[r(2659)],E=o.low,d=q[r(2659)],I=q[r(3227)],j=v.high,K=v[r(3227)],y=a.high,h=a[r(3227)],_=x[r(2659)],Q=x[r(3227)],N=w,M=g,l=C,m=B,H=D,P=L,G=z,Y=E,J=d,S=I,W=j,X=K,O=y,R=h,k=_,p=Q,T=0;A[r(6237)](T,80);T++)if(A[r(9954)](A[r(6149)],A.wlmJB)){var F=s[T];if(A[r(6237)](T,16))if(A[r(10227)](A[r(7475)],A.kcoQO))var U=F[r(2659)]=A.uclFv(u[A[r(4962)](n,A[r(7731)](T,2))],0),V=F[r(3227)]=A.lvAqR(u[A[r(6345)](A.voDIY(n,2*T),1)],0);else A[r(8033)](_0x3aa88a,_0x5dd0cf[r(6460)](_0x110a78));else if(A.pPHAc(A[r(7343)],A.IdIFj)){var Z=s[A[r(3716)](T,15)],$=Z[r(2659)],uu=Z[r(3227)],nu=A.hMPXg(A[r(5367)](A[r(8054)]($>>>1,uu<<31),A[r(1148)](A[r(2703)]($,8),A[r(4467)](uu,24))),A[r(2703)]($,7)),ru=A.lvAqR(uu>>>1,A[r(3037)]($,31))^A[r(10492)](A[r(2014)](uu,8),A[r(5449)]($,24))^(A.OMBSA(uu,7)|$<<25),fu=s[A[r(3201)](T,2)],Au=fu[r(2659)],tu=fu.low,eu=A[r(5015)](A[r(1389)](A.IrPKP(Au,19),A.ghcLv(tu,13)),A[r(1148)](A[r(5449)](Au,3),A[r(2014)](tu,29)))^Au>>>6,iu=A[r(6776)](A[r(6776)](A[r(5164)](A.BsirJ(tu,19),A[r(3037)](Au,13)),A[r(5164)](tu<<3,A.NBQtf(Au,29))),A[r(1039)](tu,6)|A.dWVgR(Au,26)),cu=s[A[r(9656)](T,7)],ou=cu[r(2659)],qu=cu[r(3227)],vu=s[T-16],bu=vu[r(2659)],su=vu[r(3227)];V=A[r(1978)](ru,qu),U=A[r(10484)](A[r(3355)](nu,ou),A[r(6237)](A[r(2964)](V,0),ru>>>0)?1:0),V=A[r(3355)](V,iu),U=A[r(3355)](A[r(1128)](U,eu),V>>>0>>2),A[r(8054)](N<<25,A[r(9963)](M,7))),Bu=A[r(9640)](A[r(1020)](A[r(8054)](A[r(9843)](M,28),A.ghcLv(N,4)),A[r(10161)](A[r(4463)](M,30),A.xLmDK(N,2))),A.juqfv(M<<25,N>>>7)),Du=A[r(2505)](A[r(1020)](A.uclFv(J>>>14,A[r(8157)](S,18)),A[r(8708)](A[r(4887)](J,18),A[r(9144)](S,14))),A[r(5164)](A[r(5509)](J,23),S>>>9)),Lu=A[r(6776)](A[r(3667)](A.xLmDK(S,14),A.YgIHq(J,18)),A[r(3667)](A[r(8074)](S,18),A[r(8367)](J,14)))^A[r(8762)](A[r(3037)](S,23),A[r(4862)](J,9)),zu=b[T],Eu=zu[r(2659)],du=zu[r(3227)],Iu=p+Lu,ju=A[r(2613)](A[r(7658)](k,Du),A[r(6237)](A[r(4517)](Iu,0),p>>>0)?1:0),Ku=(Iu=A.EjYPo(Iu,xu),ju=A.OGhqJ(A[r(9973)](ju,au),A[r(528)](Iu,0)>>0?1:0),Iu=A.CRnlh(Iu,du),ju=A[r(2809)](ju+Eu,A[r(4257)](Iu>>>0,A[r(4887)](du,0))?1:0),Iu=A[r(1902)](Iu,V),ju=A.tulgK(ju,U)+(A[r(1039)](Iu,0)>>0,Y>>>0)?1:0),0),G=H,Y=P,H=l,P=m,l=N,m=M,M=0|A[r(3868)](Iu,Ku),N=A.ZKaon(A.EjYPo(A[r(8420)](ju,yu),A.xqsqL(M>>>0,A[r(439)](Iu,0))?1:0),0)}else _0xd49851=_0x367ebd[_0xe8706a],this[r(8014)](_0xb07926);g=e[r(3227)]=A[r(6882)](g,M),e[r(2659)]=A[r(9884)](A[r(9055)](w,N),A.fLeag(A[r(6876)](g,0),M>>>0)?1:0),B=i[r(3227)]=A[r(4614)](B,m),i[r(2659)]=A[r(9330)](C,l)+(A[r(443)](A[r(4887)](B,0),A[r(8219)](m,0))?1:0),L=c.low=L+P,c.high=A[r(719)](A[r(10370)](D,H),A[r(7765)](A.rdDkp(L,0),A.qoCcq(P,0))?1:0),E=o[r(3227)]=E+Y,o[r(2659)]=A[r(8181)](A[r(9377)](z,G),A[r(7031)](E,0)>>0?1:0),I=q[r(3227)]=A[r(7813)](I,S),q[r(2659)]=A[r(8438)](A[r(3358)](d,J),A[r(9963)](I,0)>>0,A.xLmDK(X,0))?1:0),h=a.low=A[r(7604)](h,R),a.high=A[r(8420)](A.QUOvE(y,O),A.itqrU(h>>>0,R>>>0)?1:0),Q=x[r(3227)]=A[r(7658)](Q,p),x.high=A[r(5481)](A[r(7219)](_,k),A.DqGZo(A[r(4521)](Q,0),A[r(1039)](p,0))?1:0)},_doFinalize:function(){var u=f;if(A[u(2225)](A.wddES,A.wddES)){var n=this._data,r=n[u(7992)],t=A[u(1819)](this[u(6568)],8),e=A[u(6913)](n[u(7822)],8);return r[A.JlCUm(e,5)]|=A.lHkFx(128,A[u(562)](24,A.vbjQB(e,32))),r[A[u(5770)](A[u(4467)](A[u(4354)](A.gCsHk(e,128),10),5),30)]=Math[u(4727)](t/4294967296),r[A[u(3868)](A[u(8e3)](A[u(4517)](A.tulgK(e,128),10),5),31)]=t,n[u(7822)]=A.zaDFB(r[u(7855)],4),this[u(3595)](),this[u(8810)][u(8585)]()}throw new _0x11b03d(u(9777))},clone:function(){var u=f,n={crjJs:function(u,n){return u(n)}};if(r[u(2395)](r[u(6714)],r[u(4011)])){var A=e[u(6429)].call(this);return A[u(8810)]=this[u(8810)][u(6429)](),A}try{n[u(6606)](_0x470cc1,_0x325e7c[u(6460)](_0x4494ee))}catch(r){n[u(6606)](_0x2fa142,r)}},blockSize:32});t[f(2864)]=e[f(5404)](a),t.HmacSHA512=e[f(2281)](a)}(),u[n(2864)]})},{"./core":4,"./x64-core":37}],36:[function(u,n,r){var f=_0x7f58,A={poSFQ:function(u,n){return u(n)},rshQD:f(2525),rmyaW:f(8961),pWyKV:function(u,n,r,f,A){return u(n,r,f,A)},SLkme:function(u,n){return u===n},HnzeM:"lAMuS",oThae:f(7186),msgNI:function(u,n,r,f,A,t){return u(n,r,f,A,t)},ByRlC:function(u,n){return u(n)},QvdQS:f(3251),SAMQq:function(u,n){return u(n)},ESEJJ:f(7470),RWkOC:"./md5",oaZEF:function(u,n){return u(n)},bUSmn:f(4234),RaNkp:"./cipher-core",ubZuX:function(u,n){return u===n},fuPbS:f(5621),Ebsjf:function(u,n){return u&n},ZXJGV:function(u,n){return u>>>n},vJLFR:function(u,n){return u>>n},gcTey:function(u,r){return A[n(10231)](u,r)},pmDbt:function(u,n){return u^n},LcZrW:function(u,n){return A.RjqZD(u,n)},mDxFB:function(u,r){return A[n(4576)](u,r)},nqidQ:A[n(1269)],IyzyX:function(u,r){return A[n(7202)](u,r)},Eswto:function(u,r){return A[n(8473)](u,r)},cpILO:function(u,r){return A[n(6654)](u,r)},mjZfe:function(u,r){return A[n(2714)](u,r)},PImKr:A.GLyan,oKqMp:function(u,n){return A.JcPWs(u,n)},LdDXV:function(u,n){return A.gXGfw(u,n)},kwkfJ:function(u,n){return u/n},koScl:function(u,r){return A[n(6917)](u,r)}};return function(){var f=n,A={PiiZd:function(u,n){return r[_0x7f58(7435)](u,n)},kQilA:r.PImKr,yVGdh:function(u,n){return r[_0x7f58(1915)](u,n)},HJcnX:f(5413)},t=u,e=t.lib,i=e.WordArray,c=e[f(1116)],o=t.algo,q=[57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4],v=[14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32],b=[1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28],s=[{0:8421888,268435456:32768,536870912:8421378,805306368:2,1073741824:512,1342177280:8421890,1610612736:8389122,1879048192:8388608,2147483648:514,2415919104:8389120,2684354560:33280,2952790016:8421376,3221225472:32770,3489660928:8388610,3758096384:0,4026531840:33282,134217728:0,402653184:8421890,671088640:33282,939524096:32768,1207959552:8421888,1476395008:512,1744830464:8421378,2013265920:2,2281701376:8389120,2550136832:33280,2818572288:8421376,3087007744:8389122,3355443200:8388610,3623878656:32770,3892314112:514,4160749568:8388608,1:32768,268435457:2,536870913:8421888,805306369:8388608,1073741825:8421378,1342177281:33280,1610612737:512,1879048193:8389122,2147483649:8421890,2415919105:8421376,2684354561:8388610,2952790017:33282,3221225473:514,3489660929:8389120,3758096385:32770,4026531841:0,134217729:8421890,402653185:8421376,671088641:8388608,939524097:512,1207959553:32768,1476395009:8388610,1744830465:2,2013265921:33282,2281701377:32770,2550136833:8389122,2818572289:514,3087007745:8421888,3355443201:8389120,3623878657:0,3892314113:33280,4160749569:8421378},{0:1074282512,16777216:16384,33554432:524288,50331648:1074266128,67108864:1073741840,83886080:1074282496,100663296:1073758208,117440512:16,134217728:540672,150994944:1073758224,167772160:1073741824,184549376:540688,201326592:524304,218103808:0,234881024:16400,251658240:1074266112,8388608:1073758208,25165824:540688,41943040:16,58720256:1073758224,75497472:1074282512,92274688:1073741824,109051904:524288,125829120:1074266128,142606336:524304,159383552:0,176160768:16384,192937984:1074266112,209715200:1073741840,226492416:540672,243269632:1074282496,260046848:16400,268435456:0,285212672:1074266128,301989888:1073758224,318767104:1074282496,335544320:1074266112,352321536:16,369098752:540688,385875968:16384,402653184:16400,419430400:524288,436207616:524304,452984832:1073741840,469762048:540672,486539264:1073758208,503316480:1073741824,520093696:1074282512,276824064:540688,293601280:524288,310378496:1074266112,327155712:16384,343932928:1073758208,360710144:1074282512,377487360:16,394264576:1073741824,411041792:1074282496,427819008:1073741840,444596224:1073758224,461373440:524304,478150656:0,494927872:16400,511705088:1074266128,528482304:540672},{0:260,1048576:0,2097152:67109120,3145728:65796,4194304:65540,5242880:67108868,6291456:67174660,7340032:67174400,8388608:67108864,9437184:67174656,10485760:65792,11534336:67174404,12582912:67109124,13631488:65536,14680064:4,15728640:256,524288:67174656,1572864:67174404,2621440:0,3670016:67109120,4718592:67108868,5767168:65536,6815744:65540,7864320:260,8912896:4,9961472:256,11010048:67174400,12058624:65796,13107200:65792,14155776:67109124,15204352:67174660,16252928:67108864,16777216:67174656,17825792:65540,18874368:65536,19922944:67109120,20971520:256,22020096:67174660,23068672:67108868,24117248:0,25165824:67109124,26214400:67108864,27262976:4,28311552:65792,29360128:67174400,30408704:260,31457280:65796,32505856:67174404,17301504:67108864,18350080:260,19398656:67174656,20447232:0,21495808:65540,22544384:67109120,23592960:256,24641536:67174404,25690112:65536,26738688:67174660,27787264:65796,28835840:67108868,29884416:67109124,30932992:67174400,31981568:4,33030144:65792},{0:2151682048,65536:2147487808,131072:4198464,196608:2151677952,262144:0,327680:4198400,393216:2147483712,458752:4194368,524288:2147483648,589824:4194304,655360:64,720896:2147487744,786432:2151678016,851968:4160,917504:4096,983040:2151682112,32768:2147487808,98304:64,163840:2151678016,229376:2147487744,294912:4198400,360448:2151682112,425984:0,491520:2151677952,557056:4096,622592:2151682048,688128:4194304,753664:4160,819200:2147483648,884736:4194368,950272:4198464,1015808:2147483712,1048576:4194368,1114112:4198400,1179648:2147483712,1245184:0,1310720:4160,1376256:2151678016,1441792:2151682048,1507328:2147487808,1572864:2151682112,1638400:2147483648,1703936:2151677952,1769472:4198464,1835008:2147487744,1900544:4194304,1966080:64,2031616:4096,1081344:2151677952,1146880:2151682112,1212416:0,1277952:4198400,1343488:4194368,1409024:2147483648,1474560:2147487808,1540096:64,1605632:2147483712,1671168:4096,1736704:2147487744,1802240:2151678016,1867776:4160,1933312:2151682048,1998848:4194304,2064384:4198464},{0:128,4096:17039360,8192:262144,12288:536870912,16384:537133184,20480:16777344,24576:553648256,28672:262272,32768:16777216,36864:537133056,40960:536871040,45056:553910400,49152:553910272,53248:0,57344:17039488,61440:553648128,2048:17039488,6144:553648256,10240:128,14336:17039360,18432:262144,22528:537133184,26624:553910272,30720:536870912,34816:537133056,38912:0,43008:553910400,47104:16777344,51200:536871040,55296:553648128,59392:16777216,63488:262272,65536:262144,69632:128,73728:536870912,77824:553648256,81920:16777344,86016:553910272,90112:537133184,94208:16777216,98304:553910400,102400:553648128,106496:17039360,110592:537133056,114688:262272,118784:536871040,122880:0,126976:17039488,67584:553648256,71680:16777216,75776:17039360,79872:537133184,83968:536870912,88064:17039488,92160:128,96256:553910272,100352:262272,104448:553910400,108544:0,112640:553648128,116736:16777344,120832:262144,124928:537133056,129024:536871040},{0:268435464,256:8192,512:270532608,768:270540808,1024:268443648,1280:2097152,1536:2097160,1792:268435456,2048:0,2304:268443656,2560:2105344,2816:8,3072:270532616,3328:2105352,3584:8200,3840:270540800,128:270532608,384:270540808,640:8,896:2097152,1152:2105352,1408:268435464,1664:268443648,1920:8200,2176:2097160,2432:8192,2688:268443656,2944:270532616,3200:0,3456:270540800,3712:2105344,3968:268435456,4096:268443648,4352:270532616,4608:270540808,4864:8200,5120:2097152,5376:268435456,5632:268435464,5888:2105344,6144:2105352,6400:0,6656:8,6912:270532608,7168:8192,7424:268443656,7680:270540800,7936:2097160,4224:8,4480:2105344,4736:2097152,4992:268435464,5248:268443648,5504:8200,5760:270540808,6016:270532608,6272:270540800,6528:270532616,6784:8192,7040:2105352,7296:2097160,7552:0,7808:268435456,8064:268443656},{0:1048576,16:33555457,32:1024,48:1049601,64:34604033,80:0,96:1,112:34603009,128:33555456,144:1048577,160:33554433,176:34604032,192:34603008,208:1025,224:1049600,240:33554432,8:34603009,24:0,40:33555457,56:34604032,72:1048576,88:33554433,104:33554432,120:1025,136:1049601,152:33555456,168:34603008,184:1048577,200:1024,216:34604033,232:1,248:1049600,256:33554432,272:1048576,288:33555457,304:34603009,320:1048577,336:33555456,352:34604032,368:1049601,384:1025,400:34604033,416:1049600,432:1,448:0,464:34603008,480:33554433,496:1024,264:1049600,280:33555457,296:34603009,312:1,328:33554432,344:1048576,360:1025,376:34604032,392:33554433,408:34603008,424:0,440:34604033,456:1049601,472:1024,488:33555456,504:1048577},{0:134219808,1:131072,2:134217728,3:32,4:131104,5:134350880,6:134350848,7:2048,8:134348800,9:134219776,10:133120,11:134348832,12:2080,13:0,14:134217760,15:133152,2147483648:2048,2147483649:134350880,2147483650:134219808,2147483651:134217728,2147483652:134348800,2147483653:133120,2147483654:133152,2147483655:32,2147483656:134217760,2147483657:2080,2147483658:131104,2147483659:134350848,2147483660:0,2147483661:134348832,2147483662:134219776,2147483663:131072,16:133152,17:134350848,18:32,19:2048,20:134219776,21:134217760,22:134348832,23:131072,24:0,25:131104,26:134348800,27:134219808,28:134350880,29:133120,30:2080,31:134217728,2147483664:131072,2147483665:2048,2147483666:134348832,2147483667:133152,2147483668:32,2147483669:134348800,2147483670:134217728,2147483671:134219808,2147483672:134350880,2147483673:134217760,2147483674:134219776,2147483675:0,2147483676:133120,2147483677:2080,2147483678:131104,2147483679:134350848}],a=[4160749569,528482304,33030144,2064384,129024,8064,504,2147483679],x=o.DES=c.extend({_doReset:function(){for(var u=f,n={PyCUS:r[u(2426)]},A=this[u(3370)][u(7992)],t=[],e=0;r[u(6750)](e,56);e++){var i=r[u(9322)](q[e],1);t[e]=r.vTDzY(r[u(2347)](A[r.IblEv(i,5)],r[u(9322)](31,r[u(2133)](i,32))),1)}for(var c=this[u(9466)]=[],o=0;r[u(4334)](o,16);o++){var s=c[o]=[],a=b[o];for(e=0;r[u(9122)](e,24);e++)if(r.LnMQy(r[u(784)],r.HWMlb)){var x=null;try{x=_0x1b4b2b.prototype[u(9965)][u(2210)](_0x481519[u(5974)]())}catch(u){}if(x===n[u(2768)]&&!_0x46bee6.cast)return}else s[r[u(7730)](r[u(4837)](e,6),0)]|=r.mkdoQ(t[r.jZhdB(r.pVahC(v[e]-1,a),28)],r[u(9322)](31,r[u(1842)](e,6))),s[r[u(4230)](4,r[u(7730)](e/6,0))]|=t[r.pVahC(28,r.cFSIc(r[u(9749)](v[r[u(3377)](e,24)],1)+a,28))]<>>31);for(e=1;r[u(6584)](e,7);e++)s[e]=s[e]>>>r[u(3377)](r[u(10077)](r[u(7670)](e,1),4),3);s[7]=r[u(7730)](r[u(4183)](s[7],5),r.trPxj(s[7],27))}var w=this[u(6611)]=[];for(e=0;r[u(4781)](e,16);e++)w[e]=c[r[u(650)](15,e)]},encryptBlock:function(u,n){var r=f;if(!A.PiiZd(A.kQilA,r(6877)))return _0x34a868&&_0x3f7139[r(861)]?_0x1da9c2:{default:_0x55adad};this[r(2924)](u,n,this[r(9466)])},decryptBlock:function(u,n){var A=f;if(r.suynk(r[A(5024)],r[A(5024)]))return this;this[A(2924)](u,n,this._invSubKeys)},_doCryptBlock:function(u,n,t){var e=f;this._lBlock=u[n],this[e(2906)]=u[r.caveE(n,1)],w[e(2210)](this,4,252645135),w[e(2210)](this,16,65535),g[e(2210)](this,2,858993459),g[e(2210)](this,8,16711935),w[e(2210)](this,1,1431655765);for(var i=0;r.ktxHs(i,16);i++)if(r[e(797)](r.xJvIH,"nwnbE")){for(var c=t[i],o=this[e(8009)],q=this[e(2906)],v=0,b=0;r[e(6584)](b,8);b++)r[e(5622)](r.foarA,r[e(6755)])?A[e(5456)](_0x4e1c7b[_0x4833e1],_0x30f312)?delete _0x4a6373[_0x51e7d7]:_0x47e504[_0x5aeb69]=_0x4dfb80[_0x576ee]:v|=s[b][r[e(7013)](r[e(5182)](r[e(9752)](q,c[b]),a[b]),0)];this[e(8009)]=q,this._rBlock=r[e(761)](o,v)}else this.eventMonitor(_0xdc8257[_0x15fe1a]);var x=this._lBlock;this[e(8009)]=this[e(2906)],this[e(2906)]=x,w[e(2210)](this,1,1431655765),g[e(2210)](this,8,16711935),g.call(this,2,858993459),w[e(2210)](this,16,65535),w[e(2210)](this,4,252645135),u[n]=this[e(8009)],u[n+1]=this[e(2906)]},keySize:r[f(3743)](64,32),ivSize:2,blockSize:r[f(8970)](64,32)});function w(u,n){var A=f,t=r[A(5182)](r.gcTey(this[A(8009)]>>>u,this._rBlock),n);this._rBlock^=t,this._lBlock^=r[A(6835)](t,u)}function g(u,n){var A=f;if(r.mDxFB(r[A(1352)],A(6118))){var t=r.IyzyX(r.Eswto(r.IblEv(this[A(2906)],u),this[A(8009)]),n);this._lBlock^=t,this[A(2906)]^=r[A(7648)](t,u)}else _0x204158=_0x3340bf.parse(_0x5aa052)}t.DES=c[f(5404)](x);var C=o[f(6508)]=c[f(6491)]({_doReset:function(){for(var u=f,n=u(8722)[u(7897)]("|"),r=0;;){switch(n[r++]){case"0":this[u(3769)]=x[u(9160)](i[u(4703)](t[u(781)](4,6)));continue;case"1":this._des2=x[u(9160)](i.create(t[u(781)](2,4)));continue;case"2":this[u(8108)]=x[u(9160)](i[u(4703)](t[u(781)](0,2)));continue;case"3":var A=this[u(3370)];continue;case"4":var t=A[u(7992)];continue}break}},encryptBlock:function(u,n){var r=f;this._des1[r(5148)](u,n),this[r(2375)].decryptBlock(u,n),this[r(3769)].encryptBlock(u,n)},decryptBlock:function(u,n){var r=f;A[r(1120)]==A[r(1120)]?(this[r(3769)][r(5122)](u,n),this[r(2375)][r(5148)](u,n),this[r(8108)][r(5122)](u,n)):(_0x23375a=!0,_0xa7a986=_0xe1e63e)},keySize:r[f(3743)](192,32),ivSize:r[f(3743)](64,32),blockSize:r[f(9272)](64,32)});t[f(6508)]=c._createHelper(C)}(),u[n(6508)]})},{"./cipher-core":3,"./core":4,"./enc-base64":5,"./evpkdf":8,"./md5":13}],37:[function(u,n,r){var f=_0x7f58,A={qKGJw:function(u,n){return u(n)},EDyFa:function(u,n){return u===n},DkwMs:function(u,n){return u===n},VAhDB:f(7186),fPBbC:function(u,n){return u!==n},jhJWE:f(1846),auaQv:function(u,n){return u===n},Pywyv:"function",CUfzJ:function(u,n){return u===n},bbvoQ:f(10013),WwqKH:f(3251),FUsmz:f(3169),JTVDY:f(4151),wnTtn:function(u,n){return u=n},kZJud:function(u,n){return u/n},gJMgX:"NoOxW",CJknH:f(4187),RsfTY:"You must pass a resolver function as the first argument to the promise constructor",rezHO:f(6376),wHwNJ:f(5550),nKrgP:f(2527),BeRuG:f(1210),TvXdN:function(u,n){return u!=n},cMetw:f(7186),MTdpl:function(u,n){return u||n},hqhVC:f(1859),TsKKA:function(u,n){return u!==n},vZXjW:f(4316),yOmgj:function(u,n){return u!==n},RTpLi:function(u){return u()},mWBGi:f(9423),pEZVx:function(u,n){return u===n},NThIl:f(9616),ixNhx:function(u){return u()},mXldS:function(u,n){return u===n},wizBQ:f(6136),oRKmq:function(u){return u()},jUkTh:f(3595),Hotcl:function(u,n){return u!==n}};(function(t,e){var i=f,c={HbUSn:function(u,n){return u!==n},rbeeg:A[i(9832)],uUrJH:function(u,n){return u===n},hKqKn:function(u,n){return A.cxLes(u,n)},RJSkc:i(4123),EkEqD:function(u,n){return A[i(7098)](u,n)},bosWu:A.DFWQU,tMYCa:A[i(9718)],LAfnk:function(u,n,r){return A[i(8828)](u,n,r)},ACWRu:function(u,n){return u===n},oVwpS:A.VEJti,psKSm:function(u,n){return A[i(8398)](u,n)},AgUCg:function(u,n){return A.eZbFI(u,n)},kxCjo:A[i(2191)],Ewlxk:function(u){return u()},npHFB:function(u,n){return A[i(9428)](u,n)},cousu:function(u,n){return u>>>n},qWtOA:function(u,n){return A[i(8855)](u,n)},pKiLk:function(u,n){return A[i(10368)](u,n)},vQhTi:function(u,n){return A.IBUls(u,n)},bdAbI:A.iwrks,PyTDG:A[i(8152)],lGjKY:A[i(7608)],CfAib:function(u,n){return A[i(2007)](u,n)},McmSx:A.vCLGB,OOgQI:A[i(10071)],kvkYf:function(u,n){return u(n)},NGwAT:function(u,n){return u!==n},AwvxR:A[i(7261)],iTskP:function(u,n){return u^n},dmuvl:A[i(6607)],WPvvs:i(3173),RfulQ:A[i(7934)],JyKNQ:function(u,n,r,f,t,e){return A[i(5780)](u,n,r,f,t,e)},cJkSD:i(8283),aRJXe:i(10009),XCHmM:function(u,n,r,f){return A[i(5141)](u,n,r,f)},EwaYB:A[i(2578)],pWblM:A[i(7358)],neFQL:function(u,n,r){return u(n,r)},JuGaw:function(u,n,r){return A.ijsUv(u,n,r)},NiKKy:function(u,n){return A[i(10299)](u,n)},jkwrd:function(u,n,r,f,t){return A.hMrFR(u,n,r,f,t)},FsszI:i(7742),gFIxG:"./enc-base64",XgSNW:i(4234),gsVxQ:i(10507),fCxAZ:i(5701),ltdMm:A[i(3921)],wTzaU:function(u,n){return A.eZbFI(u,n)},WpLxD:A[i(9926)],LWJMW:function(u,n){return A[i(5553)](u,n)},JQXyB:A[i(6839)],lKVYp:A.WKEZP,BwGtF:i(4322),RTCFn:A.cqtzO,iwvUC:function(u,n){return A[i(6906)](u,n)},iBYNq:function(u,n,r){return A[i(6999)](u,n,r)},nwTZb:i(3001),tqXHA:A[i(9210)],bcZrG:A.VZetl,JpVZa:A[i(1439)],kbuyU:"end",ZHRgQ:function(u,n){return u>n},PYVjj:A.MUUZq,aqSLq:A.yuQhd,lsPCx:A[i(6728)],cMfdW:function(u,n){return A[i(5609)](u,n)},LjfJm:"kQoAw",TVtjo:function(u,n){return A[i(4162)](u,n)},yLkEC:function(u,n){return u/n},ecMxE:function(u,n){return A[i(2561)](u,n)},SEPwY:function(u,n){return u/n},ZIZBY:i(9319),nthoK:function(u,n){return A[i(6906)](u,n)},wQSva:i(7210),CaQfk:"kBRld",FuYSx:A.gJMgX,ovWhh:A[i(6624)],yRzjS:A[i(8776)],oQLMO:A.rezHO,DZXfn:i(5243),ECxMg:A[i(2899)],JvHLx:A[i(1243)],Cuaip:function(u,n){return u in n},dwBwD:A[i(10110)],koapL:function(u,n){return A[i(4237)](u,n)},zRxNS:A.cMetw,FxayK:function(u,n){return A[i(4608)](u,n)},IXasL:A[i(3882)],nCSZW:function(u,n){return A.OdHvj(u,n)},eupHj:function(u,n){return u||n},IQZYi:function(u,n){return A[i(8678)](u,n)},VpMAo:A[i(6189)],cPoGZ:function(u,n){return A[i(2974)](u,n)},YalIS:function(u){return A[i(7633)](u)},HgHPj:A[i(1716)],uzERQ:A[i(541)],JgyCl:function(u,n){return A.pEZVx(u,n)},xdgEI:A[i(1421)],kkxuG:function(u){return A[i(10452)](u)},vzdhG:function(u,n){return A[i(10154)](u,n)},NqHkL:i(6253),cMiOv:A[i(10094)],FxFfr:function(u){return A[i(6390)](u)}};(function(){var f,o,q,v=i,b={tCAIv:function(u,n){return u===n},EZlNq:A[v(541)],vCbQe:function(u,n){return u!==n},vapwD:function(u,n){return A[v(5587)](u,n)},FQMgE:A.tPrDO,XPXtR:v(3668),pHbHG:v(3020),fyYeD:A[v(843)],RfFtW:function(u,n,r){return A[v(6534)](u,n,r)},evjVS:function(u,n){return A.uGzQS(u,n)},mjSTS:A[v(1812)],qUbFE:function(u,n){return A[v(2007)](u,n)},XzIjp:function(u,n){return A[v(8398)](u,n)},cONMZ:function(u,n){return A[v(4026)](u,n)},BlYAT:function(u,n,r,f,t){return A.hMrFR(u,n,r,f,t)},ELnwR:function(u,n,r,f){return u(n,r,f)},kFGUL:A[v(4317)],mmNhk:function(u,n){return u===n},MYWKO:function(u,n){return A[v(4026)](u,n)},jlNrp:A[v(8457)],hHCqk:A[v(5767)],BPsmd:A.Ervey,LEGzC:function(u,n,r,f,A){return u(n,r,f,A)},awAwQ:function(u,n){return A[v(7885)](u,n)},mMvsK:A[v(8831)],KlYTj:A[v(1680)],sZlRC:A.gscXf,nJRib:A.CkEpo,PSLvA:function(u,n){return u>n},XUewK:function(u,n){return u===n},HrqHq:v(760),sgrJb:function(u,n){return u===n},FlGfI:A[v(2288)],TurIK:v(7700),jYLcB:function(u,n,r){return A[v(5465)](u,n,r)},mPkup:A.tppUP,SdwBg:function(u,n,r){return A[v(6534)](u,n,r)},wENLn:v(3283),KUtWJ:A[v(328)],JzRaw:function(u,n){return A[v(3683)](u,n)},TPLvV:A[v(1488)],hzeJw:function(u,n){return A[v(6671)](u,n)},xMOhQ:function(u,n){return A[v(4026)](u,n)},JcCIf:function(u,n){return u!==n},PfgGw:function(u,n){return A[v(2047)](u,n)},mXzZq:function(u,n){return A[v(5587)](u,n)},UtCvV:function(u,n){return A[v(5587)](u,n)},BoiHN:A[v(5944)],jpkOo:v(1483),tsBbg:A.nrxmi,ojeYo:A.aFAHq,WbzVk:function(u,n,r){return A[v(6664)](u,n,r)},fBcNq:function(u,n){return A[v(1760)](u,n)},CKBss:v(9282),PepGc:function(u,n){return u!==n},VMipf:v(3244),Dhsjx:"scQzm",AlvKc:function(u,n){return A[v(9598)](u,n)},zSpOQ:function(u,n){return A[v(5587)](u,n)},mTZbq:function(u,n){return A[v(1555)](u,n)},qJTRL:v(4050),Yerwt:function(u,n){return A[v(5587)](u,n)},Igbhr:A[v(6678)],mfzmP:v(9971),OqBmF:function(u,n){return A[v(8366)](u,n)},eWzAh:function(u){return u()},uSUCe:function(u,n){return A[v(5976)](u,n)},XwQLX:function(u,n){return A.CbUKO(u,n)},vnNqe:function(u,n,r){return u(n,r)},RGJXP:v(2841),PGQfr:A[v(7644)],eeAIm:A[v(8040)],FMwbO:"bQlFD",ZRPMq:A[v(3530)],Nyxsc:A[v(7733)]};f=this,o=function(){"use strict";var n=v,r={lAHiu:n(4261),vRiPC:function(u,n){return u===n},GuzOR:c[n(4163)],neBGO:function(u,r){return c[n(4953)](u,r)},lmYWs:c[n(9624)],mbJQn:c[n(10209)],imheT:function(u,n,r){return c.LAfnk(u,n,r)},bclqp:function(u,n){return c.ACWRu(u,n)},aZMeI:c[n(8443)],pAiNg:function(u,r){return c[n(2462)](u,r)},BRNWm:function(u,r){return c[n(9773)](u,r)},moKUa:function(u,r){return c[n(7734)](u,r)},gMLvS:"nVAZI",HkQvC:c[n(4740)],fNDXr:function(u){return c[n(2870)](u)},LcaSd:function(u,r){return c[n(1503)](u,r)},qiphj:function(u,r){return c[n(9064)](u,r)},DEzlQ:function(u,n){return c.qWtOA(u,n)},NnIaI:function(u,r){return c[n(4537)](u,r)},blCqQ:function(u,n){return u%n},pwovm:function(u,r){return c[n(844)](u,r)},bBQjO:c[n(7068)],emKrS:"./context",MSUwH:c[n(6752)],hMxBh:c.lGjKY,zYlAR:function(u,n){return c.CfAib(u,n)},iTUDK:c[n(1161)],QlFwG:c[n(6729)],Atpqh:function(u){return c[n(2870)](u)},VudSb:function(u,n){return c.kvkYf(u,n)},caOum:function(u,n){return c.uUrJH(u,n)},QZTUG:function(u,r){return c[n(4279)](u,r)},FYECp:function(u,r){return c[n(524)](u,r)},ovDWz:"rwVsp",TAVAL:c.AwvxR,VgSeh:function(u,r){return c[n(5743)](u,r)},DufuI:function(u,n){return u<1;continue;case"7":_0x4e33d7[u(9850)]=/windows/i[u(2785)](t[u(9109)]);continue;case"8":_0xb42bd[u(9920)]=/macintosh/i[u(2785)](t[u(9109)]);continue}break}else{for(var e=0;b[u(8021)](e,o);e+=2)for(var i=u(3023)[u(7897)]("|"),c=0;;){switch(i[c++]){case"0":var q=z[e];continue;case"1":z[b[u(691)](e,1)]=void 0;continue;case"2":z[e]=void 0;continue;case"3":var v=z[b[u(691)](e,1)];continue;case"4":b[u(736)](q,v);continue}break}o=0}}var d,I,j=void 0;if(C)j=c[n(416)](function(){var u=n;if(b[u(4506)](b.pHbHG,b[u(6693)])){for(var f=_0x94bd0f[u(7992)],A=_0x499fb4[u(7822)],e=[],i=0;i>>n},pbGHG:function(u,n){return u^n},qYvHj:function(u,n){return u&n},KNSoE:function(u,n){return u^n},cBnQb:function(u,n){return u*n},uWiVX:function(u,n){return u*n},Ykabc:function(u,n){return u|n},MGdoH:function(u,n){return u>>>n},yGsJN:function(u,n){return u^n},TbMeA:function(u,n){return u<>>16);continue;case"1":var o=_0x55cd6e[_0x5951af];continue;case"2":_0x42668b[_0x4bc7e3]=e.VOTDq(e[u(6006)](C,8),C>>>24);continue;case"3":_0x278741[_0x438806]=e[u(9347)](C,16)|C>>>16;continue;case"4":_0x53d84b[_0x3340e6]=e.VOTDq(e.NnXIZ(C,24),e.bZMQI(C,8));continue;case"5":_0x7649bd[_0x1b681b]=C;continue;case"6":var g=_0x51e599[D];continue;case"7":B=e[u(5168)](e.pbGHG(e[u(8645)](B,8),e[u(6921)](B,255)),99);continue;case"8":var C=e.KNSoE(e.cBnQb(_0x17ab76[B],257),e[u(1398)](B,16843008));continue;case"9":_0x22c4e6[B]=C;continue;case"10":_0x3afe48[B]=e[u(8017)](C<<8,e[u(8488)](C,24));continue;case"11":_0x1dccd5[_0x55f409]=B;continue;case"12":_0x4e8c08[B]=e[u(5727)](e.NnXIZ(C,24),e[u(8645)](C,8));continue;case"13":var B=e[u(3255)](e[u(888)](_0x3b3146^e[u(7531)](_0x161254,1)^e[u(3504)](_0x175593,2),e[u(6006)](_0x8d1b9,3)),e[u(3312)](_0x1e21fc,4));continue;case"14":_0x58e4c7[B]=_0x405649;continue;case"15":C=e.yjTeX(e[u(888)](e[u(7277)](e[u(10352)](g,16843009),e.uWiVX(D,65537)),257*o),e[u(1398)](_0x21dc9b,16843008));continue;case"16":_0x10612c?(_0x13d83e=o^_0x5efd79[_0x327c1c[_0x56fdda[e[u(3255)](g,o)]]],_0x3759c2^=_0x19d827[_0x182395[_0x439dbd]]):_0x6bc437=_0x48632e=1;continue;case"17":var D=_0x33b1b4[o];continue}break}else if(b){if(e[u(7172)](u(1009),"AXZvO"))return _0x5c06cf.getRandomValues(_0xc68557);b[x][u(8239)]()}x=-1,f=s[u(7855)]}continue}break}}function C(u,n){var r=t;this[r(7617)]=u,this[r(1925)]=n}function B(){}i[t(3269)]=function(u){var n=t,r={GnByg:function(u,n){return e[_0x7f58(3907)](u,n)},hKwWs:e.ytjhg},f=new Array(e.omoWw(arguments[n(7855)],1));if(arguments[n(7855)]>1)for(var A=1;e[n(3780)](A,arguments[n(7855)]);A++)f[A-1]=arguments[A];if(s[n(7606)](new C(u,f)),e[n(6401)](s[n(7855)],1)&&!a){if(!e[n(3863)](n(286),"bHnKg"))return r.GnByg(typeof _0x35cb13,r[n(5635)])?_0x5076ca:_0x3c77eb;q(g)}},C.prototype[t(8239)]=function(){var u=t;this[u(7617)].apply(null,this[u(1925)])},i[t(4654)]=e[t(6449)],i[t(4116)]=!0,i[t(5562)]={},i.argv=[],i.version="",i[t(10462)]={},i.on=B,i[t(995)]=B,i.once=B,i[t(5176)]=B,i[t(2285)]=B,i[t(6009)]=B,i[t(4057)]=B,i.prependListener=B,i[t(4485)]=B,i.listeners=function(u){return[]},i[t(10053)]=function(u){throw new Error(e[t(1855)])},i[t(7797)]=function(){return"/"},i[t(8908)]=function(u){var n=t;if(e[n(2741)](e[n(9275)],e[n(2614)]))throw new Error(e[n(10189)]);var r=new _0x4eaa91(_0x518f8d);_0x514040(r,_0x4897e8,_0x633a58),this[n(3672)](r,_0x18ce76)},i[t(1948)]=function(){return 0}},{}],40:[function(u,n,r){var f=_0x7f58,A={KTnvz:function(u,n,r){return u(n,r)},yDDoX:function(u,n){return u>>n},hLznF:function(u,n){return u+n},CKpXo:function(u,n){return u!==n},twJdY:"next",SuckT:f(10009),KfiEU:f(2525),OUowW:function(u,n){return u(n)},wjdHh:f(3251),jbMYZ:f(2782),iXjpS:f(4261),rBgZY:f(1342),Nofdv:function(u,n){return u===n},WRuXF:f(8602),pCERq:f(6359),AZlZh:function(u,n,r,f){return u(n,r,f)},LSYQk:f(7157),dgMNC:f(2173),FgHwf:function(u,n){return u in n},iVQXu:function(u,n){return u in n},MlsYa:f(6679),KwgAk:"yuXGv",pxqgm:function(u,n){return u-n},rXqJb:function(u,n){return u>=n},pGeqS:f(10270),pyYAM:f(4645),HVBOZ:f(8961),sqYNA:function(u,n){return u<=n},rZXxs:f(6075),PlGuB:f(7970),IZRDh:function(u,n,r){return u(n,r)},BLpeg:function(u,n){return u!==n},QSeoJ:f(10430),VzMBj:f(5124),NCdRZ:function(u,n,r){return u(n,r)},wQHJT:function(u,n){return u>>n},oLbne:f(2433),muSuG:"tQzdW",rgukm:function(u,n){return u===n},UkoGo:f(6209),IEuNs:f(1234),QuDMb:"function",YaRAf:function(u,n){return u(n)},SPolx:f(7663),rVphv:f(385),MAhsV:function(u,n){return u!==n},hPsde:"oQNdu",cnsOq:f(2525),gJtXx:f(2804),UYSBU:f(2794),haxXJ:function(u,n,r,f){return u(n,r,f)},wXzLv:f(2819),XGjyF:"timeout",rJCzP:function(u,n){return u===n},QqUYc:"suspended",rytMQ:f(8961),wEPCP:function(u,n,r,f,A){return u(n,r,f,A)},tAYrg:f(509),JTqqO:function(u,n){return u!==n},Ttabe:f(9800),rnHjd:function(u,n){return u(n)},alghu:function(u,n,r){return u(n,r)},Biyoz:"NTSyf",YbZOW:function(u,n){return u>n},gtNbx:function(u){return u()},yXGKC:function(u,n){return u>>n},ZakrC:function(u,n){return u|n},KgJEs:function(u,n){return i[_0x7f58(1214)](u,n)},QNLCS:function(u,n){return i[_0x7f58(3139)](u,n)},MQIhZ:function(u,n){return i.doxJa(u,n)},OkHTO:function(u,n){return i.XtFcp(u,n)},RNwzX:function(u,n){return i[_0x7f58(1640)](u,n)},QJoyX:function(u,n){return u<>>n},PsQvx:function(u,n){return u<>>n},CgNPQ:function(u,n){return u|n},tqkwJ:function(u,n){return u&n},WqQZj:function(u,n){return u>>>n},DYPLT:f(1192),TEnfV:f(5005)},t=function(){return function(u,n){var r=_0x7f58;if(Array[r(8259)](u))return u;if(A[r(1755)](Symbol[r(9869)],A[r(1962)](Object,u)))return function(u,n){var r=_0x7f58,f=[],t=!0,e=!1,i=void 0;try{for(var c,o=u[Symbol[r(9869)]]();!(t=(c=o[r(6460)]())[r(8379)])&&(f.push(c[r(10292)]),!n||!A[r(681)](f[r(7855)],n));t=!0);}catch(u){e=!0,i=u}finally{if(!A[r(2139)]("ouiXJ",A[r(1034)]))return _0x5e7f86.reduce(function(u,n){return u+(n?1:0)},0);try{!t&&o[r(2525)]&&o[A[r(6192)]]()}finally{if(e)throw i}}return f}(u,n);throw new TypeError(A[r(1972)])}}(),e=function(u){return u&&u[f(861)]?u:{default:u}};Object[f(4594)](r,f(861),{value:!0});var i=A.mxqqR(e,u(A.TEnfV));function c(){var u=f,n=document[u(10284)](A[u(462)]);return n[u(6243)]=1,n.height=1,[n,n[u(1839)]("2d")]}function o(u,n){var r=f;if(!A.jqCKq("tiKnq",A.hsizP))return!(!n||!u[r(9653)]);_0xc14c21=_0x346feb[r(8333)](_0x38ff8d)}function q(u){var n=f;if(!A[n(10319)](n(9710),A[n(6743)]))return u[n(10395)](0,0,10,10),u[n(10395)](2,2,6,6),!u[n(5896)](5,5,"evenodd");_0x49486d[_0x6f3dc8+_0x1881f2]^=_0x52ddd1[_0x3a2bb5]}function v(u,n){var r=f,t={Fscyh:function(u,n,r){return A[_0x7f58(5797)](u,n,r)},BNZJZ:A[r(5487)]};if(A.LxNmP===r(1117))t.Fscyh(_0x45465e,[t[r(1135)]],_0xa81408);else{u[r(6243)]=240,u[r(3327)]=60,n[r(1231)]=A[r(3949)],n[r(6109)]=r(6177),n.fillRect(100,1,62,20),n[r(6109)]=A[r(8234)],n[r(6156)]=A.uAyyg;var e=A[r(2168)](A[r(345)],String[r(7805)](55357,56835));n[r(460)](e,2,15),n[r(6109)]=A[r(7122)],n[r(6156)]="18pt Arial",n[r(460)](e,4,45)}}function b(u,n){for(var r=f,e=A.VuicW[r(7897)]("|"),i=0;;){switch(e[i++]){case"0":n.fill(A[r(1643)]);continue;case"1":n.arc(60,60,20,0,A[r(1258)](Math.PI,2),!0);continue;case"2":for(var c=0;A[r(420)](c,x[r(7855)]);c++)for(var o=A[r(8494)][r(7897)]("|"),q=0;;){switch(o[q++]){case"0":n.beginPath();continue;case"1":n[r(6109)]=b;continue;case"2":n.closePath();continue;case"3":n[r(2529)]();continue;case"4":n[r(2523)](s,a,40,0,A[r(1258)](Math.PI,2),!0);continue;case"5":var v=A[r(2772)](t,x[c],3),b=v[0],s=v[1],a=v[2];continue}break}continue;case"3":n[r(6109)]=A[r(6742)];continue;case"4":u[r(6243)]=122;continue;case"5":u[r(3327)]=110;continue;case"6":n[r(2523)](60,60,60,0,A[r(676)](Math.PI,2),!0);continue;case"7":var x=[[A[r(2845)],40,40],[A[r(811)],80,40],[A[r(3763)],60,80]];continue;case"8":n[r(690)]=A[r(7130)];continue}break}}function s(u){var n=f,r={fvwHj:function(u,n){return A[_0x7f58(7403)](u,n)},vqnpY:function(u,n){return u&n},oLgJW:function(u,n){return A[_0x7f58(8564)](u,n)},HTYfS:function(u,n){return A.StlmK(u,n)},wVUIc:function(u,n){return u&n},dfABB:function(u,n){return u|n},fluUL:function(u,n){return A[_0x7f58(706)](u,n)},Mvbpx:function(u,n){return A[_0x7f58(1004)](u,n)},mxJkM:function(u,n){return A.tqkwJ(u,n)},YOFDS:function(u,n){return A[_0x7f58(2282)](u,n)},EXnkf:function(u,n){return A[_0x7f58(5563)](u,n)},QWIph:function(u,n){return u&n},BXYLa:function(u,n){return A[_0x7f58(1370)](u,n)},zpfRs:function(u,n){return u>>A[u(4676)](6,2*A[u(7310)](_0x2dcad5,4));_0x160ff7[A.ItUgI(_0x226542,2)]|=A[u(1004)](A[u(7403)](z,E),A[u(2828)](24,8*A[u(7310)](_0x2c474b,4))),_0xe7711a++}}},{"crypto-js/md5":13}],47:[function(u,n,r){"use strict";var f=_0x7f58,A={fyPCT:function(u,n,r){return u(n,r)},JQoLw:function(u,n){return u!==n},XNgWT:f(9960),eAuMT:function(u,n){return u===n},PZVQM:f(4261),AtqVz:"symbol",rTmtI:function(u,n){return u!==n},ptXry:f(9132),iClJs:function(u,n){return u instanceof n},VHbFp:"dhewh",geNmJ:function(u,n){return u(n)},aUUmi:f(3251),LXJbr:f(2666),aCvto:f(5019),IrPls:function(u,n){return u<>>n},YWAfO:function(u,n){return u+n},KdcPQ:function(u,n){return u/n},LVoCw:function(u,n){return u*n},dRrjJ:function(u,n){return u*n},gdSus:function(u,n){return u<>>5]|=A[u(3195)](128,24-A[u(2496)](i,32));continue;case"2":t[u(7822)]=4*c[u(7855)];continue;case"3":c[A[u(9559)](A[u(9889)](A[u(6405)](i,64),9)<<4,14)]=_0x486c4a[u(4727)](A[u(5710)](e,4294967296));continue;case"4":var t=this[u(4269)];continue;case"5":this._process();continue;case"6":var e=A[u(6770)](this[u(6568)],8);continue;case"7":var i=A[u(2596)](t.sigBytes,8);continue;case"8":var c=t[u(7992)];continue;case"9":c[A.YWAfO(A[u(395)](A[u(4021)](i,64)>>>9,4),15)]=e;continue}break}},r.isWindowChrome=function(){var u=f;return A[u(4802)](A[u(3280)],A.jwmwd)?A.YOLMk(window[u(645)],void 0):_0x1d7b3b?-1:1},r[f(5956)]=function(){var u=f,n={NtgFU:function(u,n){return A[_0x7f58(6902)](u,n)},TjPEI:A[u(10316)],eAAgT:u(4653),fUicW:function(n,r){return A[u(6513)](n,r)},QTEBl:A[u(8553)],cRpDD:A[u(1521)],eSEhg:A[u(8705)],SRber:A[u(6402)]};return A.UjJoR(e,this,void 0,void 0,regeneratorRuntime[u(655)](function r(){var f=u,A={VVPiv:function(u,r){return n[_0x7f58(1356)](u,r)},rCKtY:function(u,r){return n[_0x7f58(1356)](u,r)},wollU:n[f(9216)],IxXVt:n[f(8642)],uWzJS:"blank page",DcPAv:function(u,r){return n[f(6820)](u,r)},kRyMu:n[f(1664)],PadnQ:n[f(10373)],iWUiM:n.eSEhg,CooZU:n[f(7327)]};return regeneratorRuntime[f(4099)](function(u){var n=f,r={nqGwu:A[n(2988)],ixuvR:A.IxXVt,hjvsk:A[n(4972)],XLkqr:function(u,r){return A[n(7908)](u,r)},fRpGp:A.kRyMu};if(A[n(9259)]==A[n(9259)])for(;;)switch(u[n(2519)]=u[n(6460)]){case 0:return u[n(4922)](A.iWUiM,new Promise(function(u){var f=n;if(r[f(1560)]==r[f(1560)])for(var A=r.ixuvR[f(7897)]("|"),e=0;;){switch(A[e++]){case"0":document[f(2599)][f(3761)](i);continue;case"1":i[f(8624)]=r[f(2112)];continue;case"2":u(r[f(8597)](c,r[f(9091)]));continue;case"3":var i=document.createElement(f(6793));continue;case"4":var c=t(i.contentWindow[f(645)]);continue;case"5":document[f(2599)][f(5453)](i);continue}break}else _0x5974e3()}));case 1:case A[n(2576)]:return u.stop()}else{try{var e=_0xf2dc59[_0x1d7c3a](_0x43f1c7),i=e[n(10292)]}catch(u){return void A[n(5331)](_0x39a6bc,u)}e[n(8379)]?A[n(9978)](_0x59fa3e,i):_0x3d5e82[n(5974)](i)[n(591)](_0x530458,_0xbeeb50)}},r,this)}))}},{}],48:[function(u,n,r){"use strict";var f=_0x7f58,A={jNSII:function(u,n,r){return u(n,r)},aWgST:f(3251),ALMMK:f(8944),EhwME:function(u,n){return un},GTvLj:function(u,n){return u===n},hPmoJ:f(1866),oolCY:"ekbGp",wUykW:f(788),uACOv:function(u,n){return u===n},PzfBB:"emJnw",hbXzL:f(8961),kENPw:f(861),dBImb:function(u,n){return u(n)},MFLJL:f(5212),AnplM:"debugger-checker"},t=function(u,n,r,t){var e=f,i={lNGxm:function(u,n){return A[_0x7f58(5923)](u,n)},CaAMQ:function(u,n){return A[_0x7f58(892)](u,n)},pcApl:A[e(6791)],sowZe:e(6529),QHBtA:function(u,n){return u instanceof n},nmzlS:function(u,n){return A[e(3966)](u,n)},FYPHa:function(u,n){return u(n)},qFMon:function(u,n){return A[e(9473)](u,n)},PuFsV:A[e(6201)],nyAAA:A[e(5027)],SqpzM:A[e(7292)]};function c(u){var n=e,f={wnzsw:function(u,n){return i.lNGxm(u,n)},deKYh:function(u,n){return i[_0x7f58(4761)](u,n)}};if(i[n(5886)]!==i[n(4732)])return i.QHBtA(u,r)?u:new r(function(r){f[n(10390)](r,u)});for(;f.wnzsw(_0x1bbbf5[n(7855)],4);)_0x21b355.push(_0x7c8674)}return new(r||(r=Promise))(function(r,f){var o=e,q={jrDsc:function(u,n){return u instanceof n},wygVC:function(u,n,r){return A[_0x7f58(8474)](u,n,r)},DecEm:function(u,n){return u!==n},RQDpJ:function(u,n){return A.MMesM(u,n)},PyZyb:A.nIAUq};function v(u){var n=_0x7f58,r={NcOeJ:function(u,n){return i.nmzlS(u,n)}};try{i[n(1914)](s,t[n(6460)](u))}catch(u){if(!i[n(3686)](i[n(7583)],i[n(7583)]))return q.jrDsc(_0x3647a6,_0x4288ac)?_0xc08b4c:new _0x5ba301(function(u){r[n(9539)](u,_0x319088)});i[n(2396)](f,u)}}function b(u){var n=_0x7f58,r={USAEB:function(u,n,r){return q.wygVC(u,n,r)}};if(q[n(2675)]("FCNYu","vTWcg"))try{q[n(6810)](s,t[q[n(10120)]](u))}catch(u){f(u)}else r[n(10346)](_0x3eb92e,_0x1ad2f2,_0x5d5fb7)}function s(u){var n=_0x7f58,f={iQFPG:i[n(2996)]};if(!i.qFMon(i[n(1863)],n(5830)))return!(!_0x54b79d||!_0xfc2de8[n(760)](f[n(9171)]));u.done?r(u[n(10292)]):i.nmzlS(c,u.value).then(v,b)}A[o(2154)](s,(t=t[o(6346)](u,n||[]))[o(6460)]())})};Object[f(4594)](r,A.kENPw,{value:!0}),r[f(2481)]=void 0;var e=A[f(5274)](u,A[f(9432)]);r.debuggerChecker={name:A[f(5190)],isOpen:function(){var u=f;if(!A[u(8827)](A.hPmoJ,A[u(8926)]))return t(this,void 0,void 0,regeneratorRuntime[u(655)](function n(){var r,f=u,t={feLIT:function(u,n,r){return A[_0x7f58(7192)](u,n,r)},EJSOa:function(u,n){return A.seyQU(u,n)},Wntps:f(3251),BBZTm:function(u,n){return u(n)},FsGEy:A[f(10482)],XMWbM:function(u,n){return A[f(1550)](u,n)},pZOkL:A.trKdR,sFkpP:A[f(624)],qgRaK:function(u,n){return A.oDUJS(u,n)},wKSTL:f(8961)};return regeneratorRuntime[f(4099)](function(u){for(var n=f,A={KTisc:function(u,n,r){return t[_0x7f58(8560)](u,n,r)},fXNcy:function(u,n){return t[_0x7f58(6831)](u,n)},rlcqy:t[n(2705)],HyJlC:function(u,r){return t[n(2606)](u,r)},DIOPl:t[n(1423)]};;)if(t[n(7882)](t[n(5936)],n(410)))switch(u[n(2519)]=u[n(6460)]){case 0:return r=(0,e.now)(),function(){}[n(9413)](n(4876))(),u[n(4922)](t[n(9986)],t[n(5697)]((0,e[n(4974)])()-r,100));case 3:case t[n(8832)]:return u[n(9572)]()}else _0x5c0c85[n(8018)]=_0x1dc674=A.KTisc(_0x39a0a8,A.fXNcy(_0xff700,A.rlcqy),A[n(2636)](_0x1c5261,A.DIOPl))},n,this)}));_0x421a2a=(0,_0x28ac90[u(5318)])(_0x20d56a[u(7954)])},isEnable:function(){var u=f,n={NNXox:A.wUykW,FwrnV:function(u,n){return A.uACOv(u,n)},fGqqT:A[u(1906)],bkvuQ:A[u(614)]};return t(this,void 0,void 0,regeneratorRuntime[u(655)](function r(){var f=u,A={Dpxzg:n.NNXox,tYwOL:function(u,r){return n.FwrnV(u,r)},FiBpH:f(4002),ZpxUa:n[f(6570)],hxMMP:f(2525),oqJEz:n[f(3295)]};return regeneratorRuntime[f(4099)](function(u){var n=f,r={jFCYv:A[n(3466)]};if(A[n(7735)](A[n(5310)],A.ZpxUa)){var t={LQmyw:r[n(1770)]};return function(){for(var u=n,r=t[u(9679)][u(7897)]("|"),f=0;;){switch(r[f++]){case"0":var A=o[u(329)];continue;case"1":var e=o[u(1667)];continue;case"2":var i=A[u(9614)]=v[u(6491)]({_doReset:function(){var n=u;this[n(8810)]=new(q[n(6848)])([new(c[n(6848)])(3418070365,3238371032),new(c[n(6848)])(1654270250,914150663),new(c[n(6848)])(2438529370,812702999),new(c[n(6848)])(355462360,4144912697),new(c[n(6848)])(1731405415,4290775857),new(c[n(6848)])(2394180231,1750603025),new c.init(3675008525,1694076839),new c.init(1203062813,3204075428)])},_doFinalize:function(){var n=u,r=v[n(7764)][n(2210)](this);return r[n(7822)]-=16,r}});continue;case"3":var c=e.Word;continue;case"4":var o=_0x468c8c;continue;case"5":var q=e[u(8122)];continue;case"6":o[u(1767)]=v[u(2281)](i);continue;case"7":o[u(9614)]=v._createHelper(i);continue;case"8":var v=A[u(2864)];continue}break}}(),_0x2c06dd[n(9614)]}for(;;)switch(u[n(2519)]=u[n(6460)]){case 0:return u[n(4922)](A[n(9505)],!0);case 1:case A.oqJEz:return u[n(9572)]()}},r,this)}))}}},{"../shared/utils":64}],52:[function(u,n,r){"use strict";var f=_0x7f58,A={LgaRK:function(u,n){return u(n)},SrBvN:function(u,n){return u!==n},VgjJe:f(9477),umjpV:function(u,n,r){return u(n,r)},qtvNQ:function(u,n){return u===n},fhODt:"symbol",ZECzp:f(7024),JlFtD:function(u,n){return u(n)},fOvPn:f(5667),SuGoe:function(u,n){return u(n)},bWTtF:f(972),iqcNT:function(u,n){return u+n},lxDKq:function(u,n){return u*n},uTrbI:"./core",rEcdI:"./sha1",oPtWV:f(10311),gGCSu:f(746),TYaWd:f(731),VaOoN:f(8961),gWGni:function(u,n){return u(n)},jpYyn:f(6604),TEaIc:f(5681),jvlCi:f(6964),fMSew:f(5902),rlDtu:function(u,n,r,f,A){return u(n,r,f,A)},XzWXP:function(u,n){return u!==n},xrdsL:f(2408),ALHmn:f(2525),VEzoe:function(u,n){return u!==n},ihxhA:"yGXHk",zJZSz:"VscVy",RKKeg:f(861),kvpHz:f(8276),jkRcy:f(6180),zKgEs:f(5212),IEXFy:f(3439)},t=function(u,n,r,t){var e=f,i={baftE:function(u,n,r){return A[_0x7f58(3236)](u,n,r)},lefuf:function(u,n){return A[_0x7f58(10333)](u,n)},CJmHK:A[e(3111)],mNyWs:A.ZECzp,ONxxl:function(u,n){return A[e(6053)](u,n)},CnkHs:A.fOvPn,xMSMB:function(u,n){return A.SuGoe(u,n)},xRLYe:A[e(9332)],Kmlay:function(u,n){return A[e(6053)](u,n)},ivZES:function(u,n){return A[e(8757)](u,n)},tqUHl:function(u,n){return A.lxDKq(u,n)},fTOmH:function(u,n,r){return u(n,r)},WbNCU:A.uTrbI,DRcGr:A.rEcdI,cAcEY:A[e(6899)],lpyGH:function(u,n){return A[e(10333)](u,n)},mqkjm:function(u,n){return A[e(2531)](u,n)},ENFHa:A[e(9738)],XlBqr:A[e(8986)],JmCLS:e(2525),IsYqt:A[e(3927)]};function c(u){var n=e,f=function(u,n){return A[_0x7f58(2838)](u,n)};return A[n(2531)](A[n(4563)],A[n(4563)])?i[n(1818)](_0x4842f0,_0x5e9d42,0):u instanceof r?u:new r(function(n){f(n,u)})}return new(r||(r=Promise))(function(r,f){var A=e,o={BPgxP:function(u,n){return i[_0x7f58(1007)](u,n)},ktdyk:function(u,n){return i[_0x7f58(1589)](u,n)},vYPbY:function(u,n){return i[_0x7f58(1007)](u,n)},eHjDW:function(u,n){return u%n},cMRHe:function(u,n,r){return i[_0x7f58(5192)](u,n,r)},RqadN:i[A(7600)],GdIxj:i[A(5774)],RVzaQ:i[A(6786)],Cisyl:function(u,n){return i[A(3381)](u,n)},HndgT:A(1505),VEBEh:function(u,n){return i.Kmlay(u,n)},XmdCk:function(u,n){return i[A(6823)](u,n)},EskZx:i.ENFHa,ynGMe:i.XlBqr,qBBia:i.JmCLS,MufXO:i[A(8686)]};function q(u){var n=A,r={EmJPE:function(u,n,r){return o[_0x7f58(10487)](u,n,r)},gzZLO:o[n(479)],dlqiR:o.GdIxj,eCHBS:o[n(6312)]};try{if(o[n(6594)](o.HndgT,o.HndgT))o.VEBEh(b,t[n(6460)](u));else for(var e=0;e<5;e++)_0x29ddc9[o.BPgxP(_0x2a4b89,o[n(4458)](5,e))]=o[n(1451)](e,o.ktdyk(o.eHjDW(o.vYPbY(2*_0x43a442,o.ktdyk(3,e)),5),5))}catch(u){o[n(3852)](o[n(6572)],o[n(6572)])?r[n(5968)](_0x22a300,[r.gzZLO,r[n(10175)],r[n(1618)]],_0x3c1f4b):o[n(8921)](f,u)}}function v(u){var n=A,r={sJvDj:function(u,n){return i[_0x7f58(5629)](u,n)},JiBEC:function(u,n){return u!==n},ltjAi:i[n(9608)]};if(i[n(5705)]!==i.mNyWs)return _0x2fbb62&&"function"==typeof _0x25c7d3&&r[n(8217)](_0x249f87[n(9413)],_0x112985)&&r.JiBEC(_0x156b08,_0xbf73ae[n(10129)])?r.ltjAi:typeof _0x3316fe;try{i[n(9768)](b,t[n(10009)](u))}catch(u){if(i[n(6676)]===i.CnkHs)i[n(9769)](f,u);else for(var e={BfgKi:function(u,r){return o[n(8921)](u,r)},TMDmS:o[n(1612)]};;)switch(_0x2fe6a6[n(2519)]=_0x5654ab[n(6460)]){case 0:return _0x5d7619[n(4922)](o[n(5383)],new _0x388be1(function(u){var r=n;_0x48349d[r(1210)][r(5809)](e[r(6822)],function(){e.BfgKi(u,_0x2fa54a())})}));case 1:case o[n(8824)]:return _0x118a7f[n(9572)]()}}}function b(u){var n=A;i[n(5629)](i[n(10124)],i.xRLYe)?u.done?i.Kmlay(r,u[n(10292)]):i[n(9768)](c,u[n(10292)])[n(591)](q,v):_0x1a2887[n(566)](!1)}i[A(9768)](b,(t=t[A(6346)](u,n||[])).next())})};Object[f(4594)](r,A[f(4708)],{value:!0}),r.depRegToStringChecker=void 0;var e=A[f(6053)](u,A.kvpHz),i=u(A[f(3560)]),c=A[f(2838)](u,A.zKgEs),o=/ /,q=!1;o[f(9965)]=function(){return q=!0,r[f(4489)].name},r[f(4489)]={name:A[f(3539)],isOpen:function(){var u=f,n={DrKbz:function(u,n){return A[_0x7f58(1082)](u,n)},preFd:A[u(5515)],hLdvl:function(n,r){return A[u(2531)](n,r)},dzHfL:A.TEaIc};if(A.jvlCi!==A[u(2269)])return A[u(10470)](t,this,void 0,void 0,regeneratorRuntime.mark(function u(){return regeneratorRuntime.wrap(function(u){for(var r=_0x7f58;;){if(n[r(8154)](r(5681),n[r(10243)]))return _0x19279b=_0x1acb1d,_0x56bb4b=0,_0x259933=_0x37fb08,_0x1fe750.n=_0x4b1230,_0x14b6d6;switch(u[r(2519)]=u[r(6460)]){case 0:return q=!1,(0,i[r(4783)])({dep:o}),u[r(4922)](r(2525),q);case 3:case r(8961):return u[r(9572)]()}}},u,this)}));n[u(5514)](_0x14c6da,_0x576b80[u(5614)](_0xb23b93[u(5557)],[n.preFd,u(4851),u(5390)]))},isEnable:function(){var u=f,n={Vllob:function(u,n){return A[_0x7f58(4100)](u,n)},zKXdm:u(4051),YZeVT:A[u(8423)],UvJDd:function(u,n){return u===n},rPYhb:u(1333),ybndu:A[u(5308)],Ucdzq:A.VaOoN};if(A[u(9123)](A[u(7477)],A[u(8022)]))return A.rlDtu(t,this,void 0,void 0,regeneratorRuntime.mark(function r(){var f=u,A={dUjpN:function(u,r){return n.Vllob(u,r)},gwGxj:n[f(9080)],lKZoc:n[f(5684)],gUGbL:function(u,r){return n[f(4894)](u,r)},biIRl:n[f(9290)],zJMOe:f(4592),BTZSP:n[f(3832)],zAkjb:n[f(3606)]};return regeneratorRuntime[f(4099)](function(u){var n=f;if(A[n(5741)](A[n(2886)],A[n(3021)]))for(;;){if(A[n(4075)](A.biIRl,A[n(1216)]))throw _0xb0a274;switch(u[n(2519)]=u[n(6460)]){case 0:return u.abrupt(A[n(6411)],(0,c[n(4343)])({includes:[!0],excludes:[e[n(6195)],e.isIE]}));case 1:case A[n(6577)]:return u[n(9572)]()}}else _0x4721e4=_0x2fa2e3,_0x58f2aa=_0x437a59},r,this)}));try{for(var r="3|4|1|2|5|0"[u(7897)]("|"),i=0;;){switch(r[i++]){case"0":return _0x3f8fee[u(5614)](q);case"1":var o=new v;continue;case"2":var q={supported:!0,sampleRate:o.sampleRate,state:o.state,baseLatency:o.baseLatency,outputLatency:o.outputLatency,maxChannelCount:o[u(9165)][u(4622)],numberOfInputs:o[u(9165)][u(9721)],numberOfOutputs:o[u(9165)][u(5254)],channelCount:o[u(9165)][u(9458)],channelCountMode:o[u(9165)].channelCountMode,channelInterpretation:o.destination[u(3032)]};continue;case"3":var v=_0x5d4e24.AudioContext||_0x2401ed[u(5235)];continue;case"4":if(!v)return _0x316713.stringify({supported:!1});continue;case"5":o[u(964)]();continue}break}}catch(n){return _0x51beef[u(5614)]({supported:!1,error:n[u(6264)]})}}}},{"../shared/console":61,"../shared/context":62,"../shared/utils":64}],53:[function(_0x2774f3,_0xf82d1e,_0x1bda81){"use strict";var _0x416ff7=_0x7f58,_0x4fae5b={Oxwey:_0x416ff7(4202),xzEKW:_0x416ff7(6954),VrMHa:function(u,n){return u(n)},DqAMW:function(u,n){return u instanceof n},NMigG:function(u,n){return u!==n},wOYiM:_0x416ff7(272),sgvlz:_0x416ff7(8694),zdtLx:_0x416ff7(10009),HvmpC:function(u,n){return u(n)},IyqXb:_0x416ff7(6663),vzuqZ:_0x416ff7(2770),LlZXK:function(u,n){return u&n},ISIls:function(u,n){return u>>>n},ShVXo:function(u,n){return u%n},dNjfq:"nEDaP",ZFtug:function(u,n){return u!==n},kfUOk:_0x416ff7(775),yUGgW:function(u,n,r,f,A){return u(n,r,f,A)},zNNAq:_0x416ff7(861),VcCsC:function(u,n){return u(n)},XAdVN:_0x416ff7(8276),fpdaH:function(u,n){return u(n)},CsecN:"../shared/console",RDvUo:function(u,n){return u(n)},yyoxO:_0x416ff7(5212),FMZVp:_0x416ff7(1053),FGGLh:_0x416ff7(8780)},_0x3fc1f8=function(_0x17d12b,_0x3c3959,_0x4a4fd3,_0x13cf2b){var _0x4d6904=_0x416ff7,_0x440225={nOcdn:function(u,n){return _0x4fae5b[_0x7f58(6760)](u,n)},Wnfyv:function(u,n){return _0x4fae5b[_0x7f58(561)](u,n)},WGYJn:_0x4fae5b[_0x4d6904(6228)],LQiYu:_0x4fae5b[_0x4d6904(10348)],nevAx:_0x4fae5b[_0x4d6904(10306)],KIOEk:function(u,n){return _0x4fae5b[_0x4d6904(1602)](u,n)}};function _0x4d0b84(u){return _0x440225[_0x4d6904(5696)](u,_0x4a4fd3)?u:new _0x4a4fd3(function(n){n(u)})}return new(_0x4a4fd3||(_0x4a4fd3=Promise))(function(_0x120f43,_0x3b769a){var _0x1a3278=_0x4d6904,_0x3cefff={InsuH:_0x4fae5b.Oxwey,oQzIX:function(u,n){return u!==n},pCDNA:_0x4fae5b.xzEKW,OVViE:function(u,n){return _0x4fae5b.VrMHa(u,n)},gOKxB:function(u,n){return _0x4fae5b[_0x7f58(3011)](u,n)}};function _0x416c6c(u){var n=_0x7f58,r={bzpSr:_0x3cefff.InsuH};try{_0x3cefff[n(943)]("pxAhq",_0x3cefff[n(7300)])?_0x3cefff[n(4886)](_0x378389,_0x13cf2b[n(6460)](u)):_0x348cf0=_0x66c176(r[n(4838)])()}catch(u){_0x3b769a(u)}}function _0x445304(_0x56fbe6){var _0x1995d8=_0x7f58;if(!_0x440225[_0x1995d8(807)](_0x440225[_0x1995d8(8718)],_0x440225[_0x1995d8(2365)])){var _0x38b069=0;try{eval("var _0xc9ecd6 = _0x1995d8;(-1)[_0xc9ecd6(1493)](-1);")}catch(u){_0x38b069=u[_0x1995d8(6264)].length}return _0x38b069}try{_0x378389(_0x13cf2b[_0x440225[_0x1995d8(5885)]](_0x56fbe6))}catch(u){_0x440225[_0x1995d8(6966)](_0x3b769a,u)}}function _0x378389(u){var n=_0x7f58;u[n(8379)]?_0x3cefff[n(2362)](_0x120f43,u.value):_0x3cefff[n(4886)](_0x4d0b84,u[n(10292)])[n(591)](_0x416c6c,_0x445304)}_0x378389((_0x13cf2b=_0x13cf2b[_0x1a3278(6346)](_0x17d12b,_0x3c3959||[])).next())})};Object[_0x416ff7(4594)](_0x1bda81,_0x4fae5b[_0x416ff7(7624)],{value:!0}),_0x1bda81[_0x416ff7(8282)]=void 0;var _0xaafc42=_0x4fae5b[_0x416ff7(10081)](_0x2774f3,_0x4fae5b.XAdVN),_0x15cb41=_0x4fae5b[_0x416ff7(1314)](_0x2774f3,_0x4fae5b[_0x416ff7(2723)]),_0xb80eda=_0x4fae5b[_0x416ff7(4298)](_0x2774f3,_0x4fae5b[_0x416ff7(10214)]),_0x1afe28=(0,_0xaafc42[_0x416ff7(10284)])(_0x4fae5b.FMZVp),_0x5ef118=!1;Object[_0x416ff7(4594)](_0x1afe28,"id",{get:function(){return _0x5ef118=!0,_0x1bda81[_0x416ff7(8282)].name},configurable:!0}),_0x1bda81.elementIdChecker={name:_0x4fae5b[_0x416ff7(1569)],isOpen:function(){return _0x3fc1f8(this,void 0,void 0,regeneratorRuntime.mark(function u(){var n=_0x7f58;if(_0x4fae5b[n(561)](_0x4fae5b[n(9463)],_0x4fae5b[n(10099)]))return regeneratorRuntime[n(4099)](function(u){for(var r=n;;)switch(u[r(2519)]=u[r(6460)]){case 0:return _0x5ef118=!1,(0,_0x15cb41.log)(_0x1afe28),u.abrupt(r(2525),_0x5ef118);case 3:case r(8961):return u[r(9572)]()}},u,this);_0x380b6e[_0x54070f]=new(_0x516f51[n(6848)])}))},isEnable:function(){var u=_0x416ff7,n={JNwZF:function(u,n){return _0x4fae5b[_0x7f58(9389)](u,n)},UcesD:function(u,n){return _0x4fae5b[_0x7f58(8183)](u,n)},rAAZG:function(u,n){return u-n},Xrjla:function(u,n){return _0x4fae5b[_0x7f58(8483)](u,n)},jWMFg:function(u,n){return _0x4fae5b[_0x7f58(561)](u,n)},tsjzC:_0x4fae5b.dNjfq};if(!_0x4fae5b.ZFtug(_0x4fae5b[u(10418)],_0x4fae5b.kfUOk))return _0x4fae5b[u(8079)](_0x3fc1f8,this,void 0,void 0,regeneratorRuntime[u(655)](function u(){return regeneratorRuntime.wrap(function(u){var r=_0x7f58;if(n[r(1164)](r(688),n.tsjzC))for(;;)switch(u[r(2519)]=u.next){case 0:return u[r(4922)](r(2525),(0,_0xb80eda.match)({includes:[!0],excludes:[_0xaafc42.isIE,_0xaafc42[r(8450)],_0xaafc42[r(6195)]]}));case 1:case r(8961):return u[r(9572)]()}else _0x11fe05[r(7606)](_0x13aad7)},u,this)}));var r=_0x298514(n[u(10364)](_0x55023a[n.UcesD(_0x225415,2)]>>>n[u(9875)](16,8*n.Xrjla(_0x53511e,4)),65535));_0x4c0dda[u(7606)](_0x1874e6[u(7805)](r))}}},{"../shared/console":61,"../shared/context":62,"../shared/utils":64}],54:[function(u,n,r){"use strict";var f=_0x7f58,A={GGKmo:function(u,n){return u(n)},Vkuoe:function(u,n){return u instanceof n},ISIFZ:function(u,n){return u!==n},oTCvQ:"./core",AzAeX:"PHxKp",tlPwE:function(u,n){return u(n)},leCIC:f(2841),IHigk:f(2525),HIzVx:function(u,n){return u===n},OlwUl:function(u,n){return u===n},nBNeq:f(8961),Axzwy:function(u,n,r,f,A){return u(n,r,f,A)},QgjFu:function(u,n){return u===n},HOgVd:f(4261),isBvF:function(u,n){return u!==n},PJcHA:f(5056),LOYGf:function(u,n){return u!==n},uKXVD:f(5327),xfzzu:"4|6|3|5|1|2|0",IMoyf:function(u,n){return u&n},gehFf:function(u,n){return u^n},QxqFA:function(u,n){return u===n},XgnZc:f(861)},t=function(u,n,r,t){var e=f,i={iCjcz:function(u,n){return A[_0x7f58(686)](u,n)},nvaZG:function(u,n){return A[_0x7f58(2526)](u,n)},UQDdk:function(u,n){return u===n},czfug:A.oTCvQ,clije:A[e(9502)],kZqpL:function(u,n){return A[e(5204)](u,n)}};function c(u){var n=e,f={dYzgR:function(u,n){return A[_0x7f58(686)](u,n)}};return A[n(10521)](u,r)?u:new r(function(r){f[n(2975)](r,u)})}return new(r||(r=Promise))(function(r,f){var A=e,o={BBzMA:function(u,n){return i[_0x7f58(7959)](u,n)},zvszQ:function(u,n){return i[_0x7f58(6686)](u,n)},VZgPy:A(3943),SpGNj:function(u,n){return i.UQDdk(u,n)},cakDd:i[A(8917)],lmiZU:i[A(5894)],GcTRG:function(u,n){return i[A(7959)](u,n)},Gjmpe:function(u,n){return i[A(7023)](u,n)}};function q(u){var n=A,r={XVnke:function(u,n){return o[_0x7f58(9760)](u,n)}};if(o.zvszQ(o.VZgPy,n(3343)))try{b(t[n(6460)](u))}catch(u){o.BBzMA(f,u)}else try{_0x490590(_0x4ed9f4.next(_0x394088))}catch(u){r[n(5116)](_0x39029a,u)}}function v(u){var n=A,r={ccyHJ:function(u,n){return o[_0x7f58(9806)](u,n)},oEzxY:function(u,n){return u(n)},LOlvF:o[n(4652)],Ogdic:function(u,n,r){return u(n,r)}};if(o[n(7258)]===n(424))r[n(2277)](typeof _0x45a5be,n(7186))?_0x58d584[n(8018)]=_0x22fd02=r[n(1044)](_0x33a91c,r[n(1044)](_0x5a0e6d,r.LOlvF)):r[n(2277)](typeof _0x5cfc0a,n(4261))&&_0xcf7523[n(4388)]?r[n(3356)](_0x16e2e5,[r.LOlvF],_0x56dda2):r[n(1044)](_0x5d67fe,_0xe41918[n(3080)]);else try{o[n(9760)](b,t[n(10009)](u))}catch(u){f(u)}}function b(u){var n=A;u.done?o[n(743)](r,u[n(10292)]):o[n(2983)](c,u[n(10292)])[n(591)](q,v)}b((t=t.apply(u,n||[])).next())})};Object[f(4594)](r,A[f(6387)],{value:!0}),r[f(4786)]=void 0,r.erudaChecker={name:"eruda",isOpen:function(){var u,n=f,r={cTAhe:function(u,n){return u+n},nEUQY:function(u,n){return A[_0x7f58(2526)](u,n)},vyLis:n(5303),wcbrg:"tiKfS",cvuMS:A[n(901)],TfoWh:A.IHigk,IWqcm:function(u,n){return A.HIzVx(u,n)},CqaGC:function(u,n){return A.OlwUl(u,n)},bwOuz:A[n(6332)]};return A.Axzwy(t,this,void 0,void 0,regeneratorRuntime[n(655)](function n(){return regeneratorRuntime.wrap(function(n){for(var f=_0x7f58,A={dPpHX:function(u,n){return r[_0x7f58(5567)](u,n)}};;){if(!r[f(6420)](r[f(5036)],r[f(4509)]))return _0xfd88c4[A[f(3092)]("_",_0x1a79fb)];switch(n[f(2519)]=n[f(6460)]){case 0:if(typeof eruda===r[f(4933)]){n[f(6460)]=2;break}return n[f(4922)](r.TfoWh,r[f(5695)](r[f(5695)](u=r[f(3088)](eruda,null)||r[f(5695)](eruda,void 0)?void 0:eruda[f(2025)],null)||void 0===u?void 0:u[f(2248)],!0));case 2:return n[f(4922)](r[f(6260)],!1);case 3:case r[f(7728)]:return n.stop()}}},n,this)}))},isEnable:function(){var u=f,n={Uusei:function(u,n){return A[_0x7f58(4766)](u,n)},CFOgP:A.HOgVd,NvzHb:function(u,n){return A[_0x7f58(6099)](u,n)},GlmSH:A.PJcHA,SsQje:function(u,n){return A[_0x7f58(1827)](u,n)},NMpku:A[u(4827)],azIsg:A[u(3233)],BOgEd:A.nBNeq,qFUtm:A[u(9995)],ElIqs:function(n,r){return A[u(8390)](n,r)},snReD:function(n,r){return A[u(7436)](n,r)},satAG:function(n,r){return A[u(764)](n,r)},frHAT:"GqGwB"};return t(this,void 0,void 0,regeneratorRuntime[u(655)](function r(){var f=u,A={rNfhu:n[f(9754)],WIKRr:function(u,n){return u^n},ulFSC:function(u,n){return u>>>n},TFPZb:function(u,r){return n[f(3303)](u,r)},okKTt:function(u,r){return n[f(1119)](u,r)}};return n[f(4101)](n[f(7462)],n[f(7462)])?regeneratorRuntime[f(4099)](function(u){var r=f,t={KtoZR:function(u,r){return n.Uusei(u,r)},VcxYQ:n[r(6011)]};if(n[r(7809)](n[r(9716)],n.GlmSH))for(var e=A[r(1679)].split("|"),i=0;;){switch(e[i++]){case"0":this._rBlock=A[r(4160)](b,v);continue;case"1":for(var c=0;c<8;c++)v|=_0x52a369[c][A[r(9121)](A[r(2985)](A[r(4657)](o,q[c]),_0x49c0af[c]),0)];continue;case"2":this[r(8009)]=o;continue;case"3":var o=this[r(2906)];continue;case"4":var q=_0x4818de[_0x1987a6];continue;case"5":var v=0;continue;case"6":var b=this[r(8009)];continue}break}else for(;;){if(n.SsQje(n.NMpku,n.NMpku))return _0x340088&&t[r(637)](typeof _0x1f2420[r(591)],t[r(7666)]);switch(u[r(2519)]=u[r(6460)]){case 0:return u[r(4922)](n.azIsg,!0);case 1:case r(8961):return u.stop()}}},r,this):_0x1631c2(n[f(1523)])}))}}},{}],55:[function(u,n,r){"use strict";var f=_0x7f58,A={QUSbP:function(u,n){return u instanceof n},ABRpL:f(7014),jPPRi:f(5016),IDllP:"return",WRPFc:f(3322),qCHbK:f(1015),QUOfw:function(u,n){return u===n},YvPDR:"pBvTo",QRmRY:function(u,n){return u(n)},WoMjB:f(7186),rxoHl:function(u,n){return u(n)},TogPg:"function",lunbh:f(3251),ZCrVH:"asevB",XvCYl:function(u,n){return u===n},tWqzn:function(u,n){return u===n},IuVRc:f(3594),BiFAC:function(u,n){return u(n)},DVlDC:"throw",tIBhC:function(u,n){return u(n)},QZLDv:f(8961),qfHEM:f(8525),BZSON:function(u,n,r,f,A){return u(n,r,f,A)},hMhCf:function(u,n){return u(n)},rnbpJ:function(u,n){return u*n},alHJl:function(u,n){return u<>>n},KoDah:function(u,n){return u|n},zzZpd:f(9657),WPdlg:function(u,n){return u!==n},vmtFb:f(6672),cRUgD:f(861),hmDBw:function(u,n){return u(n)},HbssH:f(8276),weUEi:f(6180),bDrrw:function(u,n){return u(n)},BXUcH:f(5212),YSwiD:f(6779)},t=function(u,n,r,t){var e=f,i={NGVtq:A[e(1464)],GLnVu:function(u,n){return A[e(7211)](u,n)},WTveC:e(8961),nAStz:"cOJIo",kCiQn:e(2521),UsJHI:function(u,n){return A[e(708)](u,n)},Nujto:A[e(6277)],YAMNH:function(u,n){return A[e(2922)](u,n)},SBoBF:A[e(4541)],uvrsG:function(u,n){return A[e(5865)](u,n)}};function c(u){var n=function(u,n){return u(n)};return A.QUSbP(u,r)?u:new r(function(r){n(r,u)})}return new(r||(r=Promise))(function(r,f){var o=e,q={fBziE:A.ABRpL,GcWdO:function(u,n){return u instanceof n},fDSGw:A[o(5547)],LxLUd:A[o(1464)],nOaBe:function(u,n){return u===n},zdFAR:A.WRPFc,hIKpB:A[o(6140)],WaHLH:function(u,n){return u(n)},SSzxV:function(u,n){return A[o(10158)](u,n)},AfbCq:A[o(1429)],LXEZc:function(u,n){return A[o(4797)](u,n)},gEHLx:A[o(8725)],WiwFL:function(u,n,r){return u(n,r)},TgAfu:function(u,n){return A[o(5967)](u,n)},vvIWj:o(2666),URvVw:A[o(5691)],CYrJZ:A[o(10268)],IWMZh:function(u,n){return u instanceof n},keWbZ:o(5248),sduDM:A.ZCrVH};function v(u){var n=o,r={zVejE:q[n(2e3)],OZlLB:n(8961)};try{if(q[n(6819)](q[n(4833)],q[n(780)]))for(var A=q[n(2158)][n(7897)]("|"),e=0;;){switch(A[e++]){case"0":var i=_0x1cbe61&&q[n(1917)](_0x48b2d5[n(10129)],_0x552d4c)?_0x2683e2:_0x427a70;continue;case"1":_0x5bc416(v,q[n(8131)],{value:_0x182097(_0x2b642f,_0x482c8e,c)});continue;case"2":var c=new _0x302632(_0x129cf9||[]);continue;case"3":return v;case"4":var v=_0x55f76a[n(4703)](i[n(10129)]);continue}break}else q.WaHLH(s,t[n(6460)](u))}catch(u){if(q[n(1448)](q.AfbCq,"pBvTo"))q[n(6028)](f,u);else for(;;)switch(_0x5acc8b[n(2519)]=_0x4d6a57[n(6460)]){case 0:return _0x7216a2.abrupt(r.zVejE,(0,_0x3a8e93[n(4343)])({includes:[!0],excludes:[_0x55767c[n(4793)],_0x3d5382[n(6195)],(_0x3ba546[n(5492)]||_0x3d1b9a[n(4276)])&&_0x4b8b15[n(3512)]]}));case 1:case r[n(284)]:return _0x40f2f9[n(9572)]()}}}function b(u){var n=o,r={szXBG:i[n(8688)],DTzCB:function(u,r){return i[n(9270)](u,r)},jaBUW:i.WTveC};if(i[n(9270)](i[n(488)],i[n(8291)])){var A={zPDYv:r[n(3952)],BIfIe:function(u,f){return r[n(1879)](u,f)},RiACr:r[n(8134)]};return _0x2be7bb[n(4099)](function(u){for(var r=n;;)switch(u[r(2519)]=u[r(6460)]){case 0:return _0x4f231f=0,(0,_0x5808d2[r(2781)])(_0x4b0e6e),u[r(4922)](A[r(1449)],A[r(2764)](_0x4562af,2));case 3:case A.RiACr:return u[r(9572)]()}},_0x435d50,this)}try{i[n(2511)](i[n(1619)],n(3314))?q[n(1448)](typeof _0xcdf14e,q.gEHLx)?_0x2edc76[n(8018)]=_0x1043a4=q.WiwFL(_0x2a9fc2,q[n(4409)](_0x33284a,"./core"),q.WaHLH(_0x3d58c7,q.vvIWj)):q.SSzxV(typeof _0x574cff,q[n(4451)])&&_0x31f40d.amd?q[n(5013)](_0x51abff,[q[n(8720)],n(2666)],_0x573811):_0x4a2354(_0x5d9647[n(3080)]):i[n(5145)](s,t[i.SBoBF](u))}catch(u){i[n(6698)](f,u)}}function s(u){var n=o;if(q[n(7749)]===q[n(9584)]){var f={joDSz:function(u,r){return q[n(7979)](u,r)}};return q[n(3006)](_0x4cfa77,_0x4534d1)?_0x530b20:new _0x100df7(function(u){f[n(9420)](u,_0x42bb19)})}u[n(8379)]?r(u[n(10292)]):q[n(7979)](c,u[n(10292)]).then(v,b)}s((t=t[o(6346)](u,n||[]))[o(6460)]())})};Object.defineProperty(r,A.cRUgD,{value:!0}),r[f(5893)]=void 0;var e=A[f(1376)](u,A.HbssH),i=u(A.weUEi),c=A[f(4797)](u,f(3955)),o=A[f(4971)](u,A[f(4174)]);function q(){}var v=0;q[f(9965)]=function(){return v++,""},r[f(5893)]={name:A[f(8576)],isOpen:function(){var u=f,n={OWmSM:A.QZLDv,sldrE:A[u(8332)]};return A.BZSON(t,this,void 0,void 0,regeneratorRuntime[u(655)](function r(){var f=u;if(n[f(9325)]==n[f(9325)])return regeneratorRuntime[f(4099)](function(u){for(var r=f;;)switch(u[r(2519)]=u.next){case 0:return v=0,(0,i.log)(q),u[r(4922)]("return",2===v);case 3:case n[r(642)]:return u[r(9572)]()}},r,this);throw _0x55fbe4}))},isEnable:function(){var u=f,n={QwQNP:A[u(1464)],DzTtS:A.QZLDv,ESxFD:function(n,r){return A[u(9737)](n,r)},mgJFy:function(n,r){return A[u(9737)](n,r)},xKWLo:function(n,r){return A[u(4659)](n,r)},csRmg:function(n,r){return A[u(8893)](n,r)},gZEWA:function(u,n){return u%n},JFMCF:function(u,n){return A.mUusr(u,n)},IlAFc:function(n,r){return A[u(10156)](n,r)},zwgog:function(u,n){return u&n},Annvh:function(n,r){return A[u(3582)](n,r)},JoXGk:function(u,n){return A.cSOjK(u,n)},GEQIr:function(u,n){return u!==n},OQphT:A.zzZpd};return A[u(9205)](A.vmtFb,u(6672))?_0x1dcd75.parse(A[u(414)](_0x366172,_0x46413f(_0x5f0ed5))):t(this,void 0,void 0,regeneratorRuntime[u(655)](function r(){var f=u,A={IfZOk:function(u,r){return n[_0x7f58(2063)](u,r)},kkGSv:function(u,r){return n[_0x7f58(7550)](u,r)},RLyBC:function(u,r){return n[_0x7f58(6216)](u,r)},pdZrc:function(u,r){return n[_0x7f58(9788)](u,r)},jmQAb:function(u,r){return n[_0x7f58(3508)](u,r)},EeNBQ:function(u,r){return n[_0x7f58(4385)](u,r)},njlCn:function(u,r){return n.xKWLo(u,r)},VHdvM:function(u,r){return n[_0x7f58(7317)](u,r)},dlHhi:function(u,n){return u+n},BVRpW:function(u,n){return u|n},jhHMx:function(u,r){return n[_0x7f58(8247)](u,r)},yCAef:function(u,r){return n[_0x7f58(10411)](u,r)},wafpV:function(u,n){return u<>>n},XSVHh:function(u,n){return u|n}};if(n[f(432)](n[f(871)],n[f(871)])){var t=this[f(4269)],i=t[f(7992)],q=A[f(2992)](this._nDataBytes,8),v=A[f(3474)](t[f(7822)],8);i[v>>>5]|=A[f(5582)](128,A[f(1725)](24,A[f(3472)](v,32))),i[A[f(3659)](A[f(2913)](A.VHdvM(A.dlHhi(v,64),9),4),14)]=A[f(5874)](A[f(8549)](A[f(8159)](A.wafpV(q,8),A[f(7944)](q,24)),16711935),A[f(6790)](A.BVRpW(A[f(5582)](q,24),A[f(2815)](q,8)),4278255360)),t[f(7822)]=A.AxWNa(i[f(7855)]+1,4),this[f(3595)]();for(var b=this._hash,s=b[f(7992)],a=0;a<5;a++){var x=s[a];s[a]=A.yCAef(16711935&(A[f(2913)](x,8)|A.qiFhw(x,24)),4278255360&A[f(7481)](A[f(5582)](x,24),x>>>8))}return b}return regeneratorRuntime[f(4099)](function(u){for(var r=f;;)switch(u[r(2519)]=u[r(6460)]){case 0:return u[r(4922)](n[r(9459)],(0,o[r(4343)])({includes:[!0],excludes:[e[r(4793)],e.isFirefox,(c[r(5492)]||c.isIphone)&&e[r(3512)]]}));case 1:case n[r(4150)]:return u[r(9572)]()}},r,this)}))}}},{"../shared/console":61,"../shared/context":62,"../shared/system-info":63,"../shared/utils":64}],56:[function(u,n,r){"use strict";var f=_0x7f58,A={FKqSY:function(u,n){return uq);case 9:case e[n(5571)]:return u[n(9572)]()}},r,this);for(var i=0;n[t(981)](i,_0x3f158f.length);i++)for(var c="0|2|4|1|3".split("|"),v=0;;){switch(c[v++]){case"0":var x=_0x22fb44[i];continue;case"1":n[t(1625)](n[t(9062)],x)&&(x[t(594)]=!0);continue;case"2":x.enumerable=x[t(3851)]||!1;continue;case"3":_0x1a2b21[t(4594)](_0x23a1be,x[t(6290)],x);continue;case"4":x[t(8441)]=!0;continue}break}}))},isEnable:function(){var u=f,n={noJfr:function(u,n){return A[_0x7f58(2752)](u,n)},tEnOJ:A[u(9402)],BXaEO:u(2525),MryRr:A[u(605)],MIoJK:function(n,r){return A[u(7212)](n,r)}};if(A.zJenz===A[u(855)])return A.XJdfX(t,this,void 0,void 0,regeneratorRuntime[u(655)](function r(){var f=u,A={RzzcL:function(u,n){return u(n)}};return regeneratorRuntime[f(4099)](function(u){for(var r=f;;)if(n[r(762)](n[r(6419)],n[r(6419)]))A[r(6767)](_0x17ccd3,_0x4cf016);else switch(u[r(2519)]=u[r(6460)]){case 0:return u[r(4922)](n[r(1771)],(0,c[r(4343)])({includes:[e[r(3512)]],excludes:[]}));case 1:case n.MryRr:return u[r(9572)]()}},r,this)}));n.MIoJK(_0x3b165d,_0xfc50e4.CryptoJS)}}},{"../shared/console":61,"../shared/context":62,"../shared/utils":64}],57:[function(u,n,r){"use strict";var f=_0x7f58,A={BtWrg:function(u,n){return u(n)},AFWKW:"Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.",mcPMq:"KPJSN",qanqA:f(9933),VAzPX:function(u,n){return u instanceof n},sUXIf:f(2811),SKYWj:function(u,n){return u!==n},mXeXi:f(4897),ouGJC:f(3304),groEH:function(u){return u()},erRKF:f(6057),Wpcff:function(u,n){return u===n},QriKE:f(10009),kYgbX:f(8961),VXTNV:function(u,n,r,f,A){return u(n,r,f,A)},Jhaai:function(u,n){return u!==n},amXKL:f(2525),OPKtj:f(1461),Surmn:f(4261),MTJiO:f(10201),akHCU:function(u,n,r,f,A){return u(n,r,f,A)},HNyui:f(861),mOmaY:f(6180),reACz:"../shared/utils"},t=function(u,n,r,t){var e=f,i={GHndb:function(u,n){return A[_0x7f58(902)](u,n)},KOEpP:A.AFWKW,sfivu:A[e(399)],Vmahj:A[e(7974)],JKwmb:function(u,n){return A[e(3736)](u,n)},hVoJf:function(u,n){return u!==n},bYwql:A[e(9280)],ykNfS:function(u,n){return A[e(3865)](u,n)},WSUsF:A[e(4973)],VBatr:A[e(7208)],xipiN:function(u){return A[e(1112)](u)},IfoVA:A.erRKF,NKFnD:function(u,n){return A[e(9873)](u,n)},lEFwh:A[e(9211)]};return new(r||(r=Promise))(function(f,A){var c=e,o={gpNKw:i[c(9706)],QEiwy:function(u,n){return un}};return regeneratorRuntime[f(4099)](function(u){for(var r=f;;)if(n[r(10474)](n.yvrZg,r(2583)))switch(u[r(2519)]=u.next){case 0:return u.abrupt(n[r(7222)],(0,c[r(4343)])({includes:[!0],excludes:[i[r(4063)]]}));case 1:case n.lhOyX:return u[r(9572)]()}else if(_0x563120[A[r(3708)]])for(typeof _0x555b34[A[r(3708)]]==A[r(7446)]&&(_0x7ad525[A[r(3708)]]=[_0x1574df[A[r(3708)]]]);A[r(9540)](_0x4708d5.preInit.length,0);)_0x4194d2[A[r(3708)]][r(9728)]()()},r,this)}))}}},{"../shared/console":61,"../shared/context":62,"../shared/utils":64}],58:[function(u,n,r){"use strict";var f=_0x7f58,A={mZJNA:function(u,n){return u!==n},KTDtP:"HuTvK",IfxjX:f(3231),vMuGj:function(u,n){return u(n)},hNDwK:f(4519),pcKFg:f(1241),LPFXA:function(u,n){return u instanceof n},mzIKU:function(u,n){return u(n)},lWLIF:f(7186),QQJMw:function(u,n){return u(n)},CAzGu:"function",dMRJU:f(2182),OxkMb:function(u,n){return u(n)},BmoSs:function(u,n){return u===n},ttVBr:f(2841),OMBJr:function(u,n){return u===n},sZWri:function(u,n){return u!==n},KBwXw:f(4865),LyMmQ:f(5624),JfHpC:f(2525),jBDsZ:function(u,n){return u>n},jsPpC:f(8961),AgjJC:f(1894),NKzpC:function(u,n,r,f,A){return u(n,r,f,A)},qYrWP:f(6319)},t=function(u,n,r,t){var e=f,i={GgWOE:function(u,n){return A.mZJNA(u,n)},FKXrg:A[e(4426)],FwEcV:A[e(8927)],whjOf:function(u,n){return A[e(6238)](u,n)},gACWJ:function(u,n){return u!==n},Nzyrw:A[e(1281)],hjtkD:A[e(3182)],klxNV:function(u,n){return A[e(311)](u,n)},bZoOl:function(u,n){return A[e(9386)](u,n)},XkVgJ:function(u,n){return A.vMuGj(u,n)},GqAbW:function(u,n){return u===n},XqAZw:A[e(8176)],BpOku:function(u,n){return A[e(2160)](u,n)},YsENg:A[e(1795)],dYhIG:function(u,n,r){return u(n,r)},jGySW:A.dMRJU,HFCbx:function(u,n){return A[e(3293)](u,n)},kPxKH:function(u,n){return u(n)}};function c(u){var n=e;if(i.gACWJ(i[n(4680)],i[n(7995)]))return i.klxNV(u,r)?u:new r(function(r){var f=n;i[f(9034)](i[f(3518)],i.FwEcV)?i[f(4998)](r,u):this._willSettleAt(_0x5cddf5(_0x1c32cb),_0x2b4ba2)});_0x1e9412(this.promise,this._result)}return new(r||(r=Promise))(function(r,f){var A=e,o={cTnmW:function(u,n){return i.GqAbW(u,n)},Ysctp:i[A(9891)],iMcCc:function(u,n){return i.BpOku(u,n)},XAnps:function(u,n){return u===n},kIExG:i[A(3818)],lEiVi:function(u,n,r){return i[A(2085)](u,n,r)},FcJXy:i[A(2787)],ibnwu:function(u,n){return i.HFCbx(u,n)},HCQQx:"keCAu",UxSLM:function(u,n){return i[A(5410)](u,n)}};function q(u){var n=A;try{o.FcJXy===o[n(2263)]?o.iMcCc(b,t[n(6460)](u)):o[n(6203)](typeof _0xd5678,o[n(5863)])?_0x384146[n(8018)]=_0x1741e0=_0x4e0576(o[n(4490)](_0x36f0e2,n(3251)),o.iMcCc(_0x24d0e3,"./cipher-core")):o[n(9925)](typeof _0x1280c9,o.kIExG)&&_0x1b38b2.amd?o.lEiVi(_0x438871,[n(3251),n(2666)],_0x10abce):o.iMcCc(_0x1617a1,_0x5f3fa7[n(3080)])}catch(u){o[n(1676)](f,u)}}function v(u){var n=A;if(o[n(1083)]!==o.HCQQx)return _0x3a071b;try{o.ibnwu(b,t[n(10009)](u))}catch(u){o.UxSLM(f,u)}}function b(u){var n=A;u[n(8379)]?i[n(7834)](r,u[n(10292)]):i[n(757)](c,u.value)[n(591)](q,v)}i[A(3180)](b,(t=t.apply(u,n||[])).next())})};Object[f(4594)](r,f(861),{value:!0}),r.windowSizeChecker=void 0;r.windowSizeChecker={name:A[f(10223)],isOpen:function(){var u=f;return t(this,void 0,void 0,regeneratorRuntime[u(655)](function n(){var r,f,t=u,e={INBBz:function(u,n){return A[_0x7f58(1384)](u,n)},UwbfF:A[t(7760)],VFbec:function(u,n){return A[t(9918)](u,n)},XBvlQ:function(u,n){return A[t(669)](u,n)},vZHCJ:A[t(5876)],OdTeV:A.LyMmQ,pOraj:A.JfHpC,CMJgu:function(u,n){return A[t(3013)](u,n)},RwBYj:function(u,n){return u-n},ZTaLQ:function(u,n){return u||n},TJBEY:A[t(6548)]};return"HgtuH"===A[t(7514)]?regeneratorRuntime.wrap(function(u){for(var n=t;;)switch(u[n(2519)]=u[n(6460)]){case 0:if(!e[n(6554)](typeof window[n(2681)],e[n(3611)])&&!e[n(7021)](typeof window[n(1686)],n(2841))){if(e[n(2775)](e.vZHCJ,e[n(9208)])){u.next=2;break}return this.create(this[n(3096)],_0x800f78,_0xb24ffe)}return u[n(4922)](e[n(2145)],!1);case 2:if(r=window[n(2681)]-window[n(1686)]>160,f=e.CMJgu(e[n(6707)](window[n(2026)],window[n(9802)]),160),!e[n(7699)](f,r)){u[n(6460)]=6;break}return u[n(4922)](e[n(2145)],!0);case 6:return u[n(4922)](e[n(2145)],!1);case 7:case e.TJBEY:return u[n(9572)]()}},n,this):_0x12dc46.regToStringChecker}))},isEnable:function(){var u={zbnuq:f(8961)};return A.NKzpC(t,this,void 0,void 0,regeneratorRuntime.mark(function n(){return regeneratorRuntime.wrap(function(n){for(var r=_0x7f58;;)switch(n.prev=n.next){case 0:return n[r(4922)](r(2525),!0);case 1:case u[r(8923)]:return n.stop()}},n,this)}))}}},{}],59:[function(u,n,r){"use strict";var f=_0x7f58,A={BeIvz:function(u,n){return u>>n},mKuej:function(u,n){return u|n},sIQiQ:f(5859),WqhLu:f(5220),aLRrv:function(u,n){return u!==n},YzjkI:f(5833),rwooE:function(u,n){return u===n},ahRZn:f(8849),QpxEG:f(9101),rMxLY:function(u,n){return u===n},qTqiO:"Ururc",rOWPV:f(8409),jtYid:f(4411),OIskv:f(1636),unZcb:f(8744),BgZxh:f(995),HirQi:f(2285),yHrBn:f(10019),QHdHy:"detectLoop",pDPlD:f(3480),NThgb:f(861),CZzBn:function(u,n){return u(n)}},t=function(){var u=f,n={bJCdN:function(u,n){return A.yEvSf(u,n)}};if(A[u(1658)](A[u(8325)],A[u(6225)])){function r(n,r){for(var f=u,t=0;A[f(7324)](t,r[f(7855)]);t++)for(var e="3|4|1|2|0"[f(7897)]("|"),i=0;;){switch(e[i++]){case"0":Object[f(4594)](n,c[f(6290)],c);continue;case"1":c[f(8441)]=!0;continue;case"2":A.GmViz(A[f(854)],c)&&(c[f(594)]=!0);continue;case"3":var c=r[t];continue;case"4":c.enumerable=c[f(3851)]||!1;continue}break}}return function(f,t,e){var i=u;if(A[i(2192)]!==A[i(9002)])return t&&A[i(2045)](r,f[i(10129)],t),e&&A[i(10424)](r,f,e),f;n[i(276)](_0x12c7c7,_0x21b4b5[i(6460)](_0x1c002c))}}n[u(276)](_0x289f7f,_0x1f9c3c)}();function e(u,n){var r=f;if(!A[r(3850)](u,n)){if(r(636)==r(636))throw new TypeError(r(10354));_0x1d3467[r(964)](),_0x2ebbdf[r(7953)][r(448)](_0x2f77fb)}}var i=function(u,n,r,t){var e=f,i={VdtFM:function(u,n){return A[_0x7f58(6413)](u,n)},sCIZn:function(u,n){return A[_0x7f58(1658)](u,n)},eJoZs:e(1106),rZUay:function(u,n){return u instanceof n},DIaft:function(u,n){return A.yEvSf(u,n)},jBqNF:A[e(8739)],SDPRK:e(6204),KAXqK:A[e(8258)],OspKq:function(u,n){return A[e(2056)](u,n)}};function c(u){var n=e,f={ryzPT:function(u,n){return i[_0x7f58(4591)](u,n)},rutYT:function(u,n){return i[_0x7f58(3542)](u,n)},BTKfp:i[n(7392)],hcHqI:function(u,n){return u(n)}};return i[n(3671)](u,r)?u:new r(function(r){var A=n,t={rbRxr:function(u,n){return f[_0x7f58(6450)](u,n)}};if(f.rutYT(A(8614),f.BTKfp))f[A(7062)](r,u);else{e&&_0x11b80b[A(4345)](e);var e=_0x55c932[A(4345)](_0x382838)[A(1353)](_0x1b2cbe);_0x3a601e[A(4791)]();for(var i=1;t[A(5057)](i,_0x458751);i++)e=_0x81e3ff[A(1353)](e),_0x4dd01d[A(4791)]();_0x2450ce[A(4189)](e)}})}return new(r||(r=Promise))(function(r,f){var A=e,o={FbzMG:function(u,n){return i[_0x7f58(3542)](u,n)},Dgwdf:i.SDPRK,aLKVb:function(u,n){return u(n)},Xhulk:function(u,n){return u===n},mmLWC:i.KAXqK,kGxWj:function(u,n){return i[_0x7f58(6996)](u,n)}};function q(u){var n=_0x7f58;if(o[n(9673)]("EZzuN",o[n(2931)]))_0xa3f8ee=null;else try{o[n(1296)](b,t.next(u))}catch(u){f(u)}}function v(u){var n=_0x7f58,r={gmkUN:function(u,n){return i[_0x7f58(7963)](u,n)}};try{if(i[n(3542)](i.jBqNF,n(575))){var A=new(_0x44ea70[n(6818)]);A[n(7595)]=_0x5d8e5d.eversion,A[n(8638)]=_0x1d69b2[n(921)],r[n(2266)](_0x20d436,A)}else b(t[n(10009)](u))}catch(u){i[n(7963)](f,u)}}function b(u){var n=_0x7f58;if(o[n(1293)](o[n(3638)],"yEYsJ"))return _0x46a7c7[n(3238)];u.done?o[n(9229)](r,u.value):o[n(9229)](c,u[n(10292)]).then(q,v)}i.OspKq(b,(t=t[A(6346)](u,n||[]))[A(6460)]())})};Object[f(4594)](r,A[f(2724)],{value:!0}),r[f(5548)]=void 0;var c=A.CZzBn(u,"../shared/context"),o=function(){var u=f,n={giuSF:A[u(7105)],ErGWl:function(u,n){return u(n)},BFWZQ:function(n,r){return A[u(5783)](n,r)},lQnwt:A[u(7720)],srOPQ:A[u(10091)],dIPLI:function(n,r){return A[u(7412)](n,r)},urTVA:function(n,r){return A[u(6133)](n,r)},lmwJP:A[u(4022)],oYhEH:A[u(3278)],OlshM:function(u,n,r){return u(n,r)},zBxVd:function(n,r){return A[u(625)](n,r)},NCgri:function(u,n){return A.riAfU(u,n)},GwiQW:function(n,r){return A[u(5137)](n,r)},cuwPh:function(n,r){return A[u(7091)](n,r)},KZcvM:function(n,r){return A[u(4074)](n,r)},qxlOv:function(u,n){return u+n},wygjT:function(n,r){return A[u(4885)](n,r)},iQZOi:function(u,n){return u<>>n},qIIHs:function(u,f){return n[r(390)](u,f)},erRLI:function(u,f){return n[r(9364)](u,f)},DLHat:function(u,r){return n.GwiQW(u,r)},EROXK:function(u,f){return n[r(4830)](u,f)},TdAGs:function(u,f){return n[r(5451)](u,f)},YvwsF:function(u,f){return n[r(6918)](u,f)},vzwvu:function(u,n){return u*n},CiEIA:function(u,r){return n.wygjT(u,r)},idFdV:function(u,r){return n.wygjT(u,r)},ifGkh:function(u,f){return n[r(6167)](u,f)},cPQHD:"element_clickevent_report",JcNPN:n[r(7049)],TWzUr:function(u,n){return u===n},TEoce:n[r(10345)],sViLB:n[r(8861)],yXYuS:function(u,f){return n[r(6585)](u,f)},IvVdd:function(u,f){return n[r(7388)](u,f)},fDSKt:n[r(8405)],YJOxH:r(8961),WcRmg:function(u,f){return n[r(3218)](u,f)},KWQSn:n[r(9895)],FCegq:n[r(3940)]};return n[r(9823)](n.zBKjE,n[r(1399)])?n[r(4717)](_0x43d3fc,_0x136658,_0x1a8dd0):i(this,void 0,void 0,regeneratorRuntime.mark(function u(){var n=r,A={TpZhp:function(u,n){return f[_0x7f58(4598)](u,n)},NwinA:function(u,n){return f[_0x7f58(3143)](u,n)},CLZXg:function(u,n){return f[_0x7f58(7707)](u,n)},cgLDE:function(u,n){return f[_0x7f58(4689)](u,n)},vfjqn:function(u,n){return f[_0x7f58(4020)](u,n)},jvxGY:function(u,n){return u>>>n},GgUlV:function(u,n){return f.TdAGs(u,n)},ptxBo:function(u,n){return f[_0x7f58(5615)](u,n)},vsNVJ:function(u,n){return f[_0x7f58(6351)](u,n)},oRtJJ:function(u,n){return f.EROXK(u,n)},pfPBr:function(u,n){return f[_0x7f58(4598)](u,n)},MJcAO:function(u,n){return f[_0x7f58(6351)](u,n)},VRMZW:function(u,n){return f[_0x7f58(4689)](u,n)},hmUYN:function(u,n){return f.CiEIA(u,n)},mBZCz:function(u,n){return f[_0x7f58(1761)](u,n)},yaSCZ:function(u,n){return f.ifGkh(u,n)},AXzxL:function(u,n){return un},yXSDi:function(u,n,r){return u(n,r)},JIsYA:f.YJOxH};if(f[n(8620)](f[n(1223)],f.FCegq))throw new _0x12109f(f[n(6280)]);var t,e,i,c,o,q,v,b,s=this;return regeneratorRuntime[n(4099)](function(u){for(var r=n,f={OQVPf:A[r(2458)],XJXci:function(u,n){return u+n},mwGPJ:A[r(935)]};;)switch(u[r(2519)]=u[r(6460)]){case 0:t=!1,e="",i=!0,c=!1,o=void 0,u[r(2519)]=5,q=this[r(3357)][Symbol[r(9869)]]();case 7:if(i=(v=q[r(6460)]())[r(8379)]){u[r(6460)]=22;break}return b=v.value,u[r(6460)]=11,b[r(10199)]();case 11:if(!u[r(3366)]){u[r(6460)]=17;break}return e=b[r(4477)],u[r(6460)]=16,b[r(2710)]();case 16:t=u[r(3366)];case 17:if(!t){if(!A.JeHoo(r(5495),A[r(7542)])){u.next=19;break}_0x52c4a8.addEventListener(f[r(2621)],function(u){var n=r;try{throw new _0x32d7c5}catch(r){var A={type:f.OQVPf,appid:f[n(5597)]("",_0x3cc5ff[n(6818)][n(3266)]()),hdid:(0,_0x2791e3[n(9591)])(_0x40e373[n(6818)][n(6030)]),qimei:_0x4dd594[n(6818)][n(2667)],time:(new _0x12bf73)[n(7744)](),action:{elementClassname:_0x2292fe.className,elementId:_0x445f73.id,elementName:_0x616637.localName,clientXY:_0x322075.stringify([u[n(5758)],u[n(8755)]]),screenXY:_0x1e6e42.stringify([u[n(1328)],u.screenY]),isTrusted:_0x44c61a[n(5614)](u.isTrusted),stack:_0x3f6826[n(5614)](r[n(7193)])}},t=_0x2f6fc5[n(5614)](A);_0x56b4ae[n(1889)](t)}})}return u[r(4922)](r(6182),22);case 19:i=!0,u.next=7;break;case 22:u.next=28;break;case 24:u[r(2519)]=24,u.t0=u[r(2819)](5),c=!0,o=u.t0;case 28:u[r(2519)]=28,u[r(2519)]=29,!i&&q[r(2525)]&&q[r(2525)]();case 31:if(u[r(2519)]=31,!c){if(r(5220)!==A[r(2456)])return _0xc1e57d[r(5322)][r(832)]=function(){var u=r,n=_0x32a8ad[u(8364)][u(9648)][u(6491)]();return n[u(9717)]=n[u(6491)]({processBlock:function(n,r){var f=u;this[f(7331)][f(5148)](n,r)}}),n[u(4805)]=n[u(6491)]({processBlock:function(n,r){var f=u;this[f(7331)][f(5122)](n,r)}}),n}(),_0x4a59d7[r(5322)][r(832)];u[r(6460)]=34;break}throw o;case 34:return u.finish(31);case 35:return u[r(8607)](28);case 36:if(A[r(5335)](t,this[r(8671)]))if(A[r(3679)](A.mzDqv,r(5833)))for(var a=255&A[r(2572)](_0x252eac[A[r(2572)](_0x49a629,2)],A[r(6749)](24,A[r(6991)](A[r(7297)](_0x3f02a8,4),8))),x=A[r(3460)](A[r(6364)](_0x4b955c[A[r(7452)](A[r(7528)](_0x439558,1),2)],A[r(6749)](24,A[r(4877)](A[r(7528)](_0x55052f,1)%4,8))),255),w=A.oRtJJ(A[r(8748)](_0x5a4931[A.ptxBo(_0x1fdb27,2)>>>2],24-A[r(3633)](A[r(7916)](A.ptxBo(_0x5ba162,2),4),8)),255),g=A[r(7906)](A[r(9621)](A[r(6634)](a,16),A[r(6634)](x,8)),w),C=0;A[r(4012)](C,4)&&A[r(4012)](A.ptxBo(_0xeed4a,A.zXkFZ(C,.75)),_0x1295bb);C++)_0x43bc69.push(_0x263e59[r(9348)](63&A[r(8748)](g,A.MJcAO(6,A.NwinA(3,C)))));else this[r(8671)]=t,this._broadcast({isOpen:t,checkerName:e});A[r(8575)](this._detectLoopDelay,0)&&!this[r(4640)]?this[r(3617)]=A[r(3066)](setTimeout,function(){return s._detectLoop()},this[r(6509)]):this[r(9572)]();case 38:case A[r(470)]:return u[r(9572)]()}},u,this,[[5,24,28,36],[29,,31,35]])}))}}]),r}try{A[u(6133)](_0x2ba2cc,_0x22b4d9[A[u(4022)]](_0x8cbb3))}catch(n){A[u(2056)](_0x1b00c3,n)}}();r[f(5548)]=o},{"../shared/context":62}],60:[function(u,n,r){"use strict";var f=_0x7f58,A={sMobO:function(u,n){return u!==n},iJrIC:f(10342),RSIxm:"end",dcHfG:function(u,n){return u in n},IjRlj:function(u,n){return u===n},fvLqP:function(u,n){return u(n)},xeaqK:f(10009),HsNiG:f(5921),tLBPf:"SqgMI",ABvdD:f(6818),eVbey:f(7217),nXlvr:f(7168),XcHEm:function(u,n){return u!=n},dVdBn:function(u,n){return u!==n},FwTev:function(u,n){return u!==n},GhZzC:f(9461),lGswM:function(u,n){return u!==n},UYehf:function(u,n,r,f){return u(n,r,f)},aELcF:f(4261),zENNe:f(9654),tHcFa:function(u,n){return u!==n},ueWvx:"Pboez",glhBg:"vKbdK",KHoCc:f(8533),ohZUr:function(u,n){return u!==n},englp:f(2604),PWOrW:f(4154),gUVLb:function(u,n){return u|n},iEgpa:f(2479),pNiJv:f(3251),qgRPx:function(u,n){return u!==n},pjQhr:f(7397),olYTB:function(u,n,r,f,A){return u(n,r,f,A)},FTngC:function(u,n){return u+n},OvKWn:f(3810),wGsxa:function(u,n){return u(n)},BJhej:function(u,n){return u===n},SAwFT:f(5314),KBCcp:f(861),EpIro:f(5548),rVPJN:function(u,n){return u(n)},XGAHe:f(7907),ZlnjU:function(u,n){return u(n)},ipaVi:f(4343),cLRra:f(5325),XlNxV:function(u,n,r){return u(n,r)},YCYUG:f(6366),XXVJv:f(6632)},t=Object[f(4703)]?function(u,n,r,t){var e=f,i={prXgz:A[e(10394)]};void 0===t&&(t=r);var c=Object[e(5862)](n,r);(!c||(A[e(2641)]("get",c)?!n.__esModule:c[e(594)]||c.configurable))&&(c={enumerable:!0,get:function(){var u=e;if(!A[u(882)](A[u(5754)],A[u(5754)]))return n[r];switch(_0x2cd258.prev=_0xde92d1[u(6460)]){case 0:return _0x2ac7d6[u(4922)](u(2525),(0,_0x3202e6[u(4343)])({includes:[!0],excludes:[_0x47de13[u(4063)]]}));case 1:case i[u(9361)]:return _0x4212d0[u(9572)]()}}}),Object[e(4594)](u,t,c)}:function(u,n,r,t){A[f(8988)](t,void 0)&&(t=r),u[t]=n[r]},e=Object.create?function(u,n){var r=f;A[r(882)](A[r(5209)],A[r(9852)])?Object.defineProperty(u,A[r(259)],{enumerable:!0,value:n}):A.fvLqP(_0xe966b,_0x3a997d[A.xeaqK](_0x2df8ec))}:function(u,n){u[A[f(259)]]=n},i=function(u){var n=f;if(A[n(882)](A[n(2207)],n(1361)))for(var r=A[n(7556)][n(7897)]("|"),i=0;;){switch(r[i++]){case"0":e(o,u);continue;case"1":return o;case"2":if(A[n(5824)](u,null))for(var c in u)A[n(8532)](c,A[n(259)])&&Object[n(10129)].hasOwnProperty[n(2210)](u,c)&&t(o,u,c);continue;case"3":var o={};continue;case"4":if(u&&u[n(861)])return u;continue}break}else _0x2abbe3(_0xfe005.CryptoJS)},c=function(u,n){var r=f;if(A[r(8532)]("Hkvat",r(4508)))return{winding:!1,data:""};for(var e in u)A.FwTev(r(7396),A.GhZzC)?A[r(4194)](e,A[r(259)])&&!Object[r(10129)][r(7423)][r(2210)](n,e)&&A[r(4995)](t,n,u,e):_0xa66f87(this[r(867)])},o=function(u,n,r,t){var e=f,i={qByYs:function(u,n){return u(n)},PflZV:function(u,n){return u instanceof n},WjnQs:A[e(6610)],NsQzW:function(u,n){return u===n},MXrkA:e(6352),nvSGB:A[e(2307)],NqVsQ:A.xeaqK,VnOtm:function(u,n){return A.tHcFa(u,n)},OaPlz:A[e(3649)],PeKSZ:A[e(10275)]};function c(u){var n=e;return i[n(6903)](u,r)?u:new r(function(r){i[n(4299)](r,u)})}return new(r||(r=Promise))(function(r,f){var A=e,o={PDabR:function(u,n){return i[_0x7f58(4299)](u,n)},wdhQa:function(u,n){return i[_0x7f58(4299)](u,n)},luedD:i[A(9161)],bXPge:function(u,n){return i.NsQzW(u,n)},nuiqS:i.MXrkA,RFqDi:i.nvSGB,dqGlv:function(u,n){return i.qByYs(u,n)},Qdinf:i[A(7681)],tKSdr:function(u,n){return i.VnOtm(u,n)},GkomL:i.OaPlz,qPfap:function(u,n){return i[A(3008)](u,n)},VLaeh:i[A(6102)]};function q(u){var n=A;try{o[n(9356)](b,t[n(6460)](u))}catch(u){o[n(9765)](f,u)}}function v(u){var n=A;if(o[n(2494)]("AJNdO",o[n(2986)]))typeof _0x50e83d===o.luedD?_0x349219=_0x44d108:_0x35d4b7=_0x73d741;else try{if(o[n(8133)]!==n(1981))o[n(5144)](b,t[o[n(9450)]](u));else if(_0x157897)throw _0xc02901}catch(u){if(o[n(1100)](o.GkomL,o[n(7563)]))throw _0xfe7073;o.wdhQa(f,u)}}function b(u){var n=A;if(o[n(3117)](n(3083),o[n(1696)]))return _0x267477[n(2210)](this,_0x28a3b5);u[n(8379)]?r(u[n(10292)]):o[n(9356)](c,u[n(10292)])[n(591)](q,v)}i[A(4299)](b,(t=t[A(6346)](u,n||[])).next())})};Object.defineProperty(r,A[f(1219)],{value:!0}),r.specificVersionMatch=r.match=r[f(7546)]=r.DevtoolsDetector=r[f(5384)]=r[f(9572)]=r.detetct_console_async=r[f(6712)]=r[f(8744)]=r[f(2285)]=r.addListener=void 0;var q=A[f(7415)](u,f(3435));Object.defineProperty(r,A.EpIro,{enumerable:!0,get:function(){var u=f;return A[u(996)](A[u(7408)],A[u(9597)])?q.DevtoolsDetector:A.KHoCc}});var v=i(A.rVPJN(u,A[f(3596)]));r[f(7546)]=v;var b=new(q[f(5548)])({checkers:[v[f(4250)],v[f(4786)],v[f(8282)],v.regToStringChecker,v[f(5893)],v[f(4489)],v.dateToStringChecker,v[f(409)]]});r.addListener=function(u){b.addListener(u)},r[f(2285)]=function(u){b[f(2285)](u)},r[f(8744)]=function(){var u=f;if(A[u(8988)](u(2479),A[u(8448)]))return b.isLaunch();var n=_0x3b94f5>0?A[u(6695)](_0x3da9e0,0):0;return A[u(8988)](this[u(5358)](n,n+_0x3fcace[u(7855)]),_0x31e553)},r.launch=function(){b.launch()},r[f(3119)]=function(){var u=f,n={nFLPP:function(u,n){return A[_0x7f58(4473)](u,n)},AuzoG:A[u(6430)],oXjrN:"end",WxePp:function(n,r){return A[u(2822)](n,r)},DuXKb:A[u(9681)]};return A[u(5795)](o,this,void 0,void 0,regeneratorRuntime.mark(function r(){var f=u,A={Jslgz:f(2525),Rdctn:n[f(4046)]};if(!n[f(4173)](n[f(737)],n[f(737)]))return regeneratorRuntime[f(4099)](function(u){for(var n=f;;)switch(u[n(2519)]=u[n(6460)]){case 0:return u[n(4922)](A[n(7320)],b[n(1636)]());case 1:case A[n(8341)]:return u.stop()}},r,this);_0x235e35[f(8018)]=_0x17e894=n[f(8480)](_0x5bce3a,n[f(8480)](_0x331e95,n.AuzoG))}))},r[f(9572)]=function(){b[f(9572)]()},r[f(5384)]=function(u){var n=f,r={PIpEL:function(u,n){return A[_0x7f58(10050)](u,n)},kBPBW:function(u,n,r,f){return u(n,r,f)}};A.ohZUr(n(3810),A[n(6681)])?_0x4cfcb8+=r[n(7567)](r[n(4224)](_0x21c7ae,_0x147947,_0x38abbb,_0x4e7cff),_0x162c99[3]):b[n(5384)](u)},r[f(6818)]=b;var s=A[f(7698)](u,f(7768));Object[f(4594)](r,A[f(8946)],{enumerable:!0,get:function(){var u=f;if(!A.BJhej(u(2430),A.SAwFT))return s[u(4343)];try{A[u(4473)](_0x2ae135,_0x303f44[A[u(8080)]](_0x2670d8))}catch(u){A.wGsxa(_0x245fe7,u)}}}),Object[f(4594)](r,A.cLRra,{enumerable:!0,get:function(){return s[f(5325)]}}),A[f(9635)](c,A.wGsxa(u,f(3555)),r),c(A[f(7698)](u,"./shared/console"),r),c(u(A[f(1804)]),r),A[f(9635)](c,u(A[f(1644)]),r)},{"./checkers/checkers":49,"./classes/devtools-detector":59,"./shared/console":61,"./shared/context":62,"./shared/system-info":63,"./shared/utils":64,"./shared/version-map":65}],61:[function(u,n,r){"use strict";var f=_0x7f58,A={JrLMp:function(u,n,r,f){return u(n,r,f)},nfZHA:f(3251),hnbRt:function(u,n){return u(n)},dOCxF:f(3917),CBhRP:function(u,n){return u!==n},yoUyn:f(7605),yjYzj:f(2781),bCtoT:function(u,n){return u(n)},IvLIH:f(4783),OIKhz:f(10516)};function t(u){var n=f,r={lvgfh:function(u,n,r,f){return A[_0x7f58(928)](u,n,r,f)},yTRvt:function(u,n){return u(n)},NBnrk:A[n(7831)],hmuvU:function(u,r){return A[n(9546)](u,r)},rsNnO:A[n(5633)],QgedI:function(u,n){return u(n)},oUiZw:n(6970)};if(!A[n(2749)](A.yoUyn,A.yoUyn))return console[u];_0x16eff6[n(8018)]=_0x588af2=r[n(3373)](_0xf13c78,r[n(5708)](_0x4fe2f6,r[n(7093)]),r[n(1712)](_0x398f19,r.rsNnO),r.QgedI(_0x291bb,r[n(6901)]))}Object[f(4594)](r,f(861),{value:!0}),r[f(10516)]=r.table=r[f(2781)]=void 0,r[f(2781)]=A[f(9546)](t,A[f(4784)]),r[f(4783)]=A[f(2289)](t,A.IvLIH),r[f(10516)]=t(A.OIKhz)},{}],62:[function(u,n,r){"use strict";var f,A,t,e,i,c=_0x7f58,o={ofzOe:function(u,n){return u===n},oXFWk:"__esModule",vGXNa:function(u,n){return u(n)},dyeji:c(2405),dLgUs:function(u,n){return u===n},otSTa:c(8601),bOyTT:function(u,n){return u!==n},PCFgC:function(u,n){return u===n},gxuiE:function(u,n){return u===n},RQOdr:function(u,n){return u===n},SguNL:function(u,n){return u===n},KEmNz:function(u,n){return u===n},BtPxQ:function(u,n){return u===n},UymCL:function(u,n){return u===n},gVxMz:function(u,n){return u===n},XVCko:c(4261)};Object[c(4594)](r,o[c(9268)],{value:!0}),r.inBrowser=r[c(10284)]=r[c(3196)]=r.isChrome=r[c(4793)]=r[c(4063)]=r[c(8450)]=r[c(3399)]=r.isFirefox=r[c(9109)]=void 0;var q=(0,o[c(1933)](u,o[c(7393)])[c(2629)])();r[c(9109)]=(o[c(9442)](f=o[c(2759)](q,null)||void 0===q?void 0:q[c(4238)],null)||o[c(2759)](f,void 0)?void 0:f[c(9109)])||o.otSTa,r[c(6195)]=c(9836)in((o.ofzOe(q,null)||o[c(9442)](q,void 0)?void 0:q[c(9575)])||{})||/firefox/i[c(2785)](r[c(9109)]),r[c(3399)]=/trident/i[c(2785)](r[c(9109)])||/msie/i.test(r[c(9109)]),r[c(8450)]=/edge/i[c(2785)](r[c(9109)]),r[c(4063)]=/webkit/i[c(2785)](r[c(9109)])&&!r[c(8450)],r[c(4793)]=/IqiyiApp/[c(2785)](r[c(9109)]),r[c(3512)]=o[c(8979)](typeof(o[c(2759)](A=o.PCFgC(q,null)||o[c(8015)](q,void 0)?void 0:q[c(9575)],null)||o[c(3616)](A,void 0)?void 0:A.chrome),"undefined")||/chrome/i[c(2785)](r[c(9109)])||/CriOS/i[c(2785)](r[c(9109)]),r[c(3196)]=o[c(8015)](((o[c(4270)](e=o[c(9442)](t=o[c(333)](q,null)||o[c(3616)](q,void 0)?void 0:q[c(9575)],null)||o[c(8015)](t,void 0)?void 0:t.safari,null)||o.KEmNz(e,void 0)?void 0:e[c(452)])||!1)[c(9965)](),"[object SafariRemoteNotification]")||/safari/i[c(2785)](r[c(9109)])&&!r[c(3512)],r.createElement=function(){var u,n=c;return(o[n(2759)](q,null)||o[n(2759)](q,void 0)?void 0:q[n(1581)])?(u=q[n(1581)])[n(10284)][n(6346)](u,arguments):{}},r[c(8075)]=o[c(6504)](typeof(o[c(3527)](i=q.document,null)||o[c(8411)](i,void 0)?void 0:i[c(10284)]),o[c(7649)])},{"./utils":64}],63:[function(u,n,r){"use strict";for(var f=_0x7f58,A={gQdXx:"0|5|3|8|1|6|4|2|7",anaYK:f(861),xPOdf:function(u,n){return u>n},QVRnI:f(9273)},t=A[f(7770)].split("|"),e=0;;){switch(t[e++]){case"0":continue;case"1":r[f(9920)]=/macintosh/i[f(2785)](i[f(9109)]);continue;case"2":r[f(2915)]=/android/i.test(i[f(9109)]);continue;case"3":r[f(9850)]=r[f(2915)]=r[f(4276)]=r[f(5492)]=r[f(9920)]=void 0;continue;case"4":r[f(4276)]=/iphone/i[f(2785)](i.userAgent);continue;case"5":Object[f(4594)](r,A[f(3924)],{value:!0});continue;case"6":r[f(5492)]=/ipad/i.test(i[f(9109)])||r[f(9920)]&&A[f(4857)](navigator[f(7954)],1);continue;case"7":r[f(9850)]=/windows/i[f(2785)](i.userAgent);continue;case"8":var i=u(A[f(6927)]);continue}break}},{"./context":62}],64:[function(u,n,r){var f=_0x7f58,A={bZaVm:function(u,n){return u>n},ltAkL:function(u,n){return u!==n},QPrgI:function(u,n){return u===n},xUdkZ:function(u,n){return u!==n},xyhee:f(1781),ylBZG:"biTFs",edVUA:f(6909),XNcrQ:f(9068),aaZVB:function(u,n){return u===n},JfeDh:f(3339),xBCGf:f(4268),CpxVv:function(u,n){return u&&n},pLCJu:f(9522),ajpuH:function(u,n){return u>>2]|=D[f(7008)](o,24-D[f(2055)](D.hnmIt(c,4),8));continue;case"3":var i=n[f(7822)];continue;case"4":var c=D[f(8431)](D.WFzOF(i,o),1);continue;case"5":var o=D[f(8431)](e,i%e);continue;case"6":n[f(9757)]();continue}break}},unpad:function(n){var r=u,f=D.Ikykp(n.words[n[r(7822)]-1>>>2],255);n[r(7822)]-=f}},_0x3a06ad[u(4128)][u(4586)]}throw a}}}var L=!0,z=!1,E=void 0;try{for(var d,I=o[Symbol[u(9869)]]();!(L=(d=I.next()).done);L=!0){var j=d.value;if(e[u(7568)](j,!0)){v=!0;break}}}catch(u){z=!0,E=u}finally{try{e.krgjW(e.IkSuK,u(1520))?n[u(5915)](_0x5b322d,_0x10bee2):!L&&I[u(2525)]&&I.return()}finally{if(u(2618)==u(2618)){if(z){if(e[u(8701)](e[u(10332)],e[u(4912)]))throw E;return _0x4b4e4c[u(2026)]}}else for(_0x55a0df.s();!(_0x11aa57=_0x2b01a3.n())[u(8379)];){var K=_0x59d46a.value;_0x6ed781+=_0x508181(K)+1}}}return e.jmPNH(q,!v)},r[f(5325)]=function(u,n,r){var t=f,e=c.versionMap[u];return A[t(351)](e,void 0)?!!A.LWdwh(A[t(6592)],A.zVFjQ)&&(_0x5bf35a=!0,_0x2e1509[t(4489)].name):(0,i[t(4697)])(e,n,r)},r[f(2629)]=function(){var u=f,r={KuzNe:e[u(2751)],YntSS:function(u,n){return e.pKmmd(u,n)},BTtqa:function(u,n){return u>>n},qDzBh:function(n,r){return e[u(1447)](n,r)},DEZwU:function(n,r){return e[u(4849)](n,r)},sPStH:function(n,r){return e[u(5231)](n,r)}};if(typeof self!==e.jMvEm)return self;if(e[u(2330)](typeof window,e.jMvEm)){if(!e.JFZmq(e[u(9120)],u(10279)))return window;for(var t=r[u(10486)][u(7897)]("|"),i=0;;){switch(t[i++]){case"0":for(var c=0;r.YntSS(c,16);c++)for(var o="1|2|0|6|4|3|5"[u(7897)]("|"),q=0;;){switch(o[q++]){case"0":var v=this[u(2906)];continue;case"1":var b=_0x197a94[c];continue;case"2":var s=this[u(8009)];continue;case"3":this._lBlock=v;continue;case"4":for(var a=0;r[u(5493)](a,8);a++)x|=_0x1b7593[a][r[u(7313)](r[u(4728)](r[u(8680)](v,b[a]),_0x16fc39[a]),0)];continue;case"5":this[u(2906)]=r[u(8680)](s,x);continue;case"6":var x=0;continue}break}continue;case"1":_0x3073fd[u(2210)](this,8,16711935);continue;case"2":this[u(8009)]=this[u(2906)];continue;case"3":_0x91533c[u(2210)](this,16,65535);continue;case"4":this[u(2906)]=w;continue;case"5":_0x2d78fd.call(this,1,1431655765);continue;case"6":_0x7a9072[u(2210)](this,1,1431655765);continue;case"7":_0x57ba47[r.sPStH(_0x7421a2,1)]=this._rBlock;continue;case"8":_0x3617a3[_0x40266d]=this._lBlock;continue;case"9":_0x88da37[u(2210)](this,2,858993459);continue;case"10":_0x597075[u(2210)](this,16,65535);continue;case"11":this[u(2906)]=_0x21280a[_0x10d190+1];continue;case"12":_0x36cfb4[u(2210)](this,2,858993459);continue;case"13":_0x13484a[u(2210)](this,4,252645135);continue;case"14":var w=this[u(8009)];continue;case"15":_0x139d09[u(2210)](this,8,16711935);continue;case"16":this[u(8009)]=_0x150938[_0x4d0559];continue;case"17":_0x170844[u(2210)](this,4,252645135);continue}break}}if(e[u(9129)](typeof n,e[u(2359)])){if(e[u(4551)](e[u(1744)],e[u(1744)]))return n;!_0x102b61&&_0x4da0d4[A[u(5647)]]&&_0x6db503[A[u(5647)]]()}return this}})[t(2210)](this)}).call(this,A[f(1249)](typeof global,A[f(7596)])?global:A[f(1249)](typeof self,A[f(7596)])?self:typeof window!==A[f(7596)]?window:{})},{"./version-map":65,"compare-versions":1}],65:[function(u,n,r){"use strict";var f=_0x7f58,A={BOEcz:function(u,n){return u===n},FDWmI:f(2525),KgkNd:function(u,n){return u in n},cwmpJ:function(u,n){return u!==n},ZNxPQ:f(7743),sYiCb:"Invalid attempt to destructure non-iterable instance",AKVZa:function(u,n){return u(n)}},t=function(){var u=f,n={uswaN:function(u,n){return u(n)},XrMCp:function(u,n){return A[_0x7f58(10004)](u,n)},KOFWG:function(u,n,r){return u(n,r)},RzDss:function(u,n){return A.cwmpJ(u,n)},pOIgF:A[u(4286)],QaNdN:A.sYiCb};function r(n,r){var f=u,t=[],e=!0,i=!1,c=void 0;try{for(var o,q=n[Symbol[f(9869)]]();!(e=(o=q[f(6460)]()).done)&&(t[f(7606)](o[f(10292)]),!r||!A[f(3464)](t[f(7855)],r));e=!0);}catch(u){i=!0,c=u}finally{try{!e&&q[A.FDWmI]&&q[A[f(729)]]()}finally{if(i)throw c}}return t}return function(f,A){var t=u;if(Array[t(8259)](f))return f;if(n[t(5721)](Symbol[t(9869)],n[t(4315)](Object,f)))return n[t(485)](r,f,A);if(!n[t(7621)](n[t(3630)],t(7743)))throw new TypeError(n[t(6389)]);n[t(4315)](_0x2ab5bb,_0x4f6ab4)}}();Object[f(4594)](r,f(861),{value:!0}),r[f(3699)]=void 0;var e=(A[f(8351)](u,f(9273))[f(9109)]||"")[f(4343)](/\w+\/(\d|\.)+(\s|$)/gi)||[],i={};r[f(3699)]=i;var c=!0,o=!1,q=void 0;try{if(f(8547)==f(8547))for(var v,b=e[Symbol.iterator]();!(c=(v=b[f(6460)]())[f(8379)]);c=!0){var s=t(v[f(10292)].split("/"),2),a=s[0],x=s[1];i[a]=x}else try{A[f(8351)](_0x52a52b,_0x3f2f1c[f(6460)](_0x13c82a))}catch(u){A[f(8351)](_0x21b9a6,u)}}catch(u){o=!0,q=u}finally{try{!c&&b[f(2525)]&&b.return()}finally{if(o)throw q}}},{"./context":62}],66:[function(u,n,r){"use strict";var f=_0x7f58,A={zSPyt:function(u,n){return u===n},HiwTS:f(6613),hwwpx:f(861)};Object[f(4594)](r,A[f(5930)],{value:!0}),r[f(6818)]=function(){var u=f;return A.zSPyt(u(6613),A[u(2134)])?navigator.cpuClass:void 0}},{}],67:[function(u,n,r){"use strict";var f=_0x7f58,A={LVjdo:function(u,n){return u!==n},LPjwi:f(7616),LLPOK:f(6235),IHZkP:f(861),NYbNL:function(u,n){return u(n)},IUgDh:f(7845)};Object[f(4594)](r,A.IHZkP,{value:!0});var t=A.NYbNL(u,A[f(10504)]);r.default=function(){var u=f;if(A.LVjdo(A.LPjwi,A[u(4869)]))return(0,t[u(4801)])((0,t.toFloat)(navigator[u(5098)]),void 0);_0x1a4676.slice(0),this[u(1545)]=_0x4612b1}},{"../utils/data":122}],68:[function(u,n,r){"use strict";var f=_0x7f58,A={DTSUR:"RCYZH",bmYZm:function(u,n){return u===n},CFdXw:function(u,n){return u!==n},vEyRT:f(7884),YwmUL:f(2525),drqju:"grxYQ",xAhHh:function(u,n){return u in n},GMVmg:function(u,n,r){return u(n,r)},roxIU:f(9615),veFcE:"mxoBF",SBELc:f(8115),hvkTv:function(u,n){return u(n)},MXbjc:function(u,n){return u=n},xFcex:"buildID",oqwuZ:function(u,n){return u===n},jPZrT:"MediaRecorderErrorEvent",fOSbR:f(10169),qxNdR:f(5969),HpMGy:f(364),Aobki:function(u,n){return u===n},blBzW:"ZmfYe",SVRto:function(u,n,r){return u(n,r)},wszLv:function(u,n){return u===n},UYtvK:f(1367),djMSX:f(2893),hLsKm:f(2053),YNQrb:f(8236),mDRIC:function(u,n){return u===n},afPps:f(9006),sykIj:f(8817),YEwAs:function(u,n){return u===n},hZBkX:f(4904),rslnv:function(u,n){return u!==n},HjFFm:"zIwQl",VfdHV:"EHcSX",SMszo:f(3580),aXBRx:"lpYZs",FVCLN:f(5970),AXVyI:f(4605),bzbmd:f(4089),GBRbY:"pJdSk",UfNny:function(u,n){return u!==n},ajnls:f(3482),ueVpB:f(5077),kNnLv:f(6971),IpaZa:f(4307),FAopp:function(u,n){return u!==n},nJZXm:f(4129),yVXxe:f(683),aNZfO:f(9313),LVGJk:"vagdH",wlbax:function(u,n,r){return u(n,r)},EQgIs:f(3251),bExUu:function(u,n){return u===n},OrsON:"preRun",EBIwE:function(u,n){return u(n)},VfOba:f(357),sGzWn:f(10281),jgkOz:function(u,n){return u!==n},nIOwt:f(6721),SLmlf:f(4876),VZfca:function(u,n){return u>n},wnhgu:function(u,n){return u-n},WfmPi:f(8961),hNhQl:f(932),GyfAc:"word",RFZmC:"none",JqxIE:function(u,n){return u+n},AbzCS:f(10232),Ywltp:f(4626),mfYGq:function(u,n){return u!==n},vBvsC:f(1535),nilMI:f(861),NueBU:function(u,n){return u(n)},svRby:f(8794),cuGag:f(1951),iNQDG:f(296),RtAgL:f(3326),XSAhG:"monospace",oCdzy:"1px",kQLcq:f(6769)},t=function(){var u=f,n={jUkcV:function(u,n){return A[_0x7f58(1440)](u,n)},gIfrx:A.drqju,zoHdf:function(u,n){return A[_0x7f58(3271)](u,n)},mTjCY:function(u,n,r){return A[_0x7f58(5060)](u,n,r)},eOzOg:A[u(5406)]};if(A[u(6276)]!==A[u(7244)]){function r(n,r){var f=u,t=[],e=!0,i=!1,c=void 0;try{for(var o,q=n[Symbol[f(9869)]]();!(e=(o=q.next())[f(8379)]);e=!0)if(A[f(9880)]===A.DTSUR){if(t[f(7606)](o.value),r&&A[f(1440)](t[f(7855)],r))break}else this.fun[f(6346)](null,this[f(1925)])}catch(u){i=!0,c=u}finally{if(A.CFdXw(f(7884),A[f(6439)]))_0x40b415[f(2357)]&&(_0x8688ab[f(6190)]=new(_0x30dc8c[f(2357)])(["en"],{type:"region"}).resolvedOptions());else try{!e&&q[A[f(1577)]]&&q[A[f(1577)]]()}finally{if(i)throw c}}return t}return function(f,A){var t=u;if(n[t(9579)](n[t(9244)],n[t(9244)])){if(Array[t(8259)](f))return f;if(n[t(7032)](Symbol[t(9869)],Object(f)))return n[t(9792)](r,f,A);throw new TypeError(n.eOzOg)}({LQqpJ:function(u,n){return u(n)}})[t(2574)](_0x20e931,_0x7240b9)}}_0x529635.value=_0x144808,_0x269ce0(_0x26b551)}();function e(u){var n=f;if(Array.isArray(u)){for(var r=0,t=A[n(4891)](Array,u[n(7855)]);A[n(6297)](r,u.length);r++)t[r]=u[r];return t}return Array[n(9487)](u)}Object[f(4594)](r,A.nilMI,{value:!0}),r[f(7769)]=void 0;var i=A[f(7012)](u,A[f(8376)]),c=u(f(5147)),o=A[f(1153)];function q(u){var n=f,r={DLAsY:function(u,n){return u!==n},YqglD:A.hNhQl,mUrit:A[n(2083)],sKaNW:A[n(7685)],zUMZv:function(u,r){return A[n(6292)](u,r)},MfwDh:A.AbzCS,HbiWL:function(u,n){return u/n},wyFrr:A[n(7977)],lRXMg:n(1053),pCZTd:function(u,n){return A.hvkTv(u,n)},IxSZd:function(u,n){return u<>>n},fXRSI:function(u,n){return u*n},ojeqg:function(u,n){return u%n},ezurY:f(861)};Object.defineProperty(r,A.ezurY,{value:!0}),r[f(6818)]=function(){var u={rxzxU:function(u,n){return A[_0x7f58(1887)](u,n)},AVvur:A.XmxXZ,UJoyV:function(u,n){return A.bFZjw(u,n)},lqGOv:function(u,n){return A[_0x7f58(805)](u,n)},dWcez:function(u,n){return A[_0x7f58(5488)](u,n)},oFuRy:function(u,n){return u-n},GLPFe:function(u,n){return A[_0x7f58(3434)](u,n)},ecTOL:function(u,n){return A[_0x7f58(3434)](u,n)},yIwTW:function(u,n){return A[_0x7f58(554)](u,n)}};return new Promise(function(n){var r=_0x7f58,f={bbCuq:function(u,n){return A.uPfxa(u,n)},gMKVE:r(4851),vVtxb:A[r(6220)],HZern:r(5861),pLIrh:A[r(1921)]};if(navigator[r(4360)])A[r(5991)](A[r(7614)],r(1883))?A[r(7812)](typeof navigator.geolocation.getAuthorizedStatus,A[r(9096)])&&0===navigator[r(4360)][r(4694)]()?navigator[r(4360)][r(9501)](function(u){var A=r;f.bbCuq(n,JSON.stringify(u.coords,[A(6604),f[A(1070)],f[A(2278)]]))},function(u){var A=r;n(JSON.stringify(u,[f[A(9397)],f.pLIrh]))},{enableHighAccuracy:!0,maximumAge:1e3}):A.omxcY(n,A.tgQmd):u[r(10476)](_0xed6fe7,u[r(1802)]);else if(A[r(7812)](A.zgEQF,A[r(3602)]))A[r(6014)](n,A[r(4358)]);else for(var t=0;u[r(4613)](t,_0x3a03e9);t++){var e=u[r(8460)](u[r(1524)](_0x36f699[t>>>2],u[r(5256)](24,u[r(7350)](t%4,8))),255);_0x2db32c[u.dWcez(_0x5c8be9+t,2)]|=e<>>n},FWGST:_0x26be34[_0xf5dc5d(755)],MuBed:function(u,n,r,f,A){return _0x26be34[_0xf5dc5d(7048)](u,n,r,f,A)},CHKCn:function(u,n){return u===n},vzZSN:function(u,n){return _0x26be34[_0xf5dc5d(6844)](u,n)},YuGVA:function(u,n,r){return u(n,r)},EEzgX:_0x26be34[_0xf5dc5d(7147)],BoWmW:_0x26be34[_0xf5dc5d(6324)],FKeIA:_0x26be34[_0xf5dc5d(3051)],RNffo:_0x26be34[_0xf5dc5d(2655)],fMzgD:_0x26be34.LArAy,oUkiF:_0x26be34.jiMik,ZFpvd:function(u){return _0x26be34[_0xf5dc5d(6279)](u)},YdIWr:_0x26be34[_0xf5dc5d(7368)],USULU:function(u,n){return _0x26be34.GftKx(u,n)},vjNUT:_0x26be34[_0xf5dc5d(9594)],SYrta:_0x26be34[_0xf5dc5d(4329)],JZqhx:function(u,n){return u===n},AkxXT:_0xf5dc5d(3313),Xnkqy:_0x26be34.XOKJS,nBwro:_0x26be34[_0xf5dc5d(6273)],ohpHB:_0x26be34[_0xf5dc5d(6168)],bWuiD:_0x26be34[_0xf5dc5d(6616)],Ovwtk:_0x26be34.nhBeZ,wWQKV:_0x26be34.acCdK};if(_0x26be34.byiAv("GFwyp",_0xf5dc5d(6795)))return regeneratorRuntime[_0xf5dc5d(4099)](function _0x414c25(_0xc93d7a){for(var _0x15f913=_0xf5dc5d,_0x586b59={jfLqb:function(u,n){return _0x36d2fd[_0x7f58(2024)](u,n)},qQvyh:function(u,n){return _0x36d2fd[_0x7f58(2008)](u,n)},rEHHQ:_0x36d2fd[_0x15f913(2097)],hbzQz:_0x36d2fd.eFlpd,qBntZ:_0x36d2fd[_0x15f913(7521)],XGsGi:_0x36d2fd.TecNw,uLJxE:function(u,n){return u!==n},GZkpG:_0x36d2fd[_0x15f913(5738)],xGdRb:function(u,n){return u===n},sUght:_0x36d2fd[_0x15f913(8803)],SFSxb:_0x36d2fd[_0x15f913(9187)],WWxRS:_0x36d2fd.wHwhF,HyFjf:_0x36d2fd.ZezGF,KHbDd:_0x36d2fd[_0x15f913(8161)],dYqTI:function(u,n){return _0x36d2fd[_0x15f913(879)](u,n)},xsGeE:_0x15f913(5142),iTHhI:function(u,n){return _0x36d2fd.FMaYq(u,n)},BERaK:"error",DhBoG:function(u,n){return u*n},KdsXV:function(u,n){return u/n},frMMh:function(u,n){return u>>2]|=i.eKMwD(_0x389cfb[_0x2e9cc6],i[r(940)](24,i[r(5987)](i[r(8621)](_0xfae87e,4),8)))}},{}],82:[function(u,n,r){"use strict";var f=_0x7f58,A={DOhqD:function(u,n){return u instanceof n},fwzOV:function(u,n){return u!==n},IeSjv:function(u,n){return u|n},fVZOu:function(u,n){return u==n},CexNl:function(u,n){return u===n},uSpqe:"JxiwA",SnKPH:"fSqIf",Reppq:function(u,n){return u(n)},yuxXJ:f(5963),hdARa:"xxxxxxxxxxxx5xxxyxxxxxxxxxxxxxxx",wHeMU:f(4261),Reimo:f(1342),NWccR:f(8195),RGAKw:f(6516),IlUzV:f(661),hfdFV:function(u,n,r){return u(n,r)},DyGtP:"audio",fQQEB:"jNMbJ",oJFBk:f(1868),Cpxwc:f(2841),hvJXL:function(u,n){return u!==n},TByTX:"vXHWm",niqdB:function(u,n){return u>=n},SjSvY:f(4585),xXeQQ:function(u,n){return u>=n},AyeXn:f(6565),HxzEY:f(2525),BJMDz:function(u,n){return u===n},bedPU:f(9207),YAvda:f(8961),RyZBM:"bTkoa",RtkEw:f(10263),CCAZK:function(u,n,r,f,A){return u(n,r,f,A)},YnVzB:f(861)},t=function(u,n,r,t){var e=f,i={AJidz:function(u,n){return A[_0x7f58(4848)](u,n)},cFHWA:function(u,n){return A[_0x7f58(3816)](u,n)},aLGSk:function(u,n){return A.IeSjv(u,n)},YGwck:function(u,n){return A[_0x7f58(2908)](u,n)},EyMfT:function(u,n){return A[_0x7f58(4414)](u,n)},GxEZv:A.uSpqe,qPtmo:A[e(10259)],WGiwZ:function(u,n){return A[e(3816)](u,n)},UemHK:e(5977),uDvrG:function(u,n){return A[e(6626)](u,n)},JtRsI:function(u,n){return u!==n},pEUwK:e(10529),lscUX:function(u,n,r){return u(n,r)},geVVD:e(7186),ZyciG:A.yuxXJ,kcMaB:function(u,n){return u===n},BraDF:A.hdARa,poASs:A[e(6688)],QsSMo:A[e(4482)],PXfRw:A[e(7651)],OtIoU:A.RGAKw,CfkWe:A.IlUzV,NrTYM:e(8232)};function c(u){return i[e(6914)](u,r)?u:new r(function(n){n(u)})}return new(r||(r=Promise))(function(r,f){var A=e,o={KgyLu:function(u,n,r){return i[_0x7f58(5423)](u,n,r)},pbVIl:function(u,n){return i[_0x7f58(8742)](u,n)},YpCpm:i[A(5545)],xyDsw:i[A(5911)],LCTCK:A(6172),FusrI:function(u,n){return i[A(5666)](u,n)},Zdehx:i[A(2862)],fQXOQ:i[A(989)],oDuAQ:i.QsSMo,PfqoP:i[A(1256)],iSzDR:i[A(8521)],QMHfG:function(u,n){return i[A(8129)](u,n)},OfhJg:i[A(3059)],jYZdW:i[A(4130)],FjnaQ:function(u,n){return i[A(8742)](u,n)}};function q(u){var n=A,r={GIjdb:function(u,n,r){return u(n,r)},JSuOV:function(u,n){return i[_0x7f58(8129)](u,n)},refnA:function(u,n){return i[_0x7f58(8288)](u,n)},TwmGt:function(u,n){return i[_0x7f58(4060)](u,n)}};if(i.EyMfT(i[n(8669)],i[n(1990)]))return _0x11b048&&o[n(7133)](_0x56ade5,_0x532a0a[n(10129)],_0x5c2a1b),_0x46f89a&&_0x236dd2(_0x4451ea,_0x1250cc),_0x45f4a4;try{if(i[n(3730)]("BvSnR",i[n(538)])){const u=r[n(1318)](_0x4a0b2f,_0xc7d976[_0x555854]||"0",_0x4ef87f[_0x528ce8]||"0");if(r[n(2306)](u,0))return u}else i[n(8742)](b,t[n(6460)](u))}catch(u){if(i[n(3871)](n(10529),i[n(7680)])){if(o.pbVIl(_0x7a7b95,_0x131829[n(5528)])!==o[n(3311)])return o[n(2941)];var e=_0xd71916.sessionStorage[n(8350)](o[n(1561)]);return o[n(2797)](e,null)&&(e=o[n(5646)].replace(/[xy]/g,function(u){var f=n,A=r[f(3430)](16*_0x53cfef[f(4874)](),0);return(r.TwmGt(u,"x")?A:3&A|8)[f(9965)](16)}),_0x243381.sessionStorage[n(10001)](o.LCTCK,e)),e}f(u)}}function v(u){var n=A,r={OsLkN:o[n(5387)],Puolk:function(u,r){return o[n(2797)](u,r)},UXcKT:o[n(9060)]};if(o[n(3478)]===o[n(6722)])!_0x26eeee&&_0x5df258[n(2525)]&&_0x362bf4[n(2525)]();else try{o.QMHfG(o.OfhJg,"mdqob")?o[n(6268)](b,t[n(10009)](u)):!_0x50ddf4&&_0x289c43[n(2525)]&&_0x173ceb[n(2525)]()}catch(u){if(o[n(366)]!=o[n(366)]){var e=typeof _0x420b76===r[n(4629)]&&_0x448bc6[n(9413)];return!!e&&(e===_0x486efd||r.Puolk(e[n(8297)]||e[n(4477)],r[n(8165)]))}o[n(6268)](f,u)}}function b(u){var n=A;u[n(8379)]?r(u[n(10292)]):o[n(9082)](c,u[n(10292)]).then(q,v)}i[A(8742)](b,(t=t.apply(u,n||[]))[A(6460)]())})};Object[f(4594)](r,A[f(5073)],{value:!0}),r[f(6818)]=function(){var u=f;if(!A[u(1331)](A[u(8227)],A.RtkEw))return A[u(9732)](t,this,void 0,void 0,regeneratorRuntime[u(655)](function n(){var r,f=u,t={rqUYQ:A.DyGtP,sPWks:function(u,n){return A.Reppq(u,n)},IIGfm:A[f(3705)],gfdrZ:A[f(7109)],ZOshR:A[f(1118)],aYNzR:function(u,n){return A[f(4414)](u,n)},jDbHq:function(u,n){return A[f(4219)](u,n)},pRNui:A[f(5985)],MxuRn:function(u,n){return A.niqdB(u,n)},uYoDK:A.SjSvY,xMfvF:function(u,n){return A.xXeQQ(u,n)},Tbxwp:A.AyeXn,fMVeL:A.HxzEY,mTuUf:function(u,n){return A[f(1331)](u,n)},cmTnt:A.bedPU,RxBxE:A[f(3931)]};return regeneratorRuntime[f(4099)](function(u){for(var n=f,A={qlVrc:t[n(4208)],LuDRL:function(u,r){return t[n(853)](u,r)},zksiM:function(u,n){return u(n)},rWVuY:t[n(4782)],Ohanv:t[n(2341)],uNMRX:t[n(8430)],kBJIT:function(u,r){return t[n(6330)](u,r)},OvfkM:function(u,r){return t[n(2663)](u,r)},nEnoM:t[n(5750)],xQFJH:"UMyRB"};;)switch(u[n(2519)]=u[n(6460)]){case 0:if(!t.MxuRn(window[n(4238)][n(9109)].indexOf(t[n(3305)]),0)||!t[n(5672)](window[n(4238)].userAgent[n(4579)](t[n(8416)]),0)){u.next=4;break}return u.abrupt(t.fMVeL,new Promise(function(u){var n=A.qlVrc;A.LuDRL(u,n)}));case 4:if(r=!1,t[n(5672)](window[n(4238)].userAgent[n(4579)](n(4e3)),0)){if(!t[n(8804)](t[n(696)],t[n(696)]))return _0x3d9557[n(5614)]({error:_0xc96df3[n(6264)]});r=!0}return u[n(4922)](t[n(1756)],new Promise(function(u){var f=n,t={xPWCr:f(2525),XoJrM:"end",RLUaI:A.rWVuY,qFeSK:function(u,n){return A[f(9163)](u,n)},ObJVL:function(u,n){return u!==n},mIryH:A[f(358)],YjPtS:function(u,n){return u(n)},UjrLK:A.uNMRX};if(navigator.mediaDevices&&navigator[f(5937)][f(4349)])if(A[f(10096)](f(8408),f(7458)))!_0x1a3b4c&&_0x2c1186[t.xPWCr]&&_0x128d46[t[f(9919)]]();else{var e=A[f(1799)];navigator[f(5937)][f(4349)]().then(function(n){var A=f,i={aVajo:t[A(9919)],bFBBT:t[A(8177)],EoTgO:function(u,n){return u===n},RVfWQ:t[A(9346)]};n[A(781)](0,1e3)[A(7565)](function(u){var n=A;if(e+="&",e+=u[n(2438)],e+=":",r){if(i.EoTgO(i[n(3680)],i[n(3680)]))e+=u[n(2833)];else if(_0x5a7cf2)throw _0x241be9}else if(i[n(8072)](n(2656),n(2656)))e+="";else for(;;)switch(_0x56a344[n(2519)]=_0x203705[n(6460)]){case 0:return _0x23f636[n(4922)](i[n(8960)],(0,_0x166827[n(4343)])({includes:[!0],excludes:[_0x346713[n(3399)],_0x5132e0.isEdge,_0x57f5c1.isFirefox]}));case 1:case i[n(5345)]:return _0x38aa9d[n(9572)]()}}),t[A(9383)](u,e)})[f(2819)](function(n){var r=f;t[r(7155)](t[r(5429)],r(1868))?_0x20c52b=_0x42fdb1=1:t.YjPtS(u,t[r(5928)])})}else A[f(9655)](A[f(2857)],A[f(841)])?A[f(6129)](u,A[f(6161)]):A[f(6129)](_0x2cd371,_0x352093)}));case 7:case t[n(7206)]:return u[n(9572)]()}},n,this)}));var n=_0x362c5d.value;try{A[u(4745)](n,_0x34b4de[u(2710)],_0x3a3f9c)}catch(u){}}},{}],83:[function(u,n,r){"use strict";var f=_0x7f58,A={eSphI:function(u,n){return u(n)},OfGxP:function(u,n){return u!==n},LlWjZ:f(2841),napiw:function(u,n){return u!==n},AbxEF:f(6785),ugobV:function(u,n){return u===n},aCsof:f(4567),LfLGx:f(5028),rpjtF:f(861)};Object[f(4594)](r,A[f(9890)],{value:!0}),r[f(6818)]=function(){var u=f;if(!A[u(5964)](A[u(7466)],A[u(2351)])){var n=window[u(4238)],r=[];do{Object.getOwnPropertyNames(n)[u(781)](0,2e3)[u(7565)](function(n){var f=u,t={YATEu:function(u,n){return A[_0x7f58(3563)](u,n)},KIySa:A[f(936)],gmDlp:function(u,n){return A[f(8470)](u,n)}};if("eevyH"===A[f(5132)])return t[f(8249)](typeof _0x20f494,t[f(251)])?_0x1dcd4d:t[f(8249)](typeof _0x26799f,t[f(251)])?_0x17a212:t.gmDlp(typeof _0x1ece4e,t[f(251)])?_0x238ed4:this;r[f(7606)](n)})}while(n=Object[u(3964)](n));return r}A[u(6076)](_0x5c82bc,_0x1d16f1.next(_0x32f546))}},{}],84:[function(u,n,r){"use strict";var f=_0x7f58,A={ensLc:function(u,n){return u(n)},pKVyv:"JAfuj",fhMmG:f(861)};Object.defineProperty(r,A[f(6179)],{value:!0}),r[f(6818)]=function(){var u=f;try{var n=navigator[u(4304)]||navigator[u(5454)]||navigator[u(5669)];if(!n)return JSON[u(5614)]({supported:!1});var r={supported:!0,effectiveType:n.effectiveType,downlink:n[u(6035)],downlinkMax:n[u(1032)],rtt:n[u(847)],saveData:n[u(9443)],type:n[u(7772)]};return JSON.stringify(r)}catch(n){return A[u(8086)]==A[u(8086)]?JSON[u(5614)]({supported:!1,error:n[u(6264)]}):A[u(895)](_0x516feb,new _0x1a8194(u(4442)))}}},{}],85:[function(u,n,r){"use strict";var f=_0x7f58,A={AxzHP:function(u,n){return u(n)},ksqwf:f(3833),vFANR:function(u,n){return u(n)},fOoBM:f(5625),xRVvx:f(4326),AjNmT:function(u,n){return u instanceof n},GjwGh:function(u,n){return u>>n},BvXmO:function(u,n){return u&n}},r=document[u(10284)](A[u(3488)]),t=null;try{A[u(693)](A[u(7374)],A.UTzCl)?t=r[u(1839)](A[u(7547)]):_0x4d5d41|=_0x3c5077[_0x4fb764][n[u(8267)](n.BvXmO(_0x41658e^_0x2d33c9[_0x415b99],_0x1edeb5[_0x43218f]),0)]}catch(u){}return!t&&(t=null),t}function i(u){var n=f;if(!A[n(10509)](A[n(6622)],n(7939))){var r={NdwpJ:function(u){return A[n(1751)](u)}};return _0x34da89[n(4979)](function(u){var f=n,A=r[f(4335)](_0x162fd1);return A.style[f(773)]=u,_0x5c2c7f[f(5453)](A),A})}try{var t=u[n(5416)](A[n(7259)]);null!=t&&t[n(1125)]()}catch(u){console[n(9569)](A.zsUED)}}function c(){var u=f,n=document[u(10284)](A[u(3488)]);return!(!n[u(1839)]||!n[u(1839)]("2d"))}Object[f(4594)](r,f(861),{value:!0}),r[f(6818)]=function(){var u=f;if(A.oRifl(t))return function(){var u=f;try{for(var n=u(739)[u(7897)]("|"),r=0;;){switch(n[r++]){case"0":var t=o[u(5416)](A[u(1085)]);continue;case"1":var c=o[u(9038)](t[u(6890)]);continue;case"2":var o=e();continue;case"3":A.Qiehb(i,o);continue;case"4":return c}break}}catch(n){return u(10281)}}();if(A[u(4280)](A.WiEfY,A[u(9674)]))return u(3184);for(;;)switch(_0x52253d[u(2519)]=_0x21ebd8[u(6460)]){case 0:return _0x5d7089[u(4922)](u(2525),(0,_0x4f09bf[u(4343)])({includes:[!0],excludes:[_0x1c55fc[u(4063)]]}));case 1:case u(8961):return _0x50d978[u(9572)]()}}},{}],96:[function(u,n,r){"use strict";var f=_0x7f58,A={wBcEU:function(u,n){return u(n)},mYPKN:function(u,n){return u instanceof n},bCett:function(u,n){return u&n},SZrBC:function(u,n){return u<>>n},RPJdW:function(u,n){return u|n},CnvCj:function(u,n){return u+n},ojBGR:function(u,n){return u!==n},ruVdm:"Eyedr",KDZZE:"undefined",KKRYM:function(u,n){return u===n},ssecT:"nGmCd",WKGmx:f(10339),fecxC:f(3535),AhGyZ:f(861)};Object[f(4594)](r,A[f(9288)],{value:!0}),r[f(6818)]=function(){var u=f,n={NIrkA:function(u,n){return u|n},eVURn:function(u,n){return A.bCett(u,n)},flwiI:function(u,n){return u|n},uyPXL:function(u,n){return A.SZrBC(u,n)},wGuSt:function(u,n){return A[_0x7f58(3983)](u,n)},lvLZg:function(u,n){return A.RPJdW(u,n)},KILoM:function(u,n){return A[_0x7f58(1069)](u,n)}};if(!A[u(5577)](A.ruVdm,A[u(959)])){if(void 0===window[u(3935)][u(5353)])return A.KDZZE;if(A[u(7196)](A[u(5872)],A.WKGmx)){var r={DKStZ:function(n,r){return A[u(3646)](n,r)}};return A[u(5088)](_0x14cd3a,_0x233208)?_0x3d2b35:new _0x439877(function(n){r[u(7126)](n,_0x5edc27)})}return window[u(3935)][u(5353)]?u(1684):A.fecxC}_0x25cd41[_0x53b4cc]=n[u(8112)](n[u(6968)](n[u(4249)](n[u(6105)](_0x229837[_0x37f047],8),n[u(7534)](_0x35c76b[_0x26820d],24)),16711935),4278255360&n[u(7522)](_0x164a0c[_0x7c129e]<<24,n[u(7534)](_0x141d61[_0x429d51],8))),_0x39d179[n.KILoM(_0x342366,_0x1cec57)]^=_0x4ffa10[_0x452541]}},{}],97:[function(u,n,r){"use strict";var f=_0x7f58,A={luVgj:function(u,n){return u(n)},ZgHYg:f(10009),VUzTR:f(394),jHUJW:function(u,n,r){return u(n,r)},HWNmA:function(u,n){return u(n)},tRjeC:function(u,n){return u(n)},VjSsN:function(u,n){return u!==n},dOJMf:f(8903),NEzAJ:function(u,n){return u(n)},bfkLj:function(u,n){return u===n},NTszx:"vmQhJ",ExMnG:f(7296),DiHaf:f(861),Azksv:f(7845)};Object.defineProperty(r,A[f(8524)],{value:!0}),r[f(8281)]=r.getScreenColorDepth=r[f(6305)]=void 0;var t=u(A.Azksv),e=window;r[f(6818)]=function(){var u=f,n={SVaMX:function(u,n){return A[_0x7f58(8627)](u,n)},rxwHK:A[u(559)]};if(A.VUzTR===u(394))return[(0,t[u(5318)])(e[u(3935)][u(6243)]),(0,t[u(5318)])(e.screen.height)];n[u(6455)](_0x4fb3ea,_0xb05a3c[n[u(8218)]](_0x251c07))},r[f(6305)]=function(){var u=f,n={XZEAR:function(u,n,r){return A[_0x7f58(2869)](u,n,r)},fZEim:function(u,n){return A[_0x7f58(3905)](u,n)},SNWli:"./core",YGxNM:function(u,n){return A.tRjeC(u,n)},oCqjR:u(2666)};if(!A[u(3177)](A[u(689)],A[u(689)]))return[e.screenLeft,e[u(8932)]];_0x118c85.exports=_0x10ff79=n[u(8848)](_0x4e7bec,n[u(1777)](_0x2d50b3,n[u(5307)]),n[u(8825)](_0x109afa,n[u(7661)]))},r[f(9336)]=function(){var u=f;return e[u(3935)][u(9009)]},r[f(8281)]=function(){var u=f,n={AiwEk:function(u,n){return A[_0x7f58(8627)](u,n)},cWtLE:function(u,n){return A[_0x7f58(1037)](u,n)}};if(!A[u(3190)](A[u(7185)],A[u(3744)]))return e[u(6660)];_0x85ac20.exports=_0x4d0973=n[u(1357)](_0x4220a3,n.cWtLE(_0x399ae6,u(3251)))}},{"../utils/data":122}],98:[function(u,n,r){"use strict";var f=_0x7f58,A={GqJIw:function(u,n){return u===n},wfZus:f(8095),uPKYb:f(8874),YePqK:function(u,n){return u>>n},kCfKG:function(u,n){return u+n},OoREA:function(u,n){return u*n},MWYLP:function(u,n){return u<>>n},ZTFES:f(7186),JHhjR:function(u,n,r){return u(n,r)},JnhsZ:f(3251),JuHjX:function(u,n){return u(n)},JYZlc:"./cipher-core",TThUa:"dPYwZ",gSHZL:function(u,n){return u>n},VVAfs:function(u,n){return u|n},xwntX:function(u){return u()},zDudO:function(u,n){return u!==n},poNEz:"NOBEj",VWBrt:function(u,n){return u(n)},EHgcl:function(u,n){return u(n)},ikxZC:f(10369),xWFsp:"csid_",xkhQS:f(861),nGHEO:f(8571),TCcPK:function(u,n){return u!==n},CbRcT:f(8211),SHnRD:f(760)},t=function(u){var n=f;if(A.GqJIw(A[n(10253)],A[n(10253)]))return u&&u[n(861)]?u:{default:u};var r=(0,_0x5c4b1c.getData)(_0x3e6645[n(6818)].SDID_NAME);return{BnicT:function(u,n){return u(n)}}[n(6872)](_0x440c56,r)?r:void 0};Object[f(4594)](r,A[f(5998)],{value:!0}),r[f(2312)]=r[f(10051)]=r.getHdid=r[f(10505)]=r.getRealSdid=void 0;var e=A.EHgcl(t,A[f(4069)](u,f(970))),i=u(A[f(7284)]);if(!String[f(10129)][f(760)])if(A[f(9834)](A.CbRcT,A[f(3362)]))for(var c=A[f(4432)].split("|"),o=0;;){switch(c[o++]){case"0":var q=_0x2aff5b[_0x4741d9]=[];continue;case"1":for(var v=0;A.YePqK(v,24);v++)q[0|A[f(3912)](v,6)]|=_0x3e8be4[A.ImPgo(A[f(2873)](_0x461a71[v],1)+b,28)]<=n},GMTYE:function(u,n){return u===n},HFOVL:A[r(635)],TMKJc:function(u,n){return A[r(5745)](u,n)},KFiaQ:A[r(8413)],WLjzh:function(u,n){return A[r(5217)](u,n)},CiefH:"speechSynthesis",VaKcK:function(u,n){return A[r(5217)](u,n)},Lonqc:A[r(8562)],SVDTW:function(u,n){return A[r(5965)](u,n)},ODISl:function(u){return A[r(5787)](u)},JygeP:function(u,n){return A[r(8943)](u,n)},IUyuN:A[r(553)],rZVkn:function(u,n){return u(n)},ZXphA:function(u,n){return A[r(2162)](u,n)},SVrNV:function(u,n){return A[r(5745)](u,n)},Eixln:A[r(1485)],GiCpl:A.HyQzq,TFRnh:function(u,n){return A[r(5392)](u,n)},JXKtW:"XYgIX",eNPfF:function(u,n){return A[r(4161)](u,n)},HmJmA:A[r(6994)],QZDWM:function(u){return A[r(5787)](u)},yBNSy:function(u,n){return u!==n},lagWv:A[r(1736)],BeEIl:function(u,n){return u>=n},UmWFD:A[r(5508)],sDywD:r(6565),DMzFv:r(2525),vTXCN:A[r(9371)]};return regeneratorRuntime[r(4099)](function(u){for(var n=r,A={NHVaY:function(u,n){return f[_0x7f58(1941)](u,n)},dRhMu:function(u,n){return f[_0x7f58(9462)](u,n)},ENheK:f[n(899)],inOFB:function(u,n){return u(n)},EfQsH:f[n(9934)],uMhQi:function(u,r){return f[n(7092)](u,r)},JxjhK:f[n(285)],jTfEY:function(u,r){return f[n(3908)](u,r)},sLdVX:f[n(8590)],KZIlL:function(u){return f[n(7087)](u)}};;){if(f[n(2343)](f[n(1594)],f[n(1594)])){for(var t=0,c=4500;A[n(5054)](c,5e3);++c)t+=_0x21c46b[n(2842)](_0x5e6717[c]);return t}switch(u[n(2519)]=u[n(6460)]){case 0:if(!f[n(9841)](window.navigator[n(9109)][n(4579)](f[n(7073)]),0)||!f[n(9841)](window[n(4238)][n(9109)].indexOf(f.sDywD),0)){u[n(6460)]=4;break}return u[n(4922)](f[n(7380)],new Promise(function(u){var r=n;if(A[r(10330)]!=A[r(10330)])try{A[r(4963)](_0x585d64,_0x457a90[r(6460)](_0x525300))}catch(u){_0x373b75(u)}else A[r(1227)](u,A[r(702)])}));case 4:return u[n(4922)](f.DMzFv,new Promise(function(u){var r=n,t={ZObxS:function(u,n){return f[_0x7f58(9276)](u,n)},SHmSL:function(u,n){return f[_0x7f58(5588)](u,n)},MuYxh:function(u,n){return f[_0x7f58(7915)](u,n)},ZVqcv:f.HFOVL,PxSsl:function(u,n){return f[_0x7f58(4010)](u,n)},bsSUS:f[r(1084)]};if(f[r(350)](f[r(8182)],window)&&f[r(1759)](f[r(6867)],window.speechSynthesis)&&f.SVDTW(window[r(1210)].onvoiceschanged,void 0))Promise[r(5521)]([f[r(1916)](e),new Promise(function(u,n){var f=r,t={NrzGS:function(u,n){return A[_0x7f58(6218)](u,n)},WNrZS:A.JxjhK,FugAG:function(u,n){return A[_0x7f58(4963)](u,n)},qEFda:f(4442)};setTimeout(function(){var u=f;if(t[u(6484)](t[u(1840)],t[u(1840)]))return t[u(1265)](n,new Error(t.qEFda));try{var r=_0x106d87.connection||_0x5cabed[u(5454)]||_0x224831[u(5669)];if(!r)return _0x16df4c[u(5614)]({supported:!1});var A={supported:!0,effectiveType:r.effectiveType,downlink:r[u(6035)],downlinkMax:r[u(1032)],rtt:r[u(847)],saveData:r[u(9443)],type:r.type};return _0x2c277e[u(5614)](A)}catch(n){return _0x5f4b3c.stringify({supported:!1,error:n[u(6264)]})}},100)})])[r(591)](function(n){return u(n.toString())})[r(2819)](function(n){var f=r,t={HmiPL:f(2785)};A[f(6360)](A.sLdVX,A.sLdVX)?(_0x410c3e[f(6925)](t.HmiPL,{autoIncrement:!0}).put(new _0x54686a),_0x4fe2aa(!1)):A[f(1227)](u,A[f(2096)](i))});else{if(f[r(9946)](f[r(1476)],f.IUyuN)){for(var c=t[r(3014)](this.tryEntries.length,1);t[r(2735)](c,0);--c){var o=this.tryEntries[c];if(t[r(5476)](o[r(3116)],_0x587a8e)){var q=o[r(6372)];if(t.MuYxh(q.type,t.ZVqcv)){var v=q[r(5469)];t.PxSsl(_0x4fe8a1,o)}return v}}throw new _0x1eb36e(t[r(1479)])}f[r(8756)](u,f[r(1916)](i))}}));case 5:case f.vTXCN:return u[n(9572)]()}}},n,this)}))}},{}],100:[function(u,n,r){"use strict";var f=_0x7f58,A={UDAMp:function(u,n){return u===n},jAERQ:f(861)};Object.defineProperty(r,A[f(6980)],{value:!0});var t=window;r[f(6818)]=function(){var u,n=f;if(A.UDAMp(u=t[n(2517)],null)||A[n(4158)](u,void 0)?void 0:u[n(1444)])return(new(t[n(2517)][n(1444)]))[n(10523)]().timeZone}},{}],101:[function(u,n,r){"use strict";var f=_0x7f58,A={yoHGu:function(u,n){return u in n},pCrmV:"__nightmare",PExUX:f(3953),OFpOF:f(1259),CDDhD:"_phantom",BBkyZ:f(4649),trjbX:f(10447),lyNVc:function(u,n){return u!==n},RBwZb:function(u,n){return u in n},qqgDo:f(7677),RpZYS:function(u,n){return u in n},sokgm:f(7018),KSyjm:function(u,n){return u in n},IQcfY:"callSelenium",nDqbv:f(5225),BVfQh:f(8322),Hquso:f(8164),CRuFo:f(1901),wpKOH:f(2299),YwkWx:"__fxdriver_evaluate",sAFMe:"__driver_unwrapped",JViii:f(2244),ippIZ:function(u,n){return u in n},IoOnX:"__selenium_unwrapped",hhKKo:function(u,n){return u in n},dniiK:f(10083),qIOke:function(u,n){return u!==n},UCHqD:function(u,n){return u!==n},rrHck:f(3662),XROfb:"selenium",dLrEj:f(861)};Object[f(4594)](r,A[f(8510)],{value:!0}),r[f(6818)]=function(){var u=f,n=[];if(A.yoHGu(A[u(1856)],window)&&n[u(7606)](A[u(4733)]),(A.yoHGu(A.OFpOF,window)||A.yoHGu(A[u(9805)],window)||u(4649)in window)&&n[u(7606)](A.BBkyZ),window.hasOwnProperty(A[u(496)])){if(!A[u(10250)](u(9480),"ODjve"))return _0x8203fd.productSub;n.push(u(6016))}return(A[u(3133)](A.qqgDo,window)||A[u(7558)](A.sokgm,window)||A.KSyjm(A.IQcfY,window)||A.nDqbv in window||A.BVfQh in document||A[u(3133)](A.Hquso,document)||A[u(3133)](A[u(5012)],document)||A[u(9494)](A[u(1950)],document)||A[u(7558)](A.YwkWx,document)||A[u(7558)](A.sAFMe,document)||A[u(9494)](A.JViii,document)||A[u(8187)](A[u(4408)],document)||u(4655)in document||A.hhKKo(A[u(2883)],document)||A.qIOke(document.documentElement.getAttribute(u(8482)),null)||A[u(10250)](document[u(440)][u(8617)](A.qqgDo),null)||A[u(5619)](document[u(440)][u(8617)](A[u(7488)]),null))&&n.push(A.XROfb),n}},{}],102:[function(u,n,r){"use strict";var f=_0x7f58,A={ctPvm:function(u,n){return u(n)},YFdMU:function(u,n,r){return u(n,r)},nxSvc:function(u,n){return u!==n},lKdcz:function(u,n){return u===n},uytDI:"XHkVc",lufiH:"NuXMG",GcDjo:f(1621),tYnDN:function(u,n){return u in n},YMiXV:"../utils/data"};Object.defineProperty(r,"__esModule",{value:!0});var t=A.ctPvm(u,A[f(8388)]),e=navigator,i=window;r[f(6818)]=function(){var u=f,n={ZGJcL:function(u,n){return A[_0x7f58(3879)](u,n)},MLZAH:function(u,n,r){return A[_0x7f58(1627)](u,n,r)}},r=0,c=void 0;A[u(4808)](e[u(7954)],void 0)&&(A.lKdcz(u(7361),A[u(8081)])?r=(0,t[u(5318)])(e[u(7954)]):n[u(3025)](_0x3b8c4e,_0xd93c16));try{document[u(3748)]("TouchEvent"),c=!0}catch(r){A[u(10422)](A[u(9932)],A[u(7420)])?(_0x47e4cc=!0,n.MLZAH(_0xc6f7d4,_0x292acc,_0x5a4e68)):c=!1}return{maxTouchPoints:r,touchEvent:c,touchStart:A.tYnDN(u(5724),i)}}},{"../utils/data":122}],103:[function(u,n,r){"use strict";var f=_0x7f58,A={TAWTJ:function(u,n){return u===n},bdNMN:f(7395),lQjnt:function(u,n){return u!==n},znhnG:f(4301),tXRhV:function(u,n){return u in n},WkqNe:function(u,n){return u(n)},vRlRK:f(2492),qUQjC:f(9615),sOZoD:function(u,n,r,f){return u(n,r,f)},TuRrB:f(3251),YUSyG:function(u,n){return u(n)},bFjkt:f(10185),mUSVw:function(u,n){return u===n},IILgX:f(544),gRNHi:f(2525),XpRJf:function(u,n){return u&n},XrKFm:"end",cZrSf:f(8616),icWYe:f(3691),VDmRw:function(u,n,r){return u(n,r)},oSazr:function(u,n){return u(n)},xCjbZ:f(4042),mXdLx:"click",OgJiG:"touchstart"},t=function(){var u=f,n={XKyDe:function(u,n,r,f){return A[_0x7f58(9568)](u,n,r,f)},PgauT:A.TuRrB,CbGur:function(u,n){return A[_0x7f58(5030)](u,n)},QWHZz:function(u,n){return u(n)},eucyR:function(u,n){return A[_0x7f58(9854)](u,n)},ijAis:A[u(1785)],aAeCS:function(n,r){return A[u(6636)](n,r)},ehFxJ:A[u(1251)],XyTHG:A.gRNHi,lSvdV:function(u,n){return u===n},jwRpj:u(3866),bvquV:function(n,r){return A[u(5729)](n,r)},TBIwx:function(u,n){return u<>>24,16711935)|n[t(2506)](n[t(4421)](i,24)|i>>>8,4278255360)}else{if(A[t(3429)](Symbol.iterator,A[t(1968)](Object,r)))return function(r,f){var A=u,t={yklZv:function(u,r){return n[_0x7f58(7112)](u,r)}},e=[],i=!0,c=!1,o=void 0;try{if(n.eucyR(n[A(6638)],n[A(6638)]))this[A(3672)](new _0xa1fc90(function(u){return t[A(3585)](u,_0x287880)}),_0x53ae79);else for(var q,v=r[Symbol.iterator]();!(i=(q=v[A(6460)]())[A(8379)])&&(e.push(q.value),!f||!n[A(10493)](e[A(7855)],f));i=!0);}catch(u){if(!n[A(10493)](A(544),n[A(2491)]))return{w:_0x13d3a6,m:_0x557cc1};c=!0,o=u}finally{if(n.eucyR(A(1078),A(8324)))try{!i&&v[A(2525)]&&v[n[A(10456)]]()}finally{if(!n[A(6677)](n[A(7216)],n[A(7216)]))return _0x835f57[A(6346)](this,arguments);if(c)throw o}else _0x331be4[A(8018)]=_0x25ca8f=n[A(1603)](_0x22c921,_0x3ccce5(n[A(9119)]),n[A(9744)](_0x27bef9,A(4632)),_0x115aad(A(10311)))}return e}(r,f);if(!A.lQjnt("BIhlI",A.vRlRK))throw new TypeError(A[t(10409)]);_0x1f2812=_0x568895()}}}();Object[f(4594)](r,f(861),{value:!0}),r[f(10098)]=r[f(3567)]=void 0;var e=A[f(9876)](u,A[f(5641)]),i=[{name:A[f(7236)],target:document},{name:f(6119),target:document},{name:f(1386),target:document},{name:A[f(8543)],target:document,options:{passive:!0}},{name:f(9248),target:window,options:{passive:!0}}];function c(u){var n=f,r=u[n(7772)];(0,e[n(6772)])(r,(new Date).getTime().toString())}r[f(3567)]=function(){var u=f;i[u(7565)](function(n){var r=u,f=n.name,A=n[r(8839)],t=n[r(3024)];A[r(5809)](f,c,t)})},r[f(10098)]=function(){var u=f,n={bmuGJ:function(u,n){return u(n)},aGczW:A[u(518)],MmQZo:A[u(10143)],Deofv:function(u,n){return u!==n},MXSjx:A[u(813)],YUfHL:function(n,r,f){return A[u(7100)](n,r,f)}},r=new Map;i[u(7565)](function(n){var f=u;if(A[f(9854)](f(8616),A.cZrSf))return _0x134749.from(_0x3bc6d);var t=n[f(4477)],i=(n[f(8839)],n[f(3024)],(0,e[f(7264)])(t));null!=i&&r.set(t,Number(i))});var c=Array[u(9487)](r)[u(9183)](function(r,f){var A=u;if(!n[A(7108)](A(3691),n[A(7486)])){var e=n[A(10240)](t,f,2),i=e[0],c=e[1];return r[i]=c,r}for(var o={zqYFY:function(u,r){return n[A(6761)](u,r)}};;)switch(_0x17e587[A(2519)]=_0x890fba[A(6460)]){case 0:return _0x45d871[A(4922)](n[A(10406)],new _0x34d150(function(u,n){var r=A,f=new _0x19bfeb.default;f[r(7263)]=(0,_0x36bd25[r(3565)])(_0x1f3ab9[r(5614)](_0x6b5b99),_0x7081f5.encryptSeed),f[r(6552)]=_0x458253[r(6552)],o[r(1038)](u,f)}));case 1:case n[A(8945)]:return _0x14f486[A(9572)]()}},{});return JSON[u(5614)](c)}},{"../utils/session_storage":125}],104:[function(u,n,r){"use strict";var f=_0x7f58,A={KIgcm:function(u,n){return u*n},jvRHy:function(u,n){return u>>>n},emZOW:function(u,n){return u-n},sAfbr:function(u,n){return u%n},alqmA:function(u,n){return u+n},RxZgr:function(u,n){return u<_0x5d8a86[n(7855)])&&(_0x411eeb=_0x23dae1.length);for(var t=0,e=_0x2fb9cd(_0xe42f28);f(t,_0x90a8ef);t++)e[t]=_0x433c1c[t];return e}u[n(8379)]?i.AdDve(r,u[n(10292)]):i[n(5380)](c,u[n(10292)])[n(591)](q,v)}i[A(7631)](b,(t=t[A(6346)](u,n||[]))[A(6460)]())})};Object[f(4594)](r,f(861),{value:!0}),r.getUserAgentData=void 0,r[f(6818)]=function(){var u=f,n={SIFbM:function(u,n,r){return A[_0x7f58(1340)](u,n,r)},hYFDx:function(u,n,r){return u(n,r)}};if(!A[u(1446)](A[u(1796)],"JRvqL"))return navigator[u(9109)];n[u(2757)](_0x39850f,function(r){n[u(6487)](_0x126dae,_0xc0d1e3,r)},function(r){n[u(6487)](_0x391aea,_0x598806,r)})},r[f(9341)]=function(){var u=f,n={jqrht:function(u,n){return u!==n},wnFEo:u(9181),kMQZb:A.AdTRh,fwtXJ:A.ULnHh,nPtmm:A.gYeFk,zMRpG:"model",EWeoU:function(n,r){return A[u(5278)](n,r)},iDPGY:A[u(3213)]};return A.jIxOk(t,this,void 0,void 0,regeneratorRuntime[u(655)](function r(){var f=u,A={eEhZX:function(u,r){return n.jqrht(u,r)},QfgmT:f(3348),skMGv:function(u,n){return u(n)},QUgdQ:n.wnFEo,TLAeh:n.kMQZb,Wsrgg:n.fwtXJ,ikaun:n.nPtmm,YDFPX:n[f(10102)],XtWzg:"platformVersion",WSJuq:"end"};if(n[f(6736)](n[f(2088)],n[f(2088)]))return regeneratorRuntime[f(4099)](function(u){for(var n=f,r={WVbHV:function(u,n){return A[_0x7f58(3224)](u,n)},rkJtd:A.QfgmT,OHled:function(u,n){return A[_0x7f58(5149)](u,n)},aEjdW:n(8569),laQNm:A.QUgdQ,EKDYe:A[n(3847)],BtZjq:A[n(429)],EGsVx:"uaFullVersion",azrpI:A.ikaun,kbDSu:A[n(7818)],PJYpm:A[n(9586)],HmKoB:n(2841)};;)switch(u[n(2519)]=u[n(6460)]){case 0:return u[n(4922)](n(2525),new Promise(function(u){var f=n,A={husEj:function(u,n){return r[_0x7f58(8800)](u,n)}};if("yJlCM"===r[f(5812)])_0x212181[f(8379)]?A[f(9048)](_0x51ab5f,_0x1a7218[f(10292)]):A[f(9048)](_0x576110,_0x4d9321[f(10292)])[f(591)](_0x43b093,_0x1d3cb1);else try{window.navigator[f(7701)][f(1822)]([r[f(8309)],r.EKDYe,r[f(7857)],r[f(2454)],r[f(699)],f(1934),r.kbDSu,r[f(1263)],"fullVersionList",f(2105)])[f(591)](function(n){var A=f;r[A(7523)](A(3348),r[A(6533)])?{DpsgD:function(u,n){return u(n)}}[A(3223)](_0x3b9fb9,_0x6c0acf[A(6460)](_0x22bd3b)):r[A(8800)](u,JSON[A(5614)](n))}).catch(function(n){var A=f;r[A(8800)](u,JSON[A(5614)](navigator[A(7701)]))})}catch(n){u(r[f(4108)])}}));case 1:case A[n(1147)]:return u[n(9572)]()}},r,this);_0x393950(_0x2153a2.state)}))}},{}],105:[function(u,n,r){"use strict";var f=_0x7f58,A={KMKef:function(u,n){return u(n)},plqYy:f(3203),BsXSW:f(861)};Object.defineProperty(r,A[f(8934)],{value:!0}),r[f(6818)]=function(){var u=f;if(A.plqYy===A[u(1932)])return navigator.vendor;A.KMKef(_0x5a3fc0,_0x5bf109[u(3080)])}},{}],106:[function(u,n,r){"use strict";var f=_0x7f58,A={ZUHSi:function(u,n){return u===n},JzbER:f(4261),TJpwM:function(u,n){return u===n},mlzpF:function(u,n){return u!==n},Smgro:f(5001),pJSVo:f(2525),PfhGL:"end",lImGf:"oKPkd",EOptx:f(2333),AWzBP:f(8967),mPWet:function(u,n){return u===n},UErwm:function(u,n){return u===n},MAevD:f(2841),xLFzs:function(u,n){return u!==n},EsYnP:"shlpy",ZKank:f(1885),ngpEE:"instantiateStreaming",cWYDi:function(u,n){return u===n},acjru:f(8490),LshtN:function(u,n){return u===n},KVoqT:"Memory",knidI:function(u,n){return u===n},YATfl:function(u,n){return u===n},pQrPn:f(861)},t=A[f(8649)](typeof Symbol,A.JzbER)&&A[f(2021)](typeof Symbol[f(9869)],A[f(7029)])?function(u){return typeof u}:function(u){var n=f;return u&&A[n(913)](typeof Symbol,A.JzbER)&&A[n(8840)](u[n(9413)],Symbol)&&A[n(1072)](u,Symbol[n(10129)])?A[n(7029)]:typeof u};Object[f(4594)](r,A[f(6210)],{value:!0}),r[f(6818)]=function(){var u=f,n={qYQFI:u(8961)};try{if(A[u(4853)]===A.EOptx)return _0x4a42b1[u(4099)](function(r){for(var f=u;;)switch(r[f(2519)]=r[f(6460)]){case 0:return r[f(4922)]("return",this[f(8421)]());case 1:case n[f(6432)]:return r[f(9572)]()}},_0xf29dd,this);var r=window[A[u(4705)]];if(A.mPWet(A[u(5685)](typeof r,u(2841))?A[u(7896)]:t(r),u(7186)))if(A[u(9808)](A[u(7956)],A[u(3784)])){if(typeof r[A[u(2004)]]===A[u(9692)]&&A.cWYDi(typeof r[A[u(9436)]],A[u(9692)])&&A[u(10450)](typeof r[A.KVoqT],A[u(9692)]))return"1"}else switch(_0x2b6625.prev=_0x4ea91d.next){case 0:return _0x77d04f=!1,(0,_0x2a5055.log)(_0x1f646b),_0x2ab20a[u(4922)](A[u(8758)],_0x368eed);case 3:case A[u(5707)]:return _0x14d04d.stop()}return"0"}catch(u){return"0"}}},{}],107:[function(u,n,r){"use strict";var f=_0x7f58,A={ApofW:function(u){return u()},xdbAa:function(u,n){return u===n},PFTCC:f(4123),lXYFq:function(u,n){return u===n},QvqFt:f(8377),mgoYb:f(2841),jIEJv:"QVnDC",PtiIC:f(3535),fCkCB:function(u,n){return u(n)},KwQfd:f(1684),LvVad:function(u,n){return u!==n},LWoUb:f(5525),rlEaO:f(1920),NMocW:function(u,n){return u^n},enTnL:function(u,n){return u|n},UBIqX:function(u,n){return u!==n},xofmw:function(u){return u()},isYpO:f(5941),KBjDO:function(u,n){return u===n},JbqDd:function(u,n){return u in n},PwVEz:f(7602),BdAjx:"clearStale",CYcmw:function(u,n){return u in n},IAqqr:"KDYFH",vzhTq:"return",aGqTo:function(u,n){return u===n},xQJQX:"rLsed",kwOFW:f(4261),kMwCr:f(1272),vAzAu:f(9814),rnqNh:f(7445),lseGU:f(7625),aItdh:"Proxy",dgxtG:f(8128),NCsYC:function(u,n){return u!==n},LwnQh:f(3759),YmYnQ:function(u,n){return u!==n},WWUrD:f(5197),SrLbA:function(u,n){return u>n},tQyjP:f(3283),TEpOB:function(u,n){return u>=n},frqVY:f(2516),aOMhf:f(3251),NigRb:f(7983),WDveo:function(u,n,r){return u(n,r)},IYIGT:f(5892),aaqoO:function(u,n){return u%n},ZXHRh:function(u,n){return u&n},wvPmt:function(u,n){return u>>>n},uFzGf:function(u,n){return u*n},LXKhH:function(u,n){return u!==n},PODEr:"txrzg",VytZc:function(u,n){return u<>>n},rpwHf:function(u,n){return u*n},JtGZI:function(u,n){return u|n},eLDTv:function(u,n){return u-n},MpdPp:function(u,n){return u*n},FFaBj:function(u,n){return u(n)},OZlyG:function(u,n){return u===n},MfxPQ:f(7425),LYOmW:function(u,n){return u<=n},KUBni:f(7962)};function t(u,n){var r=f,t={QONfm:function(u,n){return u(n)},jgyGf:function(u,n){return A[_0x7f58(4984)](u,n)},IHKVN:function(u,n){return A.OZlyG(u,n)},LLReS:r(2164),iXwPp:r(7636),YUXEF:function(u,n){return u!==n},KTXqW:A[r(9725)]},e=new Array;try{Object[r(1407)](u).slice(0,n)[r(7565)](function(u){var n=r;t[n(3250)](t.LLReS,t[n(7795)])?t[n(2738)](_0x2dbf3f,_0x3fe238[n(3080)]):t[n(6617)](u,null)&&(t.KTXqW==t.KTXqW?e.push(u):_0x8847ff[n(8379)]?t[n(2738)](_0x536421,_0x2af37d[n(10292)]):t[n(6042)](_0x2bd1b1,_0x4807ba[n(10292)]).then(_0x3d3a10,_0x55d2f0))})}catch(u){return r(3283)}if(A[r(4785)](e[r(7855)],0)){if(!A.LvVad(A.KUBni,A[r(7182)]))return A.tQyjP;var i=A[r(6520)](_0xb50fa1[_0x8d3eea[r(252)](A[r(4496)](_0x4137d2,1))],A[r(610)](A[r(7102)](_0x5ac6c7,4),2)),c=A[r(4461)](_0x29b961[_0x40d24b[r(252)](_0x2b9749)],A[r(4496)](6,A[r(8053)](A[r(4565)](_0x20b585,4),2)));_0x11f8e2[A[r(2033)](_0x146857,2)]|=A[r(1532)](i,c)<n},scFDK:f(4198),ErXqh:function(u,n){return un},dGJtK:function(u,n,r){return u(n,r)},JRvdP:f(8998),BiiGp:f(577),itDbH:function(u,n){return u===n},TQnTw:f(1113),wGfPL:f(5425),WvbpE:f(510),EpUnS:f(8014),YNvie:f(9538),LMLpM:"addMonitorByName",EsdgD:f(1889),IsYUa:function(u,n){return u(n)},ZuYhl:f(8571),pBYVO:f(7516),ElJVs:function(u,n){return u(n)},cdcaJ:f(5230),scrYQ:f(4363),cdrzz:f(5769)},t=function(){function u(u,n){for(var r=_0x7f58,f=0;f>>n},AgzYL:function(u,n){return A[_0x7f58(7154)](u,n)},nwojQ:A[o(5134)],puAKM:function(u,n,r){return u(n,r)},cxboa:A[o(7997)],TQSgn:function(u,n){return A[o(9390)](u,n)},SFsJn:A[o(2434)],MSSzY:A[o(4967)]};function v(u){var n=o;if(i.qbRrd(i[n(3903)],i[n(3903)])){for(var r=_0x505906.byteLength,A=[],e=0;e="+u+f(2332)+n)}n[f(5809)](A.mfVEk,function(u){var A=f,e={jvfeQ:t[A(7993)]};try{throw new Error}catch(f){if(t[A(7176)](t.SMzhu,t[A(533)]))_0x134c41[e[A(4235)]]=_0x1bfe44;else{var i={type:t.Xtdek,appid:t[A(10310)]("",c[A(6818)][A(3266)]()),hdid:(0,o[A(9591)])(v[A(6818)][A(6030)]),qimei:c[A(6818)][A(2667)],time:(new Date)[A(7744)](),action:{elementClassname:n[A(291)],elementId:n.id,elementName:n[A(503)],clientXY:JSON[A(5614)]([u.clientX,u[A(8755)]]),screenXY:JSON[A(5614)]([u[A(1328)],u[A(9133)]]),isTrusted:JSON.stringify(u[A(5711)]),stack:JSON[A(5614)](f[A(7193)])}},q=JSON.stringify(i);r[A(1889)](q)}}})}}],[{key:A[u(7804)],value:function(r){var f=u,A={nIxhI:function(u,r){return n.MyAAa(u,r)},byjdg:function(u,r){return n.qifgv(u,r)},ZcFvc:function(u,r){return n[_0x7f58(6864)](u,r)}};if(!n[f(7110)]("nJsoO",n[f(2850)]))return e(this,void 0,void 0,regeneratorRuntime[f(655)](function u(){var A,t,e,i,o=f,v={gelWG:function(u,r){return n.vjCCG(u,r)},iElLC:n[o(9896)],YjpJP:n[o(4744)],kqHYY:function(u,r){return n[o(4852)](u,r)},FAwxW:n[o(5899)]};return regeneratorRuntime[o(4099)](function(u){var n=o;if(v[n(8631)](v[n(7919)],v[n(7634)]))for(;;)switch(u[n(2519)]=u[n(6460)]){case 0:if(A=new(b[n(6818)]),void 0!==c[n(6818)][n(3548)]){if(v.kqHYY(v[n(5901)],v.FAwxW)){u[n(6460)]=12;break}this._prevBlock}return u[n(6460)]=4,c[n(6818)][n(2563)].buildTokenRequest();case 4:return t=u[n(3366)],u[n(6460)]=7,c[n(6818)][n(2563)][n(8956)](c[n(6818)][n(6146)],c[n(6818)][n(3228)],t);case 7:return e=u[n(3366)],u[n(6460)]=10,c.default[n(2563)][n(4457)](e);case 10:i=u.sent,c[n(6818)][n(3548)]=i;case 12:A[n(7263)]=(0,q.encrypt)(r,c.default[n(3548)][n(6840)]),A[n(6552)]=c[n(6818)][n(3548)][n(6552)],c.default[n(6146)][n(7599)](c[n(6818)][n(4433)],A);case 15:case"end":return u.stop()}else _0x199064={enumerable:!0,get:function(){return _0x4ad50d[_0x21171b]}}},u,this)}));_0x180c05[f(10049)]+=A[f(8982)](A[f(3310)](A[f(4828)](_0x11bae7[f(8172)],":"),_0x287dfa[f(6264)]),"; "),_0x275a00[f(9569)](_0x294d9b)}}]),r}();s[f(6851)]=A[f(9204)],r[f(6818)]=new s},{"../strategy/ecbEncrypt":118,"../utils/local_storage":124,"../vo/encrypt_web_device_feature_vo":127,"./report_service":114,"./states_service":116}],114:[function(u,n,r){"use strict";var f=_0x7f58,A={MRZyf:"0|2|4|3|1",dvxxE:function(u,n){return u in n},zkbcM:f(10292),LMrTj:function(u,n,r){return u(n,r)},hPInR:function(u,n,r){return u(n,r)},bWfpQ:f(10354),mFleO:function(u,n){return u!==n},rPlMx:f(1145),skfFY:f(5709),KglbB:f(10009),SRcGv:function(u,n){return u===n},IRrFB:f(6522),LJJYQ:function(u,n){return u(n)},yeUJN:f(4726),IjjmB:function(u,n){return u(n)},oibPs:function(u,n){return u(n)},jjleC:f(3900),NMHcp:f(10283),DLVpU:function(u,n){return u(n)},bhPvA:function(u,n){return u instanceof n},qpsGC:f(8953),TpoLQ:function(u,n){return u(n)},beXsL:f(5983),MPmhy:"MHuyT",XszUC:"LWvOD",wgjEM:function(u){return u()},piaJE:function(u,n,r,f,A){return u(n,r,f,A)},MTeoH:function(u,n,r){return u(n,r)},ZydoH:function(u,n){return u!==n},qbLVz:f(5087),kVxtg:function(u,n){return u===n},rnliR:f(8465),wHVZN:function(u,n,r){return u(n,r)},ZkLnk:"FZtbr",xuCHg:"ChCfB",jFpMS:function(u,n){return u>n},wCzUz:f(8961),vAYYo:function(u,n,r,f,A){return u(n,r,f,A)},HHVdn:function(u,n){return u*n},fjKyq:function(u,n){return u===n},YRTKM:f(283),JOfDJ:function(u,n){return u-n},NplWm:function(u,n){return u<>>n},TVkXh:function(u,n,r,f){return u(n,r,f)},nKdiF:f(3315),kvhyv:f(7574),SEmVe:f(4423),BtoYv:"setDebugCallBack",dPMHu:f(9741),kFFUj:f(5330),SCpxH:f(5118),UMXcC:f(5638),GzrsT:function(u,n){return u!==n},tKYeh:f(9309),daQNd:"Wnqoy",JPbNt:f(5791),qMSzL:function(u,n){return u(n)},Wiwel:function(u,n){return u(n)},WKSkT:f(2325),daTfX:"./states_service",JYfIe:function(u,n){return u(n)},BoeGe:"./feature_service",VvtMW:function(u,n){return u(n)},pYTNi:f(1187),wuqPO:function(u,n){return u(n)},thSEY:function(u,n){return u(n)},uXtOd:function(u,n){return u(n)},Vsodg:function(u,n){return u(n)},Aurzf:"./monitor_service",MmPbg:"../collector/user_actions",jLQRx:f(1388),EhUBR:function(u,n){return u+n},NDsAv:f(2909),cpewv:"/web/df/collect",yRaqH:f(6431),SfgOn:function(u,n){return u+n},NxcPD:f(963),wgWID:f(1165),UPwrS:function(u,n){return u*n},KAtqz:function(u,n){return u*n}},t=function(){function u(u,n){for(var r=_0x7f58,f=0;f0&&n[f(7862)](arguments[0],void 0))&&arguments[0];return n.nGKDx(i,this,void 0,void 0,regeneratorRuntime.mark(function u(){var n=f,e={AsHad:function(u,n){return A[_0x7f58(3215)](u,n)},YdiGZ:A[n(2283)],kzwvA:function(u,r,f){return A[n(4132)](u,r,f)}};return regeneratorRuntime[n(4099)](function(u){for(var f=n,i={qtmtZ:function(u,n){return A[_0x7f58(2910)](u,n)},SdbMd:function(u,n){return A[_0x7f58(3872)](u,n)},SrZVF:function(u,n){return A.GXKit(u,n)},Zhwll:function(u,n){return u(n)},HTCtU:A[f(4348)]};;)if(A.GpSWP(A.iQlrX,f(9980)))e[f(8050)](_0x304e8c,_0x4a0676[f(6460)](_0x44ecba));else switch(u[f(2519)]=u.next){case 0:return u[f(4922)](A[f(2419)],Promise[f(5521)]([r[f(2340)](t),new Promise(function(u,n){var A=f;if(e[A(7817)]==e[A(7817)])return e[A(4581)](setTimeout,function(){var u=A;return i.Zhwll(n,new Error(i[u(2916)]))},r[A(9090)]);_0x2822fd[_0x5b5fe4]=i[A(1821)](i[A(10265)](_0x1b02c4.abs(_0x27ee10[A(10174)](i[A(5581)](_0x45ba0b,1))),4294967296),0)})]));case 1:case A[f(7709)]:return u[f(9572)]()}},u,this)}))}},{key:u(2340),value:function(){var n=u,f={jYBPQ:function(u){return A[_0x7f58(8038)](u)},NUtQR:function(u,n){return u===n}},t=!!(arguments.length>0&&A[n(1089)](arguments[0],void 0))&&arguments[0];return A[n(9243)](i,this,void 0,void 0,regeneratorRuntime.mark(function u(){var A,e,i,c,o,q,v,b=n,s={zUDPX:function(u){return f[_0x7f58(2127)](u)},QfsMC:function(u,n){return u%n},ucmSn:b(4332),rKBxr:"bWCDl",XEThE:b(3122),LiGVN:b(5472),oiXKy:function(u,n){return f.NUtQR(u,n)},sZRJk:"return"};return regeneratorRuntime[b(4099)](function(u){var n=b;if(s[n(4682)]===s[n(5205)]){for(var f=_0xe81143.sqrt(_0x31ba30),a=2;a<=f;a++)if(!s.QfsMC(_0x487db9,a))return!1;return!0}for(;;)if(s.XEThE!==s[n(7332)])switch(u[n(2519)]=u[n(6460)]){case 0:return r[n(3612)][n(464)](),u.next=3,r[n(2563)].buildTokenRequest();case 3:return A=u[n(3366)],u[n(6460)]=6,r[n(2563)][n(8956)](r[n(6146)],r[n(3228)],A);case 6:return e=u[n(3366)],u.next=9,r.tokenService[n(4457)](e);case 9:return i=u[n(3366)],r[n(3548)]=i,u[n(6460)]=13,r[n(8983)].collect();case 13:if(c=u[n(3366)],!(s[n(2990)](t,!0)&&c[n(5808)][n(7855)]<=0)){u.next=16;break}return u[n(4922)](s.sZRJk);case 16:return u[n(6460)]=18,r[n(5171)][n(9218)](c,i);case 18:return o=u[n(3366)],u[n(6460)]=21,r[n(5171)][n(2353)](r[n(6146)],r.collectUrl,o);case 21:return q=u[n(3366)],u[n(6460)]=24,r[n(5171)][n(1422)](q);case 24:return v=u.sent,r[n(6889)]&&r[n(8226)]&&r[n(8226)](c),i.reportFrequency&&(r[n(9758)]=i[n(9758)]),u[n(4922)](s[n(1496)],v);case 28:case n(8961):return u[n(9572)]()}else _0x3be05f=s[n(8003)](_0x17c4ed)},u,this)}))}},{key:A[u(1690)],value:function(r){var f=u,A={KKMmR:function(u,r){return n[_0x7f58(4043)](u,r)},wdqBr:function(u,r){return n[_0x7f58(1961)](u,r)},igdAe:function(u,r){return n[_0x7f58(10177)](u,r)},QMrdX:function(u,r){return n[_0x7f58(1080)](u,r)}};if("pQQQu"!==f(3060)){var t={GnUAW:function(u,n){return u&n},CXIxE:function(u,n){return A[f(5110)](u,n)}};return _0x3142ce[f(4128)][f(7460)]={pad:function(u,n){var r=f,t=4*n,e=A[r(7909)](t,u.sigBytes%t);u[r(4189)](_0x101bff[r(8364)][r(8122)].random(A[r(8026)](e,1)))[r(4189)](_0x3ecbf5[r(8364)].WordArray[r(4703)]([A[r(941)](e,24)],1))},unpad:function(u){var n=f,r=t[n(1607)](u[n(7992)][t[n(4054)](u[n(7822)]-1,2)],255);u[n(7822)]-=r}},_0xafeed9[f(4128)][f(7460)]}console.warn(r)}}]),r}();r.default=C,C[f(9590)]=A[f(5868)],C.tokenUrl=A.EhUBR(C.host,A[f(8950)]),C[f(4353)]=C[f(9590)]+A[f(1831)],C.getConfigUrl=A.EhUBR(C[f(9590)],A[f(5811)]),C[f(4433)]=A[f(9803)](C.host,A[f(4950)]),C[f(3238)]=5002,C[f(2667)]="",C[f(7607)]="",C[f(2513)]=A[f(1898)],C[f(2493)]=new q.default,C[f(3612)]=new a.default,C[f(8983)]=new(v[f(6818)]),C[f(5171)]=new(b[f(6818)]),C[f(6146)]=new(o[f(6818)]),C.tokenService=new(s[f(6818)]),C.webTokenInfo=void 0,C[f(9758)]=A.UPwrS(A.KAtqz(1e3,60),10),C[f(9090)]=3e4,C[f(6889)]=!1,function(){var u=f;if(A[u(10208)](A[u(7611)],A.daQNd)){console[u(2781)](A.JPbNt);try{w.default[u(510)]()}catch(u){}}else _0x2d0908.push(_0x485ac2)}()},{"../collector/user_actions":103,"../utils/local_storage":124,"./feature_service":110,"./fingerprint_service":111,"./local_service":112,"./monitor_service":113,"./request_service":115,"./states_service":116,"./token_service":117}],115:[function(u,n,r){"use strict";var f=_0x7f58,A={nwcXW:function(u,n,r){return u(n,r)},Utvfd:function(u,n,r){return u(n,r)},uugyT:function(u,n){return u==n},yXOUz:"return",HAHbR:function(u,n){return u>n},SjJTM:function(u,n){return u<=n},LeQYm:function(u,n){return u>>n},IznKd:function(u,n){return u|n},vNejw:function(u,n){return u!==n},BSlcq:f(7599),xPRtM:"__esModule"},t=function(){var u=f,n={HhybM:function(u,n){return A[_0x7f58(8126)](u,n)},GuRlN:A[u(9943)],PUteX:function(n,r){return A[u(1327)](n,r)},YeGMh:function(u,n){return u===n},YOFZh:function(u,n){return A.SjJTM(u,n)},GiFfR:function(u,n){return uo)&&(i[4]=_0x27f668,i[5]=_0x36893a,_0x4b6a82.n=o,_0x1c815d=0))}}return function(n,f,t){var e=u;return f&&A[e(3989)](r,n[e(10129)],f),t&&A[e(1047)](r,n,t),n}}_0x5dae7d||n[u(1202)](null,_0x17b465[n.GuRlN])||_0x122e41[n.GuRlN]()}();function e(u,n){var r=f;if(A.ejrod(A[r(2074)],A.ZMwVB)){if(!A[r(979)](u,n))throw new TypeError(r(10354))}else _0x30d29b(_0x9ac41c.stringify(_0x692555))}var i=function(u,n,r,t){var e=f,i={KycGt:function(u,n){return u!==n},vybRU:A[e(5765)],IsUSJ:function(u,n){return A[e(6542)](u,n)},PappD:function(u,n){return A[e(3839)](u,n)}};function c(u){return u instanceof r?u:new r(function(n){n(u)})}return new(r||(r=Promise))(function(r,f){var o=e,q={gTcAC:function(u,n){return A.PGLxT(u,n)},vokGm:function(u,n){return A[_0x7f58(3282)](u,n)},uXmdv:A[o(6646)]};function v(u){var n=o;try{i[n(1597)](i[n(8679)],i[n(8679)])?q[n(9770)](_0x2af0c4,_0x3407a7[n(3080)]):i[n(1196)](s,t[n(6460)](u))}catch(u){i[n(6056)](f,u)}}function b(u){var n=o;try{q.vokGm(s,t[q[n(4267)]](u))}catch(u){q[n(9770)](f,u)}}function s(u){var n=o;u.done?i[n(1196)](r,u[n(10292)]):i.IsUSJ(c,u[n(10292)])[n(591)](v,b)}A[o(3839)](s,(t=t[o(6346)](u,n||[])).next())})};Object[f(4594)](r,A.xPRtM,{value:!0});var c=function(){var u=f,n={njlMH:function(u,n,r){return A.Utvfd(u,n,r)},MTczO:A.yXOUz,RkEin:A[u(4710)],Umafm:function(n,r){return A[u(7046)](n,r)},Alqgv:A[u(8847)],lgMfJ:u(6930),zaJei:A.jIzca,wbLnC:A[u(1631)],zZKwF:function(n,r){return A[u(7229)](n,r)},kitns:function(n,r){return A[u(8336)](n,r)},GIuNE:function(n,r){return A[u(6467)](n,r)},RfGuB:function(u,n){return A.vNejw(u,n)}};function r(){n[u(5163)](e,this,r)}return A[u(3989)](t,r,[{key:A[u(2326)],value:function(n,r){var f=u,t={vaxqh:A[f(5294)],AZOGa:function(u,n){return A[f(6542)](u,n)},HERFx:f(2841),ilRMe:A[f(9943)],YLqLR:A.ECBTe,QiJaW:A[f(7678)]};return i(this,void 0,void 0,regeneratorRuntime[f(655)](function u(){var A=f,e={EkDqt:t[A(5714)],jWyLw:t.YLqLR};if(t[A(2803)]==t[A(2803)])return regeneratorRuntime.wrap(function(u){for(var f=A;;)switch(u.prev=u.next){case 0:return u[f(4922)](e[f(1634)],this.httpPost(n,JSON[f(5614)](r)));case 1:case e[f(9892)]:return u.stop()}},u,this);for(var i={aTFws:t[A(5500)],AIKds:function(u,n){return t[A(4394)](u,n)},IDaSD:function(u,n){return u!==n},RUgaQ:t[A(8006)]};;)switch(_0x3386ef[A(2519)]=_0x4fe2cf[A(6460)]){case 0:return _0x29de00[A(4922)](t.ilRMe,new _0x270ca5(function(u){var n=A,r=_0x4293c3[n(10284)](n(6793));r[n(8624)]=i[n(5883)],_0x5bb1ee[n(2599)][n(5453)](r);var f=i[n(1127)](_0x10fc80,r[n(7484)].chrome);_0x4d7b83[n(2599)].removeChild(r),u(i[n(3525)](f,i[n(4721)]))}));case 1:case"end":return _0x420074.stop()}}))}},{key:u(1687),value:function(r,f){var A=u,t={FPqNJ:n[A(938)],jzwvF:n[A(3082)],XUuif:function(u,r){return n[A(2202)](u,r)},HNBuC:A(6608),AWoxZ:n[A(1622)],SVDkQ:n[A(9507)],jMaXn:n[A(10063)],LYisW:"Access-Control-Allow-Origin",oCioN:A(10382),JEGqn:function(u,r,f){return n.njlMH(u,r,f)},qdSYW:A(3251),vFRAo:n.wbLnC,EwPma:function(u,r){return n[A(7893)](u,r)},vVVZi:function(u,r){return n[A(6135)](u,r)},JYATl:function(u,n){return u>>n},OzeBL:function(u,n){return e[A(9440)](u,n)},fPAzP:function(u,n){return e[A(5313)](u,n)},BFXjD:function(u,n){return e.DWXMl(u,n)},EdMbi:function(u,n){return u==n},tChOI:function(u,n){return e[A(3069)](u,n)},Cikns:A(5382)};if(e[A(6715)](e.XqrlY,"APjvM"))for(;;)switch(u.prev=u[A(6460)]){case 0:return u[A(4922)](e[A(4083)],new Promise(function(u,n){var i=A,c={ZDWcU:function(u,n){return e.FdtSH(u,n)}};if(e[i(9545)]!=e[i(9545)])_0x15dbe0=_0x428b52;else{var o=new XMLHttpRequest;o.withCredentials=!0,o[i(9844)](e[i(7183)],r,!0),o[i(8738)](e[i(9861)],e.ZOrkr),o[i(8738)](e[i(4829)],"*"),o[i(8738)](i(3010),e.AvUba),o[i(8738)](e[i(3353)],e.CWIbw),o[i(4520)]=function(){var r=i,f={xUcra:t.ssSpz,zpyiU:function(u,n){return t.ThDfN(u,n)},PZxbk:function(u,n){return t.cIkVv(u,n)},MLCMj:function(u,n){return t[_0x7f58(4362)](u,n)},vvhMF:function(u,n){return t[_0x7f58(8395)](u,n)},GCZPW:function(u,n){return t[_0x7f58(608)](u,n)},nDcCN:function(u,n){return t[_0x7f58(608)](u,n)},uUveb:function(u,n){return t[_0x7f58(3758)](u,n)},IGRzh:function(u,n){return t[_0x7f58(5910)](u,n)},gjqFK:function(u,n){return t[_0x7f58(608)](u,n)},sjcQd:function(u,n){return u<>>8));continue;case"5":_0x2d43f4[3]^=C;continue;case"6":var b=_0x3d15b1[r(7992)];continue;case"7":var s=f[r(466)](f[r(5673)](v,16),f[r(2349)](a,4294901760));continue;case"8":var a=f[r(466)](f[r(2349)](f[r(3194)](f[r(4017)](w,8),f[r(2328)](w,24)),16711935),4278255360&f[r(5631)](f[r(7174)](w,24),f[r(2328)](w,8)));continue;case"9":_0x2e9156[1]^=s;continue;case"10":var x=b[0];continue;case"11":_0x41039e[0]^=v;continue;case"12":var w=b[1];continue;case"13":for(var g=0;f[r(5289)](g,4);g++)_0x3a86f2.call(this);continue;case"14":_0x5412b1[7]^=C;continue;case"15":var C=f.JuaRw(f[r(7174)](a,16),f[r(10513)](v,65535));continue}break}else{var B=JSON.parse(A[r(5784)]),D=(B[r(5861)],B.msg,B[r(3351)]);u(JSON[r(5614)](D))}else t[r(425)](t[r(6852)],r(1324))?n({status:this[r(1013)],body:A.statusText}):c[r(7207)](_0x583cf9,_0xae7f06)},o.send(f)}}));case 1:case e.UBfbM:return u[A(9572)]()}else e[A(3793)](_0x4cde0e,[e.EKdSZ,e[A(8099)]],_0x57a88c)},u,this);for(;;)switch(_0x290c44[n(2519)]=_0x434e8c[n(6460)]){case 0:return _0x5f2cb0[n(4922)](t.FPqNJ,(0,_0x17e822[n(4343)])({includes:[_0x16bf33.isChrome],excludes:[(_0x5bf6d8[n(5492)]||_0x404d08[n(4276)])&&_0x296066.isChrome]}));case 1:case t[n(8599)]:return _0x44a145[n(9572)]()}}))}}]),r}();r[f(6818)]=c},{}],116:[function(u,n,r){"use strict";var f=_0x7f58,A={jqwsS:function(u,n){return u>>n},OBPvV:function(u,n){return u%n},zkqqa:function(u,n){return u>n},DnFvE:function(u,n){return u|n},VlEYZ:function(u,n){return u<>>n[f(6719)](16,8*n[f(971)](_0x1911e0,4)),65535);_0x47474b.push(_0x1d0998.fromCharCode(c))}},{key:A[u(3229)],value:function(n){var f=u;null!=n&&(0,e[f(758)])(r[f(2684)],n)}},{key:A[u(1006)],value:function(f){var A=u,t={AxWve:n.jDJsG};if(n[A(6500)](n[A(1107)],n[A(1107)]))return n.lhQqt(n[A(7171)](n[A(6849)](_0x1083bc,8),4278255360),16711935&n[A(5250)](_0x493dd3,8));if(void 0===f)return f;if(null!=f[A(7260)])if(n[A(8290)](n[A(4550)],n[A(4550)])){_0x445fcc[A(4128)](this[A(4269)],this[A(2315)]);this[A(3595)](!!t[A(582)])}else(0,e[A(1005)])(r[A(2684)],f[A(7260)]);return n.Eoktj(f[A(2888)],void 0)&&(0,e.setData)(r[A(6030)],f.hdid),(0,e[A(1005)])(r.TIMESTAMPE_NAME,(new Date)[A(7744)]()),f}}]),r}();r.default=c,c[f(8168)]=10*A.fJfUF(1e3,60),c.DEFAULT_TIMESTAMPE=0,c[f(2684)]="sdid",c[f(849)]=A[f(2363)],c[f(6030)]=A.pPUKP,c.reporthost=f(1994),c.reportUrl=A.gWLxd(c[f(5834)],A[f(7142)]),c[f(9300)]=""},{"../collector/sdid":98,"../utils/local_storage":124}],117:[function(u,n,r){"use strict";var f=_0x7f58,A={cjKOd:function(u,n){return un},dAEZX:function(u,n){return u===n},XcrtP:function(u,r,A){return n[f(9092)](u,r,A)},yLFwW:n[f(5184)],KWucL:n[f(9580)]};if(n[f(10351)](n[f(4504)],n.nfhjN))return n.nPsXL(e,this,void 0,void 0,regeneratorRuntime[f(655)](function u(){var n=f,t={KYfFI:A[n(8641)],xRvsb:A[n(8813)],HXCqQ:function(u,n){return u&&n},jFAVy:function(u,n){return u3?(e=t[n(9032)](q,_0x21504a))&&(_0x241349=i[(_0x2f450d=i[4])?5:(_0x572b53=3,3)],i[4]=i[5]=_0x408758):i[0]<=o&&((e=t.jFAVy(_0x34b0b3,2)&&t[n(4931)](o,i[1]))?(_0x363d41=0,_0x9b986c.v=_0x2a63d8,_0x829bc9.n=i[1]):t.jFAVy(o,q)&&(e=t[n(4931)](_0x4ff902,3)||t[n(10229)](i[0],_0x445a54)||t[n(10229)](_0x2b7aaf,q))&&(i[4]=_0x68b20c,i[5]=_0x1a1fd6,_0x1d117a.n=q,_0x5c5bdf=0))}if(e||t[n(4439)](_0x38e716,1))return _0x10dd13;throw _0x1f2fca=!0,_0x27b2d3}));A[f(10126)](_0x33b98d,[A[f(8010)],A.KWucL],_0x1be72a)}},{key:A[u(9274)],value:function(n,r,f){var t=u,i={eLJju:t(5075),lcKGa:function(u,n){return A[t(8782)](u,n)},teGMT:function(u,n){return A.LCFTu(u,n)},jJOYh:A[t(3323)],DQKDf:A[t(7467)],PlBcc:A[t(5524)],KXgxm:"unknown",UKwqr:function(u,n){return A[t(6215)](u,n)},LucJa:A[t(7424)]};return e(this,void 0,void 0,regeneratorRuntime[t(655)](function u(){var A=t,e={IuRvi:i[A(783)]};if(i[A(5038)](i[A(10466)],"zfDMp"))return regeneratorRuntime[A(4099)](function(u){var t=A,e={TvZdE:i[t(9864)],ACAjV:function(u,n){return i.lcKGa(u,n)}};if(i.teGMT("lPRmj",i[t(7064)]))for(;;)switch(u[t(2519)]=u[t(6460)]){case 0:return u[t(4922)](i[t(8761)],n[t(7599)](r,f));case 1:case i[t(7515)]:return u[t(9572)]()}else for(var c=e.TvZdE.split("|"),o=0;;){switch(c[o++]){case"0":return function(){b[t(3351)]=s=q.aIwvZ(++s,2)};case"1":v[t(897)](b,{characterData:!0});continue;case"2":var q={aIwvZ:function(u,n){return e[t(1203)](u,n)}};continue;case"3":var v=new _0x254c9a(_0x36d55b);continue;case"4":var b=_0x2648c3[t(1313)]("");continue;case"5":var s=0;continue}break}},u,this);_0x41001f[A(7810)]=!1,_0x269571.browserName=e[A(4404)]}))}},{key:A.MjdnH,value:function(r){var f=u,A={uakHJ:function(u,r){return n[_0x7f58(5882)](u,r)},Bktkr:n.SDtuW,EEHVm:n[f(2446)],UhHgB:n[f(2228)],bPQij:n[f(7169)],nbQnC:function(u,r){return n.iSCst(u,r)},NOLFb:function(u,r){return n[f(9233)](u,r)},OZVLT:n.oQErM,wGxEk:n.LGyte,hNshR:function(u,r){return n[f(5538)](u,r)},zxuyq:function(u,n){return u!==n},aHhsO:n.WLiPZ,gjZPl:n.MuMHP};return n[f(6768)](e,this,void 0,void 0,regeneratorRuntime[f(655)](function u(){var n=f,t={rjkAN:function(u,n){return A[_0x7f58(1001)](u,n)},cryog:function(u,n){return A[_0x7f58(10458)](u,n)},fhTUd:A[n(772)],CWJHx:function(u,r){return A[n(1001)](u,r)},lKcYL:A[n(4638)],UgQrF:function(u,r){return A[n(9085)](u,r)},FGoMa:"value"};return A.zxuyq(A[n(2518)],A[n(1363)])?regeneratorRuntime.wrap(function(u){var f=n;if(A[f(6329)](A[f(5356)],A[f(5947)]))_0x2b9eab=!0,t[f(8737)](_0x2f63c8,"");else for(;;)if(A[f(6329)](f(2337),A[f(7903)]))switch(u[f(2519)]=u[f(6460)]){case 0:return u[f(4922)](f(2525),new Promise(function(u,n){var A=f;if(t[A(6974)](t[A(4737)],t[A(4737)]))_0x545232[_0x39b3ad]^=1549556828,_0x3ee019[_0xa2c96d]^=909522486;else{var e=JSON[A(8333)](r);t[A(5640)](u,e)}}));case 1:case A[f(1610)]:return u.stop()}else for(var e=t[f(8746)][f(7897)]("|"),i=0;;){switch(e[i++]){case"0":c.configurable=!0;continue;case"1":c[f(3851)]=c[f(3851)]||!1;continue;case"2":_0x3862c0.defineProperty(_0x529375,c[f(6290)],c);continue;case"3":t.UgQrF(t.FGoMa,c)&&(c.writable=!0);continue;case"4":var c=_0x6b90c1[_0x3e6b18];continue}break}},u,this):_0x35fd82.stringify({supported:!1})}))}}]),r}();r.default=o,o.version=A[f(7411)],o[f(3470)]=A[f(3887)],o[f(2005)]=A[f(7348)],o[f(6538)]=A.XHvfQ},{"../vo/version_info":129}],118:[function(u,n,r){"use strict";var f=_0x7f58,A={tYeVS:function(u,n){return u!==n},MAwvb:f(5579),iRByC:f(3490),GOoRc:function(u,n){return u===n},egCJO:f(2567),YYHTq:function(u,n,r){return u(n,r)},XqnnJ:f(7630),PWPxz:f(6977),AOaQV:function(u,n){return u(n)},lKxQI:function(u,n){return u(n)},qqIFo:function(u,n){return u!==n},iEjKY:f(384),NjsBT:function(u,n){return u===n},emDvq:function(u,n){return u(n)},SHDBv:f(10009),zPTmM:function(u,n){return u===n},MckTA:f(1468),BDGGc:f(861),JAxoD:f(4291),yjQzd:function(u,n){return u(n)},VKNDl:f(6766),HPwNg:f(2358)},t=function(u){var n=f,r={qaneA:function(u,n){return A[_0x7f58(4900)](u,n)},ETvrQ:n(6521),VqxkK:n(7301),pxIJJ:A[n(3005)],TvXyB:A.iRByC};return A[n(5856)](A.egCJO,n(4937))?r[n(4503)](_0x3155ba[n(8566)],_0x3b789c)?r[n(9903)]:_0x3b196c[n(4343)](/Edg/)?r.VqxkK:_0x196efd[n(4343)](/OPR/)?r.pxIJJ:r.TvXyB:u&&u.__esModule?u:{default:u}};Object[f(4594)](r,A[f(7453)],{value:!0}),r.decrypt=r.encrypt=void 0;var e=t(A.emDvq(u,f(2657))),i=t(u(A.JAxoD)),c=A.yjQzd(t,A[f(2123)](u,f(626))),o=A[f(2123)](t,A[f(4383)](u,A[f(3285)])),q=t(u(A.HPwNg));function v(u){return function(u){var n=f,r={rkSOt:function(u,n){return A.lKxQI(u,n)}};if(!A[n(4393)](A.iEjKY,n(384)))return u[n(7897)]("").reverse().join("");r[n(3991)](_0x4ab742,_0x37db02[n(6460)](_0x11eab2))}(u[f(5358)](0,16))}function b(u,n){var r=f,A=o[r(6818)].parse(n),t=e.default.encrypt(u,A,{mode:q[r(6818)],padding:i.default});return c.default.stringify(t[r(9003)])}function s(u,n){var r=f,t={QnasV:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},OYdTm:A.SHDBv};if(A[r(7868)](A[r(10455)],A[r(10455)])){var v=o.default[r(8333)](n),b={ciphertext:c.default[r(8333)](u),key:void 0,iv:void 0,salt:void 0,algorithm:void 0,mode:void 0,padding:void 0,blockSize:void 0,formatter:void 0};return e.default[r(8764)](b,v,{mode:q.default,padding:i[r(6818)]})[r(9965)](o[r(6818)])}t[r(3806)](_0xa0c0e8,_0x15aadb,_0x45cad7,_0x4222cc,_0x53404e,_0x1dfa77,t[r(3125)],_0x12c0b2)}r.encrypt=function(u,n){var r=f,t={eFOjD:function(u,n,r){return A.YYHTq(u,n,r)}};if(A[r(2259)]===A[r(525)])return t[r(6926)](_0x55e1cf,_0x151cba,_0x490b0c);var e=A[r(846)](v,n);return A.YYHTq(b,u,e)},r.decrypt=function(u,n){var r=f;if(A[r(5463)](r(6571),r(1531)))return _0x26366d(_0x2460b7);var t=A.emDvq(v,n);return A[r(7190)](s,u,t)}},{"crypto-js/aes":2,"crypto-js/enc-base64":5,"crypto-js/enc-utf8":7,"crypto-js/mode-ecb":17,"crypto-js/pad-pkcs7":23}],119:[function(u,n,r){"use strict";var f=_0x7f58,A={sPgpK:f(2841),ZIbGI:f(6986),zyiEP:function(u,n){return u!==n},iqmVu:f(1628),KYlnL:"XNWcL",aLUuj:function(u,n){return u instanceof n},EWpyh:function(u,n){return u===n},BLlhy:f(3593),vBPrF:f(7271),fhlTh:function(u,n){return u===n},pClxC:f(2634),hxCNW:"XWQyC",CkchX:function(u,n){return u(n)},yNfXX:"2|3|0|1|4",PkkNo:function(u,n){return u in n},KVWnm:f(10009),ZOFEe:"xgDxl",hswve:function(u,n,r,f){return u(n,r,f)},sIDjb:function(u,n){return u(n)},qzACf:f(3251),IWJMo:function(u,n,r){return u(n,r)},kVjyo:function(u,n){return u+n},YocHx:function(u,n){return u&n},VDJZl:function(u,n){return u<n},HNiVp:f(4996),nAhGl:f(1124),MYruR:function(u,n){return u(n)},DfWRm:f(10085),roULl:f(7125),lqSZx:function(u,n){return u===n},rmzny:f(2957),uZLAy:function(u){return u()},LemeY:f(3452),IvJyP:f(6898),kOaRY:f(2933),bsNrR:f(2525),poFSS:"catch",aKamv:"end",DWFxZ:function(u,n,r,f,A){return u(n,r,f,A)},uxmUJ:function(u,n){return u(n)},njCxI:function(u,n){return u(n)},jOIdE:function(u,n){return u(n)},vGwBz:f(4911),JBcsP:f(5005),bxczu:function(u,n){return u(n)},XPNLn:f(6354),OIHdq:function(u,n){return u/n}},t=function(u,n,r,t){var e=f,i={aRMJz:A.sPgpK,TncNM:A[e(8779)],wcYRP:function(u,n){return u(n)},FIaZx:function(u,n){return A.zyiEP(u,n)},qdZgn:A[e(5688)],RsxLR:A.KYlnL,eqvvr:function(u,n){return A[e(2268)](u,n)},PCrzF:function(u,n){return A[e(1347)](u,n)},NyQcd:A[e(4568)],QHobs:A[e(4751)],wdTJb:e(330),Jvkuv:function(u,n){return A[e(6443)](u,n)},vOYUA:A[e(8899)],ArZLk:A[e(3915)],zPGFE:function(u,n){return A.CkchX(u,n)},LFfoV:function(u,n){return u*n},rHptu:A[e(4092)],hattw:function(u,n){return A.PkkNo(u,n)},eJctA:A.KVWnm,yMLfl:A[e(5623)]};function c(u){var n=e;if(i[n(9169)](i[n(6597)],i.RsxLR))return i.eqvvr(u,r)?u:new r(function(r){var f=n,A={smhrY:i.aRMJz};f(6986)===i[f(5766)]?i[f(318)](r,u):_0x25952f(A.smhrY)});var f=_0x4019dd();return f?(0,_0x2738ed[n(6818)])(f[n(3351)])[n(9965)]():""}return new(r||(r=Promise))(function(r,f){var A=e,o={JdzGf:function(u,n){return i.LFfoV(u,n)},rZUUp:function(u,n){return u>>n},AIhGw:function(u,r){return n[_0x7f58(1306)](u,r)},mhrfI:function(u,r){return n[_0x7f58(1306)](u,r)},jddwG:function(u,n){return u!==n},RObDW:"HLAAO",TnsKD:n[A(2388)],POPRg:function(u,r){return n[A(9392)](u,r)},SGwVq:function(u,n){return u+n},ENVlH:function(u,r){return n.AEdfP(u,r)},nsvKK:n[A(5316)],znLgd:n[A(5879)],lIfrY:function(u,r){return n[A(9740)](u,r)},cdqOw:n.toyhG,tfymB:n[A(4544)],hmwqb:"BJCzy",iDYmt:n.zhKaW};if("0"===(0,c[A(6818)])())n[A(9449)](n[A(5437)],n[A(5437)])?n.tKUlE(f,new Error(A(6578))):_0x5d29ad[A(8018)]=_0x12c5b1=n[A(10190)](_0x4e06a9,n[A(8790)](_0x4aa91a,n[A(5245)]),n[A(8790)](_0x16c028,A(4632)),n.tKUlE(_0x33b953,A(10311)));else{if(window.hydeviceWasm&&typeof window[A(10525)][A(9483)]===n[A(4906)])if(n[A(9449)](A(2957),n[A(9498)]))n[A(6067)](r);else{if(_0x71b98f[A(4412)]!==_0x5eb953)return;_0x5001df[A(4412)]=_0x1af243,_0x649d21[A(4118)]=_0x54b3ca,n[A(8563)](_0x2459df,_0x37d35f,_0x1533d6)}else n[A(3778)](function u(){var n=A,e={uNtAX:function(u){return u()},PcumQ:function(u,n){return t[_0x7f58(6614)](u,n)},xhrxQ:function(u,n){return t.IvRpl(u,n)},MCpDG:function(u,n){return u>>>n},vFLmG:function(u,n){return t.AIhGw(u,n)},EwXTS:function(u,n){return t.jddwG(u,n)},FcoER:t[n(2287)],vsTTr:t.TnsKD,Bdvqr:function(u,r){return t[n(4951)](u,r)},fanGk:function(u,r){return t[n(6670)](u,r)}},i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;if(t.ENVlH(i,q))if(t[n(10002)]!==t[n(5950)])t[n(7645)](f,new Error(t[n(3485)]));else for(var c=0;c<80;c++)_0x22d2bc[c]=e[n(3100)](_0x2f37e0);else{if(t[n(8536)]===t[n(8446)]){var o=t[n(7315)](t[n(10162)](t[n(7315)](_0x12929a,t[n(646)](t[n(8271)](_0x412d53,_0x1117df),t[n(10264)](~_0x5885df,_0x39ce80))),_0x4296f4),_0xf74967);return t.XkbXX(t[n(9108)](o,_0x242b36)|t[n(9952)](o,t[n(2208)](32,_0x4d19b5)),_0x23ddae)}t[n(3838)](typeof window[n(10525)][n(9483)],t[n(8971)])?r():setTimeout(function(){var r=n,f={iYiqq:function(u,n){return e[_0x7f58(8581)](u,n)},cbRTg:function(u,n){return e[_0x7f58(1540)](u,n)},evRkS:function(u,n){return e[_0x7f58(4856)](u,n)},TRHUM:function(u,n){return e.vFLmG(u,n)}};if(e[r(8007)](e[r(9416)],e[r(9497)]))return e[r(10510)](u,e[r(10234)](i,1));var A=f[r(5532)](_0x1e7088[_0x249dfa],1);_0x511e97[_0x516f0f]=f[r(3152)](f.evRkS(_0x8714e6[A>>>5],f[r(5172)](31,A%32)),1)},100)}})}})};r.default=function(u,n,r){var e=f,c={qZmaW:A[e(8301)],MNbNg:function(u,n){return u===n},vsoun:A[e(7417)],OSxKD:A[e(1988)],ioqkm:function(u,n){return A[e(4278)](u,n)},DqADL:e(4346),iMORq:function(u){return u()},JXnVy:A.bsNrR,XyKky:A[e(7767)],ILspP:A[e(2100)]};return A[e(8837)](t,this,void 0,void 0,regeneratorRuntime[e(655)](function f(){var A,t,q,b,s,a,x,w,g=e,C={gVwEP:c[g(3645)],JuWCO:function(u,n){return u(n)},pYrgY:function(u,n){return c.MNbNg(u,n)},rGBLu:c.vsoun,GklJn:function(u,n){return u!==n},qmCuY:c[g(10152)],aRBWT:function(u,n){return c[g(8608)](u,n)},ElJGR:c.DqADL,CwrZl:function(u){return c[g(8685)](u)},ZuyQt:g(2888),oxYZu:c[g(3625)],BjPlQ:c[g(5187)],xfQkS:c[g(8900)]};return regeneratorRuntime[g(4099)](function(f){var e=g;if(C[e(3605)](e(6898),C[e(504)]))for(;;)switch(f[e(2519)]=f[e(6460)]){case 0:if(f[e(2519)]=0,!/Google-InspectionTool/i[e(2785)](navigator[e(9109)])){if(C[e(9271)](C[e(10092)],e(2933)))return typeof _0x167d3e===C[e(6381)]&&C[e(6603)](_0x9b1ca8,_0x3a3048)?_0x29305b:_0x45315c;f[e(6460)]=4;break}return A=(0,o[e(6818)])(C[e(506)](C[e(5848)]+u,n))[e(9965)](),f[e(4922)](e(2525),Promise[e(5974)](A));case 4:return f[e(6460)]=6,C[e(4106)](v);case 6:return t=(0,i[e(3741)])(C[e(2736)]),t=C.pYrgY(t,void 0)?"":t,q=window.hydeviceWasm.stringToNewUTF8(u),b=window[e(10525)].stringToNewUTF8(t),s=window[e(10525)][e(2550)](n),a=window[e(10525)].stringToNewUTF8(r),f[e(2519)]=12,x=window[e(10525)][e(9483)](q,b,s,a),w=window.hydeviceWasm[e(2732)](x),window[e(10525)][e(6059)](x),f[e(4922)](C[e(3494)],Promise[e(5974)](w));case 17:return f.prev=17,window[e(10525)][e(6059)](q),window[e(10525)]._free_string(b),window[e(10525)][e(6059)](s),window[e(10525)][e(6059)](a),f[e(8607)](17);case 23:f[e(6460)]=28;break;case 25:return f[e(2519)]=25,f.t0=f[C.BjPlQ](0),f.abrupt(e(2525),Promise[e(5974)](f.t0[e(6264)]||e(5827)));case 28:case C.xfQkS:return f[e(9572)]()}},f,this,[[0,25],[12,,17,23]])}))}},{"../../wasm/output/hydevice-ext.js":130,"../collector/webAssembly":106,"../utils/local_storage":124,"crypto-js/md5":13}],120:[function(u,n,r){"use strict";var f=_0x7f58,A={EDKTs:function(u,n){return u instanceof n},tKZkO:function(u,n){return u(n)},HprFg:"./lib-typedarrays",zfFer:f(2038),bKTIK:f(6802),hqDVK:function(u,n){return u(n)},eBOHX:f(10311),JZbHL:f(391),hMnmp:"./evpkdf",pFfJC:function(u,n){return u(n)},UikoL:f(2666),GLnxz:f(5431),oopnJ:f(6246),fsNxW:f(9618),IbGks:f(930),KngwO:f(3772),zvUwF:f(2234),KLYPu:f(3660),oRdct:"./tripledes",JZLaO:f(6720),VXwYY:f(1928),PyUsg:function(u,n){return u!==n},WgRNX:f(8435),bRyko:function(u,n){return u===n},avwMc:function(u,n,r,f){return u(n,r,f)},QCseU:function(u,n){return u(n)},NbMBc:f(4632),wlKWn:f(10023),vtbfy:"sIkoZ",vfSIK:f(10009),GHVeA:"vFFSi",sgUHf:f(7991),SeLri:"next",JMuAf:function(u,n){return u>n},NKeoC:f(8459),qDKoG:"GovkT",HSjAp:function(u,n){return u!==n},kGsSX:f(5905),UKoUd:f(4376),kjOVK:function(u,n){return u===n},zNOrY:f(4261),QLfAr:f(6929),kxGTS:function(u,n,r){return u(n,r)},cEHOh:function(u,n){return u(n)},cADtE:f(1517),rMBaa:function(u){return u()},ozaPL:function(u,n){return u!==n},bPFhN:function(u,n,r){return u(n,r)},aQKLK:function(u,n){return u===n},CtAEb:f(7562),yPBOB:function(u,n){return u|n},SjVGi:f(10281),emfHD:f(8185),BDzBh:function(u,n){return u=n},ooObc:function(u,n){return u+n},xJmjl:function(u,n){return u!==n},iuBqb:f(6212),riYXo:f(3240),BkPDx:function(u,n,r,f,A){return u(n,r,f,A)},ZJUSc:f(8427),dlicU:f(10060)},t=function(u,n,r,t){var e=f,i={rEbRf:e(5523),oFvlJ:e(3740),yVyTI:function(u,n){return A.EDKTs(u,n)},EnkPV:function(u,n,r,f,A,t,e,i,c,o,q,v,b,s,a,x,w,g,C,B,D,L,z,E,d,I,j,K,y,h,_,Q,N,M){return u(n,r,f,A,t,e,i,c,o,q,v,b,s,a,x,w,g,C,B,D,L,z,E,d,I,j,K,y,h,_,Q,N,M)},aXmcE:function(u,n){return A[e(2831)](u,n)},WFgyk:e(3251),hFAkp:A[e(5252)],cvRoP:function(u,n){return A[e(2831)](u,n)},pnzjt:A.zfFer,RANBb:A[e(927)],Czevl:function(u,n){return A.hqDVK(u,n)},NjMog:A.eBOHX,FcBsN:A[e(695)],ybFuq:A[e(9176)],MENsS:function(u,n){return A[e(4921)](u,n)},QAxpp:A[e(5309)],AcGkk:A.GLnxz,DYCXb:A[e(9088)],BUDnl:A[e(684)],VbIgy:A[e(4968)],ubzSG:A[e(2530)],kVBzY:A[e(7786)],xwmjn:A[e(2429)],lZaxe:A[e(911)],rDpyN:A[e(6445)],LlTbd:A.VXwYY,zThqQ:function(u,n){return A.PyUsg(u,n)},QCAdy:A.WgRNX,PTtRO:function(u,n){return A.hqDVK(u,n)},MyqkP:e(8396),bzdEf:function(u,n){return A[e(1209)](u,n)},oGUYf:function(u,n,r,f){return A[e(2669)](u,n,r,f)},PXMmD:function(u,n){return A[e(5477)](u,n)},VHXXB:A[e(6567)],Vndeg:A[e(2384)],iilHy:A.vtbfy,atASD:A[e(8966)],ZhGgC:function(u,n){return u(n)},eFYQh:function(u,n){return u(n)},rhUHW:function(u,n){return A[e(5477)](u,n)}};function c(u){var n=e,f={tQmgH:i[n(4701)]};return i[n(1465)]!=i[n(1465)]?_0x5070c5.startsWith(f[n(668)]):i[n(6208)](u,r)?u:new r(function(n){n(u)})}return new(r||(r=Promise))(function(r,f){var A=e,o={jlWEc:A(2525),JyqIj:function(u,n,r,f,A){return u(n,r,f,A)},kTECL:function(u,n){return i[A(9261)](u,n)},wNRvj:function(u,n,r,f){return i[A(5479)](u,n,r,f)},JAyRf:function(u,n){return i[A(7153)](u,n)},rOFKX:i[A(274)],RgmwY:A(4261),bWSpa:function(u,n,r){return u(n,r)},JwNqg:i[A(644)],aLAeq:i.Vndeg,MnMDf:i[A(9470)],tuPwo:function(u,n){return u(n)},WOtSm:i[A(1017)],bhTHu:function(u,n){return u!==n},QXAIk:"XxVHd",LJwDF:function(u,n){return i[A(2652)](u,n)},AcLjj:function(u,n){return i[A(7873)](u,n)}};function q(u){var n=A,r={TgTgF:function(u){return u()},wkfNp:function(u,n,r,f,A,t,e,c,o,q,v,b,s,a,x,w,g,C,B,D,L,z,E,d,I,j,K,y,h,_,Q,N,M,l){return i.EnkPV(u,n,r,f,A,t,e,c,o,q,v,b,s,a,x,w,g,C,B,D,L,z,E,d,I,j,K,y,h,_,Q,N,M,l)},smQZR:function(u,n){return i.aXmcE(u,n)},OhBsB:i[n(3378)],BaiSt:n(3917),egYMd:function(u,n){return i.aXmcE(u,n)},FlWlH:i.hFAkp,LEpNW:function(u,n){return i.cvRoP(u,n)},gxhBt:function(u,n){return u(n)},PrCBY:i[n(4243)],CpMiN:n(4632),OmkOH:function(u,r){return i[n(1947)](u,r)},ChZUd:i[n(1528)],RHYcq:n(6970),flLZl:function(u,n){return u(n)},sUHfT:function(u,r){return i[n(7912)](u,r)},YVpMH:function(u,r){return i[n(1947)](u,r)},YIpcO:i[n(274)],Yxtvb:function(u,r){return i[n(10181)](u,r)},yOnIp:i.FcBsN,LnQsb:function(u,r){return i[n(7912)](u,r)},ITlIr:i[n(1723)],dPQHD:function(u,r){return i[n(2766)](u,r)},wbBKV:i.QAxpp,paxwt:n(8538),nLTZS:function(u,n){return u(n)},SjGyE:i[n(4380)],svspB:function(u,n){return u(n)},ERmiM:i[n(4939)],uLRYR:i[n(9221)],Udnbk:n(1099),VmvzY:n(9196),jNflJ:function(u,n){return i.cvRoP(u,n)},Iuocn:i[n(7010)],PouuP:function(u,n){return u(n)},DeXpK:i[n(4749)],wFFez:i[n(3416)],xqcyj:function(u,n){return u(n)},wEGgD:i[n(494)],vtZzh:n(7551),FcVQY:function(u,n){return u(n)},afdDy:i[n(5917)],UUKHB:i[n(2575)],sgFUt:i[n(7598)]};try{i[n(657)](n(8435),i[n(3419)])?r[n(1397)](_0x1773e4):i[n(6981)](b,t[n(6460)](u))}catch(u){i[n(8087)]==i[n(8087)]?i[n(2766)](f,u):_0x34ab31[n(8018)]=_0x3d370d=r[n(4182)](_0x49ab30,r[n(10276)](_0x1a7fb4,r[n(10113)]),r[n(10276)](_0x1ad825,r[n(277)]),r[n(8984)](_0x59438c,r[n(3328)]),r.LEpNW(_0x4587e7,n(660)),r[n(5511)](_0x2aae23,"./enc-base64"),_0x161ab2(r.PrCBY),r.egYMd(_0x12425a,r[n(5494)]),r[n(8951)](_0xdb846f,n(7983)),_0x204d76(r[n(1881)]),_0x2f6597(r.RHYcq),r.flLZl(_0x53db1b,"./sha384"),r[n(8984)](_0x59025f,n(2002)),r.sUHfT(_0x3b3b9d,n(8759)),r[n(8850)](_0x3bc3e5,r[n(9776)]),r[n(271)](_0xd35552,r[n(7156)]),r[n(10160)](_0x733ffb,r[n(2148)]),r[n(2588)](_0x1a6df1,r[n(1595)]),_0x929479(r.paxwt),r[n(6969)](_0x1412ac,r[n(1233)]),r[n(3719)](_0x538dab,r[n(8028)]),r.YVpMH(_0x2eaa31,r[n(570)]),r.YVpMH(_0xe3da67,r[n(10173)]),r[n(8612)](_0x2b7a87,r[n(6071)]),r.jNflJ(_0x706c4a,r[n(7545)]),r[n(4203)](_0x506dab,r[n(4882)]),r[n(6969)](_0x539bb5,n(6130)),r[n(1184)](_0x1399e3,r[n(2967)]),r[n(2799)](_0x194df7,r.wEGgD),r[n(4425)](_0x4e281c,r[n(931)]),r[n(7131)](_0xf74ee8,r[n(3749)]),r[n(5511)](_0x1c932e,r[n(5720)]),r[n(8850)](_0x5a68d7,r[n(6416)]),r[n(2799)](_0x3ea9eb,"./rabbit-legacy"))}}function v(u){var n=A,r={svKXe:function(u,n){return o[_0x7f58(5006)](u,n)},Mjylk:n(7186),FKwee:function(u,n,r,f){return o.wNRvj(u,n,r,f)},bcCuM:function(u,n){return u(n)},EkUIu:n(3251),qDrff:function(u,r){return o[n(9447)](u,r)},DqZLQ:o[n(1588)],xglih:o[n(4274)],eASIo:function(u,r,f){return o[n(8711)](u,r,f)},kuJfr:o[n(1700)],GmNdN:function(u,r){return o[n(9447)](u,r)}};if(o[n(5006)](o.aLAeq,n(4460)))switch(_0x3a2009[n(2519)]=_0x27ac13[n(6460)]){case 0:return _0x11b935[n(4922)](o[n(10062)],this[n(1687)](_0x3251eb,_0x4d5d75[n(5614)](_0x32754f)));case 1:case"end":return _0x640cfb[n(9572)]()}else try{if(o[n(6222)]===n(2132))o[n(6525)](b,t[o[n(1510)]](u));else{var e=this;o.JyqIj(_0x4b33bc,_0x197a26,_0x161960,function(u){return e[n(4930)](_0x2f2cd1,_0x149958,u)},function(u){return e[n(4930)](_0x48c950,_0x1685ac,u)})}}catch(u){o[n(4871)](o.QXAIk,o[n(9415)])?r[n(2711)](typeof _0xf4d164,r[n(5002)])?_0x2ffbfd[n(8018)]=_0x4a1e3b=r[n(9915)](_0x1f7fea,r.bcCuM(_0xda4e23,r[n(4287)]),r.qDrff(_0x26d7c7,n(4632)),_0x2f556a(r[n(6380)])):r.svKXe(typeof _0x26f175,r[n(490)])&&_0x48f59d[n(4388)]?r[n(611)](_0x33eb56,[r[n(4287)],r.kuJfr,r.DqZLQ],_0x1c8dd3):r[n(2642)](_0x20ff6f,_0x446f66[n(3080)]):o.JAyRf(f,u)}}function b(u){var n=A;u.done?o[n(3787)](r,u[n(10292)]):o.AcLjj(c,u[n(10292)]).then(q,v)}i[A(9016)](b,(t=t[A(6346)](u,n||[])).next())})};function e(u,n){var r=f,t={ztGvv:A[r(1284)],EZRJx:function(u,n,r,f){return u(n,r,f)}};return new Promise(function(f){var A=r;return t[A(4787)]!=t[A(4787)]||t[A(1239)](setTimeout,f,u,n)})}function i(u){var n=f;return A[n(2728)](A[n(960)],A[n(1790)])?u&&A[n(4844)](typeof u[n(591)],A[n(7235)]):(_0x48d64d&&this[n(6466)](_0x5af1b4),this[n(7764)]())}Object[f(4594)](r,f(861),{value:!0}),r[f(6472)]=r[f(8693)]=r[f(1274)]=r.isPromise=r.requestIdleCallbackIfAvailable=r.wait=void 0,r[f(530)]=e,r[f(5529)]=function(u){var n=f,r={uiwpm:A[n(5125)],zMZsR:A[n(6094)],UdKsC:function(u,n){return u===n},ViUAL:function(u,n){return u(n)}},t=A[n(4850)](arguments[n(7855)],1)&&A.PyUsg(arguments[1],void 0)?arguments[1]:1/0,i=window[n(1629)];if(!i)return A[n(2831)](e,Math[n(5083)](u,t));if(A[n(3073)](A[n(10293)],A[n(10078)]))return new Promise(function(u){return i.call(window,function(){return u()},{timeout:t})});for(var c=r[n(6511)].split("|"),o=0;;){switch(c[o++]){case"0":this[n(1713)]=r[n(8666)];continue;case"1":this[n(10186)]=null;continue;case"2":this[n(5469)]=_0x11ae2b;continue;case"3":this[n(6460)]=0;continue;case"4":if(!_0x4bf43c)for(var q in this)r[n(5074)](q.charAt(0),"t")&&_0x332b17[n(2210)](this,q)&&!r[n(3093)](_0x1c17d8,+q[n(781)](1))&&(this[q]=_0x44f7f0);continue;case"5":this[n(2519)]=0;continue;case"6":this[n(8379)]=!1;continue;case"7":this[n(5273)].forEach(_0x2cf735);continue;case"8":this[n(3366)]=this[n(9991)]=_0x241402;continue}break}},r[f(9387)]=i,r[f(1274)]=function(u,n){var r=f,t={mOPca:A[r(5185)],DhEOo:function(u,n,f){return A[r(6635)](u,n,f)},sKQas:function(u,n){return A[r(1126)](u,n)}};try{if(A[r(3073)](A[r(1815)],A.cADtE)){var e=_0x2eb827[r(10284)](t.mOPca);return e[r(6243)]=1,e[r(3327)]=1,[e,e[r(1839)]("2d")]}var c=A[r(848)](u);if(A[r(4735)](i,c))c[r(591)](function(u){return t[r(10363)](n,!0,u)},function(u){return t[r(10363)](n,!1,u)});else if(A[r(3726)](r(10498),"GYNki"))A[r(2508)](n,!0,c);else try{return _0x526b82(_0x46c955(_0x3c7ac8[r(5614)](_0x4cd7de)))}catch(u){throw new _0x5f229b(r(6706))}}catch(u){A[r(2938)](A.CtAEb,"vBmWY")?t[r(7309)](_0x13de06,!1):A[r(6635)](n,!1,u)}},r[f(8693)]=function(u,n){var r=f,i={nSzfr:A[r(4976)],DwERa:A[r(8375)],cFHNT:function(u,n){return A[r(7759)](u,n)},NUiPY:function(u,n){return A[r(2728)](u,n)},vOnRL:A[r(2386)],SNXvB:function(u,n,f){return A[r(6635)](u,n,f)},tBdSz:function(u,n){return A[r(6935)](u,n)},qtCcS:function(u,n){return A.ooObc(u,n)},RKzWW:function(u,n){return A[r(9979)](u,n)},MiKau:function(u,n){return A[r(4735)](u,n)},fWFUt:r(8961)};if(A.PyUsg(A[r(9482)],A[r(8763)])){var c=A[r(4850)](arguments.length,2)&&void 0!==arguments[2]?arguments[2]:16;return A[r(4166)](t,this,void 0,void 0,regeneratorRuntime[r(655)](function f(){var t,o,q,v=r,b=function(u,n){return A[_0x7f58(8964)](u,n)};return regeneratorRuntime[v(4099)](function(r){var f=v,A={XzGAx:i[f(9525)]};if(i[f(9496)]!==f(8185))return A[f(3028)];for(;;)switch(r[f(2519)]=r[f(6460)]){case 0:t=Date[f(4974)](),o=0;case 2:if(!i[f(6650)](o,u[f(7855)])){if(i[f(7323)](i[f(3757)],f(9629))){r[f(6460)]=12;break}_0x26b749=_0x4b5d28[f(1048)](b(_0x2d6219,0)-this[f(8452)],0)}if(i.SNXvB(n,u[o],o),q=Date[f(4974)](),!i[f(7729)](q,i[f(9464)](t,c))){if(i.RKzWW(f(2305),"rJTUJ")){r[f(6460)]=9;break}return _0x51a58e++,""}return t=q,r.next=9,i[f(6077)](e,0);case 9:++o,r[f(6460)]=2;break;case 12:case i[f(2997)]:return r[f(9572)]()}},f,this)}))}return new(_0x2ccf65[r(6848)])(_0x276817)[r(1353)](_0x4cbac7)},r.suppressUnhandledRejectionWarning=function(u){var n=f;A[n(3073)](A.ZJUSc,A.dlicU)?u[n(591)](void 0,function(){}):(_0x38fb6d[n(7810)]=_0xa12621.isPrivate,_0x3092bd[n(6093)]=_0xe3b9e4.browserName)}},{}],121:[function(u,n,r){"use strict";var f=_0x7f58,A={Wfuuw:function(u,n){return u in n},nlfrA:"MSCSSMatrix",znuFB:function(u,n){return u in n},BbmVQ:"msIndexedDB",usIYf:f(3102),LYXAB:function(u,n){return u in n},mLFqq:f(3239),anQmY:f(4994),XNkJm:function(u,n){return u+n},LmtzG:function(u,n){return u===n},nvGub:f(5291),wGQUb:function(u,n){return u>=n},eLsOO:f(7702),uMYeX:function(u,n){return u in n},nzluL:f(1360),scRON:function(u,n){return u in n},reUHt:function(u,n){return u in n},HnyQM:f(7628),ojnxq:function(u){return u()},VUhAq:function(u,n){return u in n},FrvIx:f(2116),FIhhi:function(u,n){return u in n},JlXzx:f(9955),ugzTQ:"Google",lhfOe:f(8449),SxvgJ:f(4342),GDWZJ:function(u,n){return u in n},IOxBw:f(9299),xJydx:f(664),muYBO:function(u,n){return u in n},SFotC:f(1158),jmReH:"getStorageUpdates",EveCp:f(4059),vKfKG:function(u,n){return u(n)},dUjEw:f(2126),seUSM:function(u,n){return u!==n},hULrG:f(5266),JPamy:f(257),kRwpo:function(u,n){return u in n},lPoxZ:f(7756),EdyUR:function(u,n){return u in n},seaHX:"standalone",CukBK:function(u,n,r){return u(n,r)},NgdmJ:"HjEKL",LaTaV:function(u,n){return u>=n},lXvFf:f(6197),FAqzG:function(u,n){return u===n},CGJBp:f(8980),nCwvY:function(u,n){return u in n},RsCEQ:f(7787),NAyuL:function(u,n){return u in n},NVNEo:"mozInnerScreenX",xxvWy:function(u,n){return u in n},CcnQe:f(326),LMHsm:"CanvasCaptureMediaStream",HiVeg:function(u,n){return u>=n},LeqaL:f(6587),fcJFT:function(u,n){return u in n},BDJak:f(7249),fNbCG:f(9467),ocboI:function(u,n){return u===n},DnoWt:f(4037),LJqeq:function(u,n){return u>=n},jzqKq:function(u,n){return u in n},KMBPD:f(8382),lSZRp:f(2199),uYrah:function(u,n){return u in n},djDAb:"SVGGeometryElement",dliCH:f(861),rRSvG:"./data"};Object[f(4594)](r,A.dliCH,{value:!0}),r[f(3858)]=r[f(723)]=r[f(10477)]=r[f(8955)]=r.isWebKit=r[f(2143)]=r[f(1876)]=r.isTrident=void 0;var t=u(A[f(5846)]),e=window,i=navigator,c=document;function o(){var u=f;return(0,t[u(10117)])([A.Wfuuw(A[u(985)],e),A.Wfuuw(u(8965),e),A[u(6813)](A.BbmVQ,e),A[u(4006)]in i,A.LYXAB(A[u(697)],i)])>=4}r.isTrident=o,r[f(1876)]=function(){var u=f,n={nkbrX:A[u(1833)],lwSGY:function(u,n){return A.XNkJm(u,n)}};if(A[u(2565)](u(5291),A.nvGub))return A.wGQUb((0,t[u(10117)])([A[u(6813)](A.eLsOO,e),A.uMYeX(A[u(4034)],e),A.scRON(u(9168),i),A[u(10195)](A.HnyQM,i)]),3)&&!A[u(8401)](o);for(var r=n[u(4374)][u(7897)]("|"),c=0;;){switch(r[c++]){case"0":this._prevBlock=_0xda6126[u(781)](_0x1382ea,n[u(6639)](_0x5634b7,q));continue;case"1":_0x1e9691[u(2210)](this,_0xd8a301,_0x2106c8,q);continue;case"2":var q=v[u(2315)];continue;case"3":v[u(5148)](_0x390cb8,_0x3b9970);continue;case"4":var v=this._cipher;continue}break}},r.isChromium=function(){var u=f;return(0,t[u(10117)])([A[u(8445)](A[u(10483)],i),A[u(2839)](A[u(4763)],i),A[u(2565)](i[u(2487)][u(4579)](A[u(4695)]),0),A[u(6159)](A[u(10027)],e),A[u(2839)](A[u(918)],e),A[u(9644)](A[u(3175)],e),A[u(10195)](A[u(2345)],e)])>=5},r.isWebKit=function(){var u=f;return A[u(3957)]((0,t.countTruthy)([A.reUHt(u(6503),e),A.muYBO("CSSPrimitiveValue",e),A[u(2839)](A[u(3781)],e),A[u(2565)](i.vendor[u(4579)](u(6973)),0),A[u(2761)](A[u(7387)],i),A[u(10084)](A[u(10048)],e)]),4)},r[f(8955)]=function(){var u=f,n={WPCIY:function(u,n){return A.vKfKG(u,n)},ucrUV:A[u(4321)]};if(A[u(6435)](A[u(9927)],A[u(9212)]))return(0,t.countTruthy)([A[u(10215)]("safari",e),!A.GDWZJ(u(10248),e),!(A[u(6164)]in e),!A.EdyUR(A[u(437)],i)])>=3;var r={udKUm:function(r,f){return n[u(4009)](r,f)}};_0x3488ad[u(1996)][u(5e3)]({name:n.ucrUV})[u(591)](function(n){var f=u;r[f(1864)](_0x275067,n[f(3637)])})},r[f(10477)]=function(){var u,n=f;return A.LmtzG("HjEKL",A[n(8594)])?A.LaTaV((0,t.countTruthy)([A[n(6813)](A[n(7447)],i),(A[n(2565)](u=c.documentElement,null)||A[n(7289)](u,void 0)?void 0:u[n(4725)])&&A[n(10195)](A[n(4658)],c.documentElement[n(4725)]),A[n(6295)](A[n(2006)],e),A.NAyuL(A[n(3369)],e),A[n(2678)](A[n(3875)],e),A.LMHsm in e]),4):A[n(5076)](_0x2ddaf2,_0x5cdfb1,_0x4c635f)},r.isChromium86OrNewer=function(){var u=f;return A[u(5281)]((0,t.countTruthy)([!A[u(6813)](A[u(472)],e),A.fcJFT(A.BDJak,e),A[u(671)]("",e.Intl)===A[u(7384)],A[u(801)](""+e[u(8798)],A[u(8047)])]),3)},r[f(3858)]=function(){var u=f;return A[u(8663)]((0,t.countTruthy)([A[u(1418)](A[u(9252)],e),A[u(10195)](A[u(7808)],e),A[u(4767)](A.djDAb,e),u(10335)in e]),3)}},{"./data":122}],122:[function(u,n,r){"use strict";var f=_0x7f58,A={BZCxU:function(u,n){return un},uCYah:function(u,n){return u>=n},dKwrZ:function(u,n){return u*n},fsvup:function(u,n){return u/n},ERRts:function(u,n){return u>>n},NtngG:function(u,n){return u-n},aABiu:function(u,n){return u%n},zMzXb:function(u,n){return u!==n},DREkl:f(8107),lleCy:function(u,n){return u+n},VNvNn:f(8606),HYvcf:f(9977),KBoOs:"TTjlq",WeGuK:function(u,n,r){return u(n,r)},eZglz:function(u,n){return u!==n},gsWmk:function(u,n){return u!==n},YGrLJ:f(1252),EKCKo:function(u,n){return u===n},cHrTH:function(u,n){return u!==n},jbAur:f(9493),Dablx:"zkabp",RDpnu:function(u,n){return u!==n},vBTPp:f(4261),HpDGd:function(u){return u()},cBJcb:function(u,n){return u instanceof n},QKCuM:function(u,n){return u!==n},BqYHu:f(802),VagtB:"nwnon",QQtCc:function(u,n){return u(n)},hVEMm:function(u,n){return u===n},TTUpn:f(2848)};function t(u,n){for(var r=f,t=0,e=u[r(7855)];A[r(1311)](t,e);++t)if(A[r(9731)]("Mcqmu",r(8008))){if(A[r(9731)](u[t],n))return!0}else this[r(1808)]--,this[r(4118)][_0x2e4087]=_0x424ff9;return!1}Object.defineProperty(r,f(861),{value:!0}),r.maxInIterator=r[f(8924)]=r[f(4715)]=r[f(6658)]=r.countTruthy=r[f(4801)]=r.toFloat=r[f(5318)]=r[f(6573)]=r[f(2019)]=void 0,r[f(2019)]=t,r.excludes=function(u,n){var r=f;return A[r(9731)](A.ApjwF,A[r(2016)])?_0x8154c8!==_0x25f021:!A[r(1851)](t,u,n)},r[f(5318)]=function(u){return A[f(4086)](parseInt,u)},r[f(4627)]=function(u){return A[f(9247)](parseFloat,u)},r.replaceNaN=function(u,n){var r=f;return A[r(9731)](typeof u,A[r(2895)])&&A[r(9247)](isNaN,u)?n:u},r[f(10117)]=function(u){var n=f,r={zsjRz:function(u,n){return A[_0x7f58(4086)](u,n)},plNft:function(u,n){return A[_0x7f58(9731)](u,n)},afGkT:A[n(9931)]};return u.reduce(function(u,f){var A=n;if(r[A(6965)](r[A(2777)],r.afGkT))return u+(f?1:0);for(var t in this)"t"===t[A(9348)](0)&&_0x34a8d1.call(this,t)&&!r[A(4880)](_0x273761,+t.slice(1))&&(this[t]=_0x33d9e9)},0)},r[f(6658)]=function(u){var n=f,r=A[n(9509)](arguments[n(7855)],1)&&void 0!==arguments[1]?arguments[1]:1;if(A[n(9771)](Math[n(2842)](r),1))return A[n(1195)](Math.round(A.fsvup(u,r)),r);var t=A[n(6301)](1,r);return Math.round(u*t)/t},r[f(4715)]=function(u){var n=f,r={ArMXA:function(u,n){return A[_0x7f58(9731)](u,n)},tXjtJ:function(u,n){return A[_0x7f58(4086)](u,n)}};if(!A.zMzXb(A[n(7566)],A[n(7566)])){for(var t,e,i=A[n(1156)](A[n(1156)](n(1056),u),"'"),c=/^\s*([a-z-]*)(.*)$/i[n(1865)](u),o=c[1]||void 0,q={},v=/([.:#][\w-]+|\[.+?\])/gi,b=function(u,r){var f=n;q[u]=q[u]||[],q[u][f(7606)](r)};;){if(A[n(1173)](A[n(9515)],n(8606))){for(var s=_0xf6f8ec[n(7992)],a=_0x142755[n(7822)],x=[],w=0;A.ERRts(w,a);w+=2){var g=A[n(9042)](A[n(2783)](s[A[n(2783)](w,2)],A[n(3711)](16,A[n(1195)](A[n(9613)](w,4),8))),65535);x.push(_0x3bcb7d[n(7805)](g))}return x.join("")}var C=v[n(1865)](c[2]);if(!C){if(!A[n(9731)](A.HYvcf,A.KBoOs))break;r.tXjtJ(_0x255654,_0x58a6e9.next(_0x47a792))}var B=C[0];switch(B[0]){case".":A[n(6453)](b,n(2865),B[n(781)](1));break;case"#":A.WeGuK(b,"id",B[n(781)](1));break;case"[":var D=/^\[([\w-]+)([~|^$*]?=("(.*?)"|([\w-]+)))?(\s+[is])?\]$/[n(1865)](B);if(!D)throw new Error(i);A[n(6453)](b,D[1],null!==(e=null!==(t=D[4])&&A[n(5312)](t,void 0)?t:D[5])&&A.eZglz(e,void 0)?e:"");break;default:throw new Error(i)}}return[o,q]}if(r[n(3121)](_0x1008be,_0x2646bd))throw _0x17df34=_0x1b217e,_0x50025d[n(5469)];_0x29d1c4[n(5628)](_0x2f5cbf[n(5469)])},r[f(8924)]=function(u,n){var r=f,t={AdyWq:function(u,n){return A[_0x7f58(298)](u,n)},XWOhy:A[r(444)]};if(A[r(405)](u,n))return!0;if(u[r(620)]!==n[r(620)])return!1;if(u[r(6988)]){for(var e=u[r(6988)](),i=e[r(6460)]();!i[r(8379)];i=e[r(6460)]())if(!n[r(3845)](i[r(10292)]))return!A.cHrTH(A[r(4239)],A.Dablx)&&_0x37b6e2;return!0}var c=!0;return u[r(7565)](function(u){var f=r;t[f(4775)](f(360),t[f(8774)])?c&&!n[f(3845)](u)&&(c=!1):_0x4071ca=_0x1c9a0c}),c},r[f(3450)]=function(u,n){var r=f;if(A[r(4137)](A[r(4290)],A[r(5094)])){for(var t=void 0,e=void 0,i=u.next();!i[r(8379)];i=u[r(6460)]()){var c=i[r(10292)],o=A[r(9433)](n,c);(A[r(2256)](e,void 0)||o>e)&&(A[r(405)]("VubKD",A[r(7251)])?(this[_0xa3b45c]=_0xc2045a(),this[r(4118)]=this[r(4412)]=_0x9f53b1,this[r(8896)]=[],A.RDpnu(_0x578367,_0x4e1534)&&(A[r(1173)](typeof _0x1ea979,A[r(2372)])&&A[r(713)](_0x355ce4),A[r(6162)](this,_0xc27d59)?_0x6a9f7(this,_0x2221c9):A[r(713)](_0x40ae1e))):(t=c,e=o))}return t}return _0x4ee452}},{}],123:[function(u,n,r){"use strict";var f=_0x7f58,A={SxxNm:function(u,n){return u(n)},uaPTe:function(u,n){return u===n},CTOTh:f(10290),ecRti:f(3709),qrXmK:"nymku",maCdS:f(2525),docox:function(u,n){return u>n},FHxcb:function(u,n){return u+n},gbgRf:function(u,n){return u|n},FeBkc:function(u,n){return u<>>n},oxjGN:function(u,n){return u>>>n},XtKKW:function(u,n){return u+n},yhPZu:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},WzqsT:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},gRpHy:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},xKrvV:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},rxXyX:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},itjqO:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},uvEEr:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},GyAUk:function(u,n){return u!==n},vTDFs:f(9376),QEWNH:f(9615),JqRRQ:function(u,n){return u instanceof n},ClAVy:f(8961),xKtwp:function(u,n,r){return u(n,r)},LfbgI:function(u,n){return u(n)},XLuFK:function(u,n){return u===n},svuEP:"ribuG",GonkX:f(8626),wYjUo:function(u,n){return u(n)},OSSPh:f(7106),rhCaA:"UfxgZ",nIMhq:function(u,n){return u===n},MEBOc:"oRFjr",pgvqx:f(9381),QyLsc:function(u,n){return u(n)},YBqkV:f(3225),lHViJ:"RlryL",aaxOB:function(u,n){return u(n)},iHEBO:f(6818),jODRP:function(u,n){return u===n},MVqlg:function(u,n){return u+n},GOhIU:"' method",sUqyz:f(363),SnhiV:f(7951),ZsEKp:function(u,n){return u!==n},BUlmw:function(u,n,r){return u(n,r)},fEUWW:function(u,n){return u>n},PCKaU:function(u,n){return u!==n},BKVRd:function(u,n){return u&n},DjARZ:function(u,n){return u|n},RTggm:function(u,n){return u&n},IMeJN:function(u,n){return u<>>n},aJGEh:function(u,n){return u>=n},dZTqn:f(10009),vSQsi:"ubigN",KHcoQ:function(u,n){return u!==n},wsXty:"eeBvK",klDvk:f(4725),IWkoU:function(u,n,r){return u(n,r)},JeeOH:"QaOSs",iCzhO:f(3551),ADssR:f(10133),NKXxw:function(u,n){return u>>>n},WoPri:function(u,n){return u&n},JLUmM:function(u,n){return u&n},fshqW:"auKXG",VEzlB:function(u,n,r){return u(n,r)},KThXb:function(u,n){return u||n},NCpIx:"GEeOc",Ogzqd:f(858),HAuMk:f(861),gBBYR:f(5238),oebdQ:function(u,n){return u(n)},GiRjl:f(6144)},t=function(){var u=f,n={qRLRQ:function(u,n){return A[_0x7f58(5261)](u,n)},BnIdm:function(u,n){return A[_0x7f58(8326)](u,n)},HOAJX:A[u(1908)],OHZcb:A[u(4771)],BpFWQ:A[u(6433)],GEuCX:A[u(711)],qLGIh:function(u,n){return u(n)},AprXA:function(u,n){return u===n},TBTCa:function(n,r){return A[u(4190)](n,r)},KbQUA:function(n,r){return A[u(3415)](n,r)},vGpmx:function(u,n){return A.gbgRf(u,n)},tDqDB:function(n,r){return A[u(3089)](n,r)},kjeAG:function(n,r){return A[u(877)](n,r)},CaYLF:function(n,r){return A[u(1838)](n,r)},JcfWi:function(n,r){return A[u(3415)](n,r)},TaMxC:function(u,n){return A.XtKKW(u,n)},ppTZY:function(u,n){return u+n},WwlbV:function(n,r,f,t,e,i,c,o){return A[u(1519)](n,r,f,t,e,i,c,o)},uixrq:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},lpCKo:function(n,r,f,t,e,i,c,o){return A[u(7627)](n,r,f,t,e,i,c,o)},VAvQl:function(n,r,f,t,e,i,c,o){return A[u(9948)](n,r,f,t,e,i,c,o)},mCJFA:function(n,r,f,t,e,i,c,o){return A[u(9948)](n,r,f,t,e,i,c,o)},QGTCl:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},KFlVa:function(n,r,f,t,e,i,c,o){return A[u(9948)](n,r,f,t,e,i,c,o)},xPJZg:function(n,r,f,t,e,i,c,o){return A[u(4948)](n,r,f,t,e,i,c,o)},KhOSk:function(n,r,f,t,e,i,c,o){return A[u(9948)](n,r,f,t,e,i,c,o)},CjBnK:function(n,r,f,t,e,i,c,o){return A[u(5531)](n,r,f,t,e,i,c,o)},BUTpE:function(n,r,f,t,e,i,c,o){return A[u(2198)](n,r,f,t,e,i,c,o)},FqvEQ:function(n,r,f,t,e,i,c,o){return A[u(10021)](n,r,f,t,e,i,c,o)},WyNdB:function(n,r){return A[u(8363)](n,r)},xckHo:function(n,r){return A[u(8583)](n,r)},socGh:u(6230),mKqeC:function(u,n){return u in n},ufyRr:A[u(6510)],FdmVO:A[u(1091)]};return function(r,f){var A=u,t={vtFNh:function(u,r){return n[_0x7f58(7673)](u,r)},IONfI:function(u,n){return u&n},qnnNN:function(u,r){return n.vGpmx(u,r)},QYQEf:function(u,r){return n[_0x7f58(9021)](u,r)},EhYij:function(u,r){return n[_0x7f58(1036)](u,r)},aFnhJ:function(u,r){return n[_0x7f58(6942)](u,r)},dYUOr:function(u,r){return n[_0x7f58(3519)](u,r)},Xadvs:function(u,r){return n[_0x7f58(8090)](u,r)},IXugh:function(u,r){return n.ppTZY(u,r)},vpmng:function(u,r){return n.JcfWi(u,r)},rOUfw:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},LkeId:function(u,r,f,A,t,e,i,c){return n.WwlbV(u,r,f,A,t,e,i,c)},Eyuuh:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},ChHUA:function(u,r,f,A,t,e,i,c){return n[_0x7f58(4510)](u,r,f,A,t,e,i,c)},GGkSw:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},fLXjd:function(u,r,f,A,t,e,i,c){return n[_0x7f58(7067)](u,r,f,A,t,e,i,c)},zraGO:function(u,r,f,A,t,e,i,c){return n[_0x7f58(7067)](u,r,f,A,t,e,i,c)},NiSWV:function(u,r,f,A,t,e,i,c){return n[_0x7f58(3208)](u,r,f,A,t,e,i,c)},UnwhR:function(u,r,f,A,t,e,i,c){return n[_0x7f58(3208)](u,r,f,A,t,e,i,c)},fvuFH:function(u,r,f,A,t,e,i,c){return n.VAvQl(u,r,f,A,t,e,i,c)},QmiNh:function(u,r,f,A,t,e,i,c){return n.mCJFA(u,r,f,A,t,e,i,c)},XHRYs:function(u,r,f,A,t,e,i,c){return n[_0x7f58(969)](u,r,f,A,t,e,i,c)},NWDhX:function(u,r,f,A,t,e,i,c){return n[_0x7f58(3808)](u,r,f,A,t,e,i,c)},AvSSY:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},HIngY:function(u,r,f,A,t,e,i,c){return n[_0x7f58(8162)](u,r,f,A,t,e,i,c)},uERMo:function(u,r,f,A,t,e,i,c){return n.mCJFA(u,r,f,A,t,e,i,c)},SiJsH:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},WCHPm:function(u,r,f,A,t,e,i,c){return n[_0x7f58(3808)](u,r,f,A,t,e,i,c)},ZurCy:function(u,r,f,A,t,e,i,c){return n[_0x7f58(6404)](u,r,f,A,t,e,i,c)},TnVyW:function(u,r,f,A,t,e,i,c){return n[_0x7f58(1455)](u,r,f,A,t,e,i,c)},Lbmwe:function(u,r,f,A,t,e,i,c){return n[_0x7f58(6404)](u,r,f,A,t,e,i,c)},JwQVE:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},akQYU:function(u,r,f,A,t,e,i,c){return n[_0x7f58(3808)](u,r,f,A,t,e,i,c)},bBGhX:function(u,r,f,A,t,e,i,c){return n[_0x7f58(969)](u,r,f,A,t,e,i,c)},vrxCm:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},wJwNz:function(u,r,f,A,t,e,i,c){return n.CjBnK(u,r,f,A,t,e,i,c)},UABix:function(u,r,f,A,t,e,i,c){return n[_0x7f58(6325)](u,r,f,A,t,e,i,c)},BCSTC:function(u,r,f,A,t,e,i,c){return n[_0x7f58(7724)](u,r,f,A,t,e,i,c)},YnMCF:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},TfwKB:function(u,r){return n.WyNdB(u,r)},DgMTC:function(u,r){return n[_0x7f58(2747)](u,r)}};if(n[A(8200)](n[A(8256)],"nEdCT")){for(var e=void 0,i=void 0,c=_0x5670b0[A(6460)]();!c.done;c=_0x26af9f[A(6460)]()){var o=c[A(10292)],q=n[A(10255)](_0x5ecb46,o);(n[A(8349)](i,_0x2a5a04)||n.TBTCa(q,i))&&(e=o,i=q)}return e}if(Array.isArray(r))return r;if(n[A(4200)](Symbol.iterator,n[A(10255)](Object,r)))return function(r,f){var A=u,t=[],e=!0,i=!1,c=void 0;try{for(var o,q=r[Symbol[A(9869)]]();!(e=(o=q[A(6460)]())[A(8379)])&&(t[A(7606)](o.value),!f||!n.BnIdm(t[A(7855)],f));e=!0);}catch(u){A(1738)!==n.HOAJX?(i=!0,c=u):_0x38a7e4(this,_0x7cb368)}finally{if(n[A(2577)]!==n[A(7958)])try{!e&&q[A(2525)]&&q[n[A(5405)]]()}finally{if(i)throw c}else n[A(7416)](_0x5dc73d,_0x47acad)}return t}(r,f);if(!n[A(8200)](n[A(3536)],"ioBoz"))throw new TypeError(n.FdmVO);for(var v=0;v<16;v++){var b=t.vtFNh(_0x1e3665,v),s=_0x374052[b];_0x4488df[b]=t[A(8994)](t.qnnNN(t[A(6655)](s,8),t[A(1088)](s,24)),16711935)|t[A(8994)](t[A(1975)](t[A(6655)](s,24),t.aFnhJ(s,8)),4278255360)}var a=this[A(8810)][A(7992)],x=_0x4d5acb[t[A(3978)](_0x96835f,0)],w=_0x36854c[_0x1a0f85+1],g=_0x2b38a1[_0x3fbd44+2],C=_0x5ece25[t.vtFNh(_0x2885b4,3)],B=_0x378637[t[A(3978)](_0x362d1a,4)],D=_0x2c6e1f[t[A(3978)](_0x2b5bab,5)],L=_0x56ed23[t[A(3978)](_0x527a39,6)],z=_0x894ccb[t.vtFNh(_0x49285c,7)],E=_0xe89bf3[t[A(6078)](_0x39ebc4,8)],d=_0x2f4127[t[A(6078)](_0xb0178c,9)],I=_0x37db79[t[A(9329)](_0x36e4ad,10)],j=_0x1a48d1[t[A(9476)](_0x4c311a,11)],K=_0x3bfbd8[t[A(9476)](_0x2447bb,12)],y=_0xf89709[t[A(6599)](_0x273f49,13)],h=_0x1f12a4[t[A(9476)](_0x2ba261,14)],_=_0xca179c[_0x11a8a5+15],Q=a[0],N=a[1],M=a[2],l=a[3];Q=t[A(5600)](_0x2bb352,Q,N,M,l,x,7,_0x476482[0]),l=t.LkeId(_0x39c08c,l,Q,N,M,w,12,_0x960fa[1]),M=t[A(287)](_0x1b6f23,M,l,Q,N,g,17,_0x4e92f6[2]),N=_0x1a1e8e(N,M,l,Q,C,22,_0x281617[3]),Q=_0x28195f(Q,N,M,l,B,7,_0xf713ef[4]),l=t.rOUfw(_0x19f896,l,Q,N,M,D,12,_0x2beb41[5]),M=_0x70147a(M,l,Q,N,L,17,_0x4b4e41[6]),N=t[A(9314)](_0x2e3323,N,M,l,Q,z,22,_0x2d7d74[7]),Q=t.GGkSw(_0x4df8fc,Q,N,M,l,E,7,_0xe3fc38[8]),l=t[A(4975)](_0x1d419a,l,Q,N,M,d,12,_0x497667[9]),M=_0x841b0b(M,l,Q,N,I,17,_0x30acc2[10]),N=t[A(4975)](_0x341e72,N,M,l,Q,j,22,_0x55305c[11]),Q=t[A(4769)](_0xacb05b,Q,N,M,l,K,7,_0x3bde24[12]),l=t[A(2542)](_0x28b678,l,Q,N,M,y,12,_0x273e40[13]),M=t[A(1033)](_0x50ff48,M,l,Q,N,h,17,_0x3e474b[14]),N=t.UnwhR(_0x4082a6,N,M,l,Q,_,22,_0x285a75[15]),Q=t.zraGO(_0x43f268,Q,N,M,l,w,5,_0x173bba[16]),l=t[A(3995)](_0x469273,l,Q,N,M,L,9,_0x5c1268[17]),M=_0xe7425b(M,l,Q,N,j,14,_0x3e9918[18]),N=t[A(2195)](_0x3b3dd0,N,M,l,Q,x,20,_0x577a7d[19]),Q=t.fvuFH(_0x1c3697,Q,N,M,l,D,5,_0x34d5c3[20]),l=t.GGkSw(_0x7ed0bd,l,Q,N,M,I,9,_0x320238[21]),M=t.QmiNh(_0x3c6481,M,l,Q,N,_,14,_0x3b10a5[22]),N=t.XHRYs(_0xaad859,N,M,l,Q,B,20,_0x1cbcab[23]),Q=t[A(6331)](_0x22cd59,Q,N,M,l,d,5,_0x226658[24]),l=t[A(287)](_0x516d7c,l,Q,N,M,h,9,_0x5522b4[25]),M=t[A(4602)](_0x181057,M,l,Q,N,C,14,_0x48b68a[26]),N=t[A(9314)](_0x26c0e4,N,M,l,Q,E,20,_0x3073c3[27]),Q=t[A(8788)](_0x2d0969,Q,N,M,l,y,5,_0x4a74ee[28]),l=t[A(4769)](_0x1711cc,l,Q,N,M,g,9,_0x1062db[29]),M=t[A(5600)](_0x57df93,M,l,Q,N,z,14,_0x34ce72[30]),N=t[A(2039)](_0x387d0b,N,M,l,Q,K,20,_0x4e47f4[31]),Q=t[A(5600)](_0x350c26,Q,N,M,l,D,4,_0x29647e[32]),l=t.ChHUA(_0x56a7dd,l,Q,N,M,E,11,_0x51bab9[33]),M=t.uERMo(_0x411301,M,l,Q,N,j,16,_0x129427[34]),N=t[A(3199)](_0x2f27a6,N,M,l,Q,h,23,_0x10f273[35]),Q=t[A(915)](_0x426d30,Q,N,M,l,w,4,_0x2fbb5a[36]),l=_0x4d5741(l,Q,N,M,B,11,_0x2798bb[37]),M=_0x4e223a(M,l,Q,N,z,16,_0x23c82d[38]),N=t[A(7784)](_0x4ce35b,N,M,l,Q,I,23,_0x233ead[39]),Q=t[A(6586)](_0x590e38,Q,N,M,l,y,4,_0x35e340[40]),l=_0x297af9(l,Q,N,M,x,11,_0x3e8517[41]),M=t[A(8788)](_0x1be344,M,l,Q,N,C,16,_0x3fffcc[42]),N=t.ZurCy(_0x24c4f5,N,M,l,Q,L,23,_0x26464e[43]),Q=t[A(597)](_0xea32d1,Q,N,M,l,d,4,_0x207194[44]),l=_0x33c60e(l,Q,N,M,K,11,_0x725048[45]),M=t[A(6875)](_0x4ade38,M,l,Q,N,_,16,_0x2f18d7[46]),N=_0x420f5d(N,M,l,Q,g,23,_0x3bc28a[47]),Q=t[A(5731)](_0x230e8f,Q,N,M,l,x,6,_0x2b55aa[48]),l=_0x245b92(l,Q,N,M,z,10,_0x47a2f4[49]),M=t[A(8526)](_0x46e2cd,M,l,Q,N,h,15,_0x36dd97[50]),N=t[A(6331)](_0x190068,N,M,l,Q,D,21,_0xc4f636[51]),Q=t[A(6446)](_0x4e5ee6,Q,N,M,l,K,6,_0xc23960[52]),l=_0x21b67d(l,Q,N,M,C,10,_0x39b65b[53]),M=t.Eyuuh(_0x5d3b22,M,l,Q,N,I,15,_0x4e2ea6[54]),N=t[A(8646)](_0x557585,N,M,l,Q,w,21,_0x93752d[55]),Q=t.ChHUA(_0x11ea75,Q,N,M,l,E,6,_0x43e3db[56]),l=t.wJwNz(_0x4fe32a,l,Q,N,M,_,10,_0x2854bc[57]),M=t[A(7706)](_0x3e31c0,M,l,Q,N,L,15,_0x569dcc[58]),N=t[A(4254)](_0x2b023a,N,M,l,Q,y,21,_0x4e17ed[59]),Q=t[A(8664)](_0x3f5844,Q,N,M,l,B,6,_0x20195c[60]),l=_0x296bb2(l,Q,N,M,j,10,_0x3d7a92[61]),M=t.rOUfw(_0x220a21,M,l,Q,N,g,15,_0x2f2258[62]),N=_0x2ce721(N,M,l,Q,d,21,_0x1b2d24[63]),a[0]=t[A(5095)](t[A(9476)](a[0],Q),0),a[1]=0|t[A(10226)](a[1],N),a[2]=a[2]+M|0,a[3]=0|t[A(3978)](a[3],l)}}(),e=function(u,n,r,t){var e=f,i={OUuXw:function(u,n){return A.XLuFK(u,n)},TCDCZ:A[e(7978)],bNXxS:A.GonkX,rxVDx:function(u,n){return A[e(4758)](u,n)},IvzGO:A[e(2861)],YHJRh:function(u,n){return A[e(5261)](u,n)},PlrqK:e(3408),UsOMz:A[e(4033)],EwfDM:function(u,n){return A[e(6682)](u,n)},HHfUn:A.MEBOc,UUdwc:A[e(8743)],dqCsA:function(u,n){return A[e(3475)](u,n)},JgSyY:A[e(2786)],XaIZE:function(u,n){return u!==n},YeZbM:A.lHViJ,XaoSx:function(u,n){return A[e(9320)](u,n)},CRDrr:function(u,n){return A.QyLsc(u,n)}};function c(u){return A[e(2383)](u,r)?u:new r(function(n){n(u)})}return new(r||(r=Promise))(function(r,f){var o=e,q={CRXnZ:function(u,n){return A.uaPTe(u,n)},YyCXA:A.maCdS,OBbRA:A[o(8793)],fNJYT:function(u,n,r){return A[o(4055)](u,n,r)},BvTpq:function(u,n){return A[o(5261)](u,n)}};function v(u){var n=o;try{var r;if(i[n(2497)](i[n(6123)],i[n(6039)]))_0xdbb0e++,null===(r=_0x13fe6b[n(5280)])||q[n(461)](r,void 0)||r.call(_0x256839,_0x127b52);else i[n(10511)](s,t[n(6460)](u))}catch(u){if(n(6582)===i[n(7181)])switch(_0x20f76e[n(2519)]=_0x532884.next){case 0:return _0x418342[n(4922)](q[n(10393)],(0,_0x120139.match)({includes:[!0],excludes:[_0x5af693[n(4793)],_0x288ce1[n(6195)],(_0x422b66.isIpad||_0x1192fd[n(4276)])&&_0x459ea3[n(3512)]]}));case 1:case q.OBbRA:return _0xfa6013.stop()}else i[n(9370)](f,u)}}function b(u){var n=o,r={ziicr:function(u,n){return u+n},MGjXP:function(u,n,r,f){return u(n,r,f)}};try{if(i[n(2497)](i.PlrqK,i[n(2847)])){const u=q[n(2704)](_0x44e4d8,_0xca239f,10);return q[n(1154)](_0x41cd2a,u)?_0x3ca2b1:u}s(t.throw(u))}catch(u){i.EwfDM(i.HHfUn,i[n(3644)])?_0x1136db+=r[n(1459)](r[n(2470)](_0x51f5cb,_0x2b57ac,_0x21ee0c,_0xb7234d),_0x5b9181[0]):i[n(6100)](f,u)}}function s(u){var n=o,f={bAlpL:i.JgSyY};i.XaIZE(i[n(3042)],i[n(3042)])?_0x1cd704?(_0x3647d1.appId=_0x4ff218,(0,_0x2b8277.setDataAndCookie)(_0xfe066d.appidName,_0x4fc77e)):_0x1ec11a[n(9569)](f[n(253)]):u[n(8379)]?i[n(6010)](r,u[n(10292)]):i.CRDrr(c,u.value)[n(591)](v,b)}A[o(332)](s,(t=t[o(6346)](u,n||[])).next())})};Object[f(4594)](r,A.HAuMk,{value:!0}),r[f(6727)]=r[f(4743)]=r.withIframe=void 0;var i=u(A.gBBYR),c=A.oebdQ(u,A.GiRjl);function o(u,n){var r=f,e={McPfd:function(u,n){return A[_0x7f58(8363)](u,n)},WPOfM:function(u,n){return A[_0x7f58(10188)](u,n)},abjVk:function(u,n){return A[_0x7f58(4413)](u,n)},oEuGQ:function(u,n){return A[_0x7f58(3089)](u,n)},CBqzy:function(u,n){return u&n},YXEII:function(u,n){return A[_0x7f58(4199)](u,n)}},i=!0,c=!1,o=void 0;try{if(A.KHcoQ(A.fshqW,r(417)))for(var q,v=n[r(7897)](";")[Symbol.iterator]();!(i=(q=v[r(6460)]()).done);i=!0){var b=q.value,s=/^\s*([\w-]+)\s*:\s*(.+?)(\s*!([\w-]+))?\s*$/[r(1865)](b);if(s){var a=A[r(5918)](t,s,5),x=a[1],w=a[2],g=a[4];u[r(1077)](x,w,A[r(8264)](g,""))}}else _0x4dc77f[r(7423)](_0xa6b1f4)&&(this[_0x117af8]=_0x58b7c6[_0x4fa249])}catch(u){c=!0,o=u}finally{try{!i&&v.return&&v.return()}finally{if(A[r(845)]!=A[r(845)])_0x190e2c=e.McPfd(_0x5e685b[e[r(4133)](_0x348071,24)]<<24|_0x3fd2be[e[r(9141)](_0x537114>>>16,255)]<<16,e[r(2331)](_0x227391[e[r(1240)](e[r(4133)](_0x31b4bb,8),255)],8))|_0x48b514[e.YXEII(_0x307e1a,255)];else if(c){if(!A[r(3273)](A[r(7879)],A[r(7879)]))throw o;!_0x1d4b36&&_0x38a51a[r(2525)]&&_0x42a234[r(2525)]()}}}}r[f(1708)]=function(u,n){var r,t,c,o=f,q={gPcUm:function(u,n){return A[_0x7f58(8583)](u,n)},LJVRY:A[o(7941)],ChRlG:function(u,n,r,f){return u(n,r,f)},Bwdtc:function(u,n){return A[o(5261)](u,n)},MzXvq:function(u,n){return A[o(1513)](u,n)},beUyk:o(8044),YAlHv:function(u,n){return A[o(9639)](u,n)},Fegfd:A[o(9278)],GJBgO:A[o(7510)],PzMSi:A.SnhiV,wYgwT:o(2597),VFHcK:function(u,n){return A[o(3273)](u,n)},CWREo:o(3848),iMyIb:o(5934),bAJzv:function(u,n,r){return A.BUlmw(u,n,r)},vcqmM:A[o(8793)]},v=A.fEUWW(arguments[o(7855)],2)&&A[o(1626)](arguments[2],void 0)?arguments[2]:50;return e(this,void 0,void 0,regeneratorRuntime.mark(function f(){var A,e,b=o,s={SzoZE:function(u,n){return q.gPcUm(u,n)},IMimD:q[b(1608)],OGuDp:function(u,n,r,f){return q[b(10020)](u,n,r,f)},DsUvX:function(u,n){return q[b(5366)](u,n)},tMmoU:function(u,n){return q[b(4438)](u,n)},mmeEe:q[b(869)],UMIQc:function(u,n){return q[b(5366)](u,n)},DOUck:function(u,n){return q.YAlHv(u,n)},bUcKw:q[b(8659)],oUoYL:q[b(977)],alGim:function(u,n){return q[b(4438)](u,n)},snYIA:function(u,n){return u!==n},vanLE:q[b(7609)],mJkxr:function(u){return u()},RaFdK:b(4741),dmdKX:function(u,n){return u(n)},mpCRa:b(9962),pHiqK:q[b(5595)],BjpUu:function(u,n){return q[b(5668)](u,n)},ZhfeH:"TmozZ",fIink:b(7479),Ldckr:q[b(3895)],Tgmfb:function(u,n){return q.MzXvq(u,n)},kQHYU:function(u,n){return u!==n},QTTgN:q.iMyIb,umpNi:function(u,n,r){return q[b(3331)](u,n,r)},CIafC:q[b(8139)]};return regeneratorRuntime[b(4099)](function(f){var o=b,q={TpLOd:function(u,n){return s.DsUvX(u,n)},GaAWI:function(u,n){return s[_0x7f58(10500)](u,n)},bBnEW:s[o(4954)],kwHrQ:o(2647),PpOSH:function(u,n){return s.UMIQc(u,n)},rNZtH:function(u,n){return s.DOUck(u,n)},YRKUd:s[o(1042)],dNdyk:s.oUoYL,LpAUM:function(u,n){return s[o(10500)](u,n)},buJvd:function(u,n){return s[o(10500)](u,n)},rFuEz:function(u,n){return s[o(4179)](u,n)},hwFpg:function(u,n){return u===n},iZgmK:function(u,n){return s.snYIA(u,n)},GussU:s[o(2320)],qTvog:function(u){return s[o(8745)](u)},rYOou:s[o(482)],JJZQz:function(u,n){return s[o(9448)](u,n)},AEHCb:s.mpCRa,oEOJQ:o(9008),GFanq:"block",npHfe:s[o(7829)],DuwqU:function(u,n){return u in n},OJKFJ:function(u,n){return s[o(5779)](u,n)},GQqPK:s.ZhfeH,DHUCX:s[o(3198)],gBgmO:s[o(4571)]};if(s[o(5906)](o(2036),o(6841)))s.SzoZE(_0x26e3e5,s.IMimD)&&_0x22d670[o(10129)].hasOwnProperty[o(2210)](_0x3ba414,_0x2d5e19)&&s[o(8051)](_0x542443,_0x4679e1,_0xf360bd,_0x1de943);else for(;;)switch(f[o(2519)]=f[o(6460)]){case 0:A=document;case 1:if(A[o(2599)]){if(s[o(8512)](s[o(2212)],s[o(2212)]))return _0x45834e[o(5614)]({supported:!1,error:_0x1364b0.message});f[o(6460)]=6;break}return f[o(6460)]=4,(0,i[o(530)])(v);case 4:f[o(6460)]=1;break;case 6:return e=A[o(10284)](o(6793)),f[o(2519)]=7,f[o(6460)]=10,new Promise(function(u,r){var f=o,t={lzbNY:function(u,n){return q[_0x7f58(4702)](u,n)},Fylin:"./core",jIJib:function(u,n){return q[_0x7f58(4702)](u,n)}};if(!q[f(10315)](q.AEHCb,q[f(3583)]))return _0x37333c[f(4128)][f(446)];var i=!1,c=function(){i=!0,q.TpLOd(u,"")};e[f(6096)]=c,e[f(2798)]=function(u){var n=f;q.GaAWI(q[n(2175)],q.kwHrQ)?_0x1febd0+=2:(i=!0,q[n(9849)](r,u))};var v=e[f(4725)];v.setProperty(q[f(7104)],q[f(4875)],f(2317)),v[f(5389)]=f(4277),v[f(2498)]="0",v[f(454)]="0",v.visibility=q[f(4552)],n&&q[f(3558)]("srcdoc",e)?e[f(8624)]=n:q[f(9905)](q.GQqPK,q[f(8687)])?e[f(3544)]=q.gBgmO:_0x536448[f(8018)]=_0x3ec6c0=_0x45cf6c(t[f(6675)](_0x1970e7,t.Fylin),t[f(6675)](_0x75f591,"./cipher-core")),A[f(2599)][f(5453)](e),function u(){var n,r,A=f,o={riCeV:function(u,n){return q[_0x7f58(1601)](u,n)},Hbibj:q.YRKUd,gNevg:"not support sessionstorage"};if(i){if(!q[A(3857)](A(10304),q[A(404)]))return;_0x41b66e[A(8379)]?t[A(6675)](_0x476ba3,_0x1c4136[A(10292)]):t[A(5052)](_0x4308f7,_0x4d4bd1[A(10292)])[A(591)](_0x3a5418,_0x5b9af7)}if(q[A(10315)](q[A(3857)](r=q[A(630)](n=e.contentWindow,null)||q[A(5409)](n,void 0)?void 0:n.document,null)||q[A(8340)](r,void 0)?void 0:r[A(6938)],A(8465)))q.iZgmK(q.GussU,q[A(5169)])?(_0x57afa9[A(1713)]=A(10009),_0xfe7bc7[A(5469)]=new _0x2ebd1a(o[A(4364)](o.riCeV(A(3881),_0xa0aff8),o[A(10412)]))):q.qTvog(c);else{if(q[A(6278)]!=q[A(6278)])return o[A(5748)];setTimeout(u,10)}}()});case 10:if(s[o(4179)](t=s[o(5906)](r=e[o(7484)],null)||void 0===r?void 0:r[o(1581)],null)||void 0===t?void 0:t.body){f[o(6460)]=15;break}return f.next=13,(0,i.wait)(v);case 13:f.next=10;break;case 15:return f[o(6460)]=17,s[o(4718)](u,e,e[o(7484)]);case 17:return f[o(4922)](o(2525),f.sent);case 18:return f[o(2519)]=18,null===(c=e.parentNode)||s.alGim(c,void 0)||c[o(3761)](e),f.finish(18);case 21:case s[o(5354)]:return f[o(9572)]()}},f,this,[[7,,18,21]])}))},r[f(4743)]=function(u){var n=f,r={uwYKj:function(u,n){return A[_0x7f58(6423)](u,n)},SElZc:function(u,n){return A[_0x7f58(10064)](u,n)},GcVoS:A[n(9840)]};if(A[n(3489)]!=A[n(3489)]){_0x1d4b51&&(_0x1f6441=_0xbd45d9);var e=0,i=function(){};return{s:i,n:function(){var u=n;return r[u(4813)](e,_0x42b917[u(7855)])?{done:!0}:{done:!1,value:_0x32c121[e++]}},e:function(u){throw u},f:i}}var q=(0,c[n(4715)])(u),v=A.xKtwp(t,q,2),b=v[0],s=v[1],a=document[n(10284)](A.PCKaU(b,null)&&A[n(3273)](b,void 0)?b:n(1053)),x=!0,w=!1,g=void 0;try{if(A[n(2356)](A[n(1762)],A.wsXty))_0xfc39c0=_0x5bc2d7,_0x3ddfd8=1,_0x1f2a2c=_0x325e0c;else for(var C,B=Object[n(2431)](s)[Symbol.iterator]();!(x=(C=B.next())[n(8379)]);x=!0){var D=C[n(10292)],L=s[D].join(" ");if(D===A[n(10228)])A[n(9702)](o,a.style,L);else if(A[n(8326)](A[n(7111)],A[n(7111)]))a[n(5119)](D,L);else{var z=this[n(5273)][_0x4123f0];if(z.tryLoc===_0x46bc5e){var E=z[n(6372)];if(r[n(9074)](E[n(7772)],r[n(9809)])){var d=E.arg;_0xbe3282(z)}return d}}}}catch(u){A[n(2356)](A.iCzhO,A[n(1316)])?_0x648a95(_0x41a9d1,_0x8d5431):(w=!0,g=u)}finally{try{if(!x&&B[n(2525)])if(A[n(347)]!==A.ADssR){var I=A[n(9639)](_0x4a8e36,_0x5a2b1b),j=_0x29436c[I];_0x309be9[I]=A.gbgRf(A[n(6023)](A[n(5007)](j<<8,A[n(1838)](j,24)),16711935),A[n(2880)](A[n(8363)](A[n(7432)](j,24),A[n(682)](j,8)),4278255360))}else B[n(2525)]()}finally{if(w)throw g}}return a},r[f(6727)]=o},{"./async":120,"./data":122}],124:[function(u,n,r){"use strict";var f=_0x7f58,A={zhzwE:f(1026),gPpYM:function(u,n){return u(n)},jUYEd:function(u){return u()},UhUtT:function(u,n){return u(n)},VuWTw:function(u,n){return u===n},klAku:f(6240),EGDuo:function(u,n,r){return u(n,r)},iTCnq:function(u,n,r){return u(n,r)},etbQb:function(u,n,r,f){return u(n,r,f)},xLEeo:"2|3|1|4|0",LfmfI:function(u,n){return u!=n},HFOay:function(u,n){return u!==n},ksnxO:"return",PovmJ:f(4175),NOQUW:f(3788),vKwwE:f(1043),yPcmP:f(3184),pnPqn:f(1290),MOIhP:f(7971),NSvmW:"cURdk",RStHn:f(2603),MUPWg:f(5861),AuAGE:f(6264),mVwLZ:f(10108),PyBEe:f(2568),NtkJw:function(u,n){return u===n},hnHJq:f(7078),vRJaH:function(u,n){return u+n},SwjFO:function(u,n){return u==n},rwwZd:function(u,n){return u==n},PsxiC:function(u,n){return u+n},OTLkM:function(u,n){return u+n},vTPUa:"domain=",keUNF:function(u,n){return u+n},LtqFS:function(u,n){return u*n},SsvgE:"__esModule",paoPs:".huya.com"};Object[f(4594)](r,A[f(8995)],{value:!0}),r[f(3741)]=r[f(758)]=r[f(1005)]=r.getData=void 0;var t=7,e=A[f(4731)];function i(u){var n=f,r={HgwfW:A[n(6932)],FUoJg:function(u,n){return A.LfmfI(u,n)},tDWIJ:function(u,r){return A[n(9e3)](u,r)},fbZKm:n(6818),QNWoo:function(u,n,r,f){return u(n,r,f)},DJqnV:function(u,r,f){return A[n(6589)](u,r,f)},UdKAq:A.ksnxO};if(A[n(7471)]===A[n(2788)])for(var t=r[n(6370)][n(7897)]("|"),e=0;;){switch(t[e++]){case"0":return c;case"1":if(r[n(2683)](_0x1a95df,null))for(var i in _0x5cb330)r[n(4526)](i,r.fbZKm)&&_0x5b4d6f[n(10129)].hasOwnProperty[n(2210)](_0x10cd5a,i)&&r[n(7496)](_0x28b773,c,_0x354294,i);continue;case"2":if(_0x5684a1&&_0x7d521e[n(861)])return _0x3afed7;continue;case"3":var c={};continue;case"4":r[n(5234)](_0x1ffdd2,c,_0x3551c1);continue}break}else try{return window[n(9662)][n(8350)](u)}catch(u){if(A[n(4013)](n(1043),A[n(7065)]))return;switch(_0x57f017.prev=_0x105c27[n(6460)]){case 0:return _0x521d66=!1,(0,_0x21c588.table)({dep:_0x5b042a}),_0x5ce800[n(4922)](r.UdKAq,_0x219d78);case 3:case n(8961):return _0x481e2a.stop()}}}function c(u,n){var r=f,t={qbHOF:A.yPcmP};if(A.pnPqn!==A[r(2584)]){if(function(){var u=f,n={VVhTg:function(u,n){var r=_0x7f58;return A[r(8146)](u,n)},ClRND:A[u(5170)],LdeXR:A[u(5051)]};if(A[u(6478)]===A[u(2141)])return _0x106b7d[u(4703)](_0x2f70bb).compute(_0x6f7e8,_0x4d7bbf);try{if(!A.NtkJw(A[u(8789)],u(2450)))return!!window[u(9662)];n[u(10298)](_0x36414a,_0x41821c[u(5614)](_0x4fce50,[n.ClRND,n.LdeXR]))}catch(u){return!1}}())try{return window.localStorage[r(10001)](u,n),!0}catch(u){return!A[r(9e3)](A.NSvmW,A[r(8012)])&&t.qbHOF}return!1}_0x2fbe79[r(8262)]&&(_0x2fc0f1[r(5677)]=(new _0x2f6cd1.ListFormat)[r(10523)]())}function o(u){for(var n=f,r=A[n(7888)](u,"="),t=document[n(3363)][n(7897)](";"),e=0;e=n},FIyvi:function(u,n){return u===n},JzCvv:"Mcqkc",ChKQX:function(u,n){return u(n)},VKNaw:function(u,n){return u instanceof n},jAodl:"dQGqd",YSMFt:"VkOaL",mdrEQ:"kSvHh",IgogV:function(u,n){return u==n},nsgrd:A(1461),kInmF:A(4261),AYoVI:function(u,n){return u!=n},YPlXt:"undefined",bNWFJ:A(6499),xcStL:A(1166),bILFk:"yDmPu",ZvZOW:function(u,n){return u&&n},fnkws:function(u,n){return u==n},wtEam:A(3452),appSS:A(10340),EWOfe:"Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.",pFcfM:function(u,n){return u>>>n},jAEEl:function(u,n){return u+n},UkjFe:function(u,n){return u===n},aRTsY:A(4218),aAkLf:A(7158),TebqH:function(u,n,r){return u(n,r)},rgyiP:A(5197),EdgvU:function(u,n){return u===n},kqlst:"Map",fpQvZ:function(u,n){return u===n},eohvS:A(3387),QDLaj:A(3350),HOszh:function(u,n,r){return u(n,r)},DsirM:"MFeKm",eBIhI:function(u,n){return u==n},UcWGP:function(u,n){return u>n},nCFsa:function(u,n){return u(n)},RJSdX:function(u,n){return u>>n},SCVeU:function(u,n){return u-n},NHtoA:function(u,n){return u>>>n},QGwDP:A(3932),AXngL:A(2173),eTUpf:A(6092),tqMIH:function(u,n,r,f){return u(n,r,f)},gYwQN:function(u,n,r,f){return u(n,r,f)},DuxAa:A(9413),vDGZg:function(u,n,r,f){return u(n,r,f)},LXCjz:"GeneratorFunction",mCdUe:A(2070),iaHXI:A(9965),yyjfj:A(9295),Gwqeg:A(9159),gdHXM:A(6460),VtFjl:A(10009),mtEoy:function(u,n,r){return u(n,r)},CwsSw:A(2525),SuJEv:function(u,n){return u&n},tnvAs:function(u,n){return u>>>n},LaBpA:A(456),wRdoL:"iITbE",fHdYa:function(u,n,r,f){return u(n,r,f)},uiMkL:function(u,n,r,f,A){return u(n,r,f,A)},OJQQG:function(u,n){return u(n)},qPtpN:function(u,n,r,f,A,t,e,i){return u(n,r,f,A,t,e,i)},ceTGh:A(7663),ztryg:function(u,n){return u!==n},zKZGr:A(10202),fuElJ:function(u){return u()},MhFSI:function(u){return u()},OeHLw:function(u,n){return u!=n},FcAth:function(u,n){return u*n},myBkI:"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BEAgA0EBNgIYIAMgATYCDCADQqCAgICABDcCECADQX82AiwgA0KAgICAcDcCJCADQgE3AhwgA0EMahDnASECDAELIANBDGoiAkEgQR8gBiAGZyIEdEH/////B3EbIARrIgQ2AgQgAiABNgIAIAJCADcCFCACIARBBXYgBEEfcUEAR2oiATYCDCACIAQgAW4iBTYCCCACQX9Bf0EfIAVrdiAFQR9PGzYCICACQX9BICAFa3ZBACABIARNGzYCHCACIAEgASAFbCAEa2o2AhAgAiEBA0AgARDnASICIAZPDQALIAAoAgAgAmohAgsgA0EwaiQAIAILGQEBfyABEOsBIQIgACABNgIEIAAgAjYCAAsXACAAIAM2AhAgACACNgIMIAAgATYCCAsPACAAIAEgARAmEJcBIAALEQAgACABQTBqOgAAIABBAWoLEgAgACgCACIABEAgABDYARoLCxEAIAAgASgCABDYATYCACAACxkBAX8gARCjASECIAAgATYCBCAAIAI2AgALJAAgAEECTwR/IABBAmpBfnEiACAAQQFrIgAgAEECRhsFQQELCwgAIABB/wFxCwsAIAQgAjYCAEEDCwwAIAAgASgCADYCAAsXACAAEB0EQCAAIAE2AgQPCyAAIAEQHAtCAQF/IAAoAgAhAiABEAkhACACQQhqIgEQISAASwR/IAEgABAqKAIAQQBHBUEAC0UEQBAsAAsgAkEIaiAAECooAgALQwEDfwJAIAJFDQADQCAALQAAIgQgAS0AACIFRgRAIAFBAWohASAAQQFqIQAgAkEBayICDQEMAgsLIAQgBWshAwsgAwsNACAAIAEgARAmEJcBCxEAIAAgASAAKAIAKAIcEQMACwcAIABBC0kLIwECfyMAQRBrIgIkACAAIAEQXSEDIAJBEGokACABIAAgAxsLDgAgACgCCEH/////B3ELGQEBf0EKIQEgABAdBH8gABBKQQFrBUEKCwsLACAALQALQf8AcQscAQF/IAAoAgAhAiAAIAEoAgA2AgAgASACNgIACwsAIABBDGoQVyAAC0gBAn8gACgCBCIGQQh1IQUgBkEBcQRAIAIoAgAgBRBsIQULIAAoAgAiACABIAIgBWogA0ECIAZBAnEbIAQgACgCACgCGBELAAsbACAAIAFBwIQ9biIAECMgASAAQcCEPWxrEG4LBwAgAEECSQsEAEEECwoAIABBGHRBGHULKAEBfyAAIAAoAgRBAWsiATYCBCABQX9GBEAgACAAKAIAKAIIEQEACwsIAEH/////BwsFAEH/AAsIACAAEIMBGgtjACACKAIEQbABcSICQSBGBEAgAQ8LAkAgAkEQRw0AAkACQCAALQAAIgJBK2sOAwABAAELIABBAWoPCyACQTBHIAEgAGtBAkhyDQAgAC0AAUEgckH4AEcNACAAQQJqIQALIAALKwEBfyMAQRBrIgUkACAFIAQoAgA2AgAgACABIAIgAyAFEIMDIAVBEGokAAsJACAAEA4gAWoLSgECfwJAIAAtAAAiAkUgAiABLQAAIgNHcg0AA0AgAS0AASEDIAAtAAEiAkUNASABQQFqIQEgAEEBaiEAIAIgA0YNAAsLIAIgA2sLEQAgACABIAAoAgAoAiwRAwALDQAgACgCACABKAIASQsKACAAQbiEARBECwcAIABBCEsLJgAgACAAKAIYRSAAKAIQIAFyciIBNgIQIAAoAhQgAXEEQBAsAAsLIwECfyMAQRBrIgIkACABIAAQXSEDIAJBEGokACABIAAgAxsLjgEBA38CQCABIAIQsQMhBCMAQRBrIgMkACAEQff///8HTQRAAkAgBBBIBEAgACAEEBwgACEFDAELIANBCGogBBArQQFqEDggAygCDBogACADKAIIIgU2AgAgACADKAIMEBkgACAENgIECyABIAIgBRCwAyADQQA6AAcgA0EHahAeIANBEGokAAwBCxASAAsLEgAgAEIANwIAIABBADYCCCAACwgAIAAQThAMC4wBAQF/AkAgACgCBCIBIAEoAgBBDGsoAgBqKAIYRQ0AIAAoAgQiASABKAIAQQxrKAIAahCYAUUNACAAKAIEIgEgASgCAEEMaygCAGooAgRBgMAAcUUNACAAKAIEIgEgASgCAEEMaygCAGooAhgQjQFBf0cNACAAKAIEIgAgACgCAEEMaygCAGpBARBgCwuwAQEBfyAAIAE2AgQgAEEAOgAAIAEgASgCAEEMaygCAGoQmAEEQCABIAEoAgBBDGsoAgBqKAJIIgEEQCMAQRBrIgIkACABIAEoAgBBDGsoAgBqKAIYBEAgAkEIaiABEGYaAkAgAi0ACEUNACABIAEoAgBBDGsoAgBqKAIYEI0BQX9HDQAgASABKAIAQQxrKAIAakEBEGALIAJBCGoQZQsgAkEQaiQACyAAQQE6AAALIAALCwAgAEEEahBXIAALYQECfz8AQRB0IgMgACACakkgASACaiADS3IEQAALIAAgAUsEfyACQQFrIQNBfyECQX8FQQAhA0EBCyEEA0AgAiADRkUEQCAAIANqIAEgA2otAAA6AAAgAyAEaiEDDAELCwtKAQJ/IAAoAgQiB0EIdSEGIAdBAXEEQCADKAIAIAYQbCEGCyAAKAIAIgAgASACIAMgBmogBEECIAdBAnEbIAUgACgCACgCFBEKAAsgAAJAIAEgACgCBEcNACAAKAIcQQFGDQAgACACNgIcCwuaAQAgAEEBOgA1AkAgAiAAKAIERw0AIABBAToANAJAIAAoAhAiAkUEQCAAQQE2AiQgACADNgIYIAAgATYCECADQQFHDQIgACgCMEEBRg0BDAILIAEgAkYEQCAAKAIYIgJBAkYEQCAAIAM2AhggAyECCyAAKAIwQQFHDQIgAkEBRg0BDAILIAAgACgCJEEBajYCJAsgAEEBOgA2CwsKACAAIAFqKAIAC3YBAX8gACgCJCIDRQRAIAAgAjYCGCAAIAE2AhAgAEEBNgIkIAAgACgCODYCFA8LAkACQCAAKAIUIAAoAjhHDQAgACgCECABRw0AIAAoAhhBAkcNASAAIAI2AhgPCyAAQQE6ADYgAEECNgIYIAAgA0EBajYCJAsLGwAgACABQZDOAG4iABAjIAEgAEGQzgBsaxBvCxkAIAAgAUHkAG4iABAjIAEgAEHkAGxrECMLggIAIAFBv4Q9TQRAIAFBj84ATQRAIAFB4wBNBEAgAUEJTQRAIAAgARA7DwsgACABECMPCyABQecHTQRAIAAgAUHkAG4iABA7IAEgAEHkAGxrECMPCyAAIAEQbw8LIAFBn40GTQRAIAAgAUGQzgBuIgAQOyABIABBkM4AbGsQbw8LIAAgARBuDwsgAUH/wdcvTQRAIAFB/6ziBE0EQCAAIAFBwIQ9biIAEDsgASAAQcCEPWxrEG4PCyAAIAEQUA8LIAFB/5Pr3ANNBEAgACABQYDC1y9uIgAQOyABIABBgMLXL2xrEFAPCyAAIAFBgMLXL24iABAjIAEgAEGAwtcvbGsQUAs9AQF/IwBBEGsiAyQAIAMgAjoADwNAIAEEQCAAIAMtAA86AAAgAUEBayEBIABBAWohAAwBCwsgA0EQaiQAC5wCAQN/IwBBIGsiCCQAQff///8HIgkgAUF/c2ogAk8EQCAAEA4hCiABQfP///8DSQRAIAggAUEBdDYCHCAIIAEgAmo2AhAgCEEQaiAIQRxqEEkoAgAQK0EBaiEJCyAIQRxqIAhBGGogABAaKAIAEHYgCEEQaiAJEDggCCgCECECIAgoAhQaIAQEQCACIAogBBAPCyAGBEAgAiAEaiAHIAYQDwsgAyAEIAVqIglrIQcgAyAJRwRAIAIgBGogBmogBCAKaiAFaiAHEA8LIAFBCkcEQCAKEIQBCyAAIAI2AgAgACAIKAIUEBkgACAEIAZqIAdqIgA2AgQgCEEAOgAPIAAgAmogCEEPahAeIAhBHGoQdSAIQSBqJAAPCxASAAsWACAAIAEoAgA2AgAgACACKAIANgIECxIAQQQQXwRAIAAQDA8LIAAQDAsKACAAKAIAEBMaCwkAIAAgARAaGgsXACAAKAIIECVHBEAgACgCCBDaAQsgAAsLACAAQQhqEFcgAAsoAQJ/IwBBEGsiAiQAIAEoAgAgACgCAEghAyACQRBqJAAgASAAIAMbCxAAIAAgATcDCCAAQgA3AwALAgALqQEBA38gARAdRQRAIAAgASkCADcCACAAIAEoAgg2AgggABBMGg8LIAEoAgAhBCABKAIEIQIjAEEQayIDJAACQAJAAkAgAhBIBEAgACIBIAIQHAwBCyACQff///8HSw0BIANBCGogAhArQQFqEDggAygCDBogACADKAIIIgE2AgAgACADKAIMEBkgACACNgIECyABIAQgAkEBahAPIANBEGokAAwBCxASAAsLEwAgAEH8DjYCACAAQQRqEBsgAAthAQF/IwBBEGsiAiQAIAIgADYCDAJAIAAgAUYNAANAIAIgAUEBayIBNgIIIAAgAU8NASACKAIMIAIoAggQ6AIgAiACKAIMQQFqIgA2AgwgAigCCCEBDAALAAsgAkEQaiQACwQAQQELAgALIAEBfyMAQRBrIgEkACABQQxqIAAQGigCACABQRBqJAALmgMBCH8CQCAAIgFBA3EEQANAIAEtAAAiAkUgAkE9RnINAiABQQFqIgFBA3ENAAsLAkACQEGAgoQIIAEoAgAiA2sgA3JBgIGChHhxQYCBgoR4Rw0AA0BBgIKECCADQb369OkDcyICayACckGAgYKEeHFBgIGChHhHDQEgASgCBCEDIAFBBGoiAiEBIANBgIKECCADa3JBgIGChHhxQYCBgoR4Rg0ACwwBCyABIQILA0AgAiIBLQAAIgNFDQEgAUEBaiECIANBPUcNAAsLIAAgAUYEQEEADwsCQCAAIAEgAGsiA2otAAANAEHk/wAoAgAiBEUNACAEKAIAIgFFDQADQAJAAn8gACECQQAgAyIGRQ0AGiAALQAAIgUEfwJAA0AgBSABLQAAIgdHIAdFcg0BIAZBAWsiBkUNASABQQFqIQEgAi0AASEFIAJBAWohAiAFDQALQQAhBQsgBQVBAAsgAS0AAGsLRQRAIAQoAgAgA2oiAS0AAEE9Rg0BCyAEKAIEIQEgBEEEaiEEIAENAQwCCwsgAUEBaiEICyAIC3EBAn8gAEHsFzYCACAAKAIcBEAgACgCKCEBA0AgAQRAQQAgACABQQFrIgFBAnQiAiAAKAIkaigCACAAKAIgIAJqKAIAEQYADAELCyAAQRxqEBsgACgCIBAMIAAoAiQQDCAAKAIwEAwgACgCPBAMCyAACxIAQQEQXwRAIAAQDA8LIAAQDAsIACAAEC0QDAsWACAAQfQQNgIAIABBIGoQBhogABB9Cw8AIAAgACgCGCABajYCGAsXACAAIAI2AhwgACABNgIUIAAgATYCGAuRAwELfyMAQRBrIgkkAAJAIAlBCGogABBmIg0tAABBAUcNACAAIAAoAgBBDGsoAgBqIgMoAhghBCABIAJqIgogASADKAIEQbABcUEgRhshCAJAIAMtAFBBAUYEQCADKAJMIQIMAQsjAEEQayIFJAAgBUEMaiIGIAMQIiAGEF4iAkEgIAIoAgAoAhwRAwAhAiAGEBsgBUEQaiQAIAMgAjYCTCADQQE6AFALIAJBGHRBGHUhBkEAIQIjAEEQayIHJAACQCAERQ0AIAMoAgwhCyAIIAFrIgVBAEoEQCAEIAEgBSAEKAIAKAIwEQQAIAVHDQELIAogAWsiASALSARAIAdBBGoiDCALIAFrIgUgBhCUASAEIAcoAgQgDCAHLAAPQQBIGyAFIAQoAgAoAjARBAAgDBAGGiAFRw0BCyAKIAhrIgFBAEoEQCAEIAggASAEKAIAKAIwEQQAIAFHDQELIANBADYCDCAEIQILIAdBEGokACACDQAgACAAKAIAQQxrKAIAakEFEGALIA0QZSAJQRBqJAALCgAgAEGwhAEQRAsIACAAEGcQDAs7AQF/IAAoAhgiAiAAKAIcRgRAIAAgARBAIAAoAgAoAjQRAwAPCyAAIAJBAWo2AhggAiABOgAAIAEQQAsPACAAIAAoAgAoAhgRAAALoQEBA38jAEGQAWsiACQAIAAgBDYCjAEgAEIlNwOAASAAQYABaiIGQQFyQYALIAUgAigCBBDHASAAQfMAaiIEIARBDRAlIAYgAEGMAWoQWSAEaiIHIAIQWCEIIABBBGoiBiACECIgBCAIIAcgAEEQaiIEIABBDGogAEEIaiAGEP4CIAYQGyABIAQgACgCDCAAKAIIIAIgAxDDASAAQZABaiQAC50BAQN/IwBB0ABrIgAkACAAIAQ2AkwgAEIlNwNAIABBQGsiBkEBckGACyAFIAIoAgQQxwEgAEEzaiIEIARBDRAlIAYgAEHMAGoQWSAEaiIHIAIQWCEIIABBBGoiBiACECIgBCAIIAcgAEEQaiIEIABBDGogAEEIaiAGEIoDIAYQGyABIAQgACgCDCAAKAIIIAIgAxDGASAAQdAAaiQAC0IAA0AgASACRwRAIAECfyABLAAAEBUEQCADKAIAIAEsAABBAnRqKAIADAELIAEtAAALOgAAIAFBAWohAQwBCwsgAQs9AANAIAEgAkcEQCABIgAgACgCABAVBH8gAygCACAAKAIAQQJ0agUgAAsoAgA2AgAgAEEEaiEBDAELCyABC4ABAQN/IAAoAgQiBEEBcSEFAn8gAS0AN0EBRgRAIARBCHUiBiAFRQ0BGiACKAIAIAYQbAwBCyAEQQh1IAVFDQAaIAEgACgCACgCBDYCOCAAKAIEIQRBACECQQALIQUgACgCACIAIAEgAiAFaiADQQIgBEECcRsgACgCACgCHBEIAAuJAQEDfyAAEBMiAiABSQRAIwBBEGsiBCQAIAEgAmsiAgRAIAIgABBLIgMgABATIgFrSwRAIAAgAyACIANrIAFqIAEgARC9AQsgASAAEA4iA2ogAkEAEHEgACABIAJqIgAQQyAEQQA6AA8gACADaiAEQQ9qEB4LIARBEGokAA8LIAAgABAOIAEQogELhQEBAn8jAEEQayIDJAAgAUH3////B00EQAJAIAEQSARAIAAgARAcIAAhBAwBCyADQQhqIAEQK0EBahA4IAMoAgwaIAAgAygCCCIENgIAIAAgAygCDBAZIAAgATYCBAsgBCABIAIQcSADQQA6AAcgASAEaiADQQdqEB4gA0EQaiQADwsQEgALeAEDfyMAQRBrIgUkAAJAIAIgABBLIgQgABATIgNrTQRAIAJFDQEgABAOIgQgA2ogASACEA8gACACIANqIgEQQyAFQQA6AA8gASAEaiAFQQ9qEB4MAQsgACAEIAIgBGsgA2ogAyADQQAgAiABEHILIAVBEGokACAAC0MBAn8gABBLIQMgABATIQQgAiADTQRAIAAQDiIDIAEgAhAPIAAgAyACEKIBDwsgACADIAIgA2sgBEEAIAQgAiABEHILhQEBAn8jAEEQayIDJAAgAkH3////B00EQAJAIAIQSARAIAAgAhAcIAAhBAwBCyADQQhqIAIQK0EBahA4IAMoAgwaIAAgAygCCCIENgIAIAAgAygCDBAZIAAgAjYCBAsgBCABIAIQDyADQQA6AAcgAiAEaiADQQdqEB4gA0EQaiQADwsQEgALCAAgACgCEEULCQAgABAlNgIACyMBAn8gACEBA0AgASICQQRqIQEgAigCAA0ACyACIABrQQJ1Cy4BAX8jAEEQayIDJAACQCAAIAFGBEAgAEEAOgB4DAELIAEgAhB0CyADQRBqJAALEAAgACgCCCAAKAIAa0ECdQsJACAAQQA2AgALSQEBfyMAQRBrIgMkAAJAAkAgAkEeSw0AIAEtAHhBAXENACABQQE6AHgMAQsgAhCjASEBCyADQRBqJAAgACACNgIEIAAgATYCAAs5AQJ/IwBBEGsiACQAIABB/////wM2AgwgAEH/////BzYCCCAAQQxqIABBCGoQYSgCACAAQRBqJAALCAAgABB4EAwLCgAgACABIABragsyAQF/IwBBEGsiAyQAIAAQExogACACEEMgA0EAOgAPIAEgAmogA0EPahAeIANBEGokAAswACAAQf////8DSwRAECwACwJ/IABBAnQhAEEEEF8EQCAAQQQQ6gEMAQsgABDpAQsLCAAgABB3EAwLBABBfwsVACAAQbDIADYCACAAQRBqEAYaIAALFQAgAEGIyAA2AgAgAEEMahAGGiAAC4ADAQR/IAIhAANAAkAgBCAHTSAAIANPcg0AIAAsAAAiAUH/AXEhBQJ/QQEgAUEATg0AGiABQUJJDQEgAUFfTQRAIAMgAGtBAkgNAiAALQAB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ByAFQQRqIgkgAUHz////A0kEfyAFIAFBAXQ2AgwgBSABIAJqNgIEIAkgBUEMahBJKAIAECtBAWoFQff///8HCxA4IAUoAgQhAiAFKAIIGiAEBEAgAiAHIAQQDwsgAyAERwRAIAIgBGogBCAHaiADIARrEA8LIAFBCkcEQCAHEIQBCyAAIAI2AgAgACAFKAIIEBkgBUEQaiQADAELEBIACyAAIAM2AgQgCBB1IAZBEGokAAsMACAAQQFBLRDCARoLDAAgAEEBQS0QxQEaC1kBAX8gACAAKAJIIgFBAWsgAXI2AkggACgCACIBQQhxBEAgACABQSByNgIAQX8PCyAAQgA3AgQgACAAKAIsIgE2AhwgACABNgIUIAAgASAAKAIwajYCEEEACwQAQQILxwEBBH8jAEEQayIDJAACQCABQff///8DTQRAAkAgARBRBEAgACABEBwgACEEDAELIANBCGogARA/QQFqED4gAygCDBogACADKAIIIgQ2AgAgACADKAIMEBkgACABNgIECyMAQRBrIgUkACAFIAI2AgwgBCEGIAEhAgNAIAIEQCAGIAUoAgw2AgAgAkEBayECIAZBBGohBgwBCwsgBUEQaiQAIANBADYCBCAEIAFBAnRqIANBBGoQQiADQRBqJAAMAQsQEgALIAALoQEBBH8jAEEQayIHJAACQCAARQ0AIAQoAgwhBiACIAFrQQJ1IghBAEoEQCAAIAEgCBAuIAhHDQELIAMgAWtBAnUiASAGSARAIAAgB0EEaiAGIAFrIgEgBRDCASIFEA4gARAuIQYgBRAfGiABIAZHDQELIAMgAmtBAnUiAUEASgRAIAAgAiABEC4gAUcNAQsgBBDEASAAIQkLIAdBEGokACAJCw8AIAAoAgwaIABBADYCDAsNACAAIAEgAhCUASAAC5gBAQR/IwBBEGsiByQAAkAgAEUNACAEKAIMIQYgAiABayIIQQBKBEAgACABIAgQLiAIRw0BCyADIAFrIgEgBkgEQCAAIAdBBGogBiABayIBIAUQxQEiBRAOIAEQLiEGIAUQBhogASAGRw0BCyADIAJrIgFBAEoEQCAAIAIgARAuIAFHDQELIAQQxAEgACEJCyAHQRBqJAAgCQuqAQEBfwJAIANBgBBxRSACRXINACADQcoAcSIEQQhGIARBwABGcg0AIABBKzoAACAAQQFq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ACABIAEoAgAoAhwRAgALEQAgACABIAEoAgAoAhgRAgALCgAgAEHwhAEQRAsVACACBEAgACABQRh0QRh1IAIQMQsLMQEBf0G8/wAoAgAhASAABEBBvP8AQcT+ACAAIABBf0YbNgIAC0F/IAEgAUHE/gBGGwvPBAEHfyAAQQA2AlwgAEHUFTYCQCAAQawVNgIAIABBwBU2AgggAEHkFSgCACIBNgIAIAAgAUEMaygCAGpB6BUoAgA2AgAgAEEANgIEIAAgACgCAEEMaygCAGoiAkEANgIUIAIgAEEMaiIBNgIYIAJBADYCDCACQoKggIDgADcCBCACIAFFNgIQIAJBIGpBAEEoEDEgAkEcahCzASACQQA6AFAgAkKAgICAcDcCSCAAQewVKAIAIgI2AgggAkEMaygCACAAQQhqakHwFSgCADYCACAAQeAVKAIAIgI2AgAgACACQQxrKAIAakH0FSgCADYCACAAQfgVKAIANgIIIABBrBU2AgAgAEHAFTYCCCAAQdQVNgJAIAFB/A42AgAgAUEEahCzASABQgA3AhggAUIANwIQIAFCADcCCCABQgA3AiAgAUH0EDYCACABQRg2AjAgAUIANwIoIAFBADYCLCABKAIgIAFBIGoiBiABLAArIgVBAEgiAhshAyABKAIkIAUgAhshBCABKAIwIgdBCHEEQCABIAM2AgwgASADNgIIIAEgAyAEaiICNgIQIAEgAjYCLAsCQCAHQRBxRQ0AIAEgAyAEajYCLCAGQQogASgCKEH/////B3FBAWsgBUEAThsQkwEgASADNgIYIAEgAzYCFCABIAMgASgCJCABLAArIgIgAkEASBtqNgIcIAEtADBBA3FFDQADQCAEQQBIBEAgASADQf////8HaiIDNgIYIARB/////wdrIQQMAQsLIARFDQAgASADIARqNgIYCyAACw4AIAAQ2wEEQCAAEAwLCyUAIABBAEcgAEHYIEdxIABB8CBHcSAAQfD/AEdxIABBiIABR3EL3AIBA38CQCABLQAADQBB1wwQggEiAQRAIAEtAAANAQsgAEEMbEGQIWoQggEiAQRAIAEtAAANAQtB5AwQggEiAQRAIAEtAAANAQtB6w0hAQsCQANAIAEgAmotAAAiBEUgBEEvRnJFBEBBFyEEIAJBAWoiAkEXRw0BDAILCyACIQQLQesNIQMCQAJA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B0EEaiIHIANPDQEgCkEATg0ACwsgAEEwIApBEmpBEkEAEBEgACASIBEgEmsQEAwCCyAKIQYLIABBMCAGQQlqQQlBABARCyAAQSAgAiAJIARBgMAAcxARIAIgCSACIAlKGyENDAELIBQgBUEadEEfdUEJcWohCQJAIANBC0sNAEEMIANrIQZEAAAAAAAAMEAhGANAIBhEAAAAAAAAMECiIRggBkEBayIGDQALIAktAABBLUYEQCAYIAGaIBihoJohAQwBCyABIBigIBihIQELIBEgCygCLCIHIAdBH3UiBnMgBmutIBEQNiIGRgRAIAZBAWsiBkEwOgAAIAsoAiwhBwsgEEECciEKIAVBIHEhDCAGQQJrIg4gBUEPajoAACAGQQFrQS1BKyAHQQBIGzoAACAEQQhxRSADQQBMcSEIIAtBEGohBwNAIAciBSABmUQAAMD////fQWMEfyABqgVBgICAgHgLIgZBkCBqLQAAIAxyOgAAIAEgBrehRAAAAAAAADBAoiIBRAAAAAAAAAAAYSAIcSAFQQFqIgcgC0EQamtBAUdyRQRAIAVBLjoAASAFQQJqIQcLIAFEAAAAAAAAAABiDQALQX8hDSADQf3///8HIAogESAOayIIaiIGa0oNACAAQSAgAiAGIANBAmogByALQRBqIgVrIgcgB0ECayADSBsgByADGyIDaiIGIAQQESAAIAkgChAQIABBMCACIAYgBEGAgARzEBEgACAFIAcQECAAQTAgAyAHa0EAQQAQESAAIA4gCBAQIABBICACIAYgBEGAwABzEBEgAiAGIAIgBkobIQ0LIAtBsARqJAAgDQu6AgACQAJAAkACQAJAAkACQAJAAkACQAJAIAFBCWsOEgAICQoICQECAwQKCQoKCAkFBgcLIAIgAigCACIBQQRqNgIAIAAgASgCADYCAA8LIAIgAigCACIBQQRqNgIAIAAgATIBADcDAA8LIAIgAigCACIBQQRqNgIAIAAgATMBADcDAA8LIAIgAigCACIBQQRqNgIAIAAgATAAADcDAA8LIAIgAigCACIBQQRqNgIAIAAgATEAADcDAA8LIAIgAigCAEEHakF4cSIBQQhqNgIAIAAgASsDADkDAA8LIAAgAhDeAQsPCyACIAIoAgAiAUEEajYCACAAIAE0AgA3AwAPCyACIAIoAgAiAUEEajYCACAA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AgAgAEEQaiQACwQAQX8LOwADQCABIAJGRQRAIAMhACAEIAEsAAAQFQR/IAEtAAAFIAALOgAAIARBAWohBCABQQFqIQEMAQsLIAELCwAgASACIAEQFRsLKgADQCABIAJGRQRAIAMgAS0AADoAACADQQFqIQMgAUEBaiEBDAELCyABCw4AIAAgASACQeAtEJABCyEAIAEQFQR/QeAtKAIAIAFBAnRqKAIABSABC0EYdEEYdQsOACAAIAEgAkHYIRCQAQslACABEBUEf0HYISgCACABQf8BcUECdGooAgAFIAELQRh0QRh1CwkAIAAQsAEQDAs7AANAIAEgAkZFBEAgAyEAIAQgASgCABAVBH8gASgCAAUgAAs6AAAgBEEBaiEEIAFBBGohAQwBCwsgAQsRACABIAIgARAVG0EYdEEYdQsqAANAIAEgAkZFBEAgAyABLAAANgIAIANBBGohAyABQQFqIQEMAQsLIAELDgAgACABIAJB4C0QkQELGwAgARAVBH9B4C0oAgAgAUECdGooAgAFIAELCw4AIAAgASACQdghEJEBCxsAIAEQFQR/QdghKAIAIAFBAnRqKAIABSABCws5AANAAkAgAiADRg0AIAIoAgAQFUUNACACKAIAQQJ0QdA/aigCACABcUUNACACQQRqIQIMAQsLIAILOAADQAJAIAIgA0YNACACKAIAEBUEQCACKAIAQQJ0QdA/aigCACABcQ0BCyACQQRqIQIMAQsLIAILRQADQCABIAJGRQRAQQAhACADIAEoAgAQFQR/IAEoAgBBAnRB0D9qKAIABUEACzYCACADQQRqIQMgAUEEaiEBDAELCyABCyIAQQAhACACEBUEfyACQQJ0QdA/aigCACABcUEARwVBAAsLDwAgACAAKAIAKAIEEQEACwkAIAAQtgEQDAu8AQEEfyMAQRBrIgQkAANAAkAgAiAFTA0AAkAgACgCDCIDIAAoAhAiBkkEQCAEQf////8HNgIMIAQgBiADazYCCCAEIAIgBWs2AgQgBEEMaiAEQQhqIARBBGoQeRB5IQMgASAAKAIMIAMoAgAiAxAPIAAgACgCDCADajYCDAwBCyAAIAAoAgAoAigRAAAiA0F/Rg0BIAEgAxBTOgAAQQEhAwsgASADaiEBIAMgBWohBQwBCwsgBEEQaiQAIAULCAAgAEJ/EHoLqwEAAkAgBRAdRQRAIAAgBSkCADcCACAAIAUoAgg2AgggABBMGgwBCyAFKAIAIQQgBSgCBCECIwBBEGsiAyQAAkACQAJAIAIQUQRAIAAiASACEBwMAQsgAkH3////A0sNASADQQhqIAIQP0EBahA+IAMoAgwaIAAgAygCCCIBNgIAIAAgAygCDBAZIAAgAjYCBAsgASAEIAJBAWoQJyADQRBqJAAMAQsQEgALCwsIACAAIAUQfAsFAQh/AAsFAQt/AAsFAQh/AAsFAQt/AAsIACAAQn8QegsXACACIAAgASAAayIAQQJ1ECcgACACagsZAQF/QQEhASAAEB0EfyAAEEpBAWsFQQELCwUBBH8ACwUBA38ACwQAIAALEAEBfyAAKAIAIABBADYCAAsFAQN/AAsFAQN/AAsLACAAEH0aIAAQDAsKACABIABrQQJ1CwUBAn8ACxwBAX8gAC0AACECIAAgAS0AADoAACABIAI6AAALBQECfwALBQEBfwALBQECfwALBQECfwALBQECfwALAwAACwUBAX8ACwUBAX8ACwUBAn8ACwUBAn8ACwUBAn8ACwMAAAsFAQF/AAtgAQF/IwBBEGsiAiQAIAIgADYCDAJAIAAgAUYNAANAIAIgAUEEayIBNgIIIAAgAU8NASACKAIMIAIoAggQTSACIAIoAgxBBGoiADYCDCACKAIIIQEMAAsACyACQRBqJAALhAEBBH8jAEHAAWsiACQAIAAgBDYCvAEgAEGgAWoiBSAFIAVBFBAlQccKIABBvAFqEFkiB2oiBCACEFghBiAAIAIQIiAAEIoBIAAQGyAFIAQgABDMASABIAAgACAHQQJ0aiIBIAAgBiAFa0ECdGogBCAGRhsgASACIAMQwwEgAEHAAWokAAsFAQd/AAsFABAEAAsFAQd/AAsDAAALEQAgACABIAIgAyAEQQAQjgELAwAAC+YDAQh/IwBBEGsiCyQAIAYQigEhCiALQQRqIgcgBhDPASIGEMoBAkAgBxDTAQRAIAogACACIAMQzAEgBSADIAIgAGtBAnRqIgY2AgAMAQsgBSADNgIAAkACQCAAIgctAAAiCEEraw4DAAEAAQsgCiAIQRh0QRh1EFwhByAFIAUoAgAiCEEEajYCACAIIAc2AgAgAEEBaiEHCwJAIAIgB2tBAkgNACAHLQAAQTBHDQAgBy0AAUEgckH4AEcNACAKQTAQXCEIIAUgBSgCACIJQQRqNgIAIAkgCDYCACAKIAcsAAEQXCEIIAUgBSgCACIJQQRqNgIAIAkgCDYCACAHQQJqIQcLIAcgAhB+QQAhCSAGEMsBIQ1BACEIIAchBgN/IAIgBk0EfyADIAcgAGtBAnRqIAUoAgAQ9gIgBSgCAAUCQCALQQRqIgwgCBBaLQAARQ0AIAkgDCAIEFosAABHDQAgBSAFKAIAIglBBGo2AgAgCSANNgIAIAggCCAMEBNBAWtJaiEIQQAhCQsgCiAGLAAAEFwhDCAFIAUoAgAiDkEEajYCACAOIAw2AgAgBkEBaiEGIAlBAWohCQwBCwshBgsgBCAGIAMgASAAa0ECdGogASACRhs2AgAgC0EEahAGGiALQRBqJAALEQAgACABIAIgAyAEQQEQjgELDwAgACAAKAIAQQRqNgIACxEAIAAQDiAAEBNBAnRqEIEBC84BAQF/IwBBIGsiBSQAIAUgATYCHAJAIAIoAgRBAXFFBEAgACABIAIgAyAEIAAoAgAoAhgRBwAhAgwBCyAFQRBqIgAgAhAiIAAQzwEhASAAEBsCQCAEBEAgACABENUBDAELIAVBEGogARDUAQsgBSAFQRBqEMkBNgIMA0AgBSAFQRBqIgAQgQM2AgggBUEMaiAFQQhqEMgBBEAgBSgCHCECIAAQHxoFIAVBHGogBUEMaiIAKAIAKAIAEPEBIAAQgAMMAQsLCyAFQSBqJAAgAgtCAQF/IwBBEGsiBSQAIAUgAjYCDCAFIAQ2AgggBUEEaiAFQQxqED0gACABIAMgBSgCCBCpAyEAEDwgBUEQaiQAIAALewEEfyMAQdAAayIAJAAgACAENgJMIABBMGoiBSAFIAVBFBAlQccKIABBzABqEFkiB2oiBCACEFghBiAAIAIQIiAAEF4gABAbIAUgBCAAENABIAEgACAAIAdqIgEgACAGIAVraiAEIAZGGyABIAIgAxDGASAAQdAAaiQACwUBB38ACwUBB38ACwMAAAsRACAAIAEgAiADIARBABCPAQsDAAAL2wMBCH8jAEEQayILJAAgBhBeIQogC0EEaiIHIAYQ1gEiBhDKAQJAIAcQ0wEEQCAKIAAgAiADENABIAUgAyACIABraiIGNgIADAELIAUgAzYCAAJAAkAgACIHLQAAIghBK2sOAwABAAELIAogCEEYdEEYdRBHIQcgBSAFKAIAIghBAWo2AgAgCCAHOgAAIABBAWohBwsCQCACIAdrQQJIDQAgBy0AAEEwRw0AIActAAFBIHJB+ABHDQAgCkEwEEchCCAFIAUoAgAiCUEBajYCACAJIAg6AAAgCiAHLAABEEchCCAFIAUoAgAiCUEBajYCACAJIAg6AAAgB0ECaiEHCyAHIAIQfkEAIQkgBhDLASENQQAhCCAHIQYDfyACIAZNBH8gAyAHIABraiAFKAIAEH4gBSgCAAUCQCALQQRqIgwgCBBaLQAARQ0AIAkgDCAIEFosAABHDQAgBSAFKAIAIglBAWo2AgAgCSANOgAAIAggCCAMEBNBAWtJaiEIQQAhCQsgCiAGLAAAEEchDCAFIAUoAgAiDkEBajYCACAOIAw6AAAgBkEBaiEGIAlBAWohCQwBCwshBgsgBCAGIAMgASAAa2ogASACRhs2AgAgC0EEahAGGiALQRBqJAALEQAgACABIAIgAyAEQQEQjwELDwAgACAAKAIAQQFqNgIACw4AIAAQDiAAEBNqEIEBC84BAQF/IwBBIGsiBSQAIAUgATYCHAJAIAIoAgRBAXFFBEAgACABIAIgAyAEIAAoAgAoAhgRBwAhAgwBCyAFQRBqIgAgAhAiIAAQ1gEhASAAEBsCQCAEBEAgACABENUBDAELIAVBEGogARDUAQsgBSAFQRBqEMkBNgIMA0AgBSAFQRBqIgAQjQM2AgggBUEMaiAFQQhqEMgBBEAgBSgCHCECIAAQBhoFIAVBHGogBUEMaiIAKAIALAAAEPYBIAAQjAMMAQsLCyAFQSBqJAAgAgsFAQF/AAsHAgN/AX4ACwUBA38ACwUBA38ACwUBAn8ACwUBAn8ACwUBAn8ACwUBAn8ACwUBAX8ACwUBAX8ACwcCA38BfgALBQEDfwALBQEDfwALBQEBfwALBQEBfwALBQEBfwALBQEBfwALBQEBfwALQAEBf0EAIQADfyABIAJGBH8gAAUgASgCACAAQQR0aiIAQYCAgIB/cSIDQRh2IANyIABzIQAgAUEEaiEBDAELCwuOAQEDfwJAIAEgAhDmAiEEIwBBEGsiAyQAIARB9////wNNBEACQCAEEFEEQCAAIAQQHCAAIQUMAQsgA0EIaiAEED9BAWoQPiADKAIMGiAAIAMoAggiBTYCACAAIAMoAgwQGSAAIAQ2AgQLIAEgAiAFEN0CIANBADYCBCADQQRqEEIgA0EQaiQADAELEBIACwsLACAAIAIgAxCiAwtUAQJ/AkADQCADIARHBEBBfyEAIAEgAkYNAiABKAIAIgUgAygCACIGSA0CIAUgBkoEQEEBDwUgA0EEaiEDIAFBBGohAQwCCwALCyABIAJHIQALIAALQAEBf0EAIQADfyABIAJGBH8gAAUgASwAACAAQQR0aiIAQYCAgIB/cSIDQRh2IANyIABzIQAgAUEBaiEBDAELCwsKACAAIAIgAxBiC14BA38gASAEIANraiEFAkADQCADIARHBEBBfyEAIAEgAkYNAiABLAAAIgYgAywAACIHSA0CIAYgB0oEQEEBDwUgA0EBaiEDIAFBAWohAQwCCwALCyACIAVHIQALIAALpgEBBX8gACgCVCIDKAIAIQUgAygCBCIEIAAoAhQgACgCHCIHayIGIAQgBkkbIgYEQCAFIAcgBhAPIAMgAygCACAGaiIFNgIAIAMgAygCBCAGayIENgIECyAEIAIgAiAESxsiBARAIAUgASAEEA8gAyADKAIAIARqIgU2AgAgAyADKAIEIARrNgIECyAFQQA6AAAgACAAKAIsIgE2AhwgACABNgIUIAILsgMBA38jAEGgAWsiBCQAIAQgACAEQZ4BaiABGyIGNgKUASAEIAFBAWsiAEEAIAAgAU0bNgKYASAEQQBBkAEQMSAEQX82AkwgBEEvNgIkIARBfzYCUCAEIARBnwFqNgIsIAQgBEGUAWo2AlQgBkEAOgAAQQAhBiMAQdABayIFJAAgBSADNgLMASAFQaABaiIAQQBBKBAxIAUgBSgCzAE2AsgBAkBBACACIAVByAFqIAVB0ABqIAAQ4gFBAEgEQEF/IQAMAQsgBCgCTEEASCAEIAQoAgAiAUFfcTYCAAJ/AkACQCAEKAIwRQRAIARB0AA2AjAgBEEANgIcIARCADcDECAEKAIsIQYgBCAFNgIsDAELIAQoAhANAQtBfyAEEMABDQEaCyAEIAIgBUHIAWogBUHQAGogBUGgAWoQ4gELIQIgBgRAIARBAEEAIAQoAiQRBAAaIARBADYCMCAEIAY2AiwgBEEANgIcIAQoAhQhACAEQgA3AxAgAkF/IAAbIQILIAQgBCgCACIAIAFBIHFyNgIAQX8gAiAAQSBxGyEADQALIAVB0AFqJAAgBEGgAWokACAAC1MBAn8gASAAKAJUIgEgAUEAIAJBgAJqIgMQ5gEiBCABayADIAQbIgMgAiACIANLGyICEA8gACABIANqIgM2AlQgACADNgIIIAAgASACajYCBCACC78CAQR/IANB4P8AIAMbIgUoAgAhAwJAAn8CQCABRQRAIAMNAUEADwtBfiACRQ0BGgJAIAMEQCACIQQMAQsgAS0AACIDQRh0QRh1IgRBAE4EQCAABEAgACADNgIACyAEQQBHDwtBvP8AKAIAKAIARQRAQQEgAEUNAxogACAEQf+/A3E2AgBBAQ8LIANBwgFrIgNBMksNASADQQJ0KALwGiEDIAJBAWsiBEUNAyABQQFqIQELIAEtAAAiBkEDdiIHQRBrIANBGnUgB2pyQQdLDQADQCAEQQFrIQQgBkH/AXFBgAFrIANBBnRyIgNBAE4EQCAFQQA2AgAgAARAIAAgAzYCAAsgAiAEaw8LIARFDQMgAUEBaiIBLAAAIgZBQEgNAAsLIAVBADYCAEGw+gBBGTYCAEF/Cw8LIAUgAzYCAEF+C/8DAgJ+BX8jAEEgayIFJAAgAUL///////8/gyECAn4gAUIwiEL//wGDIgOnIgRBgfgAa0H9D00EQCACQgSGIABCPIiEIQIgBEGA+ABrrSEDAkAgAEL//////////w+DIgBCgYCAgICAgIAIWgRAIAJCAXwhAgwBCyAAQoCAgICAgICACFINACACQgGDIAJ8IQILQgAgAiACQv////////8HViIEGyEAIAStIAN8DAELIAAgAoRQIANC//8BUnJFBEAgAkIEhiAAQjyIhEKAgICAgICABIQhAEL/DwwBCyAEQf6HAUsEQEIAIQBC/w8MAQtBgPgAQYH4ACADUCIGGyIIIARrIgdB8ABKBEBCACEAQgAMAQsgAiACQoCAgICAgMAAhCAGGyECQQAhBiAEIAhHBEAgBUEQaiAAIAJBgAEgB2sQrgMgBSkDECAFKQMYhEIAUiEGCyAFIAAgAiAHEK0DIAUpAwhCBIYgBSkDACICQjyIhCEAAkAgBq0gAkL//////////w+DhCICQoGAgICAgICACFoEQCAAQgF8IQAMAQsgAkKAgICAgICAgAhSDQAgAEIBgyAAfCEACyAAQoCAgICAgIAIhSAAIABC/////////wdWIgQbIQAgBK0L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AAAQAAAA+P////j///8gCQAAEQAAABIAAADABwAA1AcAAAQAAAAAAAAAaAkAABMAAAAUAAAA/P////z///9oCQAAFQAAABYAAADwBwAABAgAAAwAAAAAAAAAAAoAABcAAAAYAAAABAAAAPj///8ACgAAGQAAABoAAAD0////9P///wAKAAAbAAAAHAAAACAIAAC8CQAA0AkAAOQJAAD4CQAASAgAADQIAAAAAAAAUAoAAB0AAAAeAAAAAwAAAAQAAAAfAAAAIAAAAAcAAAAIAAAACQAAACEAAAALAAAAIgAAAA0AAAAjAAAAADwAALgIAAD0CwAATlN0M19fMjliYXNpY19pb3NJY05TXzExY2hhcl90cmFpdHNJY0VFRUUAAADYOwAA7AgAAE5TdDNfXzIxNWJhc2ljX3N0cmVhbWJ1ZkljTlNfMTFjaGFyX3RyYWl0c0ljRUVFRQAAAABcPAAAOAkAAAAAAAABAAAArAgAAAP0//9OU3QzX18yMTNiYXNpY19pc3RyZWFtSWNOU18xMWNoYXJfdHJhaXRzSWNFRUVFAABcPAAAgAkAAAAAAAABAAAArAgAAAP0//9OU3QzX18yMTNiYXNpY19vc3RyZWFtSWNOU18xMWNoYXJfdHJhaXRzSWNFRUVFAAAMAAAAAAAAACAJAAAPAAAAEAAAAPT////0////IAkAABEAAAASAAAABAAAAAAAAABoCQAAEwAAABQAAAD8/////P///2gJAAAVAAAAFgAAAFw8AAAgCgAAAwAAAAIAAAAgCQAAAgAAAGgJAAACCAAATlN0M19fMjE0YmFzaWNfaW9zdHJlYW1JY05TXzExY2hhcl90cmFpdHNJY0VFRUUAADwAAFwKAADkCAAATlN0M19fMjE1YmFzaWNfc3RyaW5nYnVmSWNOU18xMWNoYXJfdHJhaXRzSWNFRU5TXzlhbGxvY2F0b3JJY0VFRUUAAABAAAAAAAAAAJALAAAkAAAAJQAAADgAAAD4////kAsAACYAAAAnAAAAwP///8D///+QCwAAKAAAACkAAACsCgAAEAsAAEwLAABgCwAAdAsAAIgLAAA4CwAAJAsAANQKAADACgAAQAAAAAAAAAAACgAAFwAAABgAAAA4AAAA+P///wAKAAAZAAAAGgAAAMD////A////AAoAABsAAAAcAAAAQAAAAAAAAAAgCQAADwAAABAAAADA////wP///yAJAAARAAAAEgAAADgAAAAAAAAAaAkAABMAAAAUAAAAyP///8j///9oCQAAFQAAABYAAAAAPAAAnAsAAAAKAABOU3QzX18yMThiYXNpY19zdHJpbmdzdHJlYW1JY05TXzExY2hhcl90cmFpdHNJY0VFTlNfOWFsbG9jYXRvckljRUVFRQAAAAAAAAAA9AsAACoAAAArAAAA2DsAAPwLAABOU3QzX18yOGlvc19iYXNlRQAAANF0ngBXnb0qgHBSD///PicKAAAAZAAAAOgDAAAQJwAAoIYBAEBCDwCAlpgAAOH1BRgAAAA1AAAAcQAAAGv////O+///kr///wAAAAAAAAAA/////////////////////////////////////////////////////////////////wABAgMEBQYHCAn/////////CgsMDQ4PEBESExQVFhcYGRobHB0eHyAhIiP///////8KCwwNDg8QERITFBUWFxgZGhscHR4fICEiI/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8AAQIEBwMGBQAAAAAAAAACAADAAwAAwAQAAMAFAADABgAAwAcAAMAIAADACQAAwAoAAMALAADADAAAwA0AAMAOAADADwAAwBAAAMARAADAEgAAwBMAAMAUAADAFQAAwBYAAMAXAADAGAAAwBkAAMAaAADAGwAAwBwAAMAdAADAHgAAwB8AAMAAAACzAQAAwwIAAMMDAADDBAAAwwUAAMMGAADDBwAAwwgAAMMJAADDCgAAwwsAAMMMAADDDQAA0w4AAMMPAADDAAAMuwEADMMCAAzDAwAMwwQADNsAAAAAGQALABkZGQAAAAAFAAAAAAAACQAAAAALAAAAAAAAAAAZAAoKGRkZAwoHAAEACQsYAAAJBgsAAAsABhkAAAAZGRkAQZEdCyEOAAAAAAAAAAAZAAsNGRkZAA0AAAIACQ4AAAAJAA4AAA4AQcsdCwEMAEHXHQsVEwAAAAATAAAAAAkMAAAAAAAMAAAM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",wsKne:function(u,n){return u-n},pnRip:function(u,n){return u!==n},VwXHX:A(2716),BwTSh:A(2837),nNfMk:"2|1|4|7|6|0|3|8|5",fEZEW:A(8120),uXJgy:function(u,n){return u==n},LjGUr:"postRun",NrmFP:function(u,n){return u(n)},lHwAv:function(u,n){return u>>>n},yMywV:A(1289),wadZa:function(u,n){return u===n},BaLtn:function(u,n){return u!==n},XsgQt:"XHaok",frZIG:function(u,n){return u===n},vckSH:function(u,n){return u(n)},YjGJv:function(u,n){return u===n},LfVuO:A(7788),rQzxB:"6|5|2|4|0|3|7|1",EDmIz:A(1942),XYsky:". Build with -sASSERTIONS for more info.",ZlYTG:A(5396),hAJqm:function(u,n){return u===n},hVtKs:A(10350),RFELD:"end",aKsbD:function(u,n){return u===n},QMXIn:A(7378),waXIE:function(u,n){return u==n},sEALK:"RGJkz",lejgr:A(8836),pFCGD:function(u,n){return u!==n},nWlZK:"cqmjt",mTfCd:A(5014),JeQia:A(3884),igxsn:function(u,n){return u(n)},MdqXz:function(u,n){return u+n},mXjJC:function(u){return u()},whfXc:A(7593),jozUZ:"clearTimeout has not been defined",BXLFl:function(u,n){return u===n},vueTy:A(8873),edKfr:"ONWsv",WQHUY:function(u){return u()},dmiRW:"TYQuc",yNvyP:function(u,n){return u(n)},ISKnQ:A(857),YXyjh:function(u,n){return u(n)},aloKU:function(u){return u()},lOZPl:function(u,n,r){return u(n,r)},icMvV:A(7762),ovEIS:function(u,n){return u+n},qRBwe:A(6184),gENpm:function(u){return u()},XViMy:A(8778),xqobD:function(u,n,r,f,A,t){return u(n,r,f,A,t)},nuuvu:A(7470),NoMIr:A(4234),zZaZc:A(4104),fsVAI:A(7881),YWQjR:A(2524),vULLy:A(4684),hYfQD:function(u,n){return u!==n},GKQUL:"tqYUG",LdFSo:function(u,n,r,f){return u(n,r,f)},Juudu:A(4477),oJDPG:A(9519),reUWO:A(8801),GEbjh:function(u,n){return u!==n},ViDvN:A(7352),tDCAy:A(4389),GJjFx:A(2292),XyjZl:A(8463),vrnEA:function(u,n){return u!==n},FWVBP:A(6976),XVkJy:function(u,n){return u(n)},tFYLX:A(3756),KGCHT:A(3534),XPzgq:function(u,n){return u>n},axQwA:function(u,n){return u-n},zgNRa:function(u,n){return u+n},fjiUy:function(u,n){return u<=n},hIfeJ:function(u,n){return u>=n},TylHt:function(u,n){return u+n},UmmSG:function(u,n){return u>>n},agxhG:function(u,n){return u|n},QYZOM:function(u,n){return u>>n},xnrIT:function(u,n){return u|n},Nzxvh:function(u,n){return u&n},fRmsu:function(u,n){return u>=n},ORaJI:function(u,n){return u|n},BaSXI:function(u,n){return u>>n},BFKSo:function(u,n){return u&n},sPidM:function(u,n){return u&n},vVswP:function(u,n){return u&n},cXEYC:function(u,n,r,f,A){return u(n,r,f,A)},AeRde:function(u,n){return u>>n},HJrrJ:function(u,n){return u-n},kaXgR:function(u,n){return u+n},BXved:function(u,n){return u*n},UjogL:function(u,n){return u(n)},kJNXB:function(u,n){return u!==n},pNQoq:A(1918),nwRPq:function(u,n){return u*n},eQFBB:function(u,n){return u>n},IqZuq:function(u,n){return u>>>n},pBCcp:function(u,n){return u/n},Colhq:function(u,n){return u/n},juROx:function(u,n){return u>>>n},jkTdm:function(u,n){return u>>n},vAygt:function(u,n){return u===n},pWXsL:"gCHot",hwQtA:A(5445),Rceqh:A(4135),HrQer:function(u,n){return u||n},tITds:A(4691),TieRO:"0|3|2|4|1",etPdn:A(6929),XUMCJ:"webgl",ooeuy:A(9815),IJTml:A(2891),IOBjg:function(u){return u()},mYssi:function(u,n){return u===n},HjnlL:A(2040),xbaRa:function(u,n){return u!==n},yfGMp:"ZcHNu",oIjeO:A(3650),LAhBM:A(2012),uFEho:A(10068),rfklh:A(10515),tGJRH:function(u,n){return u+n},fgaNS:function(u,n){return u+n},lUOCP:function(u,n){return u>n},juNTH:function(u,n){return u&n},JMfUH:function(u,n){return u*n},GKSKi:function(u,n){return u>n},qukLK:function(u,n){return u!==n},HHpjN:"NcANo",LYxct:"IbVYZ",aEIEH:function(u,n,r,f,A){return u(n,r,f,A)},rMqYH:A(2329),FgnQS:A(6514),QEpUj:function(u,n){return u+n},HqwuI:function(u,n){return u!==n},oDNSL:"OaSqf",RDuQL:A(2189),zDoXY:function(u,n){return u-n},JGWlI:function(u,n){return u%n},tPsgR:function(u,n){return u*n},GSljI:function(u,n){return u<n},Yersc:function(u,n){return u!==n},Wcdgb:A(7401),Nxlum:A(3824),GjWuQ:function(u){return u()},DGRaq:function(u,n){return u>n},cVPcH:"jGTfY",prBwa:A(7569),FEnqg:function(u,n,r){return u(n,r)},WqIxU:A(10472),zdDyR:function(u,n){return u!=n},jGTdv:function(u,n){return u!==n},aGGhL:A(2856),KxYFR:A(6084),lOPZi:A(6915),izLup:A(3342),oFuNY:"arguments",ZGBmq:A(8558),sQGba:"stringToNewUTF8",PvHSn:function(u){return u()}};function e(u,n){var r=A,f={kIaFp:function(u,n){return t[_0x7f58(7753)](u,n)},ZLFMk:function(u,n){return t[_0x7f58(7766)](u,n)},wxNyM:function(u,n){return u!==n},msLjk:t.jAodl,obBTE:t[r(1257)],CGdgp:r(8961),WpHVZ:t[r(6539)],gdHZE:r(685),HkRXc:function(u,n){return t.IgogV(u,n)},FNrCS:t.nsgrd,wWKkk:t[r(3402)],SHtQR:function(u,n){return u==n},enECQ:r(2525)},e=t[r(6025)](t.YPlXt,typeof Symbol)&&u[Symbol[r(9869)]]||u[t[r(6924)]];if(!e){if(!t[r(6488)](t[r(3754)],t.bILFk)){if(Array[r(8259)](u)||(e=t[r(7753)](i,u))||t[r(2593)](n,u)&&t[r(3958)](t[r(7872)],typeof u[r(7855)])){if("zRJzJ"!==t[r(3864)])return new _0x404b48(this,_0x34a5d2)[r(867)];e&&(u=e);var c=0,o=function(){};return{s:o,n:function(){var n=r;if(t[n(7853)](t[n(3150)],t[n(2178)]))return t.sYpWm(c,u.length)?{done:!0}:{done:!1,value:u[c++]};if(!f[n(3397)](_0x46ff5a,_0x2bd4cc))throw new _0x3ee96(n(10354))},e:function(u){throw u},f:o}}throw new TypeError(t[r(300)])}try{f[r(6064)](_0x5b5a0c,_0x4bf5da.next(_0x1dbb91))}catch(u){f[r(6064)](_0x31e07a,u)}}var q,v=!0,b=!1;return{s:function(){var n=r;if(!f.wxNyM(f.msLjk,f[n(863)]))throw _0x447d8e;e=e.call(u)},n:function(){var u=r;if(t[u(6488)](t.JzCvv,t[u(7306)])){var n=e[u(6460)]();return v=n.done,n}switch(_0x47e01c.prev=_0x40f3bb[u(6460)]){case 0:return _0x57aee2.abrupt("return",(0,_0x4142fc.match)({includes:[_0x540974[u(3512)]],excludes:[]}));case 1:case f[u(767)]:return _0x4339d9[u(9572)]()}},e:function(u){var n=r;f[n(8851)]===f.gdHZE?(0,_0x28db0e.setData)(_0xb7dd4a[n(6030)],_0x38b18c[n(2888)]):(b=!0,q=u)},f:function(){var u=r,n={fFgVi:function(u,n){return f.HkRXc(u,n)},hwkYp:f[u(3710)],byMfl:f[u(9913)],NNffN:function(u,n){return u>n}};if("ZJXDU"===u(8660))try{v||f[u(7191)](null,e[f[u(8690)]])||e[f.enECQ]()}finally{if(b)throw q}else for(n[u(8632)](typeof _0x942642[n[u(4534)]],n[u(2585)])&&(_0x37908a[n[u(4534)]]=[_0x24fa98[n[u(4534)]]]);n[u(7842)](_0xe31204[n[u(4534)]][u(7855)],0);)_0x4a050d[n[u(4534)]][u(9728)]()()}}}function i(u,n){var r=A;if(u){if(t[r(3165)](t[r(2050)],r(4218))){if(t[r(3958)](t[r(1453)],typeof u))return t[r(8196)](c,u,n);var f={}[r(9965)][r(2210)](u).slice(8,-1);return t.FIyvi(t.rgyiP,f)&&u[r(9413)]&&(f=u[r(9413)][r(4477)]),t[r(1557)](t[r(1391)],f)||t.fpQvZ(t[r(752)],f)?Array[r(9487)](u):t[r(3165)](t[r(9357)],f)||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/[r(2785)](f)?t.HOszh(c,u,n):void 0}_0x4a807e[t[r(5835)](t[r(6888)](_0x53bec4,_0x3c36d7),2)]=_0x48d1e5[_0x3b51b4>>>2]}}function c(u,n){var r=A;if(!t[r(7853)](t.DsirM,t[r(5520)])){(t[r(5825)](null,n)||t[r(6781)](n,u[r(7855)]))&&(n=u[r(7855)]);for(var f=0,e=t.nCFsa(Array,n);t[r(926)](f,n);f++)e[f]=u[f];return e}_0x310bd1[r(7606)](_0x3b9228)}function o(u){var n=A,r={PboXI:function(u,n){return u==n},DSxkA:t[n(3800)],XNogB:function(u,n){return t.naebZ(u,n)},RNKhi:t[n(3347)],UYRna:function(u,r){return t[n(3958)](u,r)},IIWpk:t[n(3402)],GQENT:function(u,n){return u!==n},ZVXgH:t[n(3396)]};return o=t[n(3402)]==typeof Symbol&&t[n(260)](t[n(3396)],typeof Symbol.iterator)?function(u){return typeof u}:function(u){var f=n;if(r[f(8787)](r[f(709)],f(2216)))return u&&r.UYRna(r[f(3877)],typeof Symbol)&&r.XNogB(u[f(9413)],Symbol)&&r[f(10203)](u,Symbol[f(10129)])?r[f(9427)]:typeof u;var A=this[f(7063)][f(5592)];if(r[f(7620)](this[f(5995)],this[f(3096)])){A[f(4128)](this[f(4269)],this[f(2315)]);var t=this._process(!!r[f(2926)])}else{t=this[f(3595)](!!r[f(2926)]);A[f(4196)](t)}return t},t.WpbHv(o,u)}function q(u,n){for(var r=A,f=0;fn},MHEFF:t[r(6946)],GNFsc:function(u,n){return u+n},pbSsR:function(u,n){return t[r(4469)](u,n)},BlUZr:function(u,n){return t[r(7902)](u,n)},aKwBZ:function(u,n,r){return u(n,r)},eiRea:t[r(7890)],BDFIE:function(u,n){return t[r(926)](u,n)},wSGAO:t[r(6756)],rCOXb:function(u,n){return un},EnrKF:function(u,n){return f.WfGYK(u,n)},bjCov:function(u,n){return f[_0x7f58(7972)](u,n)},xRagM:function(u,n){return f[_0x7f58(958)](u,n)},GmBBB:function(u,n){return u1)throw b.ZxaZN(TypeError,b[a(825)]);for(x&&b[a(268)](1,c)&&b.QELQE(g,c,o),e=c,i=o;(n=b[a(3515)](e,2)?u:i)||!x;)if(b.mnugv(b.WEqDJ,"bcAkw")){t||(e?b[a(7030)](e,3)?(e>1&&(w.n=-1),g(e,i)):w.n=i:w.v=i);try{if(b.NqBDo(a(9603),a(9727))){if(s=2,t)if(b.uFMMj==b.uFMMj){if(e||(A="next"),n=t[A])if(b[a(1030)]===a(6299)){if(!(n=n[a(2210)](t,i)))throw b.DVlRy(TypeError,b[a(1371)]);if(!n[a(8379)])return n;i=n[a(10292)],b[a(2854)](e,2)&&(e=0)}else for(var B=b[a(9605)].split("|"),D=0;;){switch(B[D++]){case"0":z.Decryptor=E;continue;case"1":var L={MsNOJ:function(u,n){return b[a(9004)](u,n)},pnfuX:function(u,n){return b[a(3998)](u,n)},syaDk:function(u,n){return u>>1,n[u(7747)](e,31)),n[u(2186)](t>>>8,n.UayWd(e,24))),n[u(6555)](t,7)),c=n[u(5777)](n[u(3837)](n[u(2186)](n.VFpaG(e,1),n[u(4826)](t,31)),n[u(1861)](e>>>8,n[u(4826)](t,24))),n[u(9552)](e>>>7,n.FFjRW(t,25))),o=_0x52c22e[_0x436e3e-2],q=o[u(2659)],v=o[u(3227)],b=n[u(9308)](n.BvDCO(n[u(7714)](q,19)|n.FFjRW(v,13),n.XbrnD(n[u(734)](q,3),n[u(6555)](v,29))),q>>>6),s=n[u(9308)](n.kUHkj(v>>>19|q<<13,n[u(3798)](n.REonz(v,3),n[u(7714)](q,29))),n[u(6106)](n[u(1297)](v,6),n[u(5221)](q,26))),a=_0x22c95e[n[u(896)](_0xb0b0fd,7)],x=a[u(2659)],w=a.low,g=_0xb851d5[n.IsPip(_0x1c5912,16)],C=g.high,B=g.low,D=n.NrUoi(c,w),L=n.CqMPR(n.CqMPR(i,x),n.cuAMe(n.VFpaG(D,0),n[u(6555)](c,0))?1:0);D=n[u(10291)](D,s),L=n[u(748)](n.NrUoi(L,b),n[u(5371)](D>>>0,n[u(2733)](s,0))?1:0),D=n[u(5350)](D,B),L=n[u(10467)](n.rEJfi(L,C),n.VcAKt(n.tkFrr(D,0),B>>>0)?1:0);_0x1c3644[u(2659)]=L,_0xa64d39.low=D}),n),g=s[r(10129)]=v[r(10129)]=Object.create(a);function C(u){var n=r;return Object.setPrototypeOf?Object[n(10061)](u,s):(u[n(8487)]=s,f.wvNuq(w,u,c,n(1342))),u.prototype=Object.create(g),u}return b.prototype=s,t[r(3386)](w,g,t[r(7763)],s),t[r(4677)](w,s,r(9413),b),b.displayName=r(1342),w(s,c,t[r(7459)]),t.UcjZd(w,g),w(g,c,t[r(8808)]),t[r(3386)](w,g,i,function(){return this}),t[r(3386)](w,g,t[r(1688)],function(){return f.AXeRB}),(x=function(){return{w:o,m:C}})()}function w(u,n,r,f){var e=A,i={jiPNJ:function(u,n){return u|n},uaIyw:function(u,n){return t[_0x7f58(4583)](u,n)},xdGeK:function(u,n){return t[_0x7f58(5957)](u,n)},TSjiH:function(u,n){return t[_0x7f58(3776)](u,n)}};if(t[e(5664)]!==e(456))throw _0x511f73;var c=Object[e(4594)];try{if(t[e(1094)]==t[e(1094)])t[e(6479)](c,{},"",{});else try{_0x311cfa(_0x369d28.next(_0x56d1ce))}catch(u){t[e(7753)](_0x49d25b,u)}}catch(u){c=0}w=function(u,n,r,f){var A=e,o={YAsmA:t.yUUFr,dyqRq:function(u,n){return t[_0x7f58(7853)](u,n)},dTCYg:A(3859),GWwLI:t.yyjfj};if(t[A(8772)](t[A(662)],t[A(662)]))_0x183d46[_0x150e4e]=16711935&i[A(6027)](_0x4088b2[_0x36536c]<<8,_0x306309[_0x168ef5]>>>24)|i[A(5276)](i[A(4105)](_0x5551b3[_0x2d07f5]<<24,i[A(612)](_0x51dccd[_0x487fb0],8)),4278255360);else if(n)c?c(u,n,{value:r,enumerable:!f,configurable:!f,writable:!f}):u[n]=r;else{var q=function(n,r){var f=A,t={PMBiM:o[f(4593)],FuZbr:function(u,n){return u===n}};if(o[f(3584)](o[f(3846)],o[f(6303)]))w(u,n,function(u){var A=f,e={UmdyX:t[A(9037)]};if(t[A(5207)]("xwSqm",A(7055)))throw new _0x2a52a3(e[A(9988)]);return this[A(5016)](n,r,u)});else{var e=this[f(8493)];e[f(4791)](),e[f(4345)](this._iKey)}};q(t[A(6787)],0),t.TJmLw(q,t.VtFjl,1),t[A(9541)](q,t[A(5630)],2)}},t[e(4890)](w,u,n,r,f)}function g(u,n,r,f,e,i,c){var o=A;try{var q=u[i](c),v=q.value}catch(u){return void t[o(5756)](r,u)}q[o(8379)]?n(v):Promise.resolve(v)[o(591)](f,e)}function C(u){return function(){var n={eVpXl:function(u,n,r,f,A,e,i,c){return t[_0x7f58(6900)](u,n,r,f,A,e,i,c)},bpinQ:function(u,n,r,f,A,e,i,c){return t[_0x7f58(6900)](u,n,r,f,A,e,i,c)},YFxmr:"throw",BtxJh:function(u,n){return t[_0x7f58(4859)](u,n)}},r=this,f=arguments;return new Promise(function(A,t){var e=_0x7f58,i=u.apply(r,f);function c(u){var r=_0x7f58;n[r(678)](g,i,A,t,c,o,r(6460),u)}function o(u){var r=_0x7f58;n[r(6934)](g,i,A,t,c,o,n[r(3947)],u)}n[e(6166)](c,void 0)})}}var B,D,L,z,E,d=window[A(10525)]=t.zdDyR(typeof d,t[A(1886)])?d:{},I=A(4691),j=typeof document!=t[A(1886)]?t[A(10237)](f=document[A(2471)],null)||t[A(4341)](f,void 0)?void 0:f[A(3544)]:void 0,K="";if(t.HrQer(!0,!1)){try{K=new URL(".",j).href}catch(u){}t.jGTdv(t[A(5045)],A(2823))?(z={nHiIh:function(u,n){return t[_0x7f58(7753)](u,n)},dsrae:function(u,n){return t[_0x7f58(7824)](u,n)},Ehlkz:function(u,n,r,f){return t[_0x7f58(4677)](u,n,r,f)},vZMxZ:t[(L=A)(4543)],ruugw:function(u,n,r){return u(n,r)},eFyVn:function(u,n){return u===n},IBXhR:function(u){return t[L(9185)](u)}},E=t[L(7902)](C,t.MhFSI(x).m(function u(n){var r,f=L,A={WOCuy:function(u,n){return z[_0x7f58(9267)](u,n)},bvgcC:function(u,n,r,f){return z[_0x7f58(7304)](u,n,r,f)},XlvKS:z[f(3916)],LSkHM:function(u,n,r){return z[f(3382)](u,n,r)},lSvVZ:f(2544)};if(z[f(5850)](f(8811),f(8811)))return z[f(9408)](x).w(function(u){var t=f;if(t(10202)===A[t(6252)])for(;;)switch(u.n){case 0:return u.n=1,A[t(4471)](fetch,n,{credentials:t(9511)});case 1:if(!(r=u.v).ok){u.n=2;break}return u.a(2,r[t(1945)]());case 2:throw new Error(r.status+A[t(3573)]+r[t(4229)]);case 3:return u.a(2)}else A[t(7932)](_0x58fd01,"default")&&_0x2500fc[t(10129)].hasOwnProperty[t(2210)](_0x5344ad,_0x47855d)&&A[t(4176)](_0x4371bf,_0x191eb8,_0x3c4753,_0x2c5806)},u);z[f(3941)](_0x1cec97,_0x1ef1ac)})),B=function(u){return E.apply(this,arguments)}):(_0x22e211=this.words=_0x3abfd3||[],t[A(7847)](_0x3b12ce,_0x5c5f51)?this.sigBytes=_0x1c1154:this[A(7822)]=t[A(2691)](_0x2d25a8[A(7855)],4))}console[A(2781)].bind(console);var y,h=console.error[A(1779)](console);t[A(9185)](function(){var u=A,n=t[u(4181)],r=atob(n),f=new Uint8Array(r[u(7855)]);for(let n=0;t[u(926)](n,r[u(7855)]);++n)f[n]=r.charCodeAt(n);y=f});var _,Q,N,M,l,m=!1;function H(){var u=A;if(!t[u(7715)](t[u(1348)],t[u(9199)]))return t.wsKne(_0x4eaa93.exp(_0x133730),1);for(var n=t[u(8867)][u(7897)]("|"),r=0;;){switch(n[r++]){case"0":M=new Int32Array(f);continue;case"1":Q=new Int8Array(f);continue;case"2":var f=_[u(10427)];continue;case"3":l=new Uint32Array(f);continue;case"4":new Int16Array(f);continue;case"5":new Float64Array(f);continue;case"6":new Uint16Array(f);continue;case"7":N=new Uint8Array(f);continue;case"8":new Float32Array(f);continue}break}}function P(){var u=A;if(d.preRun)for(t.eBIhI(typeof d[t[u(4647)]],u(4261))&&(d[t.fEZEW]=[d[t.fEZEW]]);d[t.fEZEW][u(7855)];)t[u(468)](cu,d[u(8120)][u(9728)]());t.WpbHv(Au,iu)}function G(){!0,Mu.h()}function Y(){var u=A;if(d[u(2827)])for(t[u(10420)](typeof d[t[u(2387)]],u(4261))&&(d[t[u(2387)]]=[d[t[u(2387)]]]);d.postRun[u(7855)];)t.NrmFP(eu,d[t[u(2387)]][u(9728)]());Au(tu)}var J,S=0,W=null;function X(u){var n=A,r={hPajz:function(u,n){return u|n},jljuT:function(u,n){return t[_0x7f58(4583)](u,n)},MNLje:function(u,n){return t[_0x7f58(7799)](u,n)},NrloI:function(u,n){return t[_0x7f58(4172)](u,n)}};if(t[n(7715)](t.yMywV,n(1289))){var f=_0x513a28[_0x69ae3b];_0x21ab6d[_0x4a9dc5]=r[n(5242)](r[n(8783)](r[n(9804)](f,8)|f>>>24,16711935),r[n(8783)](f<<24|r.NrloI(f,8),4278255360))}else{var e;S++,null===(e=d[n(5280)])||t[n(10151)](e,void 0)||e.call(d,S)}}function O(u){var n,r=A,f={kiVXT:function(u,n){return u!==n}};if(t[r(6531)](t[r(2696)],r(4609))){if(S--,t[r(4341)](n=d[r(5280)],null)||t[r(9022)](n,void 0)||n[r(2210)](d,S),t[r(5825)](S,0)&&W){var e=W;W=null,e()}}else for(var i,c=_0x1a4e89[r(2431)](_0x100d56)[_0x195db6[r(9869)]]();!(_0x1c7c35=(i=c[r(6460)]())[r(8379)]);_0x5dd46b=!0){var o=i[r(10292)],q=_0x349918[o];f[r(9736)](q,_0x477de3)&&(_0x5cba91.style[o]=q)}}function R(u){var n=A;if(!t.YjGJv(t.LfVuO,t.LfVuO)){var r={VcdXX:function(u,r){return t[n(7866)](u,r)}};return t[n(7766)](_0x26416c,_0x3366aa)?_0x1d4f11:new _0x16309d(function(u){r[n(5340)](u,_0x20e05f)})}for(var f=t[n(3234)].split("|"),e=0;;){switch(f[e++]){case"0":m=!0;continue;case"1":throw c;case"2":u=t[n(6888)](t[n(6888)](t[n(7164)],u),")");continue;case"3":u+=t[n(804)];continue;case"4":t[n(4859)](h,u);continue;case"5":t[n(5161)](i=d[t[n(10164)]],null)||t[n(10213)](i,void 0)||i[n(2210)](d,u);continue;case"6":var i;continue;case"7":var c=new(WebAssembly[n(4907)])(u);continue}break}}function k(){var u,n;return u=t[A(8683)],d[t[(n=A)(6283)]]?d[t[n(6283)]](u,K):t.jAEEl(K,u)}function p(u){var n=A;if(t.aKsbD(t[n(10479)],t[n(10479)])){if(t[n(4398)](u,J)&&y)return new Uint8Array(y);if(D){if("tYEZX"!==t.sEALK)return D(u);var r={jowAx:t.CwsSw,cZqvA:t[n(312)]};return t[n(4890)](_0x4cf868,this,void 0,void 0,_0x54895b[n(655)](function u(){return _0x1a6fdf.wrap(function(u){for(var n=_0x7f58;;)switch(u[n(2519)]=u.next){case 0:return u[n(4922)](r[n(8269)],this[n(8421)]());case 1:case r.cZqvA:return u[n(9572)]()}},u,this)}))}throw t[n(893)]}_0x527cbe[""+_0x5eb0b5]=""+_0x17517b}function T(u){var n=A;if(t[n(3890)](t[n(2455)],t[n(8892)]))return F[n(6346)](this,arguments);var r=_0x31c822.clone.call(this);return r[n(8810)]=this._hash[n(6429)](),r}function F(){var u=A,n={yJJiV:function(u,n){return u===n},dZzpc:t[u(4635)],cJsRL:function(n,r){return t[u(4147)](n,r)},yBGoZ:function(n,r){return t[u(1632)](n,r)},wTyJa:function(u){return t.mXjJC(u)},vMwEo:t[u(7775)],vKiho:function(u){return u()}};return(F=t[u(9031)](C,t[u(5123)](x).m(function r(f){var A,t=u;if(n.vMwEo==n.vMwEo)return n[t(9786)](x).w(function(u){for(var r=t;;)switch(u.n){case 0:if(y){if(!n[r(1150)](n[r(2554)],r(9523))){u.n=4;break}try{return _0x3c06df.localStorage[r(8350)](_0xde1817)}catch(u){return _0x2ef06a}}return u.p=1,u.n=2,n[r(8819)](B,f);case 2:return A=u.v,u.a(2,new Uint8Array(A));case 3:u.p=3,u.v;case 4:return u.a(2,p(f))}},r,null,[[1,3]]);_0x4565c7[_0x4be727]=_0x124645,_0x494572[n[t(7357)](_0x1c398e,1)]=_0x4dbf54,_0x4d201a+=2,2===_0x4e60b6&&(_0x4cb503?n[t(8819)](_0x81b9dd,_0x5a8a18):n.wTyJa(_0x4317ac))})))[u(6346)](this,arguments)}function U(u,n){return V.apply(this,arguments)}function V(){var u=A,n={DprqN:t.jozUZ,DVnXB:u(8961),chhxa:function(n,r){return t[u(8821)](n,r)},dRbEh:function(u,n){return u(n)},eZNbp:t.vueTy,UKAiP:t[u(2559)],UBUQa:function(n){return t[u(5123)](n)}};return(V=t[u(4859)](C,t[u(7643)](x).m(function r(f,A){var t,e,i,c=u,o={ZKcbe:c(2525),RZfqy:n[c(820)],gSHSZ:function(u,r){return n[c(7038)](u,r)},HyOdN:function(u,r){return n[c(5857)](u,r)},woJtx:n.eZNbp};if(n[c(7038)](c(9874),n[c(5920)]))return n[c(1141)](x).w(function(u){var n=c;if(o[n(2142)](n(8869),n(8869)))for(;;)switch(u.n){case 0:return u.p=0,u.n=1,T(f);case 1:return t=u.v,u.n=2,WebAssembly[n(8490)](t,A);case 2:return e=u.v,u.a(2,e);case 3:u.p=3,i=u.v,o[n(9564)](h,o[n(2424)][n(4189)](i)),o[n(9564)](R,i);case 4:return u.a(2)}else for(;;)switch(_0x3c8a7f[n(2519)]=_0x1c79fe[n(6460)]){case 0:return _0x24da33.abrupt(o[n(10040)],this[n(1687)](_0x7e81a,_0x443283[n(5614)](_0x17e9d1)));case 1:case o.RZfqy:return _0x1c06e6[n(9572)]()}},r,null,[[0,3]]);throw new _0x2ff77f(n[c(1287)])})))[u(6346)](this,arguments)}function Z(u,n,r){return $[A(6346)](this,arguments)}function $(){var u=A,n={mCkHF:function(u,n,r,f){return u(n,r,f)},lmelx:t[u(6207)],yRasB:function(u,n,r){return t.HOszh(u,n,r)},eqmvl:u(4303),yEXJO:function(n,r){return t[u(10356)](n,r)},KxVHL:u(1477)};if(t[u(7967)]===u(857))return($=t[u(6229)](C,t[u(6137)](x).m(function r(f,A,t){var e,i,c,o=u,q={fIaob:function(u,r,f,A){return n[_0x7f58(2654)](u,r,f,A)},jlqTU:function(u,n){return u!==n},yuymb:n[o(5997)],cwDJj:function(u,r,f){return n.yRasB(u,r,f)},OvtWB:n[o(3987)],fTTZE:function(u,r){return n[o(9399)](u,r)},OjtHa:n.KxVHL};return x().w(function(u){for(var n=o;;)switch(u.n){case 0:if(f||!WebAssembly[n(3972)]){if(!q[n(2919)](q[n(3503)],q[n(3503)])){u.n=4;break}_0xa09546(_0x3d82f8,_0x4daa0e),q.fIaob(_0x4cd0b9,_0x5deaf7,_0x214d82,_0x2e921e)}return u.p=1,e=q[n(7058)](fetch,A,{credentials:n(9511)}),u.n=2,WebAssembly.instantiateStreaming(e,t);case 2:return i=u.v,u.a(2,i);case 3:u.p=3,c=u.v,h(q.OvtWB[n(4189)](c)),q.fTTZE(h,q.OjtHa);case 4:return u.a(2,U(A,t))}},r,null,[[1,3]])})))[u(6346)](this,arguments);_0x10ccf6=!0,_0x54431c=_0x1430e4}function uu(){var u=A,n={AQsbA:function(u,n,r){return t[_0x7f58(9748)](u,n,r)}};return t[u(6488)](t[u(8884)],"FFPKy")?{a:lu}:(_0xb7c88f&&n[u(1718)](_0x2f9bc1,_0x234d23[u(10129)],_0x43eebe),_0x18f6c6&&n[u(1718)](_0x5b7029,_0x28d5fc,_0x10e998),_0x4c97bf)}function nu(){var u=A,n={qVnae:function(u,n){return u&n},DyOMA:function(u,n){return t[_0x7f58(3433)](u,n)},WHCmi:function(u,n){return t[_0x7f58(5961)](u,n)},mNYxA:function(u,n){return u>>>n},dNRCl:t[u(1971)],ljfkC:function(n){return t[u(10262)](n)},qcqsm:function(u,n){return u(n)},KtSkA:t[u(8752)],KYzfL:function(u,n,r){return u(n,r)},iuCTX:function(u,n){return u===n},xpORq:function(n,r,f,A,e,i){return t[u(1578)](n,r,f,A,e,i)},JUgrm:t.nuuvu,TyNLc:function(n,r){return t[u(7866)](n,r)},CuJfw:"./cipher-core",lRtLd:u(4261),XYZQM:t.NoMIr,XSItS:function(n,r){return t[u(7715)](n,r)},mEjfg:t[u(6549)],jgGjq:t[u(3601)],uYpje:t.YWQjR,TsNeP:"YiDNs",ahiwq:function(u,n,r,f){return t.fHdYa(u,n,r,f)},Icxyh:t.vULLy,yrWdI:function(n,r){return t[u(3844)](n,r)},PHMLx:t[u(2441)],TdnZK:function(u){return u()}};return(nu=t[u(7753)](C,t[u(1337)](x).m(function r(){var f,e,i,c,o,q=u,v={VaRYx:function(u,r){return n[_0x7f58(4450)](u,r)},UHmve:n.Icxyh,nWOhp:function(u,r){return n.yrWdI(u,r)},nhcLh:q(4777),ghhHG:n[q(2082)]};return n.TdnZK(x).w(function(u){var r=q,b={lTtAy:function(u,n){return u+n},leGkl:function(u,n){return u|n},KJBvS:function(u,r){return n[_0x7f58(2602)](u,r)},wrIhU:function(u,r){return n[_0x7f58(6893)](u,r)},gBtYs:function(u,r){return n.WHCmi(u,r)},hkpyv:function(u,r){return n[_0x7f58(5328)](u,r)},ewUWw:n.dNRCl,oabsQ:function(u){return n[_0x7f58(1140)](u)},rmoGi:function(u,r){return n[_0x7f58(3862)](u,r)},ZdcJy:n.KtSkA,BpLAQ:function(u,r,f){return n[_0x7f58(2653)](u,r,f)},Ryowg:function(u,r){return n[_0x7f58(9406)](u,r)},CWllQ:"object",GADAj:function(u,r,f,A,t,e){return n[_0x7f58(1527)](u,r,f,A,t,e)},qqCgH:"./core",PWaqt:function(u,r){return n[_0x7f58(3862)](u,r)},wVRlS:n[r(1205)],uMEff:r(2038),VftSy:function(u,f){return n[r(4450)](u,f)},niZGi:n[r(3200)],kBZVD:n[r(6183)],yZLFz:function(u,r,f){return n.KYzfL(u,r,f)},tYOIa:n[r(5101)]};if(n.XSItS(n.mEjfg,n[r(3599)])){var s=b.lTtAy(b[r(2421)](_0x5c9fb9+b[r(9294)](_0xd7f3c6&_0x3f672f,b[r(7218)](_0x49fb6c,~_0x2b9a33)),_0x55fc02),_0x8f09bf);return b[r(3591)](b[r(10425)](s,_0x3c133d)|b[r(4070)](s,32-_0x1bc91d),_0x4a2ece)}for(;;)switch(u.n){case 0:if(e=function(u){return v[r(2928)](f,u[v.UHmve])},f=function(u,n){for(var f,e,i=r,c=b[i(2031)][i(7897)]("|"),o=0;;){switch(c[o++]){case"0":return Mu;case"1":f=Mu,e=void 0,e=A,t.XbiYL(t[e(486)],t.OTWJP)?t.OJQQG(_0x10b3a6,_0x43109d):(d[t[e(10119)]]=f.i,Cu=f.j,d[t.BiqkT]=f.k,Bu=f.l,Du=f.m,Lu=f.n,f[t[e(2334)]],f[t[e(6765)]],f[t[e(9007)]],f.dynCall_iiiiiijj);continue;case"2":b[i(2509)](H);continue;case"3":b[i(6912)](O,b[i(3259)]);continue;case"4":_=Mu.g;continue;case"5":Mu=u[i(8018)];continue}break}},X(r(8778)),i=n.ljfkC(uu),!d[n[r(2580)]]){if(n[r(1067)]!==n[r(7390)]){u.n=1;break}_0x1b39b8[r(303)]=(new(_0x2fd6bc[r(1368)]))[r(10523)]()}return u.a(2,new Promise(function(u,n){var A=r;v[A(7240)](v[A(4110)],v[A(5752)])?d.instantiateWasm(i,function(n,r){var t=A;b[t(6912)](u,b[t(9355)](f,n,r))}):b[A(2694)](typeof _0x28d0aa,b[A(2338)])?_0x909034[A(8018)]=_0x415cef=b[A(1832)](_0x1c3ef2,b.rmoGi(_0x3afb37,b.qqCgH),b.PWaqt(_0x1f5a56,b.wVRlS),_0x505f51(b[A(4603)]),b[A(10381)](_0x5f44e1,"./evpkdf"),_0x1ac6fc(b.niZGi)):typeof _0x1407d6===b[A(1133)]&&_0x1b6f4a[A(4388)]?b[A(1392)](_0x37a0f6,[b[A(2233)],b[A(6145)],b[A(4603)],b[A(8753)],"./cipher-core"],_0x15133c):_0x41a2b8(_0x32fead.CryptoJS)}));case 1:return n[r(9945)](J,null)&&void 0!==J||(J=k()),u.n=2,n[r(8058)](Z,y,J,i);case 2:return c=u.v,o=n[r(3862)](e,c),u.a(2,o)}},r)})))[u(6346)](this,arguments)}t[A(7866)](function(u,n,r){var f=A;return n&&t[f(5048)](q,u[f(10129)],n),r&&t[f(8822)](q,u,r),Object[f(4594)](u,t[f(720)],{writable:!1}),u},function u(n){"use strict";for(var r=A,f=r(4518)[r(7897)]("|"),e=0;;){switch(f[e++]){case"0":t[r(5198)](b,this,t[r(3302)],t[r(8466)]);continue;case"1":continue;case"2":this.message=t.reUWO[r(4189)](n,")");continue;case"3":t[r(9748)](v,this,u);continue;case"4":this.status=n;continue}break}});var ru,fu,Au=function(u){for(var n=A,r={Lteno:function(u,n){return t[_0x7f58(6229)](u,n)}};t[n(6781)](u.length,0);)t[n(7573)](t[n(4387)],n(7352))?r[n(4514)](_0x3b8a25,new _0x9df38a(n(10085))):u[n(9728)]()(d)},tu=[],eu=function(u){var n=A;if(t[n(9022)](t[n(1538)],t[n(1538)]))return tu.push(u);_0x50e41f+="&",_0x1e0405+=_0x529d94[n(2438)],_0x7d5c45+=":",_0x5673cf?_0x7af3c+=_0x3ee94c[n(2833)]:_0x4fd9eb+=""},iu=[],cu=function(u){var n=A;return t.GJjFx===t[n(1008)]?_0xf1edbb(t[n(8683)]):iu[n(7606)](u)},ou=function(u){var n=A;return t.vrnEA(t[n(2009)],"xKRGt")?t[n(6476)](Bu,u):_0x553d03},qu=function(){return Lu()},vu=function(u,n,r,f){var e=A;if(!t[e(3538)](f,0))return 0;for(var i=r,c=t[e(4938)](t[e(6717)](r,f),1),o=0;o>6,63),n[r++]=128|t[e(3894)](q,63),o++}}return n[r]=0,t.wsKne(r,i)},bu=function(u,n,r){return t.cXEYC(vu,u,N,n,r)},su=function(){return performance.now()},au=function(){return Date.now()},xu=1,wu=function(u){return t[A(10029)](u,0)&&t.fjiUy(u,3)},gu=function(u,n){var r=A;return t[r(8041)](t[r(9277)](t[r(6888)](n,2097152),0),t.HJrrJ(4194305,!!u))?t[r(7586)](t[r(4560)](u,0),t[r(6643)](n,4294967296)):NaN};var Cu,Bu,Du,Lu,zu={},Eu=function(){var u=A;return t[u(8442)](I,t[u(3869)])},du=function(){var u=A,n={mVCjV:t[u(8263)],xuISG:t.etPdn,UKDnY:t[u(10212)]};if(!du[u(6528)]){var r=t[u(4846)]((t[u(4398)](t[u(10213)](typeof navigator,"undefined")?u(2841):t[u(5756)](o,navigator),t.sgDko)&&navigator[u(8005)]||"C").replace("-","_"),t[u(8520)]),f={USER:t[u(8552)],LOGNAME:t[u(8552)],PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:r,_:t[u(8343)](Eu)};for(var e in zu)if(t[u(3938)](u(2040),t[u(9418)]))t[u(4341)](zu[e],void 0)?delete f[e]:f[e]=zu[e];else for(var i=n[u(2227)][u(7897)]("|"),c=0;;){switch(i[c++]){case"0":var q=_0x48968c.createElement(n[u(8784)]);continue;case"1":return v;case"2":try{v=q.getContext(n.UKDnY)}catch(u){}continue;case"3":var v=null;continue;case"4":!v&&(v=null);continue}break}var b=[];for(var e in f){if(t[u(3732)](u(7319),t[u(4015)]))return typeof _0x3cc087;b[u(7606)]("".concat(e,"=")[u(4189)](f[e]))}du[u(6528)]=b}return du[u(6528)]},Iu=function(u){for(var n=A,r={AjXMy:function(u,n){return t.GEbjh(u,n)},hPxea:function(u,n){return t[_0x7f58(8035)](u,n)},WKPKx:t.RFELD,wUXue:function(u,n){return u>>>n},owsui:function(u,n){return t[_0x7f58(5961)](u,n)},qWxta:function(u,n){return t[_0x7f58(4713)](u,n)},oNvZl:function(u,n){return t.JMfUH(u,n)}},f=0,e=0;t[n(3640)](e,u.length);++e)if(t[n(4941)](t[n(5927)],t.wFrsM))_0x1e36a9(_0x43e977[1],r[n(9680)](_0x26fd14=r[n(9680)](_0x16e798=_0x59c2be[4],null)&&void 0!==_0x3a3a4d?_0x1ca2fb:_0x933abe[5],null)&&void 0!==_0x3f25be?_0x2229bf:"");else{var i=u[n(252)](e);if(t.Vbabd(i,127))if(t.sCuDH(t.TNQYr,t[n(10246)]))switch(_0x394db0[n(2519)]=_0x339cb0[n(6460)]){case 0:_0x23fdf3[n(9758)]&&r[n(9182)](_0x1cc1d5[n(9758)],0)&&_0x3fcc2b.setTimeout(function(){_0x1febb5.doReport(!1)},_0x50c48d[n(9758)]);case 1:case r[n(2959)]:return _0x4b366a[n(9572)]()}else f++;else t[n(2600)](i,2047)?f+=2:i>=55296&&t[n(7051)](i,57343)?t[n(7715)](n(2224),t[n(8456)])?(f+=4,++e):_0x346d78[r.wUXue(_0x52f2d2,2)]|=r.owsui(r[n(7469)](_0x17a2dd[n(252)](_0x39bb9f),255),24-r.oNvZl(_0x4c7b98%4,8)):t[n(7044)](t.jNyzN,t[n(3902)])?_0x651201[n(2210)](_0x39381f,_0x27b8e3,_0x40f9b6):f+=3}return f},ju=function(){var u=A,n={knWzg:function(u,n,r){return u(n,r)},jHufF:function(u,n){return t[_0x7f58(1491)](u,n)},NEiaA:t[u(9145)]};return function(r){var f=u;if(!n[f(7779)](n[f(9349)],f(4325)))return crypto.getRandomValues(r);n.knWzg(_0x29a0f4,_0x3aa936,_0x18740a)}},Ku=function(u){var n=A,r={vsJMS:function(u,n){return t[_0x7f58(5756)](u,n)},oqBFp:function(u,n){return u instanceof n}};if(t[n(5377)]!=t[n(5377)]){var f={QHSjc:function(u,n){return r.vsJMS(u,n)}};return r[n(6579)](_0xdc0c13,_0x23056a)?_0xf325a1:new _0x499b5e(function(u){f[n(9289)](u,_0xca5be4)})}(Ku=t.IOBjg(ju))(u)},yu=function(u,n){Q[A(9117)](u,n)},hu=function(u){var n=A;if(!t[n(10213)](n(794),t.FgnQS))return Du(u);_0x4db46c.regeneratorRuntime=_0x4dd850},_u=function(u){var n=A,r=t[n(3727)](t[n(4859)](Iu,u),1),f=hu(r);return t[n(4677)](bu,u,f,r),f},Qu=new TextDecoder,Nu=function(u,n,r){var f=A;if(!u)return"";var e=function(u,n,r,f){var e=A,i=t[e(1632)](n,r);if(f)return i;for(;u[n]&&!t[e(1565)](n,i);)++n;return n}(N,u,n,r);return Qu.decode(N[f(3457)](u,e))};d[t[A(6328)]]&&d[A(6084)],d[A(6915)]&&d[t[A(3738)]],d[t[A(595)]]&&(h=d[t[A(595)]]),d[A(1359)]&&(y=d.wasmBinary),d[t[A(2579)]]&&d[A(7076)],d.thisProgram&&(I=d[A(5658)]),d[t[A(2413)]]=function(u,n,r,f,e){var i=A,c={BSCQA:function(u,n){return t.OdwrM(u,n)},SfFrk:function(u,n,r){return t[_0x7f58(8822)](u,n,r)},PeltS:t.aAkLf,tUuMn:function(u,n){return t[_0x7f58(6400)](u,n)},aIdhm:function(u,n){return t.mTnNt(u,n)},uBcbh:t.sfioJ,RLnGO:function(u,n){return t[_0x7f58(3384)](u,n)},vArYt:function(u,n){return t[_0x7f58(9650)](u,n)},UrXxu:function(u,n){return t.zcAAA(u,n)}};if(t[i(7573)](t[i(5535)],t[i(707)])){var o={string:function(u){var n=i,r=0;return t[n(9650)](u,null)&&t[n(5151)](u,void 0)&&t[n(6531)](u,0)&&(t[n(10435)]!=t[n(10435)]?_0x282b7b=_0x11e912:r=t[n(7902)](_u,u)),r},array:function(u){var n=i,r=c[n(3688)](hu,u[n(7855)]);return c[n(4955)](yu,u,r),r}};function q(u){var r=i;return n===c.PeltS?c[r(9242)](Nu,u):c[r(2706)](n,c[r(9701)])?c[r(5933)](Boolean,u):u}var v=d["_"+u],b=[],s=0;if(f)for(var a=0;a>>10<<5,30)]=_0x1b0183[i(4727)](t[i(948)](z,4294967296));continue;case"7":var D=this[i(8810)].toX32();continue;case"8":var L=8*B[i(7822)];continue;case"9":this._process();continue;case"10":var z=t[i(6101)](this[i(6568)],8);continue}break}else t[i(9022)](s,0)&&(s=t[i(7295)](qu)),b[a]=x(f[a]);else{if(t[i(1969)]===t[i(2245)])return t[i(5048)](_0x4cbed3,_0xd878ae[i(7897)]("."),_0x2f5396[i(7897)]("."));b[a]=f[a]}}var E=v[i(6346)](void 0,b);return E=t[i(6642)](function(u){return c.vArYt(s,0)&&c.BSCQA(ou,s),c.UrXxu(q,u)},E)}var I={shcCb:t[i(5630)]};return t[i(3456)](_0x108a6f,this,void 0,void 0,_0x51377c.mark(function u(){var n=i;return _0x4ac3a2[n(4099)](function(u){for(var r=n;;)switch(u.prev=u[r(6460)]){case 0:return u[r(4922)](I[r(453)],this.httpPost(_0x6b878,_0x19bfab[r(5614)](_0x5260f9)));case 1:case r(8961):return u[r(9572)]()}},u,this)}))},d.UTF8ToString=Nu,d[t.sQGba]=function(u){var n=A;if(!t[n(9833)](t.kICLE,"UkNAD")){var r=Iu(u)+1,f=t.QHZTM(Cu,r);return f&&t[n(9547)](bu,u,f,r),f}var e=_0x34276c[n(5614)](_0x430739.stack);if(e.includes(n(8230))||e[n(2019)](n(377))||t.pAEtk(_0x2edadf.isTrusted,!1)){var i={type:t[n(1086)],appid:""+_0x1e1925[n(6818)].getAppId(),hdid:(0,_0x379ed3[n(9591)])(_0x193f5b[n(6818)].HDID_NAME),qimei:_0x2a5368.default[n(2667)],time:(new _0x2df140)[n(7744)](),action:{clientXY:_0x476fe3.stringify([_0x321317[n(5758)],_0x22aa90.clientY]),screenXY:_0x594672[n(5614)]([_0x32ac81[n(1328)],_0x4bae31[n(9133)]]),isTrusted:_0xb9243a[n(5614)](_0x18f2f3[n(5711)]),stack:e}},c=_0x929ae1[n(5614)](i);_0x4d6def[n(1889)](c)}};var Mu,lu={e:function(){var u=A;if(t.tFYLX!==t.KGCHT)return t[u(7866)](R,"");_0xa9cf94[u(6818)].setDebugCallBack(_0x3066a1),_0x499599[u(6818)][u(3315)](_0x21725a),_0x520a66.default[u(9741)]()},a:function(u,n,r,f){var e,i=A;if(gu(n,r),!t[i(7431)](wu,u))return 28;if(0===u)e=t[i(6137)](au);else{if(!xu)return t[i(5151)](t[i(9297)],t[i(9297)])?_0x1c7262[t[i(6283)]](_0x1c060e,_0x482d53):52;e=t.aloKU(su)}var c=Math[i(6658)](t[i(6643)](t[i(7308)](e,1e3),1e3));return fu=[t[i(1694)](c,0),(ru=c,t[i(7220)](+Math.abs(ru),1)?t.eQFBB(ru,0)?t[i(5237)](+Math[i(4727)](t.pBCcp(ru,4294967296)),0):t[i(5835)](~~+Math[i(6426)](t[i(6734)](t[i(3657)](ru,+t.juROx(~~ru,0)),4294967296)),0):0)],M[t[i(3762)](f,2)]=fu[0],M[t.jkTdm(t[i(1632)](f,4),2)]=fu[1],0},f:function(u){N[A(7855)];!function(u){var n=A,r={VDsyg:function(u,n){return u*n},KOwdk:function(u,n){return t.wsKne(u,n)},yZrnS:function(u,n){return u%n},mJuiB:function(u,n){return t[_0x7f58(2109)](u,n)},EOkGm:function(u,n){return u+n}};if(t.vAygt(t.pWXsL,t[n(6713)])){var f={zkHWc:function(u,n){return r.mJuiB(u,n)},qKIaK:function(u,n){return u>>>n},TDXEX:function(u,f){return r[n(7659)](u,f)},BwTdC:function(u,n){return u*n},FyjJr:function(u,n){return u%n},rRflQ:function(u,f){return r[n(5306)](u,f)}};return _0x58652d[n(4128)][n(4381)]={pad:function(u,f){var A=n,t=r.VDsyg(f,4);u[A(9757)](),u[A(7822)]+=r.KOwdk(t,r[A(8909)](u[A(7822)],t)||t)},unpad:function(u){for(var r=n,A=u.words,t=u[r(7822)]-1;!f[r(2200)](A[f[r(4798)](t,2)]>>>f.TDXEX(24,f[r(5575)](f[r(7215)](t,4),8)),255);)t--;u[r(7822)]=f[r(2987)](t,1)}},_0x516932[n(4128)][n(4381)]}R(t.Rceqh)}()},c:function(u,n){var r=A,f={OecWi:function(u,n,r){return t[_0x7f58(9748)](u,n,r)}};if(!t.mYssi(t.oIjeO,t[r(4714)])){var i,c=0,o=0,q=e(t[r(6137)](du));try{for(q.s();!(i=q.n())[r(8379)];)if(t[r(6972)]!==r(2905))for(var v=t.rfklh[r(7897)]("|"),b=0;;){switch(v[b++]){case"0":var s=t[r(8999)](n,c);continue;case"1":o+=4;continue;case"2":c+=t[r(3433)](t[r(6479)](bu,a,s,1/0),1);continue;case"3":l[t.fgaNS(u,o)>>2]=s;continue;case"4":var a=i[r(10292)];continue}break}else f[r(10184)](_0x4acb10,{},"")}catch(u){q.e(u)}finally{q.f()}return 0}_0x2d15f1[r(2525)]()},d:function(u,n){var r=A;if(t.GglKh!==t[r(8698)])return(0,_0x42546d[r(4910)])()&&!(0,_0x32c9c3[r(8955)])()&&!(0,_0x5e79f2[r(3858)])();var f=du();l[u>>2]=f[r(7855)];var i,c=0,o=t[r(6754)](e,f);try{for(o.s();!(i=o.n())[r(8379)];){var q=i[r(10292)];c+=t[r(3588)](t[r(10028)](Iu,q),1)}}catch(u){o.e(u)}finally{t.sCuDH(t[r(4623)],t.qnBSd)?o.f():_0x505316=_0x18a52a[r(4189)](_0x1095f3)}return l[t.IEzoc(n,2)]=c,0},b:function(u,n){var r=A;if(t[r(1415)](t.rMqYH,t[r(1653)]))return Ku(N.subarray(u,t[r(6327)](u,n))),0;t[r(6115)](_0x313b42,_0x35737b,_0x19d621,_0x2752f6,_0x51b7e7)}};t[A(10262)](function(){return nu[A(6346)](this,arguments)}),t.SNWKY(function(){var u=A;if(d[t[u(8406)]])for(typeof d[t[u(8406)]]==t[u(3402)]&&(d[t[u(8406)]]=[d[t[u(8406)]]]);t.ZXyKM(d[t.nsgrd][u(7855)],0);)d[t[u(8406)]][u(9728)]()()}),t.PvHSn(function u(){var n=A,r={jlRlO:t.CwsSw,AqWyG:t[n(312)],AxKzQ:t[n(9734)],NcOGT:function(u,r){return t[n(4341)](u,r)},TRQXS:n(9256),eKrtE:function(u,r){return t[n(1415)](u,r)},mhTTJ:function(u){return u()},PGRJA:t[n(3990)],bcgUI:function(u,r){return t[n(3286)](u,r)}};if(t[n(8877)]===t[n(4601)])try{t.gQguG(_0x1b25af,_0x143711[n(6460)](_0x57b61b))}catch(u){t[n(8640)](_0x55ed81,u)}else{if(t.ZXyKM(S,0)){if(t.Yersc(t[n(6816)],t[n(4351)]))return void(W=u);var f={WVUnp:function(u,n){return t.NgOZh(u,n)}};return _0x2b62ed[n(4099)](function(u){for(var A=n;;)switch(u.prev=u.next){case 0:return u[A(4922)](r[A(3497)],new _0x57329a(function(u,n){var r=A,t=_0x123755.parse(_0x59ac5b);f[r(8931)](u,t)}));case 1:case r[A(9683)]:return u[A(9572)]()}},_0x1db455,this)}if(t[n(2954)](P),t.DGRaq(S,0)){if(t.mYssi(t[n(9158)],t[n(9158)]))return void(W=u);this[n(6509)]=_0x229248}function e(){for(var u=n,f=r[u(9722)].split("|"),A=0;;){switch(f[A++]){case"0":r[u(5505)](t=d[r[u(4881)]],null)||r[u(5828)](t,void 0)||t[u(2210)](d);continue;case"1":r[u(6304)](G);continue;case"2":if(m)return;continue;case"3":r[u(6304)](Y);continue;case"4":var t;continue;case"5":d[r[u(2806)]]=!0;continue}break}}d[t[n(1046)]]?(d[t[n(1046)]](t[n(495)]),t[n(8240)](setTimeout,function(){var u=n,r={aATgK:t[u(1046)]};t[u(9424)](t[u(8707)],t[u(8707)])?(t[u(8925)](setTimeout,function(){return d[r[u(9775)]]("")},1),t[u(10196)](e)):_0x2f4fb7.dateTimeFormat=(new(_0xcbb3c3[u(1444)]))[u(10523)]()},1)):n(355)===t[n(10301)]?this.sigBytes=r[n(10530)](_0x3535e4.length,4):t.mXjJC(e)}})},{}]},{},[109]); \ No newline at end of file diff --git a/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/package.json b/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/package.json new file mode 100644 index 00000000..5bbefffb --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/runner.js b/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/runner.js new file mode 100644 index 00000000..331bae61 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/assets/fingerprint/runner.js @@ -0,0 +1,169 @@ +// hydevice 指纹运行器: 仿真 Android WebView 环境 -> 真实请求 df/token + df/collect -> 输出 sdid +// argv: [stateDir, deviceJson] — deviceJson 为账号画像派生的设备覆盖参数 (一号一设备) +process.on('uncaughtException', (e) => { + console.error('[uncaught]', String(e && e.message).slice(0, 120)) +}) +const fs = require('fs') +const path = require('path') +const https = require('https') + +globalThis.window = globalThis +const stateDir = process.argv[2] || '.' +let _deviceOverrides = null +// Prefer an explicitly supplied JSON path; otherwise use the device hint that +// get_huya_sdid writes into the per-account state directory. +try { + const hintPath = + process.argv[3] && process.argv[3].endsWith('.json') + ? process.argv[3] + : path.join(stateDir, 'device.json') + _deviceOverrides = JSON.parse(fs.readFileSync(hintPath, 'utf8')) +} catch (e) {} +require(path.join(__dirname, 'env.js')).makeEnv(_deviceOverrides) + +// ---- localStorage 持久化(设备稳定性) ---- +try { + fs.mkdirSync(stateDir, { recursive: true }) +} catch (e) {} +const lsFile = path.join(stateDir, 'localstorage.json') +let _ls = {} +try { + _ls = JSON.parse(fs.readFileSync(lsFile, 'utf8')) +} catch (e) {} +globalThis.localStorage = { + getItem: (k) => (k in _ls ? _ls[k] : null), + setItem: (k, v) => { + _ls[k] = String(v) + try { + fs.writeFileSync(lsFile, JSON.stringify(_ls)) + } catch (e) {} + }, + removeItem: (k) => { + delete _ls[k] + try { + fs.writeFileSync(lsFile, JSON.stringify(_ls)) + } catch (e) {} + }, + clear: () => { + _ls = {} + try { + fs.writeFileSync(lsFile, JSON.stringify(_ls)) + } catch (e) {} + }, + key: (i) => Object.keys(_ls)[i] || null, + get length() { + return Object.keys(_ls).length + }, +} +globalThis.sessionStorage = { + getItem: () => null, + setItem() {}, + removeItem() {}, + clear() {}, + key: () => null, + get length() { + return 0 + }, +} + +// ---- 真实 XHR ---- +function xhr(url, body, headers) { + return new Promise((resolve) => { + const u = new URL(url) + const data = body == null ? null : Buffer.from(String(body), 'utf8') + const req = https.request( + { + hostname: u.hostname, + port: 443, + path: u.pathname + u.search, + method: 'POST', + headers: Object.assign( + { + accept: 'application/json, text/javascript, */*; q=0.01', + 'content-type': 'application/json', + origin: 'https://aq.huya.com', + referer: 'https://aq.huya.com/', + 'user-agent': globalThis.navigator.userAgent, + 'accept-language': 'zh-CN,zh;q=0.9', + }, + headers || {}, + ), + timeout: 15000, + }, + (res) => { + let chunks = [] + res.on('data', (c) => chunks.push(c)) + res.on('end', () => + resolve({ status: res.statusCode, text: Buffer.concat(chunks).toString('utf8') }), + ) + }, + ) + req.on('timeout', () => { + req.destroy() + resolve({ status: 0, text: '' }) + }) + req.on('error', () => resolve({ status: 0, text: '' })) + if (data) req.write(data) + req.end() + }) +} +globalThis.XMLHttpRequest = class { + open(m, u) { + this._m = m + this._u = u + this._h = {} + } + setRequestHeader(k, v) { + this._h[k] = v + } + getAllResponseHeaders() { + return '' + } + addEventListener(t, f) { + if (t === 'load' || t === 'readystatechange') this._on = f + } + send(d) { + xhr(this._u, d, this._h).then((r) => { + this.status = r.status + this.readyState = 4 + this.responseText = r.text + this.response = r.text + const done = () => { + if (String(this._u).includes('/collect')) { + try { + const j = JSON.parse(r.text) + if (j && j.data) { + if (j.data.sdid) console.log('__SDID__' + j.data.sdid) + if (j.data.hdid) console.log('__HDID__' + j.data.hdid) + if (globalThis.document && globalThis.document.cookie) { + console.log('__COOKIES__' + globalThis.document.cookie) + } + setTimeout(() => process.exit(0), 200) + } + } catch (e) {} + } + try { + this.onreadystatechange && this.onreadystatechange() + } catch (e) {} + try { + this._on && this._on() + } catch (e) {} + try { + this.onload && this.onload() + } catch (e) {} + } + setTimeout(done, 30) + }) + } +} + +eval(fs.readFileSync(path.join(__dirname, 'hydevice-prod-1.2.45-min.js'), 'utf8')) +try { + globalThis.initFingerprint(process.argv[3] || '5008') +} catch (e) { + console.error('[init]', e.message.slice(0, 120)) +} +setTimeout(() => { + console.error('__TIMEOUT__') + process.exit(2) +}, 25000) diff --git a/apps/backend/src/services/semi-auto/huya-native/cookie.ts b/apps/backend/src/services/semi-auto/huya-native/cookie.ts new file mode 100644 index 00000000..41fa6464 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/cookie.ts @@ -0,0 +1,497 @@ +/** 虎牙 Cookie 规范化、网页字段补齐与 QIMEI 指纹生成。 */ + +import crypto from 'node:crypto' + +export type CookiePair = [string, string] + +const MASK_64 = 0xffffffffffffffffn +const QIMEI_EPOCH_1582 = -12216643543000n +const GAME_DID_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_' + +const DEFAULT_QIMEI_FEATURE = { + screen: { resolution: '800x600', availResolution: '800x600' }, + navigator: { + deviceMemory: 16, + pdfViewerEnabled: true, + cookieEnabled: true, + productSub: '20030107', + hardwareConcurrency: 10, + }, + webgl: 'Google Inc. (Apple)~ANGLE (Apple, ANGLE Metal Renderer: Apple M4, Unspecified Version)', + timezoneOffset: -480, +} + +const DEVICE_GPU_FEATURES: Record = { + xiaomi: ['Qualcomm', 'Adreno (TM) 650'], + redmi: ['Qualcomm', 'Adreno (TM) 650'], + vivo: ['Qualcomm', 'Adreno (TM) 650'], + iqoo: ['Qualcomm', 'Adreno (TM) 650'], + oppo: ['Qualcomm', 'Adreno (TM) 650'], + oneplus: ['Qualcomm', 'Adreno (TM) 650'], + samsung: ['ARM', 'Mali-G78'], + honor: ['ARM', 'Mali-G78'], + motorola: ['Qualcomm', 'Adreno (TM) 642L'], + realme: ['Qualcomm', 'Adreno (TM) 650'], + nubia: ['Qualcomm', 'Adreno (TM) 650'], + gionee: ['Qualcomm', 'Adreno (TM) 506'], +} + +const COOKIE_FILL_MAP: CookiePair[] = [ + ['SoundValue', '0.50'], + ['alphaValue', '0.80'], + ['isInLiveRoom', 'true'], + ['udb_passdata', '3'], + ['udb_accdata', 'undefined'], +] + +export function cookiePairs(cookie: string): CookiePair[] { + const pairs: CookiePair[] = [] + for (const part of String(cookie || '').split(';')) { + const item = part.trim() + if (!item || !item.includes('=')) continue + const separator = item.indexOf('=') + const key = item.slice(0, separator).trim() + if (!key) continue + pairs.push([key, item.slice(separator + 1).trim()]) + } + return pairs +} + +export function normalizeCookiePairs(pairs: CookiePair[]): string { + const orderedKeys: string[] = [] + const values = new Map() + for (const [rawKey, rawValue] of pairs) { + const key = String(rawKey || '').trim() + if (!key) continue + if (!values.has(key)) orderedKeys.push(key) + values.set(key, rawValue === null || rawValue === undefined ? '' : String(rawValue).trim()) + } + return orderedKeys.map((key) => `${key}=${values.get(key) || ''}`).join('; ') +} + +export function cookieValue(cookie: string, key: string): string { + let value = '' + for (const [itemKey, itemValue] of cookiePairs(cookie)) { + if (itemKey === key) value = itemValue + } + return value +} + +export function buildHuyaLoginContext(cookie: string): string { + const guidData = cookieValue(cookie, 'udb_guiddata') + const yamid = cookieValue(cookie, '__yamid_new') + const guid = cookieValue(cookie, 'guid') + if (!guidData || !yamid || !guid) return '' + return `WB-${guidData}-${yamid}-${guid}` +} + +function replaceCookie(pairs: CookiePair[], key: string, value: string): void { + const next = String(value ?? '').trim() + if (!next) return + for (let index = pairs.length - 1; index >= 0; index -= 1) { + if (pairs[index]?.[0] === key) pairs.splice(index, 1) + } + pairs.push([key, next]) +} + +function addCookie(pairs: CookiePair[], key: string, value: string): void { + const next = String(value ?? '').trim() + if (!next) return + if (pairs.some(([itemKey]) => itemKey === key)) return + pairs.push([key, next]) +} + +export function mergeHuyaWebCookie(input: { + cookie: string + biztoken: string + sdid: string + hdid: string + deviceInfo: Record + uid: number + username?: string + includeTransient?: boolean +}): string { + const pairs = cookiePairs(input.cookie) + const username = String(input.username || '').trim() + + // 扫码成功时服务端会通过 Set-Cookie 下发独立的 udb_cred;只有缺失时才用 + // biztoken 兜底,不能覆盖服务端签发的真实值。 + if (!cookieValue(input.cookie, 'udb_cred')) { + replaceCookie(pairs, 'udb_cred', input.biztoken) + } + if (input.uid) { + replaceCookie(pairs, 'udb_uid', String(input.uid)) + replaceCookie(pairs, 'yyuid', String(input.uid)) + } + replaceCookie(pairs, 'udb_biztoken', input.biztoken) + replaceCookie(pairs, 'udb_version', '1.0') + replaceCookie(pairs, 'udb_origin', '0') + replaceCookie(pairs, 'udb_status', '1') + replaceCookie(pairs, 'sdid', input.sdid) + replaceCookie(pairs, 'hdid', input.hdid) + if (username.startsWith('hy_')) { + replaceCookie(pairs, 'udb_passport', username) + replaceCookie(pairs, 'username', username) + } + + const optionalKeys = [ + 'guid', + 'udb_guiddata', + '__yamid_new', + 'game_did', + '_qimei_uuid42', + '_qimei_fingerprint', + '_qimei_h38', + 'udb_anouid', + 'udb_anobiztoken', + '__yasmid', + '__yamid_tt1', + 'SoundValue', + 'alphaValue', + 'isInLiveRoom', + 'udb_deviceid', + 'udb_passdata', + '_rep_cnt', + 'Hm_lvt_51700b6c722f5bb4cf39906a596ea41f', + 'HMACCOUNT', + 'udb_appid', + 'rep_cnt', + 'udb_accdata', + 'h_unt', + '__yaoldyyuid', + '_yasids', + 'huya_flash_rep_cnt', + 'huyasp_rep_cnt', + 'huyawap_rep_cnt', + 'huya_hd_rep_cnt', + 'Hm_lpvt_51700b6c722f5bb4cf39906a596ea41f', + 'huya_web_rep_cnt', + ] + for (const key of optionalKeys) { + const value = String(input.deviceInfo[key] || '').trim() + if (!value) continue + for (let index = pairs.length - 1; index >= 0; index -= 1) { + if (pairs[index]?.[0] === key) pairs.splice(index, 1) + } + pairs.push([key, value]) + } + const webGuideData = String(input.deviceInfo.web_guiddata || input.deviceInfo.udb_guiddata || '') + if (webGuideData) replaceCookie(pairs, 'udb_guiddata', webGuideData) + const webDeviceId = String(input.deviceInfo.web_device_id || '') + if (/^w_\d{19}$/.test(webDeviceId)) replaceCookie(pairs, 'udb_deviceid', webDeviceId) + + return normalizeCookiePairs( + input.includeTransient === false + ? pairs.filter(([key]) => key !== 'web_qrlogin_confirm_id') + : pairs, + ) +} + +export type QimeiFeature = { + screen: { resolution: string; availResolution: string } + navigator: { + deviceMemory: number | string + pdfViewerEnabled: boolean + cookieEnabled: boolean + productSub: string + hardwareConcurrency: number | string + } + webgl: string + timezoneOffset: number +} + +export function qimeiFeatureFromDeviceProfile( + deviceInfo: Record | null | undefined, +): QimeiFeature { + const info = deviceInfo || {} + const width = String(info.width || '1080') + const height = String(info.height || '2400') + const vendor = String(info.vendor || '') + .trim() + .toLowerCase() + const model = String(info.model || 'Android WebView').trim() + const [gpuVendor, renderer] = DEVICE_GPU_FEATURES[vendor] || ['Qualcomm', `${model} Graphics`] + return { + screen: { resolution: `${width}x${height}`, availResolution: `${width}x${height}` }, + navigator: { + deviceMemory: (info.device_memory as number | string | undefined) || 8, + pdfViewerEnabled: false, + cookieEnabled: true, + productSub: '20030107', + hardwareConcurrency: (info.hardware_concurrency as number | string | undefined) || 8, + }, + webgl: `Google Inc. (${gpuVendor})~ANGLE (${gpuVendor}, ${renderer})`, + timezoneOffset: -480, + } +} + +function jsText(value: unknown): string { + if (value === null || value === undefined) return '' + if (typeof value === 'boolean') return value ? 'true' : 'false' + return String(value) +} + +function qimeiFeatureString(feature: QimeiFeature): string { + return ( + [ + feature.screen.resolution, + feature.screen.availResolution, + feature.navigator.deviceMemory, + feature.navigator.pdfViewerEnabled, + feature.navigator.cookieEnabled, + feature.navigator.productSub, + feature.navigator.hardwareConcurrency, + feature.webgl, + feature.timezoneOffset, + ] + .map(jsText) + .join('###') + '###' + ) +} + +function rotl64(value: bigint, shift: number): bigint { + const normalizedShift = shift % 64 + if (normalizedShift === 0) return value & MASK_64 + return ((value << BigInt(normalizedShift)) | (value >> BigInt(64 - normalizedShift))) & MASK_64 +} + +function fmix64(value: bigint): bigint { + let next = value + next ^= next >> 33n + next = (next * 0xff51afd7ed558ccdn) & MASK_64 + next ^= next >> 33n + next = (next * 0xc4ceb9fe1a85ec53n) & MASK_64 + next ^= next >> 33n + return next & MASK_64 +} + +export function x64hash128(value: string, seed = 0): string { + const utf16 = Buffer.from(value, 'utf16le') + const data = Buffer.alloc(utf16.length / 2) + for (let index = 0; index < data.length; index += 1) data[index] = utf16[index * 2] || 0 + const length = data.length + let h1 = BigInt(seed) & MASK_64 + let h2 = BigInt(seed) & MASK_64 + const c1 = 0x87c37b91114253d5n + const c2 = 0x4cf5ad432745937fn + + for (let offset = 0; offset < length - (length % 16); offset += 16) { + let k1 = data.readBigUInt64LE(offset) + let k2 = data.readBigUInt64LE(offset + 8) + k1 = (rotl64((k1 * c1) & MASK_64, 31) * c2) & MASK_64 + h1 ^= k1 + h1 = (rotl64(h1, 27) + h2) & MASK_64 + h1 = (h1 * 5n + 0x52dce729n) & MASK_64 + k2 = (rotl64((k2 * c2) & MASK_64, 33) * c1) & MASK_64 + h2 ^= k2 + h2 = (rotl64(h2, 31) + h1) & MASK_64 + h2 = (h2 * 5n + 0x38495ab5n) & MASK_64 + } + + const tailStart = length - (length % 16) + const tail = data.subarray(tailStart) + const tailLength = tail.length + let k1 = 0n + let k2 = 0n + for (let index = tailLength - 1; index > 7; index -= 1) { + k2 ^= BigInt(tail[index] || 0) << BigInt(8 * (index - 8)) + } + if (tailLength >= 9) h2 ^= (rotl64((k2 * c2) & MASK_64, 33) * c1) & MASK_64 + for (let index = Math.min(tailLength, 8) - 1; index > 0; index -= 1) { + k1 ^= BigInt(tail[index] || 0) << BigInt(8 * index) + } + if (tailLength >= 1) { + k1 ^= BigInt(tail[0] || 0) << 32n + h1 ^= (rotl64((k1 * c1) & MASK_64, 31) * c2) & MASK_64 + } + + h1 ^= BigInt(length) + h2 ^= BigInt(length) + h1 = (h1 + h2) & MASK_64 + h2 = (h2 + h1) & MASK_64 + h1 = fmix64(h1) + h2 = fmix64(h2) + h1 = (h1 + h2) & MASK_64 + h2 = (h2 + h1) & MASK_64 + return `${h1.toString(16).padStart(16, '0')}${h2.toString(16).padStart(16, '0')}` +} + +export function qimeiFingerprintGenerate(feature?: QimeiFeature): string { + return x64hash128(qimeiFeatureString(feature || DEFAULT_QIMEI_FEATURE), 31) +} + +function crc32(buffer: Buffer): number { + let crc = 0xffffffff + for (const byte of buffer) { + crc ^= byte + for (let bit = 0; bit < 8; bit += 1) { + crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0) + } + } + return (crc ^ 0xffffffff) >>> 0 +} + +function returnBase16(value: bigint): string { + if (value <= 0n) return '' + return value.toString(16).toUpperCase() +} + +function generateBits(value: bigint, startBit: number, endBit: number): string { + const hex = returnBase16(value) + let output = '' + for (let index = Math.floor(startBit / 4); index <= Math.floor(endBit / 4); index += 1) { + output += hex[index] || '0' + } + return output +} + +function randomInt(maxExclusive: number): number { + return Math.floor(Math.random() * maxExclusive) +} + +function yamidNewGenerate32(): string { + const nowMs = BigInt(Date.now()) + const value = nowMs - QIMEI_EPOCH_1582 + return [ + generateBits(value, 0, 31), + generateBits(value, 32, 47), + `${generateBits(value, 48, 59)}1`, + generateBits(BigInt(randomInt(4095)), 0, 7), + generateBits(BigInt(randomInt(4095)), 0, 7), + generateBits(BigInt(randomInt(8191)), 0, 7) + + generateBits(BigInt(randomInt(8191)), 8, 15) + + generateBits(BigInt(randomInt(8191)), 0, 7) + + generateBits(BigInt(randomInt(8191)), 8, 15) + + generateBits(BigInt(randomInt(8191)), 0, 15), + ].join('') +} + +function gameDidGenerate(length = 35): string { + let output = '' + for (let index = 0; index < length; index += 1) { + output += GAME_DID_CHARS[randomInt(GAME_DID_CHARS.length - 1)] || '' + } + return output +} + +export function qimeiUuid42( + nowMs = Date.now(), + options: { cookieEnabled?: boolean; randomValue?: number } = {}, +): string { + const current = new Date(nowMs) + const yearHex = (current.getFullYear() % 100).toString(16).padStart(2, '0') + const monthHex = (current.getMonth() + 1).toString(16) + const dateHex = [ + current.getDate(), + current.getHours(), + current.getMinutes(), + current.getSeconds(), + ] + .map((value) => value.toString(16).padStart(2, '0')) + .join('') + const prefix = yearHex + monthHex + dateHex + (options.cookieEnabled === false ? '000' : '100') + const randomSource = () => options.randomValue ?? Math.random() + const randomSegment = Array.from({ length: 20 }, () => + Math.min(15, Math.max(0, Math.trunc(randomSource() * 16))).toString(16), + ).join('') + const template = `${prefix}----${randomSegment}----` + const replacement = crc32(Buffer.from(template, 'ascii')).toString(16).padStart(8, '0') + return prefix + replacement.slice(0, 4) + randomSegment + replacement.slice(4) +} + +export function fillWebCookieFields(input: { + cookie: string + guid: string + udbGuiddata?: string + uid?: number | string + keepGuid?: boolean + qimeiFeature?: QimeiFeature +}): string { + const pairs = new Map() + for (const [key, value] of cookiePairs(input.cookie)) pairs.set(key, value) + const add = (key: string, value: string) => { + if (value && !pairs.get(key)) pairs.set(key, value) + } + const uid = Number(input.uid || 0) || 0 + + if (input.guid) { + if (!(input.keepGuid !== false && pairs.get('guid'))) add('guid', input.guid) + } else { + add( + 'guid', + `0a${crypto.randomBytes(5).toString('hex')}966a${crypto.randomBytes(8).toString('hex')}`, + ) + } + add('udb_guiddata', input.udbGuiddata || crypto.randomBytes(16).toString('hex')) + add('udb_appid', '5002') + add('_qimei_uuid42', qimeiUuid42()) + add('__yamid_new', yamidNewGenerate32()) + add('game_did', gameDidGenerate()) + add('_qimei_fingerprint', qimeiFingerprintGenerate(input.qimeiFeature)) + add('_qimei_h38', pairs.get('_qimei_uuid42') || '') + + const yasmid = Math.random().toFixed(17) + add('__yasmid', yasmid) + add('__yamid_tt1', yasmid) + add('_rep_cnt', String(randomInt(10))) + add('rep_cnt', String(randomInt(10))) + add('h_unt', String(Math.floor(Date.now() / 1000))) + if (uid) add('__yaoldyyuid', String(uid)) + add('_yasids', `__rootsid%3D${yamidNewGenerate32()}`) + add('Hm_lvt_51700b6c722f5bb4cf39906a596ea41f', String(Math.floor(Date.now() / 1000))) + add('Hm_lpvt_51700b6c722f5bb4cf39906a596ea41f', String(Math.floor(Date.now() / 1000))) + add('HMACCOUNT', crypto.randomBytes(8).toString('hex').toUpperCase()) + add('huya_flash_rep_cnt', String(1 + randomInt(400))) + add('huyasp_rep_cnt', String(1 + randomInt(40))) + add('huya_hd_rep_cnt', String(1 + randomInt(40))) + add('huya_web_rep_cnt', String(300 + randomInt(601))) + for (const [key, value] of COOKIE_FILL_MAP) add(key, value) + + return Array.from(pairs.entries()) + .map(([key, value]) => `${key}=${value}`) + .join('; ') +} + +export type HuyaWebCookieIdentity = { + cookie: string + context: string + guid: string + udbGuiddata: string + yamidNew: string +} + +/** 为网页扫码登录补齐稳定的设备身份字段,并生成服务端要求的 WB context。 */ +export function ensureHuyaWebCookieIdentity(input: { + cookie?: string + guid?: string + udbGuiddata?: string + uid?: number | string + qimeiFeature?: QimeiFeature +}): HuyaWebCookieIdentity { + const fillInput: Parameters[0] = { + cookie: String(input.cookie || ''), + guid: String(input.guid || ''), + } + if (input.udbGuiddata) fillInput.udbGuiddata = input.udbGuiddata + if (input.uid !== undefined) fillInput.uid = input.uid + if (input.qimeiFeature) fillInput.qimeiFeature = input.qimeiFeature + const cookie = fillWebCookieFields(fillInput) + const pairs = cookiePairs(cookie) + const set = (key: string, value: string) => { + const next = value.trim() + if (!next) return + for (let index = pairs.length - 1; index >= 0; index -= 1) { + if (pairs[index]?.[0] === key) pairs.splice(index, 1) + } + pairs.push([key, next]) + } + set('udb_appid', '5002') + const normalized = normalizeCookiePairs(pairs) + return { + cookie: normalized, + context: buildHuyaLoginContext(normalized), + guid: cookieValue(normalized, 'guid'), + udbGuiddata: cookieValue(normalized, 'udb_guiddata'), + yamidNew: cookieValue(normalized, '__yamid_new'), + } +} diff --git a/apps/backend/src/services/semi-auto/huya-native/fingerprint.ts b/apps/backend/src/services/semi-auto/huya-native/fingerprint.ts new file mode 100644 index 00000000..28c6e9d6 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/fingerprint.ts @@ -0,0 +1,132 @@ +/** 通过随项目携带的 hydevice runner 获取虎牙高信任 sdid。 */ + +import { execFile } from 'node:child_process' +import fs from 'node:fs/promises' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { promisify } from 'node:util' + +const execFileAsync = promisify(execFile) +const FINGERPRINT_DIR = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + 'assets/fingerprint', +) +const RUNNER_PATH = path.join(FINGERPRINT_DIR, 'runner.js') +const SDID_PREFIX = '__SDID__' +const HDID_PREFIX = '__HDID__' +const COOKIE_PREFIX = '__COOKIES__' + +export type HuyaFingerprintResult = { + sdid: string + hdid: string + cookies: Record + source: 'fingerprint' | 'fallback' + message?: string +} + +export type FingerprintResolver = ( + stateDir: string, + appId?: string, +) => Promise + +function parseCookieText(text: string): Record { + const cookies: Record = {} + for (const part of text.split(';')) { + const item = part.trim() + if (!item || !item.includes('=')) continue + const separator = item.indexOf('=') + const key = item.slice(0, separator).trim() + const value = item.slice(separator + 1).trim() + if (key && value) cookies[key] = value + } + return cookies +} + +async function runFingerprintRunner( + stateDir: string, + appId = '5008', +): Promise { + await fs.mkdir(stateDir, { recursive: true }) + try { + const { stdout, stderr } = await execFileAsync( + process.execPath, + [RUNNER_PATH, stateDir, appId], + { + cwd: FINGERPRINT_DIR, + timeout: 45_000, + maxBuffer: 2 * 1024 * 1024, + }, + ) + let sdid = '' + let hdid = '' + let cookies: Record = {} + for (const rawLine of stdout.split(/\r?\n/)) { + const line = rawLine.trim() + if (line.startsWith(SDID_PREFIX) && line.length > SDID_PREFIX.length + 20) { + sdid = line.slice(SDID_PREFIX.length) + } else if (line.startsWith(HDID_PREFIX) && line.length > HDID_PREFIX.length + 20) { + hdid = line.slice(HDID_PREFIX.length) + } else if (line.startsWith(COOKIE_PREFIX)) { + cookies = parseCookieText(line.slice(COOKIE_PREFIX.length)) + } + } + if (sdid) return { sdid, hdid, cookies, source: 'fingerprint' } + const detail = stderr.trim().split(/\r?\n/).pop() || 'runner 未返回 sdid' + throw new Error(detail.slice(0, 160)) + } catch (error) { + if (error instanceof Error) throw error + throw new Error(String(error), { cause: error }) + } +} + +async function fallbackFingerprint(): Promise { + try { + const tokenResponse = await fetch('https://df.huya.com/web/df/token', { + method: 'POST', + headers: { 'content-type': 'application/json', accept: 'application/json' }, + body: JSON.stringify({ encryptVersion: '1.0.1', fingerprintVersion: '1.2.45' }), + signal: AbortSignal.timeout(20_000), + }) + if (!tokenResponse.ok) return null + const tokenPayload = (await tokenResponse.json()) as { data?: { token?: string } } + const token = String(tokenPayload.data?.token || '').trim() + if (!token) return null + const collectResponse = await fetch('https://df.huya.com/web/df/collect', { + method: 'POST', + headers: { 'content-type': 'application/json', accept: 'application/json' }, + body: JSON.stringify({ token }), + signal: AbortSignal.timeout(20_000), + }) + if (!collectResponse.ok) return null + const collectPayload = (await collectResponse.json()) as { + data?: { sdid?: string; hdid?: string } + } + const sdid = String(collectPayload.data?.sdid || '').trim() + if (!sdid) return null + return { + sdid, + hdid: String(collectPayload.data?.hdid || '').trim(), + cookies: {}, + source: 'fallback', + message: '低信任指纹(降级)', + } + } catch { + return null + } +} + +export const getHuyaFingerprint: FingerprintResolver = async (stateDir, appId = '5008') => { + try { + const result = await runFingerprintRunner(stateDir, appId) + if (result) return result + } catch { + // runner 失败时使用低信任降级,保持与现有 Connector 一致的可恢复行为。 + } + const fallback = await fallbackFingerprint() + if (fallback) return fallback + throw new Error('获取虎牙设备指纹失败') +} + +export async function removeFingerprintState(stateDir: string): Promise { + await fs.rm(stateDir, { recursive: true, force: true }).catch(() => undefined) +} diff --git a/apps/backend/src/services/semi-auto/huya-native/huya-native-connector.ts b/apps/backend/src/services/semi-auto/huya-native/huya-native-connector.ts new file mode 100644 index 00000000..52f0bb8f --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/huya-native-connector.ts @@ -0,0 +1,760 @@ +/** + * order_site 内置虎牙半自动履约 Connector。 + * + * 登录、角色绑定、CK 兑换和一次性浏览器注入票据全部在本进程完成。原始 CK + * 只保存在内存会话中,不落库、不写日志、不出现在票据字符串里。 + */ + +import crypto from 'node:crypto' +import os from 'node:os' +import path from 'node:path' + +import { runtimeConfig } from '../../../config/runtime.js' +import { createHttpError } from '../../../utils/http.js' +import type { + ConnectorBindingSession, + ConnectorBrowserTicket, + ConnectorInjectionPayload, + ConnectorLoginSession, +} from '../huya-connector-client.js' +import { + cookiePairs, + ensureHuyaWebCookieIdentity, + fillWebCookieFields, + mergeHuyaWebCookie, + normalizeCookiePairs, + qimeiFeatureFromDeviceProfile, +} from './cookie.js' +import { + getHuyaFingerprint, + removeFingerprintState, + type FingerprintResolver, +} from './fingerprint.js' +import { + buildBindUrls, + getLiveLinkMiniQrcode, + getLiveLinkQrcodeStatus, + hasExistingHuyaBinding, + HuyaQrRole, + HuyaRpcClient, + webBehavior, + type HuyaBindResponse, + type HuyaGameAccountData, +} from './huya-rpc.js' + +const LOGIN_QR_TTL_MS = 5 * 60 * 1000 +const CREDENTIAL_TTL_MS = 24 * 60 * 60 * 1000 +const BINDING_QR_TTL_MS = 5 * 60 * 1000 +const BROWSER_TICKET_TTL_MS = 2 * 60 * 1000 +const MAX_SESSIONS = 500 +const NATIVE_TICKET_PREFIX = 'native-ticket-' + +type FetchLike = typeof fetch +type NativeLoginStatus = ConnectorLoginSession['status'] +type NativeBindingStatus = ConnectorBindingSession['status'] + +type NativeBindState = { + status: NativeBindingStatus + qrImage: string + qrToken: string + expiresAtMs: number + account: string + role: string + channel: string + hasExistingBinding: boolean + rebindRequested: boolean + rebindScanned: boolean + baselineRoleKey: string + message: string +} + +type NativeTicket = { + ticket: string + targetUrl: string + cookie: string + expiresAtMs: number +} + +type NativeSession = { + sessionId: string + orderNo: string + taskId: number + stateDir: string + createdAtMs: number + expiresAtMs: number + qr: HuyaQrRole + behavior: string + page: string + qrid: string + qrImage: string + sdid: string + hdid: string + deviceInfo: Record + status: NativeLoginStatus + uid: number + nickname: string + cookie: string + message: string + binding: NativeBindState + tickets: Map +} + +export type HuyaNativeConnectorOptions = { + fetchImpl?: FetchLike + getFingerprint?: FingerprintResolver + now?: () => number + stateRoot?: string + rpcTimeoutMs?: number +} + +function defaultBindingState(): NativeBindState { + return { + status: 'not_started', + qrImage: '', + qrToken: '', + expiresAtMs: 0, + account: '', + role: '', + channel: '', + hasExistingBinding: false, + rebindRequested: false, + rebindScanned: false, + baselineRoleKey: '', + message: '', + } +} + +function iso(value: number): string { + return new Date(value).toISOString() +} + +function extractInt(value: unknown): number { + const parsed = Number.parseInt(String(value ?? '').trim(), 10) + return Number.isFinite(parsed) && parsed > 0 ? parsed : 0 +} + +function readString(value: unknown): string { + return String(value ?? '').trim() +} + +function parseRole(response: HuyaBindResponse | null): { + account: string + role: string + channel: string +} { + if (!response || response.status !== 200) return { account: '', role: '', channel: '' } + const data: HuyaGameAccountData = response.accountData + const account = data.gameAccount.nick || data.gameRole.roleName + const role = data.gameRole.roleName + const channel = [data.gameRole.platName, data.gameRole.areaName].filter(Boolean).join(' · ') + return { account, role, channel } +} + +function bindingRoleKey(role: { account: string; role: string; channel: string }): string { + return [role.account, role.role, role.channel].join('\u0000') +} + +function configValues() { + const huya = runtimeConfig.semiAuto?.huya + const bindActId = extractInt(huya?.bindActId || 9271) + const outerActId = readString(huya?.outerActId || '17096') + const roomPid = readString(huya?.roomPid || '1199650619883') + if (!bindActId) { + throw createHttpError('虎牙绑定活动 ID 未配置', { + statusCode: 503, + errorCode: 'huya_bind_act_not_configured', + }) + } + return { bindActId, outerActId, roomPid } +} + +export class HuyaNativeConnector { + private readonly sessions = new Map() + private readonly locks = new Map>() + private readonly fetchImpl: FetchLike + private readonly fingerprintResolver: FingerprintResolver + private readonly now: () => number + private readonly stateRoot: string + private readonly rpcTimeoutMs: number + + constructor(options: HuyaNativeConnectorOptions = {}) { + this.fetchImpl = options.fetchImpl || fetch + this.fingerprintResolver = options.getFingerprint || getHuyaFingerprint + this.now = options.now || (() => Date.now()) + this.stateRoot = options.stateRoot || path.join(os.tmpdir(), 'huya-semi-auto-device') + this.rpcTimeoutMs = options.rpcTimeoutMs || 15_000 + } + + async createLoginSession(input: { + taskId: number + orderNo: string + }): Promise { + this.prune() + const sessionId = crypto.randomBytes(24).toString('base64url') + const stateDir = path.join(this.stateRoot, sessionId) + try { + const fingerprint = await this.fingerprintResolver(stateDir, '5008') + if (!fingerprint.sdid) throw new Error(fingerprint.message || '获取虎牙设备指纹失败') + const fingerprintCookie = normalizeCookiePairs(Object.entries(fingerprint.cookies || {})) + const webIdentity = ensureHuyaWebCookieIdentity({ + cookie: fingerprintCookie, + qimeiFeature: qimeiFeatureFromDeviceProfile(fingerprint.cookies), + }) + if (!webIdentity.context) throw new Error('虎牙网页设备身份生成失败') + const qr = new HuyaQrRole({ + sdid: fingerprint.sdid, + cookie: webIdentity.cookie, + context: webIdentity.context, + fetchImpl: this.fetchImpl, + }) + await qr.bootstrapMiddle() + const behavior = webBehavior() + const response = await qr.call('/qrLgn/getQrId', '70001', { + behavior: behavior.behavior, + type: '', + domainList: '', + page: behavior.page, + }) + const qrid = readString(response.data?.qrId) + if (!qrid) throw new Error(response.message || '获取虎牙登录二维码失败') + const qrImage = await qr.getQrImg(qrid) + qr.activateFingerprintSdid() + const createdAtMs = this.now() + const session: NativeSession = { + sessionId, + orderNo: input.orderNo, + taskId: input.taskId, + stateDir, + createdAtMs, + expiresAtMs: createdAtMs + LOGIN_QR_TTL_MS, + qr, + behavior: behavior.behavior, + page: behavior.page, + qrid, + qrImage, + sdid: fingerprint.sdid, + hdid: fingerprint.hdid, + deviceInfo: { + ...(fingerprint.cookies || {}), + ...Object.fromEntries(cookiePairs(webIdentity.cookie)), + sdid: fingerprint.sdid, + hdid: fingerprint.hdid, + udb_appid: '5002', + }, + status: 'waiting_scan', + uid: 0, + nickname: '', + cookie: '', + message: '等待使用虎牙 App 扫码', + binding: defaultBindingState(), + tickets: new Map(), + } + this.sessions.set(sessionId, session) + this.prune() + return this.loginView(session) + } catch (error) { + await removeFingerprintState(stateDir) + if (error && typeof error === 'object' && 'statusCode' in error) throw error + throw createHttpError( + `创建虎牙扫码会话失败:${error instanceof Error ? error.message : String(error)}`, + { statusCode: 502, errorCode: 'huya_native_login_create_failed' }, + ) + } + } + + async getLoginSession(sessionId: string): Promise { + return this.withLock(sessionId, async () => { + const session = this.requireSession(sessionId) + if ( + session.status === 'authenticated' || + session.status === 'failed' || + session.status === 'expired' + ) { + return this.loginView(session) + } + if (session.expiresAtMs <= this.now()) { + session.status = 'expired' + session.message = '登录二维码已过期,请重新获取' + return this.loginView(session) + } + const response = await session.qr.call('/qrLgn/tryQrLogin', '70003', { + qrId: session.qrid, + remember: '1', + domainList: '', + behavior: session.behavior, + page: session.page, + }) + const data = response.data && typeof response.data === 'object' ? response.data : {} + const stage = extractInt(data.stage) + if (stage >= 2) { + await this.finishLogin(session, data) + } else if (stage === 1) { + session.status = 'scanned' + session.message = '已扫码,请在虎牙 App 确认登录' + } else { + session.status = 'waiting_scan' + session.message = '等待使用虎牙 App 扫码' + } + return this.loginView(session) + }) + } + + async startBinding( + sessionId: string, + options: { forceRebind?: boolean } = {}, + ): Promise { + return this.withLock(sessionId, async () => { + const session = this.requireAuthenticatedSession(sessionId) + const { bindActId, outerActId, roomPid } = configValues() + const rpc = new HuyaRpcClient({ fetchImpl: this.fetchImpl, timeoutMs: this.rpcTimeoutMs }) + const roleResponse = await rpc.checkUserBindGameAccount({ + uid: session.uid, + cookie: session.cookie, + bindActId, + outerActId, + }) + const role = parseRole(roleResponse) + const hasExistingBinding = hasExistingHuyaBinding(roleResponse) + session.binding.hasExistingBinding = hasExistingBinding + if (role.role && !options.forceRebind) { + this.markRoleReady(session, role, hasExistingBinding && !session.binding.rebindRequested) + if (session.binding.rebindRequested) { + session.binding.message = '已识别待换绑角色,请确认换绑' + } + return this.bindingView(session) + } + if (!roleResponse || roleResponse.status !== 200) { + throw createHttpError(roleResponse?.msg || '查询虎牙绑定状态失败', { + statusCode: 502, + errorCode: 'huya_bind_query_failed', + }) + } + const liveLink = await rpc.getLiveLinkParam({ + uid: session.uid, + cookie: session.cookie, + bindActId, + outerActId: extractInt(outerActId), + gameAuthScene: roleResponse.gameAuthScene, + }) + if (!liveLink || liveLink.status !== 200) { + throw createHttpError(liveLink?.msg || '获取绑定二维码参数失败', { + statusCode: 502, + errorCode: 'huya_livelink_param_failed', + }) + } + const profileResponse = await rpc.getUserProfileBatch({ + uid: session.uid, + cookie: session.cookie, + targetUids: [session.uid], + }) + const profile = profileResponse?.profiles[0] + const nickname = profile?.nick || profile?.passport || session.nickname + const avatar = profile?.avatar || '' + const redirectUrl = + 'https://zt.huya.com/b02faae1/pc/index.html' + + `?sourceId=yellowcarlist&pid=${roomPid}&anchorUid=${roomPid}&roomid=30596253` + const urls = buildBindUrls({ + livelinkParam: liveLink.livelinkParam, + bindActId, + gameAuthScene: roleResponse.gameAuthScene, + nickName: nickname, + faceUrl: avatar, + redirectUrl, + }) + const mini = await getLiveLinkMiniQrcode(urls.qrUrl, { + fetchImpl: this.fetchImpl, + timeoutMs: this.rpcTimeoutMs, + }) + if (!mini) { + throw createHttpError('绑定小程序码获取失败', { + statusCode: 502, + errorCode: 'huya_bind_qrcode_failed', + }) + } + if (options.forceRebind) { + session.binding.rebindRequested = true + session.binding.rebindScanned = false + session.binding.baselineRoleKey = bindingRoleKey(role) + } + session.binding.status = 'qr_pending' + session.binding.qrImage = mini.image + session.binding.qrToken = mini.token + session.binding.expiresAtMs = this.now() + BINDING_QR_TTL_MS + session.binding.message = options.forceRebind + ? '请使用虎牙 App 扫码选择需要换绑的游戏角色' + : '请使用虎牙 App 扫码绑定游戏角色' + return this.bindingView(session) + }) + } + + async pollBinding(sessionId: string): Promise { + return this.withLock(sessionId, async () => { + const session = this.requireAuthenticatedSession(sessionId) + const { bindActId, outerActId } = configValues() + let qrCompleted = false + if (['qr_pending', 'scanned'].includes(session.binding.status) && session.binding.qrToken) { + const qrStatus = await getLiveLinkQrcodeStatus(session.binding.qrToken, { + fetchImpl: this.fetchImpl, + timeoutMs: this.rpcTimeoutMs, + }) + if (qrStatus) { + if (qrStatus.isExpired || qrStatus.isFailure) { + session.binding.status = 'expired' + session.binding.message = '绑定二维码已过期,请重新获取' + return this.bindingView(session) + } + if (qrStatus.isScan) { + session.binding.status = 'scanned' + session.binding.message = '已扫码,等待绑定完成' + } + if (qrStatus.isScan || qrStatus.isCompleted) { + session.binding.rebindScanned = true + } + qrCompleted = qrStatus.isCompleted + } + } + if (session.binding.rebindRequested && !session.binding.rebindScanned) { + return this.bindingView(session) + } + const rpc = new HuyaRpcClient({ fetchImpl: this.fetchImpl, timeoutMs: this.rpcTimeoutMs }) + const response = await rpc.checkUserBindGameAccount({ + uid: session.uid, + cookie: session.cookie, + bindActId, + outerActId, + }) + if (!response || response.status !== 200) { + session.binding.status = 'failed' + session.binding.message = response?.msg || '查询绑定角色失败' + return this.bindingView(session) + } + const role = parseRole(response) + const hasExistingBinding = hasExistingHuyaBinding(response) + session.binding.hasExistingBinding = hasExistingBinding + if (role.role) { + const rebindRequested = session.binding.rebindRequested + const roleKey = bindingRoleKey(role) + const changedRole = + !session.binding.baselineRoleKey || roleKey !== session.binding.baselineRoleKey + if (rebindRequested && !changedRole) { + if (qrCompleted) { + session.binding.rebindRequested = false + session.binding.rebindScanned = false + session.binding.baselineRoleKey = '' + this.markRoleReady(session, role, hasExistingBinding) + session.binding.message = '扫码后仍识别到原绑定角色,请确认使用或重新换绑' + } else { + session.binding.status = 'scanned' + session.binding.message = '已扫码,正在等待换绑角色生效' + } + return this.bindingView(session) + } + this.markRoleReady(session, role, hasExistingBinding && !rebindRequested) + if (rebindRequested) { + session.binding.message = '已识别换绑角色,请确认换绑' + } + } else if (!['scanned', 'expired', 'failed'].includes(session.binding.status)) { + session.binding.status = 'qr_pending' + session.binding.message = '等待扫码绑定游戏角色' + } + return this.bindingView(session) + }) + } + + async confirmBinding(sessionId: string): Promise { + return this.withLock(sessionId, async () => { + const session = this.requireAuthenticatedSession(sessionId) + const { bindActId, outerActId } = configValues() + const rpc = new HuyaRpcClient({ fetchImpl: this.fetchImpl, timeoutMs: this.rpcTimeoutMs }) + const response = await rpc.checkUserBindGameAccount({ + uid: session.uid, + cookie: session.cookie, + bindActId, + outerActId, + }) + const role = parseRole(response) + if (!response || response.status !== 200 || !role.role) { + throw createHttpError('尚未识别到可确认的绑定角色', { + statusCode: 409, + errorCode: 'huya_bind_role_not_ready', + }) + } + const rebindRequested = session.binding.rebindRequested + if ( + rebindRequested && + session.binding.baselineRoleKey && + bindingRoleKey(role) === session.binding.baselineRoleKey + ) { + throw createHttpError('换绑角色尚未生效,请稍后重试', { + statusCode: 409, + errorCode: 'huya_bind_rebind_not_ready', + }) + } + const useExistingBinding = hasExistingHuyaBinding(response) && !rebindRequested + if (!useExistingBinding) { + const confirmed = await rpc.confirmBindActAccount({ + uid: session.uid, + cookie: session.cookie, + bindActId, + outerActId, + }) + if (!confirmed || confirmed.status !== 200) { + throw createHttpError(confirmed?.msg || '确认虎牙绑定失败', { + statusCode: 409, + errorCode: 'huya_bind_confirm_failed', + }) + } + } + this.markRoleReady(session, role, useExistingBinding) + session.binding.status = 'confirmed' + session.binding.hasExistingBinding = true + session.binding.rebindRequested = false + session.binding.rebindScanned = false + session.binding.baselineRoleKey = '' + session.binding.message = useExistingBinding + ? '当前虎牙账号已有绑定角色,已确认直接使用' + : rebindRequested + ? '虎牙角色换绑已确认' + : '虎牙角色绑定已确认' + return this.bindingView(session) + }) + } + + async createBrowserTicket(input: { + sessionId: string + targetUrl?: string + }): Promise { + return this.withLock(input.sessionId, async () => { + const session = this.requireSession(input.sessionId) + if (!session.cookie) { + throw createHttpError('虎牙登录态不存在或已过期', { + statusCode: 404, + errorCode: 'huya_native_credential_not_found', + }) + } + const ticket = `${NATIVE_TICKET_PREFIX}${crypto.randomBytes(32).toString('base64url')}` + const targetUrl = readString(input.targetUrl) || 'https://www.huya.com/' + const expiresAtMs = this.now() + BROWSER_TICKET_TTL_MS + session.tickets.set(ticket, { + ticket, + targetUrl, + cookie: session.cookie, + expiresAtMs, + }) + return { ticket, expiresAt: iso(expiresAtMs), targetUrl } + }) + } + + async consumeBrowserTicket(ticketInput: string): Promise { + this.prune() + const ticket = readString(ticketInput) + for (const session of this.sessions.values()) { + const item = session.tickets.get(ticket) + if (!item) continue + session.tickets.delete(ticket) + if (item.expiresAtMs <= this.now()) { + throw createHttpError('浏览器注入票据不存在或已过期', { + statusCode: 404, + errorCode: 'huya_native_ticket_expired', + }) + } + return { + platform: 'huya', + targetUrl: item.targetUrl, + expiresAt: iso(item.expiresAtMs), + cookies: cookiePairs(item.cookie) + .filter(([name, value]) => name && value) + .map(([name, value]) => ({ + name, + value, + domain: '.huya.com', + path: '/', + secure: true, + })), + } + } + throw createHttpError('浏览器注入票据不存在或已过期', { + statusCode: 404, + errorCode: 'huya_native_ticket_not_found', + }) + } + + async revokeSession(sessionIdInput: string): Promise { + const sessionId = readString(sessionIdInput) + const session = this.sessions.get(sessionId) + if (session) { + session.cookie = '' + session.tickets.clear() + this.sessions.delete(sessionId) + await removeFingerprintState(session.stateDir) + } + } + + private async finishLogin(session: NativeSession, data: Record): Promise { + const biztoken = readString(data.biztoken) + const uid = extractInt(data.uid ?? data.yyuid ?? data.lUid) + if (!biztoken || !uid) { + session.status = 'failed' + session.message = '虎牙扫码已确认,但未返回完整登录凭据' + return + } + const username = readString(data.passport ?? data.udb_passport ?? data.username) + const nickname = readString(data.nickname ?? data.nickName ?? data.nick ?? username) + session.deviceInfo.sdid = session.deviceInfo.sdid || session.sdid + session.deviceInfo.hdid = session.deviceInfo.hdid || session.hdid + try { + let merged = mergeHuyaWebCookie({ + cookie: session.qr.cookieHeader(), + biztoken, + sdid: session.sdid, + hdid: session.hdid, + deviceInfo: session.deviceInfo, + uid, + username: username.startsWith('hy_') ? username : '', + includeTransient: false, + }) + session.qr.setCookies(merged) + await session.qr.verifyCookie() + merged = mergeHuyaWebCookie({ + cookie: session.qr.cookieHeader(), + biztoken, + sdid: session.sdid, + hdid: session.hdid, + deviceInfo: session.deviceInfo, + uid, + username: username.startsWith('hy_') ? username : '', + includeTransient: false, + }) + session.cookie = fillWebCookieFields({ + cookie: merged, + guid: '', + uid, + qimeiFeature: qimeiFeatureFromDeviceProfile(session.deviceInfo), + }) + session.uid = uid + session.nickname = nickname + session.status = 'authenticated' + session.expiresAtMs = this.now() + CREDENTIAL_TTL_MS + session.message = '虎牙登录成功' + } catch (error) { + session.cookie = '' + session.status = 'failed' + session.message = error instanceof Error ? error.message : '虎牙 Cookie 兑换失败' + } + } + + private markRoleReady( + session: NativeSession, + role: { account: string; role: string; channel: string }, + existingBinding = false, + ): void { + session.binding.status = 'role_ready' + session.binding.account = role.account + session.binding.role = role.role + session.binding.channel = role.channel + session.binding.message = existingBinding + ? '当前账号已有绑定角色,请确认直接使用' + : '绑定角色已识别,请确认绑定' + } + + private requireSession(sessionIdInput: string): NativeSession { + this.prune() + const sessionId = readString(sessionIdInput) + const session = this.sessions.get(sessionId) + if (!session) { + throw createHttpError('虎牙登录会话不存在或已过期', { + statusCode: 404, + errorCode: 'huya_native_session_not_found', + }) + } + return session + } + + private requireAuthenticatedSession(sessionIdInput: string): NativeSession { + const session = this.requireSession(sessionIdInput) + if (session.status !== 'authenticated' || !session.cookie) { + throw createHttpError('请先完成虎牙登录', { + statusCode: 409, + errorCode: 'huya_native_login_required', + }) + } + return session + } + + private prune(): void { + const now = this.now() + for (const [sessionId, session] of this.sessions) { + if (session.expiresAtMs <= now) { + session.cookie = '' + session.tickets.clear() + this.sessions.delete(sessionId) + void removeFingerprintState(session.stateDir) + } + } + for (const session of this.sessions.values()) { + for (const [ticket, item] of session.tickets) { + if (item.expiresAtMs <= now) session.tickets.delete(ticket) + } + } + if (this.sessions.size > MAX_SESSIONS) { + const overflow = this.sessions.size - MAX_SESSIONS + for (const [sessionId, session] of Array.from(this.sessions.entries()).slice(0, overflow)) { + session.cookie = '' + session.tickets.clear() + this.sessions.delete(sessionId) + void removeFingerprintState(session.stateDir) + } + } + } + + private loginView(session: NativeSession): ConnectorLoginSession { + return { + sessionId: session.sessionId, + status: session.status, + qrContent: `https://aq.huya.com/r/confirm.html?k=${session.qrid}&id=5002`, + qrImage: session.qrImage, + expiresAt: iso(session.expiresAtMs), + huyaUid: session.uid ? String(session.uid) : '', + nickname: session.nickname, + hasCredential: Boolean(session.cookie), + message: session.message, + } + } + + private bindingView(session: NativeSession): ConnectorBindingSession { + const binding = session.binding + return { + sessionId: session.sessionId, + status: binding.status, + qrImage: binding.qrImage, + qrExpiresAt: binding.expiresAtMs ? iso(binding.expiresAtMs) : '', + bindGameAccount: binding.account, + bindGameRole: binding.role, + bindGameChannel: binding.channel, + hasExistingBinding: binding.hasExistingBinding, + rebindRequested: binding.rebindRequested, + message: binding.message, + } + } + + private async withLock(sessionIdInput: string, action: () => Promise): Promise { + const sessionId = readString(sessionIdInput) + const previous = this.locks.get(sessionId) || Promise.resolve() + let release: () => void = () => undefined + const gate = new Promise((resolve) => { + release = resolve + }) + const queued = previous.then(() => gate) + this.locks.set(sessionId, queued) + await previous.catch(() => undefined) + try { + return await action() + } finally { + release() + if (this.locks.get(sessionId) === queued) this.locks.delete(sessionId) + } + } +} + +export const huyaNativeConnector = new HuyaNativeConnector() +export const HUYA_NATIVE_TICKET_PREFIX = NATIVE_TICKET_PREFIX diff --git a/apps/backend/src/services/semi-auto/huya-native/huya-native.test.ts b/apps/backend/src/services/semi-auto/huya-native/huya-native.test.ts new file mode 100644 index 00000000..3f7e45c8 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/huya-native.test.ts @@ -0,0 +1,190 @@ +import assert from 'node:assert/strict' +import os from 'node:os' +import path from 'node:path' +import test from 'node:test' + +import { buildHuyaLoginContext, ensureHuyaWebCookieIdentity, x64hash128 } from './cookie.js' +import { HuyaNativeConnector } from './huya-native-connector.js' +import { hasExistingHuyaBinding, parseBindStruct } from './huya-rpc.js' + +const BIND_RESP_HEX = + '0a0100c816002a0001100120013a060016002602717136004612e6b3aae6958fe6849fe' + + '79a84e59b9ee5bf86560066000b4a06001612e6b3aae99ba8e585a8e698afe8b08ee8a8' + + '802604e6898b51360be88bb9e69e9c28694f53294600560066000b526a2595806c0b36' + + '0ce5928ce5b9b3e7b2bee88bb1460050070b' + +test('QIMEI x64hash128 与 SDK 向量一致', () => { + assert.equal(x64hash128('', 31), '24700f9f1986800ab4fcc880530dd0ed') + assert.equal(x64hash128('a', 31), 'f8b09930c1df727ef75677a1d6ae5bd6') + assert.equal(x64hash128('abc', 31), '31844fd43df93041e52bcddd13312671') +}) + +test('登录 context 使用网页设备 Cookie 的 guiddata、yamid 和 guid', () => { + const identity = ensureHuyaWebCookieIdentity({ + cookie: + 'udb_guiddata=838ed427bbdb491d8e6f6782addb0364; ' + + '__yamid_new=CBE2807148F00001332411CB1E296A00; ' + + 'guid=0a7dee10017ef16aad0229302a3029e3', + guid: 'ignored-because-existing', + }) + assert.equal( + identity.context, + 'WB-838ed427bbdb491d8e6f6782addb0364-CBE2807148F00001332411CB1E296A00-0a7dee10017ef16aad0229302a3029e3', + ) + assert.equal(buildHuyaLoginContext(identity.cookie), identity.context) + assert.match(identity.cookie, /(?:^|; )udb_appid=5002(?:;|$)/) +}) + +test('真实虎牙绑定响应尾部新增 ZERO 字段仍可解析', () => { + const response = parseBindStruct(Buffer.from(BIND_RESP_HEX, 'hex')) + assert.equal(response.status, 200) + assert.equal(response.gameName, '和平精英') + assert.equal(response.accountData.gameAccount.nick, '泪敏感的回忆') + assert.equal(response.accountData.gameRole.roleName, '泪雨全是谎言') + assert.equal(response.accountData.gameRole.areaName, '手Q') + assert.equal(response.accountData.gameRole.platName, '苹果(iOS)') +}) + +test('已绑定账号和角色时直接使用当前绑定,不再发起换绑', () => { + const response = parseBindStruct(Buffer.from(BIND_RESP_HEX, 'hex')) + assert.equal(hasExistingHuyaBinding(response), true) + + response.accountData.isBindRole = 0 + assert.equal(hasExistingHuyaBinding(response), false) + + response.accountData.isBindRole = 1 + response.status = 500 + assert.equal(hasExistingHuyaBinding(response), false) +}) + +test('内置 Connector 完成扫码、CK 兑换和一次性票据且不泄露 CK', async () => { + const requests: Array<{ url: string; body: string; headers: Record }> = [] + let stage = 0 + let now = Date.now() + const fetchImpl = (async (urlInput: string | URL | Request, init?: RequestInit) => { + const url = String(urlInput) + const body = typeof init?.body === 'string' ? init.body : '' + const headers = Object.fromEntries(new Headers(init?.headers).entries()) + requests.push({ url, body, headers }) + if (url.includes('/web/middle/')) { + return new Response('', { + status: 200, + headers: { 'content-type': 'text/html;charset=UTF-8' }, + }) + } + if (url.endsWith('/qrLgn/getQrId')) { + return new Response(JSON.stringify({ returnCode: 0, data: { qrId: 'qr-test-1' } }), { + status: 200, + headers: { 'content-type': 'application/json' }, + }) + } + if (url.includes('/qrLgn/getQrImg')) { + return new Response(Buffer.from('fake-png'), { + status: 200, + headers: { 'content-type': 'image/png' }, + }) + } + if (url.endsWith('/qrLgn/tryQrLogin')) { + const headers = new Headers({ 'content-type': 'application/json' }) + if (stage >= 2) { + headers.append('set-cookie', 'udb_cred=server-issued-cred; Path=/; Domain=huya.com') + headers.append('set-cookie', 'udb_uid=123456; Path=/; Domain=huya.com') + headers.append('set-cookie', 'yyuid=123456; Path=/; Domain=huya.com') + headers.append('set-cookie', 'udb_passport=hy_123456; Path=/; Domain=huya.com') + headers.append('set-cookie', 'username=hy_123456; Path=/; Domain=huya.com') + } + return new Response( + JSON.stringify({ + returnCode: 0, + data: + stage >= 2 + ? { + stage: 2, + uid: 123456, + passport: 'hy_123456', + nickname: '测试用户', + biztoken: 'secret-biztoken', + } + : { stage }, + }), + { status: 200, headers }, + ) + } + if (url.endsWith('/web/cookie/verify')) { + return new Response(JSON.stringify({ returnCode: 0, data: null }), { + status: 200, + headers: { 'content-type': 'application/json' }, + }) + } + throw new Error(`unexpected request: ${url}`) + }) as typeof fetch + + const connector = new HuyaNativeConnector({ + fetchImpl, + getFingerprint: async () => ({ + sdid: '0UnHUgv0_qmfD4KAKlwzhqTZaMGpYcbggchzyjwi8f6G4SHn50pqpnCn8hbYX2xJ2ahI0jmPutYTHv17Q0HdNPxBBhH9f3lfLj955gZ0iFULWVkn9LtfFJw_Qo4kgKr8OZHDqNnuwg612sGyflFn1dotW4-PHrIqa6GBd1hvMDgYhO03aCkuTa7UwhiUlpluU', + hdid: '28744de42736586c8a20e59b5ce9c5f5146fb5e8', + cookies: { + udb_appid: '5008', + game_did: '4p5Gmgx92o-TZA5lK3bgimTfc3p9Wbw6Vl2', + _qimei_uuid42: '1ab09100209100ee4d631bc545468c6addc489a95a', + __yamid_new: 'CBE2807148F00001332411CB1E296A00', + udb_guiddata: '838ed427bbdb491d8e6f6782addb0364', + guid: '0a7dee10017ef16aad0229302a3029e3', + }, + source: 'fingerprint', + }), + now: () => now, + stateRoot: path.join(os.tmpdir(), 'huya-native-test'), + }) + + const created = await connector.createLoginSession({ taskId: 1, orderNo: 'ORDER-1' }) + assert.equal(created.status, 'waiting_scan') + assert.equal(created.hasCredential, false) + assert.equal( + created.qrImage, + `data:image/png;base64,${Buffer.from('fake-png').toString('base64')}`, + ) + const getQrId = requests.find((item) => item.url.endsWith('/qrLgn/getQrId')) + assert.ok(getQrId) + const envelope = JSON.parse(getQrId.body) as Record + assert.match(String(envelope.sdid), /^csid_[0-9a-f]{32}$/) + assert.equal( + envelope.context, + 'WB-838ed427bbdb491d8e6f6782addb0364-CBE2807148F00001332411CB1E296A00-0a7dee10017ef16aad0229302a3029e3', + ) + assert.equal(getQrId.headers.reqid, envelope.requestId) + + stage = 0 + assert.equal((await connector.getLoginSession(created.sessionId)).status, 'waiting_scan') + stage = 1 + assert.equal((await connector.getLoginSession(created.sessionId)).status, 'scanned') + stage = 2 + const authenticated = await connector.getLoginSession(created.sessionId) + assert.equal(authenticated.status, 'authenticated') + assert.equal(authenticated.huyaUid, '123456') + assert.equal(authenticated.nickname, '测试用户') + assert.equal(JSON.stringify(authenticated).includes('secret-biztoken'), false) + assert.equal(JSON.stringify(authenticated).includes('server-issued-cred'), false) + + const ticket = await connector.createBrowserTicket({ + sessionId: created.sessionId, + targetUrl: 'https://www.huya.com/', + }) + assert.match(ticket.ticket, /^native-ticket-/) + assert.equal(ticket.ticket.includes('secret-biztoken'), false) + const payload = await connector.consumeBrowserTicket(ticket.ticket) + assert.equal(payload.platform, 'huya') + assert.equal( + payload.cookies.find((item) => item.name === 'udb_cred')?.value, + 'server-issued-cred', + ) + await assert.rejects(() => connector.consumeBrowserTicket(ticket.ticket), /不存在或已过期/) + + const expiring = await connector.createBrowserTicket({ sessionId: created.sessionId }) + now += 2 * 60 * 1000 + 1 + await assert.rejects(() => connector.consumeBrowserTicket(expiring.ticket), /不存在或已过期/) + + await connector.revokeSession(created.sessionId) + await assert.rejects(() => connector.getLoginSession(created.sessionId), /不存在或已过期/) +}) diff --git a/apps/backend/src/services/semi-auto/huya-native/huya-rpc.ts b/apps/backend/src/services/semi-auto/huya-native/huya-rpc.ts new file mode 100644 index 00000000..440c55c9 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/huya-rpc.ts @@ -0,0 +1,786 @@ +/** 虎牙扫码登录 JSON 协议、活动绑定 WUP RPC 与 livelink 小程序码。 */ + +import crypto from 'node:crypto' + +import { buildHuyaLoginContext, cookiePairs, cookieValue, normalizeCookiePairs } from './cookie.js' +import { + decodeWupResponse, + encodeWupRequest, + readWupStruct, + TAF_TYPE, + TafReader, + TafWriter, + type TafTypeValue, + type WupResponse, +} from './taf.js' + +export const UDB_BASE = 'https://udblgn.huya.com' +export const CDNWS_HOST = 'cdnws.api.huya.com' +export const LIVELINK_BIND_API_BASE = 'https://livelinkbind.game.qq.com' +export const HTTP_HUYA_UA = 'webh5&0.0.1&websocket&&diypc_52775' +export const PC_UA = + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' + + 'Chrome/149.0.0.0 Safari/537.36' +const APP_SIGN_WEB = '1ce3bf682483d03f146f58232ec10635' +const WEB_USER_AGENT = + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ' + + '(KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36' + +type FetchLike = typeof fetch +type JsonRecord = Record + +export type HuyaQrResponse = JsonRecord & { + data?: JsonRecord + message?: string +} + +export class HuyaCookieJar { + private readonly values = new Map() + + header(): string { + return Array.from(this.values.entries()) + .map(([key, value]) => `${key}=${value}`) + .join('; ') + } + + pairs(): Array<[string, string]> { + return Array.from(this.values.entries()) + } + + clear(): void { + this.values.clear() + } + + set(cookie: string): void { + for (const [key, value] of cookiePairs(cookie)) this.values.set(key, value) + } + + absorb(headers: Headers): void { + const withGetSetCookie = headers as Headers & { getSetCookie?: () => string[] } + const setCookies = + typeof withGetSetCookie.getSetCookie === 'function' + ? withGetSetCookie.getSetCookie() + : splitSetCookieHeader(headers.get('set-cookie') || '') + for (const raw of setCookies) { + const first = String(raw || '').split(';', 1)[0] || '' + const separator = first.indexOf('=') + if (separator <= 0) continue + const key = first.slice(0, separator).trim() + const value = first.slice(separator + 1).trim() + if (!key) continue + if (!value || /max-age=0/i.test(raw)) { + this.values.delete(key) + } else { + this.values.set(key, value) + } + } + } +} + +function splitSetCookieHeader(value: string): string[] { + if (!value) return [] + return value.split(/,(?=\s*[^;,=\s]+=)/g) +} + +function buildHeaders(cookie?: string): Record { + return cookie ? { cookie } : {} +} + +export type HuyaQrRoleOptions = { + sdid: string + cookie?: string + context?: string + fetchImpl?: FetchLike +} + +export class HuyaQrRole { + private readonly jar = new HuyaCookieJar() + private readonly context: string + private readonly guidData: string + private readonly fingerprintSdid: string + private readonly fetchImpl: FetchLike + private activeSdid: string + private readonly pageId: number + private requestCounter: number + + constructor(options: HuyaQrRoleOptions) { + const initialCookie = String(options.cookie || '').trim() + if (initialCookie) this.jar.set(initialCookie) + this.fingerprintSdid = String(options.sdid || '').trim() + // 最新网页登录先用 csid 请求二维码,随后切换到 hydevice 高信任 sdid 轮询。 + this.activeSdid = `csid_${crypto.randomBytes(16).toString('hex')}` + this.fetchImpl = options.fetchImpl || fetch + this.context = + String(options.context || '').trim() || + buildHuyaLoginContext(initialCookie) || + `WB-${crypto.randomUUID().replace(/-/g, '')}-CBC9F93DBEB000011DB11EC02A401BAD-` + this.guidData = + cookieValue(initialCookie, 'udb_guiddata') || crypto.randomBytes(16).toString('hex') + this.pageId = 40_000_000 + Math.floor(Math.random() * 1_000_000) + this.requestCounter = 40_000_000 + Math.floor(Math.random() * 1_000_000) + } + + activateFingerprintSdid(): void { + if (this.fingerprintSdid) this.activeSdid = this.fingerprintSdid + } + + setCookies(cookie: string): void { + this.jar.clear() + this.jar.set(cookie) + } + + cookieHeader(): string { + return this.jar.header() + } + + async bootstrapMiddle(): Promise { + const url = `${UDB_BASE}/web/middle/2.6/${this.pageId}/https/${this.guidData}` + const response = await this.fetchImpl(url, { + method: 'GET', + headers: { + 'user-agent': WEB_USER_AGENT, + accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', + referer: 'https://aq.huya.com/', + ...buildHeaders(this.jar.header()), + }, + signal: AbortSignal.timeout(20_000), + }) + this.jar.absorb(response.headers) + await response.arrayBuffer().catch(() => undefined) + if (!response.ok) throw new Error(`虎牙设备引导接口失败:HTTP ${response.status}`) + } + + async call(path: string, uri: string, data: JsonRecord): Promise { + const requestId = this.requestCounter + const envelope = { + uri, + version: '2.6', + context: this.context, + appId: '5002', + appSign: APP_SIGN_WEB, + authId: '', + sdid: this.activeSdid, + lcid: '2052', + byPass: '3', + requestId: String(requestId), + data, + } + this.requestCounter = requestId + 120 + Math.floor(Math.random() * 281) + const headers: Record = { + 'user-agent': WEB_USER_AGENT, + origin: UDB_BASE, + 'content-type': 'application/json;charset=UTF-8', + accept: '*/*', + context: this.context, + uri, + reqid: String(requestId), + lcid: '2052', + Referer: `${UDB_BASE}/web/middle/2.6/${this.pageId}/https/${this.context.split('-')[1] || ''}`, + ...buildHeaders(this.jar.header()), + } + const response = await this.fetchImpl(`${UDB_BASE}${path}`, { + method: 'POST', + headers, + body: JSON.stringify(envelope), + signal: AbortSignal.timeout(20_000), + }) + this.jar.absorb(response.headers) + const text = await response.text() + if (!response.ok) throw new Error(`虎牙登录接口失败:HTTP ${response.status}`) + try { + return (text ? JSON.parse(text) : {}) as HuyaQrResponse + } catch { + throw new Error('虎牙登录接口返回了无法解析的响应') + } + } + + async getQrImg(qrid: string): Promise { + const response = await this.fetchImpl( + `${UDB_BASE}/qrLgn/getQrImg?k=${encodeURIComponent(qrid)}&appId=5002`, + { + method: 'GET', + headers: { + 'user-agent': WEB_USER_AGENT, + accept: 'image/avif,image/webp,image/apng,image/*,*/*;q=0.8', + referer: 'https://aq.huya.com/', + ...buildHeaders(this.jar.header()), + }, + signal: AbortSignal.timeout(20_000), + }, + ) + this.jar.absorb(response.headers) + if (!response.ok) throw new Error(`虎牙登录二维码图片获取失败:HTTP ${response.status}`) + const contentType = String(response.headers.get('content-type') || 'image/png').split(';', 1)[0] + const buffer = Buffer.from(await response.arrayBuffer()) + if (buffer.length === 0) throw new Error('虎牙登录二维码图片为空') + return `data:${contentType || 'image/png'};base64,${buffer.toString('base64')}` + } + + async verifyCookie(): Promise { + const response = await this.fetchImpl(`${UDB_BASE}/web/cookie/verify`, { + method: 'POST', + headers: { + 'user-agent': WEB_USER_AGENT, + origin: 'https://www.huya.com', + referer: 'https://www.huya.com/', + 'content-type': 'application/json', + accept: 'application/json, text/javascript, */*; q=0.01', + cookie: this.jar.header(), + }, + body: JSON.stringify({ appId: 5002 }), + signal: AbortSignal.timeout(20_000), + }) + this.jar.absorb(response.headers) + if (!response.ok) throw new Error(`虎牙 Cookie 兑换失败:HTTP ${response.status}`) + } +} + +export function webBehavior(page = 'https://www.huya.com/'): { behavior: string; page: string } { + // 2026-11-09 最新 HAR 的扫码请求:来源 Google、当前页虎牙首页、无鼠标轨迹。 + const value = { furl: 'https://www.google.com/', curl: page, user_action: [] } + return { + behavior: encodeURIComponent(JSON.stringify(value)), + page: encodeURIComponent(page), + } +} + +export type HuyaGameAccount = { + openId: string + appId: string + type: string + faceUrl: string + nick: string + accessToken: string + extendInfo: string +} + +export type HuyaGameRole = { + roleId: string + roleName: string + areaName: string + platName: string + partitionName: string + gameSerial: string + extendInfo: string +} + +export type HuyaGameAccountData = { + isBindAccount: number + isBindRole: number + isNeedActCheck: number + gameAccount: HuyaGameAccount + gameRole: HuyaGameRole + changeBindTime: number +} + +export type HuyaBindResponse = { + status: number + msg: string + accountData: HuyaGameAccountData + gameName: string + gameAuthScene: string + changeBindDay: number +} + +/** 已绑定账号和角色时无需再次调用换绑接口,当前角色可直接确认使用。 */ +export function hasExistingHuyaBinding(response: HuyaBindResponse | null): boolean { + if (!response || response.status !== 200) return false + return Boolean(response.accountData.isBindAccount && response.accountData.isBindRole) +} + +export type HuyaConfirmResponse = { status: number; msg: string } +export type HuyaLiveLinkResponse = { + status: number + msg: string + livelinkParam: Record +} +export type HuyaUserProfile = { uid: number; nick: string; avatar: string; passport: string } +export type HuyaUserProfileResponse = { profiles: HuyaUserProfile[] } + +function emptyAccount(): HuyaGameAccount { + return { + openId: '', + appId: '', + type: '', + faceUrl: '', + nick: '', + accessToken: '', + extendInfo: '', + } +} + +function emptyRole(): HuyaGameRole { + return { + roleId: '', + roleName: '', + areaName: '', + platName: '', + partitionName: '', + gameSerial: '', + extendInfo: '', + } +} + +function emptyAccountData(): HuyaGameAccountData { + return { + isBindAccount: 0, + isBindRole: 0, + isNeedActCheck: 0, + gameAccount: emptyAccount(), + gameRole: emptyRole(), + changeBindTime: 0, + } +} + +function parseGameAccount(reader: TafReader): HuyaGameAccount { + return { + openId: reader.readString(0), + appId: reader.readString(1), + type: reader.readString(2), + faceUrl: reader.readString(3), + nick: reader.readString(4), + accessToken: reader.readString(5), + extendInfo: reader.readString(6), + } +} + +function parseGameRole(reader: TafReader): HuyaGameRole { + return { + roleId: reader.readString(0), + roleName: reader.readString(1), + areaName: reader.readString(2), + platName: reader.readString(3), + partitionName: reader.readString(4), + gameSerial: reader.readString(5), + extendInfo: reader.readString(6), + } +} + +function parseGameAccountData(reader: TafReader): HuyaGameAccountData { + return { + isBindAccount: reader.readInt32(0), + isBindRole: reader.readInt32(1), + isNeedActCheck: reader.readInt32(2), + gameAccount: reader.readStruct(3, parseGameAccount) || emptyAccount(), + gameRole: reader.readStruct(4, parseGameRole) || emptyRole(), + changeBindTime: reader.readInt32(5), + } +} + +function parseBindResponse(reader: TafReader): HuyaBindResponse { + return { + status: reader.readInt32(0), + msg: reader.readString(1), + accountData: reader.readStruct(2, parseGameAccountData) || emptyAccountData(), + gameName: reader.readString(3), + gameAuthScene: reader.readString(4), + changeBindDay: reader.readInt32(5), + } +} + +/** 解析 checkUserBindGameAccount 的 tRsp 裸结构,供集成回归和故障排查使用。 */ +export function parseBindStruct(buffer: Buffer): HuyaBindResponse { + const reader = new TafReader(buffer) + const [tag, dataType] = reader.readHead() + if (tag !== 0 || dataType !== TAF_TYPE.STRUCT_BEGIN) { + throw new Error('虎牙绑定响应不是有效的 TAF 结构体') + } + return reader.readStructBody(parseBindResponse) +} + +function parseConfirmResponse(reader: TafReader): HuyaConfirmResponse { + return { status: reader.readInt32(0), msg: reader.readString(1) } +} + +function parseLiveLinkResponse(reader: TafReader): HuyaLiveLinkResponse { + return { + status: reader.readInt32(0), + msg: reader.readString(1), + livelinkParam: reader.readMap(2), + } +} + +function parseProfile(reader: TafReader): HuyaUserProfile { + let uid = 0 + let nick = '' + let avatar = '' + let passport = '' + while (reader.remaining > 0) { + const [tag, dataType] = reader.peekHead() + if (dataType === TAF_TYPE.STRUCT_END) { + break + } + reader.readHead() + if (tag === 0) uid = reader.readIntValue(dataType) + else if (tag === 1) nick = reader.readStringValue(dataType) + else if (tag === 2) avatar = reader.readStringValue(dataType) + else if (tag === 17) passport = reader.readStringValue(dataType) + else reader.skipValue(dataType) + } + return { uid, nick, avatar, passport } +} + +function parseProfileBatch(reader: TafReader): HuyaUserProfileResponse { + const profiles = + reader.readList(0, (itemReader, dataType) => { + if (dataType !== TAF_TYPE.STRUCT_BEGIN) { + itemReader.skipValue(dataType) + return null + } + return itemReader.readStructBody((envelopeReader) => { + const profile = envelopeReader.readStruct(0, parseProfile) + return profile || { uid: 0, nick: '', avatar: '', passport: '' } + }) + }) || [] + return { profiles } +} + +export type HuyaRpcClientOptions = { + fetchImpl?: FetchLike + timeoutMs?: number +} + +export class HuyaRpcClient { + private readonly fetchImpl: FetchLike + private readonly timeoutMs: number + + constructor(options: HuyaRpcClientOptions = {}) { + this.fetchImpl = options.fetchImpl || fetch + this.timeoutMs = Math.max(1000, options.timeoutMs || 15_000) + } + + async checkUserBindGameAccount(input: { + uid: number + cookie: string + bindActId: number + outerActId: string + isUseOuterActId?: number + gid?: number + scene?: string + }): Promise { + const response = await this.callRpc( + 'webActUI', + 'checkUserBindGameAccount', + input.uid, + input.cookie, + (writer) => { + this.writeActivityUser(writer, input.uid, input.cookie) + writer.writeInt32(1, input.gid || 0) + writer.writeString(2, input.outerActId || '') + writer.writeInt32(3, 0) + writer.writeString(4, input.scene || '') + writer.writeInt32(5, input.bindActId || 0) + writer.writeInt32(6, input.isUseOuterActId ?? 1) + }, + ) + return response ? readWupStruct(response, parseBindResponse) : null + } + + async confirmBindActAccount(input: { + uid: number + cookie: string + bindActId: number + outerActId: string + gid?: number + }): Promise { + const response = await this.callRpc( + 'webActUI', + 'confirmBindActAccount', + input.uid, + input.cookie, + (writer) => { + this.writeActivityUser(writer, input.uid, input.cookie) + writer.writeInt32(1, input.gid || 0) + writer.writeString(2, input.outerActId || '') + writer.writeInt32(3, input.bindActId || 0) + }, + ) + return response ? readWupStruct(response, parseConfirmResponse) : null + } + + async getLiveLinkParam(input: { + uid: number + cookie: string + bindActId: number + outerActId: number + gameAuthScene?: string + }): Promise { + const response = await this.callRpc( + 'webActUI', + 'getLiveLinkParam', + input.uid, + input.cookie, + (writer) => { + this.writeActivityUser(writer, input.uid, input.cookie) + writer.writeInt32(1, 0) + writer.writeInt32(2, input.outerActId || 0) + writer.writeString(3, input.gameAuthScene || '') + writer.writeString(4, '') + writer.writeInt32(5, input.bindActId || 0) + }, + ) + return response ? readWupStruct(response, parseLiveLinkResponse) : null + } + + async getUserProfileBatch(input: { + uid: number + cookie: string + targetUids: number[] + }): Promise { + const targetUids = input.targetUids.map((item) => Math.trunc(item)).filter((item) => item > 0) + if (targetUids.length === 0) return null + const response = await this.callRpc( + 'huyauserui', + 'getUserProfileBatch', + input.uid, + input.cookie, + (writer) => { + this.writeActivityUser(writer, 0, '') + writer.writeList(1, targetUids, (itemWriter, item) => itemWriter.writeInt64(0, item)) + }, + ) + return response ? readWupStruct(response, parseProfileBatch) : null + } + + private async callRpc( + servant: string, + func: string, + uid: number, + cookie: string, + writeRequest: (writer: TafWriter) => void, + ): Promise { + const body = encodeWupRequest({ servant, func, requestId: 1, writeRequest }) + const baseinfo = generateRpcBaseinfo(uid, cookie) + const response = await this.fetchImpl(`https://${CDNWS_HOST}/?baseinfo=${baseinfo}`, { + method: 'POST', + headers: { + 'user-agent': PC_UA, + origin: 'https://zt.huya.com', + referer: 'https://zt.huya.com/', + 'content-type': 'application/octet-stream', + 'accept-language': 'zh-CN,zh;q=0.9', + }, + body: new Uint8Array(body), + signal: AbortSignal.timeout(this.timeoutMs), + }) + if (!response.ok) throw new Error(`虎牙 WUP 请求失败:HTTP ${response.status}`) + const buffer = Buffer.from(await response.arrayBuffer()) + return decodeWupResponse(buffer) + } + + private writeActivityUser(writer: TafWriter, uid: number, cookie: string): void { + writer.writeStruct(0, (userWriter) => { + userWriter.writeInt64(0, uid) + userWriter.writeString(1, '') + userWriter.writeString(2, '') + userWriter.writeString(3, HTTP_HUYA_UA) + userWriter.writeString(4, normalizeHuyaCookie(cookie)) + userWriter.writeInt32(5, 0) + userWriter.writeString(6, '') + userWriter.writeString(7, '') + }) + } +} + +function firstCookieValue(cookie: string, key: string): string { + for (const [itemKey, itemValue] of cookiePairs(cookie)) { + if (itemKey === key && itemValue) return itemValue + } + return '' +} + +export function resolveCookieGuid(cookie: string): string { + const guid = firstCookieValue(cookie, 'guid') + if (guid) return guid + const udbGuid = firstCookieValue(cookie, 'udb_guiddata') + if (udbGuid) return udbGuid.slice(0, 32) + const seed = ['yyuid', 'udb_uid', 'udb_passport', 'username', 'udb_biztoken'] + .map((key) => firstCookieValue(cookie, key)) + .filter(Boolean) + .join('|') + return seed ? crypto.createHash('sha256').update(seed).digest('hex').slice(0, 32) : '' +} + +export function normalizeHuyaCookie(cookie: string): string { + if (!cookie) return '' + const pairs = cookiePairs(normalizeCookiePairs(cookiePairs(cookie))).filter( + ([key]) => key !== 'huya_ua', + ) + if (!pairs.some(([key]) => key === 'guid')) { + const guid = resolveCookieGuid(cookie) + if (guid) pairs.push(['guid', guid]) + } + return normalizeCookiePairs([['huya_ua', HTTP_HUYA_UA], ...pairs]) +} + +function generateRpcBaseinfo(uid: number, cookie: string): string { + const normalizedCookie = normalizeHuyaCookie(cookie) + const guid = resolveCookieGuid(cookie) + const traceId = crypto.randomBytes(8).toString('hex') + const writer = new TafWriter() + writer.writeInt64(0, uid) + writer.writeString(1, guid) + writer.writeString(2, HTTP_HUYA_UA) + writer.writeString(3, 'HUYA&ZH&2052') + writer.writeString(4, '') + writer.writeString(5, '') + writer.writeInt32(6, 0) + writer.writeString(7, '') + writer.writeString(8, normalizedCookie) + writer.writeString(9, `${traceId}:${traceId}:0:0`) + writer.writeMap(10, {}) + return encodeURIComponent(writer.toBuffer().toString('base64')) +} + +export function livelinkQrcodeImageSrc(qrcode: string): string { + const text = String(qrcode || '').trim() + if (!text) return '' + const lower = text.toLowerCase() + if ( + lower.startsWith('https://') || + lower.startsWith('http://') || + lower.startsWith('data:image/') + ) { + return text + } + return `data:${text.startsWith('iVBOR') ? 'image/png' : 'image/jpeg'};base64,${text}` +} + +export async function getLiveLinkMiniQrcode( + bindPageUrl: string, + options: { fetchImpl?: FetchLike; timeoutMs?: number } = {}, +): Promise<{ image: string; token: string } | null> { + const url = new URL(bindPageUrl) + const query = url.search.slice(1) + const params = url.searchParams + const suffix = Array.from( + { length: 8 }, + () => 'abcdefghijklmnopqrstuvwxyz0123456789'[Math.floor(Math.random() * 36)], + ).join('') + const sessionId = `${Math.floor(Date.now() / 1000)}_${suffix}` + const fetchImpl = options.fetchImpl || fetch + const response = await fetchImpl(`${LIVELINK_BIND_API_BASE}/api/qrcode/getMiniAppQrcode`, { + method: 'POST', + headers: { + 'user-agent': PC_UA, + origin: 'https://livelink.qq.com', + referer: 'https://livelink.qq.com/', + 'content-type': 'application/json;charset=UTF-8', + accept: 'application/json, text/plain, */*', + 'accept-language': 'zh-CN,zh;q=0.9', + }, + body: JSON.stringify({ queryString: `${query}&sessionId=${sessionId}` }), + signal: AbortSignal.timeout(options.timeoutMs || 15_000), + }) + if (!response.ok) return null + const payload = (await response.json().catch(() => null)) as { + iRet?: number + jData?: { qrcode?: string; qrcodeToken?: string } + } | null + if (!payload || payload.iRet !== 0) return null + const image = livelinkQrcodeImageSrc(String(payload.jData?.qrcode || '')) + if (!image) return null + return { image, token: String(payload.jData?.qrcodeToken || '') } +} + +export async function getLiveLinkQrcodeStatus( + token: string, + options: { fetchImpl?: FetchLike; timeoutMs?: number } = {}, +): Promise<{ + isScan: boolean + isExpired: boolean + isCompleted: boolean + isFailure: boolean +} | null> { + const normalized = String(token || '').trim() + if (!normalized) return null + const fetchImpl = options.fetchImpl || fetch + const response = await fetchImpl(`${LIVELINK_BIND_API_BASE}/api/qrcode/poolingQrcodeStatus`, { + method: 'POST', + headers: { + 'user-agent': PC_UA, + origin: 'https://livelink.qq.com', + referer: 'https://livelink.qq.com/', + 'content-type': 'application/json;charset=UTF-8', + accept: 'application/json, text/plain, */*', + 'accept-language': 'zh-CN,zh;q=0.9', + }, + body: JSON.stringify({ qrcodeToken: normalized }), + signal: AbortSignal.timeout(options.timeoutMs || 15_000), + }) + if (!response.ok) return null + const payload = (await response.json().catch(() => null)) as { + iRet?: number + jData?: { + isScan?: boolean + isExpired?: boolean + isCompleted?: boolean + isFailure?: boolean + } + } | null + if (!payload || payload.iRet !== 0) return null + return { + isScan: Boolean(payload.jData?.isScan), + isExpired: Boolean(payload.jData?.isExpired), + isCompleted: Boolean(payload.jData?.isCompleted), + isFailure: Boolean(payload.jData?.isFailure), + } +} + +export function buildBindUrls(input: { + livelinkParam: Record + bindActId: number + gameAuthScene?: string + nickName?: string + faceUrl?: string + redirectUrl?: string +}): { + actionUrl: string + qrUrl: string + pcUrl: string + huyaContainerUrl: string + exchangeQqCoinUrl: string +} { + const bindQuery: Record = { + t: input.livelinkParam.t || '', + gameIdList: input.livelinkParam.gameIdList || '', + actId: input.livelinkParam.actId || '', + livePlatId: input.livelinkParam.livePlatId || '', + sig: input.livelinkParam.sig || '', + code: input.livelinkParam.code || '', + faceUrl: encodeURIComponent(input.faceUrl || ''), + nickName: encodeURIComponent(input.nickName || ''), + } + const joinQuery = (query: Record) => + Object.entries(query) + .map(([key, value]) => `${key}=${value}`) + .join('&') + const bindQueryText = joinQuery(bindQuery) + const miniPath = encodeURIComponent(`/pages/gameAccountBind/index?${bindQueryText}`) + const actionUrl = + 'https://m.huya.com?hyaction=launchweixinminiprogram' + + `&path=${miniPath}&username=gh_49af166706ae` + const pcQuery = { ...bindQuery, redirectUrl: encodeURIComponent(input.redirectUrl || '') } + const pcUrl = `https://livelink.qq.com/act/a20200527midgroupage/pc/?${joinQuery(pcQuery)}` + const huyaParams = new URLSearchParams({ + bActId: String(input.bindActId || 0), + isUseOuterActId: '1', + delayclose: '1000', + from: 'diy', + }) + if (input.gameAuthScene) huyaParams.set('gameAuthScene', input.gameAuthScene) + const huyaBase = 'https://hd.huya.com/h5/livelinkV3/index.html' + const huyaContainerUrl = `${huyaBase}?${huyaParams.toString()}` + const exchangeParams = new URLSearchParams(huyaParams) + exchangeParams.set('extendParm', 'type=qqCoinDeliver') + return { + actionUrl, + qrUrl: pcUrl, + pcUrl, + huyaContainerUrl, + exchangeQqCoinUrl: `${huyaBase}?${exchangeParams.toString()}`, + } +} + +export type { WupResponse, TafTypeValue } diff --git a/apps/backend/src/services/semi-auto/huya-native/taf.ts b/apps/backend/src/services/semi-auto/huya-native/taf.ts new file mode 100644 index 00000000..c9bc08f7 --- /dev/null +++ b/apps/backend/src/services/semi-auto/huya-native/taf.ts @@ -0,0 +1,642 @@ +/** + * 虎牙 TAF/WUP 二进制协议的最小实现。 + * + * 只覆盖半自动履约需要的 JSON 登录与活动绑定 RPC,不引入 WSS、商城下单等 + * 无关协议。编码规则与 live-hub-py 的 core/huya/taf_protocol.py、wup_protocol.py + * 保持一致。 + */ + +export const TAF_TYPE = { + INT8: 0x00, + INT16: 0x01, + INT32: 0x02, + INT64: 0x03, + FLOAT: 0x04, + DOUBLE: 0x05, + STRING1: 0x06, + STRING4: 0x07, + MAP: 0x08, + LIST: 0x09, + STRUCT_BEGIN: 0x0a, + STRUCT_END: 0x0b, + ZERO: 0x0c, + SIMPLE_LIST: 0x0d, +} as const + +export type TafTypeValue = (typeof TAF_TYPE)[keyof typeof TAF_TYPE] + +export class TafWriter { + private readonly chunks: Buffer[] = [] + + toBuffer(): Buffer { + return Buffer.concat(this.chunks) + } + + writeHead(tag: number, dataType: TafTypeValue): void { + if (tag < 15) { + this.chunks.push(Buffer.from([(tag << 4) | dataType])) + return + } + this.chunks.push(Buffer.from([0xf0 | dataType, tag])) + } + + writeInt8(tag: number, value: number): void { + if (value === 0) { + this.writeHead(tag, TAF_TYPE.ZERO) + return + } + const buffer = Buffer.allocUnsafe(1) + buffer.writeInt8(value, 0) + this.writeHead(tag, TAF_TYPE.INT8) + this.chunks.push(buffer) + } + + writeInt16(tag: number, value: number): void { + if (value >= -128 && value <= 127) { + this.writeInt8(tag, value) + return + } + const buffer = Buffer.allocUnsafe(2) + buffer.writeInt16BE(value, 0) + this.writeHead(tag, TAF_TYPE.INT16) + this.chunks.push(buffer) + } + + writeInt32(tag: number, value: number): void { + if (value >= -32768 && value <= 32767) { + this.writeInt16(tag, value) + return + } + const buffer = Buffer.allocUnsafe(4) + buffer.writeInt32BE(value, 0) + this.writeHead(tag, TAF_TYPE.INT32) + this.chunks.push(buffer) + } + + writeInt64(tag: number, value: number | bigint): void { + const normalized = typeof value === 'bigint' ? value : BigInt(Math.trunc(value)) + if (normalized >= -2147483648n && normalized <= 2147483647n) { + this.writeInt32(tag, Number(normalized)) + return + } + const buffer = Buffer.allocUnsafe(8) + buffer.writeBigInt64BE(normalized, 0) + this.writeHead(tag, TAF_TYPE.INT64) + this.chunks.push(buffer) + } + + writeString(tag: number, value: string): void { + const encoded = Buffer.from(String(value ?? ''), 'utf8') + if (encoded.length > 255) { + const length = Buffer.allocUnsafe(4) + length.writeUInt32BE(encoded.length, 0) + this.writeHead(tag, TAF_TYPE.STRING4) + this.chunks.push(length, encoded) + return + } + this.writeHead(tag, TAF_TYPE.STRING1) + this.chunks.push(Buffer.from([encoded.length]), encoded) + } + + writeBytes(tag: number, value: Uint8Array): void { + this.writeHead(tag, TAF_TYPE.SIMPLE_LIST) + this.writeHead(0, TAF_TYPE.INT8) + this.writeInt32(0, value.byteLength) + this.chunks.push(Buffer.from(value)) + } + + writeBoolean(tag: number, value: boolean): void { + this.writeInt8(tag, value ? 1 : 0) + } + + writeStructBegin(tag: number): void { + this.writeHead(tag, TAF_TYPE.STRUCT_BEGIN) + } + + writeStructEnd(): void { + this.writeHead(0, TAF_TYPE.STRUCT_END) + } + + writeStruct(tag: number, writeBody: (writer: TafWriter) => void): void { + this.writeStructBegin(tag) + writeBody(this) + this.writeStructEnd() + } + + writeMap(tag: number, value: Record): void { + this.writeHead(tag, TAF_TYPE.MAP) + this.writeInt32(0, Object.keys(value).length) + for (const [key, item] of Object.entries(value)) { + this.writeString(0, key) + this.writeString(1, item) + } + } + + writeList(tag: number, values: T[], writeItem: (writer: TafWriter, item: T) => void): void { + this.writeHead(tag, TAF_TYPE.LIST) + this.writeInt32(0, values.length) + for (const value of values) { + writeItem(this, value) + } + } +} + +export class TafReader { + private offset = 0 + + constructor(private readonly buffer: Buffer) {} + + get position(): number { + return this.offset + } + + get remaining(): number { + return this.buffer.length - this.offset + } + + peekHead(): [number, TafTypeValue] { + const position = this.offset + try { + return this.readHead() + } finally { + this.offset = position + } + } + + readHead(): [number, TafTypeValue] { + this.require(1) + const first = this.buffer[this.offset++]! + let tag = (first >> 4) & 0x0f + const dataType = (first & 0x0f) as TafTypeValue + if (tag === 15) { + this.require(1) + tag = this.buffer[this.offset++]! + } + return [tag, dataType] + } + + readIntValue(dataType: TafTypeValue): number { + if (dataType === TAF_TYPE.ZERO) return 0 + if (dataType === TAF_TYPE.INT8) { + this.require(1) + return this.buffer.readInt8(this.offset++) + } + if (dataType === TAF_TYPE.INT16) { + this.require(2) + const value = this.buffer.readInt16BE(this.offset) + this.offset += 2 + return value + } + if (dataType === TAF_TYPE.INT32) { + this.require(4) + const value = this.buffer.readInt32BE(this.offset) + this.offset += 4 + return value + } + if (dataType === TAF_TYPE.INT64) { + this.require(8) + const value = this.buffer.readBigInt64BE(this.offset) + this.offset += 8 + return Number(value) + } + throw new Error(`TAF 期望整数,实际 0x${dataType.toString(16)}`) + } + + readInt32(tag: number, defaultValue = 0): number { + const dataType = this.findTag(tag) + return dataType === null ? defaultValue : this.readIntValue(dataType) + } + + readInt64(tag: number, defaultValue = 0): number { + return this.readInt32(tag, defaultValue) + } + + readBoolean(tag: number, defaultValue = false): boolean { + return this.readInt32(tag, defaultValue ? 1 : 0) !== 0 + } + + readString(tag: number, defaultValue = ''): string { + const dataType = this.findTag(tag) + if (dataType === null) return defaultValue + return this.readStringValue(dataType) + } + + readStringValue(dataType: TafTypeValue): string { + if (dataType === TAF_TYPE.STRING1) { + this.require(1) + const length = this.buffer[this.offset++]! + this.require(length) + const value = this.buffer.toString('utf8', this.offset, this.offset + length) + this.offset += length + return value + } + if (dataType === TAF_TYPE.STRING4) { + this.require(4) + const length = this.buffer.readUInt32BE(this.offset) + this.offset += 4 + this.require(length) + const value = this.buffer.toString('utf8', this.offset, this.offset + length) + this.offset += length + return value + } + throw new Error(`TAF 期望字符串,实际 0x${dataType.toString(16)}`) + } + + readBytes(tag: number, defaultValue = Buffer.alloc(0)): Buffer { + const dataType = this.findTag(tag) + if (dataType === null) return defaultValue + if (dataType !== TAF_TYPE.SIMPLE_LIST) { + throw new Error(`TAF 期望字节数组,实际 0x${dataType.toString(16)}`) + } + this.readHead() + const length = this.readIntLength() + this.require(length) + const value = this.buffer.subarray(this.offset, this.offset + length) + this.offset += length + return value + } + + readBytesRaw(length: number): Buffer { + this.require(length) + const value = this.buffer.subarray(this.offset, this.offset + length) + this.offset += length + return value + } + + readMap(tag: number): Record { + const dataType = this.findTag(tag) + if (dataType === null) return {} + if (dataType !== TAF_TYPE.MAP) { + throw new Error(`TAF 期望 map,实际 0x${dataType.toString(16)}`) + } + const count = this.readIntLength() + const result: Record = {} + for (let index = 0; index < count; index += 1) { + const [, keyType] = this.readHead() + const key = this.readStringValue(keyType) + const [, valueType] = this.readHead() + const value = this.readValue(valueType) + result[key] = value === null || value === undefined ? '' : String(value) + } + return result + } + + readList( + tag: number, + readItem: (reader: TafReader, dataType: TafTypeValue) => T | null, + ): T[] | null { + const dataType = this.findTag(tag) + if (dataType === null) return null + if (dataType !== TAF_TYPE.LIST) { + throw new Error(`TAF 期望 list,实际 0x${dataType.toString(16)}`) + } + const count = this.readIntLength() + const values: T[] = [] + for (let index = 0; index < count; index += 1) { + const [, itemType] = this.readHead() + const item = readItem(this, itemType) + if (item !== null) values.push(item) + } + return values + } + + readIntLength(): number { + const [, dataType] = this.readHead() + return this.readIntValue(dataType) + } + + readValue( + dataType: TafTypeValue, + ): string | number | boolean | Buffer | unknown[] | Record | null { + if ( + dataType === TAF_TYPE.ZERO || + dataType === TAF_TYPE.INT8 || + dataType === TAF_TYPE.INT16 || + dataType === TAF_TYPE.INT32 || + dataType === TAF_TYPE.INT64 + ) { + return this.readIntValue(dataType) + } + if (dataType === TAF_TYPE.STRING1 || dataType === TAF_TYPE.STRING4) { + return this.readStringValue(dataType) + } + if (dataType === TAF_TYPE.FLOAT) { + this.require(4) + const value = this.buffer.readFloatBE(this.offset) + this.offset += 4 + return value + } + if (dataType === TAF_TYPE.DOUBLE) { + this.require(8) + const value = this.buffer.readDoubleBE(this.offset) + this.offset += 8 + return value + } + if (dataType === TAF_TYPE.SIMPLE_LIST) { + this.readHead() + const length = this.readIntLength() + this.require(length) + const value = this.buffer.subarray(this.offset, this.offset + length) + this.offset += length + return value + } + if (dataType === TAF_TYPE.LIST) { + const count = this.readIntLength() + const values: unknown[] = [] + for (let index = 0; index < count; index += 1) { + const [, itemType] = this.readHead() + values.push(this.readValue(itemType)) + } + return values + } + if (dataType === TAF_TYPE.MAP) { + return this.readMapBody() + } + if (dataType === TAF_TYPE.STRUCT_BEGIN) { + this.skipStructBody() + return null + } + this.skipField(dataType) + return null + } + + readStruct(tag: number, readBody: (reader: TafReader) => T): T | null { + const dataType = this.findTag(tag) + if (dataType === null) return null + if (dataType !== TAF_TYPE.STRUCT_BEGIN) { + throw new Error(`TAF 期望结构体,实际 0x${dataType.toString(16)}`) + } + return this.readStructBody(readBody) + } + + readStructBody(readBody: (reader: TafReader) => T): T { + const value = readBody(this) + this.skipToStructEnd() + const [, dataType] = this.readHead() + if (dataType !== TAF_TYPE.STRUCT_END) { + throw new Error(`TAF 期望结构体结束,实际 0x${dataType.toString(16)}`) + } + return value + } + + skipToStructEnd(): number { + let skipped = 0 + while (skipped < 128) { + const position = this.offset + const [, dataType] = this.readHead() + if (dataType === TAF_TYPE.STRUCT_END) { + this.offset = position + return skipped + } + this.skipField(dataType) + skipped += 1 + } + throw new Error('TAF 结构体尾部未解析字段过多') + } + + skipValue(dataType: TafTypeValue): void { + this.skipField(dataType) + } + + private readMapBody(): Record { + const count = this.readIntLength() + const result: Record = {} + for (let index = 0; index < count; index += 1) { + const [, keyType] = this.readHead() + const key = String(this.readValue(keyType) ?? '') + const [, valueType] = this.readHead() + result[key] = this.readValue(valueType) + } + return result + } + + private findTag(targetTag: number): TafTypeValue | null { + while (this.remaining > 0) { + const position = this.offset + const [tag, dataType] = this.readHead() + if (tag === targetTag) return dataType + if (dataType === TAF_TYPE.STRUCT_END || tag > targetTag) { + this.offset = position + return null + } + this.skipField(dataType) + } + return null + } + + private skipField(dataType: TafTypeValue): void { + if (dataType === TAF_TYPE.ZERO) return + if (dataType === TAF_TYPE.INT8) { + this.require(1) + this.offset += 1 + return + } + if (dataType === TAF_TYPE.INT16) { + this.require(2) + this.offset += 2 + return + } + if (dataType === TAF_TYPE.INT32 || dataType === TAF_TYPE.FLOAT) { + this.require(4) + this.offset += 4 + return + } + if (dataType === TAF_TYPE.INT64 || dataType === TAF_TYPE.DOUBLE) { + this.require(8) + this.offset += 8 + return + } + if (dataType === TAF_TYPE.STRING1) { + this.require(1) + const length = this.buffer[this.offset++]! + this.require(length) + this.offset += length + return + } + if (dataType === TAF_TYPE.STRING4) { + this.require(4) + const length = this.buffer.readUInt32BE(this.offset) + this.offset += 4 + this.require(length) + this.offset += length + return + } + if (dataType === TAF_TYPE.MAP) { + this.skipMapBody() + return + } + if (dataType === TAF_TYPE.LIST) { + this.skipListBody() + return + } + if (dataType === TAF_TYPE.SIMPLE_LIST) { + this.readHead() + const length = this.readIntLength() + this.require(length) + this.offset += length + return + } + if (dataType === TAF_TYPE.STRUCT_BEGIN) { + this.skipStructBody() + return + } + if (dataType === TAF_TYPE.STRUCT_END) return + throw new Error(`未知 TAF 类型 0x${String(dataType)}`) + } + + private skipMapBody(): void { + const count = this.readIntLength() + for (let index = 0; index < count; index += 1) { + const [, keyType] = this.readHead() + this.skipField(keyType) + const [, valueType] = this.readHead() + this.skipField(valueType) + } + } + + private skipListBody(): void { + const count = this.readIntLength() + for (let index = 0; index < count; index += 1) { + const [, itemType] = this.readHead() + this.skipField(itemType) + } + } + + private skipStructBody(): void { + while (this.remaining > 0) { + const [, dataType] = this.readHead() + if (dataType === TAF_TYPE.STRUCT_END) return + this.skipField(dataType) + } + throw new Error('TAF 结构体未正常结束') + } + + private require(length: number): void { + if (length < 0 || this.offset + length > this.buffer.length) { + throw new Error('TAF 数据提前结束') + } + } +} + +export type WupRequestInput = { + servant: string + func: string + requestId?: number + timeout?: number + writeRequest: (writer: TafWriter) => void +} + +export function encodeWupRequest(input: WupRequestInput): Buffer { + const requestWriter = new TafWriter() + requestWriter.writeStruct(0, input.writeRequest) + + const mapWriter = new TafWriter() + mapWriter.writeHead(0, TAF_TYPE.MAP) + mapWriter.writeInt32(0, 1) + mapWriter.writeString(0, 'tReq') + mapWriter.writeBytes(1, requestWriter.toBuffer()) + + const bodyWriter = new TafWriter() + bodyWriter.writeInt16(1, 3) + bodyWriter.writeInt8(2, 0) + bodyWriter.writeInt32(3, 0) + bodyWriter.writeInt32(4, input.requestId ?? 1) + bodyWriter.writeString(5, input.servant) + bodyWriter.writeString(6, input.func) + bodyWriter.writeBytes(7, mapWriter.toBuffer()) + bodyWriter.writeInt32(8, input.timeout ?? 3000) + bodyWriter.writeMap(9, {}) + bodyWriter.writeMap(10, {}) + const body = bodyWriter.toBuffer() + + const prefix = Buffer.allocUnsafe(4) + prefix.writeUInt32BE(4 + body.length, 0) + return Buffer.concat([prefix, body]) +} + +export type WupResponse = { + servant: string + func: string + newData: Record +} + +function normalizeWupPayload(buffer: Buffer): Buffer { + if (buffer.length < 4) return buffer + const declaredLength = buffer.readUInt32BE(0) + if (declaredLength === buffer.length || declaredLength + 4 === buffer.length) { + return buffer.subarray(4) + } + return buffer +} + +export function decodeWupResponse(input: Buffer): WupResponse { + const reader = new TafReader(normalizeWupPayload(input)) + let servant = '' + let func = '' + let buffer: Buffer = Buffer.alloc(0) + + while (reader.remaining > 0) { + const [tag, dataType] = reader.readHead() + if (tag > 10) break + if (tag === 1 || tag === 2 || tag === 3 || tag === 4 || tag === 8) { + reader.readIntValue(dataType) + continue + } + if (tag === 5) { + servant = reader.readStringValue(dataType) + continue + } + if (tag === 6) { + func = reader.readStringValue(dataType) + continue + } + if (tag === 7) { + if (dataType !== TAF_TYPE.SIMPLE_LIST) { + throw new Error('WUP sBuffer 类型无效') + } + reader.readHead() + const length = reader.readIntLength() + buffer = reader.readBytesRaw(length) + continue + } + if (tag === 9 || tag === 10) { + reader.readValue(dataType) + if (tag === 10) break + continue + } + reader.skipValue(dataType) + } + + return { servant, func, newData: decodeWupNewData(buffer) } +} + +function decodeWupNewData(buffer: Buffer): Record { + if (!buffer || buffer.length === 0) return {} + const reader = new TafReader(buffer) + const [tag, dataType] = reader.readHead() + if (tag !== 0 || dataType !== TAF_TYPE.MAP) return {} + const count = reader.readIntLength() + const result: Record = {} + for (let index = 0; index < count; index += 1) { + const [, keyType] = reader.readHead() + const key = reader.readStringValue(keyType) + const [, valueType] = reader.readHead() + if (valueType !== TAF_TYPE.SIMPLE_LIST) continue + reader.readHead() + const length = reader.readIntLength() + result[key] = reader.readBytesRaw(length) + } + return result +} + +export function readWupStruct( + response: WupResponse, + readBody: (reader: TafReader) => T, +): T | null { + const buffer = response.newData.tRsp || response.newData.tResp + if (!buffer || buffer.length === 0) return null + const reader = new TafReader(buffer) + const [, dataType] = reader.readHead() + if (dataType !== TAF_TYPE.STRUCT_BEGIN) return null + return reader.readStructBody(readBody) +} diff --git a/apps/backend/src/services/semi-auto/semi-auto-credential-crypto.test.ts b/apps/backend/src/services/semi-auto/semi-auto-credential-crypto.test.ts new file mode 100644 index 00000000..0136fc43 --- /dev/null +++ b/apps/backend/src/services/semi-auto/semi-auto-credential-crypto.test.ts @@ -0,0 +1,94 @@ +import assert from 'node:assert/strict' +import test from 'node:test' + +import { + decryptSemiAutoCredential, + encryptSemiAutoCredential, + isEncryptedSemiAutoCredential, +} from './semi-auto-credential-crypto.js' +import { buildSemiAutoCredentialCookieHeader } from './semi-auto-credential-service.js' + +const SECRET = 'test-semi-auto-credential-encryption-key-123456' + +test('半自动履约凭证使用 AES-GCM 加密并可还原', () => { + const plaintext = JSON.stringify({ + cookies: [{ name: 'SUB', value: 'secret-cookie', domain: '.weibo.com' }], + }) + const encrypted = encryptSemiAutoCredential(plaintext, SECRET) + + assert.equal(isEncryptedSemiAutoCredential(encrypted), true) + assert.notEqual(encrypted, plaintext) + assert.equal(encrypted.includes('secret-cookie'), false) + assert.equal(decryptSemiAutoCredential(encrypted, SECRET), plaintext) +}) + +test('半自动履约凭证密文被篡改时解密失败', () => { + const encrypted = encryptSemiAutoCredential('{"cookies":[]}', SECRET) + const tampered = `${encrypted.slice(0, -1)}${encrypted.endsWith('A') ? 'B' : 'A'}` + assert.throws(() => decryptSemiAutoCredential(tampered, SECRET)) +}) + +test('错误密钥不能解密半自动履约凭证', () => { + const encrypted = encryptSemiAutoCredential('{"cookies":[]}', SECRET) + assert.throws(() => + decryptSemiAutoCredential(encrypted, 'another-semi-auto-credential-encryption-key-123'), + ) +}) + +test('账号 Cookie Header 按域名、路径和安全协议筛选', () => { + const header = buildSemiAutoCredentialCookieHeader( + [ + { + name: 'SUB', + value: 'weibo-session', + domain: '.weibo.com', + path: '/', + secure: true, + httpOnly: true, + hostOnly: false, + expiresAt: null, + }, + { + name: 'SUB', + value: 'passport-session', + domain: 'passport.weibo.com', + path: '/sso', + secure: true, + httpOnly: true, + hostOnly: true, + expiresAt: null, + }, + { + name: 'INSECURE', + value: 'must-not-leak', + domain: '.weibo.com', + path: '/', + secure: false, + httpOnly: false, + hostOnly: false, + expiresAt: null, + }, + ], + 'https://weibo.com/', + ) + + assert.equal(header, 'SUB=weibo-session; INSECURE=must-not-leak') + assert.equal( + buildSemiAutoCredentialCookieHeader( + [ + { + name: 'SUB', + value: 'weibo-session', + domain: '.weibo.com', + path: '/', + secure: true, + httpOnly: true, + hostOnly: false, + expiresAt: null, + }, + ], + 'http://weibo.com/', + ), + '', + ) +}) diff --git a/apps/backend/src/services/semi-auto/semi-auto-credential-crypto.ts b/apps/backend/src/services/semi-auto/semi-auto-credential-crypto.ts new file mode 100644 index 00000000..1c2a4902 --- /dev/null +++ b/apps/backend/src/services/semi-auto/semi-auto-credential-crypto.ts @@ -0,0 +1,56 @@ +import crypto from 'node:crypto' + +import { runtimeConfig } from '../../config/runtime.js' + +const CIPHERTEXT_PREFIX = 'enc:v1:' + +function resolveEncryptionSecret(override?: string): string { + const explicit = String(override ?? runtimeConfig.semiAuto?.credentialEncryptionKey ?? '').trim() + const fallback = String(runtimeConfig.admin?.sessionSecret || '').trim() + const secret = explicit || fallback + if (!secret) { + throw new Error('缺少 SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY,无法加密半自动履约平台凭证') + } + return secret +} + +function deriveKey(secret: string): Buffer { + return crypto.createHash('sha256').update(`order-site:semi-auto-credential:${secret}`).digest() +} + +export function isEncryptedSemiAutoCredential(value: unknown): boolean { + return String(value || '').startsWith(CIPHERTEXT_PREFIX) +} + +export function encryptSemiAutoCredential(plaintext: string, secretOverride?: string): string { + const text = String(plaintext || '') + if (!text) return '' + const secret = resolveEncryptionSecret(secretOverride) + const nonce = crypto.randomBytes(12) + const cipher = crypto.createCipheriv('aes-256-gcm', deriveKey(secret), nonce) + const ciphertext = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]) + const tag = cipher.getAuthTag() + return `${CIPHERTEXT_PREFIX}${Buffer.concat([nonce, tag, ciphertext]).toString('base64url')}` +} + +export function decryptSemiAutoCredential(ciphertext: string, secretOverride?: string): string { + const value = String(ciphertext || '') + if (!value) return '' + if (!value.startsWith(CIPHERTEXT_PREFIX)) { + throw new Error('半自动履约凭证不是受支持的加密格式') + } + const raw = Buffer.from(value.slice(CIPHERTEXT_PREFIX.length), 'base64url') + if (raw.length < 29) { + throw new Error('半自动履约凭证密文长度无效') + } + const nonce = raw.subarray(0, 12) + const tag = raw.subarray(12, 28) + const ciphertextBytes = raw.subarray(28) + const decipher = crypto.createDecipheriv( + 'aes-256-gcm', + deriveKey(resolveEncryptionSecret(secretOverride)), + nonce, + ) + decipher.setAuthTag(tag) + return Buffer.concat([decipher.update(ciphertextBytes), decipher.final()]).toString('utf8') +} diff --git a/apps/backend/src/services/semi-auto/semi-auto-credential-service.ts b/apps/backend/src/services/semi-auto/semi-auto-credential-service.ts new file mode 100644 index 00000000..83a12ba1 --- /dev/null +++ b/apps/backend/src/services/semi-auto/semi-auto-credential-service.ts @@ -0,0 +1,219 @@ +import type { PoolClient } from 'pg' + +import { query } from '../../db/client.js' +import { + decryptSemiAutoCredential, + encryptSemiAutoCredential, +} from './semi-auto-credential-crypto.js' + +export type SemiAutoCredentialCookie = { + name: string + value: string + domain: string + path: string + secure: boolean + httpOnly: boolean + hostOnly?: boolean + expiresAt: string | null +} + +export type SemiAutoCredentialPayload = { + platformUid: string + nickname: string + cookies: SemiAutoCredentialCookie[] +} + +export type SemiAutoCredentialSource = 'qr' | 'sms' | 'web' | 'app' | 'import' + +export type SemiAutoCredentialRecord = SemiAutoCredentialPayload & { + id: number + platform: 'huya' | 'weibo' + source: SemiAutoCredentialSource | '' + status: 'unknown' | 'valid' | 'invalid' | 'error' + updatedAt: string +} + +type CredentialRow = { + id: number + platform: 'huya' | 'weibo' + platform_uid: string + platform_nickname: string + credential_ciphertext: string + credential_source: SemiAutoCredentialSource | '' + credential_status: 'unknown' | 'valid' | 'invalid' | 'error' + credential_updated_at: string +} + +function normalizeCookieList(value: unknown): SemiAutoCredentialCookie[] { + if (!Array.isArray(value)) return [] + return value + .filter((item): item is Record => + Boolean(item && typeof item === 'object' && !Array.isArray(item)), + ) + .map((item) => { + const domain = String(item.domain || '') + .trim() + .toLowerCase() + return { + name: String(item.name || '').trim(), + value: String(item.value || ''), + domain, + path: String(item.path || '/').trim() || '/', + secure: item.secure === true, + httpOnly: item.httpOnly === true, + hostOnly: typeof item.hostOnly === 'boolean' ? item.hostOnly : !domain.startsWith('.'), + expiresAt: item.expiresAt ? String(item.expiresAt) : null, + } + }) + .filter((item) => item.name && item.domain) +} + +export function buildSemiAutoCredentialCookieHeader( + cookies: SemiAutoCredentialCookie[], + requestUrlInput: unknown, +): string { + const requestUrl = new URL(String(requestUrlInput || '').trim()) + const hostname = requestUrl.hostname.toLowerCase() + const requestPath = requestUrl.pathname || '/' + const nowMs = Date.now() + return cookies + .filter((cookie) => { + if (cookie.secure && requestUrl.protocol !== 'https:') return false + if (cookie.expiresAt) { + const expiresAtMs = Date.parse(cookie.expiresAt) + if (Number.isFinite(expiresAtMs) && expiresAtMs <= nowMs) return false + } + const cookieDomain = cookie.domain.trim().toLowerCase().replace(/^\./, '') + if (!cookieDomain) return false + const hostOnly = cookie.hostOnly ?? !cookie.domain.startsWith('.') + const domainMatches = hostOnly + ? hostname === cookieDomain + : hostname === cookieDomain || hostname.endsWith(`.${cookieDomain}`) + if (!domainMatches) return false + const cookiePath = cookie.path || '/' + return ( + requestPath === cookiePath || + requestPath.startsWith(cookiePath.endsWith('/') ? cookiePath : `${cookiePath}/`) + ) + }) + .sort((left, right) => (right.path || '/').length - (left.path || '/').length) + .map((cookie) => `${cookie.name}=${cookie.value}`) + .join('; ') +} + +function decodeCredential(row: CredentialRow): SemiAutoCredentialRecord { + const decrypted = decryptSemiAutoCredential(row.credential_ciphertext) + const parsed = JSON.parse(decrypted) as Record + return { + id: Number(row.id), + platform: row.platform, + platformUid: row.platform_uid, + nickname: row.platform_nickname, + cookies: normalizeCookieList(parsed.cookies), + source: row.credential_source, + status: row.credential_status, + updatedAt: row.credential_updated_at, + } +} + +export async function upsertSemiAutoCredentialWithClient( + client: Pick, + input: { + platform: 'huya' | 'weibo' + source: SemiAutoCredentialSource + payload: SemiAutoCredentialPayload + }, +): Promise { + const platformUid = String(input.payload.platformUid || '').trim() + if (!platformUid) { + throw new Error('平台账号 UID 为空,无法保存半自动履约凭证') + } + const cookies = normalizeCookieList(input.payload.cookies) + if (cookies.length === 0) { + throw new Error('平台 Cookie 为空,无法保存半自动履约凭证') + } + const encrypted = encryptSemiAutoCredential( + JSON.stringify({ + cookies, + }), + ) + const result = await client.query<{ id: number }>( + ` + INSERT INTO semi_auto_credentials ( + platform, platform_uid, platform_nickname, credential_ciphertext, + credential_source, credential_status, credential_updated_at, + last_checked_at, last_check_error, created_at, updated_at + ) VALUES ( + $1, $2, $3, $4, $5, 'valid', NOW(), NOW(), '', NOW(), NOW() + ) + ON CONFLICT (platform, platform_uid) DO UPDATE + SET platform_nickname = EXCLUDED.platform_nickname, + credential_ciphertext = EXCLUDED.credential_ciphertext, + credential_source = EXCLUDED.credential_source, + credential_status = 'valid', + credential_updated_at = NOW(), + last_checked_at = NOW(), + last_check_error = '', + updated_at = NOW() + RETURNING id + `, + [ + input.platform, + platformUid, + String(input.payload.nickname || '') + .trim() + .slice(0, 120), + encrypted, + input.source, + ], + ) + return Number(result.rows[0]?.id || 0) +} + +export async function loadSemiAutoCredential( + credentialIdInput: unknown, +): Promise { + const credentialId = Number(credentialIdInput || 0) + if (!Number.isInteger(credentialId) || credentialId <= 0) return null + const result = await query( + ` + SELECT + id, platform, platform_uid, platform_nickname, credential_ciphertext, + credential_source, credential_status, credential_updated_at + FROM semi_auto_credentials + WHERE id = $1 + LIMIT 1 + `, + [credentialId], + ) + const row = result.rows[0] + return row ? decodeCredential(row) : null +} + +export async function markSemiAutoCredentialCheck( + credentialIdInput: unknown, + input: { + status: 'valid' | 'invalid' | 'error' + error?: string + }, +): Promise { + const credentialId = Number(credentialIdInput || 0) + if (!Number.isInteger(credentialId) || credentialId <= 0) return + await query( + ` + UPDATE semi_auto_credentials + SET credential_status = $2, + last_checked_at = NOW(), + last_check_error = $3, + updated_at = NOW() + WHERE id = $1 + `, + [ + credentialId, + input.status, + String(input.error || '') + .trim() + .slice(0, 1000), + ], + ) +} diff --git a/apps/backend/src/services/semi-auto/semi-auto-task-service.ts b/apps/backend/src/services/semi-auto/semi-auto-task-service.ts new file mode 100644 index 00000000..3b60b4ee --- /dev/null +++ b/apps/backend/src/services/semi-auto/semi-auto-task-service.ts @@ -0,0 +1,1598 @@ +import type { PoolClient } from 'pg' + +import { query, withTransaction } from '../../db/client.js' +import type { AdminSession } from '../admin/admin-auth-service.js' +import { + confirmManualFulfillment, + runManualFulfillmentPostCommit, +} from '../finance/manual-fulfillment-service.js' +import { getFileAssetByObjectKey } from '../../repositories/file-asset-repo.js' +import { createHttpError } from '../../utils/http.js' +import { nowIso } from '../../utils/time.js' +import { safeParseJson } from '../admin/admin-query-utils.js' +import { publishAdminOrderRealtimeChange } from '../realtime/realtime-event-service.js' +import { + buildFileUrl, + ORDER_SERVICE_SCREENSHOT_CONTENT_TYPES, + type UploadedFileDto, +} from '../file-storage/file-storage-service.js' +import { + createHuyaBrowserTicket, + createHuyaLoginSession, + getHuyaBinding, + getHuyaLoginSession, + revokeHuyaSession, + startHuyaBinding, + consumeHuyaBrowserTicket, + type ConnectorBindingSession, + type SemiAutoConnectorMode, + type ConnectorLoginSession, +} from './huya-connector-client.js' +import { + consumeWeiboBrowserTicket, + createWeiboBrowserTicket, + createWeiboLoginSession, + exportWeiboSessionCredential, + getWeiboBinding, + getWeiboCountryCodes, + getWeiboLoginSession, + loginWeiboSms, + restoreWeiboSessionFromCredential, + revokeWeiboSession, + sendWeiboSmsCode, +} from './weibo-connector-client.js' +import { WEIBO_TICKET_PREFIX } from './weibo-native/weibo-native-connector.js' +import { + buildSemiAutoCredentialCookieHeader, + loadSemiAutoCredential, + markSemiAutoCredentialCheck, + upsertSemiAutoCredentialWithClient, +} from './semi-auto-credential-service.js' + +const SEMI_AUTO_PLATFORMS = new Set(['huya', 'weibo']) +type SemiAutoPlatform = 'huya' | 'weibo' +type LoginStatus = + | 'waiting_login' + | 'qr_pending' + | 'scanned' + | 'authenticated' + | 'failed' + | 'expired' +type BindingStatus = + | 'not_started' + | 'qr_pending' + | 'scanned' + | 'role_ready' + | 'confirmed' + | 'failed' + | 'expired' +type ExecutionStatus = + | 'waiting_customer' + | 'waiting_operator' + | 'processing' + | 'completed' + | 'failed' + | 'cancelled' + +type TaskRow = { + id: number + order_id: number + order_item_id: number + fulfillment_id: number | null + manual_fulfillment_config_id: number | null + platform: SemiAutoPlatform + login_status: LoginStatus + binding_status: BindingStatus + execution_status: ExecutionStatus + connector_mode: SemiAutoConnectorMode + connector_session_id: string + credential_id: number | null + credential_status: 'unknown' | 'valid' | 'invalid' | 'error' | null + credential_source: string | null + credential_updated_at: string | null + huya_uid: string + platform_nickname: string + bind_game_account: string + bind_game_role: string + bind_game_channel: string + target_quantity: number + completed_quantity: number + assigned_admin_user_id: number | null + assigned_admin_name?: string + customer_link_opened_at: string | null + auth_started_at: string | null + authenticated_at: string | null + binding_started_at: string | null + bound_at: string | null + completed_at: string | null + completion_note: string + external_order_no: string + completion_evidence_json: Record + last_error: string + created_at: string + updated_at: string + platform_order_id: string + provider: string + shop_id: string + sku_code: string + sku_name: string + quantity: number + product_name: string + manual_platform_key: string + manual_cost_mode: string + manual_credit_quantity: number | string + semi_auto_config_json: Record +} + +type TaskEventInput = { + eventType: string + actorType?: 'system' | 'customer' | 'admin' | 'connector' + actorId?: string + fromLoginStatus?: LoginStatus | null + toLoginStatus?: LoginStatus | null + fromBindingStatus?: BindingStatus | null + toBindingStatus?: BindingStatus | null + fromExecutionStatus?: ExecutionStatus | null + toExecutionStatus?: ExecutionStatus | null + detail?: Record +} + +type TaskActorType = 'system' | 'customer' | 'admin' | 'connector' + +function normalizeId(value: unknown, label = '任务 ID'): number { + const id = Number(value) + if (!Number.isInteger(id) || id <= 0) { + throw createHttpError(`${label}无效`, { + statusCode: 400, + errorCode: 'semi_auto_task_id_invalid', + }) + } + return id +} + +function normalizeOrderNo(value: unknown): string { + const text = String(value ?? '').trim() + if (!text) { + throw createHttpError('订单号无效,请确认订单号是否正确', { + statusCode: 404, + errorCode: 'semi_auto_order_not_found', + }) + } + return text +} + +function displayStatus(task: TaskRow) { + if (task.execution_status === 'completed') return { key: 'completed', label: '已完成' } + if (task.execution_status === 'cancelled') return { key: 'cancelled', label: '已取消' } + if ( + task.execution_status === 'failed' || + task.login_status === 'failed' || + task.binding_status === 'failed' + ) { + return { key: 'failed', label: '需客服处理' } + } + if (task.binding_status === 'confirmed') { + return { key: 'waiting_operator', label: '等待客服处理' } + } + if (task.binding_status === 'role_ready') { + return { key: 'binding_confirm', label: '待确认绑定' } + } + if (task.login_status === 'authenticated') { + return { key: 'waiting_binding', label: '等待扫码绑定' } + } + if (task.login_status === 'scanned') return { key: 'login_scanned', label: '已扫码,确认中' } + if (task.login_status === 'qr_pending') return { key: 'waiting_login', label: '等待客户登录' } + return { key: 'waiting_customer', label: '等待客户打开链接' } +} + +function mapTask(task: TaskRow) { + return { + id: Number(task.id), + orderId: Number(task.order_id), + orderItemId: Number(task.order_item_id), + fulfillmentId: task.fulfillment_id ? Number(task.fulfillment_id) : null, + platform: task.platform, + platformLabel: + task.platform === 'huya' ? '虎牙' : task.platform === 'weibo' ? '微博' : task.platform, + loginStatus: task.login_status, + bindingStatus: task.binding_status, + executionStatus: task.execution_status, + connectorMode: task.connector_mode, + displayStatus: displayStatus(task), + connectorReady: Boolean(task.connector_session_id || task.credential_id), + credentialReady: Boolean(task.credential_id), + credentialStatus: task.credential_status || 'unknown', + credentialSource: task.credential_source || '', + credentialUpdatedAt: task.credential_updated_at, + huyaUid: task.huya_uid, + platformNickname: task.platform_nickname, + bindGameAccount: task.bind_game_account, + bindGameRole: task.bind_game_role, + bindGameChannel: task.bind_game_channel, + targetQuantity: Number(task.target_quantity || 1), + completedQuantity: Number(task.completed_quantity || 0), + assignedAdminUserId: task.assigned_admin_user_id ? Number(task.assigned_admin_user_id) : null, + assignedAdminName: String(task.assigned_admin_name || ''), + customerLinkOpenedAt: task.customer_link_opened_at, + authStartedAt: task.auth_started_at, + authenticatedAt: task.authenticated_at, + bindingStartedAt: task.binding_started_at, + boundAt: task.bound_at, + completedAt: task.completed_at, + completionNote: task.completion_note, + externalOrderNo: task.external_order_no, + completionEvidence: task.completion_evidence_json || {}, + lastError: task.last_error, + createdAt: task.created_at, + updatedAt: task.updated_at, + orderNo: task.platform_order_id, + provider: task.provider, + shopId: task.shop_id, + skuCode: task.sku_code, + skuName: task.sku_name, + productName: task.product_name, + quantity: Number(task.quantity || 1), + semiAutoConfig: task.semi_auto_config_json || {}, + } +} + +export type SemiAutoTaskDto = ReturnType + +async function appendTaskEvent( + client: Pick, + taskId: number, + event: TaskEventInput, +) { + await client.query( + ` + INSERT INTO semi_auto_task_events ( + task_id, event_type, actor_type, actor_id, + from_login_status, to_login_status, + from_binding_status, to_binding_status, + from_execution_status, to_execution_status, + detail_json, created_at + ) VALUES ( + $1, $2, $3, $4, + $5, $6, + $7, $8, + $9, $10, + $11::jsonb, NOW() + ) + `, + [ + taskId, + event.eventType, + event.actorType || 'system', + event.actorId || '', + event.fromLoginStatus || null, + event.toLoginStatus || null, + event.fromBindingStatus || null, + event.toBindingStatus || null, + event.fromExecutionStatus || null, + event.toExecutionStatus || null, + JSON.stringify(event.detail || {}), + ], + ) +} + +const TASK_SELECT = ` + SELECT + task.*, + admin.display_name AS assigned_admin_name, + o.platform_order_id, + o.provider, + o.shop_id, + oi.sku_code, + oi.sku_name, + oi.quantity, + COALESCE(NULLIF(oi.sku_name, ''), NULLIF(oi.sku_code, ''), '订单商品') AS product_name, + cfg.platform_key AS manual_platform_key, + cfg.cost_mode AS manual_cost_mode, + cfg.credit_quantity AS manual_credit_quantity, + cfg.semi_auto_config_json, + credential.credential_status, + credential.credential_source, + credential.credential_updated_at + FROM semi_auto_tasks task + JOIN orders o ON o.id = task.order_id + JOIN order_items oi ON oi.id = task.order_item_id + LEFT JOIN manual_fulfillment_configs cfg ON cfg.id = task.manual_fulfillment_config_id + LEFT JOIN admin_users admin ON admin.id = task.assigned_admin_user_id + LEFT JOIN semi_auto_credentials credential ON credential.id = task.credential_id +` + +async function loadTask(taskId: number): Promise { + const result = await query(`${TASK_SELECT} WHERE task.id = $1 LIMIT 1`, [taskId]) + const task = result.rows[0] + if (!task) { + throw createHttpError('半自动履约任务不存在', { + statusCode: 404, + errorCode: 'semi_auto_task_not_found', + }) + } + return task +} + +async function loadTaskForOrder(orderNo: string, taskId: number): Promise { + const task = await loadTask(taskId) + if (String(task.platform_order_id || '').trim() !== orderNo) { + throw createHttpError('订单号或任务无效', { + statusCode: 404, + errorCode: 'semi_auto_task_not_found', + }) + } + return task +} + +async function loadTaskForUpdateWithClient(client: PoolClient, taskId: number): Promise { + const result = await client.query( + `${TASK_SELECT} WHERE task.id = $1 LIMIT 1 FOR UPDATE OF task`, + [taskId], + ) + const task = result.rows[0] + if (!task) { + throw createHttpError('半自动履约任务不存在', { + statusCode: 404, + errorCode: 'semi_auto_task_not_found', + }) + } + return task +} + +function assertWeiboTask(task: TaskRow) { + if (task.platform !== 'weibo') { + throw createHttpError('当前任务不是微博任务', { + statusCode: 409, + errorCode: 'semi_auto_platform_mismatch', + }) + } +} + +async function createLoginSessionForTask( + task: TaskRow, + orderNo: string, +): Promise { + const input = { taskId: task.id, orderNo } + return task.platform === 'weibo' + ? createWeiboLoginSession(input, task.connector_mode) + : createHuyaLoginSession(input, task.connector_mode) +} + +async function getLoginSessionForTask( + task: TaskRow, + sessionId: string, +): Promise { + return task.platform === 'weibo' + ? getWeiboLoginSession(sessionId, task.connector_mode) + : getHuyaLoginSession(sessionId, task.connector_mode) +} + +async function revokeSessionForTask(task: TaskRow, sessionId: string): Promise { + if (task.platform === 'weibo') { + await revokeWeiboSession(sessionId, task.connector_mode) + return + } + await revokeHuyaSession(sessionId, task.connector_mode) +} + +async function getBindingForTask( + task: TaskRow, + sessionId: string, +): Promise { + return task.platform === 'weibo' + ? getWeiboBinding(sessionId, task.connector_mode) + : getHuyaBinding(sessionId, task.connector_mode) +} + +async function ensureConnectorSessionForTask(task: TaskRow): Promise { + if (task.execution_status === 'completed' || task.execution_status === 'cancelled') return task + if (task.connector_session_id) { + try { + const session = await getLoginSessionForTask(task, task.connector_session_id) + if (session.status === 'authenticated') return task + } catch { + // 进程重启或多实例切换后,内存会话会丢失;下面用已保存的账号 CK 恢复。 + } + } + if (task.platform !== 'weibo' || !task.credential_id) return task + const credential = await loadSemiAutoCredential(task.credential_id) + if (!credential || credential.platform !== 'weibo') return task + try { + const session = await restoreWeiboSessionFromCredential( + { + taskId: task.id, + orderNo: task.platform_order_id, + platformUid: credential.platformUid, + nickname: credential.nickname, + cookies: credential.cookies, + }, + task.connector_mode, + ) + await markSemiAutoCredentialCheck(task.credential_id, { status: 'valid' }) + await withTransaction(async (client) => { + await client.query( + ` + UPDATE semi_auto_tasks + SET connector_session_id = $2, + login_status = 'authenticated', + huya_uid = CASE WHEN $3 <> '' THEN $3 ELSE huya_uid END, + platform_nickname = CASE WHEN $4 <> '' THEN $4 ELSE platform_nickname END, + last_error = '', + updated_at = NOW() + WHERE id = $1 + `, + [task.id, session.sessionId, session.huyaUid, session.nickname], + ) + await appendTaskEvent(client, task.id, { + eventType: 'credential_session_restored', + actorType: 'connector', + detail: { + credentialId: task.credential_id, + hasCredential: session.hasCredential, + }, + }) + }) + return loadTask(task.id) + } catch (error) { + await markSemiAutoCredentialCheck(task.credential_id, { + status: 'invalid', + error: error instanceof Error ? error.message : String(error), + }).catch(() => undefined) + throw error + } +} + +type SemiAutoCandidate = { + order_id: number + platform_order_id: string + order_item_id: number + fulfillment_id: number + manual_fulfillment_config_id: number + platform: SemiAutoPlatform + quantity: number +} + +async function insertMissingSemiAutoTasksWithClient(client: PoolClient, orderNo?: string) { + const params: unknown[] = [] + let orderFilter = '' + if (orderNo) { + params.push(orderNo) + orderFilter = 'AND o.platform_order_id = $1' + } + const candidates = await client.query( + ` + SELECT + o.id AS order_id, + o.platform_order_id, + oi.id AS order_item_id, + f.id AS fulfillment_id, + cfg.id AS manual_fulfillment_config_id, + cfg.semi_auto_platform AS platform, + GREATEST(1, COALESCE(oi.quantity, 1))::int AS quantity + FROM orders o + JOIN order_items oi ON oi.order_id = o.id + JOIN fulfillments f ON f.order_item_id = oi.id + JOIN manual_fulfillment_configs cfg ON cfg.id = f.fulfillment_config_id + WHERE f.channel = 'manual' + AND f.status = 'assigned' + AND cfg.enabled = TRUE + AND cfg.semi_auto_enabled = TRUE + AND cfg.semi_auto_platform IN ('huya', 'weibo') + ${orderFilter} + AND NOT EXISTS ( + SELECT 1 FROM semi_auto_tasks existing WHERE existing.order_item_id = oi.id + ) + ORDER BY o.id DESC, oi.id ASC + `, + params, + ) + + const createdIds: number[] = [] + const orderIds = new Set() + for (const row of candidates.rows) { + const inserted = await client.query<{ id: number }>( + ` + INSERT INTO semi_auto_tasks ( + order_id, order_item_id, fulfillment_id, manual_fulfillment_config_id, + platform, target_quantity, created_at, updated_at + ) VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW()) + ON CONFLICT (order_item_id) DO NOTHING + RETURNING id + `, + [ + Number(row.order_id), + Number(row.order_item_id), + Number(row.fulfillment_id), + Number(row.manual_fulfillment_config_id), + row.platform, + Number(row.quantity || 1), + ], + ) + const taskId = Number(inserted.rows[0]?.id || 0) + if (!taskId) continue + createdIds.push(taskId) + orderIds.add(Number(row.order_id)) + await appendTaskEvent(client, taskId, { + eventType: 'task_created', + toLoginStatus: 'waiting_login', + toBindingStatus: 'not_started', + toExecutionStatus: 'waiting_customer', + detail: { orderNo: row.platform_order_id }, + }) + } + return { createdIds, orderIds: [...orderIds] } +} + +export async function ensureSemiAutoTasksForOrder(orderNoInput: unknown) { + const orderNo = normalizeOrderNo(orderNoInput) + const result = await withTransaction((client) => + insertMissingSemiAutoTasksWithClient(client, orderNo), + ) + if (result.orderIds[0]) { + publishAdminOrderRealtimeChange(result.orderIds[0]) + } + return { orderNo, createdIds: result.createdIds } +} + +/** + * 后台列表读取前的幂等回填。 + * + * 客户不先打开 `/c/订单号` 时,任务也必须进入客服工作台;后备查询只插入缺失任务, + * 不修改已有任务状态,也不会重复写事件。 + */ +export async function backfillSemiAutoTasks() { + const result = await withTransaction((client) => insertMissingSemiAutoTasksWithClient(client)) + return { createdIds: result.createdIds, orderIds: result.orderIds } +} + +export async function listPublicSemiAutoTasks(orderNoInput: unknown) { + const orderNo = normalizeOrderNo(orderNoInput) + await ensureSemiAutoTasksForOrder(orderNo) + const result = await query( + `${TASK_SELECT} + WHERE o.platform_order_id = $1 + AND task.execution_status <> 'cancelled' + ORDER BY task.id ASC`, + [orderNo], + ) + return result.rows.map(mapTask) +} + +export async function markCustomerLinkOpened(orderNoInput: unknown, taskIdInput: unknown) { + const orderNo = normalizeOrderNo(orderNoInput) + const taskId = normalizeId(taskIdInput) + await ensureSemiAutoTasksForOrder(orderNo) + const task = await loadTaskForOrder(orderNo, taskId) + if (!task.customer_link_opened_at) { + await withTransaction(async (client) => { + await client.query( + `UPDATE semi_auto_tasks SET customer_link_opened_at = NOW(), updated_at = NOW() WHERE id = $1`, + [taskId], + ) + await appendTaskEvent(client, taskId, { + eventType: 'customer_link_opened', + actorType: 'customer', + }) + }) + } + return { ok: true } +} + +function mapLoginUpdate(session: ConnectorLoginSession) { + const statusMap: Record = { + waiting_scan: 'qr_pending', + scanned: 'scanned', + authenticated: 'authenticated', + expired: 'expired', + failed: 'failed', + } + return { + status: statusMap[session.status] || 'failed', + uid: String(session.huyaUid || ''), + nickname: String(session.nickname || ''), + message: String(session.message || ''), + hasCredential: session.hasCredential === true, + } +} + +async function updateLoginTask( + task: TaskRow, + session: ConnectorLoginSession, + actorType: TaskActorType, +) { + const mapped = mapLoginUpdate(session) + // 微博没有独立的游戏角色绑定步骤:登录成功即视为授权完成。 + const autoConfirmWeiboBinding = + task.platform === 'weibo' && + mapped.status === 'authenticated' && + task.binding_status !== 'confirmed' + const nextExecutionStatus: ExecutionStatus = + mapped.status === 'authenticated' + ? task.platform === 'weibo' || task.binding_status === 'confirmed' + ? 'waiting_operator' + : 'waiting_customer' + : task.execution_status + const storedCredential = + task.platform === 'weibo' && mapped.status === 'authenticated' && mapped.hasCredential + ? exportWeiboSessionCredential(session.sessionId, task.connector_mode) + : null + await withTransaction(async (client) => { + const credentialId = storedCredential + ? await upsertSemiAutoCredentialWithClient(client, { + platform: 'weibo', + source: 'qr', + payload: storedCredential, + }) + : null + await client.query( + ` + UPDATE semi_auto_tasks + SET login_status = $2, + credential_id = COALESCE($8, credential_id), + huya_uid = CASE WHEN $3 <> '' THEN $3 ELSE huya_uid END, + platform_nickname = CASE WHEN $4 <> '' THEN $4 ELSE platform_nickname END, + authenticated_at = CASE WHEN $2 = 'authenticated' THEN COALESCE(authenticated_at, NOW()) ELSE authenticated_at END, + binding_status = CASE WHEN $6::boolean THEN 'confirmed' ELSE binding_status END, + bind_game_account = CASE WHEN $6::boolean AND $4 <> '' THEN $4 ELSE bind_game_account END, + bind_game_role = CASE WHEN $6::boolean AND $3 <> '' THEN $3 ELSE bind_game_role END, + bind_game_channel = CASE WHEN $6::boolean THEN '微博' ELSE bind_game_channel END, + bound_at = CASE WHEN $6::boolean THEN COALESCE(bound_at, NOW()) ELSE bound_at END, + execution_status = $5, + last_error = CASE WHEN $2 IN ('failed', 'expired') THEN $7 ELSE '' END, + updated_at = NOW() + WHERE id = $1 + `, + [ + task.id, + mapped.status, + mapped.uid, + mapped.nickname, + nextExecutionStatus, + autoConfirmWeiboBinding, + mapped.message, + credentialId, + ], + ) + await appendTaskEvent(client, task.id, { + eventType: 'login_status_changed', + actorType, + fromLoginStatus: task.login_status, + toLoginStatus: mapped.status, + fromExecutionStatus: task.execution_status, + toExecutionStatus: nextExecutionStatus, + detail: { + hasCredential: mapped.hasCredential, + message: mapped.message, + }, + }) + if (autoConfirmWeiboBinding) { + await appendTaskEvent(client, task.id, { + eventType: 'binding_status_changed', + actorType, + fromBindingStatus: task.binding_status, + toBindingStatus: 'confirmed', + fromExecutionStatus: task.execution_status, + toExecutionStatus: nextExecutionStatus, + detail: { + gameAccount: mapped.nickname, + gameRole: mapped.uid, + gameChannel: '微博', + message: '微博登录成功,授权已完成', + }, + }) + } + }) +} + +function mapBindingUpdate(session: ConnectorBindingSession) { + const statusMap: Record = { + not_started: 'not_started', + qr_pending: 'qr_pending', + scanned: 'scanned', + role_ready: 'role_ready', + confirmed: 'confirmed', + expired: 'expired', + failed: 'failed', + } + return { + status: statusMap[session.status] || 'failed', + qrImage: String(session.qrImage || ''), + bindGameAccount: String(session.bindGameAccount || ''), + bindGameRole: String(session.bindGameRole || ''), + bindGameChannel: String(session.bindGameChannel || ''), + message: String(session.message || ''), + } +} + +async function updateBindingTask( + task: TaskRow, + session: ConnectorBindingSession, + actorType: TaskActorType, +) { + const mapped = mapBindingUpdate(session) + const executionStatus: ExecutionStatus = + mapped.status === 'confirmed' + ? 'waiting_operator' + : mapped.status === 'failed' || mapped.status === 'expired' + ? 'failed' + : task.execution_status === 'completed' || task.execution_status === 'cancelled' + ? task.execution_status + : 'waiting_customer' + await withTransaction(async (client) => { + await client.query( + ` + UPDATE semi_auto_tasks + SET binding_status = $2, + bind_game_account = CASE WHEN $3 <> '' THEN $3 ELSE bind_game_account END, + bind_game_role = CASE WHEN $4 <> '' THEN $4 ELSE bind_game_role END, + bind_game_channel = CASE WHEN $5 <> '' THEN $5 ELSE bind_game_channel END, + bound_at = CASE WHEN $2 IN ('role_ready', 'confirmed') THEN COALESCE(bound_at, NOW()) ELSE bound_at END, + execution_status = $6, + last_error = CASE WHEN $2 IN ('failed', 'expired') THEN $7 ELSE '' END, + updated_at = NOW() + WHERE id = $1 + `, + [ + task.id, + mapped.status, + mapped.bindGameAccount, + mapped.bindGameRole, + mapped.bindGameChannel, + executionStatus, + mapped.message, + ], + ) + await appendTaskEvent(client, task.id, { + eventType: 'binding_status_changed', + actorType, + fromBindingStatus: task.binding_status, + toBindingStatus: mapped.status, + fromExecutionStatus: task.execution_status, + toExecutionStatus: executionStatus, + detail: { + gameAccount: mapped.bindGameAccount, + gameRole: mapped.bindGameRole, + gameChannel: mapped.bindGameChannel, + message: mapped.message, + }, + }) + }) + return { + status: mapped.status, + qrImage: mapped.qrImage, + bindGameAccount: mapped.bindGameAccount, + bindGameRole: mapped.bindGameRole, + bindGameChannel: mapped.bindGameChannel, + message: mapped.message, + } +} + +export async function startPublicLogin(orderNoInput: unknown, taskIdInput: unknown) { + const orderNo = normalizeOrderNo(orderNoInput) + const taskId = normalizeId(taskIdInput) + await ensureSemiAutoTasksForOrder(orderNo) + const task = await loadTaskForOrder(orderNo, taskId) + if (task.execution_status === 'completed' || task.execution_status === 'cancelled') { + throw createHttpError('当前订单已结束,不能重新登录', { + statusCode: 409, + errorCode: 'semi_auto_task_closed', + }) + } + + let reusableSession: ConnectorLoginSession | null = null + if ( + task.connector_session_id && + task.login_status !== 'expired' && + task.login_status !== 'failed' + ) { + try { + reusableSession = await getLoginSessionForTask(task, task.connector_session_id) + } catch { + // Connector 重启或短期会话被清理后,任务里的旧 ID 已不可用;重新创建前先尽力撤销。 + await revokeSessionForTask(task, task.connector_session_id).catch(() => undefined) + } + } else if (task.connector_session_id) { + await revokeSessionForTask(task, task.connector_session_id).catch(() => undefined) + } + + if (reusableSession) { + await updateLoginTask(task, reusableSession, 'customer') + const refreshedTask = await loadTask(task.id) + return { + task: mapTask(refreshedTask), + login: { + status: mapLoginUpdate(reusableSession).status, + qrContent: reusableSession.qrContent, + qrImage: String(reusableSession.qrImage || ''), + expiresAt: reusableSession.expiresAt, + message: reusableSession.message, + }, + } + } + + const session = await createLoginSessionForTask(task, orderNo) + await withTransaction(async (client) => { + await client.query( + ` + UPDATE semi_auto_tasks + SET connector_session_id = $2, + login_status = 'qr_pending', + binding_status = 'not_started', + execution_status = 'waiting_customer', + auth_started_at = COALESCE(auth_started_at, NOW()), + last_error = '', + updated_at = NOW() + WHERE id = $1 + `, + [task.id, session.sessionId], + ) + await appendTaskEvent(client, task.id, { + eventType: 'login_started', + actorType: 'customer', + fromLoginStatus: task.login_status, + toLoginStatus: 'qr_pending', + fromExecutionStatus: task.execution_status, + toExecutionStatus: 'waiting_customer', + detail: { expiresAt: session.expiresAt }, + }) + }) + const refreshedTask = await loadTask(task.id) + return { + task: mapTask(refreshedTask), + login: { + status: mapLoginUpdate(session).status, + qrContent: session.qrContent, + qrImage: String(session.qrImage || ''), + expiresAt: session.expiresAt, + message: session.message, + }, + } +} + +export async function pollPublicLogin(orderNoInput: unknown, taskIdInput: unknown) { + const orderNo = normalizeOrderNo(orderNoInput) + const taskId = normalizeId(taskIdInput) + const task = await ensureConnectorSessionForTask(await loadTaskForOrder(orderNo, taskId)) + if (!task.connector_session_id) { + return { task: mapTask(task), login: null } + } + const session = await getLoginSessionForTask(task, task.connector_session_id) + await updateLoginTask(task, session, 'customer') + const updated = await loadTask(task.id) + return { + task: mapTask(updated), + login: { + status: mapLoginUpdate(session).status, + qrContent: session.qrContent, + qrImage: String(session.qrImage || ''), + expiresAt: session.expiresAt, + message: session.message, + }, + } +} + +export async function startPublicBinding( + orderNoInput: unknown, + taskIdInput: unknown, + input: { forceRebind?: unknown } = {}, +) { + const orderNo = normalizeOrderNo(orderNoInput) + const taskId = normalizeId(taskIdInput) + const task = await loadTaskForOrder(orderNo, taskId) + if (task.execution_status === 'completed' || task.execution_status === 'cancelled') { + throw createHttpError('当前订单已结束,不能重新绑定', { + statusCode: 409, + errorCode: 'semi_auto_task_closed', + }) + } + if (!task.connector_session_id || task.login_status !== 'authenticated') { + throw createHttpError('请先完成平台登录', { + statusCode: 409, + errorCode: 'semi_auto_login_required', + }) + } + const session = + task.platform === 'weibo' + ? await getWeiboBinding(task.connector_session_id, task.connector_mode) + : await startHuyaBinding(task.connector_session_id, task.connector_mode, { + forceRebind: input.forceRebind === true, + }) + const binding = await updateBindingTask(task, session, 'customer') + const updated = await loadTask(task.id) + return { task: mapTask(updated), binding } +} + +export async function pollPublicBinding(orderNoInput: unknown, taskIdInput: unknown) { + const orderNo = normalizeOrderNo(orderNoInput) + const taskId = normalizeId(taskIdInput) + const task = await loadTaskForOrder(orderNo, taskId) + if (task.execution_status === 'completed' || task.execution_status === 'cancelled') { + return { task: mapTask(task), binding: null } + } + if (!task.connector_session_id || task.login_status !== 'authenticated') { + return { task: mapTask(task), binding: null } + } + const session = await getBindingForTask(task, task.connector_session_id) + const binding = await updateBindingTask(task, session, 'customer') + const updated = await loadTask(task.id) + return { task: mapTask(updated), binding } +} + +export async function confirmPublicBinding(orderNoInput: unknown, taskIdInput: unknown) { + const orderNo = normalizeOrderNo(orderNoInput) + const taskId = normalizeId(taskIdInput) + const task = await loadTaskForOrder(orderNo, taskId) + if (task.execution_status === 'completed' || task.execution_status === 'cancelled') { + throw createHttpError('当前订单已结束,不能确认绑定', { + statusCode: 409, + errorCode: 'semi_auto_task_closed', + }) + } + if ( + !task.connector_session_id || + (task.platform !== 'weibo' && task.binding_status !== 'role_ready') + ) { + throw createHttpError('当前没有待确认的绑定角色', { + statusCode: 409, + errorCode: 'semi_auto_binding_not_ready', + }) + } + const session = await getBindingForTask(task, task.connector_session_id) + const binding = await updateBindingTask(task, session, 'customer') + const updated = await loadTask(task.id) + return { task: mapTask(updated), binding } +} + +export async function sendPublicWeiboSmsCode( + orderNoInput: unknown, + taskIdInput: unknown, + mobileInput: unknown, + countryCodeInput: unknown = '86', + mfaIdInput: unknown = '', +) { + const orderNo = normalizeOrderNo(orderNoInput) + const taskId = normalizeId(taskIdInput) + const task = await loadTaskForOrder(orderNo, taskId) + assertWeiboTask(task) + if (task.execution_status === 'completed' || task.execution_status === 'cancelled') { + throw createHttpError('当前订单已结束,不能重新登录', { + statusCode: 409, + errorCode: 'semi_auto_task_closed', + }) + } + const result = await sendWeiboSmsCode( + { + taskId: task.id, + mobile: String(mobileInput ?? '').trim(), + countryCode: String(countryCodeInput ?? '86').trim() || '86', + mfaId: String(mfaIdInput ?? '').trim(), + }, + task.connector_mode, + ) + return { + ok: !result.mfaRequired, + message: result.mfaRequired ? '需要完成微博安全验证' : '验证码已发送,请注意查收', + ...result, + } +} + +export async function loginPublicWeiboSms( + orderNoInput: unknown, + taskIdInput: unknown, + input: { mobile?: unknown; code?: unknown; countryCode?: unknown; rid?: unknown } = {}, +) { + const orderNo = normalizeOrderNo(orderNoInput) + const taskId = normalizeId(taskIdInput) + const task = await loadTaskForOrder(orderNo, taskId) + assertWeiboTask(task) + if (task.execution_status === 'completed' || task.execution_status === 'cancelled') { + throw createHttpError('当前订单已结束,不能重新登录', { + statusCode: 409, + errorCode: 'semi_auto_task_closed', + }) + } + + const previousSessionId = task.connector_session_id + const { sessionId, session } = await loginWeiboSms( + { + taskId: task.id, + orderNo, + mobile: String(input.mobile ?? '').trim(), + code: String(input.code ?? '').trim(), + countryCode: String(input.countryCode ?? '86').trim() || '86', + rid: String(input.rid ?? '').trim(), + }, + task.connector_mode, + ) + const mapped = mapLoginUpdate(session) + const storedCredential = + session.status === 'authenticated' && session.hasCredential + ? exportWeiboSessionCredential(sessionId, task.connector_mode) + : null + + if (session.status !== 'authenticated') { + await withTransaction(async (client) => { + await client.query( + ` + UPDATE semi_auto_tasks + SET connector_session_id = $2, + login_status = $3, + last_error = $4, + updated_at = NOW() + WHERE id = $1 + `, + [task.id, sessionId, mapped.status, mapped.message], + ) + await appendTaskEvent(client, task.id, { + eventType: 'login_status_changed', + actorType: 'customer', + fromLoginStatus: task.login_status, + toLoginStatus: mapped.status, + fromExecutionStatus: task.execution_status, + toExecutionStatus: task.execution_status, + detail: { method: 'sms', message: mapped.message }, + }) + }) + throw createHttpError(mapped.message || '微博登录失败,请重试', { + statusCode: 409, + errorCode: 'weibo_login_failed', + }) + } + + const nextExecutionStatus: ExecutionStatus = 'waiting_operator' + await withTransaction(async (client) => { + const credentialId = storedCredential + ? await upsertSemiAutoCredentialWithClient(client, { + platform: 'weibo', + source: 'sms', + payload: storedCredential, + }) + : null + await client.query( + ` + UPDATE semi_auto_tasks + SET connector_session_id = $2, + credential_id = COALESCE($5, credential_id), + login_status = 'authenticated', + binding_status = 'confirmed', + execution_status = 'waiting_operator', + huya_uid = CASE WHEN $3 <> '' THEN $3 ELSE huya_uid END, + platform_nickname = CASE WHEN $4 <> '' THEN $4 ELSE platform_nickname END, + bind_game_account = CASE WHEN $4 <> '' THEN $4 ELSE bind_game_account END, + bind_game_role = CASE WHEN $3 <> '' THEN $3 ELSE bind_game_role END, + bind_game_channel = '微博', + auth_started_at = COALESCE(auth_started_at, NOW()), + authenticated_at = COALESCE(authenticated_at, NOW()), + bound_at = COALESCE(bound_at, NOW()), + last_error = '', + updated_at = NOW() + WHERE id = $1 + `, + [task.id, sessionId, mapped.uid, mapped.nickname, credentialId], + ) + await appendTaskEvent(client, task.id, { + eventType: 'login_status_changed', + actorType: 'customer', + fromLoginStatus: task.login_status, + toLoginStatus: 'authenticated', + fromExecutionStatus: task.execution_status, + toExecutionStatus: nextExecutionStatus, + detail: { method: 'sms', hasCredential: mapped.hasCredential, message: mapped.message }, + }) + if (task.binding_status !== 'confirmed') { + await appendTaskEvent(client, task.id, { + eventType: 'binding_status_changed', + actorType: 'customer', + fromBindingStatus: task.binding_status, + toBindingStatus: 'confirmed', + fromExecutionStatus: task.execution_status, + toExecutionStatus: nextExecutionStatus, + detail: { + gameAccount: mapped.nickname, + gameRole: mapped.uid, + gameChannel: '微博', + method: 'sms', + message: '微博登录成功,授权已完成', + }, + }) + } + }) + + if (previousSessionId && previousSessionId !== sessionId) { + await revokeWeiboSession(previousSessionId, task.connector_mode).catch(() => undefined) + } + const updated = await loadTask(task.id) + return { + task: mapTask(updated), + login: { + status: mapped.status, + qrContent: '', + qrImage: '', + expiresAt: session.expiresAt, + message: session.message, + }, + } +} + +export async function getPublicWeiboCountryCodes(orderNoInput: unknown, taskIdInput: unknown) { + const task = await loadTaskForOrder(normalizeOrderNo(orderNoInput), normalizeId(taskIdInput)) + assertWeiboTask(task) + return { countryCodes: await getWeiboCountryCodes(task.connector_mode) } +} + +export async function startPublicWeiboQrLogin(orderNoInput: unknown, taskIdInput: unknown) { + const task = await loadTaskForOrder(normalizeOrderNo(orderNoInput), normalizeId(taskIdInput)) + assertWeiboTask(task) + return startPublicLogin(orderNoInput, taskIdInput) +} + +export async function pollPublicWeiboQrLogin(orderNoInput: unknown, taskIdInput: unknown) { + const task = await loadTaskForOrder(normalizeOrderNo(orderNoInput), normalizeId(taskIdInput)) + assertWeiboTask(task) + return pollPublicLogin(orderNoInput, taskIdInput) +} + +export async function listAdminSemiAutoTasks(input: Record = {}) { + await backfillSemiAutoTasks() + const page = Math.max(1, Math.trunc(Number(input.page) || 1)) + const pageSize = Math.min(100, Math.max(1, Math.trunc(Number(input.pageSize) || 20))) + const platform = String(input.platform || '').trim() + const status = String(input.status || '').trim() + const keyword = String(input.keyword || '').trim() + const conditions = ['1 = 1'] + const params: unknown[] = [] + if (platform === 'huya' || platform === 'weibo') { + params.push(platform) + conditions.push(`task.platform = $${params.length}`) + } + if ( + [ + 'waiting_customer', + 'waiting_operator', + 'processing', + 'completed', + 'failed', + 'cancelled', + ].includes(status) + ) { + params.push(status) + conditions.push(`task.execution_status = $${params.length}`) + } + if (keyword) { + params.push(`%${keyword.replace(/[\\%_]/g, '\\$&')}%`) + const p = `$${params.length}` + conditions.push( + `(o.platform_order_id ILIKE ${p} OR oi.sku_name ILIKE ${p} OR oi.sku_code ILIKE ${p} OR task.huya_uid ILIKE ${p} OR task.bind_game_role ILIKE ${p})`, + ) + } + const where = conditions.join(' AND ') + const count = await query<{ total: number }>( + `SELECT COUNT(*)::int AS total + FROM semi_auto_tasks task + JOIN orders o ON o.id = task.order_id + JOIN order_items oi ON oi.id = task.order_item_id + WHERE ${where}`, + params, + ) + const listParams = [...params, pageSize, (page - 1) * pageSize] + const result = await query( + `${TASK_SELECT} + WHERE ${where} + ORDER BY + CASE task.execution_status + WHEN 'waiting_operator' THEN 0 + WHEN 'waiting_customer' THEN 1 + WHEN 'processing' THEN 2 + WHEN 'failed' THEN 3 + ELSE 4 + END, + task.updated_at DESC, + task.id DESC + LIMIT $${listParams.length - 1} OFFSET $${listParams.length}`, + listParams, + ) + return { + items: result.rows.map(mapTask), + pagination: { page, pageSize, total: Number(count.rows[0]?.total || 0) }, + } +} + +export async function getAdminSemiAutoTask(taskIdInput: unknown) { + const task = await loadTask(normalizeId(taskIdInput)) + const events = await query<{ + id: number + event_type: string + actor_type: string + actor_id: string + detail_json: Record + created_at: string + }>( + `SELECT id, event_type, actor_type, actor_id, detail_json, created_at + FROM semi_auto_task_events + WHERE task_id = $1 + ORDER BY id DESC + LIMIT 200`, + [task.id], + ) + return { + task: mapTask(task), + events: events.rows.map((event) => ({ + id: Number(event.id), + eventType: event.event_type, + actorType: event.actor_type, + actorId: event.actor_id, + detail: event.detail_json || {}, + createdAt: event.created_at, + })), + } +} + +export async function exportAdminSemiAutoCredential(taskIdInput: unknown, session: AdminSession) { + const task = await loadTask(normalizeId(taskIdInput)) + const adminUserId = Number(session.userId || 0) + if (task.assigned_admin_user_id && Number(task.assigned_admin_user_id) !== adminUserId) { + throw createHttpError('该任务已被其他客服领取', { + statusCode: 409, + errorCode: 'semi_auto_task_claimed', + }) + } + if (!task.credential_id) { + throw createHttpError('当前任务尚未保存账号 CK', { + statusCode: 404, + errorCode: 'semi_auto_credential_not_found', + }) + } + const credential = await loadSemiAutoCredential(task.credential_id) + if (!credential || credential.platform !== task.platform) { + throw createHttpError('账号 CK 不存在或与任务平台不一致', { + statusCode: 404, + errorCode: 'semi_auto_credential_not_found', + }) + } + const config = safeParseJson(task.semi_auto_config_json) + const targets = Array.isArray(config.browserTargets) ? config.browserTargets : [] + const configuredTarget = String( + targets.find((item): item is { url?: string } => Boolean(item && typeof item === 'object')) + ?.url || '', + ).trim() + const targetUrl = /^https:\/\//i.test(configuredTarget) + ? configuredTarget + : credential.platform === 'weibo' + ? 'https://weibo.com/' + : '' + const cookieHeader = targetUrl + ? buildSemiAutoCredentialCookieHeader(credential.cookies, targetUrl) + : '' + return { + credentialId: credential.id, + platform: credential.platform, + platformUid: credential.platformUid, + nickname: credential.nickname, + source: credential.source, + status: credential.status, + updatedAt: credential.updatedAt, + targetUrl, + cookieHeader, + cookies: credential.cookies, + } +} + +export async function claimAdminSemiAutoTask(taskIdInput: unknown, session: AdminSession) { + const taskId = normalizeId(taskIdInput) + const task = await loadTask(taskId) + const adminUserId = Number(session.userId || 0) + if (task.assigned_admin_user_id && Number(task.assigned_admin_user_id) !== adminUserId) { + throw createHttpError('该任务已被其他客服领取', { + statusCode: 409, + errorCode: 'semi_auto_task_claimed', + }) + } + await withTransaction(async (client) => { + await client.query( + `UPDATE semi_auto_tasks + SET assigned_admin_user_id = $2, updated_at = NOW() + WHERE id = $1`, + [taskId, adminUserId], + ) + await appendTaskEvent(client, taskId, { + eventType: 'task_claimed', + actorType: 'admin', + actorId: String(adminUserId), + }) + }) + return getAdminSemiAutoTask(taskId) +} + +export async function syncAdminSemiAutoTask(taskIdInput: unknown) { + const taskId = normalizeId(taskIdInput) + let task = await ensureConnectorSessionForTask(await loadTask(taskId)) + if (!task.connector_session_id) return getAdminSemiAutoTask(taskId) + if ( + task.login_status !== 'authenticated' && + task.login_status !== 'failed' && + task.login_status !== 'expired' + ) { + const login = await getLoginSessionForTask(task, task.connector_session_id) + await updateLoginTask(task, login, 'connector') + task = await loadTask(taskId) + } + if (task.login_status === 'authenticated' && task.binding_status !== 'confirmed') { + const binding = await getBindingForTask(task, task.connector_session_id) + await updateBindingTask(task, binding, 'connector') + } + return getAdminSemiAutoTask(taskId) +} + +export async function createAdminBrowserSession( + taskIdInput: unknown, + targetUrlInput: unknown, + session: AdminSession, +) { + const taskId = normalizeId(taskIdInput) + const task = await ensureConnectorSessionForTask(await loadTask(taskId)) + const adminUserId = Number(session.userId || 0) + if (task.assigned_admin_user_id && Number(task.assigned_admin_user_id) !== adminUserId) { + throw createHttpError('该任务已被其他客服领取', { + statusCode: 409, + errorCode: 'semi_auto_task_claimed', + }) + } + if (!task.connector_session_id || task.binding_status !== 'confirmed') { + throw createHttpError('客户尚未完成登录和绑定', { + statusCode: 409, + errorCode: 'semi_auto_binding_required', + }) + } + const config = safeParseJson(task.semi_auto_config_json) + const targets = Array.isArray(config.browserTargets) ? config.browserTargets : [] + const explicitTarget = String(targetUrlInput || '').trim() + const fallbackTarget = targets.find((item): item is { url?: string } => + Boolean(item && typeof item === 'object'), + )?.url + const targetUrl = explicitTarget || String(fallbackTarget || '') + const ticket = + task.platform === 'weibo' + ? await createWeiboBrowserTicket( + { sessionId: task.connector_session_id, targetUrl }, + task.connector_mode, + ) + : await createHuyaBrowserTicket( + { + sessionId: task.connector_session_id, + targetUrl, + }, + task.connector_mode, + ) + await withTransaction(async (client) => { + await client.query( + `UPDATE semi_auto_tasks + SET assigned_admin_user_id = COALESCE(assigned_admin_user_id, $2), + execution_status = CASE WHEN execution_status = 'waiting_operator' THEN 'processing' ELSE execution_status END, + updated_at = NOW() + WHERE id = $1`, + [taskId, adminUserId], + ) + await appendTaskEvent(client, taskId, { + eventType: 'browser_session_opened', + actorType: 'admin', + actorId: String(adminUserId), + detail: { targetUrl }, + }) + }) + return ticket +} + +export async function consumeSemiAutoInjectionTicket(ticketInput: unknown) { + const ticket = String(ticketInput || '').trim() + if (!ticket) { + throw createHttpError('注入票据无效', { + statusCode: 400, + errorCode: 'semi_auto_injection_ticket_invalid', + }) + } + if (ticket.startsWith(WEIBO_TICKET_PREFIX)) { + return consumeWeiboBrowserTicket(ticket) + } + return consumeHuyaBrowserTicket(ticket) +} + +async function resolveCompletionEvidence( + screenshots: unknown, + session: AdminSession, +): Promise { + const files = Array.isArray(screenshots) ? screenshots : [] + const uploaderId = String(session.userId || session.username || '') + const result: UploadedFileDto[] = [] + for (const item of files.slice(0, 10)) { + const source = item && typeof item === 'object' ? (item as Record) : {} + const objectKey = String(source.objectKey || source.object_key || '').trim() + if (!objectKey) continue + const asset = await getFileAssetByObjectKey(objectKey) + if ( + !asset || + asset.status !== 'active' || + asset.uploader_type !== 'admin' || + asset.uploader_id !== uploaderId || + asset.scene !== 'semi-auto-evidence' || + !ORDER_SERVICE_SCREENSHOT_CONTENT_TYPES.has(String(asset.content_type || '')) + ) { + throw createHttpError('完成截图无效,请重新上传', { + statusCode: 400, + errorCode: 'semi_auto_evidence_invalid', + }) + } + result.push({ + objectKey: asset.object_key, + url: buildFileUrl(asset.object_key), + thumbnailUrl: buildFileUrl(asset.thumbnail_object_key || asset.object_key), + mediumUrl: buildFileUrl(asset.medium_object_key || asset.object_key), + filename: asset.original_filename, + contentType: asset.content_type, + size: Number(asset.size_bytes || 0), + }) + } + return result +} + +export async function completeAdminSemiAutoTask( + taskIdInput: unknown, + payload: Record, + session: AdminSession, +) { + const taskId = normalizeId(taskIdInput) + let current = await loadTask(taskId) + if (current.execution_status === 'completed') return getAdminSemiAutoTask(taskId) + current = await ensureConnectorSessionForTask(current) + if (current.execution_status === 'completed') return getAdminSemiAutoTask(taskId) + if (current.execution_status === 'cancelled') { + throw createHttpError('任务已取消,不能完成', { + statusCode: 409, + errorCode: 'semi_auto_task_cancelled', + }) + } + const screenshots = await resolveCompletionEvidence(payload.screenshots || [], session) + const note = String(payload.note || '') + .trim() + .slice(0, 1000) + const externalOrderNo = String(payload.externalOrderNo || payload.external_order_no || '') + .trim() + .slice(0, 200) + const costFenRaw = Number(payload.costFen ?? payload.cost_fen) + const costFen = + Number.isFinite(costFenRaw) && costFenRaw >= 0 ? Math.trunc(costFenRaw) : undefined + const completionNote = [note, externalOrderNo ? `外部单号:${externalOrderNo}` : ''] + .filter(Boolean) + .join(';') + const adminUserId = Number(session.userId || 0) + + // 人工财务确认、履约状态和半自动任务完成必须同事务提交: + // 任何任务更新失败都会回滚成本快照、钱包扣减和履约状态,避免“已扣钱但任务未完成”。 + const completion = await withTransaction(async (client) => { + const task = await loadTaskForUpdateWithClient(client, taskId) + if (task.execution_status === 'completed') { + return { task, completedNow: false } + } + if (task.execution_status === 'cancelled') { + throw createHttpError('任务已取消,不能完成', { + statusCode: 409, + errorCode: 'semi_auto_task_cancelled', + }) + } + if (!task.connector_session_id || task.binding_status !== 'confirmed') { + throw createHttpError('客户尚未完成登录和绑定,不能完成履约', { + statusCode: 409, + errorCode: 'semi_auto_binding_required', + }) + } + if (task.assigned_admin_user_id && Number(task.assigned_admin_user_id) !== adminUserId) { + throw createHttpError('该任务已被其他客服领取', { + statusCode: 409, + errorCode: 'semi_auto_task_claimed', + }) + } + + await confirmManualFulfillment( + { + orderItemId: task.order_item_id, + platformKey: task.manual_platform_key, + ...(costFen !== undefined ? { costFen } : {}), + note: completionNote || '半自动履约完成', + }, + session, + { client }, + ) + + const updated = await client.query<{ id: number }>( + ` + UPDATE semi_auto_tasks + SET assigned_admin_user_id = COALESCE(assigned_admin_user_id, $2), + execution_status = 'completed', + completed_quantity = target_quantity, + completed_at = NOW(), + completion_note = $3, + external_order_no = $4, + completion_evidence_json = $5::jsonb, + last_error = '', + updated_at = NOW() + WHERE id = $1 + RETURNING id + `, + [taskId, adminUserId, note, externalOrderNo, JSON.stringify({ screenshots })], + ) + if (!updated.rows[0]) { + throw createHttpError('半自动履约任务状态更新失败', { + statusCode: 500, + errorCode: 'semi_auto_task_completion_failed', + }) + } + await appendTaskEvent(client, taskId, { + eventType: 'task_completed', + actorType: 'admin', + actorId: String(adminUserId), + fromExecutionStatus: task.execution_status, + toExecutionStatus: 'completed', + detail: { + note, + externalOrderNo, + screenshotCount: screenshots.length, + }, + }) + return { task, completedNow: true } + }) + + if (!completion.completedNow) { + return getAdminSemiAutoTask(taskId) + } + await runManualFulfillmentPostCommit(completion.task.order_item_id) + if (completion.task.connector_session_id) { + await revokeSessionForTask(completion.task, completion.task.connector_session_id).catch( + () => undefined, + ) + } + publishAdminOrderRealtimeChange(Number(completion.task.order_id)) + return getAdminSemiAutoTask(taskId) +} + +export async function cancelAdminSemiAutoTask( + taskIdInput: unknown, + payload: Record, + session: AdminSession, +) { + const taskId = normalizeId(taskIdInput) + const task = await loadTask(taskId) + if (task.execution_status === 'completed') { + throw createHttpError('已完成任务不能取消', { + statusCode: 409, + errorCode: 'semi_auto_task_completed', + }) + } + const reason = String(payload.reason || '') + .trim() + .slice(0, 500) + const adminUserId = Number(session.userId || 0) + await withTransaction(async (client) => { + await client.query( + ` + UPDATE semi_auto_tasks + SET execution_status = 'cancelled', + last_error = $2, + updated_at = NOW() + WHERE id = $1 + `, + [taskId, reason], + ) + await appendTaskEvent(client, taskId, { + eventType: 'task_cancelled', + actorType: 'admin', + actorId: String(adminUserId), + fromExecutionStatus: task.execution_status, + toExecutionStatus: 'cancelled', + detail: { reason }, + }) + }) + if (task.connector_session_id) { + await revokeSessionForTask(task, task.connector_session_id).catch(() => undefined) + } + publishAdminOrderRealtimeChange(Number(task.order_id)) + return getAdminSemiAutoTask(taskId) +} diff --git a/apps/backend/src/services/semi-auto/semi-auto-task.integration.test.ts b/apps/backend/src/services/semi-auto/semi-auto-task.integration.test.ts new file mode 100644 index 00000000..3ec65fc5 --- /dev/null +++ b/apps/backend/src/services/semi-auto/semi-auto-task.integration.test.ts @@ -0,0 +1,518 @@ +/** + * 半自动任务真实 PostgreSQL 集成测试。 + * + * SEMI_AUTO_TASK_TEST_DATABASE_URL=postgres://... \ + * npx tsx --test src/services/semi-auto/semi-auto-task.integration.test.ts + */ +import assert from 'node:assert/strict' +import test from 'node:test' + +const TEST_DATABASE_URL = String(process.env.SEMI_AUTO_TASK_TEST_DATABASE_URL || '').trim() + +test( + '人工渠道半自动任务可由客户入口和后台列表幂等回填', + { skip: !TEST_DATABASE_URL ? '未设置 SEMI_AUTO_TASK_TEST_DATABASE_URL' : false }, + async () => { + process.env.DATABASE_URL = TEST_DATABASE_URL + const { closeDb, query } = await import('../../db/client.js') + const { ensureSemiAutoTasksForOrder, listAdminSemiAutoTasks, listPublicSemiAutoTasks } = + await import('./semi-auto-task-service.js') + const suffix = `${Date.now()}_${Math.floor(Math.random() * 1_000_000)}` + const orderNo = `IT-SEMI-AUTO-${suffix}` + const skuKey = `半自动测试-${suffix}` + let orderId = 0 + let configId = 0 + try { + const order = await query<{ id: number }>( + ` + INSERT INTO orders ( + provider, platform, shop_id, shop_name, platform_order_id, + order_status, pay_status, total_amount, paid_at, created_at, updated_at + ) VALUES ( + '91kaquan', 'kuaishou-91', $1, '半自动测试店', $2, + 'paid', 'paid', 1000, NOW(), NOW(), NOW() + ) RETURNING id + `, + [`semi-auto-shop-${suffix}`, orderNo], + ) + orderId = Number(order.rows[0]?.id || 0) + assert.ok(orderId > 0) + const item = await query<{ id: number }>( + ` + INSERT INTO order_items ( + order_id, sku_code, sku_name, quantity, spec_json, item_snapshot_json, + revenue_amount_fen, revenue_basis, created_at, updated_at + ) VALUES ( + $1, $2, $3, 1, $4::jsonb, $4::jsonb, + 1000, 'order_total', NOW(), NOW() + ) RETURNING id + `, + [orderId, `semi-${suffix}`, skuKey, JSON.stringify({ skuNick: skuKey })], + ) + const orderItemId = Number(item.rows[0]?.id || 0) + assert.ok(orderItemId > 0) + const fulfillment = await query<{ id: number }>( + 'SELECT id FROM fulfillments WHERE order_item_id = $1 LIMIT 1', + [orderItemId], + ) + const fulfillmentId = Number(fulfillment.rows[0]?.id || 0) + assert.ok(fulfillmentId > 0) + + const config = await query<{ id: number }>( + ` + INSERT INTO manual_fulfillment_configs ( + sku_key, platform_key, credit_quantity, cost_mode, enabled, note, + channels_json, semi_auto_enabled, semi_auto_platform, + semi_auto_config_json, created_at, updated_at + ) VALUES ( + $1, 'fund_cash', 100, 'fixed', TRUE, '集成测试', + '[{"platformKey":"fund_cash","creditQuantity":100,"costMode":"fixed","enabled":true}]'::jsonb, + TRUE, 'huya', '{"pageTitle":"虎牙授权测试"}'::jsonb, + NOW(), NOW() + ) RETURNING id + `, + [skuKey], + ) + configId = Number(config.rows[0]?.id || 0) + assert.ok(configId > 0) + await query( + ` + UPDATE fulfillments + SET channel = 'manual', status = 'assigned', fulfillment_config_id = $2, + source = 'manual_confirm', updated_at = NOW() + WHERE id = $1 + `, + [fulfillmentId, configId], + ) + + // 客服工作台先打开时也必须看到任务,不能依赖客户先访问 `/c/订单号`。 + const adminList = await listAdminSemiAutoTasks({ keyword: orderNo }) + assert.equal(adminList.pagination.total, 1) + assert.equal(adminList.items[0]?.orderNo, orderNo) + + const first = await ensureSemiAutoTasksForOrder(orderNo) + const second = await ensureSemiAutoTasksForOrder(orderNo) + assert.equal(first.createdIds.length, 0) + assert.equal(second.createdIds.length, 0) + + const tasks = await listPublicSemiAutoTasks(orderNo) + assert.equal(tasks.length, 1) + assert.equal(tasks[0]?.orderItemId, orderItemId) + assert.equal(tasks[0]?.platform, 'huya') + assert.equal(tasks[0]?.orderNo, orderNo) + assert.equal(tasks[0]?.quantity, 1) + assert.equal(tasks[0]?.semiAutoConfig.pageTitle, '虎牙授权测试') + } finally { + if (orderId > 0) await query('DELETE FROM orders WHERE id = $1', [orderId]) + if (configId > 0) { + await query('DELETE FROM manual_fulfillment_configs WHERE id = $1', [configId]) + } + await closeDb() + } + }, +) + +test( + '半自动完成失败会连同财务确认一起回滚,成功后重复完成不重复扣成本', + { skip: !TEST_DATABASE_URL ? '未设置 SEMI_AUTO_TASK_TEST_DATABASE_URL' : false }, + async () => { + process.env.DATABASE_URL = TEST_DATABASE_URL + const { closeDb, query } = await import('../../db/client.js') + const { completeAdminSemiAutoTask, ensureSemiAutoTasksForOrder } = + await import('./semi-auto-task-service.js') + const suffix = `${Date.now()}_${Math.floor(Math.random() * 1_000_000)}` + const orderNo = `IT-SEMI-AUTO-ATOMIC-${suffix}` + const skuKey = `半自动原子性-${suffix}` + const triggerName = `trg_semi_auto_atomic_${suffix}` + const functionName = `fn_semi_auto_atomic_${suffix}` + let orderId = 0 + let configId = 0 + let adminId = 0 + let triggerCreated = false + try { + const admin = await query<{ id: number }>( + `INSERT INTO admin_users (username, password_hash, role, status, created_at, updated_at) + VALUES ($1, 'x', 'support', 'active', NOW(), NOW()) RETURNING id`, + [`it_semi_auto_admin_${suffix}`], + ) + adminId = Number(admin.rows[0]?.id || 0) + assert.ok(adminId > 0) + + const order = await query<{ id: number }>( + ` + INSERT INTO orders ( + provider, platform, shop_id, shop_name, platform_order_id, + order_status, pay_status, total_amount, paid_at, created_at, updated_at + ) VALUES ( + '91kaquan', 'kuaishou-91', $1, '半自动原子性测试店', $2, + 'paid', 'paid', 1000, NOW(), NOW(), NOW() + ) RETURNING id + `, + [`semi-auto-atomic-shop-${suffix}`, orderNo], + ) + orderId = Number(order.rows[0]?.id || 0) + assert.ok(orderId > 0) + const item = await query<{ id: number }>( + ` + INSERT INTO order_items ( + order_id, sku_code, sku_name, quantity, spec_json, item_snapshot_json, + revenue_amount_fen, revenue_basis, created_at, updated_at + ) VALUES ( + $1, $2, $3, 1, $4::jsonb, $4::jsonb, + 1000, 'order_total', NOW(), NOW() + ) RETURNING id + `, + [orderId, `semi-atomic-${suffix}`, skuKey, JSON.stringify({ skuNick: skuKey })], + ) + const orderItemId = Number(item.rows[0]?.id || 0) + assert.ok(orderItemId > 0) + const fulfillment = await query<{ id: number }>( + 'SELECT id FROM fulfillments WHERE order_item_id = $1 LIMIT 1', + [orderItemId], + ) + const fulfillmentId = Number(fulfillment.rows[0]?.id || 0) + assert.ok(fulfillmentId > 0) + + const config = await query<{ id: number }>( + ` + INSERT INTO manual_fulfillment_configs ( + sku_key, platform_key, credit_quantity, cost_mode, enabled, note, + channels_json, semi_auto_enabled, semi_auto_platform, + semi_auto_config_json, created_at, updated_at + ) VALUES ( + $1, 'on_account', 0, 'variable', TRUE, '原子性集成测试', + '[{"platformKey":"on_account","creditQuantity":0,"costMode":"variable","enabled":true}]'::jsonb, + TRUE, 'huya', '{}'::jsonb, NOW(), NOW() + ) RETURNING id + `, + [skuKey], + ) + configId = Number(config.rows[0]?.id || 0) + assert.ok(configId > 0) + await query( + ` + UPDATE fulfillments + SET channel = 'manual', status = 'assigned', fulfillment_config_id = $2, + source = 'manual_confirm', updated_at = NOW() + WHERE id = $1 + `, + [fulfillmentId, configId], + ) + + const ensured = await ensureSemiAutoTasksForOrder(orderNo) + const taskId = Number(ensured.createdIds[0] || 0) + assert.ok(taskId > 0) + await query( + ` + UPDATE semi_auto_tasks + SET connector_session_id = $2, + login_status = 'authenticated', + binding_status = 'confirmed', + execution_status = 'waiting_operator', + authenticated_at = NOW(), + bound_at = NOW(), + updated_at = NOW() + WHERE id = $1 + `, + [taskId, `it-session-${suffix}`], + ) + + await query( + ` + CREATE OR REPLACE FUNCTION ${functionName}() RETURNS trigger + LANGUAGE plpgsql AS $$ + BEGIN + IF NEW.execution_status = 'completed' THEN + RAISE EXCEPTION 'forced semi auto completion failure'; + END IF; + RETURN NEW; + END; + $$ + `, + ) + await query( + ` + CREATE TRIGGER ${triggerName} + BEFORE UPDATE OF execution_status ON semi_auto_tasks + FOR EACH ROW EXECUTE FUNCTION ${functionName}() + `, + ) + triggerCreated = true + + const session = { + userId: adminId, + role: 'support', + displayName: '半自动原子性客服', + } as never + await assert.rejects( + () => + completeAdminSemiAutoTask( + taskId, + { costFen: 123, note: '触发任务更新失败以验证回滚' }, + session, + ), + /forced semi auto completion failure/, + ) + + const rolledBack = await query<{ + execution_status: string + snapshot_count: number + bill_count: number + fulfillment_channel: string + }>( + ` + SELECT + task.execution_status, + (SELECT COUNT(*)::int FROM cost_snapshots cs WHERE cs.order_item_id = $2) AS snapshot_count, + (SELECT COUNT(*)::int FROM on_account_bills oab WHERE oab.order_item_id = $2) AS bill_count, + f.channel AS fulfillment_channel + FROM semi_auto_tasks task + JOIN fulfillments f ON f.id = task.fulfillment_id + WHERE task.id = $1 + `, + [taskId, orderItemId], + ) + assert.equal(rolledBack.rows[0]?.execution_status, 'waiting_operator') + assert.equal(Number(rolledBack.rows[0]?.snapshot_count), 0) + assert.equal(Number(rolledBack.rows[0]?.bill_count), 0) + assert.equal(rolledBack.rows[0]?.fulfillment_channel, 'manual') + + await query(`DROP TRIGGER ${triggerName} ON semi_auto_tasks`) + triggerCreated = false + await query(`DROP FUNCTION ${functionName}()`) + + const completed = await completeAdminSemiAutoTask( + taskId, + { costFen: 123, note: '事务重试成功' }, + session, + ) + assert.equal(completed.task.executionStatus, 'completed') + const afterCompletion = await query<{ snapshot_count: number; bill_count: number }>( + ` + SELECT + (SELECT COUNT(*)::int FROM cost_snapshots cs WHERE cs.order_item_id = $1) AS snapshot_count, + (SELECT COUNT(*)::int FROM on_account_bills oab WHERE oab.order_item_id = $1) AS bill_count + `, + [orderItemId], + ) + assert.equal(Number(afterCompletion.rows[0]?.snapshot_count), 1) + assert.equal(Number(afterCompletion.rows[0]?.bill_count), 1) + + await completeAdminSemiAutoTask(taskId, { costFen: 123 }, session) + const afterDuplicate = await query<{ snapshot_count: number }>( + 'SELECT COUNT(*)::int AS snapshot_count FROM cost_snapshots WHERE order_item_id = $1', + [orderItemId], + ) + assert.equal(Number(afterDuplicate.rows[0]?.snapshot_count), 1) + } finally { + if (triggerCreated) { + await query(`DROP TRIGGER IF EXISTS ${triggerName} ON semi_auto_tasks`) + } + await query(`DROP FUNCTION IF EXISTS ${functionName}()`) + if (orderId > 0) { + await query( + 'DELETE FROM cost_snapshots WHERE order_item_id IN (SELECT id FROM order_items WHERE order_id = $1)', + [orderId], + ) + await query( + 'DELETE FROM on_account_bills WHERE order_item_id IN (SELECT id FROM order_items WHERE order_id = $1)', + [orderId], + ) + await query( + 'DELETE FROM cost_exceptions WHERE subject_id IN (SELECT id FROM order_items WHERE order_id = $1)', + [orderId], + ) + await query('DELETE FROM orders WHERE id = $1', [orderId]) + } + // 已过账总账凭证按财务规则不可物理删除;测试只清理可重建销售投影。 + await query( + `DELETE FROM sales_daily_facts + WHERE stat_date = (NOW() AT TIME ZONE 'Asia/Shanghai')::date`, + ) + if (configId > 0) { + await query('DELETE FROM manual_fulfillment_configs WHERE id = $1', [configId]) + } + if (adminId > 0) { + await query('DELETE FROM admin_users WHERE id = $1', [adminId]) + } + await closeDb() + } + }, +) + +test( + '微博账号 CK 以账号级密文保存并可解密加载', + { skip: !TEST_DATABASE_URL ? '未设置 SEMI_AUTO_TASK_TEST_DATABASE_URL' : false }, + async () => { + process.env.DATABASE_URL = TEST_DATABASE_URL + process.env.SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY = + 'integration-test-semi-auto-credential-key-123456' + const { closeDb, query, withTransaction } = await import('../../db/client.js') + const { loadSemiAutoCredential, upsertSemiAutoCredentialWithClient } = + await import('./semi-auto-credential-service.js') + const suffix = `${Date.now()}_${Math.floor(Math.random() * 1_000_000)}` + let credentialId = 0 + try { + credentialId = await withTransaction((client) => + upsertSemiAutoCredentialWithClient(client, { + platform: 'weibo', + source: 'sms', + payload: { + platformUid: `it-weibo-${suffix}`, + nickname: '集成测试微博', + cookies: [ + { + name: 'SUB', + value: `secret-sub-${suffix}`, + domain: '.weibo.com', + path: '/', + secure: true, + httpOnly: true, + }, + ], + }, + }), + ) + const raw = await query<{ + credential_ciphertext: string + credential_source: string + credential_status: string + }>( + `SELECT credential_ciphertext, credential_source, credential_status + FROM semi_auto_credentials WHERE id = $1`, + [credentialId], + ) + assert.equal(raw.rows[0]?.credential_source, 'sms') + assert.equal(raw.rows[0]?.credential_status, 'valid') + assert.ok(raw.rows[0]?.credential_ciphertext.startsWith('enc:v1:')) + assert.equal(raw.rows[0]?.credential_ciphertext.includes(`secret-sub-${suffix}`), false) + + const credential = await loadSemiAutoCredential(credentialId) + assert.equal(credential?.platformUid, `it-weibo-${suffix}`) + assert.equal(credential?.cookies[0]?.value, `secret-sub-${suffix}`) + } finally { + if (credentialId > 0) { + await query('DELETE FROM semi_auto_credentials WHERE id = $1', [credentialId]) + } + delete process.env.SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY + await closeDb() + } + }, +) + +test( + '开发 Mock 可生成半自动履约测试单并回填任务', + { skip: !TEST_DATABASE_URL ? '未设置 SEMI_AUTO_TASK_TEST_DATABASE_URL' : false }, + async () => { + process.env.DATABASE_URL = TEST_DATABASE_URL + process.env.ENABLE_DEV_MOCK = '1' + const { closeDb, query } = await import('../../db/client.js') + const { createSemiAutoMock } = await import('../dev-mock/dev-mock-service.js') + const suffix = `${Date.now()}_${Math.floor(Math.random() * 1_000_000)}` + const orderNo = `IT-MOCK-SA-${suffix}` + const skuKey = `半自动Mock-${suffix}` + let orderId = 0 + let configId = 0 + try { + const result = await createSemiAutoMock({ + orderNo, + skuName: skuKey, + quantity: 1, + pageTitle: 'Mock 集成测试', + connectorMode: 'embedded', + }) + orderId = result.orderId + configId = result.configId + assert.ok(result.orderItemId > 0) + assert.ok(result.fulfillmentId > 0) + assert.ok(result.taskId > 0) + assert.equal(result.connectorMode, 'embedded') + assert.equal(result.customerPath, `/c/${encodeURIComponent(orderNo)}`) + + const row = await query<{ + channel: string + fulfillment_status: string + fulfillment_config_id: number + semi_auto_enabled: boolean + semi_auto_platform: string + connector_mode: string + login_status: string + binding_status: string + execution_status: string + }>( + ` + SELECT + f.channel, + f.status AS fulfillment_status, + f.fulfillment_config_id, + cfg.semi_auto_enabled, + cfg.semi_auto_platform, + task.connector_mode, + task.login_status, + task.binding_status, + task.execution_status + FROM semi_auto_tasks task + JOIN fulfillments f ON f.id = task.fulfillment_id + JOIN manual_fulfillment_configs cfg ON cfg.id = task.manual_fulfillment_config_id + WHERE task.order_item_id = $1 + `, + [result.orderItemId], + ) + assert.equal(row.rows[0]?.channel, 'manual') + assert.equal(row.rows[0]?.fulfillment_status, 'assigned') + assert.equal(Number(row.rows[0]?.fulfillment_config_id), result.configId) + assert.equal(row.rows[0]?.semi_auto_enabled, true) + assert.equal(row.rows[0]?.semi_auto_platform, 'huya') + assert.equal(row.rows[0]?.connector_mode, 'embedded') + assert.equal(row.rows[0]?.login_status, 'waiting_login') + assert.equal(row.rows[0]?.binding_status, 'not_started') + assert.equal(row.rows[0]?.execution_status, 'waiting_customer') + } finally { + if (orderId > 0) await query('DELETE FROM orders WHERE id = $1', [orderId]) + if (configId > 0) { + await query('DELETE FROM manual_fulfillment_configs WHERE id = $1', [configId]) + } + delete process.env.ENABLE_DEV_MOCK + await closeDb() + } + }, +) + +test( + '开发 Mock 可显式选择内置 Mock Connector', + { skip: !TEST_DATABASE_URL ? '未设置 SEMI_AUTO_TASK_TEST_DATABASE_URL' : false }, + async () => { + process.env.DATABASE_URL = TEST_DATABASE_URL + process.env.ENABLE_DEV_MOCK = '1' + const { closeDb, query } = await import('../../db/client.js') + const { createSemiAutoMock } = await import('../dev-mock/dev-mock-service.js') + const suffix = `${Date.now()}_${Math.floor(Math.random() * 1_000_000)}` + const orderNo = `IT-MOCK-SA-MOCK-${suffix}` + let orderId = 0 + let configId = 0 + try { + const result = await createSemiAutoMock({ + orderNo, + skuName: `半自动Mock连接器-${suffix}`, + quantity: 1, + connectorMode: 'mock', + }) + orderId = result.orderId + configId = result.configId + assert.equal(result.connectorMode, 'mock') + + const row = await query<{ connector_mode: string }>( + 'SELECT connector_mode FROM semi_auto_tasks WHERE id = $1', + [result.taskId], + ) + assert.equal(row.rows[0]?.connector_mode, 'mock') + } finally { + if (orderId > 0) await query('DELETE FROM orders WHERE id = $1', [orderId]) + if (configId > 0) { + await query('DELETE FROM manual_fulfillment_configs WHERE id = $1', [configId]) + } + delete process.env.ENABLE_DEV_MOCK + await closeDb() + } + }, +) diff --git a/apps/backend/src/services/semi-auto/weibo-connector-client.ts b/apps/backend/src/services/semi-auto/weibo-connector-client.ts new file mode 100644 index 00000000..bc9d50d2 --- /dev/null +++ b/apps/backend/src/services/semi-auto/weibo-connector-client.ts @@ -0,0 +1,136 @@ +import { createHttpError } from '../../utils/http.js' +import type { + ConnectorBindingSession, + ConnectorBrowserTicket, + ConnectorInjectionPayload, + ConnectorLoginSession, + SemiAutoConnectorMode, +} from './huya-connector-client.js' +import { + type WeiboSerializedCookie, + type WeiboStoredCredential, + type WeiboSmsSendResult, + weiboNativeConnector, + type WeiboCountryCode, +} from './weibo-native/weibo-native-connector.js' + +/** + * 微博半自动 Connector 客户端。 + * + * Mock 闭环阶段只实现 embedded(order_site 进程内);external 保留接口, + * 后续接生产微博 Connector 时再补远程请求。 + */ + +function assertEmbedded(mode: SemiAutoConnectorMode) { + if (mode !== 'embedded') { + throw createHttpError('微博半自动履约目前仅支持内置 Connector', { + statusCode: 503, + errorCode: 'weibo_connector_mode_unsupported', + }) + } +} + +export async function createWeiboLoginSession( + input: { taskId: number; orderNo: string }, + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + return weiboNativeConnector.createQrLoginSession(input) +} + +export async function getWeiboLoginSession( + sessionId: string, + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + return weiboNativeConnector.getQrLoginSession(sessionId) +} + +export async function sendWeiboSmsCode( + input: { + taskId: number + mobile: string + countryCode: string + mfaId?: string + }, + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + return weiboNativeConnector.sendSmsCode(input) +} + +export async function loginWeiboSms( + input: { + taskId: number + orderNo: string + mobile: string + code: string + countryCode?: string + rid?: string + }, + mode: SemiAutoConnectorMode = 'embedded', +): Promise<{ sessionId: string; session: ConnectorLoginSession }> { + assertEmbedded(mode) + return weiboNativeConnector.loginWithSms(input) +} + +export function exportWeiboSessionCredential( + sessionId: string, + mode: SemiAutoConnectorMode = 'embedded', +): WeiboStoredCredential { + assertEmbedded(mode) + return weiboNativeConnector.exportSessionCredential(sessionId) +} + +export async function restoreWeiboSessionFromCredential( + input: { + taskId: number + orderNo: string + platformUid: string + nickname: string + cookies: WeiboSerializedCookie[] + }, + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + return weiboNativeConnector.restoreSessionFromCredential(input) +} + +export async function getWeiboCountryCodes( + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + return weiboNativeConnector.getCountryCodes() +} + +export async function getWeiboBinding( + sessionId: string, + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + return weiboNativeConnector.getBinding(sessionId) +} + +export async function createWeiboBrowserTicket( + input: { sessionId: string; targetUrl?: string }, + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + return weiboNativeConnector.createBrowserTicket(input) +} + +export async function consumeWeiboBrowserTicket( + ticket: string, + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + return weiboNativeConnector.consumeBrowserTicket(ticket) +} + +export async function revokeWeiboSession( + sessionId: string, + mode: SemiAutoConnectorMode = 'embedded', +): Promise { + assertEmbedded(mode) + await weiboNativeConnector.revokeSession(sessionId) +} diff --git a/apps/backend/src/services/semi-auto/weibo-native/weibo-native-connector.ts b/apps/backend/src/services/semi-auto/weibo-native/weibo-native-connector.ts new file mode 100644 index 00000000..1893b9f1 --- /dev/null +++ b/apps/backend/src/services/semi-auto/weibo-native/weibo-native-connector.ts @@ -0,0 +1,1069 @@ +/** + * order_site 内置微博半自动 Connector(Mock 闭环用)。 + * + * 支持: + * - 微博扫码登录(passport /sso/v2/qrcode/*) + * - 手机号短信验证码登录(passport /sso/v2/sms/send + /sso/v2/login) + * - 登录后账号信息 + * - 一次性浏览器注入票据 + * + * 手机号和验证码只保存在短期内存会话中;登录成功后的账号 Cookie 由任务服务 + * 导出为账号级凭证,经 AES-256-GCM 加密后落库,不写日志。 + */ + +import crypto from 'node:crypto' + +import { createHttpError } from '../../../utils/http.js' +import type { + ConnectorBindingSession, + ConnectorBrowserTicket, + ConnectorInjectionPayload, + ConnectorLoginSession, +} from '../huya-connector-client.js' + +const PASSPORT_BASE = 'https://passport.weibo.com' +const WEIBO_BASE = 'https://weibo.com' +const WEIBO_LOGIN_URL = + 'https://weibo.com/newlogin?tabtype=weibo&gid=102803&openLoginLayer=0&url=https%3A%2F%2Fweibo.com%2F' +const WEIBO_LOGIN_VER = '20250520' +const SIGNIN_REFERER = + `${PASSPORT_BASE}/sso/signin?entry=miniblog&source=miniblog&disp=popup` + + `&url=${encodeURIComponent(WEIBO_LOGIN_URL)}&from=weibopro` +const PC_UA = + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' + + 'Chrome/155.0.0.0 Safari/537.36' + +const LOGIN_QR_TTL_MS = 5 * 60 * 1000 +const CREDENTIAL_TTL_MS = 24 * 60 * 60 * 1000 +const BROWSER_TICKET_TTL_MS = 2 * 60 * 1000 +const SMS_COOKIE_TTL_MS = 10 * 60 * 1000 +const COUNTRY_CODE_TTL_MS = 60 * 60 * 1000 +const MAX_SESSIONS = 200 +const TICKET_PREFIX = 'weibo-ticket-' +export const WEIBO_YIDUN_CAPTCHA_ID = '7cda0ba2785647ada4d6e946ddb2d465' + +export type WeiboCountryCode = { + code: string + name: string +} + +const FALLBACK_COUNTRY_CODES: WeiboCountryCode[] = [ + { code: '86', name: '中国' }, + { code: '852', name: '中国香港' }, + { code: '886', name: '中国台湾' }, + { code: '853', name: '中国澳门' }, + { code: '81', name: '日本' }, +] + +// 微博网页登录 JS 会对手机号/验证码做一层 XOR + base64url + 字母替换编码。 +const SSO_ENCODE_KEY = 'x9Lp2WnQ' +const SSO_BASE_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_' +const SSO_MAP_ALPHABET = 'iaAehJvQ7RIDBX5L31T0kcf9ElVbpMdPZSmzoN_uxGO-2rFUtyY6sHCwKj4Wqgn8' + +function encodeSsoField(value: string): string { + const bytes = Buffer.from(String(value || ''), 'utf8') + const key = Buffer.from(SSO_ENCODE_KEY, 'utf8') + const xored = Buffer.allocUnsafe(bytes.length) + for (let index = 0; index < bytes.length; index += 1) { + const byte = bytes[index] ?? 0 + const keyByte = key[index % key.length] ?? 0 + xored[index] = byte ^ keyByte + } + const encoded = xored + .toString('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, '') + let result = '' + for (const char of encoded) { + const alphabetIndex = SSO_BASE_ALPHABET.indexOf(char) + result += alphabetIndex >= 0 ? SSO_MAP_ALPHABET[alphabetIndex] : char + } + return result +} + +type FetchLike = typeof fetch + +type WeiboAccount = { + uid: string + nickname: string + avatar: string +} + +type WeiboTicket = { + ticket: string + targetUrl: string + cookies: WeiboSerializedCookie[] + expiresAtMs: number +} + +export type WeiboSerializedCookie = { + name: string + value: string + domain: string + path: string + secure: boolean + httpOnly: boolean + hostOnly?: boolean + expiresAt: string | null +} + +type StoredWeiboCookie = WeiboSerializedCookie & { + domain: string + hostOnly: boolean + expiresAtMs: number +} + +class WeiboCookieJar { + private readonly values = new Map() + + addFromResponse(headers: Headers, requestUrl: string): void { + const url = new URL(requestUrl) + for (const raw of readSetCookie(headers)) { + this.addSetCookie(raw, url) + } + } + + headerFor(requestUrl: string): string { + const url = new URL(requestUrl) + const nowMs = Date.now() + const pairs: string[] = [] + for (const [key, cookie] of this.values) { + if (cookie.expiresAtMs > 0 && cookie.expiresAtMs <= nowMs) { + this.values.delete(key) + continue + } + if (!this.matches(cookie, url)) continue + pairs.push(`${cookie.name}=${cookie.value}`) + } + return pairs.join('; ') + } + + value(requestUrl: string, name: string): string { + const url = new URL(requestUrl) + for (const cookie of this.values.values()) { + if (cookie.name === name && this.matches(cookie, url)) return cookie.value + } + return '' + } + + has(requestUrl: string, name: string): boolean { + return Boolean(this.value(requestUrl, name)) + } + + serialize(requestUrl = WEIBO_BASE): WeiboSerializedCookie[] { + const url = new URL(requestUrl) + return Array.from(this.values.values()) + .filter((cookie) => this.matches(cookie, url)) + .map((cookie) => this.toSerialized(cookie)) + .filter((cookie): cookie is WeiboSerializedCookie => cookie !== null) + } + + serializeAll(): WeiboSerializedCookie[] { + return Array.from(this.values.values()) + .map((cookie) => this.toSerialized(cookie)) + .filter((cookie): cookie is WeiboSerializedCookie => cookie !== null) + } + + static fromSerialized(cookies: WeiboSerializedCookie[]): WeiboCookieJar { + const jar = new WeiboCookieJar() + for (const cookie of cookies) { + const domain = String(cookie.domain || '') + .trim() + .toLowerCase() + if (!cookie.name || !domain) continue + const expiresAtMs = cookie.expiresAt ? Date.parse(cookie.expiresAt) : 0 + jar.values.set(`${cookie.name}\u0000${domain}\u0000${cookie.path || '/'}`, { + name: cookie.name, + value: String(cookie.value || ''), + domain, + path: cookie.path || '/', + secure: cookie.secure === true, + httpOnly: cookie.httpOnly === true, + expiresAt: cookie.expiresAt || null, + hostOnly: typeof cookie.hostOnly === 'boolean' ? cookie.hostOnly : !domain.startsWith('.'), + expiresAtMs: Number.isFinite(expiresAtMs) ? expiresAtMs : 0, + }) + } + return jar + } + + clear(): void { + this.values.clear() + } + + private toSerialized(cookie: StoredWeiboCookie): WeiboSerializedCookie | null { + if (cookie.expiresAtMs > 0 && cookie.expiresAtMs <= Date.now()) return null + return { + name: cookie.name, + value: cookie.value, + domain: cookie.domain, + path: cookie.path, + secure: cookie.secure, + httpOnly: cookie.httpOnly, + hostOnly: cookie.hostOnly, + expiresAt: cookie.expiresAtMs > 0 ? new Date(cookie.expiresAtMs).toISOString() : null, + } + } + + private addSetCookie(raw: string, requestUrl: URL): void { + const parts = String(raw || '') + .split(';') + .map((part) => part.trim()) + .filter(Boolean) + const first = parts.shift() || '' + const separator = first.indexOf('=') + if (separator <= 0) return + const name = first.slice(0, separator).trim() + const value = first.slice(separator + 1).trim() + if (!name) return + + let domain = '' + let cookiePath = '' + let secure = false + let httpOnly = false + let expiresAtMs = 0 + for (const part of parts) { + const index = part.indexOf('=') + const key = (index >= 0 ? part.slice(0, index) : part).trim().toLowerCase() + const attr = index >= 0 ? part.slice(index + 1).trim() : '' + if (key === 'domain') domain = attr.toLowerCase() + else if (key === 'path') cookiePath = attr || '/' + else if (key === 'secure') secure = true + else if (key === 'httponly') httpOnly = true + else if (key === 'max-age') { + const seconds = Number(attr) + if (Number.isFinite(seconds)) { + expiresAtMs = seconds <= 0 ? 1 : Date.now() + seconds * 1000 + } + } else if (key === 'expires') { + const parsed = Date.parse(attr) + if (Number.isFinite(parsed)) expiresAtMs = parsed + } + } + + const hostOnly = !domain + const normalizedDomain = (domain || requestUrl.hostname).toLowerCase() + if ( + !hostOnly && + requestUrl.hostname !== normalizedDomain.replace(/^\./, '') && + !requestUrl.hostname.endsWith(normalizedDomain) + ) { + return + } + const path = cookiePath || defaultCookiePath(requestUrl.pathname) + const key = `${name}\u0000${normalizedDomain}\u0000${path}` + if (expiresAtMs > 0 && expiresAtMs <= Date.now()) { + this.values.delete(key) + return + } + this.values.set(key, { + name, + value, + domain: normalizedDomain, + path, + secure, + httpOnly, + expiresAt: expiresAtMs > 0 ? new Date(expiresAtMs).toISOString() : null, + hostOnly, + expiresAtMs, + }) + } + + private matches(cookie: StoredWeiboCookie, url: URL): boolean { + if (cookie.secure && url.protocol !== 'https:') return false + const hostname = url.hostname.toLowerCase() + const cookieDomain = cookie.domain.replace(/^\./, '') + const domainMatches = cookie.hostOnly + ? hostname === cookieDomain + : hostname === cookieDomain || hostname.endsWith(`.${cookieDomain}`) + if (!domainMatches) return false + const requestPath = url.pathname || '/' + return ( + requestPath === cookie.path || + requestPath.startsWith(cookie.path.endsWith('/') ? cookie.path : `${cookie.path}/`) + ) + } +} + +function defaultCookiePath(pathname: string): string { + const value = String(pathname || '/') + const index = value.lastIndexOf('/') + return index <= 0 ? '/' : value.slice(0, index) +} + +type WeiboSession = { + sessionId: string + taskId: number + orderNo: string + createdAtMs: number + expiresAtMs: number + status: ConnectorLoginSession['status'] + qrid: string + qrImage: string + message: string + cookies: WeiboCookieJar + account: WeiboAccount | null + tickets: Map +} + +type SmsLoginState = { + taskId: number + mobile: string + cookies: WeiboCookieJar + mfaId: string + createdAtMs: number + expiresAtMs: number +} + +export type WeiboStoredCredential = { + platformUid: string + nickname: string + cookies: WeiboSerializedCookie[] +} + +export type WeiboSmsSendResult = { + mfaRequired: boolean + mfaId?: string + captchaId?: string +} + +export type WeiboNativeConnectorOptions = { + fetchImpl?: FetchLike + now?: () => number + timeoutMs?: number + stateRoot?: string +} + +function iso(value: number): string { + return new Date(value).toISOString() +} + +function readSetCookie(headers: Headers): string[] { + const withGetSetCookie = headers as Headers & { getSetCookie?: () => string[] } + if (typeof withGetSetCookie.getSetCookie === 'function') { + return withGetSetCookie.getSetCookie() + } + return (headers.get('set-cookie') || '').split(/,(?=\s*[^;,=\s]+=)/g).filter(Boolean) +} + +export class WeiboNativeConnector { + private readonly sessions = new Map() + private readonly smsSessions = new Map() + private countryCodeCache: { items: WeiboCountryCode[]; expiresAtMs: number } | null = null + private readonly fetchImpl: FetchLike + private readonly now: () => number + private readonly timeoutMs: number + + constructor(options: WeiboNativeConnectorOptions = {}) { + this.fetchImpl = options.fetchImpl || fetch + this.now = options.now || (() => Date.now()) + this.timeoutMs = Math.max(1000, options.timeoutMs || 15_000) + } + + async createQrLoginSession(input: { + taskId: number + orderNo: string + }): Promise { + this.prune() + const sessionId = crypto.randomBytes(18).toString('base64url') + const cookies = await this.createBootstrapSession() + const response = await this.fetchImpl( + `${PASSPORT_BASE}/sso/v2/qrcode/image?entry=miniblog&size=180`, + { + method: 'GET', + headers: this.jsonHeaders(PASSPORT_BASE, cookies), + signal: AbortSignal.timeout(this.timeoutMs), + }, + ) + cookies.addFromResponse(response.headers, `${PASSPORT_BASE}/sso/v2/qrcode/image`) + if (!response.ok) { + throw createHttpError(`获取微博登录二维码失败:HTTP ${response.status}`, { + statusCode: 502, + errorCode: 'weibo_qrcode_failed', + }) + } + const payload = (await response.json().catch(() => null)) as { + retcode?: number + msg?: string + data?: { qrid?: string; image?: string } + } | null + if (!payload || Number(payload.retcode) !== 20000000 || !payload.data?.qrid) { + throw createHttpError(payload?.msg || '获取微博登录二维码失败', { + statusCode: 502, + errorCode: 'weibo_qrcode_failed', + }) + } + const qrImage = await this.downloadQrImage(String(payload.data.image || '')) + const nowMs = this.now() + const session: WeiboSession = { + sessionId, + taskId: Number(input.taskId) || 0, + orderNo: String(input.orderNo || ''), + createdAtMs: nowMs, + expiresAtMs: nowMs + CREDENTIAL_TTL_MS, + status: 'waiting_scan', + qrid: String(payload.data.qrid), + qrImage, + message: '请使用微博 App 扫码登录', + cookies, + account: null, + tickets: new Map(), + } + this.sessions.set(sessionId, session) + return this.loginView(session) + } + + async getQrLoginSession(sessionId: string): Promise { + const session = this.requireSession(sessionId) + if (session.status === 'authenticated') return this.loginView(session) + if (session.status === 'expired' || session.status === 'failed') return this.loginView(session) + const checkUrl = + `${PASSPORT_BASE}/sso/v2/qrcode/check?entry=miniblog&source=miniblog` + + `&url=${encodeURIComponent(WEIBO_LOGIN_URL)}&qrid=${encodeURIComponent(session.qrid)}` + + `&disp=popup&rid=norid&ver=${WEIBO_LOGIN_VER}` + const response = await this.fetchImpl(checkUrl, { + method: 'GET', + headers: this.jsonHeaders(checkUrl, session.cookies), + signal: AbortSignal.timeout(this.timeoutMs), + }) + session.cookies.addFromResponse(response.headers, checkUrl) + if (!response.ok) { + session.status = 'failed' + session.message = `微博扫码状态查询失败:HTTP ${response.status}` + return this.loginView(session) + } + const payload = (await response.json().catch(() => null)) as { + retcode?: number + msg?: string + data?: { url?: string } + } | null + const retcode = Number(payload?.retcode || 0) + if (retcode === 20000000) { + const loginUrl = String(payload?.data?.url || '').trim() + if (!loginUrl) { + session.status = 'failed' + session.message = '微博登录成功但缺少跳转地址' + return this.loginView(session) + } + await this.finishLogin(session, loginUrl) + return this.loginView(session) + } + if ([50114000, 50114001].includes(retcode)) { + session.status = 'waiting_scan' + session.message = '请使用微博 App 扫码登录' + return this.loginView(session) + } + if (retcode === 50114002) { + session.status = 'scanned' + session.message = '已扫码,请在微博客户端确认登录' + return this.loginView(session) + } + if ([50114003, 50114004, 50114015].includes(retcode)) { + session.status = 'expired' + session.message = '登录二维码已过期,请刷新' + return this.loginView(session) + } + session.status = 'failed' + session.message = String(payload?.msg || '微博扫码登录失败') + return this.loginView(session) + } + + async getCountryCodes(): Promise { + const nowMs = this.now() + if (this.countryCodeCache && this.countryCodeCache.expiresAtMs > nowMs) { + return this.countryCodeCache.items + } + try { + const cookies = await this.createBootstrapSession() + const body = new URLSearchParams({ entry: 'miniblog', source: 'miniblog' }) + const response = await this.fetchImpl(`${PASSPORT_BASE}/sso/v2/web/config`, { + method: 'POST', + headers: this.formHeaders(`${PASSPORT_BASE}/sso/v2/web/config`, cookies), + body, + signal: AbortSignal.timeout(this.timeoutMs), + }) + cookies.addFromResponse(response.headers, `${PASSPORT_BASE}/sso/v2/web/config`) + if (response.ok) { + const payload = (await response.json().catch(() => null)) as { + retcode?: number + data?: { + country_code?: Array<{ + country_code?: string | number + local?: { zh_CN?: string } + }> + } + } | null + if (Number(payload?.retcode) === 20000000) { + const items = (payload?.data?.country_code || []) + .map((item) => ({ + code: String(item.country_code || '').trim(), + name: String(item.local?.zh_CN || '').trim(), + })) + .filter((item) => item.code && item.name) + if (items.length > 0) { + this.countryCodeCache = { items, expiresAtMs: nowMs + COUNTRY_CODE_TTL_MS } + return items + } + } + } + } catch { + // 国家码只影响输入体验,拉取失败时使用内置兜底列表。 + } + return FALLBACK_COUNTRY_CODES + } + + async sendSmsCode(input: { + taskId: number + mobile: string + countryCode?: unknown + mfaId?: string + }): Promise { + this.prune() + const taskId = Number(input.taskId) || 0 + if (taskId <= 0) { + throw createHttpError('半自动履约任务无效', { + statusCode: 400, + errorCode: 'weibo_task_id_required', + }) + } + const mobile = this.normalizeMobile(input.mobile, input.countryCode) + const stateKey = this.smsStateKey(taskId, mobile) + let state = this.smsSessions.get(stateKey) + if (!state) { + state = { + taskId, + mobile, + cookies: await this.createBootstrapSession(), + mfaId: '', + createdAtMs: this.now(), + expiresAtMs: this.now() + SMS_COOKIE_TTL_MS, + } + this.smsSessions.set(stateKey, state) + } + const requestedMfaId = String(input.mfaId || '').trim() + if (requestedMfaId && requestedMfaId !== state.mfaId) { + throw createHttpError('微博安全验证已过期,请重新获取验证码', { + statusCode: 409, + errorCode: 'weibo_sms_mfa_expired', + }) + } + const body = new URLSearchParams({ + entry: 'miniblog', + mobile: encodeSsoField(mobile), + el: '2', + }) + if (requestedMfaId) body.set('mfa_id', requestedMfaId) + const sendUrl = `${PASSPORT_BASE}/sso/v2/sms/send` + const response = await this.fetchImpl(`${PASSPORT_BASE}/sso/v2/sms/send`, { + method: 'POST', + headers: this.formHeaders(sendUrl, state.cookies), + body, + signal: AbortSignal.timeout(this.timeoutMs), + }) + state.cookies.addFromResponse(response.headers, sendUrl) + const payload = (await response.json().catch(() => null)) as { + retcode?: number + msg?: string + data?: { act?: string; mfa_id?: string } + } | null + if (Number(payload?.retcode) === 0 && String(payload?.data?.act || '') === 'mfa_1') { + const mfaId = String(payload?.data?.mfa_id || '').trim() + if (!mfaId) { + throw createHttpError('微博要求安全验证,但未返回验证标识', { + statusCode: 502, + errorCode: 'weibo_sms_mfa_invalid', + }) + } + state.mfaId = mfaId + state.expiresAtMs = this.now() + SMS_COOKIE_TTL_MS + return { + mfaRequired: true, + mfaId, + captchaId: WEIBO_YIDUN_CAPTCHA_ID, + } + } + if (!response.ok || !payload || Number(payload.retcode) !== 20000000) { + throw createHttpError(payload?.msg || `发送微博短信验证码失败:HTTP ${response.status}`, { + statusCode: 409, + errorCode: 'weibo_sms_send_failed', + }) + } + state.mfaId = '' + state.expiresAtMs = this.now() + SMS_COOKIE_TTL_MS + return { mfaRequired: false } + } + + async loginWithSms(input: { + taskId: number + orderNo: string + mobile: string + code: string + countryCode?: unknown + rid?: string + }): Promise<{ sessionId: string; session: ConnectorLoginSession }> { + this.prune() + const mobile = this.normalizeMobile(input.mobile, input.countryCode) + const code = String(input.code || '').trim() + if (!code) { + throw createHttpError('请输入微博短信验证码', { + statusCode: 400, + errorCode: 'weibo_sms_code_required', + }) + } + const stateKey = this.smsStateKey(Number(input.taskId) || 0, mobile) + const state = this.smsSessions.get(stateKey) + if (!state) { + throw createHttpError('短信登录会话不存在或已过期,请重新获取验证码', { + statusCode: 409, + errorCode: 'weibo_sms_session_missing', + }) + } + const body = new URLSearchParams({ + entry: 'miniblog', + source: 'miniblog', + type: '2', + url: WEIBO_LOGIN_URL, + ver: WEIBO_LOGIN_VER, + username: encodeSsoField(mobile), + scode: encodeSsoField(code), + el: '2', + disp: 'popup', + rid: String(input.rid || '').trim() || 'norid', + }) + const loginUrl = `${PASSPORT_BASE}/sso/v2/login` + const response = await this.fetchImpl(`${PASSPORT_BASE}/sso/v2/login`, { + method: 'POST', + headers: this.formHeaders(loginUrl, state.cookies), + body, + signal: AbortSignal.timeout(this.timeoutMs), + }) + state.cookies.addFromResponse(response.headers, loginUrl) + const payload = (await response.json().catch(() => null)) as { + retcode?: number + msg?: string + data?: { data?: { act?: string; location?: string; mfa_id?: string } } + } | null + if (!response.ok || !payload) { + throw createHttpError(`微博短信登录失败:HTTP ${response.status}`, { + statusCode: 502, + errorCode: 'weibo_sms_login_failed', + }) + } + const act = String(payload.data?.data?.act || '') + if (act === 'mfa_1' || act === 'mfa_2') { + throw createHttpError('微博要求二次验证,请在微博 App 完成验证后重试', { + statusCode: 409, + errorCode: 'weibo_sms_mfa_required', + }) + } + if (act !== 'goto') { + throw createHttpError(payload.msg || '微博短信登录失败,请检查验证码', { + statusCode: 409, + errorCode: 'weibo_sms_login_failed', + }) + } + const location = String(payload.data?.data?.location || '').trim() + if (!location) { + throw createHttpError('微博登录成功但缺少跳转地址', { + statusCode: 502, + errorCode: 'weibo_sms_login_failed', + }) + } + const nowMs = this.now() + const session: WeiboSession = { + sessionId: crypto.randomBytes(18).toString('base64url'), + taskId: Number(input.taskId) || 0, + orderNo: String(input.orderNo || ''), + createdAtMs: nowMs, + expiresAtMs: nowMs + CREDENTIAL_TTL_MS, + status: 'authenticated', + qrid: '', + qrImage: '', + message: '微博登录成功', + cookies: state.cookies, + account: null, + tickets: new Map(), + } + this.smsSessions.delete(stateKey) + await this.finishLogin(session, location) + this.sessions.set(session.sessionId, session) + return { sessionId: session.sessionId, session: this.loginView(session) } + } + + async getBinding(sessionId: string): Promise { + const session = this.requireSession(sessionId) + if (session.status !== 'authenticated' || !session.account) { + throw createHttpError('微博账号尚未登录', { + statusCode: 409, + errorCode: 'weibo_login_required', + }) + } + return this.bindingView(session) + } + + async createBrowserTicket(input: { + sessionId: string + targetUrl?: string + }): Promise { + const session = this.requireSession(input.sessionId) + if (!session.cookies.has(WEIBO_BASE, 'SUB')) { + throw createHttpError('微博登录态不存在或已过期', { + statusCode: 404, + errorCode: 'weibo_credential_not_found', + }) + } + const ticket = `${TICKET_PREFIX}${crypto.randomBytes(32).toString('base64url')}` + const targetUrl = String(input.targetUrl || '').trim() || 'https://weibo.com/' + const expiresAtMs = this.now() + BROWSER_TICKET_TTL_MS + session.tickets.set(ticket, { + ticket, + targetUrl, + cookies: session.cookies.serialize(targetUrl), + expiresAtMs, + }) + return { ticket, expiresAt: iso(expiresAtMs), targetUrl } + } + + async consumeBrowserTicket(ticketInput: string): Promise { + this.prune() + const ticket = String(ticketInput || '').trim() + if (!ticket) { + throw createHttpError('注入票据无效', { + statusCode: 400, + errorCode: 'weibo_ticket_invalid', + }) + } + for (const session of this.sessions.values()) { + const item = session.tickets.get(ticket) + if (!item) continue + session.tickets.delete(ticket) + if (item.expiresAtMs <= this.now()) { + throw createHttpError('浏览器注入票据不存在或已过期', { + statusCode: 404, + errorCode: 'weibo_ticket_expired', + }) + } + return { + platform: 'weibo', + targetUrl: item.targetUrl, + expiresAt: iso(item.expiresAtMs), + cookies: item.cookies, + } + } + throw createHttpError('浏览器注入票据不存在或已过期', { + statusCode: 404, + errorCode: 'weibo_ticket_not_found', + }) + } + + async revokeSession(sessionIdInput: string): Promise { + const sessionId = String(sessionIdInput || '').trim() + const session = this.sessions.get(sessionId) + if (!session) return + session.cookies.clear() + session.tickets.clear() + this.sessions.delete(sessionId) + } + + exportSessionCredential(sessionIdInput: string): WeiboStoredCredential { + const session = this.requireSession(sessionIdInput) + if (!session.account?.uid || !session.cookies.has(WEIBO_BASE, 'SUB')) { + throw createHttpError('微博登录凭证尚未就绪', { + statusCode: 409, + errorCode: 'weibo_credential_not_ready', + }) + } + return { + platformUid: session.account.uid, + nickname: session.account.nickname, + cookies: session.cookies.serializeAll(), + } + } + + async restoreSessionFromCredential(input: { + taskId: number + orderNo: string + platformUid: string + nickname: string + cookies: WeiboSerializedCookie[] + }): Promise { + this.prune() + const cookies = WeiboCookieJar.fromSerialized(input.cookies) + if (!cookies.has(WEIBO_BASE, 'SUB')) { + throw createHttpError('微博 CK 已失效,请重新登录', { + statusCode: 409, + errorCode: 'weibo_credential_invalid', + }) + } + const account = await this.fetchAccount(cookies.headerFor(WEIBO_BASE)) + if (!account.uid) { + throw createHttpError('微博 CK 已失效,请重新登录', { + statusCode: 409, + errorCode: 'weibo_credential_invalid', + }) + } + if (String(input.platformUid || '') && account.uid !== String(input.platformUid)) { + throw createHttpError('微博 CK 与任务账号不一致,请重新登录', { + statusCode: 409, + errorCode: 'weibo_credential_account_mismatch', + }) + } + const nowMs = this.now() + const session: WeiboSession = { + sessionId: crypto.randomBytes(18).toString('base64url'), + taskId: Number(input.taskId) || 0, + orderNo: String(input.orderNo || ''), + createdAtMs: nowMs, + expiresAtMs: nowMs + CREDENTIAL_TTL_MS, + status: 'authenticated', + qrid: '', + qrImage: '', + message: '微博登录成功', + cookies, + account: { + ...account, + nickname: account.nickname || String(input.nickname || ''), + }, + tickets: new Map(), + } + this.sessions.set(session.sessionId, session) + return this.loginView(session) + } + + private async finishLogin(session: WeiboSession, loginUrl: string): Promise { + await this.followWithCookies(loginUrl, session.cookies) + if (!session.cookies.has(WEIBO_BASE, 'SUB')) { + session.status = 'failed' + session.message = '微博登录成功但未获取到登录 Cookie' + return + } + session.account = await this.fetchAccount(session.cookies.headerFor(WEIBO_BASE)) + if (!session.account.uid) { + session.status = 'failed' + session.message = '微博登录成功但账号信息读取失败' + return + } + session.status = 'authenticated' + session.message = '微博登录成功' + } + + private async followWithCookies( + url: string, + cookies: WeiboCookieJar, + ): Promise<{ finalUrl: string }> { + let currentUrl = url + for (let index = 0; index < 8; index += 1) { + const response = await this.fetchImpl(currentUrl, { + method: 'GET', + headers: { + 'user-agent': PC_UA, + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'accept-language': 'zh-CN,zh;q=0.9', + cookie: cookies.headerFor(currentUrl), + }, + redirect: 'manual', + signal: AbortSignal.timeout(this.timeoutMs), + }) + cookies.addFromResponse(response.headers, currentUrl) + const location = response.headers.get('location') + if (response.status >= 300 && response.status < 400 && location) { + currentUrl = new URL(location, currentUrl).toString() + continue + } + await response.arrayBuffer().catch(() => undefined) + break + } + return { finalUrl: currentUrl } + } + + private async fetchAccount(cookie: string): Promise { + try { + const response = await this.fetchImpl(`${WEIBO_BASE}/ajax/side/info`, { + method: 'GET', + headers: { + 'user-agent': PC_UA, + referer: 'https://weibo.com/', + 'x-requested-with': 'XMLHttpRequest', + accept: 'application/json, text/plain, */*', + cookie, + }, + signal: AbortSignal.timeout(this.timeoutMs), + }) + const payload = (await response.json().catch(() => null)) as { + data?: { + user?: { + id?: number | string + screen_name?: string + avatar_large?: string + } + } + } | null + const user = payload?.data?.user + return { + uid: String(user?.id || ''), + nickname: String(user?.screen_name || ''), + avatar: String(user?.avatar_large || ''), + } + } catch { + return { uid: '', nickname: '', avatar: '' } + } + } + + private async downloadQrImage(imageUrl: string): Promise { + const url = String(imageUrl || '').trim() + if (!url) return '' + const response = await this.fetchImpl(url, { + method: 'GET', + headers: { + 'user-agent': PC_UA, + referer: 'https://passport.weibo.com/', + accept: 'image/avif,image/webp,image/apng,image/*,*/*;q=0.8', + }, + signal: AbortSignal.timeout(this.timeoutMs), + }) + if (!response.ok) return '' + const contentType = String(response.headers.get('content-type') || 'image/png').split(';', 1)[0] + const buffer = Buffer.from(await response.arrayBuffer()) + if (buffer.length === 0) return '' + return `data:${contentType || 'image/png'};base64,${buffer.toString('base64')}` + } + + private loginView(session: WeiboSession): ConnectorLoginSession { + return { + sessionId: session.sessionId, + status: session.status, + qrContent: '', + qrImage: session.qrImage, + expiresAt: iso(session.createdAtMs + LOGIN_QR_TTL_MS), + huyaUid: session.account?.uid || '', + nickname: session.account?.nickname || '', + hasCredential: session.cookies.has(WEIBO_BASE, 'SUB'), + message: session.message, + } + } + + private bindingView(session: WeiboSession): ConnectorBindingSession { + const account = session.account + return { + sessionId: session.sessionId, + status: 'confirmed', + qrImage: '', + qrExpiresAt: '', + bindGameAccount: account?.nickname || '', + bindGameRole: account?.uid || '', + bindGameChannel: '微博', + hasExistingBinding: true, + rebindRequested: false, + message: '微博账号已授权', + } + } + + private requireSession(sessionIdInput: string): WeiboSession { + this.prune() + const sessionId = String(sessionIdInput || '').trim() + const session = this.sessions.get(sessionId) + if (!session) { + throw createHttpError('微博登录会话不存在或已过期', { + statusCode: 404, + errorCode: 'weibo_session_not_found', + }) + } + return session + } + + private normalizeMobile(value: string, countryCodeInput: unknown = '86'): string { + const digits = String(value || '').replace(/\D/g, '') + if (!digits) { + throw createHttpError('请输入手机号', { + statusCode: 400, + errorCode: 'weibo_mobile_required', + }) + } + const countryCode = String(countryCodeInput ?? '').replace(/\D/g, '') || '86' + // 微博网页端:大陆手机号直接使用 11 位号码;其他地区使用 00 + 国家码 + 号码。 + if (countryCode === '86') { + if (digits.startsWith('86') && digits.length > 11) return digits.slice(2) + return digits + } + if (digits.startsWith('00')) return digits + return `00${countryCode}${digits}` + } + + private async createBootstrapSession(): Promise { + const cookies = new WeiboCookieJar() + let currentUrl = SIGNIN_REFERER + for (let index = 0; index < 5; index += 1) { + const response = await this.fetchImpl(currentUrl, { + method: 'GET', + headers: { + 'user-agent': PC_UA, + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'accept-language': 'zh-CN,zh;q=0.9', + ...(cookies.headerFor(currentUrl) ? { cookie: cookies.headerFor(currentUrl) } : {}), + }, + redirect: 'manual', + signal: AbortSignal.timeout(this.timeoutMs), + }) + cookies.addFromResponse(response.headers, currentUrl) + const location = response.headers.get('location') + if (response.status >= 300 && response.status < 400 && location) { + currentUrl = new URL(location, currentUrl).toString() + continue + } + await response.arrayBuffer().catch(() => undefined) + break + } + return cookies + } + + private smsStateKey(taskId: number, mobile: string): string { + return `${taskId}:${mobile}` + } + + private jsonHeaders(requestUrl: string, cookies: WeiboCookieJar): Record { + return { + 'user-agent': PC_UA, + origin: PASSPORT_BASE, + referer: SIGNIN_REFERER, + accept: 'application/json, text/plain, */*', + 'accept-language': 'zh-CN,zh;q=0.9', + 'x-requested-with': 'XMLHttpRequest', + ...(cookies.value(requestUrl, 'X-CSRF-TOKEN') + ? { 'x-csrf-token': cookies.value(requestUrl, 'X-CSRF-TOKEN') } + : {}), + ...(cookies.headerFor(requestUrl) ? { cookie: cookies.headerFor(requestUrl) } : {}), + } + } + + private formHeaders(requestUrl: string, cookies: WeiboCookieJar): Record { + return { + ...this.jsonHeaders(requestUrl, cookies), + 'content-type': 'application/x-www-form-urlencoded', + } + } + + private prune(): void { + const nowMs = this.now() + for (const [key, item] of Array.from(this.smsSessions.entries())) { + if (item.expiresAtMs <= nowMs) this.smsSessions.delete(key) + } + for (const [sessionId, session] of Array.from(this.sessions.entries())) { + if (session.expiresAtMs <= nowMs) { + session.cookies.clear() + session.tickets.clear() + this.sessions.delete(sessionId) + } + } + if (this.sessions.size <= MAX_SESSIONS) return + const overflow = this.sessions.size - MAX_SESSIONS + for (const [sessionId, session] of Array.from(this.sessions.entries()).slice(0, overflow)) { + session.cookies.clear() + session.tickets.clear() + this.sessions.delete(sessionId) + } + } +} + +export const weiboNativeConnector = new WeiboNativeConnector() +export const WEIBO_TICKET_PREFIX = TICKET_PREFIX diff --git a/apps/backend/src/services/semi-auto/weibo-native/weibo-native.test.ts b/apps/backend/src/services/semi-auto/weibo-native/weibo-native.test.ts new file mode 100644 index 00000000..89d8cc86 --- /dev/null +++ b/apps/backend/src/services/semi-auto/weibo-native/weibo-native.test.ts @@ -0,0 +1,329 @@ +import assert from 'node:assert/strict' +import test from 'node:test' + +import { WEIBO_TICKET_PREFIX, WeiboNativeConnector } from './weibo-native-connector.js' + +type CapturedCall = { url: string; init: RequestInit } + +function jsonResponse(payload: unknown): Response { + return new Response(JSON.stringify(payload), { + status: 200, + headers: { 'content-type': 'application/json' }, + }) +} + +function createFetchMock( + handler: (url: string, init: RequestInit) => Response | Promise, +) { + const calls: CapturedCall[] = [] + const fetchImpl = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = + typeof input === 'string' + ? input + : input instanceof URL + ? input.toString() + : String(input.url) + const requestInit = init || {} + calls.push({ url, init: requestInit }) + return handler(url, requestInit) + }) as typeof fetch + return { fetchImpl, calls } +} + +function defaultHandler(url: string): Response { + if (url.includes('/sso/signin')) { + return new Response('', { + status: 200, + headers: { + 'content-type': 'text/html', + 'set-cookie': 'X-CSRF-TOKEN=CK-demo; Path=/sso', + }, + }) + } + if (url.includes('/sso/v2/web/config')) { + return jsonResponse({ + retcode: 20000000, + data: { + country_code: [ + { country_code: '86', local: { zh_CN: '中国' } }, + { country_code: '852', local: { zh_CN: '中国香港' } }, + { country_code: '886', local: { zh_CN: '中国台湾' } }, + ], + }, + }) + } + if (url.includes('/sso/v2/qrcode/image')) { + return jsonResponse({ + retcode: 20000000, + data: { qrid: 'qr-1', image: 'https://v2.qr.weibo.cn/qr-demo.png' }, + }) + } + if (url.includes('/sso/v2/qrcode/check')) { + return jsonResponse({ retcode: 50114001, msg: '未使用', data: null }) + } + if (url.startsWith('https://v2.qr.weibo.cn/')) { + return new Response(Buffer.from('fake-png'), { + status: 200, + headers: { 'content-type': 'image/png' }, + }) + } + if (url.includes('/sso/v2/sms/send')) { + return jsonResponse({ retcode: 20000000 }) + } + if (url.includes('/sso/v2/login')) { + const headers = new Headers({ + 'content-type': 'application/json', + }) + headers.append('set-cookie', 'SUB=demo-sub; Path=/; Domain=.weibo.com') + headers.append('set-cookie', 'PASSPORT_ONLY=demo-passport; Path=/sso') + return new Response( + JSON.stringify({ + retcode: 20000000, + data: { + data: { + act: 'goto', + location: 'https://passport.weibo.com/sso/v2/goto?ticket=demo', + }, + }, + }), + { + status: 200, + headers, + }, + ) + } + if (url.includes('/sso/v2/goto')) { + return new Response(null, { + status: 302, + headers: { + location: 'https://weibo.com/', + 'set-cookie': 'SUB=demo-sub; Path=/; Domain=.weibo.com', + }, + }) + } + if (url === 'https://weibo.com/') { + return new Response('', { + status: 200, + headers: { 'content-type': 'text/html' }, + }) + } + if (url.includes('/ajax/side/info')) { + return jsonResponse({ + data: { + user: { + id: 123456, + screen_name: '微博测试账号', + avatar_large: 'https://tvax1.sinaimg.cn/demo.jpg', + }, + }, + }) + } + return new Response('not found', { status: 404 }) +} + +test('微博二维码会话解析 qrid 并把图片转成 base64', async () => { + const { fetchImpl, calls } = createFetchMock(defaultHandler) + const connector = new WeiboNativeConnector({ fetchImpl }) + const session = await connector.createQrLoginSession({ taskId: 1, orderNo: 'MOCKWB1' }) + + assert.equal(session.status, 'waiting_scan') + assert.match(session.qrImage || '', /^data:image\/png;base64,/) + assert.ok(calls.some((call) => call.url.includes('qrcode/image?entry=miniblog&size=180'))) +}) + +test('微博二维码未扫码时保持等待扫码状态', async () => { + const { fetchImpl } = createFetchMock(defaultHandler) + const connector = new WeiboNativeConnector({ fetchImpl }) + const session = await connector.createQrLoginSession({ taskId: 1, orderNo: 'MOCKWB1' }) + const polled = await connector.getQrLoginSession(session.sessionId) + assert.equal(polled.status, 'waiting_scan') +}) + +test('微博发送短信验证码使用大陆 11 位手机号', async () => { + const { fetchImpl, calls } = createFetchMock(defaultHandler) + const connector = new WeiboNativeConnector({ fetchImpl }) + await connector.sendSmsCode({ taskId: 1, mobile: '18900762182' }) + + const call = calls.find((item) => item.url.includes('/sso/v2/sms/send')) + assert.ok(call) + const form = new URLSearchParams(String(call.init.body)) + assert.equal(form.get('entry'), 'miniblog') + assert.equal(form.get('mobile'), 'T3JH3iRZfvXRi9K') + assert.equal(form.get('mfa_id'), null) + assert.equal(form.get('el'), '2') +}) + +test('微博短信发送支持其他国家码并按 00 前缀编码', async () => { + const { fetchImpl, calls } = createFetchMock(defaultHandler) + const connector = new WeiboNativeConnector({ fetchImpl }) + await connector.sendSmsCode({ + taskId: 1, + mobile: '61234567', + countryCode: '852', + }) + + const call = calls.find((item) => item.url.includes('/sso/v2/sms/send')) + assert.ok(call) + const form = new URLSearchParams(String(call.init.body)) + assert.equal(form.get('mobile'), 'TiNs13aS9CXDe9Nva3') +}) + +test('微博国家码列表来自 web config 并缓存', async () => { + const { fetchImpl, calls } = createFetchMock(defaultHandler) + const connector = new WeiboNativeConnector({ fetchImpl }) + const first = await connector.getCountryCodes() + const second = await connector.getCountryCodes() + + assert.deepEqual(first, [ + { code: '86', name: '中国' }, + { code: '852', name: '中国香港' }, + { code: '886', name: '中国台湾' }, + ]) + assert.deepEqual(second, first) + assert.equal(calls.filter((call) => call.url.includes('/sso/v2/web/config')).length, 1) +}) + +test('微博短信登录会带上发码响应下发的 Cookie', async () => { + const { fetchImpl, calls } = createFetchMock((url) => { + if (url.includes('/sso/v2/sms/send')) { + return new Response(JSON.stringify({ retcode: 20000000 }), { + status: 200, + headers: { + 'content-type': 'application/json', + 'set-cookie': 'SCF=send-cookie; Path=/', + }, + }) + } + return defaultHandler(url) + }) + const connector = new WeiboNativeConnector({ fetchImpl }) + await connector.sendSmsCode({ taskId: 1, mobile: '13800138000' }) + const { session } = await connector.loginWithSms({ + taskId: 1, + orderNo: 'MOCKWB1', + mobile: '13800138000', + code: '123456', + }) + + assert.equal(session.status, 'authenticated') + const redirectCall = calls.find((item) => item.url.includes('/sso/v2/goto')) + assert.ok(redirectCall) + const headers = redirectCall.init.headers as Record + assert.match(headers.cookie || '', /SCF=send-cookie/) +}) + +test('微博短信登录建立会话并可生成一次性注入票据', async () => { + const { fetchImpl, calls } = createFetchMock(defaultHandler) + const connector = new WeiboNativeConnector({ fetchImpl }) + await connector.sendSmsCode({ taskId: 1, mobile: '138 0013 8000' }) + const { sessionId, session } = await connector.loginWithSms({ + taskId: 1, + orderNo: 'MOCKWB1', + mobile: '138 0013 8000', + code: '123456', + }) + + assert.equal(session.status, 'authenticated') + assert.equal(session.huyaUid, '123456') + assert.equal(session.nickname, '微博测试账号') + + const loginCall = calls.find((item) => item.url.includes('/sso/v2/login')) + assert.ok(loginCall) + const form = new URLSearchParams(String(loginCall.init.body)) + assert.equal(form.get('type'), '2') + assert.equal(form.get('username'), 'T3Gs3iR_9fN7A9t') + assert.equal(form.get('scode'), 'T3r81iMS') + + const ticket = await connector.createBrowserTicket({ + sessionId, + targetUrl: 'https://weibo.com/', + }) + assert.ok(ticket.ticket.startsWith(WEIBO_TICKET_PREFIX)) + + const payload = await connector.consumeBrowserTicket(ticket.ticket) + assert.equal(payload.platform, 'weibo') + assert.equal(payload.targetUrl, 'https://weibo.com/') + assert.ok(payload.cookies.some((cookie) => cookie.name === 'SUB' && cookie.value === 'demo-sub')) + + await assert.rejects(() => connector.consumeBrowserTicket(ticket.ticket), /票据不存在或已过期/) +}) + +test('微博短信发送遇到 mfa_1 时返回易盾挑战,完成挑战后可用 mfa_id 重发', async () => { + let sendCount = 0 + const { fetchImpl, calls } = createFetchMock((url, init) => { + if (url.includes('/sso/v2/sms/send')) { + sendCount += 1 + const form = new URLSearchParams(String(init.body)) + if (!form.get('mfa_id')) { + return jsonResponse({ + retcode: 0, + msg: 'need mfa', + data: { act: 'mfa_1', mfa_id: 'mfa-demo' }, + }) + } + return jsonResponse({ retcode: 20000000, msg: '', data: [] }) + } + return defaultHandler(url) + }) + const connector = new WeiboNativeConnector({ fetchImpl }) + + const first = await connector.sendSmsCode({ taskId: 1, mobile: '13800138000' }) + assert.equal(first.mfaRequired, true) + assert.equal(first.mfaId, 'mfa-demo') + assert.equal(first.captchaId, '7cda0ba2785647ada4d6e946ddb2d465') + + const second = await connector.sendSmsCode({ + taskId: 1, + mobile: '13800138000', + mfaId: 'mfa-demo', + }) + assert.equal(second.mfaRequired, false) + assert.equal(sendCount, 2) + const secondForm = new URLSearchParams( + String(calls.filter((call) => call.url.includes('/sso/v2/sms/send'))[1]?.init.body), + ) + assert.equal(secondForm.get('mfa_id'), 'mfa-demo') +}) + +test('微博 CK 可按账号级凭证导出并从序列化 Cookie 恢复会话', async () => { + const { fetchImpl } = createFetchMock(defaultHandler) + const connector = new WeiboNativeConnector({ fetchImpl }) + await connector.sendSmsCode({ taskId: 1, mobile: '13800138000' }) + const { sessionId } = await connector.loginWithSms({ + taskId: 1, + orderNo: 'MOCKWB1', + mobile: '13800138000', + code: '123456', + }) + const credential = connector.exportSessionCredential(sessionId) + assert.equal(credential.platformUid, '123456') + assert.ok(credential.cookies.some((cookie) => cookie.name === 'SUB')) + assert.ok( + credential.cookies.some( + (cookie) => + cookie.name === 'PASSPORT_ONLY' && + cookie.domain === 'passport.weibo.com' && + cookie.path === '/sso', + ), + ) + + const ticket = await connector.createBrowserTicket({ + sessionId, + targetUrl: 'https://weibo.com/', + }) + const injection = await connector.consumeBrowserTicket(ticket.ticket) + assert.equal( + injection.cookies.some((cookie) => cookie.name === 'PASSPORT_ONLY'), + false, + ) + + const restored = await connector.restoreSessionFromCredential({ + taskId: 2, + orderNo: 'MOCKWB2', + platformUid: credential.platformUid, + nickname: credential.nickname, + cookies: credential.cookies, + }) + assert.equal(restored.status, 'authenticated') + assert.equal(restored.hasCredential, true) +}) diff --git a/apps/backend/src/types/runtime-config.ts b/apps/backend/src/types/runtime-config.ts index faa95205..6bb89dd5 100644 --- a/apps/backend/src/types/runtime-config.ts +++ b/apps/backend/src/types/runtime-config.ts @@ -61,6 +61,20 @@ export type RuntimeConfig = { claimBaseUrl: string tokenTtlHours: number } + semiAuto: { + /** 新建半自动任务的默认 Connector:内置真实实现、外部 Connector 或开发 Mock。 */ + defaultConnectorMode: 'embedded' | 'external' | 'mock' + connectorBaseUrl: string + connectorApiKey: string + connectorTimeoutMs: number + /** 半自动平台账号 CK 的落库加密密钥;生产必填,本地缺省回退后台会话密钥。 */ + credentialEncryptionKey?: string + huya: { + bindActId: number + outerActId: string + roomPid: string + } + } admin: { sessionSecret: string /** 后台空闲多久未访问即失效(每次访问滑动续期)。 */ diff --git a/apps/frontend/src/App.tsx b/apps/frontend/src/App.tsx index 11e2415c..877b1dda 100644 --- a/apps/frontend/src/App.tsx +++ b/apps/frontend/src/App.tsx @@ -12,6 +12,7 @@ import { import { getAdminRole, hasAdminSession } from '@/utils/admin-auth' import { isClaimPath, isH5ClaimPath } from '@/utils/claim-path' +import { isCustomerFulfillmentPath } from '@/utils/customer-fulfillment-link' import { isLegacySupplementPath, isOrderServicePath, @@ -42,12 +43,16 @@ const AdminOrdersPage = lazy(() => import('@/pages/admin/AdminOrdersPage')) const AdminPlatformShopsPage = lazy(() => import('@/pages/admin/platform/AdminPlatformShopsPage')) const AdminTaskDetailPage = lazy(() => import('@/pages/admin/AdminTaskDetailPage')) const AdminTasksPage = lazy(() => import('@/pages/admin/AdminTasksPage')) +const AdminSemiAutoTasksPage = lazy(() => import('@/pages/admin/AdminSemiAutoTasksPage')) const AdminUsersPage = lazy(() => import('@/pages/admin/AdminUsersPage')) const AdminDevMockPage = lazy(() => import('@/pages/admin/AdminDevMockPage')) const AdminWorkerPlatformPage = lazy(() => import('@/pages/admin/AdminWorkerPlatformPage')) const ClaimPage = lazy(() => import('@/pages/claim/ClaimPage')) const H5ClaimEntryPage = lazy(() => import('@/pages/claim/H5ClaimEntryPage')) const OrderServicePage = lazy(() => import('@/pages/public/OrderServicePage')) +const CustomerFulfillmentPage = lazy( + () => import('@/pages/customer-fulfillment/CustomerFulfillmentPage'), +) const NotFoundPage = lazy(() => import('@/pages/NotFoundPage')) const RedeemPage = lazy(() => import('@/pages/redeem/RedeemPage')) const WorkerHallPage = lazy(() => import('@/pages/worker/WorkerHallPage')) @@ -131,6 +136,10 @@ export default function App() { return } + if (isCustomerFulfillmentPath(window.location.pathname)) { + return + } + // 旧 /supplement 短期兼容:统一跳到 /o。 if (isLegacySupplementPath(window.location.pathname)) { return @@ -158,6 +167,20 @@ function OrderServiceApplication() { ) } +function CustomerFulfillmentApplication() { + useClearStrayHash() + return ( + + }> + + } /> + } /> + + + + ) +} + function CollectRedirectApplication() { useEffect(() => { const orderNo = resolveLegacySupplementOrderNo(window.location.pathname) @@ -180,6 +203,7 @@ function AdminApplication() { } /> } /> } /> + } /> }> } /> diff --git a/apps/frontend/src/layouts/AdminLayout.tsx b/apps/frontend/src/layouts/AdminLayout.tsx index 5f3b583b..5d28d6e2 100644 --- a/apps/frontend/src/layouts/AdminLayout.tsx +++ b/apps/frontend/src/layouts/AdminLayout.tsx @@ -12,6 +12,7 @@ import { MenuFoldOutlined, MenuUnfoldOutlined, OrderedListOutlined, + RobotOutlined, SafetyCertificateOutlined, SettingOutlined, SoundOutlined, @@ -246,6 +247,11 @@ export default function AdminLayout() { label: '我的钱包', }, { key: '/admin/tasks', icon: , label: '任务' }, + { + key: '/admin/semi-auto-tasks', + icon: , + label: '半自动履约', + }, { key: '/admin/worker-platform', icon: , label: '接单平台' }, { key: '/admin/kuaishou-industry', @@ -263,6 +269,11 @@ export default function AdminLayout() { { key: '/admin/orders', icon: , label: '订单' }, financeSubMenu, { key: '/admin/tasks', icon: , label: '任务' }, + { + key: '/admin/semi-auto-tasks', + icon: , + label: '半自动履约', + }, { key: '/admin/worker-platform', icon: , label: '接单平台' }, { key: '/admin/kuaishou-industry', diff --git a/apps/frontend/src/pages/admin/AdminDevMockPage.tsx b/apps/frontend/src/pages/admin/AdminDevMockPage.tsx index c4f62e45..d0b6bdf5 100644 --- a/apps/frontend/src/pages/admin/AdminDevMockPage.tsx +++ b/apps/frontend/src/pages/admin/AdminDevMockPage.tsx @@ -8,6 +8,7 @@ import { Divider, Form, Input, + InputNumber, Result, Row, Select, @@ -23,10 +24,12 @@ import { buildOpen91QueryDevMock, createAffiliateDashDevMock, createKuaishouIndustryVoucherDevMock, + createSemiAutoDevMock, fetchDevMockStatus, type DevMockCreateResult, type DevMockKuaishouIndustryVoucherResult, type DevMockOpen91QueryResult, + type DevMockSemiAutoResult, } from '@/services/admin' export default function AdminDevMockPage() { @@ -35,6 +38,7 @@ export default function AdminDevMockPage() { const [lastVoucherCreate, setLastVoucherCreate] = useState(null) const [lastQuery, setLastQuery] = useState(null) + const [lastSemiAuto, setLastSemiAuto] = useState(null) const statusQuery = useQuery({ queryKey: ['admin-dev-mock-status'], @@ -78,6 +82,17 @@ export default function AdminDevMockPage() { }, }) + const semiAutoMutation = useMutation({ + mutationFn: createSemiAutoDevMock, + onSuccess: (response) => { + setLastSemiAuto(response.data) + message.success('半自动履约 Mock 已生成') + }, + onError: (error) => { + message.error(error instanceof Error ? error.message : '生成失败') + }, + }) + const defaultOrderNo = useMemo(() => lastCreate?.orderNo || '', [lastCreate?.orderNo]) if (statusQuery.isLoading) { @@ -109,7 +124,7 @@ export default function AdminDevMockPage() {
NODE_ENV={status?.nodeEnv || '-'} } @@ -119,8 +134,8 @@ export default function AdminDevMockPage() { type="info" showIcon icon={} - message="Mock 会写入开发库真实订单/任务;当前仅保留 affiliate-dash / 电子凭证 / 91 查单。" - description="affiliate-dash 可用默认 UID 测试绑定与提交发货。" + message="Mock 会写入开发库真实订单/任务;除订单外,登录、绑定、票据注入和完成确认都可以走真实流程。" + description="默认使用 order_site 内置真实 Connector,不依赖 live-hub-py;只有显式选择内置 Mock 时才会 Mock 登录和绑定。" /> @@ -134,7 +149,19 @@ export default function AdminDevMockPage() { - + + semiAutoMutation.mutate(values)} + /> + + + + + voucherMutation.mutate(values)} @@ -143,7 +170,7 @@ export default function AdminDevMockPage() { - +
) : null} + {lastSemiAuto ? ( + 打开后台任务} + > + + + 订单号 +
+ + {lastSemiAuto.orderNo} + +
+ + + 内部 SKU / 任务 +
+ {lastSemiAuto.semiAutoPlatform === 'weibo' ? '微博' : '虎牙'} ·{' '} + {lastSemiAuto.skuKey} · 任务 #{lastSemiAuto.taskId} +
+ + + 客户履约入口 +
+ + {window.location.origin} + {lastSemiAuto.customerPath} + +
+ + + + + + + + {lastSemiAuto.tips.map((tip) => ( +
  • {tip}
  • + ))} + + } + /> + +
    +
    + ) : null} + {lastVoucherCreate ? ( ) } + +function SemiAutoMockForm({ + loading, + defaultConnectorMode, + externalConnectorConfigured, + mockConnectorAvailable, + onSubmit, +}: { + loading: boolean + defaultConnectorMode?: 'embedded' | 'external' | 'mock' + externalConnectorConfigured?: boolean + mockConnectorAvailable?: boolean + onSubmit: (values: { + platform: 'huya' | 'weibo' + orderNo?: string + skuName?: string + quantity?: number + pageTitle?: string + browserTargetUrl?: string + connectorMode?: 'embedded' | 'external' | 'mock' + }) => void +}) { + const [form] = Form.useForm() + const selectedPlatform = + (Form.useWatch('platform', form) as 'huya' | 'weibo' | undefined) || 'huya' + const defaultMode = + defaultConnectorMode === 'mock' && mockConnectorAvailable + ? 'mock' + : defaultConnectorMode === 'external' + ? 'external' + : 'embedded' + const selectedMode = + (Form.useWatch('connectorMode', form) as 'embedded' | 'external' | 'mock' | undefined) || + defaultMode + + return ( + + + + + ) : ( + + )} + + + + + + + + + + + + + + + + + + + + + ) +} diff --git a/apps/frontend/src/pages/admin/AdminSemiAutoTasksPage.tsx b/apps/frontend/src/pages/admin/AdminSemiAutoTasksPage.tsx new file mode 100644 index 00000000..d0f42d78 --- /dev/null +++ b/apps/frontend/src/pages/admin/AdminSemiAutoTasksPage.tsx @@ -0,0 +1,755 @@ +import { + CheckCircleOutlined, + ChromeOutlined, + CopyOutlined, + KeyOutlined, + ReloadOutlined, + UserSwitchOutlined, +} from '@ant-design/icons' +import { + App, + Button, + Card, + Descriptions, + Drawer, + Form, + Input, + InputNumber, + Modal, + Select, + Space, + Tag, + Timeline, + Typography, +} from 'antd' +import type { TableColumnsType } from 'antd' +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import { useEffect, useMemo, useState } from 'react' + +import ImageUpload from '@/components/files/ImageUpload' +import PageHeader from '@/components/admin/PageHeader' +import PercentTable from '@/components/common/PercentTable' +import { uploadFile } from '@/services/files' +import { + cancelAdminSemiAutoTask, + claimAdminSemiAutoTask, + completeAdminSemiAutoTask, + createAdminSemiAutoBrowserSession, + exportAdminSemiAutoCredential, + fetchAdminSemiAutoTask, + fetchAdminSemiAutoTasks, + syncAdminSemiAutoTask, +} from '@/services/admin/semi-auto' +import type { SemiAutoCredentialExport, SemiAutoTask } from '@/types/admin/semi-auto' +import type { UploadedFile } from '@/types/worker-platform' +import { hasAdminPermission } from '@/utils/admin-auth' +import { formatAdminDateTime } from '@/utils/admin-time' + +const { Text } = Typography + +const STATUS_COLORS: Record = { + waiting_customer: 'blue', + waiting_login: 'blue', + login_scanned: 'cyan', + waiting_binding: 'gold', + binding_confirm: 'orange', + waiting_operator: 'volcano', + processing: 'processing', + completed: 'success', + failed: 'error', + cancelled: 'default', +} + +const PLATFORM_LABELS: Record = { + huya: '虎牙', + weibo: '微博', +} + +type CompleteFormValues = { + note?: string + externalOrderNo?: string + costYuan?: number +} + +export default function AdminSemiAutoTasksPage() { + const { message, modal } = App.useApp() + const queryClient = useQueryClient() + const [keyword, setKeyword] = useState('') + const [platform, setPlatform] = useState('') + const [status, setStatus] = useState('') + const [page, setPage] = useState(1) + const [pageSize, setPageSize] = useState(20) + const [detailTaskId, setDetailTaskId] = useState(null) + const [completeTask, setCompleteTask] = useState(null) + const [completeFiles, setCompleteFiles] = useState([]) + const [credentialExport, setCredentialExport] = useState(null) + const [completeForm] = Form.useForm() + + const params = useMemo( + () => ({ + page, + pageSize, + keyword: keyword.trim() || undefined, + platform: platform || undefined, + status: status || undefined, + }), + [keyword, page, pageSize, platform, status], + ) + + const listQuery = useQuery({ + queryKey: ['admin-semi-auto-tasks', params], + queryFn: () => fetchAdminSemiAutoTasks(params), + refetchInterval: 3000, + }) + const detailQuery = useQuery({ + queryKey: ['admin-semi-auto-task', detailTaskId], + queryFn: () => fetchAdminSemiAutoTask(Number(detailTaskId)), + enabled: Boolean(detailTaskId), + refetchInterval: detailTaskId ? 3000 : false, + }) + const list = listQuery.data?.data?.items || [] + const pagination = listQuery.data?.data?.pagination + const detail = detailQuery.data?.data + + useEffect(() => { + if (detailTaskId && listQuery.data && !list.some((item) => item.id === detailTaskId)) { + setDetailTaskId(null) + } + }, [detailTaskId, list, listQuery.data]) + + useEffect(() => { + const handleResult = (event: Event) => { + const detail = (event as CustomEvent).detail + if (typeof detail !== 'string') return + try { + const result = JSON.parse(detail) as { + ok?: boolean + written?: number + error?: string + } + if (!result || typeof result !== 'object') return + if (result.ok) { + message.success(`浏览器登录态已注入(${Number(result.written || 0)} 个 Cookie)`) + } else { + message.error(result.error || '浏览器登录态注入失败') + } + } catch { + // 忽略其他页面事件 + } + } + window.addEventListener('huya-exchange-result', handleResult) + return () => window.removeEventListener('huya-exchange-result', handleResult) + }, [message]) + + const syncMutation = useMutation({ + mutationFn: (taskId: number) => syncAdminSemiAutoTask(taskId), + onSuccess: () => { + message.success('状态已刷新') + void refreshAll() + }, + onError: (error) => message.error(error instanceof Error ? error.message : '刷新失败'), + }) + + const claimMutation = useMutation({ + mutationFn: (taskId: number) => claimAdminSemiAutoTask(taskId), + onSuccess: () => { + message.success('任务已领取') + void refreshAll() + }, + onError: (error) => message.error(error instanceof Error ? error.message : '领取失败'), + }) + + const injectionMutation = useMutation({ + mutationFn: (task: SemiAutoTask) => + createAdminSemiAutoBrowserSession(task.id, firstTargetUrl(task)), + onSuccess: (response) => { + const ticket = String(response.data?.ticket || '').trim() + if (!ticket) { + message.error('注入票据生成失败') + return + } + window.postMessage({ type: 'ORDER_SITE_SEMI_AUTO_INJECT', ticket }, window.location.origin) + message.info('正在通过虎牙履约助手注入登录态,请稍候') + void refreshAll() + }, + onError: (error) => + message.error(error instanceof Error ? error.message : '打开浏览器登录态失败'), + }) + + const credentialExportMutation = useMutation({ + mutationFn: (taskId: number) => exportAdminSemiAutoCredential(taskId), + onSuccess: (response) => { + if (!response.data) { + message.error('账号 CK 导出失败') + return + } + setCredentialExport(response.data) + }, + onError: (error) => message.error(error instanceof Error ? error.message : '导出账号 CK 失败'), + }) + + const completeMutation = useMutation({ + mutationFn: async (values: CompleteFormValues) => { + if (!completeTask) throw new Error('任务不存在') + const costFen = + values.costYuan !== undefined && values.costYuan !== null + ? Math.round(Number(values.costYuan) * 100) + : undefined + return completeAdminSemiAutoTask(completeTask.id, { + note: values.note || '', + externalOrderNo: values.externalOrderNo || '', + ...(costFen !== undefined ? { costFen } : {}), + screenshots: completeFiles.map((file) => ({ ...file })), + }) + }, + onSuccess: () => { + message.success('半自动履约已完成') + setCompleteTask(null) + setCompleteFiles([]) + completeForm.resetFields() + void refreshAll() + }, + onError: (error) => message.error(error instanceof Error ? error.message : '完成履约失败'), + }) + + const cancelMutation = useMutation({ + mutationFn: ({ taskId, reason }: { taskId: number; reason: string }) => + cancelAdminSemiAutoTask(taskId, reason), + onSuccess: () => { + message.success('任务已取消') + void refreshAll() + }, + onError: (error) => message.error(error instanceof Error ? error.message : '取消失败'), + }) + + async function refreshAll() { + await Promise.all([ + queryClient.invalidateQueries({ queryKey: ['admin-semi-auto-tasks'] }), + detailTaskId + ? queryClient.invalidateQueries({ queryKey: ['admin-semi-auto-task', detailTaskId] }) + : Promise.resolve(), + ]) + } + + function copyCustomerLink(task: SemiAutoTask) { + const url = `${window.location.origin}/c/${encodeURIComponent(task.orderNo)}` + void navigator.clipboard + .writeText(url) + .then(() => message.success('客户授权链接已复制')) + .catch(() => message.error('复制失败,请手动复制')) + } + + function copyCredentialText(text: string, label: string) { + void navigator.clipboard + .writeText(text) + .then(() => message.success(`${label}已复制`)) + .catch(() => message.error('复制失败,请手动选择文本')) + } + + function confirmExportCredential(task: SemiAutoTask) { + modal.confirm({ + title: '导出账号 CK', + content: + 'CK 等同于平台登录态。导出后会显示在当前页面,请勿发给无关人员;关闭弹窗后不会保留在页面状态中。', + okText: '确认导出', + okButtonProps: { danger: true }, + cancelText: '取消', + onOk: () => credentialExportMutation.mutateAsync(task.id), + }) + } + + function openComplete(task: SemiAutoTask) { + setCompleteTask(task) + setCompleteFiles([]) + completeForm.resetFields() + } + + function confirmCancel(task: SemiAutoTask) { + let reason = '' + modal.confirm({ + title: '取消半自动履约任务', + content: ( + { + reason = event.target.value + }} + /> + ), + okText: '确认取消', + okButtonProps: { danger: true }, + cancelText: '返回', + onOk: () => cancelMutation.mutateAsync({ taskId: task.id, reason }), + }) + } + + const columns: TableColumnsType = [ + { + title: '订单 / 商品', + key: 'order', + width: 260, + render: (_, task) => ( + + {task.orderNo} + {task.productName || task.skuName || task.skuCode} + SKU:{task.skuCode || '-'} + + ), + }, + { + title: '平台', + dataIndex: 'platform', + width: 90, + render: (value: string) => {PLATFORM_LABELS[value] || value}, + }, + { + title: 'Connector', + dataIndex: 'connectorMode', + width: 110, + render: (value: string) => ( + + {value === 'mock' ? '内置 Mock' : '真实'} + + ), + }, + { + title: '客户登录', + key: 'login', + width: 180, + render: (_, task) => ( + + {task.displayStatus.label} + {task.huyaUid ? `UID ${task.huyaUid}` : '未获取 UID'} + + CK: + {task.credentialStatus === 'valid' + ? '有效' + : task.credentialStatus === 'invalid' + ? '失效' + : task.credentialStatus === 'error' + ? '检测异常' + : '未保存'} + + + ), + }, + { + title: '授权 / 绑定角色', + key: 'binding', + width: 190, + render: (_, task) => + task.bindGameRole ? ( + + {task.bindGameRole} + + {[task.bindGameAccount, task.bindGameChannel].filter(Boolean).join(' · ') || '-'} + + + ) : ( + {task.platform === 'weibo' ? '未授权' : '未绑定'} + ), + }, + { + title: '客服', + dataIndex: 'assignedAdminName', + width: 110, + render: (value: string) => value || '未领取', + }, + { + title: '更新时间', + dataIndex: 'updatedAt', + width: 155, + render: (value: string) => formatAdminDateTime(value), + }, + { + title: '操作', + key: 'actions', + width: 360, + render: (_, task) => ( + + + + + {!task.assignedAdminUserId ? ( + + ) : null} + + {task.executionStatus !== 'completed' && task.executionStatus !== 'cancelled' ? ( + <> + + + + ) : null} + + ), + }, + ] + + return ( +
    + + + + { + setKeyword(event.target.value) + setPage(1) + }} + style={{ width: 280 }} + /> + { + setStatus(value || '') + setPage(1) + }} + options={[ + { value: 'waiting_customer', label: '等待客户' }, + { value: 'waiting_operator', label: '等待客服' }, + { value: 'processing', label: '处理中' }, + { value: 'completed', label: '已完成' }, + { value: 'failed', label: '失败' }, + { value: 'cancelled', label: '已取消' }, + ]} + style={{ width: 130 }} + /> + + + + rowKey="id" + loading={listQuery.isLoading} + columns={columns} + dataSource={list} + scroll={{ x: 1400 }} + pagination={{ + current: pagination?.page || page, + pageSize: pagination?.pageSize || pageSize, + total: pagination?.total || 0, + showSizeChanger: true, + onChange: (nextPage, nextPageSize) => { + setPage(nextPage) + setPageSize(nextPageSize) + }, + }} + /> + + + setDetailTaskId(null)} + > + {detailQuery.isLoading ? ( + 加载中... + ) : detail?.task ? ( + + + + {detail.task.productName} + + + {PLATFORM_LABELS[detail.task.platform] || detail.task.platform} + + + + {detail.task.connectorMode === 'mock' + ? '内置 Mock' + : detail.task.connectorMode === 'external' + ? '远程真实' + : '内置真实'} + + + + + {detail.task.displayStatus.label} + + + + {detail.task.huyaUid || '-'} + + + {detail.task.platformNickname || '-'} + + + + + {detail.task.credentialStatus === 'valid' + ? '有效' + : detail.task.credentialStatus === 'invalid' + ? '失效' + : detail.task.credentialStatus === 'error' + ? '检测异常' + : '未保存'} + + + {detail.task.credentialSource + ? `${detail.task.credentialSource} · ${formatAdminDateTime(detail.task.credentialUpdatedAt)}` + : '-'} + + + + + {detail.task.bindGameAccount || '-'} + + {detail.task.platform === 'weibo' ? ( + + {detail.task.bindingStatus === 'confirmed' ? '登录即授权' : '未授权'} + + ) : ( + + {detail.task.bindGameRole || '-'} + + )} + {detail.task.platform !== 'weibo' ? ( + + {detail.task.bindGameChannel || '-'} + + ) : null} + + {detail.task.assignedAdminName || '未领取'} + + + {formatAdminDateTime(detail.task.updatedAt)} + + + {detail.task.lastError ? ( + + {detail.task.lastError} + + ) : null} + + + + + + {detail.task.credentialReady && + hasAdminPermission('semi_auto.credential.export') ? ( + + ) : null} + + + + ({ + color: event.eventType.includes('failed') ? 'red' : 'blue', + children: ( + + {event.eventType} + + {formatAdminDateTime(event.createdAt)} · {event.actorType} + {event.actorId ? ` ${event.actorId}` : ''} + + + ), + }))} + /> + + + ) : ( + 暂无任务详情 + )} + + + setCredentialExport(null)} + > + {credentialExport ? ( + + + 以下内容包含平台登录态,仅用于本次受控操作。关闭弹窗后请勿在聊天、日志或工单中留存。 + + + + {credentialExport.targetUrl || 'Cookie Header'} + + + + + + + 完整域名 Cookie + + + + + + ) : null} + + + { + setCompleteTask(null) + setCompleteFiles([]) + completeForm.resetFields() + }} + onOk={() => { + void completeForm.validateFields().then((values) => completeMutation.mutate(values)) + }} + > + form={completeForm} layout="vertical"> + + + + + + + + + + + + + + +
    + ) +} + +function firstTargetUrl(task: SemiAutoTask) { + const targets = Array.isArray(task.semiAutoConfig?.browserTargets) + ? task.semiAutoConfig.browserTargets + : [] + return String(targets.find((item) => item?.url)?.url || '') +} diff --git a/apps/frontend/src/pages/admin/cost-center/ManualSkuConfigPanel.tsx b/apps/frontend/src/pages/admin/cost-center/ManualSkuConfigPanel.tsx index 40c0368c..d85f531b 100644 --- a/apps/frontend/src/pages/admin/cost-center/ManualSkuConfigPanel.tsx +++ b/apps/frontend/src/pages/admin/cost-center/ManualSkuConfigPanel.tsx @@ -31,6 +31,7 @@ import { Row, Select, Space, + Switch, Statistic, Tag, Typography, @@ -65,6 +66,14 @@ type ConfigFormValues = { creditQuantity: number }> note?: string + semiAutoEnabled?: boolean + semiAutoPlatform?: '' | 'huya' | 'weibo' + semiAutoConfig?: { + pageTitle?: string + pageDescription?: string + loginInstructions?: string + bindingInstructions?: string + } } const PLATFORM_TAG_COLORS: Record = { @@ -142,6 +151,9 @@ export function ManualSkuConfigPanel() { creditQuantity: Number(channel.creditQuantity || 0), })), note: values.note || '', + semiAutoEnabled: values.semiAutoEnabled === true, + semiAutoPlatform: values.semiAutoEnabled ? values.semiAutoPlatform || '' : '', + semiAutoConfig: values.semiAutoConfig || {}, }), onSuccess: (response) => { const summary = response.data.syncSummary @@ -201,6 +213,9 @@ export function ManualSkuConfigPanel() { creditQuantity: channel.creditQuantity, })), note: item.config?.note || '', + semiAutoEnabled: item.config?.semiAutoEnabled === true, + semiAutoPlatform: item.config?.semiAutoPlatform || '', + semiAutoConfig: item.config?.semiAutoConfig || {}, }) setModalOpen(true) } @@ -212,6 +227,9 @@ export function ManualSkuConfigPanel() { skuKey: skuKey.trim(), channels: [{ platformKey: '', creditQuantity: 0 }], note: '', + semiAutoEnabled: false, + semiAutoPlatform: '', + semiAutoConfig: {}, }) setModalOpen(true) } @@ -636,6 +654,54 @@ export function ManualSkuConfigPanel() { )} + + + + + + {() => + form.getFieldValue('semiAutoEnabled') ? ( + <> + + + + + + + + + +
    + + + + + + + + ) : null + } + + diff --git a/apps/frontend/src/pages/customer-fulfillment/CustomerFulfillmentPage.tsx b/apps/frontend/src/pages/customer-fulfillment/CustomerFulfillmentPage.tsx new file mode 100644 index 00000000..651a1a1d --- /dev/null +++ b/apps/frontend/src/pages/customer-fulfillment/CustomerFulfillmentPage.tsx @@ -0,0 +1,810 @@ +import { + CheckCircleFilled, + LoadingOutlined, + QrcodeOutlined, + SafetyCertificateOutlined, +} from '@ant-design/icons' +import { + Alert, + App, + Button, + Card, + Col, + Image, + Input, + Result, + Row, + Select, + Space, + Spin, + Steps, + Tabs, + Tag, + Typography, +} from 'antd' +import QRCode from 'qrcode' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useParams } from 'react-router' + +import { + confirmCustomerBinding, + fetchCustomerFulfillment, + fetchCustomerWeiboCountryCodes, + loginCustomerWeiboSms, + markCustomerFulfillmentOpened, + pollCustomerBinding, + pollCustomerLogin, + pollCustomerWeiboQrLogin, + sendCustomerWeiboSmsCode, + startCustomerBinding, + startCustomerLogin, + startCustomerWeiboQrLogin, +} from '@/services/customer-fulfillment' +import type { CustomerWeiboCountryCode } from '@/services/customer-fulfillment' +import type { + CustomerBindingInfo, + CustomerLoginInfo, + CustomerSemiAutoTask, +} from '@/types/customer-fulfillment' +import { formatAdminDateTime } from '@/utils/admin-time' +import { runWeiboYidunChallenge } from '@/utils/weibo-yidun' + +const { Text, Title, Paragraph } = Typography + +const POLL_INTERVAL_MS = 2000 + +const DEFAULT_WEIBO_COUNTRY_CODES: CustomerWeiboCountryCode[] = [ + { code: '86', name: '中国' }, + { code: '852', name: '中国香港' }, + { code: '886', name: '中国台湾' }, + { code: '853', name: '中国澳门' }, + { code: '81', name: '日本' }, +] + +export default function CustomerFulfillmentPage() { + const { message } = App.useApp() + const { orderNo: routeOrderNo } = useParams<{ orderNo?: string }>() + const orderNo = String(routeOrderNo || '').trim() + const [loading, setLoading] = useState(true) + const [loadError, setLoadError] = useState('') + const [tasks, setTasks] = useState([]) + const [selectedTaskId, setSelectedTaskId] = useState(0) + const [loginInfo, setLoginInfo] = useState(null) + const [bindingInfo, setBindingInfo] = useState(null) + const [loginQrImage, setLoginQrImage] = useState('') + const [bindingActionLoading, setBindingActionLoading] = useState(false) + const [loginMode, setLoginMode] = useState<'sms' | 'qr'>('sms') + const [mobile, setMobile] = useState('') + const [countryCode, setCountryCode] = useState('86') + const [countryCodes, setCountryCodes] = useState( + DEFAULT_WEIBO_COUNTRY_CODES, + ) + const [smsCode, setSmsCode] = useState('') + const [smsSending, setSmsSending] = useState(false) + const [smsLogging, setSmsLogging] = useState(false) + const [smsCountdown, setSmsCountdown] = useState(0) + const [smsMfaRequired, setSmsMfaRequired] = useState(false) + const startingRef = useRef(false) + const hydratingBindingRef = useRef(false) + + const selectedTask = useMemo( + () => tasks.find((task) => task.id === selectedTaskId) || tasks[0] || null, + [selectedTaskId, tasks], + ) + const isWeibo = selectedTask?.platform === 'weibo' + + const load = useCallback( + async (silent = false) => { + if (!orderNo) { + setLoadError('订单号无效,请确认订单号是否正确') + setLoading(false) + return + } + if (!silent) setLoading(true) + try { + const response = await fetchCustomerFulfillment(orderNo) + const nextTasks = response.data || [] + setTasks(nextTasks) + setLoadError('') + setSelectedTaskId((current) => { + if (nextTasks.some((task) => task.id === current)) return current + return nextTasks[0]?.id || 0 + }) + } catch (error) { + if (!silent) { + setTasks([]) + setLoadError(error instanceof Error ? error.message : '读取订单履约信息失败') + } + } finally { + if (!silent) setLoading(false) + } + }, + [orderNo], + ) + + useEffect(() => { + void load() + }, [load]) + + useEffect(() => { + if (!selectedTask) return + void markCustomerFulfillmentOpened(orderNo, selectedTask.id).catch(() => undefined) + }, [orderNo, selectedTask?.id]) + + useEffect(() => { + if (!selectedTask || selectedTask.platform !== 'weibo' || !orderNo) return + let cancelled = false + void fetchCustomerWeiboCountryCodes(orderNo, selectedTask.id) + .then((response) => { + if (cancelled) return + const list = response.data?.countryCodes || [] + if (list.length > 0) setCountryCodes(list) + }) + .catch(() => undefined) + return () => { + cancelled = true + } + }, [orderNo, selectedTask?.id, selectedTask?.platform]) + + useEffect(() => { + if (loginInfo?.qrImage) { + setLoginQrImage(loginInfo.qrImage) + return + } + if (!loginInfo?.qrContent) { + setLoginQrImage('') + return + } + void QRCode.toDataURL(loginInfo.qrContent, { + width: 300, + margin: 2, + color: { dark: '#111827', light: '#ffffff' }, + }).then(setLoginQrImage) + }, [loginInfo?.qrContent, loginInfo?.qrImage]) + + useEffect(() => { + if (smsCountdown <= 0) return + const timer = window.setTimeout(() => setSmsCountdown((value) => value - 1), 1000) + return () => window.clearTimeout(timer) + }, [smsCountdown]) + + useEffect(() => { + if (!selectedTask || !orderNo) return + if (!['qr_pending', 'scanned'].includes(selectedTask.loginStatus)) return + const tick = async () => { + try { + const response = + selectedTask.platform === 'weibo' + ? await pollCustomerWeiboQrLogin(orderNo, selectedTask.id) + : await pollCustomerLogin(orderNo, selectedTask.id) + if (response.data.task) { + setTasks((current) => + current.map((task) => (task.id === response.data.task.id ? response.data.task : task)), + ) + } + if (response.data.login) setLoginInfo(response.data.login) + } catch { + // 短暂轮询失败不打断客户页面,下一轮继续。 + } + } + const timer = window.setInterval(() => { + void tick() + }, POLL_INTERVAL_MS) + return () => window.clearInterval(timer) + }, [orderNo, selectedTask?.id, selectedTask?.loginStatus, selectedTask?.platform]) + + useEffect(() => { + if (!selectedTask || !orderNo || selectedTask.platform === 'weibo') return + if ( + selectedTask.loginStatus !== 'authenticated' || + selectedTask.bindingStatus === 'confirmed' + ) { + return + } + if (selectedTask.bindingStatus === 'not_started' && !startingRef.current) { + startingRef.current = true + void startCustomerBinding(orderNo, selectedTask.id) + .then((response) => { + setTasks((current) => + current.map((task) => (task.id === response.data.task.id ? response.data.task : task)), + ) + setBindingInfo(response.data.binding) + }) + .catch((error) => { + message.error(error instanceof Error ? error.message : '创建绑定二维码失败') + }) + .finally(() => { + startingRef.current = false + }) + return + } + if (!['qr_pending', 'scanned'].includes(selectedTask.bindingStatus)) return + const tick = async () => { + try { + const response = await pollCustomerBinding(orderNo, selectedTask.id) + if (response.data.task) { + setTasks((current) => + current.map((task) => (task.id === response.data.task.id ? response.data.task : task)), + ) + } + if (response.data.binding) setBindingInfo(response.data.binding) + } catch { + // 同上,下一轮继续。 + } + } + const timer = window.setInterval(() => { + void tick() + }, POLL_INTERVAL_MS) + return () => window.clearInterval(timer) + }, [message, orderNo, selectedTask?.bindingStatus, selectedTask?.id, selectedTask?.loginStatus]) + + useEffect(() => { + if ( + !selectedTask || + !orderNo || + selectedTask.platform === 'weibo' || + bindingInfo || + hydratingBindingRef.current + ) + return + if ( + selectedTask.loginStatus !== 'authenticated' || + selectedTask.bindingStatus !== 'role_ready' + ) { + return + } + hydratingBindingRef.current = true + void pollCustomerBinding(orderNo, selectedTask.id) + .then((response) => { + setTasks((current) => + current.map((task) => (task.id === response.data.task.id ? response.data.task : task)), + ) + if (response.data.binding) setBindingInfo(response.data.binding) + }) + .catch(() => undefined) + .finally(() => { + hydratingBindingRef.current = false + }) + }, [ + bindingInfo, + orderNo, + selectedTask?.bindingStatus, + selectedTask?.id, + selectedTask?.loginStatus, + ]) + + async function handleStartLogin() { + if (!selectedTask) return + setLoading(true) + try { + const response = + selectedTask.platform === 'weibo' + ? await startCustomerWeiboQrLogin(orderNo, selectedTask.id) + : await startCustomerLogin(orderNo, selectedTask.id) + setTasks((current) => + current.map((task) => (task.id === response.data.task.id ? response.data.task : task)), + ) + setLoginInfo(response.data.login) + setBindingInfo(null) + } catch (error) { + message.error(error instanceof Error ? error.message : '创建登录二维码失败') + } finally { + setLoading(false) + } + } + + async function handleSendWeiboSms() { + if (!selectedTask) return + const phone = mobile.trim() + if (!isValidWeiboMobile(countryCode, phone)) { + message.warning('请输入正确的手机号') + return + } + setSmsSending(true) + try { + let response = await sendCustomerWeiboSmsCode(orderNo, selectedTask.id, phone, countryCode) + if (response.data.mfaRequired) { + setSmsMfaRequired(true) + if (!response.data.mfaId || !response.data.captchaId) { + throw new Error('微博返回的安全验证参数不完整') + } + await runWeiboYidunChallenge(response.data.mfaId, response.data.captchaId) + response = await sendCustomerWeiboSmsCode( + orderNo, + selectedTask.id, + phone, + countryCode, + response.data.mfaId, + ) + if (response.data.mfaRequired) { + throw new Error('微博安全验证未通过,请重新获取验证码') + } + } + message.success(response.data.message || '验证码已发送,请注意查收') + setSmsMfaRequired(false) + setSmsCountdown(60) + } catch (error) { + message.error(error instanceof Error ? error.message : '发送微博验证码失败') + } finally { + setSmsSending(false) + } + } + + async function handleLoginWeiboSms() { + if (!selectedTask) return + const phone = mobile.trim() + if (!isValidWeiboMobile(countryCode, phone)) { + message.warning('请输入正确的手机号') + return + } + if (!smsCode.trim()) { + message.warning('请输入微博短信验证码') + return + } + setSmsLogging(true) + try { + const response = await loginCustomerWeiboSms(orderNo, selectedTask.id, { + mobile: phone, + code: smsCode.trim(), + countryCode, + }) + setTasks((current) => + current.map((task) => (task.id === response.data.task.id ? response.data.task : task)), + ) + setLoginInfo(response.data.login) + setBindingInfo(null) + message.success('微博登录成功,等待客服处理') + } catch (error) { + const errorCode = (error as { errorCode?: string } | null)?.errorCode || '' + if (errorCode === 'weibo_sms_mfa_required') { + setSmsMfaRequired(true) + message.warning('微博要求二次验证,请改用扫码登录') + return + } + message.error(error instanceof Error ? error.message : '微博短信登录失败') + } finally { + setSmsLogging(false) + } + } + + async function handleConfirmBinding() { + if (!selectedTask) return + setBindingActionLoading(true) + try { + const response = await confirmCustomerBinding(orderNo, selectedTask.id) + setTasks((current) => + current.map((task) => (task.id === response.data.task.id ? response.data.task : task)), + ) + setBindingInfo(response.data.binding) + message.success('绑定已确认,等待客服处理') + } catch (error) { + message.error(error instanceof Error ? error.message : '确认绑定失败') + } finally { + setBindingActionLoading(false) + } + } + + async function handleStartRebind() { + if (!selectedTask) return + setBindingActionLoading(true) + try { + const response = await startCustomerBinding(orderNo, selectedTask.id, { + forceRebind: true, + }) + setTasks((current) => + current.map((task) => (task.id === response.data.task.id ? response.data.task : task)), + ) + setBindingInfo(response.data.binding) + } catch (error) { + message.error(error instanceof Error ? error.message : '创建换绑二维码失败') + } finally { + setBindingActionLoading(false) + } + } + + if (loading) { + return ( +
    + } tip="正在读取订单履约信息..." /> +
    + ) + } + + if (loadError || tasks.length === 0) { + return ( +
    + +
    + ) + } + + if (selectedTask?.executionStatus === 'completed') { + return ( +
    + } + title="履约已完成" + subTitle={ + selectedTask.completionNote + ? selectedTask.completionNote + : isWeibo + ? '客服已完成本订单的微博发帖操作,请到微博账号中确认。' + : '客服已完成本订单的充值或赠送操作,请到平台账号中确认。' + } + extra={ + selectedTask.completedAt + ? `完成时间:${formatAdminDateTime(selectedTask.completedAt)}` + : undefined + } + /> +
    + ) + } + + const config = selectedTask?.semiAutoConfig || {} + const title = config.pageTitle || (isWeibo ? '微博账号授权' : '账号授权与角色绑定') + const description = + config.pageDescription || + (isWeibo + ? '请使用本人微博账号完成登录,登录成功后客服会处理您的订单。' + : '请按页面指引完成平台登录和游戏角色绑定,客服随后会处理您的订单。') + const currentStep = resolveStep(selectedTask, bindingInfo) + const loginQrVisible = + selectedTask && ['qr_pending', 'scanned'].includes(selectedTask.loginStatus) + const bindingQrVisible = + selectedTask?.platform !== 'weibo' && + selectedTask?.loginStatus === 'authenticated' && + ['qr_pending', 'scanned', 'role_ready'].includes(selectedTask.bindingStatus) + const bindingQrPending = ['qr_pending', 'scanned'].includes(selectedTask?.bindingStatus || '') + const bindingRole = bindingInfo?.bindGameRole || selectedTask?.bindGameRole || '' + const bindingAccount = bindingInfo?.bindGameAccount || selectedTask?.bindGameAccount || '' + const bindingChannel = bindingInfo?.bindGameChannel || selectedTask?.bindGameChannel || '' + const roleChoiceRequired = + selectedTask?.bindingStatus === 'role_ready' && + bindingInfo?.hasExistingBinding === true && + bindingInfo?.rebindRequested !== true + + return ( +
    + +
    + + {title} + + + {description} + +
    + + {tasks.length > 1 ? ( + + + {tasks.map((task) => ( + + ))} + + + ) : null} + + + + + + 订单号 + + {selectedTask?.orderNo} + + 商品 + {selectedTask?.productName || selectedTask?.skuName} + {selectedTask?.platformLabel || selectedTask?.platform} + {selectedTask?.displayStatus.label} + + + + }, + { title: '客服处理', icon: }, + { title: '完成' }, + ] + : [ + { title: '登录平台', icon: }, + { title: '扫码绑定', icon: }, + { title: '客服处理', icon: }, + { title: '完成' }, + ] + } + /> + + + + + {selectedTask && selectedTask.executionStatus === 'failed' ? ( + + ) : null} + + {selectedTask?.loginStatus === 'waiting_login' || + selectedTask?.loginStatus === 'failed' || + selectedTask?.loginStatus === 'expired' ? ( + + {isWeibo ? ( + setLoginMode(key as 'sms' | 'qr')} + items={[ + { + key: 'sms', + label: '手机号登录', + children: ( + + + {smsMfaRequired ? ( + + ) : null} + + setMobile(event.target.value)} + placeholder="手机号" + maxLength={countryCode === '86' ? 11 : 15} + inputMode="numeric" + style={{ flex: 1 }} + /> + + + + setSmsCode(event.target.value)} + placeholder="请输入短信验证码" + maxLength={8} + onPressEnter={() => void handleLoginWeiboSms()} + /> + + + + 如安全验证弹窗未出现,请检查浏览器是否拦截脚本。 + + + ), + }, + { + key: 'qr', + label: '扫码登录', + children: ( + + + + + ), + }, + ]} + /> + ) : ( + + + + + )} + + ) : null} + + {loginQrVisible ? ( + + + {loginQrImage ? ( + {isWeibo + ) : ( + + )} + {loginInfo?.message || '等待扫码'} + {selectedTask.loginStatus === 'scanned' ? ( + + {isWeibo ? '已扫码,请在微博客户端确认登录' : '已扫码,请在 App 确认'} + + ) : null} + + + + ) : null} + + {bindingQrVisible ? ( + + + {bindingQrPending && bindingInfo?.qrImage ? ( + 游戏角色绑定二维码 + ) : bindingQrPending ? ( + + ) : null} + + {bindingInfo?.message || + config.bindingInstructions || + '请使用虎牙 App 扫码完成游戏角色绑定。'} + + {bindingRole ? ( + + ) : null} + {selectedTask.bindingStatus === 'role_ready' ? ( + + {roleChoiceRequired ? ( + + 请确认这是本次需要的游戏角色;角色不正确时请重新扫码换绑。 + + ) : null} + + + {roleChoiceRequired ? ( + + ) : null} + + + ) : null} + + + ) : null} + + {selectedTask?.bindingStatus === 'confirmed' && + selectedTask.executionStatus !== 'completed' ? ( + + + + ) : null} +
    +
    + ) +} + +function isValidWeiboMobile(countryCode: string, value: string) { + const digits = value.replace(/\D/g, '') + if (!digits) return false + if (countryCode === '86') return /^1\d{10}$/.test(digits) + return digits.length >= 5 && digits.length <= 15 +} + +function resolveStep(task: CustomerSemiAutoTask | null, binding: CustomerBindingInfo | null) { + if (!task) return 0 + if (task.platform === 'weibo') { + if (task.executionStatus === 'completed') return 2 + if (task.bindingStatus === 'confirmed') return 1 + return 0 + } + if (task.executionStatus === 'completed') return 3 + if (task.bindingStatus === 'confirmed') return 2 + if (task.loginStatus === 'authenticated' || binding) return 1 + return 0 +} diff --git a/apps/frontend/src/services/admin/cost-center.ts b/apps/frontend/src/services/admin/cost-center.ts index 0136ec42..a61b1ea5 100644 --- a/apps/frontend/src/services/admin/cost-center.ts +++ b/apps/frontend/src/services/admin/cost-center.ts @@ -362,6 +362,9 @@ export function saveAdminManualConfig(payload: { canonicalProductId?: number | null enabled?: boolean note?: string + semiAutoEnabled?: boolean + semiAutoPlatform?: '' | 'huya' | 'weibo' + semiAutoConfig?: Record }) { return apiPost('/api/v1/admin/cost-center/manual-configs', payload) } diff --git a/apps/frontend/src/services/admin/dev-mock.ts b/apps/frontend/src/services/admin/dev-mock.ts index 981e43f1..7f54e343 100644 --- a/apps/frontend/src/services/admin/dev-mock.ts +++ b/apps/frontend/src/services/admin/dev-mock.ts @@ -10,6 +10,12 @@ export type DevMockStatus = { description: string steps: string[] }> + semiAuto?: { + defaultConnectorMode: 'embedded' | 'external' | 'mock' + externalConnectorConfigured: boolean + mockConnectorAvailable: boolean + platform: string + } } export type DevMockCreateResult = { @@ -45,6 +51,23 @@ export type DevMockKuaishouIndustryVoucherResult = { }> } +export type DevMockSemiAutoResult = { + platform: 'semi_auto' + semiAutoPlatform: 'huya' | 'weibo' + orderId: number + orderNo: string + orderItemId: number + fulfillmentId: number + configId: number + taskId: number + skuKey: string + connectorMode: 'embedded' | 'external' | 'mock' + connectorConfigured: boolean + customerPath: string + adminPath: string + tips: string[] +} + export function fetchDevMockStatus() { return apiGet('/api/v1/admin/dev-mock/status') } @@ -66,6 +89,19 @@ export function createKuaishouIndustryVoucherDevMock(payload: { sellerId?: strin ) } +export function createSemiAutoDevMock(payload: { + platform?: 'huya' | 'weibo' + orderNo?: string + skuName?: string + quantity?: number + pageTitle?: string + pageDescription?: string + browserTargetUrl?: string + connectorMode?: 'embedded' | 'external' | 'mock' +}) { + return apiPost('/api/v1/admin/dev-mock/semi-auto', payload) +} + export function buildOpen91QueryDevMock(payload: { orderNo: string execute?: boolean diff --git a/apps/frontend/src/services/admin/semi-auto.ts b/apps/frontend/src/services/admin/semi-auto.ts new file mode 100644 index 00000000..1ec458d9 --- /dev/null +++ b/apps/frontend/src/services/admin/semi-auto.ts @@ -0,0 +1,52 @@ +import { apiGet, apiPost } from '@/lib/http' +import type { + SemiAutoCredentialExport, + SemiAutoTaskDetail, + SemiAutoTaskListResult, +} from '@/types/admin/semi-auto' + +export function fetchAdminSemiAutoTasks(params: Record = {}) { + return apiGet('/api/v1/admin/semi-auto/tasks', params) +} + +export function fetchAdminSemiAutoTask(taskId: number) { + return apiGet(`/api/v1/admin/semi-auto/tasks/${taskId}`) +} + +export function exportAdminSemiAutoCredential(taskId: number) { + return apiPost( + `/api/v1/admin/semi-auto/tasks/${taskId}/credential/export`, + {}, + ) +} + +export function claimAdminSemiAutoTask(taskId: number) { + return apiPost(`/api/v1/admin/semi-auto/tasks/${taskId}/claim`, {}) +} + +export function syncAdminSemiAutoTask(taskId: number) { + return apiPost(`/api/v1/admin/semi-auto/tasks/${taskId}/sync`, {}) +} + +export function createAdminSemiAutoBrowserSession(taskId: number, targetUrl?: string) { + return apiPost<{ ticket: string; expiresAt: string; targetUrl: string }>( + `/api/v1/admin/semi-auto/tasks/${taskId}/browser-session`, + { targetUrl: targetUrl || '' }, + ) +} + +export function completeAdminSemiAutoTask( + taskId: number, + payload: { + note?: string + externalOrderNo?: string + costFen?: number + screenshots?: Array> + }, +) { + return apiPost(`/api/v1/admin/semi-auto/tasks/${taskId}/complete`, payload) +} + +export function cancelAdminSemiAutoTask(taskId: number, reason: string) { + return apiPost(`/api/v1/admin/semi-auto/tasks/${taskId}/cancel`, { reason }) +} diff --git a/apps/frontend/src/services/customer-fulfillment.ts b/apps/frontend/src/services/customer-fulfillment.ts new file mode 100644 index 00000000..9ea205ad --- /dev/null +++ b/apps/frontend/src/services/customer-fulfillment.ts @@ -0,0 +1,110 @@ +import { apiGet, apiPost } from '@/lib/http' +import type { + CustomerBindingInfo, + CustomerLoginInfo, + CustomerSemiAutoTask, +} from '@/types/customer-fulfillment' + +export function fetchCustomerFulfillment(orderNo: string) { + return apiGet( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}`, + ) +} + +export function markCustomerFulfillmentOpened(orderNo: string, taskId: number) { + return apiPost<{ ok: boolean }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/open`, + {}, + ) +} + +export function startCustomerLogin(orderNo: string, taskId: number) { + return apiPost<{ task: CustomerSemiAutoTask; login: CustomerLoginInfo }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/login/start`, + {}, + ) +} + +export function pollCustomerLogin(orderNo: string, taskId: number) { + return apiGet<{ task: CustomerSemiAutoTask; login: CustomerLoginInfo | null }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/login/status`, + ) +} + +export function startCustomerBinding( + orderNo: string, + taskId: number, + options: { forceRebind?: boolean } = {}, +) { + return apiPost<{ task: CustomerSemiAutoTask; binding: CustomerBindingInfo }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/binding/start`, + options.forceRebind ? { forceRebind: true } : {}, + ) +} + +export function pollCustomerBinding(orderNo: string, taskId: number) { + return apiGet<{ task: CustomerSemiAutoTask; binding: CustomerBindingInfo | null }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/binding/status`, + ) +} + +export function confirmCustomerBinding(orderNo: string, taskId: number) { + return apiPost<{ task: CustomerSemiAutoTask; binding: CustomerBindingInfo }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/binding/confirm`, + {}, + ) +} + +export type CustomerWeiboCountryCode = { + code: string + name: string +} + +export function fetchCustomerWeiboCountryCodes(orderNo: string, taskId: number) { + return apiGet<{ countryCodes: CustomerWeiboCountryCode[] }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/weibo/config`, + ) +} + +export function sendCustomerWeiboSmsCode( + orderNo: string, + taskId: number, + mobile: string, + countryCode: string, + mfaId = '', +) { + return apiPost<{ + ok: boolean + message: string + mfaRequired: boolean + mfaId?: string + captchaId?: string + }>(`/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/weibo/sms/send`, { + mobile, + countryCode, + mfaId, + }) +} + +export function loginCustomerWeiboSms( + orderNo: string, + taskId: number, + input: { mobile: string; code: string; countryCode: string; rid?: string }, +) { + return apiPost<{ task: CustomerSemiAutoTask; login: CustomerLoginInfo }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/weibo/sms/login`, + input, + ) +} + +export function startCustomerWeiboQrLogin(orderNo: string, taskId: number) { + return apiGet<{ task: CustomerSemiAutoTask; login: CustomerLoginInfo }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/weibo/qrcode`, + ) +} + +export function pollCustomerWeiboQrLogin(orderNo: string, taskId: number) { + return apiGet<{ task: CustomerSemiAutoTask; login: CustomerLoginInfo | null }>( + `/api/v1/customer-fulfillment/${encodeURIComponent(orderNo)}/tasks/${taskId}/weibo/qrcode/status`, + ) +} diff --git a/apps/frontend/src/styles/client.css b/apps/frontend/src/styles/client.css index 42e7c49f..5dadeaba 100644 --- a/apps/frontend/src/styles/client.css +++ b/apps/frontend/src/styles/client.css @@ -1435,3 +1435,26 @@ max-width: 116px; } } + +.customer-fulfillment-page { + min-height: 100vh; + padding: clamp(18px, 3vw, 42px) clamp(14px, 4vw, 64px); + background: + radial-gradient(circle at 10% 0%, rgba(249, 115, 22, 0.14), transparent 30%), + linear-gradient(180deg, #fffaf5 0%, #f8fafc 45%, #f1f5f9 100%); +} + +.customer-fulfillment-page > * { + width: min(1080px, 100%); + margin-inline: auto; +} + +.customer-fulfillment-centered { + display: grid; + place-items: center; +} + +.customer-fulfillment-centered .ant-result, +.customer-fulfillment-centered .ant-spin-nested-loading { + width: min(720px, 100%); +} diff --git a/apps/frontend/src/types/admin/cost-center.ts b/apps/frontend/src/types/admin/cost-center.ts index d11b3b40..dc5a3952 100644 --- a/apps/frontend/src/types/admin/cost-center.ts +++ b/apps/frontend/src/types/admin/cost-center.ts @@ -430,6 +430,15 @@ export interface ManualFulfillmentConfig { /** 平台换算率(分/积分):南航/乐玩 1,ROCK 100(1 积分 = 1 元)。 */ creditUnitPriceFen: number enabled: boolean + semiAutoEnabled: boolean + semiAutoPlatform: '' | 'huya' | 'weibo' + semiAutoConfig: { + pageTitle?: string + pageDescription?: string + loginInstructions?: string + bindingInstructions?: string + browserTargets?: Array<{ key: string; label: string; url: string }> + } note?: string createdAt?: string updatedAt?: string diff --git a/apps/frontend/src/types/admin/semi-auto.ts b/apps/frontend/src/types/admin/semi-auto.ts new file mode 100644 index 00000000..b2de9aaf --- /dev/null +++ b/apps/frontend/src/types/admin/semi-auto.ts @@ -0,0 +1,101 @@ +export type SemiAutoPlatform = 'huya' | 'weibo' + +export type SemiAutoDisplayStatus = { + key: string + label: string +} + +export type SemiAutoTask = { + id: number + orderId: number + orderItemId: number + fulfillmentId: number | null + platform: SemiAutoPlatform + platformLabel: string + loginStatus: string + bindingStatus: string + executionStatus: string + connectorMode: 'embedded' | 'external' | 'mock' + displayStatus: SemiAutoDisplayStatus + connectorReady: boolean + credentialReady: boolean + credentialStatus: 'unknown' | 'valid' | 'invalid' | 'error' + credentialSource: string + credentialUpdatedAt: string | null + huyaUid: string + platformNickname: string + bindGameAccount: string + bindGameRole: string + bindGameChannel: string + targetQuantity: number + completedQuantity: number + assignedAdminUserId: number | null + assignedAdminName: string + customerLinkOpenedAt: string | null + authStartedAt: string | null + authenticatedAt: string | null + bindingStartedAt: string | null + boundAt: string | null + completedAt: string | null + completionNote: string + externalOrderNo: string + completionEvidence: Record + lastError: string + createdAt: string + updatedAt: string + orderNo: string + provider: string + shopId: string + skuCode: string + skuName: string + productName: string + quantity: number + semiAutoConfig: { + pageTitle?: string + pageDescription?: string + loginInstructions?: string + bindingInstructions?: string + browserTargets?: Array<{ key: string; label: string; url: string }> + } +} + +export type SemiAutoTaskEvent = { + id: number + eventType: string + actorType: string + actorId: string + detail: Record + createdAt: string +} + +export type SemiAutoTaskListResult = { + items: SemiAutoTask[] + pagination: { page: number; pageSize: number; total: number } +} + +export type SemiAutoTaskDetail = { + task: SemiAutoTask + events: SemiAutoTaskEvent[] +} + +export type SemiAutoCredentialExport = { + credentialId: number + platform: SemiAutoPlatform + platformUid: string + nickname: string + source: string + status: 'unknown' | 'valid' | 'invalid' | 'error' + updatedAt: string + targetUrl: string + cookieHeader: string + cookies: Array<{ + name: string + value: string + domain: string + path: string + secure: boolean + httpOnly: boolean + hostOnly?: boolean + expiresAt: string | null + }> +} diff --git a/apps/frontend/src/types/customer-fulfillment.ts b/apps/frontend/src/types/customer-fulfillment.ts new file mode 100644 index 00000000..3dd4b6c1 --- /dev/null +++ b/apps/frontend/src/types/customer-fulfillment.ts @@ -0,0 +1,47 @@ +export type CustomerSemiAutoTask = { + id: number + platform: 'huya' | 'weibo' + platformLabel: string + orderNo: string + productName: string + skuName: string + skuCode: string + quantity: number + loginStatus: string + bindingStatus: string + executionStatus: string + displayStatus: { key: string; label: string } + huyaUid: string + platformNickname: string + bindGameAccount: string + bindGameRole: string + bindGameChannel: string + completedAt: string | null + completionNote: string + semiAutoConfig: { + pageTitle?: string + pageDescription?: string + loginInstructions?: string + bindingInstructions?: string + } +} + +export type CustomerLoginInfo = { + status: string + qrContent: string + qrImage?: string + expiresAt: string + message: string +} + +export type CustomerBindingInfo = { + status: string + qrImage: string + qrExpiresAt: string + bindGameAccount: string + bindGameRole: string + bindGameChannel: string + hasExistingBinding?: boolean + rebindRequested?: boolean + message: string +} diff --git a/apps/frontend/src/utils/customer-fulfillment-link.ts b/apps/frontend/src/utils/customer-fulfillment-link.ts new file mode 100644 index 00000000..5fc0777b --- /dev/null +++ b/apps/frontend/src/utils/customer-fulfillment-link.ts @@ -0,0 +1,6 @@ +/** 客户半自动履约入口:/c/:orderNo。 */ +export function isCustomerFulfillmentPath(pathname: unknown): boolean { + const normalized = String(pathname || '').trim() + if (!normalized.startsWith('/')) return false + return normalized.split(/[?#]/)[0].replace(/\/+$/, '').split('/').filter(Boolean)[0] === 'c' +} diff --git a/apps/frontend/src/utils/weibo-yidun.ts b/apps/frontend/src/utils/weibo-yidun.ts new file mode 100644 index 00000000..c6bdd06a --- /dev/null +++ b/apps/frontend/src/utils/weibo-yidun.ts @@ -0,0 +1,70 @@ +type WeiboYidunCallback = (params: unknown, message: string, success: boolean) => void + +type WeiboYidunWindow = Window & { + ydInit?: ( + options: { + geetestKey: string + captchaId: string + product: 'popup' + lang: string + }, + callback: WeiboYidunCallback, + ) => void +} + +const YIDUN_SDK_URL = 'https://passport.sinaimg.cn/js/yidun/v1/yidunsdk.min.js' +let sdkPromise: Promise | null = null + +export function loadWeiboYidunSdk(): Promise { + if (typeof window === 'undefined' || typeof document === 'undefined') { + return Promise.reject(new Error('当前环境不支持微博安全验证')) + } + if ((window as WeiboYidunWindow).ydInit) return Promise.resolve() + if (sdkPromise) return sdkPromise + + sdkPromise = new Promise((resolve, reject) => { + const existing = document.querySelector(`script[src="${YIDUN_SDK_URL}"]`) + const script = existing || document.createElement('script') + script.src = YIDUN_SDK_URL + script.async = true + script.onload = () => { + if ((window as WeiboYidunWindow).ydInit) { + resolve() + } else { + sdkPromise = null + reject(new Error('微博安全验证组件初始化失败')) + } + } + script.onerror = () => { + sdkPromise = null + reject(new Error('微博安全验证组件加载失败,请检查网络')) + } + if (!existing) document.head.appendChild(script) + }) + return sdkPromise +} + +export async function runWeiboYidunChallenge(mfaId: string, captchaId: string): Promise { + await loadWeiboYidunSdk() + const ydInit = (window as WeiboYidunWindow).ydInit + if (!ydInit) throw new Error('微博安全验证组件不可用') + if (!mfaId || !captchaId) throw new Error('微博安全验证参数无效') + + await new Promise((resolve, reject) => { + ydInit( + { + geetestKey: mfaId, + captchaId, + product: 'popup', + lang: 'zh-CN', + }, + (_params, message, success) => { + if (success) { + resolve() + return + } + reject(new Error(message === 'close' ? '已取消安全验证' : message || '微博安全验证失败')) + }, + ) + }) +} diff --git a/apps/frontend/tests/customer-fulfillment-link.test.ts b/apps/frontend/tests/customer-fulfillment-link.test.ts new file mode 100644 index 00000000..ea553831 --- /dev/null +++ b/apps/frontend/tests/customer-fulfillment-link.test.ts @@ -0,0 +1,17 @@ +import assert from 'node:assert/strict' +import test from 'node:test' + +import { isCustomerFulfillmentPath } from '../src/utils/customer-fulfillment-link.ts' + +test('客户半自动履约入口:/c 命名空间整段命中', () => { + assert.equal(isCustomerFulfillmentPath('/c/263123'), true) + assert.equal(isCustomerFulfillmentPath('/c'), true) + assert.equal(isCustomerFulfillmentPath('/c/a/b'), true) +}) + +test('客户半自动履约入口不误伤相似前缀和其他路径', () => { + assert.equal(isCustomerFulfillmentPath('/claim/x'), false) + assert.equal(isCustomerFulfillmentPath('/customer/x'), false) + assert.equal(isCustomerFulfillmentPath('/admin/c/1'), false) + assert.equal(isCustomerFulfillmentPath('c/1'), false) +}) diff --git a/deploy/docker/backend-dev.Dockerfile b/deploy/docker/backend-dev.Dockerfile index f0d5f491..e2b63a00 100644 --- a/deploy/docker/backend-dev.Dockerfile +++ b/deploy/docker/backend-dev.Dockerfile @@ -1,37 +1,12 @@ # 快手轻量开发镜像:只保留 Node 运行时和基础工具。 -# 基础镜像源可整体替换(.env 的 BASE_REGISTRY),原因见 backend.Dockerfile 顶部注释。 -ARG BASE_REGISTRY=docker.m.daocloud.io -FROM ${BASE_REGISTRY}/library/node:22-bookworm - -# 阿里云公共源(全国可达);也可构建时覆盖:--build-arg DEBIAN_MIRROR=mirrors.cloud.aliyuncs.com -ARG DEBIAN_MIRROR=mirrors.aliyun.com -ARG NPM_REGISTRY=https://registry.npmmirror.com +# 本地 dev 不写死 registry,交给 Docker Desktop 的默认 Docker Hub 与 mirrors。 +FROM node:22-bookworm-slim ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Asia/Shanghai -ENV NPM_CONFIG_REGISTRY=${NPM_REGISTRY} WORKDIR /app -# bookworm 基础镜像可能尚无 ca-certificates;国内源常跳 HTTPS,需先跳过校验装证书 -RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,target=/var/lib/apt,sharing=locked \ - sed -i "s|http://deb.debian.org/debian|http://${DEBIAN_MIRROR}/debian|g" /etc/apt/sources.list.d/debian.sources \ - && sed -i "s|http://security.debian.org/debian-security|http://${DEBIAN_MIRROR}/debian-security|g" /etc/apt/sources.list.d/debian.sources \ - && apt-get -o Acquire::https::Verify-Peer=false -o Acquire::https::Verify-Host=false update \ - && apt-get -o Acquire::https::Verify-Peer=false -o Acquire::https::Verify-Host=false install -y --no-install-recommends \ - ca-certificates \ - && apt-get update \ - && apt-get install -y --no-install-recommends \ - curl tzdata \ - && ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime \ - && echo ${TZ} > /etc/timezone - -COPY apps/backend/package.json apps/backend/package-lock.json ./ -RUN --mount=type=cache,target=/root/.npm npm ci - -COPY apps/backend/ ./ - RUN mkdir -p /app/data EXPOSE 3000 diff --git a/deploy/mac-dev.sh b/deploy/mac-dev.sh index aad4cc72..6a6b7944 100755 --- a/deploy/mac-dev.sh +++ b/deploy/mac-dev.sh @@ -322,10 +322,20 @@ wait_for_health() { print_applied_migrations() { log "已应用数据库迁移" - local sql migrations - sql='SELECT COALESCE(filename, name) FROM schema_migrations ORDER BY COALESCE(filename, name);' - - if migrations="$("${COMPOSE_CMD[@]}" exec -T postgres sh -lc 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Atc "$1"' sh "${sql}" 2>&1)"; then + local migrations + # 必须从后端真实 DATABASE_URL 读取,不能固定用 postgres 容器的 POSTGRES_DB: + # 本地测试库可能通过 DATABASE_URL 指向独立数据库(例如 order_site_test)。 + if migrations="$("${COMPOSE_CMD[@]}" exec -T backend node --import tsx --input-type=module -e ' + const { query, closeDb } = await import("./src/db/client.ts"); + try { + const result = await query( + "SELECT COALESCE(filename, name) AS name FROM schema_migrations ORDER BY COALESCE(filename, name)" + ); + console.log(result.rows.map((row) => row.name).join("\n")); + } finally { + await closeDb(); + } + ' 2>&1)"; then printf '%s\n' "${migrations:-"(无迁移记录)"}" return fi diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 93adc571..75af6b4a 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -6,7 +6,7 @@ x-json-log-rotation: &json-log-rotation services: postgres: - image: ${BASE_REGISTRY:-docker.m.daocloud.io}/library/postgres:16-bookworm + image: postgres:16-bookworm command: [ "postgres", @@ -51,29 +51,35 @@ services: - postgres_dev_data:/var/lib/postgresql/data minio: - image: ${BASE_REGISTRY:-docker.m.daocloud.io}/minio/minio:latest + # MinIO 官方镜像已停止维护;使用固定版本的 Bitnami Legacy 构建,避免 latest 漂移。 + image: bitnamilegacy/minio:2025.7.23-debian-12-r5 + # 首次启动以 root 修正既有 dev volume 的权限,随后镜像脚本会降权为 minio 用户运行。 + user: "0" restart: unless-stopped logging: *json-log-rotation - command: server /data --address ":9000" --console-address ":9001" environment: TZ: ${TZ:-Asia/Shanghai} MINIO_ROOT_USER: ${STORAGE_ACCESS_KEY_ID:-minioadmin} MINIO_ROOT_PASSWORD: ${STORAGE_SECRET_ACCESS_KEY:-minioadmin} + MINIO_API_PORT_NUMBER: "9000" + MINIO_CONSOLE_PORT_NUMBER: "9001" + MINIO_BROWSER: "on" ports: - "${MINIO_API_PORT:-19000}:9000" - "${MINIO_CONSOLE_PORT:-19001}:9001" + healthcheck: + test: ["CMD", "curl", "-fsS", "http://127.0.0.1:9000/minio/health/live"] + interval: 5s + timeout: 5s + retries: 20 + start_period: 10s volumes: - - minio_dev_data:/data + - minio_dev_data:/bitnami/minio/data backend: build: context: . dockerfile: deploy/docker/backend-dev.Dockerfile - args: - # 基础镜像源(registry 前缀),与生产 compose 同一套语义。 - BASE_REGISTRY: ${BASE_REGISTRY:-docker.m.daocloud.io} - DEBIAN_MIRROR: ${DEBIAN_MIRROR:-mirrors.aliyun.com} - NPM_REGISTRY: ${NPM_REGISTRY:-https://registry.npmmirror.com} restart: unless-stopped env_file: - .env @@ -83,10 +89,13 @@ services: postgres: condition: service_healthy minio: - condition: service_started + condition: service_healthy healthcheck: test: - ["CMD-SHELL", "curl -fsS http://127.0.0.1:3000/health/ready || exit 1"] + [ + "CMD-SHELL", + "node -e \"fetch('http://127.0.0.1:3000/health/ready').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\"", + ] interval: 5s timeout: 5s retries: 20 @@ -118,6 +127,11 @@ services: WORKSPACE_ROOT: /workspace # ADMIN_* 仅走 env_file,避免 JSON 经 ${} 注入时被 YAML 破坏 KUASHOU_INDUSTRY_RATE_LIMIT_MAX: ${KUASHOU_INDUSTRY_RATE_LIMIT_MAX:-120} + # 默认使用 order_site 内置真实 Connector;只有 external 模式才读取远程地址与密钥。 + SEMI_AUTO_DEFAULT_CONNECTOR_MODE: ${SEMI_AUTO_DEFAULT_CONNECTOR_MODE:-embedded} + SEMI_AUTO_CONNECTOR_BASE_URL: ${SEMI_AUTO_CONNECTOR_BASE_URL:-} + SEMI_AUTO_CONNECTOR_API_KEY: ${SEMI_AUTO_CONNECTOR_API_KEY:-} + SEMI_AUTO_CONNECTOR_TIMEOUT_MS: ${SEMI_AUTO_CONNECTOR_TIMEOUT_MS:-15000} logging: *json-log-rotation volumes: - ./apps/backend:/app @@ -131,7 +145,7 @@ services: - ./apps/backend/data:/app/data frontend: - image: ${BASE_REGISTRY:-docker.m.daocloud.io}/library/node:22-bookworm-slim + image: node:22-bookworm-slim working_dir: /app restart: unless-stopped logging: *json-log-rotation @@ -142,7 +156,6 @@ services: environment: TZ: ${TZ:-Asia/Shanghai} CHOKIDAR_USEPOLLING: "true" - NPM_CONFIG_REGISTRY: https://registry.npmmirror.com VITE_API_TARGET: http://backend:3000 VITE_ALLOWED_HOSTS: ${VITE_ALLOWED_HOSTS:-localhost,127.0.0.1} VITE_WORKER_SITE_URL: ${WORKER_SITE_ADDR:-http://worker.localhost} @@ -155,7 +168,7 @@ services: # 打手端专用 dev server:同一份代码,只把「打手端 hostname」设成 IP, # 由 Caddy 的 8080 端口反代过来(前端按 hostname 判站点,见 utils/site.ts)。 frontend-worker: - image: ${BASE_REGISTRY:-docker.m.daocloud.io}/library/node:22-bookworm-slim + image: node:22-bookworm-slim working_dir: /app restart: unless-stopped logging: *json-log-rotation @@ -169,7 +182,6 @@ services: environment: TZ: ${TZ:-Asia/Shanghai} CHOKIDAR_USEPOLLING: "true" - NPM_CONFIG_REGISTRY: https://registry.npmmirror.com VITE_API_TARGET: http://backend:3000 VITE_ALLOWED_HOSTS: ${VITE_ALLOWED_HOSTS:-localhost,127.0.0.1} VITE_WORKER_SITE_URL: ${WORKER_SITE_ADDR_IP:-http://192.168.10.8} @@ -180,7 +192,7 @@ services: - frontend_worker_node_modules:/app/node_modules web: - image: ${BASE_REGISTRY:-docker.m.daocloud.io}/library/caddy:2-alpine + image: caddy:2-alpine restart: unless-stopped logging: *json-log-rotation depends_on: diff --git a/docker-compose.yml b/docker-compose.yml index eff95463..7112f9f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -137,6 +137,10 @@ services: # ADMIN_SESSION_SECRET / ADMIN_DEFAULT_USERS_JSON 仅走 env_file。 # 勿在此处用 ${ADMIN_DEFAULT_USERS_JSON} 再注入:JSON 会被 YAML 解析破坏,导致生产校验失败。 KUASHOU_INDUSTRY_RATE_LIMIT_MAX: ${KUASHOU_INDUSTRY_RATE_LIMIT_MAX:-120} + SEMI_AUTO_CONNECTOR_BASE_URL: ${SEMI_AUTO_CONNECTOR_BASE_URL:-} + SEMI_AUTO_CONNECTOR_API_KEY: ${SEMI_AUTO_CONNECTOR_API_KEY:-} + SEMI_AUTO_DEFAULT_CONNECTOR_MODE: ${SEMI_AUTO_DEFAULT_CONNECTOR_MODE:-embedded} + SEMI_AUTO_CONNECTOR_TIMEOUT_MS: ${SEMI_AUTO_CONNECTOR_TIMEOUT_MS:-15000} logging: *json-log-rotation volumes: - ./apps/backend/data:/app/data diff --git a/docs/生产升级操作手册.md b/docs/生产升级操作手册.md index 23a9368a..71b8e794 100644 --- a/docs/生产升级操作手册.md +++ b/docs/生产升级操作手册.md @@ -17,6 +17,24 @@ updated_at: 2026-11-08 > [部署启动与数据库重建](部署启动与数据库重建.md)。 > 只要包含迁移、表结构切换或派生数据重建,必须按本手册执行。 +> 2026-11-13 增量待发布基线:`dev_11.9_2` 从生产迁移 `151` 增量到 `156`。 +> 该次变更包含 `152_order_source_facts_immutable.sql`、`153_semi_auto_fulfillment.sql`、 +> `154_semi_auto_connector_mode.sql`、`155_semi_auto_connector_mode_embedded.sql`、 +> `156_semi_auto_credentials.sql`。在发布负责人确认目标提交并完成隔离恢复演练前,只作为开发基线, +> 不得按旧的 `147–150` 一条路径直接上线。 + +### 1.1 迁移 `151 → 156` 增量门禁 + +- 升级前必须确认生产最高迁移仍为 `151`;分支合并后重新核对迁移号,禁止回退或改写 `151` 及以前文件。 +- `156` 新增账号级加密凭证表、`semi_auto_tasks.credential_id` 和 + `semi_auto.credential.export` 权限;不迁移或清理订单、退款、资金流水等 A 级事实。 +- 发布环境必须预先配置稳定的 `SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY`(至少 32 字符)。 + 未配置或仍为示例值时,生产运行时校验会拒绝启动。 +- 迁移完成后至少验证 `semi_auto_credentials` 表、任务外键、索引和导出权限存在; + 用测试库完成 `001 → 156` 空库迁移,并在隔离库验证 `151 → 156`。 +- 该增量仍包含迁移,普通停机发布不能使用 `deploy/ubuntu-deploy.sh` 在旧后端运行时直接换库; + 必须沿用本手册的停写、最终备份、隔离恢复验证、迁移、新后端健康检查和验收流程。 + ## 一、本次升级基线 以下信息是 2026-11-08 的首次执行基线。后续每次升级必须由发布负责人更新, diff --git a/docs/统一订单履约与财务模型-权威版.md b/docs/统一订单履约与财务模型-权威版.md index 7d1d797c..c70fb5cb 100644 --- a/docs/统一订单履约与财务模型-权威版.md +++ b/docs/统一订单履约与财务模型-权威版.md @@ -3,16 +3,16 @@ type: 权威架构与实施计划 description: 订单、内部 SKU、履约路由、履约执行、商品、成本与财务的唯一权威口径及重构计划。 tags: [订单, 内部SKU, 履约, 商品, 成本, 财务, 迁移] status: authoritative -version: 2.5 -updated_at: 2026-11-09 +version: 2.11 +updated_at: 2026-11-13 --- # 统一订单、履约与财务模型 > 状态:**唯一权威文档**。 -> 最后校准:2026-11-09。 +> 最后校准:2026-11-13。 > 生产基线:迁移 `151`。 -> 开发基线:迁移 `152`(仅本地,尚未部署生产)。 +> 开发基线:迁移 `156`(仅本地,尚未部署生产)。 > > 从本文件生效起,订单、内部 SKU、履约渠道、履约载体、标准商品、成本和财务相关实现, > 只能以本文件为业务口径。其他旧分析只作为历史资料,不再具备设计或验收效力。 @@ -269,6 +269,56 @@ fulfillment_issues 同一订单项只能有一个当前尝试。历史尝试只追加,不覆盖。 +### 3.4.1 人工渠道半自动履约 + +半自动履约不是新的履约渠道,而是 `manual` 渠道下的辅助执行域: + +```text +manual fulfillment + → semi_auto_tasks + → 平台登录 / 角色绑定 / 浏览器辅助操作 + → confirmManualFulfillment +``` + +规则: + +- `fulfillments.channel` 仍为 `manual`;成本、销售与总账口径不变。 +- 是否启用半自动履约由 `manual_fulfillment_configs.semi_auto_*` 显式配置,不能按商品名或平台前缀猜测。 +- 半自动任务必须绑定 `order_item_id`、`fulfillments.id` 和人工履约配置,不得伪造接单平台工单。 +- 登录状态、绑定状态、执行状态必须正交保存于 `semi_auto_tasks`;不得写入 `material_json` 作为正式状态。 +- 平台 CK 是账号级凭证,唯一持久化真源为 `semi_auto_credentials`。Cookie 集合按平台 UID 唯一保存, + 使用 AES-256-GCM 加密后写入 `credential_ciphertext`,并记录来源、更新时间、健康状态和最近检查错误。 + `semi_auto_tasks.credential_id` 只引用账号凭证,任务表不保存 CK 明文。 +- Connector 会话仍是进程内短期缓存,但不再是唯一真源。进程重启、会话过期或实例切换后, + 执行器必须从账号级密文凭证恢复会话;恢复前校验平台 UID,恢复失败时更新凭证健康状态并要求重新登录。 +- 生产必须配置稳定且至少 32 字符的 `SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY`。该密钥不得与日志、 + 任务事件、接口响应或导出内容一起保存;未完成历史凭证重加密前不得直接更换密钥。 +- CK 不得进入普通任务 DTO、客户页面、任务事件、错误日志或审计明细。人工后台默认只展示平台 UID、 + 凭证来源、健康状态和更新时间;仅持有 `semi_auto.credential.export` 权限的角色可受控导出单个任务的 + 账号 Cookie,导出响应必须禁止缓存,审计只记录任务、凭证 ID 和平台,不记录 Cookie 内容。 +- 微博登录必须保留完整域名/路径 Cookie Jar,不能在跨域跳转后把所有同名 Cookie 合并成单个字符串。 + 浏览器注入只下发与目标 URL 匹配的 Cookie;账号级凭证保存完整集合,以便后续会话恢复和跨域重放。 +- 微博手机号登录首次发码返回 `mfa_1` 时,客户必须在浏览器完成网易易盾安全验证,再使用同一会话的 + `mfa_id` 重发短信;服务端不尝试绕过或伪造人机验证。 +- 半自动任务通过 `connector_mode` 显式记录 Connector 来源: + `embedded` 为 order_site 内置真实实现并作为默认值,`external` 为显式配置的远程真实实现, + `mock` 为 order_site 内置开发 Mock 且仅在非生产环境可用。开发 Mock 造单时默认选择 `embedded`, + 只有需要完全脱离虎牙接口联调页面时才显式选择 `mock`。 +- 虎牙二维码登录有效期 `5` 分钟;登录成功后的 Connector 内存会话有效期 `24` 小时, + 账号级 CK 由加密凭证保存并通过健康检查判定有效性;角色绑定二维码 `5` 分钟; + 浏览器一次性注入票据 `2` 分钟且消费后立即失效。重新登录前必须撤销旧 Connector 会话。 +- 虎牙账号已经绑定游戏角色时,客户必须确认当前角色是否为本次需要的角色:选择“使用当前角色”时 + 不再调用虎牙换绑接口;选择“角色不对,重新扫码换绑”时重新生成绑定二维码,并在确认新角色时 + 调用换绑接口。未绑定账号和角色时直接走确认绑定。换绑冷却、未到可换绑时间等上游业务拒绝必须原样提示客户。 +- 浏览器扩展复用 live-hub-py 的 `web/extension/huya-exchange-helper`,不新增第二个扩展; + 扩展只允许消费一次性注入票据,页面不得直接读取 CK。 +- 客服完成半自动任务必须与 `confirmManualFulfillment` 在同一数据库事务中提交: + 成本快照、钱包扣减、履约状态和 `semi_auto_tasks` 完成状态必须全部成功或全部回滚; + 事务提交后才执行报表刷新、Connector 会话撤销等旁路动作。 +- 后台“任务 → 半自动履约”列表读取前必须执行幂等任务回填,不能依赖客户先打开 `/c/<订单号>`。 +- 完成截图可选;操作人、操作时间、外部单号和成本确认必须留痕。 +- 客户统一入口为 `/c/<平台订单号>`,它是入口而非安全授权凭据;高价值或全自动场景必须增加二次验证,不能仅凭订单号自动履约。 + ### 3.5 商品与财务域 标准商品目标结构: @@ -320,6 +370,8 @@ finance_journal_* -- 总账凭证,可重建 | 当前履约状态 | 履约状态服务 | `fulfillments` | 多服务直接更新订单项 | | 执行尝试 | 履约尝试服务 | `fulfillment_attempts` | 用最大 ID 猜当前任务 | | 当前异常 | 履约异常服务 | `fulfillment_issues` | 自由 JSON 字符串代替问题模型 | +| 半自动任务 | 半自动任务服务 | `semi_auto_tasks` / `semi_auto_task_events` | 把登录/绑定/执行状态写进 `material_json` | +| 客户平台 CK | 半自动凭证服务 | `semi_auto_credentials` 加密凭证 | 明文落库、写日志、普通接口返回或未审计导出 CK | | 标准商品 | 商品主数据服务 | `product_catalog` | 用商品来源反推渠道 | | 平台商品到财务商品 | 商品归一服务 | `channel_product_mappings` | 人工在多个页面重复维护 | | 成本规则 | 成本中心 | `cost_versions` | 业务表直接改金额 | @@ -476,6 +528,24 @@ current_status has_active_cost ``` +### 7.1 半自动履约入口 + +管理后台“任务 → 半自动履约”读取 `semi_auto_tasks`,平台作为扩展维度: + +```text +全部 / 虎牙 / 微博 / ... +``` + +客户页 `/c/<平台订单号>` 统一展示: + +```text +平台登录 → 角色绑定 → 客服处理 → 完成 +``` + +页面只能展示客户完成操作所需的最小信息,不得展示 CK、内部成本或其他订单。后台默认只展示平台 UID、 +绑定角色、凭证来源、健康状态、更新时间和一次性注入入口;持有独立导出权限的角色可按任务受控查看 +账号 CK,导出动作必须留审计且不得复用普通详情接口。 + ## 八、存量数据处理方案 ### 8.1 已被其他渠道接管的 `man:` 商品 @@ -878,14 +948,19 @@ docs/archive/ ## 十三、当前下一步 -本地阶段 0–6 已按硬切方案完成,生产仍停留在迁移 `146`。后续顺序固定为: +截至 2026-11-13,生产基线为 `151`,本地开发基线为 `156`。迁移 `152` 保护订单来源快照, +迁移 `153` 增加人工渠道半自动任务,迁移 `154` 增加半自动任务的 Connector 来源, +迁移 `155` 将内置真实 Connector 设为默认并扩充来源约束,迁移 `156` 增加账号级加密凭证、 +任务凭证引用和受控导出权限。 1. 生产升级只按 [生产升级操作手册](生产升级操作手册.md) 执行。 2. 升级前备份必须完成隔离恢复验证;恢复验证未通过时禁止迁移。 -3. `147 → 150` 作为同一硬切迁移组执行,迁移后刷新统计并完成商品、履约、 +3. `147 → 153` 按生产升级手册分批执行,迁移后刷新统计并完成商品、履约、 财务三组严格审计;无法确定的数据进入未路由或待分类,不做猜测。 4. 执行 `finance:rebuild-derived` 的 dry-run,核对 A 级数据守恒后, 再按窗口执行 `--execute --confirm=REBUILD_DERIVED`,并验证第二次重建幂等。 5. 观察一个完整财务期间,确认页面、履约、事实和总账持续对平。 -6. 观察期结束后,再单独发布兼容表、旧脚本别名和 `legacy_*` 字段的删除迁移。 +6. 半自动履约继续完善微博手机号登录、易盾二次验证、完整域名 Cookie 保存、会话恢复和受控导出; + 所有平台继续复用账号级凭证模型,不把平台专用 CK 状态写回订单或商品字段。 +7. 观察期结束后,再单独发布兼容表、旧脚本别名和 `legacy_*` 字段的删除迁移。 diff --git a/docs/部署启动与数据库重建.md b/docs/部署启动与数据库重建.md index 00aa13ba..7fed6988 100644 --- a/docs/部署启动与数据库重建.md +++ b/docs/部署启动与数据库重建.md @@ -152,6 +152,7 @@ CLAIM_BASE_URL POSTGRES_PASSWORD DATABASE_URL ADMIN_SESSION_SECRET +SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY ADMIN_DEFAULT_USERS_JSON CORS_ALLOWED_ORIGINS STORAGE_MODE @@ -164,6 +165,10 @@ STORAGE_OSS_REGION 其中 `APP_DOMAIN`、`CORS_ALLOWED_ORIGINS` 与 `STORAGE_MODE=oss` / `STORAGE_OSS_*` 为生产必需:`docker-compose.yml:95` 的 `STORAGE_MODE` 生产默认即 `oss`,`apps/backend/src/config/runtime-validation.ts:107-114` 在生产环境强制校验 `STORAGE_OSS_*` 凭据并使用显式 CORS 域名白名单;`.env.server.example` 已给出这些变量的模板值,其中带 `change-me` 的占位会被 `deploy/ubuntu-deploy.sh` 的占位值检查拦住,需替换为真实值。 +`SEMI_AUTO_CREDENTIAL_ENCRYPTION_KEY` 用于加密半自动履约的账号级平台 CK,生产必需且至少 32 个字符。 +该密钥必须长期稳定保存;直接更换会导致已有 `semi_auto_credentials` 无法解密。需要轮换时,先实现并验证 +旧密钥解密、新密钥重加密的数据迁移,不能只修改环境变量。 + 容器内连接 Compose PostgreSQL 时,主机名用 `postgres`: ```text @@ -219,7 +224,7 @@ docker compose ps docker compose logs -f backend ``` -## 财务/成本上线后的初始化(当前开发基线 150) +## 财务/成本上线后的初始化(历史基线 150) 代码与迁移只负责建表;**存量订单回填、备用金账户、积分余额、商品目录、人工 SKU 不会自动创建**。 部署成功后按「回填 → 商品初始化 → 财务同步 → 验收」四步走: