@redonvn/zalo-ads-sdk 0.2.20 → 0.2.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/store.ts","../src/auth.ts","../src/client.ts","../src/validators/audiences.validator.ts","../src/dtos/ads.dto.ts","../src/validators/campaigns.validator.ts","../src/services/campaigns.service.ts","../src/services/account.service.ts","../src/services/audiences.service.ts","../src/services/reports.service.ts","../src/services/conversions.service.ts","../src/services/automated-rules.service.ts","../src/validators/flows.validator.ts","../src/services/flows.service.ts","../src/services/media.service.ts","../src/services/ads.service.ts","../src/services/chat-widget.service.ts","../src/validators/forms.validator.ts","../src/services/forms.service.ts","../src/validators/instant-pages.validator.ts","../src/services/instant-pages.service.ts","../src/services/profile-ads.service.ts","../src/services/widget.service.ts","../src/sdk.ts","../src/manager.ts","../src/dtos/instant-pages.dto.ts","../src/helpers/instant-page-factory.ts","../src/validators/automated-rules.validator.ts","../src/validators/conversions.validator.ts","../src/validators/profile-ads.validator.ts","../src/validators/reports.validator.ts","../src/validators/media.validator.ts"],"sourcesContent":["import type { ZaloAuthManager, ZaloSsoAuthOptions } from \"./auth\";\nimport type { ZaloRedisLikeClient, ZaloSessionStore } from \"./store\";\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport type FileInput = string | Blob | ArrayBuffer | Uint8Array;\n\nexport interface ZaloSdkAuthContext {\n readonly url: string;\n readonly host: string;\n readonly operationId: string;\n readonly method: HttpMethod;\n}\n\nexport interface ZaloSdkAuth {\n headers?: Record<string, string>;\n cookies?: Record<string, string>;\n getHeaders?: (context: ZaloSdkAuthContext) => Promise<Record<string, string> | undefined> | Record<string, string> | undefined;\n getCookies?: (context: ZaloSdkAuthContext) => Promise<Record<string, string> | undefined> | Record<string, string> | undefined;\n}\n\nexport interface ZaloAccountScope {\n accountId?: string | number;\n memberId?: string | number;\n agencyId?: string | number;\n accountType?: 'PERSONAL' | 'ACCESSOR' | 'AGENCY' | 'AGENCY_MASTER' | 'AGENCY_SUB_ACCOUNT' | string;\n isRoot?: boolean;\n}\n\nexport interface ZaloAdsSdkOptions {\n /**\n * Phạm vi tài khoản quảng cáo cô lập (Isolated Workspace) - chứa accountId, memberId, agencyId, accountType.\n * Dùng để tự động gài tham số báo cáo (agencyId, createdBy) và cô lập phiên (ads_user_id, PLAY_SESSION).\n */\n accountScope?: ZaloAccountScope;\n /**\n * Định danh Integration (`integrationId`) hoặc `accountKey` để cô lập phiên khi quản lý nhiều tài khoản trên RAM/Redis.\n * Nếu không truyền, SDK tự động tạo `accountKey` duy nhất từ `zpsid`.\n */\n integrationId?: string;\n /**\n * Alias của `integrationId` để định danh tài khoản trong `ZaloSessionStore`.\n */\n accountKey?: string;\n /**\n * Giá trị cookie `zpsid` gốc của Zalo (hoặc nguyên chuỗi Cookie trình duyệt có chứa `zpsid=...`).\n * Khi truyền `zpsid`, SDK sẽ tự động khởi tạo `ZaloAuthManager` để thực hiện Silent OAuth2 PKCE SSO\n * lấy `PLAY_SESSION`, `XSRF-TOKEN`, `zf_id` và `Authorization` token cho từng domain.\n */\n zpsid?: string;\n /**\n * Cookie phụ `zoaw_sek` (tùy chọn, dùng cho các API thuộc `api.widget.zalo.me` / `widget.chat.zalo.me`).\n */\n zoawSek?: string;\n /**\n * Tầng lưu trữ phiên (RAM `MemoryZaloSessionStore`, Redis `RedisZaloSessionStore`, hoặc 2 tầng `TieredZaloSessionStore`).\n * Nếu không truyền `sessionStore` và `redis`, mặc định dùng `defaultSharedMemorySessionStore` (RAM LRU).\n */\n sessionStore?: ZaloSessionStore;\n /**\n * Truyền trực tiếp `RedisService` (của `redai-v201-be-app-staging`) hoặc `ioredis` client\n * để tự động bật lưu trữ 2 tầng (L1 RAM + L2 Redis + Distributed Lock).\n */\n redis?: ZaloRedisLikeClient;\n /**\n * Tiền tố key trên Redis khi sử dụng tùy chọn `redis` (mặc định: `'zalo_ads:sso'`).\n */\n redisKeyPrefix?: string;\n /**\n * Cấu hình nâng cao cho cơ chế tự động xác thực SSO qua `zpsid`.\n */\n ssoAuth?: ZaloSsoAuthOptions;\n /**\n * Instance `ZaloAuthManager` truyền từ ngoài vào (nếu muốn dùng chung giữa nhiều instance SDK).\n */\n authManager?: ZaloAuthManager;\n /**\n * Tự động handshake lại và retry 1 lần khi gặp lỗi 401 Unauthorized (mặc định: `true`).\n */\n autoRetryOn401?: boolean;\n auth?: ZaloSdkAuth;\n authByHost?: Record<string, ZaloSdkAuth>;\n fetch?: typeof fetch;\n baseUrls?: Partial<Record<\"ads\" | \"forms\" | \"instantPages\" | \"profileAds\" | \"widget\" | \"chatWidget\", string>>;\n}\n\nexport interface RequestOptions {\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport class ZaloSdkError extends Error {\n public readonly status: number;\n public readonly operationId: string;\n public readonly responseBody: unknown;\n\n constructor(message: string, status = 500, operationId = \"unknown\", responseBody: unknown = null) {\n super(message);\n this.name = \"ZaloSdkError\";\n this.status = status;\n this.operationId = operationId;\n this.responseBody = responseBody;\n }\n}\n\nexport interface FileDownloadResponse {\n file: Blob;\n filename?: string;\n contentType: string | null;\n}\n","import type { ZaloAdsDomain, ZaloDomainSession } from './auth';\n\n/**\n * Interface tương thích với cả:\n * 1. `RedisService` của `redai-v201-be-app-staging` (`get`, `setWithExpiry`, `set`, `del`, `setNX`)\n * 2. `ioredis` / `node-redis` client tiêu chuẩn (`get`, `setex` / `set`, `del`)\n */\nexport interface ZaloRedisLikeClient {\n get(key: string): Promise<string | null>;\n del(key: string | string[]): Promise< unknown>;\n /** Method của NestJS RedisService trong redai-v201-be-app-staging */\n setWithExpiry?(key: string, value: string, expiryInSeconds: number): Promise<unknown>;\n /** Method của NestJS RedisService trong redai-v201-be-app-staging */\n setNX?(key: string, value: string, expiryInSeconds: number): Promise<boolean>;\n /** Method của ioredis */\n setex?(key: string, seconds: number, value: string): Promise<unknown>;\n /** Method cơ bản của RedisService / ioredis / node-redis */\n set?(key: string, value: string, ...args: unknown[]): Promise<unknown>;\n}\n\n/**\n * Interface chuẩn cho tầng lưu trữ Session Zalo Ads (RAM / Redis / Custom DB).\n * Hỗ trợ đa tài khoản (multi-account / multi-integration) thông qua `accountKey`.\n */\nexport interface ZaloSessionStore {\n /** Lấy phiên của 1 domain thuộc 1 tài khoản/integration */\n get(accountKey: string, domain: ZaloAdsDomain): Promise<ZaloDomainSession | null> | ZaloDomainSession | null;\n\n /** Lưu phiên của 1 domain thuộc 1 tài khoản/integration */\n set(accountKey: string, domain: ZaloAdsDomain, session: ZaloDomainSession, ttlSeconds?: number): Promise<void> | void;\n\n /** Xóa phiên của 1 domain hoặc toàn bộ domain thuộc 1 tài khoản/integration */\n delete(accountKey: string, domain?: ZaloAdsDomain): Promise<void> | void;\n\n /** Lấy toàn bộ phiên các domain của 1 tài khoản/integration */\n getAll?(accountKey: string): Promise<Partial<Record<ZaloAdsDomain, ZaloDomainSession>>> | Partial<Record<ZaloAdsDomain, ZaloDomainSession>>;\n\n /**\n * Distributed lock (tùy chọn, dùng cho Redis multi-instance/cluster)\n * Trả về true nếu chiếm được lock, false nếu tiến trình khác đang giữ lock.\n */\n acquireLock?(accountKey: string, domain: ZaloAdsDomain, ttlSeconds: number): Promise<boolean>;\n\n /** Giải phóng distributed lock */\n releaseLock?(accountKey: string, domain: ZaloAdsDomain): Promise<void>;\n}\n\nexport const ALL_ZALO_ADS_DOMAINS: readonly ZaloAdsDomain[] = [\n 'ads.zalo.me',\n 'page.ads.zalo.me',\n 'form.ads.zalo.me',\n 'profile.ads.zalo.me',\n 'api.widget.zalo.me',\n 'widget.chat.zalo.me',\n];\n\nexport interface MemoryZaloSessionStoreOptions {\n /**\n * Số lượng tài khoản/integration tối đa giữ trong RAM (LRU eviction).\n * Mặc định: 500 tài khoản.\n */\n maxAccounts?: number;\n}\n\n/**\n * Lưu trữ Session trong RAM (L1 Cache) có cơ chế LRU chống tràn bộ nhớ khi quản lý nhiều Integration.\n */\nexport class MemoryZaloSessionStore implements ZaloSessionStore {\n private readonly store = new Map<string, Map<ZaloAdsDomain, ZaloDomainSession>>();\n private readonly maxAccounts: number;\n\n public constructor(options: MemoryZaloSessionStoreOptions = {}) {\n this.maxAccounts = options.maxAccounts ?? 500;\n }\n\n public get(accountKey: string, domain: ZaloAdsDomain): ZaloDomainSession | null {\n const accountMap = this.store.get(accountKey);\n if (!accountMap) return null;\n\n // Cập nhật thứ tự LRU\n this.store.delete(accountKey);\n this.store.set(accountKey, accountMap);\n\n const session = accountMap.get(domain);\n if (!session) return null;\n\n if (Date.now() >= session.expiresAt) {\n accountMap.delete(domain);\n return null;\n }\n\n return session;\n }\n\n public set(\n accountKey: string,\n domain: ZaloAdsDomain,\n session: ZaloDomainSession,\n ttlSeconds?: number,\n ): void {\n let accountMap = this.store.get(accountKey);\n if (accountMap) {\n this.store.delete(accountKey);\n } else {\n if (this.store.size >= this.maxAccounts) {\n const oldestKey = this.store.keys().next().value;\n if (oldestKey !== undefined) {\n this.store.delete(oldestKey);\n }\n }\n accountMap = new Map<ZaloAdsDomain, ZaloDomainSession>();\n }\n\n const storedSession: ZaloDomainSession = ttlSeconds\n ? { ...session, expiresAt: Math.min(session.expiresAt, Date.now() + ttlSeconds * 1000) }\n : session;\n\n accountMap.set(domain, storedSession);\n this.store.set(accountKey, accountMap);\n }\n\n public delete(accountKey: string, domain?: ZaloAdsDomain): void {\n if (!domain) {\n this.store.delete(accountKey);\n return;\n }\n const accountMap = this.store.get(accountKey);\n if (accountMap) {\n accountMap.delete(domain);\n if (accountMap.size === 0) {\n this.store.delete(accountKey);\n }\n }\n }\n\n public getAll(accountKey: string): Partial<Record<ZaloAdsDomain, ZaloDomainSession>> {\n const accountMap = this.store.get(accountKey);\n if (!accountMap) return {};\n const now = Date.now();\n const result: Partial<Record<ZaloAdsDomain, ZaloDomainSession>> = {};\n for (const [domain, session] of accountMap.entries()) {\n if (now < session.expiresAt) {\n result[domain] = session;\n } else {\n accountMap.delete(domain);\n }\n }\n return result;\n }\n\n /** Xóa toàn bộ dữ liệu trong RAM */\n public clearAll(): void {\n this.store.clear();\n }\n\n /** Số lượng tài khoản đang được giữ trong RAM */\n public get size(): number {\n return this.store.size;\n }\n}\n\nexport interface RedisZaloSessionStoreOptions {\n /**\n * Tiền tố key trên Redis.\n * Mặc định: `'zalo_ads:sso'` -> key có dạng `zalo_ads:sso:session:{accountKey}:{domain}`\n */\n keyPrefix?: string;\n /**\n * Thời gian sống mặc định trên Redis (giây) nếu session không có expiresAt.\n * Mặc định: 2700 giây (45 phút).\n */\n defaultTtlSeconds?: number;\n}\n\n/**\n * Lưu trữ Session trên Redis (L2 Shared Cache) kèm Distributed Lock chống race-condition\n * khi nhiều worker/instance backend cùng refresh 1 tài khoản/integration.\n *\n * Tương thích trực tiếp với `RedisService` của `redai-v201-be-app-staging` hoặc `ioredis`.\n */\nexport class RedisZaloSessionStore implements ZaloSessionStore {\n private readonly keyPrefix: string;\n private readonly defaultTtlSeconds: number;\n\n public constructor(\n private readonly redis: ZaloRedisLikeClient,\n options: RedisZaloSessionStoreOptions = {},\n ) {\n this.keyPrefix = options.keyPrefix ?? 'zalo_ads:sso';\n this.defaultTtlSeconds = options.defaultTtlSeconds ?? 45 * 60;\n }\n\n private buildSessionKey(accountKey: string, domain: ZaloAdsDomain): string {\n return `${this.keyPrefix}:session:${accountKey}:${domain}`;\n }\n\n private buildLockKey(accountKey: string, domain: ZaloAdsDomain): string {\n return `${this.keyPrefix}:lock:${accountKey}:${domain}`;\n }\n\n public async get(accountKey: string, domain: ZaloAdsDomain): Promise<ZaloDomainSession | null> {\n const key = this.buildSessionKey(accountKey, domain);\n const raw = await this.redis.get(key);\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw) as ZaloDomainSession;\n if (!parsed || typeof parsed !== 'object' || Date.now() >= parsed.expiresAt) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n }\n\n public async set(\n accountKey: string,\n domain: ZaloAdsDomain,\n session: ZaloDomainSession,\n ttlSeconds?: number,\n ): Promise<void> {\n const key = this.buildSessionKey(accountKey, domain);\n const remainingSeconds = Math.floor((session.expiresAt - Date.now()) / 1000);\n const effectiveTtl = Math.max(1, ttlSeconds ?? (remainingSeconds > 0 ? remainingSeconds : this.defaultTtlSeconds));\n const serialized = JSON.stringify(session);\n\n if (typeof this.redis.setWithExpiry === 'function') {\n await this.redis.setWithExpiry(key, serialized, effectiveTtl);\n return;\n }\n if (typeof this.redis.setex === 'function') {\n await this.redis.setex(key, effectiveTtl, serialized);\n return;\n }\n if (typeof this.redis.set === 'function') {\n await this.redis.set(key, serialized, 'EX', effectiveTtl);\n }\n }\n\n public async delete(accountKey: string, domain?: ZaloAdsDomain): Promise<void> {\n if (domain) {\n await this.redis.del(this.buildSessionKey(accountKey, domain));\n return;\n }\n const keys = ALL_ZALO_ADS_DOMAINS.map(d => this.buildSessionKey(accountKey, d));\n await Promise.all(keys.map(k => this.redis.del(k)));\n }\n\n public async getAll(accountKey: string): Promise<Partial<Record<ZaloAdsDomain, ZaloDomainSession>>> {\n const entries = await Promise.all(\n ALL_ZALO_ADS_DOMAINS.map(async domain => {\n const session = await this.get(accountKey, domain);\n return [domain, session] as const;\n }),\n );\n const result: Partial<Record<ZaloAdsDomain, ZaloDomainSession>> = {};\n for (const [domain, session] of entries) {\n if (session) {\n result[domain] = session;\n }\n }\n return result;\n }\n\n public async acquireLock(\n accountKey: string,\n domain: ZaloAdsDomain,\n ttlSeconds = 15,\n ): Promise<boolean> {\n const lockKey = this.buildLockKey(accountKey, domain);\n const lockValue = `${Date.now()}`;\n if (typeof this.redis.setNX === 'function') {\n return Boolean(await this.redis.setNX(lockKey, lockValue, ttlSeconds));\n }\n if (typeof this.redis.set === 'function') {\n const res = await this.redis.set(lockKey, lockValue, 'EX', ttlSeconds, 'NX');\n return res === 'OK' || res === true;\n }\n return true;\n }\n\n public async releaseLock(accountKey: string, domain: ZaloAdsDomain): Promise<void> {\n const lockKey = this.buildLockKey(accountKey, domain);\n try {\n await this.redis.del(lockKey);\n } catch {\n // Ignore lock release errors\n }\n }\n}\n\nexport interface TieredZaloSessionStoreOptions extends MemoryZaloSessionStoreOptions, RedisZaloSessionStoreOptions {\n /**\n * Thời gian sống tối đa của L1 RAM cache (giây) trước khi đồng bộ lại với L2 Redis.\n * Mặc định: 300 giây (5 phút) để đảm bảo các worker luôn đồng bộ nếu 1 worker khác refresh session.\n */\n l1MaxTtlSeconds?: number;\n}\n\n/**\n * Lưu trữ 2 tầng (L1 RAM + L2 Redis):\n * - Đọc cực nhanh từ RAM (0ms) cho các request liên tiếp trong cùng process.\n * - Tự động đồng bộ xuống Redis để chia sẻ phiên giữa nhiều worker/pod và giữ phiên khi restart server.\n * - Hỗ trợ Distributed Lock qua Redis khi thực hiện OAuth Handshake.\n */\nexport class TieredZaloSessionStore implements ZaloSessionStore {\n public readonly l1Memory: MemoryZaloSessionStore;\n public readonly l2Redis: RedisZaloSessionStore;\n private readonly l1MaxTtlSeconds: number;\n\n public constructor(\n redis: ZaloRedisLikeClient,\n options: TieredZaloSessionStoreOptions = {},\n ) {\n this.l1Memory = new MemoryZaloSessionStore({ maxAccounts: options.maxAccounts });\n this.l2Redis = new RedisZaloSessionStore(redis, {\n keyPrefix: options.keyPrefix,\n defaultTtlSeconds: options.defaultTtlSeconds,\n });\n this.l1MaxTtlSeconds = options.l1MaxTtlSeconds ?? 300;\n }\n\n public async get(accountKey: string, domain: ZaloAdsDomain): Promise<ZaloDomainSession | null> {\n const fromL1 = this.l1Memory.get(accountKey, domain);\n if (fromL1) {\n return fromL1;\n }\n\n const fromL2 = await this.l2Redis.get(accountKey, domain);\n if (fromL2) {\n this.l1Memory.set(accountKey, domain, fromL2, this.l1MaxTtlSeconds);\n return fromL2;\n }\n\n return null;\n }\n\n public async set(\n accountKey: string,\n domain: ZaloAdsDomain,\n session: ZaloDomainSession,\n ttlSeconds?: number,\n ): Promise<void> {\n this.l1Memory.set(accountKey, domain, session, ttlSeconds ?? this.l1MaxTtlSeconds);\n await this.l2Redis.set(accountKey, domain, session, ttlSeconds);\n }\n\n public async delete(accountKey: string, domain?: ZaloAdsDomain): Promise<void> {\n this.l1Memory.delete(accountKey, domain);\n await this.l2Redis.delete(accountKey, domain);\n }\n\n public async getAll(accountKey: string): Promise<Partial<Record<ZaloAdsDomain, ZaloDomainSession>>> {\n const fromL2 = await this.l2Redis.getAll(accountKey);\n for (const [domain, session] of Object.entries(fromL2) as [ZaloAdsDomain, ZaloDomainSession][]) {\n if (session) {\n this.l1Memory.set(accountKey, domain, session, this.l1MaxTtlSeconds);\n }\n }\n return fromL2;\n }\n\n public acquireLock(accountKey: string, domain: ZaloAdsDomain, ttlSeconds = 15): Promise<boolean> {\n return this.l2Redis.acquireLock(accountKey, domain, ttlSeconds);\n }\n\n public releaseLock(accountKey: string, domain: ZaloAdsDomain): Promise<void> {\n return this.l2Redis.releaseLock(accountKey, domain);\n }\n}\n\n/**\n * Default global L1 Memory store dùng chung trong cùng Node.js process.\n * Giúp ngay cả khi khởi tạo `new ZaloAdsSdk({ zpsid })` nhiều lần ở các request khác nhau\n * vẫn tự động tái sử dụng được session trong RAM theo đúng tài khoản (`accountKey`).\n */\nexport const defaultSharedMemorySessionStore = new MemoryZaloSessionStore({\n maxAccounts: 1000,\n});\n","import {\n defaultSharedMemorySessionStore,\n TieredZaloSessionStore,\n type ZaloRedisLikeClient,\n type ZaloSessionStore,\n} from \"./store\";\nimport type { ZaloAccountScope, ZaloSdkAuth, ZaloSdkAuthContext } from \"./types\";\n\nexport type ZaloAuthDomain =\n | \"ads.zalo.me\"\n | \"page.ads.zalo.me\"\n | \"form.ads.zalo.me\"\n | \"profile.ads.zalo.me\"\n | \"api.widget.zalo.me\"\n | \"widget.chat.zalo.me\";\n\nexport type ZaloAdsDomain = ZaloAuthDomain;\n\nexport interface ZaloPlaySessionPayload {\n data?: {\n /** Ads Member ID (trên ads.zalo.me) */\n id?: string;\n /** Role trên ads.zalo.me (ví dụ: \"2\") */\n role?: string;\n /** Root account ID trên ads.zalo.me */\n root?: string;\n /** Instant Page User ID / Owner ID (trên page.ads.zalo.me) */\n nid?: string;\n /** Session ID */\n sid?: string;\n /** Zalo SSO Ticket */\n zpsid?: string;\n [key: string]: unknown;\n };\n nbf?: number;\n iat?: number;\n exp?: number;\n [key: string]: unknown;\n}\n\nexport interface ZaloAdsWhoamiProfile {\n id: number;\n name: string;\n avatar?: string;\n budget?: number;\n role?: string;\n phone?: string;\n sid?: string;\n [key: string]: unknown;\n}\n\nexport interface ZaloFormSessionProfile {\n uid: string;\n fullName: string;\n avatar?: string;\n token: string;\n isInVN?: boolean;\n oas?: Array<{\n oaId: string;\n noisedOaId: string;\n name: string;\n oaAvatar?: string;\n status: number;\n role: number;\n [key: string]: unknown;\n }>;\n [key: string]: unknown;\n}\n\nexport interface ZaloDomainSession {\n domain: ZaloAuthDomain;\n /** Định danh tài khoản hoặc Integration ID sở hữu phiên này */\n accountKey?: string;\n /** Fingerprint của zpsid đã tạo ra phiên này (dùng để tự động phát hiện khi người dùng đổi zpsid mới) */\n zpsidFingerprint?: string;\n cookies: Record<string, string>;\n xsrfToken?: string;\n bearerToken?: string;\n headers: Record<string, string>;\n playSessionPayload?: ZaloPlaySessionPayload;\n adsProfile?: ZaloAdsWhoamiProfile;\n formProfile?: ZaloFormSessionProfile;\n createdAt: number;\n expiresAt: number;\n}\n\nexport interface ZaloSsoAuthOptions {\n /**\n * Định danh tài khoản hoặc `integrationId` (dùng để phân tách cache RAM/Redis khi quản lý nhiều tài khoản).\n * Nếu không truyền, SDK tự động trích xuất từ `zpsid` (ví dụ: `zalo_330114198_...`).\n */\n accountKey?: string;\n /**\n * Phạm vi tài khoản quảng cáo cô lập (Isolated Workspace) - chứa accountId, memberId, agencyId, accountType.\n */\n accountScope?: ZaloAccountScope;\n /**\n * Alias của `accountKey` dành cho hệ thống Multi-Integration trên Backend.\n */\n integrationId?: string;\n /**\n * Giá trị cookie `zpsid` gốc của Zalo (domain `.zalo.me`) hoặc nguyên chuỗi Cookie trình duyệt có chứa `zpsid=...`.\n */\n zpsid?: string;\n /**\n * Callback động để lấy `zpsid` (hữu ích khi đọc từ DB/Redis/Vault theo `integrationId`).\n */\n getZpsid?: () => Promise<string> | string;\n /**\n * Các cookie bổ sung muốn gắn kèm (ví dụ: `zoaw_sek`, `zoaw_type` cho chat widget).\n */\n extraCookies?: Record<string, string>;\n /**\n * Thời gian sống (TTL) của phiên cache cho mỗi domain tính bằng mili-giây (mặc định: 45 phút).\n */\n sessionTtlMs?: number;\n /**\n * Tầng lưu trữ phiên (RAM / Redis / Tiered).\n * Nếu không truyền `sessionStore` và `redis`, mặc định dùng `defaultSharedMemorySessionStore` (RAM LRU).\n */\n sessionStore?: ZaloSessionStore;\n /**\n * Truyền trực tiếp `RedisService` (của NestJS backend) hoặc `ioredis` client để tự động bật cache 2 tầng (L1 RAM + L2 Redis + Distributed Lock).\n */\n redis?: ZaloRedisLikeClient;\n /**\n * Tiền tố key trên Redis khi truyền `redis` (mặc định: `'zalo_ads:sso'`).\n */\n redisKeyPrefix?: string;\n /**\n * Custom fetch implementation (mặc định: `globalThis.fetch`).\n */\n fetch?: typeof fetch;\n /**\n * Custom User-Agent header.\n */\n userAgent?: string;\n /**\n * Hook được gọi mỗi khi một domain hoàn tất handshake và sinh session mới.\n */\n onSessionRefreshed?: (domain: ZaloAuthDomain, session: ZaloDomainSession) => Promise<void> | void;\n /**\n * Khôi phục sẵn danh sách phiên đã cache trước đó.\n */\n initialSessions?: Partial<Record<ZaloAuthDomain, ZaloDomainSession>>;\n}\n\nconst DEFAULT_USER_AGENT =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36\";\n\nconst DEFAULT_SESSION_TTL_MS = 45 * 60 * 1000; // 45 minutes\n\n/**\n * Tạo mã băm ngắn (FNV-1a 32-bit hex) để làm fingerprint cho `zpsid` mà không lưu lộ nguyên chuỗi `zpsid` trên key Redis.\n */\nexport function computeZpsidFingerprint(zpsid: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < zpsid.length; i++) {\n hash ^= zpsid.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Tự động trích xuất `accountKey` duy nhất từ `zpsid` (kết hợp Zalo User ID nằm ở phần tử thứ 2 của `zpsid` và mã băm).\n * Ví dụ: `g_kQ.330114198.434.Tme...` -> `zalo_330114198_7f4c9a12`\n */\nexport function deriveAccountKeyFromZpsid(zpsid: string): string {\n const parts = zpsid.trim().split(\".\");\n const uidCandidate = parts.length >= 2 && /^\\d+$/.test(parts[1]) ? parts[1] : \"user\";\n return `zalo_${uidCandidate}_${computeZpsidFingerprint(zpsid.trim())}`;\n}\n\n/**\n * Giải mã payload JWT của cookie `PLAY_SESSION` (không cần secret key) để đọc `id`, `nid`, `sid`, `iat`.\n */\nexport function decodePlaySessionJwt(playSessionCookie: string): ZaloPlaySessionPayload | undefined {\n try {\n const token = playSessionCookie.replace(/^PLAY_SESSION=/, \"\").trim();\n const parts = token.split(\".\");\n if (parts.length < 2) return undefined;\n const base64Url = parts[1];\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\");\n const binaryStr = globalThis.atob(padded);\n const bytes = Uint8Array.from(binaryStr, (ch) => ch.charCodeAt(0));\n const jsonStr = new TextDecoder(\"utf-8\").decode(bytes);\n return JSON.parse(jsonStr) as ZaloPlaySessionPayload;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Trích xuất `zpsid` và các cookie phụ từ một chuỗi Cookie đầy đủ hoặc giá trị `zpsid` đơn lẻ.\n */\nexport function parseZaloCookieInput(rawInput: string): {\n zpsid: string;\n extractedCookies: Record<string, string>;\n} {\n const trimmed = rawInput.trim();\n const extractedCookies: Record<string, string> = {};\n\n if (!trimmed.includes(\"=\") && !trimmed.includes(\";\")) {\n return { zpsid: trimmed, extractedCookies };\n }\n\n for (const part of trimmed.split(\";\")) {\n const eqIdx = part.indexOf(\"=\");\n if (eqIdx > 0) {\n const k = part.slice(0, eqIdx).trim();\n const v = part.slice(eqIdx + 1).trim();\n if (k && v) extractedCookies[k] = v;\n }\n }\n\n const zpsid = extractedCookies[\"zpsid\"] ?? trimmed.replace(/^zpsid=/i, \"\").trim();\n return { zpsid, extractedCookies };\n}\n\n/**\n * Trình quản lý xác thực tập trung cho hệ sinh thái Zalo Ads (`ads.zalo.me`, `page.ads.zalo.me`,\n * `form.ads.zalo.me`, `profile.ads.zalo.me`, `api.widget.zalo.me`, `widget.chat.zalo.me`).\n *\n * Hỗ trợ lưu trữ phiên trên RAM (`MemoryZaloSessionStore`), Redis (`RedisZaloSessionStore`),\n * hoặc kết hợp 2 tầng L1 RAM + L2 Redis (`TieredZaloSessionStore`) cho mô hình Multi-Account / Multi-Integration.\n */\nexport class ZaloAuthManager {\n private explicitAccountKey?: string;\n private accountScope?: ZaloAccountScope;\n private zpsid?: string;\n private readonly getZpsidFn?: () => Promise<string> | string;\n private extraCookies: Record<string, string>;\n private readonly sessionTtlMs: number;\n private readonly sessionStore: ZaloSessionStore;\n private readonly fetchImpl: typeof fetch;\n private readonly userAgent: string;\n private readonly onSessionRefreshed?: (\n domain: ZaloAuthDomain,\n session: ZaloDomainSession\n ) => Promise<void> | void;\n\n private readonly sessions = new Map<ZaloAuthDomain, ZaloDomainSession>();\n private readonly inflightHandshakes = new Map<ZaloAuthDomain, Promise<ZaloDomainSession>>();\n\n public constructor(options: ZaloSsoAuthOptions | string) {\n const normalizedOptions: ZaloSsoAuthOptions =\n typeof options === \"string\" ? { zpsid: options } : options;\n\n this.fetchImpl = normalizedOptions.fetch ?? globalThis.fetch;\n if (!this.fetchImpl) {\n throw new Error(\"A Fetch implementation is required (Node.js 18+ provides global fetch).\");\n }\n\n this.explicitAccountKey = normalizedOptions.integrationId ?? normalizedOptions.accountKey;\n this.accountScope = normalizedOptions.accountScope;\n this.extraCookies = { ...(normalizedOptions.extraCookies ?? {}) };\n\n if (normalizedOptions.zpsid) {\n const parsed = parseZaloCookieInput(normalizedOptions.zpsid);\n this.zpsid = parsed.zpsid;\n for (const flagKey of [\"zoaw_sek\", \"zoaw_type\", \"__zi\", \"__zi-legacy\"]) {\n if (parsed.extractedCookies[flagKey] && !this.extraCookies[flagKey]) {\n this.extraCookies[flagKey] = parsed.extractedCookies[flagKey];\n }\n }\n }\n\n this.getZpsidFn = normalizedOptions.getZpsid;\n this.sessionTtlMs = normalizedOptions.sessionTtlMs ?? DEFAULT_SESSION_TTL_MS;\n this.userAgent = normalizedOptions.userAgent ?? DEFAULT_USER_AGENT;\n this.onSessionRefreshed = normalizedOptions.onSessionRefreshed;\n\n if (normalizedOptions.sessionStore) {\n this.sessionStore = normalizedOptions.sessionStore;\n } else if (normalizedOptions.redis) {\n this.sessionStore = new TieredZaloSessionStore(normalizedOptions.redis, {\n keyPrefix: normalizedOptions.redisKeyPrefix,\n });\n } else {\n this.sessionStore = defaultSharedMemorySessionStore;\n }\n\n if (normalizedOptions.initialSessions) {\n for (const [domain, session] of Object.entries(normalizedOptions.initialSessions)) {\n if (session) this.sessions.set(domain as ZaloAuthDomain, session);\n }\n }\n }\n\n /**\n * Trả về `accountKey` hiện tại (hoặc `integrationId` nếu được cấu hình).\n */\n public getAccountKey(): string {\n if (this.explicitAccountKey) {\n return this.explicitAccountKey;\n }\n if (this.zpsid) {\n return deriveAccountKeyFromZpsid(this.zpsid);\n }\n return \"zalo_default_account\";\n }\n\n /**\n * Trả về `sessionStore` đang sử dụng (RAM / Redis / Tiered).\n */\n public getSessionStore(): ZaloSessionStore {\n return this.sessionStore;\n }\n\n public getAccountScope(): ZaloAccountScope | undefined {\n return this.accountScope;\n }\n\n public setAccountScope(scope?: ZaloAccountScope): void {\n this.accountScope = scope;\n }\n\n /**\n * Cập nhật `zpsid` mới và xóa toàn bộ cache phiên cũ trên cả RAM lẫn Redis.\n */\n public setZpsid(zpsidInput: string): void {\n const parsed = parseZaloCookieInput(zpsidInput);\n const prevZpsid = this.zpsid;\n this.zpsid = parsed.zpsid;\n for (const flagKey of [\"zoaw_sek\", \"zoaw_type\", \"__zi\", \"__zi-legacy\"]) {\n if (parsed.extractedCookies[flagKey]) {\n this.extraCookies[flagKey] = parsed.extractedCookies[flagKey];\n }\n }\n if (prevZpsid !== this.zpsid) {\n this.clearSessions();\n }\n }\n\n /**\n * Xóa phiên đã cache của một domain cụ thể (trên cả local RAM và `sessionStore` Redis/Memory).\n */\n public invalidateDomain(hostOrDomain: string): void {\n const domain = this.normalizeDomain(hostOrDomain);\n this.sessions.delete(domain);\n const accountKey = this.getAccountKey();\n void Promise.resolve(this.sessionStore.delete(accountKey, domain)).catch(() => undefined);\n }\n\n /**\n * Xóa phiên bất đồng bộ (đảm bảo đã xóa xong trên Redis trước khi thực hiện bước tiếp theo).\n */\n public async invalidateDomainAsync(hostOrDomain: string): Promise<void> {\n const domain = this.normalizeDomain(hostOrDomain);\n this.sessions.delete(domain);\n const accountKey = this.getAccountKey();\n await this.sessionStore.delete(accountKey, domain);\n }\n\n /**\n * Xóa toàn bộ phiên đã cache của mọi domain thuộc tài khoản này.\n */\n public clearSessions(): void {\n this.sessions.clear();\n const accountKey = this.getAccountKey();\n void Promise.resolve(this.sessionStore.delete(accountKey)).catch(() => undefined);\n }\n\n /**\n * Xóa toàn bộ phiên đã cache của mọi domain thuộc tài khoản này (bất đồng bộ, chờ Redis xóa xong).\n */\n public async clearSessionsAsync(): Promise<void> {\n this.sessions.clear();\n const accountKey = this.getAccountKey();\n await this.sessionStore.delete(accountKey);\n }\n\n /**\n * Xuất toàn bộ phiên đang cache để lưu trữ ngoài.\n */\n public exportSessions(): Partial<Record<ZaloAuthDomain, ZaloDomainSession>> {\n const output: Partial<Record<ZaloAuthDomain, ZaloDomainSession>> = {};\n for (const [domain, session] of this.sessions.entries()) {\n output[domain] = session;\n }\n return output;\n }\n\n /**\n * Nạp lại các phiên đã lưu trữ từ bên ngoài.\n */\n public importSessions(snapshot: Partial<Record<ZaloAuthDomain, ZaloDomainSession>>): void {\n const accountKey = this.getAccountKey();\n for (const [domain, session] of Object.entries(snapshot)) {\n if (session) {\n this.sessions.set(domain as ZaloAuthDomain, session);\n void Promise.resolve(\n this.sessionStore.set(accountKey, domain as ZaloAuthDomain, session)\n ).catch(() => undefined);\n }\n }\n }\n\n /**\n * Lấy phiên hợp lệ của một domain (kiểm tra L1 Instance Map -> L1/L2 SessionStore -> tự động chạy OAuth2 PKCE Handshake nếu chưa có hoặc đã hết hạn).\n */\n public async getSession(hostOrDomain: string, forceRefresh = false): Promise<ZaloDomainSession> {\n const domain = this.normalizeDomain(hostOrDomain);\n const zpsid = await this.resolveZpsid();\n const currentFingerprint = computeZpsidFingerprint(zpsid);\n const accountKey = this.getAccountKey();\n\n if (!forceRefresh) {\n const localSession = this.sessions.get(domain);\n if (localSession && this.isSessionValid(localSession, currentFingerprint)) {\n return localSession;\n }\n\n const storedSession = await this.sessionStore.get(accountKey, domain);\n if (storedSession && this.isSessionValid(storedSession, currentFingerprint)) {\n this.sessions.set(domain, storedSession);\n return storedSession;\n }\n }\n\n return this.authenticateDomain(domain, forceRefresh);\n }\n\n /**\n * Thực hiện đồng thời OAuth2 PKCE Handshake cho nhiều domain (mặc định: `ads.zalo.me`, `page.ads.zalo.me`, `form.ads.zalo.me`).\n */\n public async authenticateAll(\n domains: ZaloAuthDomain[] = [\"ads.zalo.me\", \"page.ads.zalo.me\", \"form.ads.zalo.me\"],\n forceRefresh = true\n ): Promise<Record<string, ZaloDomainSession>> {\n const entries = await Promise.all(\n domains.map(async (d) => [d, await this.authenticateDomain(d, forceRefresh)] as const)\n );\n return Object.fromEntries(entries);\n }\n\n /**\n * Thực hiện OAuth2 PKCE Handshake bằng `zpsid` cho một domain cụ thể.\n * Có chống trùng lặp trong cùng process (in-flight deduplication) VÀ giữa nhiều process/pod qua Redis Distributed Lock.\n */\n public async authenticateDomain(\n hostOrDomain: string,\n forceRefresh = false\n ): Promise<ZaloDomainSession> {\n const domain = this.normalizeDomain(hostOrDomain);\n const zpsid = await this.resolveZpsid();\n const currentFingerprint = computeZpsidFingerprint(zpsid);\n const accountKey = this.getAccountKey();\n\n if (!forceRefresh) {\n const existing = this.sessions.get(domain);\n if (existing && this.isSessionValid(existing, currentFingerprint)) {\n return existing;\n }\n const fromStore = await this.sessionStore.get(accountKey, domain);\n if (fromStore && this.isSessionValid(fromStore, currentFingerprint)) {\n this.sessions.set(domain, fromStore);\n return fromStore;\n }\n }\n\n const inflight = this.inflightHandshakes.get(domain);\n if (inflight) return inflight;\n\n const promise = this.performHandshakeWithDistributedLock(\n accountKey,\n domain,\n zpsid,\n currentFingerprint,\n forceRefresh\n ).finally(() => {\n this.inflightHandshakes.delete(domain);\n });\n\n this.inflightHandshakes.set(domain, promise);\n return promise;\n }\n\n /**\n * Lấy bộ HTTP Headers chuẩn (`Cookie`, `x-xsrf-token`, `Authorization`, ...) cho bất kỳ URL hoặc domain Zalo Ads nào.\n */\n public async getAuthHeaders(\n urlOrDomain: string,\n forceRefresh = false\n ): Promise<Record<string, string>> {\n const domain = this.extractDomainFromUrlOrHost(urlOrDomain);\n const session = await this.getSession(domain, forceRefresh);\n return {\n ...session.headers,\n Cookie: this.formatCookieHeader(session.cookies),\n };\n }\n\n /**\n * Lấy bản đồ Cookie (`Record<string, string>`) đã xác thực của domain.\n */\n public async getCookies(\n urlOrDomain: string,\n forceRefresh = false\n ): Promise<Record<string, string>> {\n const domain = this.extractDomainFromUrlOrHost(urlOrDomain);\n const session = await this.getSession(domain, forceRefresh);\n return { ...session.cookies };\n }\n\n /**\n * Chuyển đổi `ZaloAuthManager` thành đối tượng `ZaloSdkAuth` để gắn trực tiếp vào `ZaloSdkHttpClient`.\n */\n public toSdkAuth(): ZaloSdkAuth {\n return {\n getHeaders: async (context: ZaloSdkAuthContext) => {\n const session = await this.getSession(context.host, false);\n return { ...session.headers };\n },\n getCookies: async (context: ZaloSdkAuthContext) => {\n const session = await this.getSession(context.host, false);\n return { ...session.cookies };\n },\n };\n }\n\n /**\n * Hàm `fetch` độc lập có bọc sẵn xác thực tự động và tự retry 1 lần nếu gặp HTTP 401 hoặc `{ code: 401 }`.\n */\n public async request(url: string, init: RequestInit = {}): Promise<Response> {\n const domain = this.extractDomainFromUrlOrHost(url);\n const executeFetch = async (forceRefresh: boolean): Promise<Response> => {\n const authHeaders = await this.getAuthHeaders(domain, forceRefresh);\n const mergedHeaders = new Headers(authHeaders);\n if (init.headers) {\n const customHeaders = new Headers(init.headers);\n customHeaders.forEach((value, key) => mergedHeaders.set(key, value));\n }\n return this.fetchImpl(url, {\n ...init,\n headers: mergedHeaders,\n });\n };\n\n const response = await executeFetch(false);\n if (response.status === 401) {\n await this.invalidateDomainAsync(domain);\n return executeFetch(true);\n }\n\n // Riêng form.ads.zalo.me trả HTTP 200 kèm JSON {\"msg\":\"Unauthorized\",\"code\":401}\n if (domain === \"form.ads.zalo.me\") {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"json\")) {\n const cloned = response.clone();\n const body = (await cloned.json().catch(() => null)) as { code?: number } | null;\n if (body && body.code === 401) {\n await this.invalidateDomainAsync(domain);\n return executeFetch(true);\n }\n }\n }\n\n return response;\n }\n\n private isSessionValid(session: ZaloDomainSession, currentFingerprint: string): boolean {\n if (Date.now() >= session.expiresAt) {\n return false;\n }\n if (session.zpsidFingerprint && session.zpsidFingerprint !== currentFingerprint) {\n return false;\n }\n // Nếu session thuộc ads.zalo.me và có chỉ định accountScope.memberId (sub-account),\n // bắt buộc JWT trong PLAY_SESSION phải khớp với memberId của sub-account đó.\n if (\n session.domain === \"ads.zalo.me\" &&\n this.accountScope?.memberId &&\n String(this.accountScope.memberId) !== \"0\" &&\n !this.accountScope.isRoot\n ) {\n const expectedMemberId = String(this.accountScope.memberId);\n const activeMemberId = String(session.playSessionPayload?.data?.id ?? \"\");\n if (activeMemberId && activeMemberId !== expectedMemberId) {\n return false;\n }\n }\n return true;\n }\n\n private async resolveZpsid(): Promise<string> {\n if (this.getZpsidFn) {\n const dynamicVal = await this.getZpsidFn();\n if (dynamicVal) {\n const parsed = parseZaloCookieInput(dynamicVal);\n this.zpsid = parsed.zpsid;\n for (const flagKey of [\"zoaw_sek\", \"zoaw_type\", \"__zi\", \"__zi-legacy\"]) {\n if (parsed.extractedCookies[flagKey] && !this.extraCookies[flagKey]) {\n this.extraCookies[flagKey] = parsed.extractedCookies[flagKey];\n }\n }\n }\n }\n if (!this.zpsid) {\n throw new Error(\n \"ZaloAuthManager: Missing `zpsid` cookie. Provide `zpsid` or `getZpsid` in ZaloAdsSdk / ZaloAuthManager options.\"\n );\n }\n return this.zpsid;\n }\n\n private async performHandshakeWithDistributedLock(\n accountKey: string,\n domain: ZaloAuthDomain,\n zpsid: string,\n currentFingerprint: string,\n forceRefresh: boolean\n ): Promise<ZaloDomainSession> {\n if (this.sessionStore.acquireLock && this.sessionStore.releaseLock) {\n const lockAcquired = await this.sessionStore\n .acquireLock(accountKey, domain, 15)\n .catch(() => true);\n\n if (!lockAcquired && !forceRefresh) {\n // Tiến trình/pod khác đang thực hiện handshake cho cùng integrationId + domain -> chờ lấy kết quả từ Redis\n for (let attempt = 0; attempt < 6; attempt++) {\n await new Promise((resolve) => setTimeout(resolve, 350));\n const sharedSession = await this.sessionStore.get(accountKey, domain);\n if (sharedSession && this.isSessionValid(sharedSession, currentFingerprint)) {\n this.sessions.set(domain, sharedSession);\n return sharedSession;\n }\n }\n }\n\n try {\n return await this.performHandshake(accountKey, domain, zpsid, currentFingerprint);\n } finally {\n if (lockAcquired) {\n await this.sessionStore.releaseLock(accountKey, domain).catch(() => undefined);\n }\n }\n }\n\n return this.performHandshake(accountKey, domain, zpsid, currentFingerprint);\n }\n\n private async performHandshake(\n accountKey: string,\n domain: ZaloAuthDomain,\n zpsid: string,\n zpsidFingerprint: string\n ): Promise<ZaloDomainSession> {\n const cookies: Record<string, string> = {\n ...this.extraCookies,\n zpsid,\n };\n\n const headers: Record<string, string> = {\n \"User-Agent\": this.userAgent,\n };\n\n let adsProfile: ZaloAdsWhoamiProfile | undefined;\n let formProfile: ZaloFormSessionProfile | undefined;\n\n if (domain === \"ads.zalo.me\") {\n const explicitPlaySession = this.extraCookies?.PLAY_SESSION || cookies[\"PLAY_SESSION\"];\n // Chỉ thực hiện followOAuthRedirects api/login nếu CHƯA có PLAY_SESSION ủy quyền\n if (!explicitPlaySession) {\n await this.followOAuthRedirects(\"https://ads.zalo.me/api/login\", cookies, true);\n }\n // Gọi /api/whoami để lấy XSRF-TOKEN và thông tin tài khoản quảng cáo\n const whoamiRes = await this.fetchImpl(\"https://ads.zalo.me/api/whoami\", {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"application/json\",\n },\n });\n this.mergeSetCookies(whoamiRes, cookies);\n // Bảo toàn PLAY_SESSION ủy quyền đã truyền vào nếu có\n if (explicitPlaySession) {\n cookies[\"PLAY_SESSION\"] = explicitPlaySession;\n }\n const whoamiJson = (await whoamiRes.json().catch(() => null)) as {\n code?: number;\n data?: ZaloAdsWhoamiProfile;\n } | null;\n if (whoamiJson?.data) {\n adsProfile = whoamiJson.data;\n }\n\n // Tự động chuyển đổi ngữ cảnh tài khoản theo accountScope nếu là tài khoản con hoặc tài khoản ủy quyền\n const currentActiveId = String(\n decodePlaySessionJwt(cookies[\"PLAY_SESSION\"] || \"\")?.data?.id ?? \"\"\n );\n const shouldSwitchContext = Boolean(\n this.accountScope?.memberId &&\n String(this.accountScope.memberId) !== \"0\" &&\n !this.accountScope.isRoot &&\n (!explicitPlaySession || (currentActiveId && currentActiveId !== String(this.accountScope.memberId)))\n );\n\n if (shouldSwitchContext) {\n const memberIdStr = String(this.accountScope!.memberId);\n const switchUrls: string[] = [];\n if (this.accountScope!.accountType === \"ACCESSOR\") {\n switchUrls.push(`https://ads.zalo.me/api/ba/personal/login?memberId=${memberIdStr}`);\n } else if (\n this.accountScope!.accountType === \"AGENCY_MASTER\" ||\n this.accountScope!.accountType === \"AGENCY\" ||\n this.accountScope!.accountType === \"AGENCY_SUB_ACCOUNT\"\n ) {\n switchUrls.push(`https://ads.zalo.me/api/ba/agency/login?memberId=${memberIdStr}`);\n switchUrls.push(`https://ads.zalo.me/api/ba/personal/login?memberId=${memberIdStr}`);\n } else {\n switchUrls.push(`https://ads.zalo.me/api/ba/agency/login?memberId=${memberIdStr}`);\n switchUrls.push(`https://ads.zalo.me/api/ba/personal/login?memberId=${memberIdStr}`);\n }\n\n for (const switchUrl of switchUrls) {\n try {\n const switchRes = await this.fetchImpl(switchUrl, {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"application/json, text/plain, */*\",\n },\n redirect: \"manual\",\n });\n this.mergeSetCookies(switchRes, cookies);\n const location = switchRes.headers.get(\"location\") || \"\";\n if (location && !location.includes(\"/client/denied\")) {\n const switchedWhoamiRes = await this.fetchImpl(\"https://ads.zalo.me/api/whoami\", {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"application/json\",\n },\n });\n this.mergeSetCookies(switchedWhoamiRes, cookies);\n const switchedJson = (await switchedWhoamiRes.json().catch(() => null)) as {\n code?: number;\n data?: ZaloAdsWhoamiProfile;\n } | null;\n if (switchedJson?.data) {\n adsProfile = switchedJson.data;\n }\n break;\n }\n } catch {\n // Tiếp tục thử URL kế tiếp nếu có\n }\n }\n }\n\n if (this.accountScope?.memberId && String(this.accountScope.memberId) !== \"0\") {\n cookies[\"ads_user_id\"] = String(this.accountScope.memberId);\n } else if (this.extraCookies?.ads_user_id) {\n cookies[\"ads_user_id\"] = String(this.extraCookies.ads_user_id);\n } else if (adsProfile?.id) {\n cookies[\"ads_user_id\"] = String(adsProfile.id);\n }\n } else if (domain === \"page.ads.zalo.me\") {\n await this.followOAuthRedirects(\"https://page.ads.zalo.me/api/login\", cookies, false);\n } else if (domain === \"form.ads.zalo.me\") {\n const loginUrl =\n \"https://form.ads.zalo.me/client/manage/api/auth/login?state=\" +\n encodeURIComponent(\"https://form.ads.zalo.me/client/manage\");\n await this.followOAuthRedirects(loginUrl, cookies, false);\n\n const sessionRes = await this.fetchImpl(\n \"https://form.ads.zalo.me/client/manage/api/auth/session\",\n {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"application/json\",\n },\n }\n );\n this.mergeSetCookies(sessionRes, cookies);\n const sessionJson = (await sessionRes.json().catch(() => null)) as {\n code?: number;\n data?: ZaloFormSessionProfile;\n } | null;\n if (sessionJson?.data) {\n formProfile = sessionJson.data;\n }\n } else if (domain === \"profile.ads.zalo.me\") {\n const profileRes = await this.followOAuthRedirects(\"https://profile.ads.zalo.me/\", cookies, false);\n if (profileRes) {\n const html = await profileRes.text().catch(() => \"\");\n const csrfMatch = html.match(/CSRF_TOKEN\\s*=\\s*['\"]([^'\"]+)['\"]/);\n if (csrfMatch?.[1]) {\n cookies[\"CSRF_TOKEN\"] = csrfMatch[1];\n }\n }\n headers[\"Origin\"] = \"https://profile.ads.zalo.me\";\n headers[\"Referer\"] = \"https://profile.ads.zalo.me/\";\n } else if (domain === \"api.widget.zalo.me\" || domain === \"widget.chat.zalo.me\") {\n headers[\"Origin\"] = \"https://ads.zalo.me\";\n headers[\"Referer\"] = \"https://ads.zalo.me/\";\n }\n\n const xsrfToken = cookies[\"XSRF-TOKEN\"] ?? cookies[\"CSRF_TOKEN\"];\n if (cookies[\"XSRF-TOKEN\"]) {\n headers[\"x-xsrf-token\"] = cookies[\"XSRF-TOKEN\"];\n }\n\n const bearerToken = formProfile?.token;\n if (bearerToken) {\n headers[\"Authorization\"] = bearerToken;\n }\n\n const playSessionPayload = cookies[\"PLAY_SESSION\"]\n ? decodePlaySessionJwt(cookies[\"PLAY_SESSION\"])\n : undefined;\n\n const now = Date.now();\n const jwtExpMs = playSessionPayload?.exp ? playSessionPayload.exp * 1000 - 60_000 : undefined;\n const expiresAt =\n jwtExpMs && jwtExpMs > now ? Math.min(jwtExpMs, now + this.sessionTtlMs) : now + this.sessionTtlMs;\n\n const session: ZaloDomainSession = {\n domain,\n accountKey,\n zpsidFingerprint,\n cookies,\n xsrfToken,\n bearerToken,\n headers,\n playSessionPayload,\n adsProfile,\n formProfile,\n createdAt: now,\n expiresAt,\n };\n\n this.sessions.set(domain, session);\n await this.sessionStore.set(accountKey, domain, session);\n\n if (this.onSessionRefreshed) {\n await this.onSessionRefreshed(domain, session);\n }\n return session;\n }\n\n private async followOAuthRedirects(\n startUrl: string,\n cookies: Record<string, string>,\n stripSelectAccount: boolean\n ): Promise<Response | undefined> {\n let currentUrl = startUrl;\n let lastResponse: Response | undefined;\n for (let step = 1; step <= 7; step++) {\n const res = await this.fetchImpl(currentUrl, {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\",\n },\n redirect: \"manual\",\n });\n lastResponse = res;\n\n this.mergeSetCookies(res, cookies);\n\n let location = res.headers.get(\"location\");\n\n // Nếu tài khoản Zalo mới lần đầu truy cập domain con (ví dụ page.ads.zalo.me) chưa bấm \"Cho phép\",\n // oauth.zaloapp.com/v4/permission sẽ trả về 200 OK chứa <form id=\"zid_consent_form\">.\n // Tự động submit form \"Cho phép\" để lấy 302 Redirect kèm authorization code!\n if (\n !location &&\n res.status === 200 &&\n currentUrl.includes(\"oauth.zaloapp.com/v4/permission\")\n ) {\n const html = await res.text().catch(() => \"\");\n const csrfMatch = html.match(/name=\"csrf_token\"[^>]*value=\"([^\"]+)\"/);\n if (csrfMatch && html.includes(\"zid_consent_form\")) {\n const stateMatch = html.match(/name=\"state\"[^>]*value=\"([^\"]+)\"/);\n const parsedOAuthUrl = new URL(currentUrl);\n const consentForm = new URLSearchParams({\n csrf_token: csrfMatch[1],\n app_id: parsedOAuthUrl.searchParams.get(\"app_id\") ?? \"\",\n redirect_uri: parsedOAuthUrl.searchParams.get(\"redirect_uri\") ?? \"\",\n bndl_id: \"\",\n pkg_name: \"\",\n sign_key: \"\",\n wp_guid: \"\",\n mac: \"\",\n ref: \"\",\n token_login_post: \"\",\n state: stateMatch ? stateMatch[1] : parsedOAuthUrl.searchParams.get(\"state\") ?? \"\",\n ext_info: \"\",\n enable_qgpf: \"\",\n });\n\n const consentRes = await this.fetchImpl(currentUrl, {\n method: \"POST\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Origin: \"https://oauth.zaloapp.com\",\n Referer: currentUrl,\n },\n body: consentForm.toString(),\n redirect: \"manual\",\n });\n lastResponse = consentRes;\n\n this.mergeSetCookies(consentRes, cookies);\n location = consentRes.headers.get(\"location\");\n if (!location || consentRes.status < 300 || consentRes.status >= 400) {\n break;\n }\n } else {\n break;\n }\n } else if (!location || res.status < 300 || res.status >= 400) {\n break;\n }\n\n if (\n stripSelectAccount &&\n location.includes(\"oauth.zaloapp.com\") &&\n location.includes(\"select_account=true\")\n ) {\n location = location\n .replace(\"&select_account=true\", \"\")\n .replace(\"select_account=true&\", \"\")\n .replace(\"?select_account=true\", \"?\");\n }\n\n if (location.startsWith(\"http://profile.ads.zalo.me\")) {\n location = location.replace(/^http:\\/\\//, \"https://\");\n }\n\n currentUrl = location.startsWith(\"http\")\n ? location\n : new URL(location, currentUrl).toString();\n }\n return lastResponse;\n }\n\n private mergeSetCookies(res: Response, target: Record<string, string>): void {\n const headersWithSetCookie = res.headers as Headers & {\n getSetCookie?: () => string[];\n };\n const setCookieList: string[] =\n typeof headersWithSetCookie.getSetCookie === \"function\"\n ? headersWithSetCookie.getSetCookie()\n : res.headers.get(\"set-cookie\")\n ? [res.headers.get(\"set-cookie\") as string]\n : [];\n\n for (const raw of setCookieList) {\n const [firstPart] = raw.split(\";\");\n const eqIdx = firstPart.indexOf(\"=\");\n if (eqIdx > 0) {\n const key = firstPart.slice(0, eqIdx).trim();\n const val = firstPart.slice(eqIdx + 1).trim();\n // Bỏ qua các lệnh xóa cookie rỗng (ví dụ PLAY_SESSION=; Max-Age=0)\n if (val) {\n target[key] = val;\n }\n }\n }\n }\n\n private formatCookieHeader(cookies: Record<string, string>): string {\n return Object.entries(cookies)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \");\n }\n\n private extractDomainFromUrlOrHost(urlOrDomain: string): ZaloAuthDomain {\n if (urlOrDomain.startsWith(\"http://\") || urlOrDomain.startsWith(\"https://\")) {\n return this.normalizeDomain(new URL(urlOrDomain).hostname);\n }\n return this.normalizeDomain(urlOrDomain);\n }\n\n private normalizeDomain(host: string): ZaloAuthDomain {\n const clean = host.toLowerCase().trim().replace(/:\\d+$/, \"\");\n switch (clean) {\n case \"ads.zalo.me\":\n case \"page.ads.zalo.me\":\n case \"form.ads.zalo.me\":\n case \"profile.ads.zalo.me\":\n case \"api.widget.zalo.me\":\n case \"widget.chat.zalo.me\":\n return clean;\n default:\n return \"ads.zalo.me\";\n }\n }\n}\n\n/**\n * Helper khởi tạo nhanh đối tượng `ZaloSdkAuth` từ `zpsid` hoặc `ZaloSsoAuthOptions`.\n */\nexport function createZaloSsoAuth(options: ZaloSsoAuthOptions | string): ZaloSdkAuth {\n const manager = new ZaloAuthManager(options);\n return manager.toSdkAuth();\n}\n","import { ZaloAuthManager, type ZaloSsoAuthOptions } from \"./auth\";\nimport type { FileInput, HttpMethod, RequestOptions, ZaloAccountScope, ZaloAdsSdkOptions, ZaloSdkAuth, ZaloSdkAuthContext } from \"./types\";\nimport { ZaloSdkError } from \"./types\";\n\nexport type BodyType = \"json\" | \"urlencoded\" | \"multipart\" | \"none\";\n\nexport interface OperationDefinition {\n operationId: string;\n method: HttpMethod;\n endpoint: string;\n baseUrl: string;\n binaryFields: string[];\n pathFields: string[];\n queryFields: string[];\n headerFields: string[];\n cookieFields: string[];\n bodyFields: string[];\n}\n\nconst DEFAULT_BASE_URLS = {\n ads: \"https://ads.zalo.me\",\n forms: \"https://form.ads.zalo.me\",\n instantPages: \"https://page.ads.zalo.me\",\n profileAds: \"https://profile.ads.zalo.me\",\n widget: \"https://api.widget.zalo.me\",\n chatWidget: \"https://widget.chat.zalo.me\"\n} as const;\n\nexport class ZaloSdkHttpClient {\n private readonly fetchImpl: typeof fetch;\n private readonly baseUrls: Record<string, string>;\n private defaultAuth?: ZaloSdkAuth;\n private readonly authByHost = new Map<string, ZaloSdkAuth>();\n private authManagerInstance?: ZaloAuthManager;\n private readonly autoRetryOn401: boolean;\n public accountScope?: ZaloAccountScope;\n\n constructor(options: ZaloAdsSdkOptions = {}) {\n this.fetchImpl = options.fetch ?? globalThis.fetch;\n if (!this.fetchImpl) throw new Error(\"A Fetch implementation is required (Node.js 18+ provides global fetch).\");\n this.baseUrls = { ...DEFAULT_BASE_URLS, ...(options.baseUrls ?? {}) };\n this.autoRetryOn401 = options.autoRetryOn401 ?? true;\n this.accountScope = options.accountScope;\n\n if (options.authManager) {\n this.authManagerInstance = options.authManager;\n if (options.accountScope && !this.authManagerInstance.getAccountScope()) {\n this.authManagerInstance.setAccountScope(options.accountScope);\n }\n } else if (options.zpsid || options.ssoAuth) {\n const extraCookies: Record<string, string> = {\n ...(options.ssoAuth?.extraCookies ?? {}),\n ...(options.zoawSek ? { zoaw_sek: options.zoawSek } : {}),\n };\n if (options.accountScope?.memberId && String(options.accountScope.memberId) !== \"0\") {\n extraCookies[\"ads_user_id\"] = String(options.accountScope.memberId);\n }\n this.authManagerInstance = new ZaloAuthManager({\n fetch: this.fetchImpl,\n integrationId: options.integrationId,\n accountKey: options.accountKey,\n accountScope: options.accountScope ?? options.ssoAuth?.accountScope,\n sessionStore: options.sessionStore,\n redis: options.redis,\n redisKeyPrefix: options.redisKeyPrefix,\n ...(options.ssoAuth ?? {}),\n extraCookies,\n ...(options.zpsid ? { zpsid: options.zpsid } : {}),\n });\n }\n\n this.defaultAuth = options.auth ?? this.authManagerInstance?.toSdkAuth();\n for (const [host, auth] of Object.entries(options.authByHost ?? {})) this.authByHost.set(host, auth);\n }\n\n public get authManager(): ZaloAuthManager | undefined {\n return this.authManagerInstance;\n }\n\n public setAuthManager(manager?: ZaloAuthManager): void {\n this.authManagerInstance = manager;\n this.defaultAuth = manager?.toSdkAuth();\n }\n\n public setZpsid(zpsidInput: string, ssoOptions?: Omit<ZaloSsoAuthOptions, \"zpsid\">): ZaloAuthManager {\n if (this.authManagerInstance && !ssoOptions) {\n this.authManagerInstance.setZpsid(zpsidInput);\n } else {\n this.authManagerInstance = new ZaloAuthManager({\n fetch: this.fetchImpl,\n ...(ssoOptions ?? {}),\n zpsid: zpsidInput\n });\n this.defaultAuth = this.authManagerInstance.toSdkAuth();\n }\n return this.authManagerInstance;\n }\n\n public setAuth(auth?: ZaloSdkAuth): void { this.defaultAuth = auth; }\n public setAuthForHost(host: string, auth?: ZaloSdkAuth): void {\n if (auth) this.authByHost.set(host, auth); else this.authByHost.delete(host);\n }\n public resolveBaseUrl(baseUrl: string): string {\n const found = Object.values(this.baseUrls).find((value) => value === baseUrl);\n return found ?? baseUrl;\n }\n\n public requestJson<TResponse>(operation: OperationDefinition, input: Record<string, unknown> = {}, options: RequestOptions = {}): Promise<TResponse> {\n return this.execute<TResponse>(operation, input, \"json\", options);\n }\n\n public requestFormUrlEncoded<TResponse>(operation: OperationDefinition, input: Record<string, unknown> = {}, options: RequestOptions = {}): Promise<TResponse> {\n return this.execute<TResponse>(operation, input, \"urlencoded\", options);\n }\n\n public requestMultipart<TResponse>(operation: OperationDefinition, input: Record<string, unknown> = {}, options: RequestOptions = {}): Promise<TResponse> {\n return this.execute<TResponse>(operation, input, \"multipart\", options);\n }\n\n public requestWithoutBody<TResponse>(operation: OperationDefinition, input: Record<string, unknown> = {}, options: RequestOptions = {}): Promise<TResponse> {\n return this.execute<TResponse>(operation, input, \"none\", options);\n }\n\n private async execute<TResponse>(\n operation: OperationDefinition,\n input: Record<string, unknown>,\n bodyType: BodyType,\n options: RequestOptions,\n isRetry = false\n ): Promise<TResponse> {\n const path = { ...asRecord(input.path_param) };\n const endpoint = operation.endpoint.replace(/\\{([^}]+)\\}/g, (_match, key: string) => encodeURIComponent(String(path[key])));\n const url = new URL(endpoint, operation.baseUrl);\n for (const [key, value] of Object.entries(asRecord(input.query_param))) appendQuery(url.searchParams, key, value);\n const context: ZaloSdkAuthContext = { url: url.toString(), host: url.host, operationId: operation.operationId, method: operation.method };\n const auth = this.authByHost.get(url.host) ?? this.defaultAuth;\n const headers = new Headers(await resolveHeaders(auth, context));\n for (const [key, value] of Object.entries(options.headers ?? {})) headers.set(key, value);\n const cookies = await resolveCookies(auth, context);\n if (Object.keys(cookies).length && !headers.has(\"cookie\")) {\n headers.set(\"cookie\", Object.entries(cookies).filter(([, v]) => v !== undefined && v !== \"\").map(([k, v]) => `${k}=${v}`).join(\"; \"));\n }\n\n const init: RequestInit = { method: operation.method, headers, signal: options.signal };\n const body = asRecord(input.body);\n if (bodyType === \"json\") {\n headers.set(\"content-type\", headers.get(\"content-type\") ?? \"application/json\");\n const jsonPayload = input.body !== undefined ? input.body : body;\n init.body = JSON.stringify(jsonPayload);\n } else if (bodyType === \"urlencoded\") {\n headers.set(\"content-type\", headers.get(\"content-type\") ?? \"application/x-www-form-urlencoded;charset=UTF-8\");\n const encoded = new URLSearchParams();\n for (const [key, value] of Object.entries(body)) {\n if (value === undefined) continue;\n encoded.set(key, typeof value === \"string\" ? value : JSON.stringify(value));\n }\n init.body = encoded;\n } else if (bodyType === \"multipart\") {\n const form = new FormData();\n for (const [key, value] of Object.entries(body)) {\n if (value === undefined) continue;\n if (operation.binaryFields.includes(key)) form.append(key, await this.resolveFile(value as FileInput), fileNameFrom(value));\n else form.append(key, typeof value === \"string\" ? value : JSON.stringify(value));\n }\n headers.delete(\"content-type\");\n init.body = form;\n }\n\n const response = await this.fetchImpl(url, init);\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n const responseBody: unknown = contentType.includes(\"json\") ? await response.json().catch(() => undefined) : await response.blob();\n\n const isFormUnauthorized =\n url.host === \"form.ads.zalo.me\" &&\n responseBody !== null &&\n typeof responseBody === \"object\" &&\n (responseBody as { code?: unknown }).code === 401;\n\n if ((response.status === 401 || isFormUnauthorized) && !isRetry && this.autoRetryOn401 && this.authManagerInstance) {\n await this.authManagerInstance.invalidateDomainAsync(url.host);\n return this.execute<TResponse>(operation, input, bodyType, options, true);\n }\n\n if (!response.ok) throw new ZaloSdkError(`Zalo request failed with HTTP ${response.status}.`, response.status, operation.operationId, responseBody);\n return responseBody as TResponse;\n }\n\n /** Converts a flat public DTO into the transport locations required by one API. */\n public toTransportInput(operation: OperationDefinition, dto: Record<string, unknown>): Record<string, unknown> {\n const output: Record<string, unknown> = {};\n const add = (location: string, names: string[]) => {\n if (!names.length) return;\n const values: Record<string, unknown> = {};\n for (const name of names) if (dto[name] !== undefined) values[name] = dto[name];\n output[location] = values;\n };\n add(\"path_param\", operation.pathFields);\n add(\"query_param\", operation.queryFields);\n add(\"header_param\", operation.headerFields);\n add(\"cookie_param\", operation.cookieFields);\n add(\"body\", operation.bodyFields);\n\n // Tự động gài context từ accountScope vào query_param nếu caller không truyền thủ công\n if (this.accountScope && output.query_param) {\n const query = output.query_param as Record<string, unknown>;\n const isAgencyContext =\n this.accountScope.accountType === \"AGENCY_SUB_ACCOUNT\" ||\n this.accountScope.accountType === \"AGENCY_MASTER\" ||\n this.accountScope.accountType === \"AGENCY\" ||\n Boolean(this.accountScope.agencyId);\n\n if (\n operation.queryFields.includes(\"agencyId\") &&\n query.agencyId === undefined &&\n isAgencyContext &&\n this.accountScope.agencyId\n ) {\n query.agencyId = Number(this.accountScope.agencyId);\n }\n\n if (\n operation.queryFields.includes(\"createdBy\") &&\n query.createdBy === undefined &&\n this.accountScope.accountType === \"AGENCY_SUB_ACCOUNT\" &&\n this.accountScope.memberId &&\n String(this.accountScope.memberId) !== \"0\"\n ) {\n query.createdBy = Number(this.accountScope.memberId);\n }\n }\n\n return output;\n }\n\n private async resolveFile(input: FileInput): Promise<Blob> {\n if (typeof input === \"string\") {\n if (/^(https?:|data:)/i.test(input)) {\n const response = await this.fetchImpl(input);\n if (!response.ok) throw new Error(`Cannot download upload file URL: HTTP ${response.status}.`);\n return response.blob();\n }\n // Local file path in Node.js runtime\n const fs = await import(\"node:fs/promises\");\n const bytes = await fs.readFile(input);\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return new Blob([copy.buffer], { type: inferMimeType(input) });\n }\n if (input instanceof Blob) return input;\n if (input instanceof ArrayBuffer) return new Blob([input]);\n // Copy first so TypeScript does not retain a SharedArrayBuffer-compatible view.\n const bytes = new Uint8Array(input.byteLength);\n bytes.set(input);\n return new Blob([bytes.buffer]);\n }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value) ? value as Record<string, unknown> : {};\n}\nfunction appendQuery(params: URLSearchParams, key: string, value: unknown): void {\n if (value === undefined || value === null || value === \"\") return;\n if (Array.isArray(value)) { for (const item of value) params.append(key, String(item)); return; }\n params.set(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n}\nfunction fileNameFrom(value: unknown): string {\n if (typeof value === \"string\") {\n if (/^https?:/i.test(value)) {\n try { return new URL(value).pathname.split(\"/\").pop() || \"upload\"; } catch { return \"upload\"; }\n }\n const base = value.split(/[\\\\/]/).pop();\n return base || \"upload\";\n }\n if (value && typeof value === \"object\" && \"name\" in value && typeof (value as { name?: unknown }).name === \"string\") {\n return (value as { name: string }).name;\n }\n if (value instanceof Blob && value.type) {\n const ext = value.type.split(\"/\")[1]?.replace(\"jpeg\", \"jpg\");\n if (ext) return `upload.${ext}`;\n }\n return \"upload\";\n}\nfunction inferMimeType(filePath: string): string {\n const lower = filePath.toLowerCase();\n if (lower.endsWith(\".jpg\") || lower.endsWith(\".jpeg\")) return \"image/jpeg\";\n if (lower.endsWith(\".png\")) return \"image/png\";\n if (lower.endsWith(\".gif\")) return \"image/gif\";\n if (lower.endsWith(\".webp\")) return \"image/webp\";\n if (lower.endsWith(\".mp4\")) return \"video/mp4\";\n if (lower.endsWith(\".txt\")) return \"text/plain\";\n if (lower.endsWith(\".csv\")) return \"text/csv\";\n return \"application/octet-stream\";\n}\nasync function resolveHeaders(auth: ZaloSdkAuth | undefined, context: ZaloSdkAuthContext): Promise<Record<string, string>> {\n return { ...(auth?.headers ?? {}), ...((await auth?.getHeaders?.(context)) ?? {}) };\n}\nasync function resolveCookies(auth: ZaloSdkAuth | undefined, context: ZaloSdkAuthContext): Promise<Record<string, string>> {\n return { ...(auth?.cookies ?? {}), ...((await auth?.getCookies?.(context)) ?? {}) };\n}\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Targeting & Custom Audiences trên Zalo Ads:\n * 1. createSavedAudience (POST /api/ad/audience với caType = 1)\n * 2. createPhoneAudience (POST /api/ad/audience với caType = 3)\n * 3. createLookalikeAudience (POST /api/ad/audience với caType = 6)\n * 4. createFormEventAudience (POST /api/ad/audience với caType = 12)\n * 5. createMessageOaEventAudience (POST /api/ad/audience với caType = 11)\n * 6. createMessagePersonalEventAudience (POST /api/ad/audience với caType = 14)\n * 7. createFormLeadAudience (POST /api/ad/audience với caType = 10)\n * 8. createMessageOaLeadAudience (POST /api/ad/audience với caType = 13)\n * 9. createCommerceFormAudience (POST /api/ad/audience với caType = 15)\n * 10. createLeadSignalAudience (POST /api/ad/audience với caType = 16)\n * 11. estimateAudience (POST /api/ad/estimateAudience)\n * 12. deleteCustomAudience (DELETE /api/ad/audience/{customAudienceId})\n */\n\nimport type { ValidationResult } from \"./instant-pages.validator\";\nimport type {\n ZaloAdsUploadCustomAudiencePhoneListRequest,\n ZaloAdsCreateCustomAudienceRequest,\n} from \"../dtos/ads.dto\";\n\n/**\n * Danh mục mã 63 Tỉnh/Thành phố chuẩn theo 3 Vùng miền trên Zalo Ads Targeting Engine (Danh mục cũ):\n */\nexport const ZALO_REGION_PROVINCE_CODES: Record<number, string[]> = {\n 1: [\n \"VN58\", \"VN44\", \"VN72\", \"VN83\", \"VN50\", \"VN13\", \"VN82\", \"VN70\", \"VN53\", \"VN30\",\n \"VN74\", \"VN34\", \"VN52\", \"VN79\", \"VN80\", \"VN32\", \"VN71\", \"VN59\", \"VN86\", \"VN05\",\n \"VN85\", \"VN39\", \"VN35\", \"VN89\", \"VN81\", \"VN92\", \"VN90\", \"VN68\"\n ],\n 2: [\n \"VN55\", \"VN88\", \"VN47\", \"VN62\", \"VN54\", \"VN61\", \"VN64\", \"VN49\", \"VN63\", \"VN46\",\n \"VN84\", \"VN66\", \"VN91\", \"VN60\", \"VN23\", \"VN78\"\n ],\n 3: [\n \"VN87\", \"VN03\", \"VN76\", \"VN43\", \"VN65\", \"VN21\", \"VN24\", \"VN75\", \"VN45\", \"VN67\",\n \"VN01\", \"VN73\", \"VN77\", \"VN37\", \"VN20\", \"VN09\", \"VN69\", \"VN33\", \"VN93\"\n ]\n};\n\n/**\n * Danh mục 34 Cụm Tỉnh/Thành phố mới sau sáp nhập trên Zalo Ads (newProvinces).\n * Khi cấu hình WardTargeting (từ cải cách hành chính 2026), Zalo Ads Angular UI\n * BẮT BUỘC tra cứu theo 34 mã mới này. Nếu truyền mã tỉnh đã bị gộp (như VN75 - Bình Dương),\n * giao diện Zalo Ads sẽ bị lỗi đỏ: 'Invalid wards params'.\n */\nexport const ZALO_NEW_REGION_PROVINCE_CODES: Record<number, string[]> = {\n 1: [\"VN58\", \"VN44\", \"VN83\", \"VN32\", \"VN59\", \"VN13\", \"VN89\", \"VN30\", \"VN74\", \"VN34\", \"VN52\", \"VN05\", \"VN85\", \"VN39\", \"VN81\", \"VN92\", \"VN90\", \"VN68\"],\n 2: [\"VN66\", \"VN88\", \"VN54\", \"VN64\", \"VN49\", \"VN63\", \"VN23\", \"VN78\"],\n 3: [\"VN20\", \"VN87\", \"VN43\", \"VN33\", \"VN01\", \"VN77\", \"VN09\", \"VN69\"]\n};\n\n/** Bảng tra cứu ánh xạ mã tỉnh cũ sang cụm tỉnh mới sau sáp nhập */\nexport const ZALO_PROVINCE_MERGE_MAPPING: Record<string, { newCode: string; regionId: number; name: string }> = {\n VN75: { newCode: \"VN20\", regionId: 3, name: \"Bình Dương (đã sáp nhập vào cụm Hồ Chí Minh VN20)\" },\n VN45: { newCode: \"VN20\", regionId: 3, name: \"Bà Rịa - Vũng Tàu (đã sáp nhập vào cụm Hồ Chí Minh VN20)\" },\n VN76: { newCode: \"VN43\", regionId: 3, name: \"Bình Phước (đã sáp nhập vào cụm Đồng Nai VN43)\" },\n VN24: { newCode: \"VN33\", regionId: 3, name: \"Long An (đã sáp nhập vào cụm Tây Ninh VN33)\" },\n VN21: { newCode: \"VN01\", regionId: 3, name: \"Kiên Giang (đã sáp nhập vào cụm An Giang VN01)\" },\n VN73: { newCode: \"VN77\", regionId: 3, name: \"Bạc Liêu (đã sáp nhập vào cụm Cà Mau VN77)\" },\n VN37: { newCode: \"VN09\", regionId: 3, name: \"Tiền Giang (đã sáp nhập vào cụm Đồng Tháp VN09)\" },\n VN03: { newCode: \"VN69\", regionId: 3, name: \"Bến Tre (đã sáp nhập vào cụm Vĩnh Long VN69)\" },\n VN67: { newCode: \"VN69\", regionId: 3, name: \"Trà Vinh (đã sáp nhập vào cụm Vĩnh Long VN69)\" },\n VN65: { newCode: \"VN87\", regionId: 3, name: \"Sóc Trăng (đã sáp nhập vào cụm Cần Thơ VN87)\" },\n VN93: { newCode: \"VN87\", regionId: 3, name: \"Hậu Giang (đã sáp nhập vào cụm Cần Thơ VN87)\" },\n VN61: { newCode: \"VN88\", regionId: 2, name: \"Phú Yên (đã sáp nhập vào cụm Đắk Lắk VN88)\" },\n VN60: { newCode: \"VN54\", regionId: 2, name: \"Ninh Thuận (đã sáp nhập vào cụm Khánh Hòa VN54)\" },\n VN62: { newCode: \"VN64\", regionId: 2, name: \"Quảng Bình (đã sáp nhập vào cụm Quảng Trị VN64)\" },\n VN46: { newCode: \"VN49\", regionId: 2, name: \"Bình Định (đã sáp nhập vào cụm Gia Lai VN49)\" },\n VN55: { newCode: \"VN63\", regionId: 2, name: \"Kon Tum (đã sáp nhập vào cụm Quảng Ngãi VN63)\" },\n VN47: { newCode: \"VN23\", regionId: 2, name: \"Bình Thuận (đã sáp nhập vào cụm Lâm Đồng VN23)\" },\n VN91: { newCode: \"VN23\", regionId: 2, name: \"Đắk Nông (đã sáp nhập vào cụm Lâm Đồng VN23)\" },\n VN84: { newCode: \"VN78\", regionId: 2, name: \"Quảng Nam (đã sáp nhập vào cụm Đà Nẵng VN78)\" },\n VN86: { newCode: \"VN83\", regionId: 1, name: \"Ninh Bình (đã sáp nhập vào cụm Phú Thọ VN83)\" },\n VN53: { newCode: \"VN83\", regionId: 1, name: \"Bắc Kạn (đã sáp nhập vào cụm Phú Thọ VN83)\" },\n VN82: { newCode: \"VN59\", regionId: 1, name: \"Bắc Giang (đã sáp nhập vào cụm Ninh Bình VN59)\" },\n VN80: { newCode: \"VN59\", regionId: 1, name: \"Phú Thọ cũ (đã sáp nhập vào cụm Ninh Bình VN59)\" },\n VN79: { newCode: \"VN13\", regionId: 1, name: \"Hải Dương (đã sáp nhập vào cụm Hải Phòng VN13)\" },\n VN71: { newCode: \"VN74\", regionId: 1, name: \"Hưng Yên cũ (đã sáp nhập vào cụm Bắc Ninh VN74)\" },\n VN72: { newCode: \"VN85\", regionId: 1, name: \"Yên Bái (đã sáp nhập vào cụm Thái Nguyên VN85)\" },\n VN35: { newCode: \"VN81\", regionId: 1, name: \"Thái Bình (đã sáp nhập vào cụm Hưng Yên VN81)\" },\n VN70: { newCode: \"VN90\", regionId: 1, name: \"Vĩnh Phúc (đã sáp nhập vào cụm Lào Cai VN90)\" },\n VN50: { newCode: \"VN68\", regionId: 1, name: \"Hòa Bình (đã sáp nhập vào cụm Tuyên Quang VN68)\" }\n};\n\n/**\n * 1. Kiểm tra request Tạo Nhóm đối tượng đã lưu (Saved Audience - caType = 1)\n */\nexport function validateCreateSavedAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 1;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name) {\n errors.push(\"Tên nhóm đối tượng 'name' là bắt buộc.\");\n } else if (name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown>;\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n targetingObj = {};\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n } else {\n errors.push(\"Trường 'targeting' là bắt buộc (chuỗi JSON hoặc Object cấu hình targeting).\");\n targetingObj = {};\n }\n\n // Chuẩn hóa targeting defaults\n const gender = typeof targetingObj.Gender === \"number\" ? targetingObj.Gender : 0;\n if (![0, 1, 2].includes(gender)) {\n errors.push(\"Trường 'Gender' phải là 0 (Tất cả), 1 (Nam), hoặc 2 (Nữ).\");\n }\n\n const VALID_AGE_RANGES = [10282, 10283, 10284, 10285, 10286, 10287, 10288];\n const newAgeRanges = Array.isArray(targetingObj.NewAgeRanges) && targetingObj.NewAgeRanges.length > 0\n ? targetingObj.NewAgeRanges.map(Number)\n : VALID_AGE_RANGES;\n\n for (const age of newAgeRanges) {\n if (!VALID_AGE_RANGES.includes(age)) {\n errors.push(`Mã độ tuổi '${age}' không hợp lệ. Các mã cho phép: ${VALID_AGE_RANGES.join(\", \")}.`);\n }\n }\n\n const VALID_OS = [0, 1, 2, 3];\n const os = Array.isArray(targetingObj.Os) && targetingObj.Os.length > 0\n ? targetingObj.Os.map(Number)\n : [0, 1, 3];\n\n for (const o of os) {\n if (!VALID_OS.includes(o)) {\n errors.push(`Mã hệ điều hành '${o}' không hợp lệ (0: Android, 1: iOS, 2: Windows Phone, 3: PC).`);\n }\n }\n\n // Cấu hình vị trí địa lý\n let location: any = targetingObj.Location;\n if (!location || typeof location !== \"object\") {\n location = {\n Addresses: [],\n Cities: [],\n DistrictTargeting: { Includes: [], Excludes: [] },\n WardTargeting: { Includes: [], Excludes: [] },\n IsConvertedToWard: false,\n };\n } else {\n const rawWard = location.WardTargeting && typeof location.WardTargeting === \"object\"\n ? location.WardTargeting\n : undefined;\n const rawDistrict = location.DistrictTargeting && typeof location.DistrictTargeting === \"object\"\n ? location.DistrictTargeting\n : undefined;\n const baseTargeting = rawWard || rawDistrict || { Includes: [], Excludes: [] };\n\n location = {\n Addresses: Array.isArray(location.Addresses) ? location.Addresses : [],\n Cities: Array.isArray(location.Cities) ? location.Cities : [],\n DistrictTargeting: rawDistrict || baseTargeting,\n WardTargeting: rawWard || baseTargeting,\n IsConvertedToWard: location.IsConvertedToWard !== undefined ? Boolean(location.IsConvertedToWard) : false,\n };\n\n const includes = location.WardTargeting.Includes || location.DistrictTargeting.Includes;\n if (includes && !Array.isArray(includes)) {\n errors.push(\"Trường 'Location.WardTargeting.Includes' (hoặc DistrictTargeting.Includes) phải là một mảng khu vực.\");\n } else if (Array.isArray(includes)) {\n for (const inc of includes) {\n if (![1, 2, 3].includes(Number(inc.Id))) {\n errors.push(`Mã vùng miền Id='${inc.Id}' không hợp lệ (1: Miền Bắc, 2: Miền Trung, 3: Miền Nam).`);\n }\n if (inc.Provinces && !Array.isArray(inc.Provinces)) {\n errors.push(`Trường 'Provinces' trong vùng miền Id=${inc.Id} phải là một mảng tỉnh/thành.`);\n } else if (Array.isArray(inc.Provinces)) {\n for (const prov of inc.Provinces) {\n if (!prov.Id || typeof prov.Id !== \"string\") {\n errors.push(`Mã tỉnh 'Id' (${JSON.stringify(prov)}) trong vùng miền ${inc.Id} phải là chuỗi hợp lệ (ví dụ: 'VN44', 'VN20').`);\n } else {\n const mergeInfo = ZALO_PROVINCE_MERGE_MAPPING[prov.Id];\n if (mergeInfo) {\n errors.push(\n `Mã tỉnh '${prov.Id}' (${mergeInfo.name}) đã được Zalo Ads gộp/sáp nhập vào cụm mã '${mergeInfo.newCode}'. ` +\n `Vui lòng sử dụng mã cụm '${mergeInfo.newCode}' trong WardTargeting, nếu không giao diện Zalo Ads Web sẽ báo lỗi đỏ 'Invalid wards params'.`\n );\n } else {\n const validNewRegionProvs = ZALO_NEW_REGION_PROVINCE_CODES[Number(inc.Id)] || [];\n if (!validNewRegionProvs.includes(prov.Id)) {\n const actualRegion = Object.keys(ZALO_NEW_REGION_PROVINCE_CODES).find(r => ZALO_NEW_REGION_PROVINCE_CODES[Number(r)].includes(prov.Id));\n errors.push(\n `Mã tỉnh '${prov.Id}' không nằm trong 34 Cụm Tỉnh/Thành mới của Vùng ${inc.Id} trên Zalo Ads (sẽ gây lỗi 'Invalid wards params' trên UI). ` +\n (actualRegion ? `Mã này thuộc Vùng ${actualRegion}. ` : \"\")\n );\n }\n }\n }\n if (prov.Districts && !Array.isArray(prov.Districts)) {\n errors.push(`Trường 'Districts' của tỉnh ${prov.Id} phải là một mảng (hoặc [] khi chọn cả tỉnh).`);\n }\n }\n }\n }\n }\n }\n\n const finalTargeting = {\n ...targetingObj,\n CustomAudienceId: 0,\n Gender: gender,\n NewAgeRanges: newAgeRanges,\n Os: os,\n Location: location\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 1,\n targeting: JSON.stringify(finalTargeting)\n } : undefined\n };\n}\n\n/**\n * 2. Kiểm tra request Tạo Nhóm đối tượng từ danh sách Số điện thoại (caType = 3)\n */\nexport function validateCreatePhoneAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 3;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n } else {\n errors.push(\"Trường 'targeting' là bắt buộc.\");\n }\n\n const path = typeof targetingObj.Path === \"string\" ? targetingObj.Path.trim() : \"\";\n if (!path) {\n errors.push(\"Trường 'Path' (URL file .txt sau khi upload) là bắt buộc.\");\n }\n\n const total = typeof targetingObj.Total === \"number\" ? targetingObj.Total : 0;\n if (total <= 0) {\n errors.push(\"Trường 'Total' (số lượng SĐT trong file) phải lớn hơn 0.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 3,\n targeting: JSON.stringify({\n Name: String(targetingObj.Name || \"phones.txt\"),\n Path: path,\n Total: total,\n ZaloId: Number(targetingObj.ZaloId || 0),\n OriginAudience: 0\n })\n } : undefined\n };\n}\n\n/**\n * 3. Kiểm tra request Tạo Nhóm đối tượng tương tự Lookalike (caType = 6)\n */\nexport function validateCreateLookalikeAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 6;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n } else {\n errors.push(\"Trường 'targeting' là bắt buộc.\");\n }\n\n const originAudience = Number(targetingObj.OriginAudience);\n if (!originAudience || originAudience <= 0) {\n errors.push(\"Trường 'OriginAudience' (ID nhóm đối tượng SĐT gốc) là bắt buộc.\");\n }\n\n const total = Number(targetingObj.Total);\n if (![1000000, 1500000, 2000000].includes(total)) {\n errors.push(\"Trường 'Total' của Lookalike chỉ chấp nhận các mốc: 1.000.000, 1.500.000 hoặc 2.000.000.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 6,\n targeting: JSON.stringify({\n OriginAudience: originAudience,\n Total: total,\n Name: String(targetingObj.Name || \"Lookalike Audience\"),\n Path: String(targetingObj.Path || \"\")\n })\n } : undefined\n };\n}\n\n/**\n * 4. Kiểm tra request Tạo Nhóm đối tượng sự kiện Form (caType = 12)\n */\nexport function validateCreateFormEventAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 12;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n }\n\n const eventType = Number(targetingObj.EventType);\n if (![1, 2, 3, 4].includes(eventType)) {\n errors.push(\"Trường 'EventType' phải là 1 (Đã xem chưa gửi), 2 (Đã xem & gửi), 3 (Đã xem), hoặc 4 (Mở chat từ Form).\");\n }\n\n const oaId = typeof targetingObj.OaId === \"string\" ? targetingObj.OaId.trim() : String(targetingObj.OaId || \"\");\n if (!oaId) {\n errors.push(\"Trường 'OaId' (dạng chuỗi của pageId hoặc noisedId) là bắt buộc.\");\n }\n\n const numDays = Number(targetingObj.NumDays);\n if (isNaN(numDays) || numDays < 1 || numDays > 90) {\n errors.push(\"Trường 'NumDays' phải nằm trong khoảng từ 1 đến 90 ngày.\");\n }\n\n const formIds = Array.isArray(targetingObj.FormIds) ? targetingObj.FormIds : [];\n if (formIds.length === 0) {\n errors.push(\"Trường 'FormIds' phải chứa ít nhất 1 ID Form.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 12,\n targeting: JSON.stringify({\n EventType: eventType,\n OaId: oaId,\n NumDays: numDays,\n FormIds: formIds\n })\n } : undefined\n };\n}\n\n/**\n * 5. Kiểm tra request Tạo Nhóm đối tượng sự kiện Tin nhắn OA (caType = 11)\n */\nexport function validateCreateMessageOaEventAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 11;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n }\n\n const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);\n const oaId = typeof targetingObj.OaId === \"string\" ? targetingObj.OaId.trim() : String(targetingObj.OaId || \"\");\n if (!oaId) {\n errors.push(\"Trường 'OaId' (chuỗi pageId hoặc noisedId của OA) là bắt buộc.\");\n }\n\n const numDays = Number(targetingObj.NumDays);\n if (isNaN(numDays) || numDays < 1 || numDays > 90) {\n errors.push(\"Trường 'NumDays' phải nằm trong khoảng từ 1 đến 90 ngày.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 11,\n targeting: JSON.stringify({\n EventId: eventId,\n OaId: oaId,\n NumDays: numDays\n })\n } : undefined\n };\n}\n\n/**\n * 6. Kiểm tra request Tạo Nhóm đối tượng sự kiện Tin nhắn Cá nhân (caType = 14)\n */\nexport function validateCreateMessagePersonalEventAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 14;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n }\n\n const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);\n if (![1, 2, 3].includes(eventId)) {\n errors.push(\"Trường 'EventId' phải là 1 (Đã liên hệ), 2 (Đã xem không liên hệ), hoặc 3 (Xem carousel không liên hệ).\");\n }\n\n const numDays = Number(targetingObj.NumDays);\n if (isNaN(numDays) || numDays < 1 || numDays > 90) {\n errors.push(\"Trường 'NumDays' phải nằm trong khoảng từ 1 đến 90 ngày.\");\n }\n\n const pageIds = Array.isArray(targetingObj.PageIds) ? targetingObj.PageIds.map(String) : [];\n if (pageIds.length === 0) {\n errors.push(\"Trường 'PageIds' phải chứa ít nhất 1 ID trang cá nhân.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 14,\n targeting: JSON.stringify({\n EventId: eventId,\n NumDays: numDays,\n PageIds: pageIds\n })\n } : undefined\n };\n}\n\n/**\n * 7. Kiểm tra request Ước tính quy mô đối tượng (POST /api/ad/estimateAudience)\n */\nexport function validateEstimateAudienceRequest(input: unknown): ValidationResult<{\n gender: number;\n ageRanges: number[];\n platforms: number[];\n locations: string;\n provinces: number[];\n wardsTargeting: string;\n priceType: number;\n number: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n\n const gender = typeof raw.gender === \"number\" ? raw.gender : 0;\n if (![0, 1, 2].includes(gender)) {\n errors.push(\"Trường 'gender' phải là 0, 1 hoặc 2.\");\n }\n\n const ageRanges = Array.isArray(raw.ageRanges) && raw.ageRanges.length > 0\n ? raw.ageRanges.map(Number)\n : [10283, 10284, 10285, 10286, 10287];\n\n const platforms = Array.isArray(raw.platforms) && raw.platforms.length > 0\n ? raw.platforms.map(Number)\n : [0, 1, 3];\n\n const priceType = typeof raw.priceType === \"number\" ? raw.priceType : 2;\n\n const wardsTargeting = typeof raw.wardsTargeting === \"string\" && raw.wardsTargeting.trim()\n ? raw.wardsTargeting.trim()\n : JSON.stringify({ Includes: [], Excludes: [] });\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n gender,\n ageRanges,\n platforms,\n locations: typeof raw.locations === \"string\" ? raw.locations : \"\",\n provinces: Array.isArray(raw.provinces) ? raw.provinces.map(Number) : [],\n wardsTargeting,\n priceType,\n number: typeof raw.number === \"string\" ? raw.number : String(raw.number || \"0\")\n } : undefined\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của tệp danh sách số điện thoại tải lên Zalo Ads (POST /api/ad/uploadPhoneList).\n */\nexport function validateUploadCustomAudiencePhoneListRequest(\n input: unknown\n): ValidationResult<ZaloAdsUploadCustomAudiencePhoneListRequest> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu tải danh sách số điện thoại phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const file = raw.File ?? raw.file;\n\n if (!file) {\n errors.push(\"Trường tệp danh sách số điện thoại ('File') là bắt buộc.\");\n return { isValid: false, errors };\n }\n\n if (typeof file === \"string\") {\n const trimmed = file.trim();\n if (!trimmed) {\n errors.push(\"Đường dẫn tệp danh sách số điện thoại không được để trống.\");\n } else if (!/^https?:\\/\\/.+/i.test(trimmed)) {\n errors.push(`Đường dẫn tệp '${trimmed}' không hợp lệ. Phải là URL HTTP hoặc HTTPS.`);\n }\n\n const cleanUrl = trimmed.split(\"?\")[0].toLowerCase();\n if (!cleanUrl.endsWith(\".txt\") && !cleanUrl.endsWith(\".csv\")) {\n errors.push(\"Tệp danh sách số điện thoại phải có định dạng .txt hoặc .csv.\");\n }\n }\n\n const isHashRaw = raw.isHash !== undefined ? String(raw.isHash).trim() : \"0\";\n if (isHashRaw !== \"0\" && isHashRaw !== \"1\") {\n errors.push(`Giá trị 'isHash' không hợp lệ: '${raw.isHash}'. Chỉ hỗ trợ '0' (danh sách SĐT thô) hoặc '1' (danh sách đã băm).`);\n }\n\n const cleanData: ZaloAdsUploadCustomAudiencePhoneListRequest = {\n File: file as any,\n isHash: isHashRaw as \"0\" | \"1\",\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n/**\n * Router kiểm tra tính hợp lệ dữ liệu tạo Custom Audience tổng hợp theo caType (POST /api/ad/audience).\n */\nexport function validateCreateCustomAudienceRequest(\n input: unknown\n): ValidationResult<ZaloAdsCreateCustomAudienceRequest> {\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu tạo đối tượng tùy chỉnh (Custom Audience) phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const caType = Number(raw.caType);\n\n switch (caType) {\n case 1:\n return validateCreateSavedAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 3:\n return validateCreatePhoneAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 6:\n return validateCreateLookalikeAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 12:\n return validateCreateFormEventAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 11:\n return validateCreateMessageOaEventAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 14:\n return validateCreateMessagePersonalEventAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n default: {\n const errors: string[] = [];\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name) {\n errors.push(\"Tên tập đối tượng ('name') là bắt buộc.\");\n } else if (name.length > 100) {\n errors.push(`Tên tập đối tượng không được vượt quá 100 ký tự (hiện tại: ${name.length} ký tự).`);\n }\n if (!Number.isInteger(caType) || caType <= 0) {\n errors.push(`Loại đối tượng tùy chỉnh ('caType') không hợp lệ: ${raw.caType}.`);\n }\n if (!raw.targeting || typeof raw.targeting !== \"object\") {\n errors.push(\"Cấu hình nhắm mục tiêu ('targeting') là bắt buộc.\");\n }\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? (raw as unknown as ZaloAdsCreateCustomAudienceRequest) : undefined,\n };\n }\n }\n}\n\n/**\n * Gom nhóm toàn bộ Validators cho Targeting & Audiences APIs.\n */\nexport const ZaloAudiencesValidator = {\n createCustomAudience: validateCreateCustomAudienceRequest,\n createSavedAudience: validateCreateSavedAudienceRequest,\n createPhoneAudience: validateCreatePhoneAudienceRequest,\n createLookalikeAudience: validateCreateLookalikeAudienceRequest,\n createFormEventAudience: validateCreateFormEventAudienceRequest,\n createMessageOaEventAudience: validateCreateMessageOaEventAudienceRequest,\n createMessagePersonalEventAudience: validateCreateMessagePersonalEventAudienceRequest,\n estimateAudience: validateEstimateAudienceRequest,\n uploadPhoneList: validateUploadCustomAudiencePhoneListRequest,\n validateUploadPhoneList: validateUploadCustomAudiencePhoneListRequest,\n validateUploadCustomAudiencePhoneList: validateUploadCustomAudiencePhoneListRequest,\n} as const;\n","/** DTOs for Zalo Ads. Request fields are flattened; services route them automatically. */\r\nimport type { FileInput } from \"../types\";\r\n\r\n/** Một tin nhắn con được gửi khi người dùng chọn nút tư vấn của kịch bản. */\r\nexport class ZaloAdsFlowChildMessageDto {\r\n /** Mẫu Zalo đã xác minh dùng 8 cho tin nhắn văn bản trong nhánh. */\r\n type!: 8;\r\n /** Nội dung phản hồi trong nhánh. */\r\n text!: string;\r\n}\r\n\r\n/** Nút hành động trong một tin nhắn kịch bản. */\r\nexport class ZaloAdsFlowButtonDto {\r\n /** 3 = Gửi tin nhắn vào nhánh hội thoại; 10 = Mở website; 12 = Thực hiện cuộc gọi. */\r\n type!: 3 | 10 | 12 | number;\r\n /** Nhãn nút hiển thị cho người dùng. */\r\n text!: string;\r\n /** URL website; bắt buộc với type 10. */\r\n url?: string;\r\n /** Cờ của nút website; dùng true với type 10. */\r\n editable?: boolean;\r\n /** Số hotline, bắt buộc khi type là 12. */\r\n phone?: string;\r\n /** Nhánh tin nhắn, bắt buộc khi type là 3. Với type 10 hoặc 12, để null hoặc bỏ qua. */\r\n messages?: ZaloAdsFlowChildMessageDto[] | null;\r\n}\r\n\r\n/** Một bước tin nhắn trong kịch bản. */\r\nexport class ZaloAdsFlowMessageDto {\r\n /** 1 = Tin nhắn văn bản; 2 = Tin nhắn kèm hình ảnh. */\r\n type!: number;\r\n /** Nội dung tin nhắn, tối đa 1961 ký tự. Hỗ trợ biến: {{user_name}}, {{page_name}}, {{user_gender}}, {{user_id}}, {{page_id}}, {{date}}, {{datetime}}. */\r\n text!: string;\r\n /** URL media hoặc null với tin nhắn văn bản thuần. Bắt buộc và không được null khi type = 2. */\r\n url?: string | null;\r\n /** Các nút đi kèm tin nhắn. */\r\n buttons?: ZaloAdsFlowButtonDto[];\r\n}\r\n\r\n/** Tạo một kịch bản tin nhắn mới và nhận ZaloFlowId để gắn vào quảng cáo Tin nhắn. */\r\nexport class ZaloAdsCreateFlowRequest {\r\n /** ID Official Account sở hữu kịch bản. */\r\n oaId!: number;\r\n /** Luôn null khi tạo kịch bản mới. */\r\n id!: null;\r\n /** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */\r\n name!: string;\r\n /** Các tin nhắn được gửi theo thứ tự trong kịch bản. */\r\n messages!: ZaloAdsFlowMessageDto[];\r\n}\r\n\r\nexport class ZaloAdsCreateFlowResponse {\r\n /** 0 khi tạo thành công; 1 khi lỗi (ví dụ: đã tới hạn mức 20 kịch bản). */\r\n code!: number;\r\n /** Thông báo lỗi từ Zalo Ads khi code khác 0. */\r\n msg?: string;\r\n /** ID kịch bản mới, truyền vào data.ZaloFlowId khi cập nhật quảng cáo Tin nhắn. */\r\n data?: { id: number };\r\n}\r\n\r\n/** Cập nhật kịch bản tin nhắn có sẵn của Official Account, gồm tin nhắn văn bản hoặc ảnh, các biến động và nút tương tác. Đây là mutation tool thuộc lane zalo-ads-message; dùng khi đã có Flow ID và cần thay đổi nội dung mà vẫn giữ liên kết quảng cáo. */\r\nexport type ZaloAdsUpdateFlowRequest = {\r\n /** ID Flow cần cập nhật. */\r\n id: number;\r\n /** Tên kịch bản; giao diện hiện giới hạn tối đa 27 ký tự. */\r\n name: string;\r\n /** ID Official Account sở hữu kịch bản. */\r\n oaId: number;\r\n /** Chuỗi tin nhắn của kịch bản. */\r\n messages: ZaloAdsFlowMessageDto[];\r\n};\r\n\r\nexport type ZaloAdsUpdateFlowResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: {\r\n id?: number;\r\n };\r\n};\r\n\r\n/**\r\n * Chế độ phân phối ngân sách quảng cáo trên Zalo Ads (Settings.DeliveryType):\r\n * - 0: Tiêu chuẩn (Standard) - Phân phối ngân sách đồng đều suốt toàn bộ thời gian chạy quảng cáo.\r\n * - 1: Tăng tốc (SpeedUp) - Phân phối quảng cáo nhanh nhất có thể cho tới khi cạn ngân sách.\r\n * \r\n * Lưu ý: Chỉ xuất hiện và có hiệu lực khi Price.LimitType = 1 (Toàn lịch chạy).\r\n */\r\nexport type ZaloAdsDeliveryType = 0 | 1;\r\n\r\nexport interface ZaloAdsAdPriceSettingsDto {\r\n /**\r\n * Mức giá đặt thầu (VNĐ).\r\n * - Đặt 0 khi chọn đấu thầu tự động hoặc khi Price.Type = 5 (CPA - Lượt liên hệ).\r\n * - Bắt buộc > 0 khi chọn đấu thầu thủ công (CPC).\r\n */\r\n Bid: number;\r\n /**\r\n * Phương thức tính tiền:\r\n * - 1: Lượt hiển thị (CPM) - Website Ads legacy.\r\n * - 2: Lượt nhấn (CPC) - Website, Form, Message, OA, Video, Commerce, Article.\r\n * - 5: Lượt liên hệ (CPA) - Dành riêng cho Quảng cáo Tin nhắn (Type 30) khi tối ưu theo lượt khách nhắn tin liên hệ.\r\n */\r\n Type: number;\r\n /**\r\n * Hạn mức chi tiêu (VNĐ).\r\n * - Quảng cáo Tin nhắn yêu cầu ngân sách tối thiểu 600,000 VNĐ.\r\n */\r\n Limit: number;\r\n /**\r\n * Phạm vi áp dụng ngân sách (ZaloAdsPriceLimitType):\r\n * - 1: Toàn lịch chạy (LIFE_TIME - áp dụng ngân sách tổng cho toàn bộ thời gian chạy).\r\n * - 2: Mỗi ngày (DAILY - hạn mức ngân sách phân bổ theo từng ngày).\r\n */\r\n LimitType: number;\r\n /**\r\n * Phương thức chi tiêu / tối ưu hóa:\r\n * - 0: Đặt giá thầu thủ công (Manual Bid).\r\n * - 1: Tự động tối ưu chi phí theo ngân sách (Total budget / Auto optimize, bắt buộc khi Type = 5 CPA).\r\n */\r\n SpendingMethod: number;\r\n}\r\n\r\nexport interface ZaloAdsAdMultiImageItemDto {\r\n Url: string;\r\n Title?: string;\r\n Description?: string;\r\n TargetUrl?: string;\r\n}\r\n\r\nexport interface ZaloAdsAdImageSettingsDto {\r\n LogoUrl?: string;\r\n LandscapeCoverUrl?: string;\r\n SquareCoverUrl?: string;\r\n VideoUrl?: string;\r\n VideoDuration?: number;\r\n MediaId?: number;\r\n MultiImages?: Array<ZaloAdsAdMultiImageItemDto>;\r\n}\r\n\r\nexport interface ZaloAdsAdInfoSettingsDto {\r\n Title?: string;\r\n Description?: string;\r\n Caption?: string;\r\n /**\r\n * Chú thích mở rộng (không bắt buộc).\r\n * - Quy chuẩn độ dài: Tối thiểu 90 ký tự, tối đa 2000 ký tự (90 - 2,000 ký tự).\r\n * - Nếu để trống \"\" hoặc không truyền: Hợp lệ.\r\n * - Nếu đã nhập: Bắt buộc từ 90 đến 2,000 ký tự.\r\n * - Tự động kích hoạt mã bố cục mở rộng XTemplates = 49 (LONG_CAPTION).\r\n */\r\n LongCaption?: string;\r\n Action?: number;\r\n ButtonText?: string;\r\n MoreInfo?: string;\r\n TargetUrl?: string | { Url?: string; DisplayText?: string };\r\n Phone?: string;\r\n SupportPhone?: string;\r\n Address?: string;\r\n XTemplates?: Array<number>;\r\n Template?: number;\r\n WebsiteCategories?: Array<number>;\r\n AdtimaAdCategories?: Array<number>;\r\n Files?: Array<unknown>;\r\n}\r\n\r\nexport interface ZaloAdsAdAppInfoSettingsDto {\r\n AppType?: number;\r\n OsType?: number;\r\n StoreUrl?: string;\r\n}\r\n\r\nexport interface ZaloAdsAdTargetingProvinceItemDto {\r\n /**\r\n * Mã định danh Tỉnh/Thành phố theo danh mục 34 Cụm Tỉnh mới sau sáp nhập 2026 (`newProvinces` trên Zalo Ads).\r\n * \r\n * QUAN TRỌNG: Giao diện Zalo Ads Angular Web chỉ phân giải cây Xã/Phường theo 34 mã cụm này.\r\n * Nếu truyền mã tỉnh lẻ đã bị sáp nhập (ví dụ: 'VN75' - Bình Dương, 'VN45' - Vũng Tàu, 'VN76' - Bình Phước),\r\n * giao diện web sẽ bị lỗi ngoại lệ popup: 'Invalid wards params'.\r\n * \r\n * Quy tắc ánh xạ mã cụm tỉnh:\r\n * - Cụm 'VN20' (Hồ Chí Minh): Bao gồm TP.HCM, Bình Dương ('VN75'), Bà Rịa - Vũng Tàu ('VN45').\r\n * - Cụm 'VN43' (Đồng Nai): Bao gồm Đồng Nai, Bình Phước ('VN76').\r\n * - Cụm 'VN44' (Hà Nội): Giữ nguyên không sáp nhập.\r\n * - Cụm 'VN33' (Tây Ninh): Bao gồm Tây Ninh, Long An ('VN24').\r\n * - Cụm 'VN01' (An Giang): Bao gồm An Giang, Kiên Giang ('VN21').\r\n * - Cụm 'VN87' (Cần Thơ): Bao gồm Cần Thơ, Sóc Trăng ('VN65'), Hậu Giang ('VN93').\r\n * - Cụm 'VN77' (Cà Mau): Bao gồm Cà Mau, Bạc Liêu ('VN73').\r\n * - Cụm 'VN09' (Đồng Tháp): Bao gồm Đồng Tháp, Tiền Giang ('VN37').\r\n * - Cụm 'VN69' (Vĩnh Long): Bao gồm Vĩnh Long, Bến Tre ('VN03'), Trà Vinh ('VN67').\r\n */\r\n Id: string;\r\n /** Danh sách mã xã/phường mục tiêu (mảng rỗng [] biểu thị chọn toàn bộ tỉnh/thành). */\r\n Districts: Array<number | string>;\r\n}\r\n\r\nexport interface ZaloAdsAdTargetingRegionItemDto {\r\n /**\r\n * Mã vùng miền:\r\n * - 1: Miền Bắc (18 cụm tỉnh mới / 28 tỉnh cũ)\r\n * - 2: Miền Trung (8 cụm tỉnh mới / 16 tỉnh cũ)\r\n * - 3: Miền Nam (8 cụm tỉnh mới / 19 tỉnh cũ)\r\n */\r\n Id: number;\r\n /**\r\n * Danh sách tỉnh/thành phố được chọn trong vùng.\r\n * Theo cơ chế compressAdData của Zalo Ads Client Engine:\r\n * Nếu mảng Provinces là rỗng ([]), hệ thống hiểu là CHỌN TOÀN BỘ VÙNG MIỀN ĐÓ.\r\n */\r\n Provinces: Array<ZaloAdsAdTargetingProvinceItemDto>;\r\n}\r\n\r\nexport interface ZaloAdsAdTargetingLocationContainerDto {\r\n Includes: Array<ZaloAdsAdTargetingRegionItemDto>;\r\n Excludes: Array<ZaloAdsAdTargetingRegionItemDto>;\r\n}\r\n\r\nexport interface ZaloAdsAdLocationSettingsDto {\r\n Cities?: Array<unknown>;\r\n Addresses?: Array<unknown>;\r\n /** Nhắm chọn cấp Tỉnh/Thành theo cấu trúc phân cấp Vùng miền. */\r\n DistrictTargeting?: ZaloAdsAdTargetingLocationContainerDto;\r\n /** Nhắm chọn chi tiết cấp Phường/Xã mới theo quy chuẩn 2026. */\r\n WardTargeting?: ZaloAdsAdTargetingLocationContainerDto;\r\n /** Cờ đánh dấu đã chuyển đổi sang cấp xã/phường. */\r\n IsConvertedToWard?: boolean;\r\n}\r\n\r\nexport interface ZaloAdsAdTargetingSettingsDto {\r\n Gender?: number;\r\n AgeRanges?: Array<number>;\r\n NewAgeRanges?: Array<number>;\r\n Location?: ZaloAdsAdLocationSettingsDto;\r\n Locations?: string;\r\n Provinces?: Array<number>;\r\n DistrictsTargeting?: string;\r\n WardsTargeting?: string;\r\n Platforms?: Array<number>;\r\n NetworkTypes?: Array<number>;\r\n Os?: Array<number>;\r\n OsTypes?: Array<number>;\r\n AdvanceTargeting?: {\r\n Includes?: Array<number>;\r\n Excludes?: Array<number>;\r\n };\r\n AdvanceTargetings?: Array<number>;\r\n CustomAudienceId?: number;\r\n ExcludedAudienceId?: number;\r\n Retargeting?: string;\r\n DmpAudience?: string;\r\n PhoneList?: Array<unknown>;\r\n CustomAudiences?: Array<number>;\r\n ExcludeCustomAudiences?: Array<number>;\r\n IncludedAudiences?: {\r\n Phones?: Array<unknown>;\r\n LeadSignal?: Array<unknown>;\r\n };\r\n ExcludedAudiences?: {\r\n Phones?: Array<unknown>;\r\n Forms?: Array<unknown>;\r\n Messages?: Array<unknown>;\r\n FormEvents?: Array<unknown>;\r\n MessageOAs?: Array<unknown>;\r\n MessageNonOAEvents?: Array<unknown>;\r\n } | null;\r\n}\r\n\r\nexport interface ZaloAdsAdZVideoSettingsDto {\r\n Url: string;\r\n Duration: number;\r\n Src: number;\r\n Thumbnail: string;\r\n Description: string;\r\n ChannelName: string;\r\n ChannelAvt: string;\r\n VideoThumbnail: string;\r\n ThumbnailIndex: number | null;\r\n}\r\n\r\nexport interface ZaloAdsAdSettingsDto {\r\n Image: ZaloAdsAdImageSettingsDto;\r\n Price: ZaloAdsAdPriceSettingsDto;\r\n AdInfo: ZaloAdsAdInfoSettingsDto;\r\n AppInfo?: ZaloAdsAdAppInfoSettingsDto;\r\n Targeting: ZaloAdsAdTargetingSettingsDto;\r\n ZVideo?: ZaloAdsAdZVideoSettingsDto;\r\n VideoPlatform?: number;\r\n Rating?: number;\r\n NewFeatures?: Array<number>;\r\n CreatedClientVersion?: number;\r\n /**\r\n * Phương thức phân phối quảng cáo (0: Tiêu chuẩn - Standard, 1: Tăng tốc - SpeedUp).\r\n * Chỉ có hiệu lực khi Price.LimitType = 1 (Toàn lịch chạy).\r\n */\r\n DeliveryType?: ZaloAdsDeliveryType | number;\r\n}\r\n\r\nexport interface ZaloAdsAdUpdatePayloadDto {\r\n AdId: number;\r\n CampaignId: number;\r\n MemberId: number;\r\n RowVersion: number;\r\n AdName: string;\r\n Type: number;\r\n Settings: ZaloAdsAdSettingsDto;\r\n Status: number;\r\n StartDate: number;\r\n EndDate: number;\r\n ZaloFlowId?: number;\r\n ZaloPageId?: number;\r\n ZaloFormId?: string;\r\n ZaloFeedId?: string | number;\r\n ZaloVideoId?: number;\r\n MiniPageId?: number;\r\n UseConversion?: ZaloAdsUseConversionValue | number;\r\n ConversionId?: number;\r\n Report?: Record<string, number>;\r\n}\r\n\r\n/** Danh mục mã hành động / nút CTA chuẩn trên Zalo Ads */\r\nexport const ZaloAdsActionType = {\r\n DAT_NGAY: 1,\r\n MUA_NGAY: 2,\r\n THU_NGAY: 3,\r\n TAI_NGAY: 4,\r\n XEM_THEM: 5,\r\n NGHE_NGAY: 6,\r\n CHOI_NGAY: 7,\r\n DANG_KY: 8,\r\n GOI_DIEN: 9,\r\n /** Dành riêng cho Quảng cáo Official Account (Type 2) */\r\n QUAN_TAM_OA: 6,\r\n} as const;\r\n\r\n/** Danh mục mã nguồn video trên Zalo Ads (Settings.ZVideo.Src) */\r\nexport const ZaloAdsVideoSrc = {\r\n UNUSED: -1,\r\n /** Sử dụng mã Zalo Video được cấp từ kênh */\r\n VIDEO_CODE: 1,\r\n /** Tự tải video lên hoặc chọn từ Thư viện Media */\r\n SELF_UPLOAD: 2,\r\n} as const;\r\n\r\nexport type ZaloAdsVideoSrcValue = typeof ZaloAdsVideoSrc[keyof typeof ZaloAdsVideoSrc];\r\n\r\n/** Danh mục chu kỳ áp dụng ngân sách trên Zalo Ads (Settings.Price.LimitType) - Alias của ZaloAdsPriceLimitType */\r\nexport const ZaloAdsBudgetScheduleType = {\r\n /** Toàn lịch chạy */\r\n TOTAL_SCHEDULE: 1,\r\n /** Mỗi ngày */\r\n DAILY: 2,\r\n} as const;\r\n\r\nexport type ZaloAdsBudgetScheduleTypeValue = typeof ZaloAdsBudgetScheduleType[keyof typeof ZaloAdsBudgetScheduleType];\r\n\r\n/** Danh mục mã khoảng tuổi nhắm chọn đối tượng trên Zalo Ads */\r\nexport const ZaloAdsAgeRangeId = {\r\n UNDER_18: 10282,\r\n FROM_18_TO_24: 10283,\r\n FROM_25_TO_34: 10284,\r\n FROM_35_TO_44: 10285,\r\n FROM_45_TO_54: 10286,\r\n FROM_55_TO_64: 10287,\r\n OVER_64: 10288,\r\n} as const;\r\n\r\n/** Danh mục mã hệ điều hành */\r\nexport const ZaloAdsOsId = {\r\n ANDROID: 0,\r\n IOS: 1,\r\n PC: 3,\r\n} as const;\r\n\r\nexport type ZaloAdsOsIdValue = typeof ZaloAdsOsId[keyof typeof ZaloAdsOsId];\r\n\r\n/** Danh mục mã 3 Vùng miền chuẩn trên Zalo Ads Targeting Engine */\r\nexport const ZaloAdsRegionId = {\r\n /** Miền Bắc (28 tỉnh/thành phố) */\r\n NORTH: 1,\r\n /** Miền Trung (16 tỉnh/thành phố) */\r\n CENTRAL: 2,\r\n /** Miền Nam (19 tỉnh/thành phố) */\r\n SOUTH: 3,\r\n} as const;\r\n\r\nexport type ZaloAdsRegionIdValue = typeof ZaloAdsRegionId[keyof typeof ZaloAdsRegionId];\r\n\r\n/**\r\n * Danh mục mã Tỉnh/Thành phố chuẩn trên Zalo Ads Targeting Engine (theo chuẩn ISO 3166-2:VN tiền tố 'VN')\r\n */\r\nexport const ZaloAdsProvinceCode = {\r\n // Miền Bắc (Region 1 - 28 tỉnh/thành)\r\n HANOI: 'VN44',\r\n HAI_PHONG: 'VN13',\r\n BAC_NINH: 'VN74',\r\n QUANG_NINH: 'VN30',\r\n HAI_DUONG: 'VN79',\r\n HUNG_YEN: 'VN81',\r\n VINH_PHUC: 'VN86',\r\n THAI_NGUYEN: 'VN85',\r\n BAC_GIANG: 'VN71',\r\n PHU_THO: 'VN83',\r\n NAM_DINH: 'VN82',\r\n THAI_BINH: 'VN35',\r\n NINH_BINH: 'VN59',\r\n THANH_HOA: 'VN34',\r\n NGHE_AN: 'VN58',\r\n HA_TINH: 'VN52',\r\n HOA_BINH: 'VN53',\r\n SON_LA: 'VN32',\r\n DIEN_BIEN: 'VN92',\r\n LAI_CHAU: 'VN89',\r\n LAO_CAI: 'VN90',\r\n YEN_BAI: 'VN70',\r\n TUYEN_QUANG: 'VN68',\r\n HA_GIANG: 'VN50',\r\n CAO_BANG: 'VN05',\r\n BAC_KAN: 'VN72',\r\n LANG_SON: 'VN39',\r\n HA_NAM: 'VN80',\r\n\r\n // Miền Trung (Region 2 - 16 tỉnh/thành)\r\n DA_NANG: 'VN78',\r\n THUA_THIEN_HUE: 'VN66',\r\n QUANG_NAM: 'VN84',\r\n QUANG_NGAI: 'VN63',\r\n BINH_DINH: 'VN46',\r\n PHU_YEN: 'VN61',\r\n KHANH_HOA: 'VN54',\r\n NINH_THUAN: 'VN60',\r\n BINH_THUAN: 'VN47',\r\n KON_TUM: 'VN55',\r\n GIA_LAI: 'VN49',\r\n DAK_LAK: 'VN88',\r\n DAK_NONG: 'VN91',\r\n LAM_DONG: 'VN23',\r\n QUANG_BINH: 'VN62',\r\n QUANG_TRI: 'VN64',\r\n\r\n // Miền Nam (Region 3 - 19 tỉnh/thành)\r\n HO_CHI_MINH: 'VN20',\r\n BINH_DUONG: 'VN75',\r\n DONG_NAI: 'VN43',\r\n BA_RIA_VUNG_TAU: 'VN45',\r\n LONG_AN: 'VN24',\r\n TIEN_GIANG: 'VN37',\r\n BEN_TRE: 'VN03',\r\n DONG_THAP: 'VN09',\r\n VINH_LONG: 'VN69',\r\n CAN_THO: 'VN87',\r\n HAU_GIANG: 'VN93',\r\n AN_GIANG: 'VN01',\r\n KIEN_GIANG: 'VN21',\r\n SOC_TRANG: 'VN65',\r\n BAC_LIEU: 'VN73',\r\n CA_MAU: 'VN77',\r\n TAY_NINH: 'VN33',\r\n BINH_PHUOC: 'VN76',\r\n TRA_VINH: 'VN67',\r\n} as const;\r\n\r\nexport type ZaloAdsProvinceCodeValue = typeof ZaloAdsProvinceCode[keyof typeof ZaloAdsProvinceCode];\r\n\r\n/**\r\n * Danh mục kiểu phân phối ngân sách quảng cáo (\"Cách phân phối\" trên giao diện Zalo Ads):\r\n * Trường dữ liệu lưu trữ tại: `Settings.DeliveryType` (kiểu số nguyên 0 hoặc 1).\r\n *\r\n * - STANDARD (0): Tiêu chuẩn (Paced Delivery)\r\n * Thuật toán Zalo Ads rải đều ngân sách xuyên suốt các khung giờ trong ngày/toàn lịch chạy\r\n * dựa theo lưu lượng thị trường và tỷ lệ giờ cao điểm. Tự động điều tiết hãm tốc độ cắn tiền\r\n * nếu phát hiện ngân sách tiêu xài quá nhanh. Phù hợp duy trì thương hiệu, ổn định chi phí CPA.\r\n *\r\n * - SPEED_UP / ACCELERATED (1): Tăng tốc (Uncapped Pacing)\r\n * Gỡ bỏ hoàn toàn bộ điều tiết tốc độ. Miễn là có phiên đấu giá (auction) phù hợp với giá thầu\r\n * và tệp đối tượng nhắm chọn, hệ thống sẽ phân phối tối đa ngay lập tức cho đến khi cạn kiệt ngân sách.\r\n * Phù hợp cho chiến dịch Flash Sale, sự kiện ngắn, hoặc cần tối đa hóa tiếp cận trong thời gian ngắn.\r\n *\r\n * ĐIỀU KIỆN NGẦM ĐỂ HIỂN THỊ TRÊN UI (hàm `shouldHaveDeliveryType` trong mã nguồn Angular):\r\n * 1. `Price.Type in [CPC (2), CPA (5)]`: Hình thức tính tiền phải là CPC hoặc CPA.\r\n * 2. `Price.LimitType === LIFE_TIME (1)`: Bắt buộc chọn ngân sách \"Toàn lịch chạy\" (không áp dụng cho ngân sách mỗi ngày).\r\n * 3. `validDaysRun(StartDate, EndDate) >= 2`: Thời gian chạy chiến dịch tối thiểu từ 2 ngày trở lên.\r\n */\r\nexport const ZaloAdsDeliveryType = {\r\n /** Tiêu chuẩn (0): Phân phối đồng đều nhất có thể theo giờ cao điểm (Standard). */\r\n STANDARD: 0,\r\n /** Tăng tốc (1): Phân phối nhanh nhất có thể để tối đa hóa tiếp cận (SpeedUp). */\r\n SPEED_UP: 1,\r\n /** Alias tương thích ngược cho SPEED_UP (1). */\r\n ACCELERATED: 1,\r\n} as const;\r\n\r\nexport type ZaloAdsDeliveryTypeValue = typeof ZaloAdsDeliveryType[keyof typeof ZaloAdsDeliveryType];\r\n\r\n/**\r\n * Danh mục phương thức phân phối ngân sách chi tiêu (`Settings.Price.SpendingMethod`):\r\n * - STANDARD (0): Tiêu chuẩn (rải đều ngân sách).\r\n * - FAST / ACCELERATED (1): Nhanh / Tăng tốc (ưu tiên thắng thầu và phân phối tối đa ngay lập tức).\r\n */\r\nexport const ZaloAdsSpendingMethod = {\r\n /** Tiêu chuẩn (0): Rải đều ngân sách xuyên suốt ngày. */\r\n STANDARD: 0,\r\n /** Tăng tốc (1): Phân phối nhanh, ưu tiên thắng thầu ngay khi có phiên đấu giá. */\r\n FAST: 1,\r\n /** Alias cho FAST (1). */\r\n ACCELERATED: 1,\r\n} as const;\r\n\r\nexport type ZaloAdsSpendingMethodValue = typeof ZaloAdsSpendingMethod[keyof typeof ZaloAdsSpendingMethod];\r\n\r\n/**\r\n * Danh mục phương thức tính tiền quảng cáo (`Settings.Price.Type`):\r\n * - CPM (1): Lượt hiển thị (áp dụng cho Display Ads hoặc tối ưu hiển thị).\r\n * - CPC (2): Lượt nhấn (Click) - Chuẩn cho Website Ads, Commerce Ads.\r\n * - CPI (3): Lượt cài đặt ứng dụng (App Install).\r\n * - CPF (4): Lượt quan tâm Official Account (Follow).\r\n * - CPA (5): Lượt liên hệ / chuyển đổi mục tiêu (Lead / Message).\r\n * - CPO (6): Lượt đặt hàng (Order).\r\n * - CPV (7): Lượt xem video hoàn tất (Complete View).\r\n * - CPD (8): Chi phí cố định theo ngày.\r\n * - CPV1S (9): Lượt xem video từ 1 giây.\r\n */\r\nexport const ZaloAdsPriceType = {\r\n CPM: 1,\r\n CPC: 2,\r\n CPI: 3,\r\n CPF: 4,\r\n CPA: 5,\r\n CPO: 6,\r\n CPV: 7,\r\n CPD: 8,\r\n CPV1S: 9,\r\n} as const;\r\n\r\nexport type ZaloAdsPriceTypeValue = typeof ZaloAdsPriceType[keyof typeof ZaloAdsPriceType];\r\n\r\n/**\r\n * Danh mục kiểu áp dụng ngân sách (`Settings.Price.LimitType`):\r\n * - LIFE_TIME (1): Toàn lịch chạy (ngân sách tổng cho toàn bộ thời gian chiến dịch, tối thiểu 600.000 VNĐ).\r\n * - DAILY (2): Mỗi ngày (ngân sách giới hạn theo từng ngày).\r\n */\r\nexport const ZaloAdsPriceLimitType = {\r\n /** Áp dụng ngân sách cho toàn lịch chạy (Life time budget). */\r\n LIFE_TIME: 1,\r\n /** Áp dụng ngân sách cho mỗi ngày (Daily budget). */\r\n DAILY: 2,\r\n} as const;\r\n\r\nexport type ZaloAdsPriceLimitTypeValue = typeof ZaloAdsPriceLimitType[keyof typeof ZaloAdsPriceLimitType];\r\n\r\n/**\r\n * Danh mục mã giao diện bố cục hiển thị mở rộng (`Settings.AdInfo.XTemplates`):\r\n * Checkbox \"Hiển thị nhiều hình ảnh\" trên UI Zalo Ads chỉ được bật khi mảng XTemplates\r\n * chứa đồng thời cả 42 (Carousel) và 43 (Album): [42, 43].\r\n */\r\nexport const ZaloAdsXTemplates = {\r\n /** Định dạng thẻ quay vòng lướt ngang nhiều hình ảnh. */\r\n CAROUSEL: 42,\r\n /** Định dạng bộ sưu tập album ảnh (lưới 4 ảnh). */\r\n ALBUM: 43,\r\n /** Định dạng video tự động phát trên Feed. */\r\n ZALO_VIDEO: 44,\r\n /** Định dạng ảnh dọc toàn màn hình. */\r\n PORTRAIT_IMAGE: 45,\r\n /** Định dạng ảnh đơn truyền thống (1024x533). */\r\n SINGLE_IMAGE: 46,\r\n /** Định dạng ảnh bìa cho quảng cáo video. */\r\n COVER_IMAGE_FOR_VIDEO_AD: 47,\r\n /** Định dạng ảnh vuông. */\r\n SQUARE_IMAGE: 48,\r\n /** Định dạng chú thích nội dung dài (tối đa 2.000 ký tự). */\r\n LONG_CAPTION: 49,\r\n} as const;\r\n\r\nexport type ZaloAdsXTemplatesValue = typeof ZaloAdsXTemplates[keyof typeof ZaloAdsXTemplates];\r\n\r\n/**\r\n * Danh mục mã tỉ lệ cắt ảnh chuẩn (`Settings.Image.ExtraImgs[i].Crops[j].Ratio`):\r\n * Ma trận 8 lát cắt bắt buộc cho bộ 4 ảnh Album + Carousel:\r\n * - Ảnh 0 (Ảnh bìa): Bắt buộc đủ 3 lát cắt: RATIO_4_3 (1), RATIO_2_1 (2 - Bìa Album), RATIO_1_1 (4).\r\n * (Nếu thiếu RATIO_2_1, UI sẽ báo lỗi: \"Thiếu ảnh cắt tỉ lệ album\").\r\n * - Ảnh 1: Bắt buộc 2 lát cắt: RATIO_4_3 (1), RATIO_1_1 (4).\r\n * - Ảnh 2: Bắt buộc 2 lát cắt: RATIO_4_3 (1), RATIO_1_1 (4).\r\n * - Ảnh 3: Bắt buộc 1 lát cắt: RATIO_1_1 (4).\r\n */\r\nexport const ZaloAdsImageRatio = {\r\n /** Tỉ lệ 16:9 (1024x576 px - Video / Banner phong cảnh). */\r\n RATIO_16_9: 0,\r\n /** Tỉ lệ 4:3 (1024x768 px - Ảnh phụ Album / Carousel). */\r\n RATIO_4_3: 1,\r\n /** Tỉ lệ 2:1 (1024x512 px - ẢNH BÌA NGANG BẮT BUỘC CỦA ALBUM). */\r\n RATIO_2_1: 2,\r\n /** Tỉ lệ 3:2. */\r\n RATIO_3_2: 3,\r\n /** Tỉ lệ 1:1 (1024x1024 px - Ảnh vuông). */\r\n RATIO_1_1: 4,\r\n} as const;\r\n\r\nexport type ZaloAdsImageRatioValue = typeof ZaloAdsImageRatio[keyof typeof ZaloAdsImageRatio];\r\n\r\n/**\r\n * Danh mục cờ và nguồn dữ liệu tối ưu hóa chuyển đổi (`UseConversion`):\r\n * - NOT_USE (0): Không chọn pixel - Tắt tối ưu hóa chuyển đổi. Hệ thống chỉ phân phối theo giá thầu lượt click (CPC) hoặc hiển thị (CPM) mà không quan tâm hành vi người dùng trên website.\r\n * - USE (1): Pixel của tôi - Nguồn dữ liệu từ Zalo Pixel cá nhân do nhà quảng cáo tự chèn mã JavaScript (window.za(...)) vào mã nguồn website (ví dụ: https://redai.vn). Bắt buộc đi kèm `ConversionId` từ GET /api/conversion/all.\r\n * - LADI_PAGE (2): Pixel liên kết Ladipage - Dành cho Landing Page dựng bằng nền tảng LadiPage đã tích hợp Zalo Pixel sẵn. Hệ thống tự động nhận diện sự kiện chuẩn mà không cần tạo conversion thủ công.\r\n * - MINI_APP (3): Zalo Mini App - Dành cho các chiến dịch hướng người dùng vào ứng dụng Zalo Mini App.\r\n * - USE_OFF (-1): Cờ lưu nháp khi tạm thời tắt hoặc hủy chọn Pixel cá nhân.\r\n * - LADI_PAGE_OFF (-2): Cờ lưu nháp khi tắt liên kết Pixel Ladipage.\r\n * - MINI_APP_OFF (-3): Cờ lưu nháp khi tắt liên kết Zalo Mini App.\r\n */\r\nexport const ZaloAdsUseConversion = {\r\n /** Không chọn pixel (0): Tắt tối ưu hóa chuyển đổi. */\r\n NOT_USE: 0,\r\n /** Pixel của tôi (1): Zalo Pixel tự host chèn script, cần kèm ConversionId. */\r\n USE: 1,\r\n /** Pixel liên kết Ladipage (2): Landing Page đối tác LadiPage. */\r\n LADI_PAGE: 2,\r\n /** Zalo Mini App (3): Ứng dụng Zalo Mini App. */\r\n MINI_APP: 3,\r\n /** Tạm thời tắt Pixel của tôi (-1): Cờ lưu nháp. */\r\n USE_OFF: -1,\r\n /** Tạm thời tắt Pixel Ladipage (-2): Cờ lưu nháp. */\r\n LADI_PAGE_OFF: -2,\r\n /** Tạm thời tắt Pixel Mini App (-3): Cờ lưu nháp. */\r\n MINI_APP_OFF: -3,\r\n} as const;\r\n\r\nexport type ZaloAdsUseConversionValue = typeof ZaloAdsUseConversion[keyof typeof ZaloAdsUseConversion];\r\n\r\n\r\nexport interface ZaloAdsAdMutationResultDto {\r\n AdId?: number;\r\n CampaignId?: number;\r\n Status?: number;\r\n RowVersion?: number;\r\n}\r\n\r\n/** Tham số yêu cầu nhân bản mẫu quảng cáo (POST /zaapi/DuplicateAd) */\r\nexport interface ZaloAdsDuplicateAdRequest {\r\n /** ID mẫu quảng cáo gốc cần nhân bản (bắt buộc). */\r\n adid?: number;\r\n /** Alias cho adid. */\r\n adId?: number;\r\n}\r\n\r\n/** Kết quả phản hồi khi nhân bản mẫu quảng cáo */\r\nexport interface ZaloAdsDuplicateAdResponse {\r\n /** Mã trạng thái: 0 = Thành công, khác 0 = Lỗi */\r\n code: number;\r\n /** Chuỗi thông báo kết quả (chứa ID của Ad mới tạo) */\r\n msg?: string;\r\n /** ID số nguyên của Ad mới vừa được nhân bản */\r\n data: number;\r\n}\r\n\r\nexport interface ZaloAdsCampaignCreatePayloadDto {\r\n name: string;\r\n campaignType: number;\r\n pageId: number;\r\n productId: number;\r\n targetUrl?: string;\r\n articleId?: number;\r\n adtype: number;\r\n budgetType: number;\r\n budgetlimit: number;\r\n limitType: number;\r\n campaignObjective: number;\r\n campaignId: number;\r\n adId: number;\r\n}\n\r\n/** Payload tạo chiến dịch Quảng cáo Commerce (Shop) */\r\nexport interface ZaloAdsCreateCommerceCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account (OA ID) liên kết (bắt buộc > 0) */\r\n pageId: number;\r\n /** ID sản phẩm Zalo Shop liên kết (tùy chọn; mặc định -1 nếu không gắn) */\r\n productId?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Display */\r\nexport interface ZaloAdsCreateDisplayCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo OA (tùy chọn; mặc định -1) */\r\n pageId?: number;\r\n /** URL trang đích của quảng cáo (tùy chọn) */\r\n targetUrl?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Website */\r\nexport interface ZaloAdsCreateWebsiteCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** URL trang đích của website (bắt buộc) */\r\n targetUrl: string;\r\n /** ID Zalo OA (tùy chọn; không bắt buộc) */\r\n pageId?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Biểu mẫu (Lead Form) */\r\nexport interface ZaloAdsCreateFormCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account sở hữu Form (bắt buộc > 0) */\r\n pageId: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Tin nhắn (Message) */\r\nexport interface ZaloAdsCreateMessageCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account nhận tin nhắn (bắt buộc > 0) */\r\n pageId: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Tăng người quan tâm Zalo Official Account */\r\nexport interface ZaloAdsCreateOfficialAccountCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account cần tăng lượt quan tâm (bắt buộc > 0) */\r\n pageId: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Bài viết OA */\r\nexport interface ZaloAdsCreateArticleCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account sở hữu bài viết (bắt buộc > 0) */\r\n pageId: number;\r\n /** ID bài viết trên Zalo OA lấy từ getOwnedArticles (bắt buộc > 0) */\r\n articleId: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Video */\r\nexport interface ZaloAdsCreateVideoCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** URL trang đích của website khi click vào video (bắt buộc) */\r\n targetUrl: string;\r\n /** ID Zalo OA (tùy chọn; không bắt buộc) */\r\n pageId?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n\r\nexport interface ZaloAdsFormSectionTableItemDto {\r\n key: string;\r\n value: string;\r\n}\r\n\r\nexport interface ZaloAdsFormSectionImageItemDto {\r\n url: string;\r\n title?: string;\r\n caption?: string;\r\n}\r\n\r\nexport interface ZaloAdsFormSectionContentDto {\r\n title?: string;\r\n description?: string;\r\n table?: Array<ZaloAdsFormSectionTableItemDto>;\r\n images?: Array<ZaloAdsFormSectionImageItemDto>;\r\n}\r\n\r\nexport interface ZaloAdsFormSectionDto {\r\n type: \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | number;\r\n title: string;\r\n expand: boolean;\r\n disable: boolean;\r\n content: ZaloAdsFormSectionContentDto;\r\n}\r\n\r\nexport interface ZaloAdsFormQuestionUiDto {\r\n icon?: string;\r\n title?: string;\r\n removable?: boolean;\r\n}\r\n\r\nexport interface ZaloAdsFormAnswerDto {\r\n id?: string;\r\n type: \"2\" | \"7\" | \"13\" | number;\r\n value?: string | null;\r\n priority?: number;\r\n placeHolder?: string;\r\n}\r\n\r\nexport interface ZaloAdsFormQuestionDto {\r\n id?: string;\r\n ui?: ZaloAdsFormQuestionUiDto;\r\n type: \"1\" | number;\r\n title: string;\r\n answers: Array<ZaloAdsFormAnswerDto>;\r\n groupIdx?: number;\r\n priority?: number;\r\n isRequired: boolean;\r\n editDisabled?: boolean;\r\n}\r\n\r\nexport interface ZaloAdsCreateFormPayloadDto {\r\n id?: string;\r\n oaId: string;\r\n formName: string;\r\n title?: string;\r\n description?: string;\r\n coverPhoto?: string;\r\n thanks?: string;\r\n gotoText?: string;\r\n gotoActionType?: number;\r\n website?: string;\r\n phone?: string;\r\n submitTitle?: string;\r\n reviewSubmit?: boolean;\r\n oaConsentWidget?: boolean;\r\n useCustomConsent?: boolean;\r\n sections?: Array<ZaloAdsFormSectionDto>;\r\n questions: Array<ZaloAdsFormQuestionDto>;\r\n}\r\n\r\n/** Cập nhật quảng cáo Video; service tự JSON.stringify data rồi gửi form-urlencoded. */\r\nexport class ZaloAdsUpdateVideoAdRequest {\r\n data!: ZaloAdsAdUpdatePayloadDto | string;\r\n est?: string;\r\n isBoostAd?: 0 | 1;\r\n stt?: number;\r\n}\r\n\r\nexport class ZaloAdsUpdateVideoAdResponse {\r\n code!: number;\r\n msg!: string;\r\n data?: ZaloAdsAdMutationResultDto;\r\n}\r\n\r\n/** Lấy danh sách hoặc Flow cụ thể của một Official Account. Dùng flowId khi cần đọc một Flow trước khi cập nhật, hoặc offset và limit khi duyệt danh sách. */\r\nexport type ZaloAdsListFlowsByOfficialAccountRequest = {\r\n /** ID Official Account cần lấy Flow. */\r\n oaId: number;\r\n /** Số Flow tối đa cần trả về. */\r\n limit: number;\r\n /** Vị trí bắt đầu, tính từ 0, khi liệt kê Flow. Không cần gửi khi dùng flowId. */\r\n offset?: number;\r\n /** ID Flow cụ thể cần lấy. Khi gửi tham số này, response extend có thể có index. */\r\n flowId?: number;\r\n};\r\n\r\nexport type ZaloAdsListFlowsByOfficialAccountResponse = {\r\n code: number;\r\n data: Array<{\r\n id: number;\r\n name: string;\r\n createdTime: number;\r\n modified: number;\r\n status: number;\r\n isDraft: boolean;\r\n editable: number;\r\n messages: Array<{\r\n type: number;\r\n text: string;\r\n url?: string;\r\n buttons: Array<{ type: number; text: string; editable: boolean; url?: string; phone?: string; messages: Array<ZaloAdsFlowChildMessageDto> }>;\r\n elements: Array<{ type?: number; title?: string; url?: string }>;\r\n stepId: number;\r\n }>;\r\n }>;\r\n extend: { total: number; index?: number };\r\n};\r\n\r\n/**\r\n * Danh mục mã trạng thái chiến dịch trên Zalo Ads (POST /api/campaign/change-status):\r\n * - OFF (0): Tắt / Dừng chiến dịch (Inactive).\r\n * - ACTIVE (1): Bật / Tiếp tục / Kích hoạt lại chiến dịch (Active).\r\n * - PAUSED (2): Tạm dừng chiến dịch (Lưu ý: Nếu chiến dịch nháp chưa có QC hoạt động sẽ ném HTTP 500).\r\n * - DELETED (-2): Xóa vĩnh viễn chiến dịch.\r\n */\r\nexport const ZaloAdsCampaignStatus = {\r\n OFF: 0,\r\n ACTIVE: 1,\r\n PAUSED: 2,\r\n DELETED: -2,\r\n} as const;\r\n\r\nexport type ZaloAdsCampaignStatusValue = typeof ZaloAdsCampaignStatus[keyof typeof ZaloAdsCampaignStatus];\r\n\r\n/** Thay đổi trạng thái của một chiến dịch Zalo Ads (Bật / Tắt / Tạm dừng / Xóa) theo mã trạng thái được chỉ định (`POST /api/campaign/change-status`). */\r\nexport type ZaloAdsChangeCampaignStatusRequest = {\r\n /** Mã trạng thái cần áp dụng: 1 = Bật lại, 0 = Tắt, 2 = Tạm dừng, -2 = Xóa chiến dịch. */\r\n status: 0 | 1 | 2 | -2 | number;\r\n /** ID chiến dịch cần đổi trạng thái. */\r\n campaignId: number;\r\n};\r\n\r\nexport type ZaloAdsChangeCampaignStatusResponse = {\r\n /** Thông điệp kết quả từ Zalo Ads (ví dụ: 'Thành công', 'Xóa chiến dịch thành công.'). */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị thao tác thành công. */\r\n code: number;\r\n /** Trạng thái mới của chiến dịch sau khi thay đổi (1: Đã bật, 0: Đã tắt). */\r\n data?: number;\r\n};\r\n\r\n/** Tạo audience tùy chỉnh từ điều kiện targeting, tệp nguồn hoặc audience loại trừ/bao gồm đã chọn. Đây là mutation tool thuộc lane zalo-ads-audience; dùng khi cấu trúc targeting và quyền xử lý dữ liệu đã được xác nhận. Targeting được gửi dưới dạng chuỗi JSON theo contentSchema. */\r\nexport type ZaloAdsCreateCustomAudienceRequest = {\r\n /** Tên audience tùy chỉnh. */\r\n name: string;\r\n /** Loại custom audience; đã quan sát 1 và 3, không giới hạn enum vì chưa đủ bằng chứng. */\r\n caType: number;\r\n /** Chuỗi JSON targeting. Xem contentSchema để biết cấu trúc Location, tuổi, nền tảng, targeting nâng cao và audience bao gồm/loại trừ. */\r\n targeting: string;\r\n};\r\n\r\nexport type ZaloAdsCreateCustomAudienceResponse = {\r\n msg: string;\r\n /** ID audience vừa tạo; cùng giá trị với data.CustomAudienceId trong phản hồi đã quan sát. */\r\n caId: number;\r\n code: number;\r\n /** Một audience tùy chỉnh trong Zalo Ads. */\r\n data: {\r\n /** Tên audience. */\r\n Name: string;\r\n /** Loại audience. */\r\n Type: number;\r\n /** Loại quảng cáo liên quan, khi API trả về. */\r\n AdType?: number;\r\n /** ID OA/trang liên quan, khi API trả về. */\r\n PageId?: number;\r\n /** Thời điểm tạo dạng Unix timestamp theo giây. */\r\n Created?: number;\r\n /** ID thành viên sở hữu hoặc tạo audience, khi API trả về. */\r\n MemberId?: number;\r\n /** Thiết lập bổ sung của audience. */\r\n Settings?: string;\r\n /** ID thành viên tạo audience, khi API trả về. */\r\n CreatedBy?: number;\r\n /** Chuỗi JSON mô tả tệp nguồn và cấu hình targeting. */\r\n Targeting?: string;\r\n /** Loại chiến dịch liên quan, khi API trả về. */\r\n CampaignType?: number;\r\n /** ID audience tùy chỉnh; dùng cho thao tác xóa hoặc liên kết audience vào quảng cáo. */\r\n CustomAudienceId: number;\r\n };\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo E-commerce (Commerce) trên Zalo Ads (campaignType = 9). Service tự JSON.stringify nếu truyền object. */\r\nexport type ZaloAdsCreateEcommerceCampaignRequest = {\r\n /** Cấu hình chiến dịch Commerce (object hoặc chuỗi JSON): { name, campaignType: 9, pageId, productId, targetUrl, adtype: -1, budgetType: 1, budgetlimit, limitType: 2, campaignObjective: 0, campaignId: 0, adId: 0 }. */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateEcommerceCampaignResponse = {\r\n msg: string;\r\n code: number;\r\n data?: {\r\n adId?: number;\r\n campaignId?: number;\r\n campaign_id?: number;\r\n };\r\n};\r\n\r\n/** Tạo form gắn Official Account, câu hỏi thu thập thông tin, nội dung section và màn hình cảm ơn. Đây là thao tác mutation; form mới sẽ xuất hiện trong danh sách biểu mẫu của OA. */\r\nexport type ZaloAdsCreateFormRequest = {\r\n /** Cấu hình biểu mẫu thu thập thông tin khách hàng hoặc chuỗi JSON.stringify(CreateFormPayload). */\r\n data: ZaloAdsCreateFormPayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateFormResponse = {\r\n code: \"0\" | 0;\r\n data: {\r\n /** ID form mới tạo, dùng để gắn vào cấu hình quảng cáo. */\r\n id: string;\r\n oaId: string;\r\n ownId?: string;\r\n title?: string;\r\n status: number;\r\n /** Unix epoch giây. */\r\n createAt: number;\r\n formName: string;\r\n sections: Array<ZaloAdsFormSectionDto>;\r\n questions: Array<ZaloAdsFormQuestionDto>;\r\n /** Unix epoch giây. */\r\n updatedAt: number;\r\n description?: string;\r\n };\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo biểu mẫu (Form) trên Zalo Ads (campaignType = 8). Service tự JSON.stringify nếu truyền object. */\r\nexport type ZaloAdsCreateFormCampaignRequest = {\r\n /** Cấu hình chiến dịch biểu mẫu (object hoặc chuỗi JSON). */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateFormCampaignResponse = {\r\n msg: string;\r\n code: number;\r\n data?: {\r\n adId: number;\r\n campaignId: number;\r\n };\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Tin nhắn trên Zalo Ads (campaignType = 10). Service tự JSON.stringify nếu truyền object. */\r\nexport type ZaloAdsCreateMessageCampaignRequest = {\r\n /** Cấu hình chiến dịch Tin nhắn (object hoặc chuỗi JSON). */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateMessageCampaignResponse = {\r\n code?: number;\r\n msg?: string;\r\n data?: {\r\n adId?: number;\r\n campaignId?: number;\r\n campaign_id?: number;\r\n };\r\n error?: number;\r\n message?: string;\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Zalo Official Account (campaignType = 2). Service tự JSON.stringify nếu truyền object. */\r\nexport type ZaloAdsCreateOfficialAccountCampaignRequest = {\r\n /** Cấu hình chiến dịch Official Account (object hoặc chuỗi JSON). */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateOfficialAccountCampaignResponse = {\r\n msg: string;\r\n code: number;\r\n data?: {\r\n adId?: number;\r\n campaignId?: number;\r\n campaign_id?: number;\r\n };\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Bài viết trên Zalo Ads (campaignType = 4). Service tự JSON.stringify payload này vào field form data. */\r\nexport class ZaloAdsCreatePostCampaignRequest {\r\n /** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */\r\n data!: ZaloAdsCampaignCreatePayloadDto | string;\r\n}\r\n\r\nexport class ZaloAdsCreatePostCampaignResponse {\r\n code!: number;\r\n /** Chuỗi ID quảng cáo mới trong response Zalo Ads. */\r\n msg!: string;\r\n data!: { adId: number; campaignId: number };\r\n}\r\n\r\nexport interface ZaloAdsConversionElementSelectorDto {\r\n class?: Array<string>;\r\n id?: string;\r\n tag?: string;\r\n}\r\n\r\n/** Tạo conversion để đo lường hành động trên trang đích Zalo Ads. Đây là mutation tool thuộc lane zalo-ads-conversion; dùng sau khi đã xác định nhãn conversion, URL trang đích và quy tắc sự kiện click hoặc URL. Chỉ gọi khi cần tạo mới vì mỗi lần gọi sẽ phát sinh một conversion trong tài khoản quảng cáo. */\r\nexport type ZaloAdsCreateConversionRequest = {\r\n /** Tên conversion, phải duy nhất trong tài khoản quảng cáo (2–180 ký tự). */\r\n name: string;\r\n /** Nhãn conversion: 10 khách hàng tiềm năng, 11 mua hàng, 5 liên hệ, 4 đăng ký, 9 bắt đầu thanh toán, 2 thêm giỏ hàng, 19 khác. */\r\n labelId: 2 | 4 | 5 | 9 | 10 | 11 | 19 | number;\r\n /** Kiểu khớp URL: 1 hoặc 2. */\r\n urlType: 1 | 2 | number;\r\n /** Bộ chọn phần tử click; ví dụ [{\"class\":[\"btn\"]}]. Dùng mảng rỗng khi không áp dụng. */\r\n elements: Array<ZaloAdsConversionElementSelectorDto>;\r\n /** Từ khóa URL cần ghi nhận; dùng mảng rỗng khi không áp dụng. */\r\n keywords: Array<string>;\r\n /** Danh sách ID nút theo cấu hình click; dùng mảng rỗng khi không áp dụng. */\r\n buttonIds: Array<string>;\r\n /** URL trang đích có Zalo Pixel. */\r\n landingPage: string;\r\n};\r\n\r\nexport interface ZaloAdsConversionItemDto {\r\n conversionId: number;\r\n name: string;\r\n labelId: number;\r\n urlType?: number;\r\n landingPage?: string;\r\n status?: number;\r\n created?: number;\r\n memberId?: number;\r\n}\r\n\r\nexport type ZaloAdsCreateConversionResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: ZaloAdsConversionItemDto | number;\r\n};\r\n\r\n/** Xóa một conversion đã cấu hình trên Zalo Ads. Đây là destructive tool thuộc lane zalo-ads-conversion; chỉ dùng sau khi đối chiếu ID từ danh sách conversion và xác nhận cần dừng ghi nhận dữ liệu mới. Không dùng để tạm dừng hoặc chỉnh sửa conversion vì thao tác không thể khôi phục. */\r\nexport type ZaloAdsDeleteConversionRequest = {\r\n /** ID conversion cần xóa, lấy từ ZaloAds_getApiConversionAll hoặc trang chi tiết conversion. Thao tác không thể khôi phục. */\r\n conversionId: number;\r\n};\r\n\r\nexport type ZaloAdsDeleteConversionResponse = {\r\n /** Thông báo trạng thái từ Zalo Ads. */\r\n msg: string;\r\n /** Mã thành công đã capture: 0. */\r\n code: 0 | number;\r\n};\r\n\r\n/** Xóa một audience tùy chỉnh theo ID trên Zalo Ads. Đây là destructive tool thuộc lane zalo-ads-audience; chỉ dùng sau khi xác nhận đúng audience và hệ quả không thể hoàn tác. Dùng CustomAudienceId từ tool danh sách hoặc tạo audience. */\r\nexport type ZaloAdsDeleteCustomAudienceRequest = {\r\n /** ID audience tùy chỉnh cần xóa, lấy từ CustomAudienceId của tool danh sách hoặc tool tạo audience. */\r\n customAudienceId: number;\r\n};\r\n\r\nexport type ZaloAdsDeleteCustomAudienceResponse = {\r\n /** Thông điệp kết quả từ Zalo Ads. */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n};\r\n\r\n/** Lấy chi tiết một quảng cáo theo ID (GET /zaapi/getAdFromAdId?adId=...&v=2&newWard=true). */\r\nexport type ZaloAdsGetAdByIdRequest = {\r\n /** ID mẫu quảng cáo cần lấy chi tiết (query param `adId`). */\r\n adId?: number | string;\r\n /** Phiên bản schema cấu trúc dữ liệu trả về (mặc định: 2). */\r\n v?: number | string;\r\n /** Cờ kích hoạt định dạng nhắm chọn cấp Phường/Xã mới (mặc định: true). */\r\n newWard?: boolean | string;\r\n};\r\n\r\n/** Thông tin chiến dịch mở rộng đính kèm trong phản hồi getAdById */\r\nexport interface ZaloAdsCampaignDetailExtendDto {\r\n CampaignId: number;\r\n MemberId: number;\r\n Name: string;\r\n Type: number;\r\n StartDate: number;\r\n EndDate: number;\r\n Status: number;\r\n Modified?: number;\r\n Created?: number;\r\n AdtimaCampaignId?: number;\r\n AdtimaOrderId?: number;\r\n ReadOnly?: number;\r\n CrmCampaignId?: string;\r\n Settings?: {\r\n BudgetLimit?: {\r\n Type?: number;\r\n Amount?: number;\r\n LimitType?: number;\r\n };\r\n };\r\n CreatedBy?: number;\r\n AgencyId?: number;\r\n Username?: string;\r\n ViewType?: string;\r\n}\r\n\r\nexport type ZaloAdsGetAdByIdResponse = {\r\n code?: number;\r\n msg?: string;\r\n data?: ZaloAdsAdUpdatePayloadDto;\r\n extend?: ZaloAdsCampaignDetailExtendDto;\r\n flags?: {\r\n IsOaValidForAd?: boolean;\r\n [key: string]: unknown;\r\n };\r\n report?: number[] | Record<string, number>;\r\n viewdata?: unknown[];\r\n AdId?: number;\r\n CampaignId?: number;\r\n MemberId?: number;\r\n RowVersion?: number;\r\n AdName?: string;\r\n Type?: number;\r\n Settings?: ZaloAdsAdSettingsDto;\r\n Status?: number;\r\n StartDate?: number;\r\n EndDate?: number;\r\n ZaloFlowId?: number;\r\n ZaloPageId?: number;\r\n ZaloFormId?: string;\r\n ZaloFeedId?: string | number;\r\n MiniPageId?: number;\r\n UseConversion?: ZaloAdsUseConversionValue | number;\r\n ConversionId?: number;\r\n Report?: Record<string, number>;\r\n};\r\n\r\n\r\n/** Lấy lịch sử thao tác và các hạng mục thay đổi của một quảng cáo Zalo Ads. Đây là detail tool thuộc lane quản lý quảng cáo; dùng để kiểm tra ai đã tạo hoặc điều chỉnh nội dung, đối tượng, hình/video và conversion. Mỗi bản ghi nêu người thực hiện, thời điểm và danh sách thay đổi chính hoặc bổ sung. */\r\nexport type ZaloAdsGetAdChangeLogRequest = {\r\n /** ID quảng cáo cần xem lịch sử. Có thể lấy từ kết quả tạo quảng cáo hoặc dữ liệu chi tiết quảng cáo. */\r\n adId: number;\r\n /** Mã loại nhật ký (mặc định: 1). */\r\n type?: number;\r\n};\r\n\r\nexport type ZaloAdsGetAdChangeLogResponse = {\r\n /** Thông điệp kết quả từ Zalo Ads. */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị thành công. */\r\n code: number;\r\n /** Danh sách bản ghi lịch sử, sắp xếp theo quy ước của Zalo Ads. */\r\n data: Array<{\r\n /** ID quảng cáo được thay đổi; trùng với adId đã truy vấn. */\r\n ItemId: number;\r\n /** Tên người dùng đã thực hiện thao tác. */\r\n Member: string;\r\n /** Các thay đổi nghiệp vụ chính, ví dụ tạo mới, đối tượng hoặc nội dung quảng cáo. */\r\n Content: Array<string>;\r\n /** Thời điểm ghi nhận thay đổi, Unix timestamp tính bằng giây. */\r\n Created: number;\r\n /** Các thay đổi bổ sung, ví dụ hiển thị nhiều ảnh, video hoặc conversion. */\r\n ExtraContent: Array<string>;\r\n }>;\r\n};\r\n\r\n/** Lấy các lựa chọn nhắm chọn nâng cao có thể dùng khi thiết lập quảng cáo. Đây là entry tool thuộc lane zalo-ads-targeting; dùng để xây dựng bộ tiêu chí audience trước bước ước lượng hoặc cập nhật quảng cáo. */\r\nexport type ZaloAdsGetApiAdGetlistadadvancetargetingRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiAdGetlistadadvancetargetingResponse = {\r\n code: number;\r\n data: Array<{\r\n id: number;\r\n /** Các nhánh targeting con; có thể lồng nhiều cấp. */\r\n subs?: Array<{\r\n id: number;\r\n subs?: Array<{\r\n id: number;\r\n displayName: string;\r\n }>;\r\n displayName: string;\r\n }>;\r\n displayName: string;\r\n }>;\r\n};\r\n\r\nexport interface ZaloAdsAccessorItemDto {\r\n /** ID định danh của thành viên trên Zalo Ads (ví dụ: 257887336). */\r\n memberId: number;\r\n /** Tên hiển thị của thành viên. */\r\n memberName: string;\r\n /** Số điện thoại của thành viên (định dạng 84...). */\r\n memberPhone?: string;\r\n /** URL ảnh đại diện của thành viên. */\r\n memberAvatar?: string;\r\n /** Cấp độ quyền truy cập (0 = Chủ tài khoản gốc). */\r\n accessLevel: number;\r\n}\r\n\r\nexport interface ZaloAdsAccountAgencyInfoDto {\r\n /** Mã định danh của Agency (ví dụ: 277596648). */\r\n agencyId: number;\r\n /** ID tài khoản chủ sở hữu Agency (ví dụ: 257887336). */\r\n ownerId: number;\r\n /** Tên pháp nhân hoặc tên hiển thị của Agency. */\r\n agencyName: string;\r\n /** Thời điểm khởi tạo Agency, định dạng Unix timestamp tính bằng giây. */\r\n created?: number;\r\n /** Cấp độ quyền của tài khoản hiện tại trong Agency (ví dụ: 9 = Chủ sở hữu Agency). */\r\n accessLevel: number;\r\n}\r\n\r\n/** Lấy danh sách tài khoản hoặc thành viên có quyền truy cập/tạo chiến dịch trên tài khoản quảng cáo hiện tại (dùng cho bộ lọc người tạo hoặc chuyển đổi ngữ cảnh tài khoản). Đây là entry tool thuộc lane zalo-ads-account; hỗ trợ tham số isShowAll (0 hoặc 1) và trả về danh sách personalAccessors, agencyInfo, agencyAccessors. */\r\nexport type ZaloAdsGetApiBaAccountAllaccessorsRequest = {\r\n /** Cờ hiển thị toàn bộ danh sách người truy cập (0 = Chỉ hiển thị mặc định/đang hoạt động, 1 = Hiển thị tất cả). Mặc định giao diện Zalo Ads truyền 0. */\r\n isShowAll?: 0 | 1 | number;\r\n};\r\n\r\nexport type ZaloAdsGetApiBaAccountAllaccessorsResponse = {\r\n /** Mã kết quả (0 = Thành công). */\r\n code: number;\r\n /** Thông điệp trạng thái (ví dụ: 'success'). */\r\n msg?: string;\r\n data: {\r\n /** Danh sách thành viên truy cập cấp tài khoản cá nhân (bao gồm chủ tài khoản với accessLevel = 0). */\r\n personalAccessors: Array<ZaloAdsAccessorItemDto>;\r\n /** Thông tin Agency liên kết (nếu có). */\r\n agencyInfo?: ZaloAdsAccountAgencyInfoDto;\r\n /** Danh sách thành viên thuộc Agency có quyền truy cập tài khoản khách hàng này (nếu có). */\r\n agencyAccessors?: Array<ZaloAdsAccessorItemDto>;\r\n };\r\n};\r\n\r\nexport interface ZaloAdsGrantedMemberItemDto {\r\n /** ID định danh của thành viên trên Zalo Ads (ví dụ: 330114198). */\r\n memberId: number;\r\n /** Tên hiển thị của thành viên. */\r\n memberName: string;\r\n /** Số điện thoại liên hệ của thành viên (định dạng 84...). */\r\n memberPhone?: string;\r\n /** URL ảnh đại diện của thành viên. */\r\n memberAvatar?: string;\r\n /** Cấp độ phân quyền truy cập của thành viên (ví dụ: 1 = Quản trị viên, 2 = Nhà quảng cáo, 3 = Người phân tích/Xem báo cáo). */\r\n accessLevel: number;\r\n}\r\n\r\n/** Lấy danh sách toàn bộ thành viên đã được cấp quyền truy cập trong tài khoản quảng cáo cá nhân và Agency hiện tại. Đây là entry tool thuộc lane zalo-ads-account; dùng để kiểm tra thông tin Agency (agencyInfo), danh sách thành viên được cấp quyền cấp cá nhân (personalGrantedAccessMembers) và cấp Agency (agencyGrantedAccessMembers) trước khi phối hợp quản trị. */\r\nexport type ZaloAdsGetApiBaAccountAllgrantedmembersRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiBaAccountAllgrantedmembersResponse = {\r\n /** Mã kết quả (0 = Thành công). */\r\n code: number;\r\n /** Thông điệp trạng thái (ví dụ: 'success'). */\r\n msg?: string;\r\n data: {\r\n /** Danh sách thành viên được cấp quyền truy cập ở cấp tài khoản cá nhân. */\r\n personalGrantedAccessMembers: Array<ZaloAdsGrantedMemberItemDto>;\r\n /** Thông tin đơn vị Agency quản lý tài khoản (nếu tài khoản là Agency hoặc thuộc Agency). */\r\n agencyInfo?: ZaloAdsAccountAgencyInfoDto;\r\n /** Danh sách nhân sự/thành viên thuộc Agency được cấp quyền truy cập. */\r\n agencyGrantedAccessMembers: Array<ZaloAdsGrantedMemberItemDto>;\r\n };\r\n};\r\n\r\nexport interface ZaloAdsAgencyEmployeeItemDto {\r\n /** ID của agency quản lý. */\r\n agencyId: number;\r\n /** ID tài khoản thành viên của nhân viên. */\r\n memberId: number;\r\n /** Họ và tên nhân viên. */\r\n memberName: string;\r\n /** URL ảnh đại diện của nhân viên. */\r\n memberAvatar?: string;\r\n /** Số điện thoại của nhân viên. */\r\n memberPhone?: string;\r\n /** Cấp bậc quyền hạn trong agency (ví dụ: 9 = Quản trị viên/Chủ sở hữu, 8 = Nhân viên quản trị). */\r\n accessLevel: number;\r\n /** Số lượng khách hàng/tài khoản mà nhân viên này được phân công quản lý. */\r\n numberOfGrantedAccessMembers?: number;\r\n /** Thời điểm tham gia agency, Unix timestamp tính bằng giây. */\r\n joinDate?: number;\r\n}\r\n\r\n/** Lấy danh sách nhân viên trực thuộc Agency trên Zalo Ads cùng cấp bậc phân quyền và avatar. */\r\nexport type ZaloAdsGetApiBaAgencyEmployeesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiBaAgencyEmployeesResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsAgencyEmployeeItemDto>;\r\n};\r\n\r\n/** Lấy danh sách nguồn hoặc sự kiện chuyển đổi đã cấu hình. Đây là entry tool thuộc lane zalo-ads-conversion; dùng khi chọn conversion để đo lường hoặc tối ưu chiến dịch. */\r\nexport type ZaloAdsGetApiConversionAllRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiConversionAllResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsConversionItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsStandardEventItemDto {\r\n id: number;\r\n name: string;\r\n code?: string;\r\n description?: string;\r\n}\r\n\r\n/** Lấy danh mục sự kiện chuyển đổi chuẩn mà Zalo Ads hỗ trợ. Đây là helper tool thuộc lane zalo-ads-conversion; dùng khi ánh xạ mục tiêu đo lường vào event chuẩn. */\r\nexport type ZaloAdsGetApiConversionStandardEventsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiConversionStandardEventsResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsStandardEventItemDto>;\r\n};\r\n\r\n/** Lấy danh sách audience tùy chỉnh có thể dùng để nhắm chọn. Đây là entry tool thuộc lane zalo-ads-audience; dùng để chọn, kiểm tra hoặc lấy CustomAudienceId trước khi liên kết hay xóa audience. */\r\nexport type ZaloAdsGetApiCustomAudienceAllRequest = {\r\n /** Bật cách phân loại địa giới hành chính mới khi lấy audience. */\r\n newWard?: boolean;\r\n};\r\n\r\nexport type ZaloAdsGetApiCustomAudienceAllResponse = {\r\n msg: string;\r\n code: number;\r\n /** Các audience tùy chỉnh hiện có. */\r\n data: Array<{\r\n /** Tên audience. */\r\n Name: string;\r\n /** Loại audience. */\r\n Type: number;\r\n /** Loại quảng cáo liên quan, khi API trả về. */\r\n AdType?: number;\r\n /** ID OA/trang liên quan, khi API trả về. */\r\n PageId?: number;\r\n /** Thời điểm tạo dạng Unix timestamp theo giây. */\r\n Created?: number;\r\n /** ID thành viên sở hữu hoặc tạo audience, khi API trả về. */\r\n MemberId?: number;\r\n /** Thiết lập bổ sung của audience. */\r\n Settings?: string;\r\n /** ID thành viên tạo audience, khi API trả về. */\r\n CreatedBy?: number;\r\n /** Chuỗi JSON mô tả tệp nguồn và cấu hình targeting. */\r\n Targeting?: string;\r\n /** Loại chiến dịch liên quan, khi API trả về. */\r\n CampaignType?: number;\r\n /** ID audience tùy chỉnh; dùng cho thao tác xóa hoặc liên kết audience vào quảng cáo. */\r\n CustomAudienceId: number;\r\n }>;\r\n};\r\n\r\nexport interface ZaloAdsFileGroupItemDto {\r\n id: number;\r\n name: string;\r\n memberId?: number;\r\n created?: number;\r\n totalFiles?: number;\r\n}\r\n\r\n/** Lấy các nhóm tệp media hiện có trong tài khoản quảng cáo. Đây là entry tool thuộc lane zalo-ads-media; dùng để tìm nơi chứa tài nguyên trước khi chọn ảnh hoặc video. */\r\nexport type ZaloAdsGetApiFilegroupsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiFilegroupsResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsFileGroupItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsLpNewsButtonDto {\r\n /** Nhãn nút (ví dụ: 'Xem thêm', 'Xem ngay', 'Quảng cáo ngay'). */\r\n label: string;\r\n /** Đường dẫn URL đích khi nhấn nút. */\r\n linkUrl: string;\r\n /** Loại điều hướng (1 = Mở tab mới, 2 = Route nội bộ). */\r\n type: number;\r\n /** Cờ bật/tắt hiển thị nút (dùng cho secondaryButton). */\r\n isDisplayed?: boolean;\r\n}\r\n\r\nexport interface ZaloAdsLpNewsItemDto {\r\n /** Tiêu đề tin tức/sự kiện. */\r\n title: string;\r\n /** Mô tả ngắn của tin tức/sự kiện. */\r\n description: string;\r\n /** URL hình ảnh banner của tin tức. */\r\n imageUrl: string;\r\n /** Cờ cho biết tin tức có hiển thị trên trang Tổng quan (Dashboard) hay không. */\r\n displayOnHomePage?: boolean;\r\n /** Cờ cho biết tin tức có hiển thị trên trang chủ Landing Page hay không. */\r\n displayOnLandingPage?: boolean;\r\n /** Cấu hình nút hành động chính trên Dashboard. */\r\n primaryButton?: ZaloAdsLpNewsButtonDto;\r\n /** Cấu hình nút hành động phụ trên Dashboard. */\r\n secondaryButton?: ZaloAdsLpNewsButtonDto;\r\n /** Cấu hình nút hành động hiển thị trên popup Landing Page. */\r\n landingPageButton?: ZaloAdsLpNewsButtonDto;\r\n}\r\n\r\n/** Lấy thông tin tin tức/sự kiện nổi bật hiển thị dạng popup nổi (balloon) trên trang chủ Landing Page của Zalo Ads. Đây là entry tool thuộc lane zalo-ads-content; trả về đối tượng tin tức trong data (khi code = 0) hoặc thông báo \"Landing page new is empty\" (khi code = 1). */\r\nexport type ZaloAdsGetApiLpNewsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiLpNewsResponse = {\r\n /** Mã trạng thái (0 = Có tin tức trả về trong data, 1 = Không có tin tức nào đang hiển thị trên Landing Page). */\r\n code: number;\r\n /** Thông báo trạng thái (ví dụ: 'Landing page new is empty' khi code = 1). */\r\n msg?: string;\r\n /** Chi tiết bài viết/tin tức nổi bật hiển thị trên Landing Page (chỉ có mặt khi code = 0). */\r\n data?: ZaloAdsLpNewsItemDto;\r\n};\r\n\r\n/** Lấy danh sách ảnh, video hoặc tài nguyên media theo khoảng thời gian. Đây là entry tool thuộc lane zalo-ads-media; dùng khi cần chọn asset đã tải lên cho mẫu quảng cáo. */\r\nexport type ZaloAdsGetApiMediaItemsRequest = {\r\n /** Mốc kết thúc lọc media, Unix timestamp theo giây. */\r\n endDate: number;\r\n /** Mốc bắt đầu lọc media, Unix timestamp theo giây. */\r\n startDate: number;\r\n};\r\n\r\nexport type ZaloAdsGetApiMediaItemsResponse = {\r\n code: number;\r\n data: Array<{\r\n Name: string;\r\n Type: number;\r\n Status: number;\r\n Created: number;\r\n MediaId: number;\r\n MemberId: number;\r\n Settings: {\r\n Url: string;\r\n Width: number;\r\n Height: number;\r\n Duration: number;\r\n ThumbUrl: string;\r\n };\r\n CreatedBy: number;\r\n }>;\r\n};\r\n\r\nexport interface ZaloAdsMemberFileItemDto {\r\n id: number;\r\n name: string;\r\n fileUrl: string;\r\n status?: number;\r\n lineNumber?: number;\r\n created?: number;\r\n memberId?: number;\r\n}\r\n\r\n/** Lấy các tệp do thành viên hiện tại quản lý trong tài khoản quảng cáo. Đây là entry tool thuộc lane zalo-ads-media; dùng để tra cứu asset theo quyền sở hữu hoặc trạng thái. */\r\nexport type ZaloAdsGetApiMemberFilesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiMemberFilesResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsMemberFileItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsNotifyHeaderItemDto {\r\n /** ID định danh của thông báo (ví dụ: 1). */\r\n id: number;\r\n /** Nội dung chi tiết của thông báo hiển thị trên đầu trang. */\r\n text: string;\r\n}\r\n\r\n/** Lấy danh sách thông báo quan trọng hiển thị trên thanh tiêu đề (header announcements) của trình quản lý Zalo Ads. Đây là helper tool thuộc lane zalo-ads-notification; dùng khi cần kiểm tra các cảnh báo hệ thống hoặc nhắc nhở quan tâm OA Hỗ trợ quảng cáo Zalo Ads. */\r\nexport type ZaloAdsGetApiNotifiesHeaderRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiNotifiesHeaderResponse = {\r\n /** Mã kết quả (0 = Thành công). */\r\n code: number;\r\n /** Thông điệp trạng thái (ví dụ: 'success'). */\r\n msg?: string;\r\n /** Danh sách các thông báo hiển thị ở đầu trang (header banner). */\r\n announcements: Array<ZaloAdsNotifyHeaderItemDto>;\r\n};\r\n\r\n/** Lấy lịch sử nạp tiền (charge/payment transaction history) của tài khoản quảng cáo Zalo Ads trong khoảng thời gian tối đa 31 ngày. Đây là entry tool thuộc lane zalo-ads-billing; dùng khi đối soát các giao dịch nạp tiền, ngân hàng, kênh nạp, trạng thái và xuất hóa đơn theo khoảng thời gian xác định. */\r\nexport type ZaloAdsGetApiPaymentTransactionHistoryRequest = {\r\n /** Mốc thời gian kết thúc khoảng tra cứu, định dạng Unix timestamp tính bằng giây (khoảng cách giữa from và to tối đa 31 ngày). */\r\n to: number;\r\n /** Mốc thời gian bắt đầu khoảng tra cứu, định dạng Unix timestamp tính bằng giây (khoảng cách giữa from và to tối đa 31 ngày). */\r\n from: number;\r\n /** ID tài khoản/thành viên cần tra cứu lịch sử nạp tiền. Truyền 0 để lấy theo tài khoản hiện tại đang đăng nhập hoặc truyền ID thành viên cụ thể (ví dụ: 257887336). */\r\n memberId: number;\r\n};\r\n\r\nexport interface ZaloAdsPaymentTransactionItemDto {\r\n /** Số tiền nạp (VNĐ), ví dụ: 1000000. */\r\n amount: number;\r\n /** Tên ngân hàng hoặc nguồn nạp (ví dụ: 'Ngân hàng TMCP Hàng Hải Việt Nam', 'Voucher'). */\r\n bankName: string;\r\n /** Kênh nạp tiền (ví dụ: 'Chuyển khoản', 'ZaloPay', 'Thẻ ATM', 'Voucher'). */\r\n channel: string;\r\n /** Nội dung/ghi chú giao dịch nạp tiền. */\r\n content: string;\r\n /** Thời điểm phát sinh giao dịch nạp tiền, định dạng Unix timestamp tính bằng giây. */\r\n date: number;\r\n /** ID người hoặc hệ thống thực hiện nạp tiền (ví dụ: 257887336). */\r\n createdId: number;\r\n /** Tên người hoặc hệ thống thực hiện nạp tiền (ví dụ: 'Zalo Ads'). */\r\n createdName: string;\r\n /** Tên phụ của đơn vị/người nạp hộ (nếu có). */\r\n secondaryName?: string;\r\n /** ID tài khoản quảng cáo thụ hưởng số tiền nạp. */\r\n memberId: number;\r\n /** Cờ đánh dấu giao dịch có xuất hóa đơn (true = Có, false = Không). */\r\n receipt: boolean;\r\n /** Trạng thái giao dịch nạp tiền (ví dụ: 'Thành công'). */\r\n status: string;\r\n}\r\n\r\nexport type ZaloAdsGetApiPaymentTransactionHistoryResponse = {\r\n /** Mã trạng thái phản hồi (0 = Thành công, 1 = Lỗi tham số hoặc vượt quá 31 ngày). */\r\n code: number;\r\n /** Thông báo trạng thái hoặc chi tiết lỗi từ hệ thống. */\r\n msg?: string;\r\n /** Danh sách các giao dịch nạp tiền trong khoảng thời gian đã chọn. */\r\n data: Array<ZaloAdsPaymentTransactionItemDto>;\r\n /** Thông tin bổ sung của tài khoản được tra cứu (khi xem theo memberId). */\r\n extend?: {\r\n name?: string;\r\n };\r\n};\r\n\r\n/** Lấy danh mục vùng miền, tỉnh thành và ID quận huyện phục vụ nhắm chọn theo vị trí. Đây là helper tool thuộc lane zalo-ads-targeting; dùng khi xây dựng điều kiện địa lý chi tiết. */\r\nexport type ZaloAdsGetApiPlaceGetalldistrictsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiPlaceGetalldistrictsResponse = {\r\n code: number;\r\n /** Map vùng miền, key là ID vùng. */\r\n data: {\r\n [key: string]: {\r\n id: number;\r\n name: string;\r\n dmpId: number;\r\n provinces: {\r\n [key: string]: {\r\n id: string;\r\n name: string;\r\n dmpId: number;\r\n district: Array<number>;\r\n oldProvinceId?: string;\r\n };\r\n };\r\n newProvinces: {\r\n [key: string]: {\r\n id: string;\r\n name: string;\r\n dmpId: number;\r\n district: Array<number>;\r\n oldProvinceId?: string;\r\n };\r\n };\r\n };\r\n };\r\n};\r\n\r\nexport interface ZaloAdsSpellCheckIssueDto {\r\n /** Mã quy tắc lỗi ('111'/'278' = Lỗi chính tả, '113' = Lỗi lạm dụng kí tự, '121' = Lỗi viết hoa, '236'/'237' = Lỗi sử dụng URL/SĐT). */\r\n code?: string;\r\n /** Nhãn mô tả loại lỗi hiển thị cho người dùng. */\r\n label?: string;\r\n /** Vị trí ký tự bắt đầu của cụm từ lỗi (0-indexed). */\r\n start: number;\r\n /** Vị trí ký tự kết thúc của cụm từ lỗi. */\r\n end: number;\r\n /** Cụm từ gốc bị phát hiện lỗi trong văn bản đầu vào. */\r\n originalText: string;\r\n /** Cụm từ gợi ý thay thế (chuỗi rỗng nếu gợi ý xóa bỏ). */\r\n text: string;\r\n /** Cờ đánh dấu gợi ý là xóa bỏ cụm từ lỗi (true khi text rỗng). */\r\n isRemoval?: boolean;\r\n /** Mã phân loại diff (mặc định: 0). */\r\n type?: number;\r\n}\r\n\r\n/** Kiểm tra chính tả và quy định nội dung quảng cáo (viết hoa, lạm dụng ký tự, SĐT/URL) bằng AI cho văn bản quảng cáo (tiêu đề hoặc chú thích). Đây là helper tool thuộc lane zalo-ads-content; bắt buộc truyền query param text và trả về danh sách vị trí lỗi kèm gợi ý chỉnh sửa trong trường data.diffs. */\r\nexport type ZaloAdsGetApiSpellCheckV2Request = {\r\n /** Nội dung văn bản cần kiểm tra chính tả và quy chuẩn quảng cáo (ví dụ: tiêu đề hoặc chú thích mẫu quảng cáo). */\r\n text: string;\r\n};\r\n\r\nexport type ZaloAdsGetApiSpellCheckV2Response = {\r\n /** Mã kết quả HTTP/API (0 = Thành công). */\r\n code: number;\r\n /** Thông báo trạng thái (nếu có). */\r\n msg?: string;\r\n data: {\r\n /** UUID định danh phiên yêu cầu AI kiểm tra chính tả (dùng để gắn vào tracking request_ai_id khi lưu quảng cáo). */\r\n requestAiId: string;\r\n /** Văn bản đầu ra hoàn chỉnh sau khi AI gợi ý chỉnh sửa. */\r\n aiOutput: string;\r\n /** Thời gian xử lý của AI tính bằng mili giây (ms). */\r\n elapsedTime: number;\r\n /** Mã trạng thái dịch vụ AI (0 = SUCCESS, -1 = AI_SERVER_FAILURE, -2 = AI_REQUEST_TIMEOUT). */\r\n error: number;\r\n /** Danh sách các lỗi chính tả hoặc vi phạm quy định từ ngữ phát hiện được trong văn bản. */\r\n diffs: Array<ZaloAdsSpellCheckIssueDto>;\r\n };\r\n};\r\n\r\nexport interface ZaloAdsSpellCheckViolationDto {\r\n start: number;\r\n end: number;\r\n original_text: string;\r\n rules: number[];\r\n suggestion: string;\r\n}\r\n\r\n/** Khởi tạo tác vụ kiểm tra chính tả và vi phạm quy chuẩn quảng cáo AI V3 (POST /api/spell-check/v3). */\r\nexport type ZaloAdsCreateSpellCheckV3JobRequest = {\r\n /** Tiêu đề mẫu quảng cáo (title). */\r\n title: string;\r\n /** Chú thích / mô tả mẫu quảng cáo (caption). */\r\n caption: string;\r\n};\r\n\r\nexport type ZaloAdsCreateSpellCheckV3JobResponse = {\r\n code: 0 | number;\r\n data: {\r\n error: number;\r\n jobId: string;\r\n };\r\n};\r\n\r\n/** Lấy kết quả kiểm tra chính tả và vi phạm quy chuẩn quảng cáo AI V3 theo jobId (GET /api/spell-check/v3/{jobId}). */\r\nexport type ZaloAdsGetSpellCheckV3JobRequest = {\r\n /** Mã tác vụ kiểm tra chính tả dạng http-<uuid>. */\r\n jobId: string;\r\n};\r\n\r\nexport type ZaloAdsGetSpellCheckV3JobResponse = {\r\n code: 0 | number;\r\n data: {\r\n error: number;\r\n jobId: string;\r\n status: \"PROCESSING\" | \"COMPLETED\";\r\n message?: string;\r\n completedAt?: string;\r\n details?: {\r\n violations?: Array<ZaloAdsSpellCheckViolationDto>;\r\n title_merged_violations?: Array<ZaloAdsSpellCheckViolationDto>;\r\n caption_merged_violations?: Array<ZaloAdsSpellCheckViolationDto>;\r\n title_suggestion?: string;\r\n caption_suggestion?: string;\r\n error?: string;\r\n };\r\n };\r\n};\r\n\r\n/** Lấy thông tin tài khoản Zalo Ads hiện được xác thực, gồm ngân sách, hạn mức và các khả năng được cấp. Đây là auth-sensitive entry tool thuộc lane zalo-ads-account; dùng để xác nhận đúng ngữ cảnh tài khoản trước thao tác khác. Dữ liệu cá nhân, hợp đồng và định danh phiên chỉ được xử lý trong phạm vi được ủy quyền. */\r\nexport type ZaloAdsGetApiWhoamiRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiWhoamiResponse = {\r\n code: number;\r\n data: {\r\n id: number;\r\n /** Định danh phiên hoặc tài khoản nhạy cảm. */\r\n sid?: string;\r\n name: string;\r\n rank: number;\r\n role: string;\r\n /** Dữ liệu cá nhân. */\r\n phone?: string;\r\n avatar?: string;\r\n budget: number;\r\n /** Thông tin hợp đồng, khi API trả về; chứa dữ liệu nhạy cảm. */\r\n contract?: {\r\n code?: string;\r\n name?: string;\r\n email?: string;\r\n phone?: string;\r\n address?: string;\r\n company?: string;\r\n /** Unix timestamp theo giây. */\r\n confirmedAt?: number;\r\n legalRepresentative?: string;\r\n };\r\n /** Các cờ khả năng của tài khoản. */\r\n extraFlags?: {\r\n canUseCpm?: boolean;\r\n showSurvey?: boolean;\r\n canUseZVideo?: boolean;\r\n canChangeRole?: boolean;\r\n canUseCatalog?: boolean;\r\n canUseCommerceAd?: boolean;\r\n canUseConversion?: boolean;\r\n canUseShoppingAd?: boolean;\r\n canUseEngagementAd?: boolean;\r\n canUseAutomatedRule?: boolean;\r\n canUseExtraTemplate?: boolean;\r\n canUseMiniPageFormAd?: boolean;\r\n usedSimplifiedVersion?: boolean;\r\n canUseMiniPageMessageAd?: boolean;\r\n canUseOptimizeUniversalPixel?: boolean;\r\n /** Cho phép dùng kiểm tra chính tả AI (/api/spell-check/v2). */\r\n canUseSpellCheck?: boolean;\r\n /** Cho phép dùng tính năng tạo nhiều ảnh bằng AI. */\r\n canUseMultiImageAi?: boolean;\r\n /** Cho phép dùng công cụ tạo video. */\r\n canUseVideoCreationTool?: boolean;\r\n };\r\n /** Thông tin Agency quản lý tài khoản; chỉ xuất hiện khi tài khoản thuộc một Agency. */\r\n agencyInfo?: {\r\n /** ID Agency. */\r\n agencyId?: number;\r\n /** Tên Agency. */\r\n agencyName?: string;\r\n /** Cấp quyền của tài khoản trong Agency (quan sát được: 7, 9). */\r\n level?: number;\r\n };\r\n /** Tài khoản gốc liên quan; chứa dữ liệu cá nhân. */\r\n rootMember?: {\r\n id?: number;\r\n name?: string;\r\n avatar?: string;\r\n zaloName?: string;\r\n loginType?: number;\r\n loginLevel?: number;\r\n };\r\n limitedMoney: number;\r\n currentLimitMoney: number;\r\n unreadNotifications?: number;\r\n };\r\n};\r\n\r\n/** Lấy báo cáo hiệu quả theo quảng cáo theo khoảng thời gian, có thể lọc trạng thái và breakdown. Đây là entry tool thuộc lane zalo-ads-reporting; dùng khi cần danh sách quảng cáo cùng metric tổng hợp hoặc trạng thái. filter là chuỗi JSON điều kiện, không truyền object lồng nhau. */\r\nexport type ZaloAdsGetReportapiV2AdsRequest = {\r\n /** Mốc client/report kết thúc, Unix epoch mili giây; là biến thể query đã quan sát ở endpoint này. */\r\n to?: number;\r\n /** Mốc client/report bắt đầu, Unix epoch mili giây; là biến thể query đã quan sát ở endpoint này. */\r\n from?: number;\r\n /** Chuỗi JSON của mảng điều kiện lọc. Mỗi phần tử có Field và Value kiểu chuỗi; ví dụ lọc trạng thái: [{\"Value\":\"3\",\"Field\":\"Status\"}]. Runtime tự URL-encode query string. */\r\n filter?: string;\r\n /** Kết thúc khoảng báo cáo, Unix epoch giây; phải >= startDate. */\r\n endDate: number;\r\n /** Tham số làm mới từ giao diện. Literal undefined đã được quan sát nhưng ý nghĩa upstream chưa xác minh; nên bỏ qua khi không cần mô phỏng UI. */\r\n refresh?: string;\r\n /** Danh sách mã breakdown phân tách bằng dấu phẩy, ví dụ 1002,2001. */\r\n breakdown?: string;\r\n /** Bắt đầu khoảng báo cáo, Unix epoch giây. */\r\n startDate: number;\r\n};\r\n\r\nexport interface ZaloAdsAdReportItemDto {\r\n /** ID quảng cáo; dùng làm adId cho thao tác chi tiết/cập nhật. */\r\n id: number;\r\n name: string;\r\n /** Mã loại quảng cáo upstream; đã quan sát 28. */\r\n adType: number;\r\n /** Mã trạng thái. Khi lọc dùng Value chuỗi, ví dụ \"3\" hoặc \"4\", trong filter. */\r\n status: number;\r\n /** Unix epoch giây. */\r\n endDate: number;\r\n /** URL ảnh bìa. */\r\n coverUrl?: string;\r\n memberId: number;\r\n /** Unix epoch giây. */\r\n modified?: number;\r\n /** Mã read-only upstream; đã quan sát -1, không phải boolean. */\r\n readOnly?: number;\r\n viewType?: number;\r\n createdBy?: number;\r\n /** Unix epoch giây. */\r\n startDate: number;\r\n /** ID chiến dịch chứa quảng cáo. */\r\n campaignId: number;\r\n memberName?: string;\r\n /** Mã loại giá thầu upstream. */\r\n adPriceType?: number;\r\n /** Metric động; key là mã chỉ số Zalo Ads. */\r\n reportTotal: Record<string, number>;\r\n campaignName: string;\r\n campaignType?: number;\r\n conversionId?: number;\r\n reportByDate?: Record<string, Record<string, number>>;\r\n reportBySubId?: Record<string, Record<string, number>>;\r\n adtimaBookingId?: number;\r\n reportTotalByTemplate?: Record<string, Record<string, number>>;\r\n reportBySubIdThenByDate?: Record<string, Record<string, Record<string, number>>>;\r\n reportByTemplateThenByDate?: Record<string, Record<string, Record<string, number>>>;\r\n}\r\n\r\nexport type ZaloAdsGetReportapiV2AdsResponse = {\r\n msg: string;\r\n /** 0 là thành công. */\r\n code: number;\r\n data: Array<ZaloAdsAdReportItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsCampaignReportItemDto {\r\n id: number;\r\n name: string;\r\n status: number;\r\n endDate: number;\r\n memberId: number;\r\n readOnly: number;\r\n viewType: number;\r\n startDate: number;\r\n memberName?: string;\r\n /** Metric động; key là mã chỉ số Zalo Ads. */\r\n reportTotal: Record<string, number>;\r\n campaignType: number;\r\n adtimaCampaignId: number;\r\n reportByDate?: Record<string, Record<string, number>>;\r\n}\r\n\r\n/** Lấy báo cáo chi tiết của một chiến dịch đã biết. Đây là detail tool thuộc lane zalo-ads-reporting; dùng khi đã có campaign ID và cần xem chỉ số hiệu quả của chiến dịch đó. */\r\nexport type ZaloAdsGetReportapiV2CampaignsRequest = {\r\n /** ID chiến dịch cần xem báo cáo. */\r\n campaignId?: number | string;\r\n /** Ngày bắt đầu báo cáo, Unix timestamp theo giây. */\r\n startDate?: number;\r\n /** Ngày kết thúc báo cáo, Unix timestamp theo giây. */\r\n endDate?: number;\r\n /** Mốc làm mới truy vấn, Unix timestamp mili giây. */\r\n refresh?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetReportapiV2CampaignsResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsCampaignReportItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsUniqueUserReportDataDto {\r\n totalUniqueUsers: number;\r\n totalReach?: number;\r\n frequency?: number;\r\n byDate?: Record<string, number>;\r\n}\r\n\r\n/** Lấy thống kê người dùng duy nhất tiếp cận hoặc tương tác với quảng cáo / chiến dịch (GET https://ads.zalo.me/reportapi/v2/unique-user). */\r\nexport type ZaloAdsGetReportapiV2UniqueUserRequest = {\r\n start: number;\r\n end: number;\r\n campaignId?: number | string;\r\n adId?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetReportapiV2UniqueUserResponse = {\r\n code: number;\r\n msg?: string;\r\n data: number;\r\n extend?: Array<{ adId: number; count: number }>;\r\n};\r\n\r\n/** Lấy báo cáo hiệu quả campaign theo phiên bản dữ liệu báo cáo v3. Đây là entry tool thuộc lane zalo-ads-reporting; dùng khi cần tổng hợp hoặc so sánh chỉ số nhiều chiến dịch trong một khoảng thời gian. */\r\nexport type ZaloAdsGetReportapiV3CampaignsRequest = {\r\n /** Chuỗi JSON biểu diễn các bộ lọc Campaigns; dùng \"[]\" khi không có bộ lọc. */\r\n filter?: string;\r\n /** Ngày kết thúc báo cáo, Unix timestamp theo giây. */\r\n endDate: number;\r\n /** Mốc làm mới truy vấn khi upstream yêu cầu, Unix timestamp mili giây. */\r\n refresh?: number;\r\n /** ID agency quản lý tài khoản; dùng 0 khi không thuộc agency. */\r\n agencyId?: number;\r\n /** ID người tạo chiến dịch dùng để lọc danh sách campaign. */\r\n createdBy?: number;\r\n /** Ngày bắt đầu báo cáo, Unix timestamp theo giây. */\r\n startDate: number;\r\n};\r\n\r\nexport type ZaloAdsGetReportapiV3CampaignsResponse = {\r\n msg: string;\r\n code: number;\r\n data: Array<ZaloAdsCampaignReportItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsZaapiCampaignReportItemDto {\r\n AdId: number;\r\n AdName: string;\r\n CampaignId: number;\r\n CampaignName: string;\r\n CampaignType: number;\r\n Date: number;\r\n Cost: number;\r\n Quantity: number;\r\n}\r\n\r\n/** Lấy báo cáo hiệu quả của campaign theo dữ liệu vận hành Zalo Ads (GET https://ads.zalo.me/zaapi/Campaign/reportCampaign). */\r\nexport type ZaloAdsGetZaapiCampaignReportcampaignRequest = {\r\n campaignId: number | string;\r\n from: number;\r\n to: number;\r\n campId?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetZaapiCampaignReportcampaignResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: Array<ZaloAdsZaapiCampaignReportItemDto>;\r\n};\r\n\r\n/** Kiểm tra một chiến dịch có chứa nhiều quảng cáo hay không. Đây là helper tool thuộc lane zalo-ads-campaign; dùng trước khi chọn luồng xem hoặc cập nhật quảng cáo trong campaign. */\r\nexport type ZaloAdsGetZaapiCheckcamphasmanyadsRequest = {\r\n campaignId?: number | string;\r\n campId?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetZaapiCheckcamphasmanyadsResponse = {\r\n code: number;\r\n msg?: string;\r\n data: boolean | number;\r\n};\r\n\r\n/** Lấy danh sách quảng cáo thuộc một chiến dịch. Đây là entry tool thuộc lane zalo-ads-ad; dùng khi đã có campaign ID và cần chọn quảng cáo để xem hoặc chỉnh sửa. */\r\nexport type ZaloAdsGetZaapiGetadsfromcampaignidRequest = {\r\n campaignId?: number | string;\r\n campId?: number | string;\r\n dataType?: number | string;\r\n v?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetZaapiGetadsfromcampaignidResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsAdUpdatePayloadDto>;\r\n extend?: ZaloAdsCampaignDetailExtendDto;\r\n extra?: {\r\n appliedRuleInfo?: Array<unknown>;\r\n [key: string]: unknown;\r\n };\r\n};\r\n\r\nexport interface ZaloAdsPageConfigDto {\r\n /** Hạng tài khoản OA (ví dụ: 0 = Phổ thông, 1 = Xác thực/Nâng cao). */\r\n tier?: number;\r\n viewStatus?: number;\r\n isVerified?: boolean;\r\n allowMessage?: boolean;\r\n}\r\n\r\n/** Một địa điểm trong `extraInfo.locations` của OA (quan sát trên 67 địa điểm của 64 OA). */\r\nexport interface ZaloAdsOwnedPageLocationDto {\r\n /** Địa chỉ đầy đủ. */\r\n address: string;\r\n /** Mã tỉnh/thành. */\r\n provinceId: number;\r\n /** Mã quận/huyện; chỉ có ở 64/67 địa điểm quan sát được. */\r\n districtId?: number;\r\n /** Vĩ độ. */\r\n lat: number;\r\n /** Kinh độ. */\r\n lng: number;\r\n}\r\n\r\n/** Cấu trúc của chuỗi JSON `extraInfo` sau khi `JSON.parse`. Dữ liệu cá nhân, chỉ xử lý trong phạm vi được ủy quyền. */\r\nexport interface ZaloAdsOwnedPageExtraInfoDto {\r\n website: string | null;\r\n contactName: string;\r\n hotline: string | null;\r\n workingTime: string | null;\r\n /** Số điện thoại liên hệ dạng quốc tế, ví dụ \"84384473007\". */\r\n contactPhone: string;\r\n locations: Array<ZaloAdsOwnedPageLocationDto>;\r\n}\r\n\r\nexport interface ZaloAdsOwnedPageItemDto {\r\n /** ID nội bộ page/OA (trùng với pageId, ví dụ: 429753475). */\r\n id: number;\r\n /** Tên danh mục ngành nghề, khi có. */\r\n cate?: string;\r\n /** Tên page/OA. */\r\n name: string;\r\n /** Loại page/OA (ví dụ: 2 = Doanh nghiệp/Cửa hàng). */\r\n type: number;\r\n /** Cờ store (0 hoặc 1). */\r\n store?: number;\r\n /** Cấu hình phân hạng page/OA thay đổi theo loại. */\r\n config?: ZaloAdsPageConfigDto;\r\n /** ID nội bộ của page/OA dùng trong các API Zalo Ads như tạo chiến dịch (/zaapi/addNewCamp) hoặc lấy danh sách bài viết (/zaapi/getOwnedArticles). */\r\n pageId: number;\r\n /** Trạng thái hoạt động page/OA (ví dụ: 1 = Đang hoạt động). */\r\n status: number;\r\n /** Các ID danh mục ngành nghề (ví dụ: [10018]). */\r\n cateIds?: Array<number>;\r\n /** ID chủ sở hữu, chỉ xử lý trong phạm vi được ủy quyền. */\r\n ownerId?: number;\r\n configAd?: {\r\n /** Trạng thái hiển thị quảng cáo (ví dụ: 1 = Cho phép). */\r\n viewStatus?: number;\r\n };\r\n /** URL ảnh bìa, khi có. */\r\n coverUrl?: string;\r\n /** Mã định danh OA làm nhiễu dạng chuỗi số dài (trùng với pageIdNoised). */\r\n noisedId?: string;\r\n /** Tên hiển thị page/OA. */\r\n pageName: string;\r\n /** URL ảnh đại diện, khi có. */\r\n avatarUrl?: string;\r\n /** Cho biết OA đã chứng thực tích vàng (true) hay chưa (false). */\r\n certified?: boolean;\r\n /** Chuỗi JSON chứa thông tin liên hệ (website, contactName, hotline, contactPhone, workingTime) và danh sách vị trí (locations), khi có. */\r\n extraInfo?: string;\r\n /** Trạng thái vận hành page/OA (ví dụ: 1 = Hoạt động bình thường). */\r\n pageStatus: number;\r\n /** Thời điểm tạo dạng Unix timestamp mili giây. */\r\n createdTime?: number;\r\n /** Mô tả page/OA, khi có. */\r\n description?: string;\r\n /** Thời điểm cập nhật dạng Unix timestamp mili giây. */\r\n updatedTime?: number;\r\n /** Mã định danh OA công khai/làm nhiễu dạng chuỗi số dài (ví dụ: '305001418732969574'), dùng làm oaId trong các API Instant Pages, Zalo Forms và Message Flows. */\r\n pageIdNoised?: string;\r\n}\r\n\r\n/** Lấy danh sách tất cả Zalo Official Account hoặc trang có thể sử dụng. Đây là entry tool thuộc lane zalo-ads-page; dùng khi cần chọn page/OA trước khi tạo chiến dịch hoặc lấy bài viết OA. */\r\nexport type ZaloAdsGetZaapiGetallpagesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetZaapiGetallpagesResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsOwnedPageItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsOwnedArticleItemDto {\r\n /** Mã định danh nội bộ của bài viết (ví dụ: 17050656), dùng để truyền vào trường articleId khi tạo chiến dịch Quảng cáo Bài viết (campaignType = 4) hoặc ZaloFeedId khi cập nhật quảng cáo. */\r\n articleId: number;\r\n /** ID nội bộ của trang Zalo Official Account sở hữu bài viết (ví dụ: 429753475). */\r\n pageId: number;\r\n /** Tiêu đề của bài viết. */\r\n title: string;\r\n /** Đoạn mô tả tóm tắt (sapo) của bài viết. */\r\n description?: string;\r\n /** Đường dẫn URL công khai để xem bài viết trên Zalo OA (ví dụ: 'https://post.oa.zalo.me/d?id=...&pageId=...'). */\r\n viewUrl: string;\r\n /** URL ảnh đại diện thu nhỏ (thumbnail) của bài viết. */\r\n thumbnail?: string;\r\n /** Tổng số lượt xem bài viết. */\r\n numViews?: number;\r\n /** Tổng số lượt chia sẻ bài viết. */\r\n numShares?: number;\r\n /** Cờ đánh dấu bài viết định dạng video (true) hay bài viết thông thường (false). */\r\n isVideoArticle: boolean;\r\n}\r\n\r\n/** Lấy danh sách các bài viết đã xuất bản thuộc một trang Zalo Official Account (OA) cụ thể theo mã pageId nội bộ. Đây là entry tool thuộc lane zalo-ads-content / zalo-ads-article; dùng khi chọn bài viết nguồn cho quảng cáo bài viết (campaignType = 4). */\r\nexport type ZaloAdsGetZaapiGetownedarticlesRequest = {\r\n /** ID nội bộ của trang Zalo Official Account (trường pageId hoặc id kiểu số nguyên lấy từ getZaapiGetownedpages / getZaapiGetallpages, ví dụ: 429753475). Không truyền pageIdNoised. */\r\n pageId: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetZaapiGetownedarticlesResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsOwnedArticleItemDto>;\r\n};\r\n\r\n/** Lấy các OA do tài khoản hiện tại sở hữu hoặc quản lý. Đây là entry tool thuộc lane zalo-ads-page; dùng để lấy page ID hợp lệ trước khi cấu hình campaign hoặc lấy bài viết OA. */\r\nexport type ZaloAdsGetZaapiGetownedpagesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetZaapiGetownedpagesResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** Danh sách page/OA. */\r\n data: Array<ZaloAdsOwnedPageItemDto>;\r\n};\r\n\r\n/** Lấy khách hàng thuộc agency cùng ngân sách, hạn mức và trạng thái truy cập. Đây là auth-sensitive entry tool thuộc lane zalo-ads-agency; dùng khi cần đối soát danh sách khách hàng hoặc hạn mức theo agency. Dữ liệu định danh và số điện thoại thành viên chỉ được xử lý trong phạm vi được ủy quyền. */\r\nexport type ZaloAdsListAgencyCustomersWithBudgetRequest = {\r\n /** Số khách hàng tối đa mỗi lần lấy (mặc định: 15). */\r\n limit?: number;\r\n /** Vị trí bắt đầu để phân trang, gốc 0 (mặc định: 0). */\r\n offset?: number;\r\n /** Sắp xếp ngày tham gia tăng dần khi là true (mặc định: true). */\r\n joinDateAsc?: boolean;\r\n};\r\n\r\nexport type ZaloAdsListAgencyCustomersWithBudgetResponse = {\r\n /** Thông điệp kết quả. */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n data: {\r\n /** Tổng số khách hàng phù hợp. */\r\n total: number;\r\n /** ID chủ sở hữu agency; chỉ xử lý trong phạm vi được ủy quyền. */\r\n ownerId: number;\r\n /** ID agency. */\r\n agencyId: number;\r\n /** Tên agency. */\r\n agencyName: string;\r\n /** Các khách hàng/thành viên của agency. */\r\n memberList: Array<{\r\n /** Ngân sách hiện tại. */\r\n budget: number;\r\n /** Trạng thái thành viên. */\r\n status: number;\r\n /** ID agency quản lý thành viên. */\r\n agencyId: number;\r\n /** Thời điểm tham gia, Unix timestamp theo giây. */\r\n joinDate: number;\r\n /** ID khách hàng/thành viên. */\r\n memberId: number;\r\n /** Tên thành viên; dữ liệu cá nhân. */\r\n memberName: string;\r\n /** Cấp quyền truy cập. */\r\n accessLevel: number;\r\n /** Số điện thoại thành viên; dữ liệu cá nhân. */\r\n memberPhone?: string;\r\n /** Giá trị hạn mức đã giới hạn. */\r\n limitedMoney: number;\r\n /** URL ảnh đại diện thành viên; dữ liệu cá nhân. */\r\n memberAvatar?: string;\r\n /** Hạn mức hiện tại. */\r\n currentLimitMoney: number;\r\n /** Số người có quyền truy cập. */\r\n numberOfAccessors: number;\r\n}>;\r\n};\r\n};\r\n\r\n/** Lấy danh sách cấu hình báo cáo tùy chỉnh của tài khoản, gồm tên, chỉ số và trạng thái mặc định. Đây là entry tool thuộc lane zalo-ads-reporting; dùng khi cần chọn hoặc kiểm tra báo cáo đã lưu. */\r\nexport type ZaloAdsListCustomReportsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsListCustomReportsResponse = {\r\n code: number;\r\n data: Array<{\r\n id: number;\r\n name: string;\r\n created: number;\r\n memberId: number;\r\n modified: number;\r\n settings: Array<number>;\r\n isDefault: boolean;\r\n}>;\r\n};\r\n\r\n/** Lấy danh sách biểu mẫu Zalo Ads theo Official Account, gồm trạng thái, câu hỏi, nội dung và thời điểm cập nhật. Đây là auth-sensitive entry tool thuộc lane zalo-ads-form; dùng khi đã có OA ID và cần chọn hoặc kiểm tra biểu mẫu trước khi cấu hình quảng cáo. Nội dung biểu mẫu, thông tin chủ sở hữu và URL liên quan chỉ được dùng trong phạm vi được ủy quyền. */\r\nexport type ZaloAdsListFormsByOfficialAccountRequest = {\r\n /** ID Zalo Official Account cần lấy danh sách biểu mẫu. Dùng chuỗi số để giữ nguyên ID dài. */\r\n oaId: string;\r\n /** Trả về toàn bộ biểu mẫu theo OA khi được bật. */\r\n isAll?: boolean;\r\n};\r\n\r\nexport type ZaloAdsListFormsByOfficialAccountResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** Các biểu mẫu Zalo Ads. */\r\n data: Array<{\r\n /** ID biểu mẫu. */\r\n id: string;\r\n /** Nguồn tạo biểu mẫu, khi API trả về. */\r\n src?: string;\r\n /** ID Official Account của biểu mẫu. */\r\n oaId: string;\r\n /** ID chủ sở hữu hoặc tài khoản liên quan, khi API trả về. */\r\n ownId?: string;\r\n /** Số điện thoại liên hệ, khi có; dữ liệu cá nhân. */\r\n phone?: string;\r\n /** Tiêu đề biểu mẫu, khi có. */\r\n title?: string;\r\n /** Tên Official Account, khi API trả về. */\r\n oaName?: string;\r\n /** Trạng thái biểu mẫu. */\r\n status: number;\r\n /** Nội dung cảm ơn sau khi gửi, khi có. */\r\n thanks?: string;\r\n /** Mã hoặc URL công khai của biểu mẫu, khi có. */\r\n formUrl?: string;\r\n /** Thông tin chủ sở hữu; chỉ xử lý trong phạm vi được ủy quyền. */\r\n ownInfo?: {\r\n avatar?: string;\r\n nickName?: string;\r\n};\r\n /** Website liên kết, khi có. */\r\n website?: string;\r\n /** Thời điểm tạo dạng Unix timestamp theo giây. */\r\n createAt?: number;\r\n /** Tên biểu mẫu. */\r\n formName: string;\r\n /** Nhãn hành động chuyển tiếp. */\r\n gotoText?: string;\r\n /** URL ảnh đại diện Official Account, khi API trả về. */\r\n oaAvatar?: string;\r\n /** Các section nội dung biểu mẫu. */\r\n sections?: Array<{\r\n /** Loại section. */\r\n type: number;\r\n /** Tiêu đề section. */\r\n title: string;\r\n /** Trạng thái mở rộng section. */\r\n expand: boolean;\r\n /** Nội dung section thay đổi theo type, ví dụ images, videos hoặc table. */\r\n content: ZaloAdsFormSectionContentDto;\r\n /** Cho biết section bị vô hiệu hóa hay không. */\r\n disable: boolean;\r\n }>;\r\n /** Danh sách câu hỏi của biểu mẫu. */\r\n questions: Array<{\r\n /** ID câu hỏi. */\r\n id: string;\r\n /** Loại câu hỏi. */\r\n type: number;\r\n /** Nội dung câu hỏi. */\r\n title: string;\r\n /** Các cấu hình câu trả lời. */\r\n answers: Array<{\r\n /** ID câu trả lời. */\r\n id: string;\r\n /** Loại câu trả lời. */\r\n type: number;\r\n /** Thứ tự hiển thị. */\r\n priority: number;\r\n /** Gợi ý nhập liệu, khi có. */\r\n placeHolder?: string;\r\n }>;\r\n /** Thứ tự hiển thị câu hỏi. */\r\n priority: number;\r\n /** Cho biết câu hỏi có bắt buộc hay không. */\r\n isRequired: boolean;\r\n /** Cho biết câu hỏi có bị khóa chỉnh sửa hay không. */\r\n editDisabled?: boolean;\r\n }>;\r\n /** Thời điểm cập nhật dạng Unix timestamp theo giây. */\r\n updatedAt?: number;\r\n /** Các điều kiện bổ sung, khi có. */\r\n conditions?: Array<{\r\n field?: string;\r\n operator?: string;\r\n value?: string | number;\r\n }>;\r\n /** URL ảnh bìa, khi có. */\r\n coverPhoto?: string;\r\n /** Mô tả biểu mẫu, khi có. */\r\n description?: string;\r\n /** Tiêu đề xác nhận gửi, khi có. */\r\n submitTitle?: string;\r\n /** Cờ duyệt trước khi gửi. */\r\n reviewSubmit?: boolean;\r\n /** Loại hành động chuyển tiếp. */\r\n gotoActionType?: number;\r\n /** Nhóm câu hỏi, khi có. */\r\n groupQuestions?: Array<{\r\n groupIdx?: number;\r\n title?: string;\r\n }>;\r\n /** Cờ widget đồng ý OA. */\r\n oaConsentWidget?: boolean;\r\n /** Cờ dùng consent tùy chỉnh. */\r\n useCustomConsent?: boolean;\r\n}>;\r\n extend: {\r\n /** Trang dữ liệu hiện tại. */\r\n page: number;\r\n /** Tổng số biểu mẫu. */\r\n total: number;\r\n };\r\n};\r\n\r\n/** Lấy các mini page theo ID template, gồm trạng thái, URL xem trước và thời điểm phát hành. Đây là auth-sensitive entry tool thuộc lane zalo-ads-content; dùng khi đã biết template ID và cần chọn mini page cho nội dung hoặc quảng cáo. Thông tin chủ sở hữu trong phản hồi chỉ được dùng trong phạm vi được ủy quyền. */\r\nexport type ZaloAdsListMiniPagesByTemplateRequest = {\r\n /** ID template mini page cần lấy. Capture đã quan sát một ID đơn lẻ. */\r\n templateIds: number;\r\n};\r\n\r\nexport type ZaloAdsListMiniPagesByTemplateResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** Các mini page trả về. */\r\n data: Array<{\r\n /** ID nội bộ mini page. */\r\n id: number;\r\n /** Tên mini page. */\r\n name: string;\r\n /** ID Zalo Official Account liên kết, khi API trả về. */\r\n oaId?: string;\r\n /** Trạng thái kích hoạt. */\r\n active: number;\r\n /** ID biểu mẫu liên kết, khi API trả về. */\r\n formId?: string;\r\n /** Trạng thái mini page. */\r\n status: number;\r\n /** ID người dùng liên quan, khi API trả về. */\r\n userId?: number;\r\n /** Thời điểm tạo dạng Unix timestamp theo giây. */\r\n created?: number;\r\n /** Phiên bản mini page. */\r\n version: number;\r\n /** Thời điểm sửa dạng Unix timestamp theo giây. */\r\n modified?: number;\r\n /** ID công khai của mini page. */\r\n publicId: string;\r\n /** Tên chủ sở hữu, khi API trả về; xử lý như dữ liệu cá nhân. */\r\n ownerName?: string;\r\n /** Thời điểm phát hành dạng Unix timestamp theo giây. */\r\n published?: number;\r\n /** URL xem trước mini page. */\r\n previewUrl?: string;\r\n /** Tên hoặc khóa ảnh đại diện chủ sở hữu, khi API trả về; xử lý như dữ liệu cá nhân. */\r\n ownerAvatar?: string;\r\n }>;\r\n};\r\n\r\n/** Lấy danh mục nhãn conversion Personal Pixel mà Zalo Ads hỗ trợ. Đây là helper tool thuộc lane zalo-ads-conversion; dùng khi chọn nhãn sự kiện cho cấu hình đo lường hoặc tối ưu quảng cáo. */\r\nexport type ZaloAdsListPersonalPixelLabelsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsListPersonalPixelLabelsResponse = {\r\n code: number;\r\n data: Array<{\r\n id: number;\r\n name: string;\r\n }>;\r\n};\r\n\r\n/** Ước lượng quy mô audience và mức giá gợi ý từ điều kiện nhắm chọn đã chọn. Đây là helper tool thuộc lane zalo-ads-targeting; dùng trước khi tạo hoặc cập nhật quảng cáo để đánh giá độ phủ dự kiến. */\r\nexport type ZaloAdsPostApiAdEstimateaudienceRequest = {\r\n /** Mã giới tính target. */\r\n gender: number;\r\n /** Số lượng hoặc tham số audience dạng chuỗi theo API. */\r\n number: string;\r\n /** Các mã nhóm tuổi. */\r\n ageRanges: Array<number>;\r\n /** Chuỗi vị trí bổ sung theo API. */\r\n locations: string;\r\n /** Các mã nền tảng. */\r\n platforms: Array<number>;\r\n /** Loại giá/đấu thầu. */\r\n priceType: number;\r\n /** Danh sách ID tỉnh theo định dạng API. */\r\n provinces: Array<number>;\r\n /** Chuỗi JSON targeting phường/xã gồm Includes/Excludes. */\r\n wardsTargeting: string;\r\n /** Chuỗi JSON targeting gồm Includes/Excludes, vùng/tỉnh và danh sách ID quận/huyện. */\r\n districtsTargeting: string;\r\n};\r\n\r\nexport type ZaloAdsPostApiAdEstimateaudienceResponse = {\r\n msg: string;\r\n code: number;\r\n data: {\r\n /** Quy mô audience đã định dạng. */\r\n totalAudience: string;\r\n suggestedPrice: {\r\n min: number;\r\n lower: number;\r\n upper: number;\r\n };\r\n };\r\n};\r\n\r\nexport interface ZaloAdsMediaSaveSettingsDto {\r\n Url: string;\r\n Width: number;\r\n Height: number;\r\n Duration?: number;\r\n ThumbUrl?: string;\r\n}\r\n\r\nexport interface ZaloAdsMediaSavePayloadDto {\r\n Name: string;\r\n Type: number;\r\n Settings: ZaloAdsMediaSaveSettingsDto;\r\n}\r\n\r\n/** Lưu tài nguyên media vào thư viện Zalo Ads sau khi đã có URL ảnh hoặc video và metadata kích thước. Đây là mutation tool thuộc lane zalo-ads-media; dùng sau bước upload để nhận MediaId cho cấu hình quảng cáo. */\r\nexport type ZaloAdsPostApiMediaSaveRequest = {\r\n /** Chuỗi JSON hoặc object media gồm Name (tên), Type (loại) và Settings với Url, Width, Height. Form-urlencoded field name là data. */\r\n data: ZaloAdsMediaSavePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsPostApiMediaSaveResponse = {\r\n code: number;\r\n /** ID media vừa được lưu. */\r\n data: number;\r\n};\r\n\r\n/** Tải ảnh lên kho media của tài khoản quảng cáo (`POST /api/member/upload-image`). Đây là mutation tool thuộc lane zalo-ads-media; dùng khi cần tạo asset ảnh trước bước cấu hình quảng cáo. Đã xác minh thực tế trên Zalo Ads sử dụng trường multipart `File` (chữ hoa). */\r\nexport type ZaloAdsPostApiMemberUploadImageRequest = {\r\n /** Tệp ảnh cần tải lên (URL HTTP/HTTPS, đường dẫn file local trong Node.js, hoặc Blob/Uint8Array). */\r\n File?: FileInput;\r\n /** Alias tương thích ngược cho `File` (service tự ánh xạ sang `File`). */\r\n file?: FileInput;\r\n};\r\n\r\nexport type ZaloAdsPostApiMemberUploadImageResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** URL ảnh do Zalo Ads trả về. */\r\n data: string;\r\n msg?: string;\r\n};\r\n\r\n/** Xóa hoặc gỡ một quảng cáo đã chọn khỏi Zalo Ads. Đây là mutation tool thuộc lane zalo-ads-ad; chỉ dùng khi đã xác nhận đúng quảng cáo cần xóa. */\r\nexport type ZaloAdsPostZaapiDeleteadRequest = {\r\n adId?: number | string;\r\n};\r\n\r\nexport type ZaloAdsPostZaapiDeleteadResponse = {\r\n code: number;\r\n msg: string;\r\n data?: number | boolean;\r\n};\r\n\r\n/** Đổi tên hiển thị của một chiến dịch Zalo Ads đã tồn tại. Đây là mutation tool thuộc lane quản lý chiến dịch; dùng khi chỉ cần thay tên mà không thay đổi ngân sách, lịch chạy hoặc quảng cáo bên trong. Kết quả chỉ xác nhận thao tác thành công hoặc trả lỗi từ Zalo Ads. */\r\nexport type ZaloAdsRenameCampaignRequest = {\r\n /** ID chiến dịch cần đổi tên (server nhận tham số campid). */\r\n campid?: number;\r\n /** Alias thân thiện cho campid */\r\n campaignId?: number;\r\n /** Tên hiển thị mới của chiến dịch (server nhận tham số newname). */\r\n newname?: string;\r\n /** Alias thân thiện cho newname */\r\n campaignName?: string;\r\n name?: string;\r\n};\r\n\r\nexport type ZaloAdsRenameCampaignResponse = {\r\n /** Thông điệp kết quả từ Zalo Ads. */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị đổi tên thành công. */\r\n code: number;\r\n};\r\n\r\n/** Cập nhật cấu hình quảng cáo E-commerce / Commerce hiện có trên Zalo Ads (Type = 19 hoặc 23). */\r\nexport type ZaloAdsUpdateEcommerceAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo E-commerce / Commerce (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateEcommerceAdResponse = {\r\n msg: string;\r\n code: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Cập nhật quảng cáo biểu mẫu (Form) đang có trên Zalo Ads (Type = 18). */\r\nexport type ZaloAdsUpdateFormAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo biểu mẫu (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateFormAdResponse = {\r\n msg: string;\r\n code: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Cấu hình đầy đủ của quảng cáo Tin nhắn. Giữ lại các trường hệ thống lấy từ getAdById khi cập nhật. */\r\nexport class ZaloAdsMessageAdUpdateDataDto {\r\n AdId!: number;\r\n CampaignId!: number;\r\n MemberId!: number;\r\n /** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */\r\n RowVersion!: number;\r\n AdName!: string;\r\n /** 20 (hoặc 19) là quảng cáo Tin nhắn. */\r\n Type!: number;\r\n Settings!: ZaloAdsAdSettingsDto;\r\n Status!: number;\r\n StartDate!: number;\r\n EndDate!: number;\r\n /** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */\r\n ZaloFlowId!: number;\r\n ZaloPageId?: number;\r\n ZaloFormId?: string;\r\n UseConversion?: ZaloAdsUseConversionValue | number;\r\n ConversionId?: number;\r\n Report?: Record<string, number>;\r\n}\r\n\r\n/** Cập nhật quảng cáo Tin nhắn. Service tự JSON.stringify data rồi gửi form-urlencoded. */\r\nexport class ZaloAdsUpdateMessageAdRequest {\r\n /** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */\r\n data!: ZaloAdsMessageAdUpdateDataDto | ZaloAdsAdUpdatePayloadDto | string;\r\n /** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal \"undefined\". */\r\n est?: string;\r\n /** 0 là quảng cáo thông thường, 1 là boost ad. */\r\n isBoostAd?: 0 | 1 | string;\r\n /** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */\r\n stt?: number | string;\r\n}\r\n\r\nexport class ZaloAdsUpdateMessageAdResponse {\r\n msg!: string;\r\n code!: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n}\r\n\r\n/** Tải ảnh và thiết lập vùng crop để tạo asset dùng cho quảng cáo Zalo Ads (`POST /zaapi/UploadCrop`). Đây là mutation tool thuộc lane zalo-ads-media; dùng trước khi đưa URL asset kết quả vào quảng cáo Display. Cần có URL ảnh nguồn và đầy đủ x, y, width, height, scale; dùng toàn bộ 0 cùng scale 1 khi không crop. */\r\nexport type ZaloAdsUpdateNewAdsRequest = {\r\n /** URL ảnh nguồn hoặc tệp ảnh cần tải lên và crop. */\r\n File: FileInput;\r\n /** Tọa độ crop ngang; 0 khi không crop. */\r\n x: number;\r\n /** Tọa độ crop dọc; 0 khi không crop. */\r\n y: number;\r\n /** Chiều rộng crop; 0 khi không crop. */\r\n width: number;\r\n /** Chiều cao crop; 0 khi không crop. */\r\n height: number;\r\n /** Tỷ lệ crop/zoom; payload quan sát dùng 1. */\r\n scale: number;\r\n};\r\n\r\nexport type ZaloAdsUpdateNewAdsResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: string;\r\n};\r\n\r\n/** Cập nhật quảng cáo Zalo Official Account hiện có (Type = 2 hoặc 10). */\r\nexport type ZaloAdsUpdateOfficialAccountAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo Official Account (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateOfficialAccountAdResponse = {\r\n msg: string;\r\n code: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Cập nhật quảng cáo Bài viết hiện có trên Zalo Ads (Type = 3 hoặc 12). */\r\nexport type ZaloAdsUpdatePostAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo Bài viết (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdatePostAdResponse = {\r\n msg: string;\r\n code: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Website trên Zalo Ads (campaignType = 1, Type = 9). */\r\nexport type ZaloAdsCreateWebsiteCampaignRequest = {\r\n /** Cấu hình chiến dịch Website (object hoặc chuỗi JSON): { name, campaignType: 1, pageId, productId: -1, targetUrl, adtype: -1, budgetType: 0, budgetlimit, limitType: 0, campaignObjective: 0, campaignId: 0, adId: 0 }. */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateWebsiteCampaignResponse = {\r\n code: number;\r\n msg: string;\r\n data?: {\r\n adId: number;\r\n campaignId: number;\r\n };\r\n};\r\n\r\n/** Cập nhật quảng cáo Website trên Zalo Ads (Type = 9). */\r\nexport type ZaloAdsUpdateWebsiteAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo Website (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateWebsiteAdResponse = {\r\n code: number;\r\n msg: string;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Display trên Zalo Ads (campaignType = 1, Type = 2). */\r\nexport type ZaloAdsCreateDisplayCampaignRequest = {\r\n /** Cấu hình chiến dịch Display (object hoặc chuỗi JSON): { name, campaignType: 1, pageId: -1, productId: -1, targetUrl, adtype: 2, budgetType: 1, budgetlimit, limitType: 1, campaignObjective: 0, campaignId: 0, adId: 0 }. */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateDisplayCampaignResponse = {\r\n code: number;\r\n msg: string;\r\n data?: {\r\n adId: number;\r\n campaignId: number;\r\n };\r\n};\r\n\r\n/** Cập nhật quảng cáo Display trên Zalo Ads (Type = 2). */\r\nexport type ZaloAdsUpdateDisplayAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo Display (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateDisplayAdResponse = {\r\n code: number;\r\n msg: string;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Video trên Zalo Ads (campaignType = 3, Type = 11). */\r\nexport type ZaloAdsCreateVideoCampaignRequest = {\r\n /** Cấu hình chiến dịch Video (object hoặc chuỗi JSON): { name, campaignType: 3, pageId: -1, productId: -1, targetUrl, adtype: -1, budgetType: 1, budgetlimit, limitType: 1, campaignObjective: 0, campaignId: 0, adId: 0 }. */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateVideoCampaignResponse = {\r\n code: number;\r\n msg: string;\r\n data?: {\r\n adId: number;\r\n campaignId: number;\r\n };\r\n};\r\n\r\n/** Xóa vĩnh viễn chiến dịch quảng cáo trên Zalo Ads (status = -2). */\r\nexport type ZaloAdsDeleteCampaignRequest = {\r\n /** ID chiến dịch cần xóa. */\r\n campaignId: number;\r\n /** Mã trạng thái xóa chiến dịch (mặc định là -2). */\r\n status?: -2;\r\n};\r\n\r\nexport type ZaloAdsDeleteCampaignResponse = {\r\n /** Mã kết quả; 0 là xóa thành công. */\r\n code: number;\r\n /** Thông báo kết quả: \"Xóa chiến dịch thành công.\" */\r\n msg: string;\r\n};\r\n\r\nexport interface ZaloAdsAutomatedRuleActionDto {\r\n /** Mã loại hành động thực thi khi thỏa mãn điều kiện (ví dụ: 5). */\r\n type: number;\r\n /** Mã trường mục tiêu mà hành động tác động (ví dụ: 1). */\r\n field: number;\r\n /** Giới hạn trần hoặc sàn của hành động điều chỉnh (ví dụ: 1000000). */\r\n limit: number;\r\n /** Mảng giá trị tham số của hành động (ví dụ: [5] tương ứng mức thay đổi 5%). */\r\n values: Array<number>;\r\n}\r\n\r\nexport interface ZaloAdsAutomatedRuleConditionDto {\r\n /** Mã loại điều kiện đánh giá (ví dụ: 1). */\r\n type: number;\r\n /** Mã chỉ số đo lường dùng làm điều kiện (ví dụ: 11). */\r\n field: number;\r\n /** Giá trị ngưỡng so sánh của điều kiện (ví dụ: [1000]). */\r\n values: Array<number>;\r\n /** Mã toán tử so sánh của điều kiện (ví dụ: 1). */\r\n operator: number;\r\n /** Mã khoảng thời gian lấy dữ liệu đối chiếu điều kiện (ví dụ: 2). */\r\n timeRange: number;\r\n}\r\n\r\nexport interface ZaloAdsAutomatedRuleScheduleDto {\r\n type?: number;\r\n frequency?: number;\r\n hours?: Array<number>;\r\n daysOfWeek?: Array<number>;\r\n}\r\n\r\n/** Tìm kiếm và lấy danh sách quy tắc tự động (Automated Rules) trên Zalo Ads. */\r\nexport type ZaloAdsListAutomatedRulesRequest = {\r\n /** Từ khóa lọc theo tên quy tắc tự động (truyền \"\" để lấy toàn bộ). */\r\n ruleName?: string;\r\n};\r\n\r\nexport type ZaloAdsListAutomatedRulesResponse = {\r\n code: number;\r\n data: Array<{\r\n automatedRule: {\r\n automatedRuleId: number;\r\n rowVersion: number;\r\n memberId: number;\r\n createdBy: number;\r\n ruleName: string;\r\n action: ZaloAdsAutomatedRuleActionDto;\r\n conditions: Array<ZaloAdsAutomatedRuleConditionDto>;\r\n schedule: ZaloAdsAutomatedRuleScheduleDto;\r\n status: number;\r\n createdTime: number;\r\n appliedTo: number;\r\n };\r\n campaignIds?: number[];\r\n adIds?: number[];\r\n }>;\r\n};\r\n\r\n/** Tạo mới một quy tắc tự động (Automated Rule) trên Zalo Ads với phạm vi áp dụng, hành động thực thi, bộ điều kiện kích hoạt và tần suất kiểm tra. Đây là mutation tool thuộc lane zalo-ads-automation. */\r\nexport type ZaloAdsCreateAutomatedRuleRequest = {\r\n /** Phạm vi áp dụng quy tắc tự động (ví dụ: 1). */\r\n scope?: number;\r\n /** Tên quy tắc tự động cần tạo. */\r\n ruleName: string;\r\n /** Cấu hình hành động tự động thực thi khi các điều kiện được thỏa mãn. */\r\n action: ZaloAdsAutomatedRuleActionDto;\r\n /** Danh sách các điều kiện kích hoạt quy tắc tự động. */\r\n conditions: Array<ZaloAdsAutomatedRuleConditionDto>;\r\n /** Tần suất hệ thống chạy kiểm tra quy tắc (ví dụ: 12). */\r\n frequency?: number;\r\n /** Danh sách ID chiến dịch hoặc quảng cáo cụ thể áp dụng quy tắc; truyền mảng rỗng [] nếu áp dụng theo toàn bộ scope. */\r\n appliedIds?: Array<number>;\r\n /** Trường tương thích ngược với cấu trúc cũ. */\r\n appliedTo?: number;\r\n schedule?: ZaloAdsAutomatedRuleScheduleDto;\r\n campaignIds?: number[];\r\n adIds?: number[];\r\n};\r\n\r\nexport type ZaloAdsCreateAutomatedRuleResponse = {\r\n /** Mã kết quả phản hồi từ Zalo Ads (0 là tạo quy tắc thành công). */\r\n code: number;\r\n /** Thông điệp kết quả xử lý (ví dụ: 'Quy tắc của bạn đã được tạo thành công.'). */\r\n msg?: string;\r\n /** ID quy tắc tự động vừa tạo hoặc cờ kết quả trả về từ hệ thống (ví dụ: 1). */\r\n data?: number;\r\n};\r\n\r\nexport interface ZaloAdsAutomatedRuleAppliedItemDto {\r\n appliedId: number;\r\n mode: number; // 0: Unapply, 1: Apply\r\n}\r\n\r\n/** Cập nhật quy tắc tự động (Automated Rule) trên Zalo Ads (`POST /api/ad/automatedrules/update`). */\r\nexport type ZaloAdsUpdateAutomatedRuleRequest = {\r\n automatedRuleId: number;\r\n scope?: number; // 1: Quảng cáo (Ads)\r\n ruleName: string;\r\n action: ZaloAdsAutomatedRuleActionDto;\r\n conditions: Array<ZaloAdsAutomatedRuleConditionDto>;\r\n frequency?: number;\r\n appliedItems?: Array<ZaloAdsAutomatedRuleAppliedItemDto>;\r\n appliedIds?: number[];\r\n rowVersion?: number;\r\n appliedTo?: number;\r\n schedule?: ZaloAdsAutomatedRuleScheduleDto;\r\n campaignIds?: number[];\r\n adIds?: number[];\r\n};\r\n\r\nexport type ZaloAdsUpdateAutomatedRuleResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: number | boolean;\r\n};\r\n\r\n/** Tra cứu chi tiết một quy tắc tự động (Automated Rule) theo ID (`GET /api/automatedrules/{automatedRuleId}`). */\r\nexport type ZaloAdsGetAutomatedRuleDetailRequest = {\r\n automatedRuleId: number;\r\n};\r\n\r\nexport type ZaloAdsGetAutomatedRuleDetailResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: {\r\n automatedRule: {\r\n automatedRuleId: number;\r\n rowVersion?: number;\r\n memberId?: number;\r\n createdBy?: number;\r\n ruleName: string;\r\n action: ZaloAdsAutomatedRuleActionDto;\r\n conditions: Array<ZaloAdsAutomatedRuleConditionDto>;\r\n scope: number;\r\n appliedIds?: number[];\r\n frequency?: number;\r\n created?: number;\r\n modified?: number;\r\n };\r\n status: number;\r\n };\r\n};\r\n\r\n/** Thay đổi trạng thái bật hoặc tắt (active/inactive) của một quy tắc tự động (Automated Rule) trên Zalo Ads theo ID quy tắc (`POST /api/automatedrules/change-status`). Dùng khi đã có `automatedRuleId` và cần tạm dừng (`status = 0`) hoặc kích hoạt lại (`status = 1`) quy tắc tự động. */\r\nexport type ZaloAdsChangeAutomatedRuleStatusRequest = {\r\n /** ID định danh duy nhất của quy tắc tự động cần thay đổi trạng thái (lấy từ `listAutomatedRules`). */\r\n automatedRuleId?: number;\r\n /** Danh sách ID quy tắc tự động (tương thích ngược). */\r\n automatedRuleIds?: number[];\r\n /** Trạng thái mới của quy tắc tự động: 0 = Tạm dừng / Tắt, 1 = Bật / Hoạt động. */\r\n status: 0 | 1 | 2 | number;\r\n};\r\n\r\nexport type ZaloAdsChangeAutomatedRuleStatusResponse = {\r\n /** Mã kết quả phản hồi từ Zalo Ads (0 là thành công). */\r\n code: number;\r\n /** Thông điệp kết quả thay đổi trạng thái quy tắc tự động (ví dụ: 'Thay đổi trạng thái thành công.'). */\r\n msg?: string;\r\n data?: number | boolean;\r\n};\r\n\r\n/** Tra cứu lịch sử thực thi (executeHistory) và lịch sử chỉnh sửa (editHistory) của một quy tắc tự động (Automated Rule) trên Zalo Ads theo ID quy tắc (`GET /api/automatedrules/history/{automatedRuleId}`). */\r\nexport type ZaloAdsGetAutomatedRuleHistoryRequest = {\r\n /** ID định danh duy nhất của quy tắc tự động cần xem lịch sử (lấy từ `listAutomatedRules`). */\r\n automatedRuleId: number;\r\n};\r\n\r\nexport type ZaloAdsGetAutomatedRuleHistoryResponse = {\r\n /** Mã kết quả phản hồi từ Zalo Ads (0 là thành công). */\r\n code: number;\r\n /** Thông điệp trạng thái phản hồi từ Zalo Ads (nếu có). */\r\n msg?: string;\r\n /** Dữ liệu lịch sử thực thi và lịch sử chỉnh sửa của quy tắc tự động. */\r\n data: {\r\n /** Danh sách lịch sử các lần tạo hoặc chỉnh sửa cấu hình/trạng thái quy tắc tự động. */\r\n editHistory: Array<{\r\n /** Tên thành viên / người dùng thực hiện chỉnh sửa quy tắc. */\r\n member: string;\r\n /** Danh sách các dòng mô tả nội dung thay đổi trong lần chỉnh sửa. */\r\n content: Array<string>;\r\n /** Thời điểm thực hiện chỉnh sửa (Unix timestamp tính bằng giây). */\r\n created: number;\r\n }>;\r\n /** Danh sách lịch sử các lần hệ thống tự động kích hoạt và thực thi quy tắc. */\r\n executeHistory: Array<{\r\n /** Danh sách các dòng mô tả kết quả thực thi tự động. */\r\n content?: Array<string>;\r\n /** Thời điểm hệ thống thực thi quy tắc (Unix timestamp tính bằng giây). */\r\n created?: number;\r\n }>;\r\n };\r\n};\r\n\r\n/** Xóa quy tắc tự động trên Zalo Ads. */\r\nexport type ZaloAdsDeleteAutomatedRuleRequest = {\r\n automatedRuleIds: number[];\r\n};\r\n\r\nexport type ZaloAdsDeleteAutomatedRuleResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: number | boolean;\r\n};\r\n\r\n/** Tải tệp danh sách số điện thoại để tạo hoặc bổ sung nguồn audience tùy chỉnh trong Zalo Ads. Đây là mutation tool thuộc lane zalo-ads-audience; chỉ dùng khi đã có quyền xử lý dữ liệu cá nhân, tệp hợp lệ và xác nhận phạm vi upload. Không đưa số điện thoại hoặc URL tệp có dữ liệu cá nhân vào mô tả, example hay log. */\r\nexport type ZaloAdsUploadCustomAudiencePhoneListRequest = {\r\n /** Tệp danh sách số điện thoại tải lên. Capture đã quan sát MIME text/plain. */\r\n File: FileInput;\r\n /** Cờ truyền trong FormData của Zalo Ads. Capture đã quan sát giá trị \"1\"; chỉ dùng giá trị do luồng nghiệp vụ Zalo Ads yêu cầu. */\r\n isHash: \"0\" | \"1\";\r\n};\r\n\r\nexport type ZaloAdsUploadCustomAudiencePhoneListResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** Thông tin tệp đã được Zalo Ads tiếp nhận. */\r\n data: {\r\n /** ID Zalo liên quan đến kết quả upload. */\r\n zaloId: number;\r\n /** URL tệp do Zalo Ads trả về. Có thể chứa dữ liệu cá nhân, chỉ dùng trong phạm vi được ủy quyền. */\r\n fileUrl: string;\r\n /** Số dòng được báo trong kết quả upload. */\r\n lineNumber: number;\r\n };\r\n};\r\n\r\n/** Tải video lên kho media của tài khoản quảng cáo. Đây là mutation tool thuộc lane zalo-ads-media; dùng khi cần tạo asset video trước bước cấu hình quảng cáo. */\r\nexport type ZaloAdsUploadVideoRequest = {\r\n /** Tệp video tải lên. Capture đã quan sát field File (chữ hoa) với MIME video/mp4. */\r\n File?: FileInput;\r\n /** Alias tương thích chữ thường cho File. */\r\n file?: FileInput;\r\n};\r\n\r\nexport type ZaloAdsUploadVideoResponse = {\r\n code: number;\r\n /** URL video do Zalo Ads trả về. */\r\n data: string;\r\n msg?: string;\r\n};\r\n\r\n/** Tạo mới hoặc cập nhật cấu hình báo cáo tùy chỉnh với tên, cờ mặc định và danh sách chỉ số. Đây là mutation tool thuộc lane zalo-ads-reporting; dùng khi đã xác định bộ cột báo cáo cần lưu. */\r\nexport type ZaloAdsUpsertCustomReportRequest = {\r\n /** ID báo cáo; dùng 0 để tạo mới theo capture. */\r\n id: number;\r\n /** Tên báo cáo tùy chỉnh. */\r\n name: string;\r\n /** Các mã cột/chỉ số cần hiển thị trong báo cáo. */\r\n settings: Array<number>;\r\n /** Đặt làm báo cáo mặc định. */\r\n isDefault: boolean;\r\n};\r\n\r\nexport type ZaloAdsUpsertCustomReportResponse = {\r\n code: number;\r\n /** ID báo cáo vừa tạo hoặc cập nhật. */\r\n data: number;\r\n};\r\n\r\n/** Khởi tạo mới một chiến dịch Quảng cáo Commerce (`campaignType = 22`) trên Zalo Ads để quảng bá sản phẩm và chốt đơn trực tiếp qua trang đích bán hàng (Instant Page / Mini Page). Alias chuẩn theo tool `zalo_ads_create_commerce_campaign` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsCreateCommerceCampaignRequest = ZaloAdsCreateEcommerceCampaignRequest;\r\nexport type ZaloAdsCreateCommerceCampaignResponse = ZaloAdsCreateEcommerceCampaignResponse;\r\n\r\n/** Thiết lập và lưu cấu hình chi tiết cho mẫu Quảng cáo Commerce (`Type = 23`, gắn `MiniPageId`) trên Zalo Ads. Alias chuẩn theo tool `zalo_ads_update_commerce_ad` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsUpdateCommerceAdRequest = ZaloAdsUpdateEcommerceAdRequest;\r\nexport type ZaloAdsUpdateCommerceAdResponse = ZaloAdsUpdateEcommerceAdResponse;\r\n\r\n/** Khởi tạo mới một chiến dịch Quảng cáo Bài viết (`campaignType = 4`) trên Zalo Ads để quảng bá một bài viết đã xuất bản trên Zalo Official Account (`articleId`). Alias chuẩn theo tool `zalo_ads_create_article_campaign` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsCreateArticleCampaignRequest = ZaloAdsCreatePostCampaignRequest;\r\nexport type ZaloAdsCreateArticleCampaignResponse = ZaloAdsCreatePostCampaignResponse;\r\n\r\n/** Thiết lập và lưu cấu hình chi tiết cho mẫu Quảng cáo Bài viết (`Type = 3`, gắn `ZaloFeedId`) trên Zalo Ads. Alias chuẩn theo tool `zalo_ads_update_article_ad` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsUpdateArticleAdRequest = ZaloAdsUpdatePostAdRequest;\r\nexport type ZaloAdsUpdateArticleAdResponse = ZaloAdsUpdatePostAdResponse;\r\n\r\n/** Khởi tạo mới một chiến dịch Quảng cáo Zalo Official Account (`campaignType = 3`) trên Zalo Ads nhằm tăng lượt Quan tâm (Follow) cho trang Zalo OA. Alias chuẩn theo tool `zalo_ads_create_oa_campaign` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsCreateOaCampaignRequest = ZaloAdsCreateOfficialAccountCampaignRequest;\r\nexport type ZaloAdsCreateOaCampaignResponse = ZaloAdsCreateOfficialAccountCampaignResponse;\r\n\r\n/** Thiết lập và lưu cấu hình chi tiết cho mẫu Quảng cáo Zalo Official Account (`Type = 2`, `Action = 6`) trên Zalo Ads. Alias chuẩn theo tool `zalo_ads_update_oa_ad` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsUpdateOaAdRequest = ZaloAdsUpdateOfficialAccountAdRequest;\r\nexport type ZaloAdsUpdateOaAdResponse = ZaloAdsUpdateOfficialAccountAdResponse;\r\n\r\n/** Tạo mới 'Nhóm đối tượng đã lưu' (`caType = 1` - `DEFAULT`) trên Zalo Ads (`POST /api/ad/audience`). */\r\nexport type ZaloAdsCreateSavedAudienceRequest = {\r\n /** Tên nhóm đối tượng đã lưu (từ 2 đến 255 ký tự). */\r\n name: string;\r\n /** Mã loại nhóm đối tượng (cố định `1` = DEFAULT cho Nhóm đối tượng đã lưu). */\r\n caType?: 1;\r\n /** Chuỗi JSON (`JSON.stringify`) hoặc Object cấu hình nhắm chọn (`NewAgeRanges`, `Gender`, `Os`, `Location`, `AdvanceTargeting`, `IncludedAudiences`, `ExcludedAudiences`). */\r\n targeting: string | Record<string, unknown>;\r\n};\r\n\r\nexport type ZaloAdsCreateSavedAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Lấy danh sách tài khoản Zalo Official Account (OA) có dữ liệu chuyển đổi (Lead Signal) của nhà quảng cáo (`GET /api/ad/audience/leadSignal/oas`). */\r\nexport type ZaloAdsLeadSignalOaItem = {\r\n /** ID số của Official Account. */\r\n id: number;\r\n /** ID mã hóa chuỗi của Official Account. */\r\n noisedId?: string;\r\n /** Tên hiển thị của Official Account. */\r\n name: string;\r\n /** URL ảnh đại diện của Official Account. */\r\n avatarUrl?: string;\r\n};\r\n\r\nexport type ZaloAdsListLeadSignalOasResponse = {\r\n code: number;\r\n msg: string;\r\n data: Array<ZaloAdsLeadSignalOaItem>;\r\n};\r\n\r\nexport interface ZaloAdsConversionNameItemDto {\r\n /** Mã định danh duy nhất của sự kiện chuyển đổi (Conversion ID). */\r\n id: number;\r\n /** Tên sự kiện chuyển đổi (Conversion Name, duy nhất trong phạm vi tài khoản quảng cáo). */\r\n name: string;\r\n}\r\n\r\n/** Lấy danh sách rút gọn gồm ID và tên của toàn bộ các sự kiện chuyển đổi (Conversion) đã tạo trên tài khoản quảng cáo Zalo Ads (`GET /api/conversion/names`). */\r\nexport type ZaloAdsListConversionNamesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsListConversionNamesResponse = {\r\n /** Mã kết quả phản hồi từ Zalo Ads (`0` = Thành công). */\r\n code: number;\r\n /** Thông điệp kết quả phản hồi (ví dụ: `'success'`). */\r\n msg?: string;\r\n /** Mảng danh sách rút gọn `{ id, name }` các sự kiện chuyển đổi hiện có. */\r\n data: Array<ZaloAdsConversionNameItemDto>;\r\n};\r\n\r\n// ============================================================================\r\n// DEDICATED AUDIENCE TARGETING & CREATION TYPES (caType = 3, 6, 10, 11, 12, 13, 14, 15, 16)\r\n// ============================================================================\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng SĐT (`caType = 3`). */\r\nexport interface ZaloAdsPhoneAudienceTargetingDto {\r\n /** Tên file .txt đã tải lên (ví dụ: 'example.txt'). */\r\n Name: string;\r\n /** Đường dẫn URL công khai của file .txt sau khi upload. */\r\n Path: string;\r\n /** Tổng số lượng SĐT hợp lệ trong tệp. */\r\n Total: number;\r\n /** Mã định danh tệp SĐT do Zalo cấp. */\r\n ZaloId: number;\r\n /** Cờ đánh dấu SĐT đã được người dùng tự mã hóa SHA256 (bắt đầu bằng 84) trước khi tải lên. */\r\n IsHashedByUser?: boolean;\r\n /** Mặc định là 0. */\r\n OriginAudience?: number;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ danh sách Số điện thoại (`caType = 3` - `PHONE_LIST`). */\r\nexport type ZaloAdsCreatePhoneAudienceRequest = {\r\n name: string;\r\n caType?: 3;\r\n targeting: string | ZaloAdsPhoneAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreatePhoneAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng tương tự (`caType = 6`). */\r\nexport interface ZaloAdsLookalikeAudienceTargetingDto {\r\n /** ID của nhóm đối tượng SĐT gốc (`caType = 3`). Bắt buộc nhóm gốc phải có từ 1.000 đến 10.000 SĐT! */\r\n OriginAudience: number;\r\n /** Quy mô nhóm đối tượng mở rộng: 1.000.000, 1.500.000 hoặc 2.000.000. */\r\n Total: 1000000 | 1500000 | 2000000 | number;\r\n /** Tên nhóm đối tượng SĐT gốc. */\r\n Name: string;\r\n /** Đường dẫn file nhóm gốc (chuỗi rỗng hoặc URL). */\r\n Path?: string;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng tương tự Lookalike (`caType = 6` - `LOOKALIKE`). */\r\nexport type ZaloAdsCreateLookalikeAudienceRequest = {\r\n name: string;\r\n caType?: 6;\r\n targeting: string | ZaloAdsLookalikeAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateLookalikeAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng sự kiện Form (`caType = 12`). */\r\nexport interface ZaloAdsFormEventAudienceTargetingDto {\r\n /** 1: Đã xem Form nhưng chưa submit, 2: Đã xem Form và submit, 3: Đã xem Form, 4: Mở chat OA từ Form. */\r\n EventType: 1 | 2 | 3 | 4 | number;\r\n /** ID mã hóa chuỗi (noisedId) của tài khoản OA. */\r\n OaId: string;\r\n /** Khoảng thời gian lưu vết người dùng (1 đến 90 ngày; gợi ý: 7, 14, 30, 60, 90). */\r\n NumDays: number;\r\n /** Danh sách ID biểu mẫu Zalo Form. */\r\n FormIds: string[];\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Zalo Form (`caType = 12` - `FORM_EVENT_AUDIENCE`). */\r\nexport type ZaloAdsCreateFormEventAudienceRequest = {\r\n name: string;\r\n caType?: 12;\r\n targeting: string | ZaloAdsFormEventAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateFormEventAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng sự kiện Tin nhắn OA (`caType = 11`). */\r\nexport interface ZaloAdsMessageOaEventAudienceTargetingDto {\r\n /** 1: Liên hệ sau khi xem quảng cáo tin nhắn. */\r\n EventId: 1 | number;\r\n /** ID mã hóa chuỗi (noisedId) của tài khoản OA xác thực. */\r\n OaId: string;\r\n /** Khoảng thời gian lưu vết người dùng (1 đến 90 ngày). */\r\n NumDays: number;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn OA (`caType = 11` - `MESSAGE_AUDIENCE`). */\r\nexport type ZaloAdsCreateMessageOaEventAudienceRequest = {\r\n name: string;\r\n caType?: 11;\r\n targeting: string | ZaloAdsMessageOaEventAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateMessageOaEventAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng sự kiện Tin nhắn cá nhân (`caType = 14`). */\r\nexport interface ZaloAdsMessagePersonalEventAudienceTargetingDto {\r\n /** 1: Đã liên hệ, 2: Đã xem nội dung nhưng không liên hệ, 3: Dành thời gian xem ảnh và video ở carousel nhưng không liên hệ. */\r\n EventId?: 1 | 2 | 3 | number;\r\n /** Bí danh tương thích ngược cho EventId. */\r\n EventType?: 1 | 2 | 3 | number;\r\n /** Khoảng thời gian lưu vết người dùng (1 đến 90 ngày). */\r\n NumDays: number;\r\n /** Danh sách publicId hoặc ID số của các Mini Page template Tin nhắn. */\r\n PageIds: string[];\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn cá nhân (`caType = 14` - `MESSAGE_PERSONAL_EVENT_AUDIENCE`). */\r\nexport type ZaloAdsCreateMessagePersonalEventAudienceRequest = {\r\n name: string;\r\n caType?: 14;\r\n targeting: string | ZaloAdsMessagePersonalEventAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateMessagePersonalEventAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng Trung tâm Lead - Zalo Form (`caType = 10`). */\r\nexport interface ZaloAdsFormLeadAudienceTargetingDto {\r\n Name: string;\r\n FormAudienceId: string | number;\r\n Total: number;\r\n IsCommerce?: false;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Zalo Form (`caType = 10` - `FORM_AUDIENCE`). */\r\nexport type ZaloAdsCreateFormLeadAudienceRequest = {\r\n name: string;\r\n caType?: 10;\r\n targeting: string | ZaloAdsFormLeadAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateFormLeadAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng Trung tâm Lead - Commerce Form (`caType = 15`). */\r\nexport interface ZaloAdsCommerceFormAudienceTargetingDto {\r\n Name: string;\r\n FormAudienceId: string | number;\r\n Total: number;\r\n IsCommerce: true;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Commerce Form (`caType = 15` - `COMMERCE_FORM_AUDIENCE`). */\r\nexport type ZaloAdsCreateCommerceFormAudienceRequest = {\r\n name: string;\r\n caType?: 15;\r\n targeting: string | ZaloAdsCommerceFormAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateCommerceFormAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng Trung tâm Lead - Kịch bản Tin nhắn OA (`caType = 13`). */\r\nexport interface ZaloAdsMessageOaLeadAudienceTargetingDto {\r\n Name: string;\r\n MessageOAAudienceId: string | number;\r\n Total: number;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Kịch bản Tin nhắn OA (`caType = 13` - `MESSAGE_OA_AUDIENCE`). */\r\nexport type ZaloAdsCreateMessageOaLeadAudienceRequest = {\r\n name: string;\r\n caType?: 13;\r\n targeting: string | ZaloAdsMessageOaLeadAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateMessageOaLeadAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng Dữ liệu chuyển đổi Lead Signal (`caType = 16`). */\r\nexport interface ZaloAdsLeadSignalAudienceTargetingDto {\r\n /** ID số của Official Account có dữ liệu chuyển đổi. */\r\n OaId: number;\r\n /** Tên nhãn sự kiện chuyển đổi. */\r\n Label: string;\r\n /** Mức điều chỉnh độ rộng đối tượng từ 1 đến 20 (mặc định: 5). */\r\n SegmentCount: number;\r\n /** Ước tính số người tiếp cận (Math.round(A30 / 20 * SegmentCount)). */\r\n Total: number;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ Dữ liệu chuyển đổi Lead Signal (`caType = 16` - `LEAD_SIGNAL_AUDIENCE`). */\r\nexport type ZaloAdsCreateLeadSignalAudienceRequest = {\r\n name: string;\r\n caType?: 16;\r\n targeting: string | ZaloAdsLeadSignalAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateLeadSignalAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Lấy số liệu báo cáo tổng quan Dashboard (GET https://ads.zalo.me/reportapi/report/overview). */\r\nexport type ZaloAdsGetReportOverviewRequest = {\r\n /** Chuỗi JSON mã hóa URL, ví dụ: '{\"StartDate\":1768755600,\"EndDate\":1768928399}' */\r\n data: string;\r\n};\r\n\r\nexport type ZaloAdsGetReportOverviewResponse = {\r\n code: number;\r\n data: Record<string, Record<string, number>>;\r\n extend?: {\r\n totalUniqueUser?: number;\r\n };\r\n};\r\n\r\n/** Lấy báo cáo nhân khẩu học của chiến dịch hoặc quảng cáo (GET https://ads.zalo.me/api/demographics/report). */\r\nexport type ZaloAdsGetDemographicsReportRequest = {\r\n campaignId: number;\r\n adId: number;\r\n startDate: number;\r\n endDate: number;\r\n agencyId?: number;\r\n from?: number;\r\n to?: number;\r\n};\r\n\r\nexport type ZaloAdsGetDemographicsReportResponse = {\r\n cAgeGender?: Record<string, number>;\r\n iAgeGender?: Record<string, number>;\r\n location?: Record<string, unknown>;\r\n};\r\n\r\n/** Xóa cấu hình báo cáo tùy chỉnh theo ID (POST https://ads.zalo.me/reportapi/custom-report/delete/{id}). */\r\nexport type ZaloAdsDeleteCustomReportRequest = {\r\n id: number | string;\r\n};\r\n\r\nexport type ZaloAdsDeleteCustomReportResponse = {\r\n code?: number;\r\n msg?: string;\r\n data?: unknown;\r\n};\r\n\r\n/** Lấy danh sách các bộ lọc báo cáo đã lưu (GET https://ads.zalo.me/reportapi/api/filter/list). */\r\nexport type ZaloAdsListReportFiltersRequest = {\r\n /** 0: all/chung, 1: campaign, 2: ad */\r\n model: number | string;\r\n};\r\n\r\nexport type ZaloAdsListReportFiltersResponse = Array<{\r\n id: number;\r\n name: string;\r\n content: string;\r\n model: number;\r\n}>;\r\n\r\n\r\n\r\n/** Xuất và tải báo cáo hiệu quả quảng cáo dạng file Excel (.xlsx) qua endpoint thu thập và xuất báo cáo (POST https://ads.zalo.me/api/collect). */\r\nexport type ZaloAdsDownloadReportRequest = {\r\n /** Hành động / chủ đề tải báo cáo; mặc định là \"cd.download.report\". */\r\n t?: \"cd.download.report\" | string;\r\n /** Danh sách ID các mẫu quảng cáo cần xuất báo cáo (ví dụ: [19770157]). */\r\n adIds: number[];\r\n /** Mã trạng thái lọc quảng cáo khi xuất báo cáo (ví dụ: 2 = Đang chạy). */\r\n status?: number;\r\n /** Bộ lọc thời gian: 0 = Toàn thời gian / Tùy chỉnh. */\r\n dateFilter?: number;\r\n /** Loại chỉ số dữ liệu báo cáo (100001: Lượt nhấn / Chi phí / Hiển thị). */\r\n reportKind?: number;\r\n /** Unix timestamp thời điểm gửi lệnh xuất báo cáo (giây). */\r\n et?: number;\r\n};\r\n\r\nexport type ZaloAdsDownloadReportResponse = Blob;\r\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Chiến dịch & Quảng cáo Zalo Ads:\n * 1. Khởi tạo 8 loại chiến dịch (Website, Form, Message, OA, Video, Commerce, Article, Display)\n * 2. Thiết lập & cập nhật chi tiết mẫu quảng cáo (Ad Types: 5, 18, 30, 2, 11, 28, 3, 21)\n * 3. Đổi tên, thay đổi trạng thái, xóa chiến dịch và xóa quảng cáo\n *\n * Tích hợp toàn bộ quy chuẩn giao diện (UI reverse engineering), giới hạn độ dài ký tự,\n * quy chuẩn media, mã ID ngầm và bẫy kỹ thuật đúc kết từ live test trên máy chủ Zalo Ads.\n */\n\nimport {\n ZALO_REGION_PROVINCE_CODES,\n ZALO_NEW_REGION_PROVINCE_CODES,\n ZALO_PROVINCE_MERGE_MAPPING,\n} from \"./audiences.validator\";\nimport {\n ZaloAdsActionType,\n ZaloAdsAgeRangeId,\n ZaloAdsOsId,\n ZaloAdsDeliveryType,\n ZaloAdsUseConversion,\n type ZaloAdsCampaignCreatePayloadDto,\n type ZaloAdsAdUpdatePayloadDto,\n type ZaloAdsUpdateNewAdsRequest,\n type ZaloAdsCreateCommerceCampaignPayloadDto,\n type ZaloAdsCreateDisplayCampaignPayloadDto,\n type ZaloAdsCreateWebsiteCampaignPayloadDto,\n type ZaloAdsCreateFormCampaignPayloadDto,\n type ZaloAdsCreateMessageCampaignPayloadDto,\n type ZaloAdsCreateOfficialAccountCampaignPayloadDto,\n type ZaloAdsCreateArticleCampaignPayloadDto,\n type ZaloAdsCreateVideoCampaignPayloadDto,\n} from \"../dtos/ads.dto\";\n\nexport interface CampaignValidationResult<T = unknown> {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n data?: T;\n}\n\nexport interface ValidateCampaignOptions {\n strictMode?: boolean;\n}\n\nexport interface ValidateAdOptions {\n strictMode?: boolean;\n}\n\n/** Danh sách mã CampaignType hợp lệ trên Zalo Ads */\nexport const VALID_CAMPAIGN_TYPES = {\n WEBSITE: 6,\n FORM: 17,\n MESSAGE: 18,\n OA: 3,\n VIDEO: 14,\n COMMERCE: 22,\n ARTICLE: 4,\n DISPLAY: 20,\n} as const;\n\n/** Danh sách mã AdType hợp lệ thực tế do máy chủ Zalo Ads xử lý */\nexport const VALID_AD_TYPES = {\n WEBSITE: 5,\n FORM: 18,\n MESSAGE: 30,\n OA: 2,\n VIDEO: 11,\n COMMERCE: 28, // Server trả về 28 (không phải 23)\n ARTICLE: 3,\n DISPLAY: 21,\n} as const;\n\n/** Danh sách CTA hợp lệ cho từng loại Ad */\nexport const ALLOWED_CTAS_PER_AD_TYPE: Record<number, number[]> = {\n // Website (Type 5): 9 CTAs\n [VALID_AD_TYPES.WEBSITE]: [\n ZaloAdsActionType.DAT_NGAY,\n ZaloAdsActionType.MUA_NGAY,\n ZaloAdsActionType.THU_NGAY,\n ZaloAdsActionType.TAI_NGAY,\n ZaloAdsActionType.XEM_THEM,\n ZaloAdsActionType.NGHE_NGAY,\n ZaloAdsActionType.CHOI_NGAY,\n ZaloAdsActionType.DANG_KY,\n ZaloAdsActionType.GOI_DIEN,\n ],\n // Video (Type 11): 8 CTAs\n [VALID_AD_TYPES.VIDEO]: [\n ZaloAdsActionType.DAT_NGAY,\n ZaloAdsActionType.MUA_NGAY,\n ZaloAdsActionType.THU_NGAY,\n ZaloAdsActionType.TAI_NGAY,\n ZaloAdsActionType.XEM_THEM,\n ZaloAdsActionType.NGHE_NGAY,\n ZaloAdsActionType.CHOI_NGAY,\n ZaloAdsActionType.DANG_KY,\n ],\n // Article (Type 3): 7 CTAs\n [VALID_AD_TYPES.ARTICLE]: [\n ZaloAdsActionType.DAT_NGAY,\n ZaloAdsActionType.MUA_NGAY,\n ZaloAdsActionType.THU_NGAY,\n ZaloAdsActionType.TAI_NGAY,\n ZaloAdsActionType.XEM_THEM,\n ZaloAdsActionType.CHOI_NGAY,\n ZaloAdsActionType.DANG_KY,\n ],\n // Form (Type 18): 5 CTAs\n [VALID_AD_TYPES.FORM]: [\n ZaloAdsActionType.DAT_NGAY,\n ZaloAdsActionType.MUA_NGAY,\n ZaloAdsActionType.THU_NGAY,\n ZaloAdsActionType.XEM_THEM,\n ZaloAdsActionType.DANG_KY,\n ],\n // Commerce (Type 28): 3 CTAs\n [VALID_AD_TYPES.COMMERCE]: [\n ZaloAdsActionType.DAT_NGAY,\n ZaloAdsActionType.MUA_NGAY,\n ZaloAdsActionType.XEM_THEM,\n ],\n // OA (Type 2): Cố định Quan tâm OA (6)\n [VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA],\n};\n\n/**\n * Kiểm tra tính hợp lệ payload tạo mới Chiến dịch Zalo Ads (POST /zaapi/addNewCamp).\n */\nexport function validateCreateCampaignPayload(\n payload: Partial<ZaloAdsCampaignCreatePayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // 1. Tên chiến dịch\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"name là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"name không được vượt quá 255 ký tự.\");\n }\n\n // 2. Loại chiến dịch (campaignType)\n const validTypes = Object.values(VALID_CAMPAIGN_TYPES);\n if (payload.campaignType === undefined || payload.campaignType === null) {\n errors.push(\"campaignType là bắt buộc.\");\n } else if (!validTypes.includes(payload.campaignType as any)) {\n errors.push(\n `campaignType: ${payload.campaignType} không hợp lệ. Các loại hỗ trợ: 6 (Website), 17 (Form), 18 (Message), 3 (OA), 14 (Video), 22 (Commerce), 4 (Article), 20 (Display).`\n );\n }\n\n // 3. Official Account ID (pageId)\n // Các loại bắt buộc OA (pageId > 0): Form (17), Message (18), OA (3), Commerce (22), Article (4)\n // Các loại KHÔNG bắt buộc OA: Website (6), Video (14), Display (20)\n const OA_REQUIRED_CAMPAIGN_TYPES = [\n VALID_CAMPAIGN_TYPES.FORM,\n VALID_CAMPAIGN_TYPES.MESSAGE,\n VALID_CAMPAIGN_TYPES.OA,\n VALID_CAMPAIGN_TYPES.COMMERCE,\n VALID_CAMPAIGN_TYPES.ARTICLE,\n ];\n if (payload.campaignType !== undefined && OA_REQUIRED_CAMPAIGN_TYPES.includes(payload.campaignType as any)) {\n if (!payload.pageId || payload.pageId <= 0) {\n errors.push(\"pageId của Official Account là bắt buộc đối với loại chiến dịch này (phải > 0, chọn từ Danh sách tài khoản OA).\");\n }\n } else if (payload.campaignType === VALID_CAMPAIGN_TYPES.DISPLAY) {\n if (payload.pageId !== -1 && payload.pageId !== 0 && !payload.pageId) {\n warnings.push(\"Quảng cáo Display thường sử dụng pageId = -1.\");\n }\n }\n\n // 4. Ràng buộc theo từng loại chiến dịch\n switch (payload.campaignType) {\n case VALID_CAMPAIGN_TYPES.WEBSITE:\n if (!payload.targetUrl || typeof payload.targetUrl !== \"string\" || !payload.targetUrl.trim()) {\n errors.push(\"targetUrl là bắt buộc đối với Quảng cáo Website.\");\n } else if (!/^https?:\\/\\/.+/i.test(payload.targetUrl)) {\n errors.push(\"targetUrl phải là một đường link hợp lệ bắt đầu bằng http:// hoặc https://.\");\n }\n break;\n\n case VALID_CAMPAIGN_TYPES.ARTICLE:\n if (!payload.articleId || payload.articleId <= 0) {\n errors.push(\"articleId là bắt buộc đối với Quảng cáo Bài Viết (phải > 0, lấy từ getOwnedArticles).\");\n }\n break;\n\n case VALID_CAMPAIGN_TYPES.COMMERCE:\n if (payload.productId === undefined || payload.productId === null) {\n warnings.push(\"Quảng cáo Commerce nên chỉ định productId (hoặc -1/0 khi dùng Instant Page sản phẩm).\");\n }\n break;\n\n case VALID_CAMPAIGN_TYPES.FORM:\n case VALID_CAMPAIGN_TYPES.MESSAGE:\n // Form & Message có thể gán formId / flowId ở bước updateAd\n break;\n }\n\n // 5. Ngân sách & phương thức chi tiêu\n if (payload.budgetType !== undefined && payload.budgetlimit !== undefined) {\n if (payload.budgetType === 2) {\n // Toàn lịch chạy\n if (payload.budgetlimit > 0 && payload.budgetlimit < 600000) {\n errors.push(\"Ngân sách cho Toàn lịch chạy tối thiểu là 600,000 VNĐ.\");\n }\n } else if (payload.budgetType === 1) {\n // Mỗi ngày\n if (payload.budgetlimit > 0 && payload.budgetlimit < 50) {\n warnings.push(\"Số lượng tương tác mỗi ngày tối thiểu được khuyến nghị từ 50 lượt.\");\n }\n }\n }\n\n // 6. Kiểm tra cơ chế Multi-Ad\n if (payload.campaignId && payload.campaignId > 0) {\n if (payload.adId !== 0) {\n warnings.push(\"Khi thêm Ad mới vào chiến dịch hiện có (Multi-Ad), adId nên để bằng 0.\");\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ payload Cập nhật Mẫu Quảng cáo (POST /zaapi/UpdateAd).\n */\nexport function validateUpdateAdPayload(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n // 1. Định danh bắt buộc\n if (!payload.AdId || payload.AdId <= 0) {\n errors.push(\"AdId là bắt buộc (phải > 0).\");\n }\n if (!payload.CampaignId || payload.CampaignId <= 0) {\n errors.push(\"CampaignId là bắt buộc (phải > 0).\");\n }\n\n // 2. Tên quảng cáo\n if (!payload.AdName || !payload.AdName.trim()) {\n errors.push(\"AdName là bắt buộc và không được để trống.\");\n } else if (payload.AdName.length > 255) {\n errors.push(`AdName quá dài (${payload.AdName.length}/255 ký tự).`);\n }\n\n // 3. Kiểm tra thông tin nội dung quảng cáo (Settings.AdInfo)\n const adInfo = payload.Settings?.AdInfo;\n if (!adInfo) {\n errors.push(\"Settings.AdInfo là bắt buộc.\");\n } else {\n // Caption (Chú thích)\n if (!adInfo.Caption || !adInfo.Caption.trim()) {\n errors.push(\"Settings.AdInfo.Caption là bắt buộc.\");\n } else {\n const captionLen = adInfo.Caption.trim().length;\n if (captionLen < 35) {\n errors.push(`Settings.AdInfo.Caption quá ngắn (${captionLen}/35 ký tự tối thiểu).`);\n } else if (captionLen > 90) {\n errors.push(`Settings.AdInfo.Caption quá dài (${captionLen}/90 ký tự tối đa).`);\n }\n }\n\n // LongCaption (Chú thích mở rộng - không bắt buộc, nhưng nếu có phải từ 90 đến 2,000 ký tự)\n const longCaption = adInfo.LongCaption ?? adInfo.MoreInfo;\n if (longCaption !== undefined && longCaption !== null && longCaption.trim().length > 0) {\n const longCaptionLen = longCaption.trim().length;\n if (longCaptionLen < 90) {\n errors.push(\n `Settings.AdInfo.LongCaption (Chú thích mở rộng) quá ngắn (${longCaptionLen}/90 ký tự tối thiểu). Theo quy chuẩn Zalo Ads, trường này không bắt buộc, nhưng nếu nhập thì bắt buộc phải từ 90 đến 2,000 ký tự.`\n );\n } else if (longCaptionLen > 2000) {\n errors.push(\n `Settings.AdInfo.LongCaption (Chú thích mở rộng) quá dài (${longCaptionLen}/2000 ký tự tối đa).`\n );\n }\n\n // Kiểm tra đồng bộ mã bố cục mở rộng XTemplates (49: LONG_CAPTION)\n if (adInfo.XTemplates && Array.isArray(adInfo.XTemplates) && !adInfo.XTemplates.includes(49)) {\n warnings.push(\n \"Khi có Chú thích mở rộng (LongCaption), bạn nên thêm mã 49 (LONG_CAPTION) vào Settings.AdInfo.XTemplates để kích hoạt giao diện hiển thị bài viết dài trên Zalo Feed.\"\n );\n }\n }\n\n // Kiểm tra Nút CTA (Action)\n if (adInfo.Action !== undefined && payload.Type) {\n const allowedCtas = ALLOWED_CTAS_PER_AD_TYPE[payload.Type];\n if (allowedCtas && !allowedCtas.includes(adInfo.Action)) {\n warnings.push(\n `Mã hành động Action: ${adInfo.Action} có thể không nằm trong danh mục nút CTA hỗ trợ cho Ad Type ${payload.Type}.`\n );\n }\n }\n }\n\n // 4. Kiểm tra Giá thầu & Ngân sách (Settings.Price)\n const price = payload.Settings?.Price;\n if (!price) {\n errors.push(\"Settings.Price là bắt buộc.\");\n } else {\n // Quy tắc sống còn đảo ngược Price.Type\n if (payload.Type === VALID_AD_TYPES.WEBSITE) {\n if (price.Type !== 1) {\n errors.push(\n \"Đối với Quảng cáo Website (Type 5), Price.Type bắt buộc phải bằng 1 (CPC). Nếu truyền 2 sẽ bị máy chủ lỗi.\"\n );\n }\n if (price.LimitType === 1) {\n errors.push(\n \"Quảng cáo Website không hỗ trợ LimitType: 1 (tổng ngân sách). Bắt buộc phải dùng LimitType: 0 (ngân sách ngày).\"\n );\n }\n } else if (payload.Type === VALID_AD_TYPES.VIDEO) {\n // Quảng cáo Video (Type 11): Chạy trên nền tảng Video Platform, bắt buộc dùng CPM (Type 1) hoặc CPV (Type 7)\n if (price.Type !== 1 && price.Type !== 7) {\n errors.push(\n \"Đối với Quảng cáo Video (Type 11) trên Video Platform, Price.Type bắt buộc là 1 (CPM - Lượt hiển thị) hoặc 7 (CPV - Lượt xem). Nếu truyền 2 (CPC), form chỉnh sửa của Zalo Ads sẽ không hiển thị được giá và số lượng.\"\n );\n }\n if (price.Type === 1 && (price.Limit ?? 0) < 50) {\n errors.push(\n \"Đối với Quảng cáo Video CPM, số lượng hiển thị tối thiểu (Price.Limit) là 50 (tương ứng 50,000 lượt hiển thị).\"\n );\n }\n } else if (\n payload.Type === VALID_AD_TYPES.COMMERCE ||\n payload.Type === VALID_AD_TYPES.ARTICLE ||\n payload.Type === VALID_AD_TYPES.FORM\n ) {\n if (price.Type !== 2) {\n errors.push(\n `Đối với Ad Type ${payload.Type}, Price.Type bắt buộc phải bằng 2 (CPC).`\n );\n }\n } else if (payload.Type === VALID_AD_TYPES.OA) {\n // Quảng cáo Zalo Official Account (Type 2): Hỗ trợ Price.Type = 2 (CPC - Lượt nhấn) hoặc Price.Type = 5 (CPA - Lượt quan tâm Beta)\n if (price.Type !== 2 && price.Type !== 5) {\n errors.push(\n \"Đối với Quảng cáo OA (Type 2), Price.Type chỉ hỗ trợ 2 (Lượt nhấn - CPC) hoặc 5 (Lượt quan tâm - CPA Beta).\"\n );\n }\n if (price.Type === 2) {\n // CPC: Đặt giá thủ công theo số lượng tương tác\n if (price.SpendingMethod !== 0 && price.SpendingMethod !== undefined) {\n errors.push(\n \"Khi tính tiền theo Lượt nhấn (Price.Type = 2 / CPC), SpendingMethod bắt buộc phải bằng 0 (Đặt giá thầu thủ công theo số lượng tương tác).\"\n );\n }\n if (price.Bid !== undefined && price.Bid < 650) {\n errors.push(\n `Giá đặt mỗi lượt nhấn (Price.Bid) tối thiểu là 650 VNĐ (sàn hệ thống Zalo Ads). Hiện tại đang truyền: ${price.Bid}đ.`\n );\n }\n if (price.Limit !== undefined && price.Limit < 50) {\n errors.push(\n `Số lượng lượt nhấn (Price.Limit) tối thiểu là 50 lượt/ngày (minCTA = 50). Hiện tại đang truyền: ${price.Limit}.`\n );\n } else if (price.Limit !== undefined && price.Limit > 5000) {\n warnings.push(\n `⚠️ CẢNH BÁO BẪY NGÂN SÁCH ZALO ADS: Khi Price.Type = 2 (CPC), trường Price.Limit mang ý nghĩa là SỐ LƯỢNG LƯỢT NHẤN (Clicks count), KHÔNG PHẢI SỐ TIỀN VNĐ. Bạn đang truyền Limit = ${price.Limit} lượt nhấn, có thể khiến Tổng chi phí dự kiến tăng vọt lên hàng trăm triệu VNĐ.`\n );\n }\n } else if (price.Type === 5) {\n // CPA (Lượt quan tâm OA): Hỗ trợ 2 cách đặt giá:\n // 1. Tổng ngân sách quảng cáo (SpendingMethod = 1 / TOTALBUDGET): Tự động tối ưu chi phí\n // 2. Tự đặt giá (SpendingMethod = 0 / QUANTITY): Đặt giá thầu thủ công cho từng lượt quan tâm\n if (price.SpendingMethod === 1) {\n // Cách 1: Tổng ngân sách quảng cáo\n if (price.Bid !== undefined && price.Bid !== 0) {\n errors.push(\n \"Khi chọn 'Tổng ngân sách quảng cáo' cho Lượt quan tâm (SpendingMethod = 1), trường Bid bắt buộc phải bằng 0 (hệ thống tự động đấu thầu).\"\n );\n }\n if (price.Limit !== undefined && price.Limit < 500000) {\n errors.push(\n `Ngân sách tối thiểu cho Lượt quan tâm theo Tổng ngân sách là 500,000 VNĐ / ngày (Price.Limit >= 500000). Hiện tại đang truyền: ${price.Limit}đ.`\n );\n }\n } else if (price.SpendingMethod === 0) {\n // Cách 2: Tự đặt giá (Manual Bid cho Lượt quan tâm)\n if (price.Bid !== undefined && price.Bid < 10000) {\n errors.push(\n `Giá đặt mỗi Lượt quan tâm (Price.Bid) tối thiểu là 10,000 VNĐ / lượt quan tâm (sàn hệ thống cho OA Follow). Hiện tại đang truyền: ${price.Bid}đ.`\n );\n }\n if (price.Limit !== undefined && price.Limit < 100) {\n errors.push(\n `Số lượng Lượt quan tâm (Price.Limit) tối thiểu là 100 lượt (minCTA = 100). Hiện tại đang truyền: ${price.Limit}.`\n );\n } else if (price.Limit !== undefined && price.Limit > 5000) {\n warnings.push(\n `⚠️ CẢNH BÁO BẪY NGÂN SÁCH ZALO ADS: Khi chọn 'Tự đặt giá' cho Lượt quan tâm (SpendingMethod = 0), trường Price.Limit là SỐ LƯỢNG LƯỢT QUAN TÂM (tối thiểu 100 lượt), KHÔNG PHẢI SỐ TIỀN VNĐ.`\n );\n }\n } else if (price.SpendingMethod !== undefined) {\n errors.push(\n \"Cách đặt giá SpendingMethod cho Lượt quan tâm chỉ chấp nhận 1 (Tổng ngân sách quảng cáo) hoặc 0 (Tự đặt giá).\"\n );\n }\n }\n } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {\n // Quảng cáo Tin Nhắn (Type 30): Hỗ trợ Price.Type = 2 (CPC - Click vào tin nhắn) hoặc Price.Type = 5 (CPA - Lượt liên hệ)\n if (price.Type !== 2 && price.Type !== 5) {\n errors.push(\n \"Đối với Quảng cáo Tin nhắn (Type 30), Price.Type chỉ hỗ trợ 2 (Lượt nhấn - CPC) hoặc 5 (Lượt liên hệ - CPA).\"\n );\n }\n if (price.Type === 5) {\n if (price.SpendingMethod !== 1) {\n errors.push(\n \"Khi tính tiền theo Lượt liên hệ (Price.Type = 5 / CPA), SpendingMethod bắt buộc phải bằng 1 (Tối ưu tự động theo ngân sách).\"\n );\n }\n if (price.Bid !== undefined && price.Bid !== 0) {\n errors.push(\n \"Khi tính tiền theo Lượt liên hệ (Price.Type = 5 / CPA), trường Bid bắt buộc phải bằng 0 (Zalo Ads tự động tối ưu giá thầu, nếu truyền > 0 máy chủ sẽ báo lỗi code 13: Giá đặt không hợp lệ).\"\n );\n }\n }\n if (price.Limit !== undefined && price.Limit > 0 && price.Limit < 600000) {\n errors.push(\n \"Ngân sách tối thiểu cho Quảng cáo Tin nhắn là 600,000 VNĐ (Price.Limit >= 600000). Nếu đặt dưới 600k máy chủ sẽ từ chối.\"\n );\n }\n }\n\n // Kiểm tra DeliveryType trong Settings\n if (payload.Settings && (payload.Settings as any).DeliveryType !== undefined) {\n const deliveryType = (payload.Settings as any).DeliveryType;\n if (deliveryType !== 0 && deliveryType !== 1) {\n errors.push(\"Cài đặt phân phối Settings.DeliveryType chỉ chấp nhận 0 (Tiêu chuẩn - Standard) hoặc 1 (Tăng tốc - SpeedUp).\");\n }\n if ((price.LimitType === 2 || price.LimitType === 0) && deliveryType === 1) {\n warnings.push(\"Phân phối Tăng tốc (DeliveryType = 1) chỉ có hiệu lực khi đặt Ngân sách toàn lịch chạy (Price.LimitType = 1).\");\n }\n }\n\n // Số lượng đặt tối thiểu cho tương tác\n if (price.SpendingMethod === 0 && price.Limit !== undefined && price.Limit > 0 && price.Limit < 50) {\n warnings.push(\"Số lượng lượt tương tác đặt mỗi ngày tối thiểu là 50 lượt.\");\n }\n }\n\n // 5. Kiểm tra nhắm chọn đối tượng (Settings.Targeting)\n const targeting = payload.Settings?.Targeting;\n if (targeting) {\n // Age ranges: Hỗ trợ cả NewAgeRanges (dạng mảng chuỗi ['18_24', '25_34', ...]) lẫn AgeRanges (mảng số legacy)\n const newAges = targeting.NewAgeRanges;\n const oldAges = targeting.AgeRanges;\n if (newAges && newAges.length > 0) {\n const validNewAgeKeys = [\"13_17\", \"18_24\", \"25_34\", \"35_44\", \"45_54\", \"55_64\", \"65_plus\", \"10283\", \"10284\", \"10285\", \"10286\", \"10287\", \"10288\"];\n const invalid = newAges.filter(a => !validNewAgeKeys.includes(String(a)));\n if (invalid.length > 0) {\n warnings.push(`Mã NewAgeRanges không phổ biến: ${invalid.join(\", \")}.`);\n }\n } else if (oldAges && oldAges.length > 0) {\n const validAges = Object.values(ZaloAdsAgeRangeId);\n const invalidAges = oldAges.filter(a => !validAges.includes(a as any));\n if (invalidAges.length > 0) {\n errors.push(`Mã khoảng tuổi không hợp lệ: ${invalidAges.join(\", \")}. Hợp lệ: ${validAges.join(\", \")}.`);\n }\n }\n\n // OS types: Hỗ trợ cả Os (mảng [0, 1, 3]) lẫn OsTypes\n const osList = targeting.Os || targeting.OsTypes;\n if (osList && osList.length > 0) {\n const validOs = [0, 1, 2, 3];\n const invalidOs = osList.filter(os => !validOs.includes(Number(os)));\n if (invalidOs.length > 0) {\n errors.push(`Mã hệ điều hành không hợp lệ: ${invalidOs.join(\", \")}. Hợp lệ: 0 (Android), 1 (iOS), 3 (PC).`);\n }\n }\n\n // Delivery Type (Cách phân phối: 0 = Tiêu chuẩn, 1 = Tăng tốc)\n const deliveryType = (payload.Settings as any)?.DeliveryType;\n if (\n deliveryType !== undefined &&\n deliveryType !== ZaloAdsDeliveryType.STANDARD &&\n deliveryType !== ZaloAdsDeliveryType.SPEED_UP\n ) {\n warnings.push(\n \"DeliveryType không hợp lệ. Giá trị chuẩn: 0 (Tiêu chuẩn / Standard) hoặc 1 (Tăng tốc / SpeedUp).\"\n );\n }\n\n // Location targeting validation (2026 Admin format)\n const location = targeting.Location;\n if (location) {\n const container = location.WardTargeting || location.DistrictTargeting;\n if (container && Array.isArray(container.Includes)) {\n const validRegions: number[] = [1, 2, 3];\n for (const item of container.Includes) {\n if (!validRegions.includes(Number(item.Id))) {\n warnings.push(\n `Mã vùng miền (Id: ${item.Id}) không hợp lệ. Các mã vùng chuẩn: 1 (Miền Bắc), 2 (Miền Trung), 3 (Miền Nam).`\n );\n }\n if (item.Provinces && !Array.isArray(item.Provinces)) {\n warnings.push(`Trường 'Provinces' trong vùng miền Id=${item.Id} phải là một mảng tỉnh/thành.`);\n } else if (Array.isArray(item.Provinces)) {\n for (const prov of item.Provinces) {\n if (!prov.Id || typeof prov.Id !== \"string\") {\n warnings.push(\n `Mã tỉnh 'Id' (${JSON.stringify(prov)}) trong vùng miền ${item.Id} phải là chuỗi hợp lệ (ví dụ: 'VN44', 'VN20').`\n );\n } else {\n const mergeInfo = ZALO_PROVINCE_MERGE_MAPPING[prov.Id];\n if (mergeInfo) {\n errors.push(\n `Mã tỉnh '${prov.Id}' (${mergeInfo.name}) đã được Zalo Ads gộp/sáp nhập vào cụm mã '${mergeInfo.newCode}'. ` +\n `Vui lòng sử dụng mã cụm '${mergeInfo.newCode}' trong WardTargeting, nếu không giao diện Zalo Ads Web sẽ báo lỗi đỏ 'Invalid wards params'.`\n );\n } else {\n const validNewRegionProvs = ZALO_NEW_REGION_PROVINCE_CODES[Number(item.Id)] || [];\n if (!validNewRegionProvs.includes(prov.Id)) {\n const actualRegion = Object.keys(ZALO_NEW_REGION_PROVINCE_CODES).find(r => ZALO_NEW_REGION_PROVINCE_CODES[Number(r)].includes(prov.Id));\n errors.push(\n `Mã tỉnh '${prov.Id}' không nằm trong 34 Cụm Tỉnh/Thành mới của Vùng ${item.Id} trên Zalo Ads (sẽ gây lỗi 'Invalid wards params' trên UI). ` +\n (actualRegion ? `Mã này thuộc Vùng ${actualRegion}. ` : \"\")\n );\n }\n }\n }\n if (prov.Districts && !Array.isArray(prov.Districts)) {\n warnings.push(`Trường 'Districts' của tỉnh ${prov.Id} phải là một mảng (hoặc [] khi chọn cả tỉnh).`);\n }\n }\n }\n }\n }\n }\n }\n\n // 6. Kiểm tra cấu hình tối ưu chuyển đổi (UseConversion & ConversionId)\n if (payload.UseConversion !== undefined) {\n const validUseConversions: number[] = Object.values(ZaloAdsUseConversion);\n if (!validUseConversions.includes(payload.UseConversion as number)) {\n warnings.push(\n `UseConversion (${payload.UseConversion}) không nằm trong danh mục chuẩn: 0 (NOT_USE), 1 (USE), 2 (LADI_PAGE), 3 (MINI_APP), -1 (USE_OFF), -2 (LADI_PAGE_OFF), -3 (MINI_APP_OFF).`\n );\n }\n if (payload.UseConversion === ZaloAdsUseConversion.USE && (!payload.ConversionId || payload.ConversionId <= 0)) {\n warnings.push(\n \"Khi chọn UseConversion = 1 (Pixel của tôi), nên cấu hình ConversionId hợp lệ từ danh sách GET /api/conversion/all để thuật toán máy học Zalo Ads tối ưu tỷ lệ chuyển đổi.\"\n );\n }\n }\n\n // 7. Ràng buộc theo từng loại Ad đặc thù\n if (payload.Type === VALID_AD_TYPES.FORM) {\n if (!payload.ZaloFormId || !payload.ZaloFormId.trim()) {\n errors.push(\"ZaloFormId là bắt buộc đối với Quảng cáo Form (Ad Type 18).\");\n }\n } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {\n if (!payload.Settings?.Image?.LogoUrl) {\n errors.push(\"Settings.Image.LogoUrl là bắt buộc đối với Quảng cáo Tin Nhắn (Ad Type 30).\");\n }\n if (!payload.MiniPageId || payload.MiniPageId <= 0) {\n errors.push(\n \"MiniPageId là bắt buộc đối với Quảng cáo Tin Nhắn (Ad Type 30, Template 4 - Kịch bản giới thiệu thương hiệu / Tin nhắn). Nếu thiếu hoặc = 0, máy chủ Zalo Ads sẽ từ chối với lỗi: 'Mini Page không hợp lệ.'.\"\n );\n }\n if (!payload.ZaloFlowId) {\n warnings.push(\"Quảng cáo Tin Nhắn nên gắn ZaloFlowId để tự động kích hoạt kịch bản chatbot tương tác khi người dùng mở tin nhắn.\");\n }\n if ((payload.Settings?.Image as any)?.ExtraImgs && (payload.Settings?.Image as any)?.ExtraImgs.length > 0) {\n errors.push(\n \"Quảng cáo Tin Nhắn định dạng ảnh đơn (Landscape Cover) không được truyền mảng 'ExtraImgs'. Nếu truyền thừa sẽ bị máy chủ báo lỗi 'Dữ liệu không hợp lệ'.\"\n );\n }\n } else if (payload.Type === VALID_AD_TYPES.COMMERCE) {\n if (!payload.MiniPageId || payload.MiniPageId <= 0) {\n errors.push(\"MiniPageId là bắt buộc đối với Quảng cáo Commerce (Ad Type 28, Template 1/2/3).\");\n }\n } else if (payload.Type === VALID_AD_TYPES.VIDEO) {\n if (!payload.ZaloVideoId && !payload.Settings?.Image?.VideoUrl) {\n errors.push(\"ZaloVideoId hoặc Settings.Image.VideoUrl là bắt buộc đối với Quảng cáo Video (Ad Type 11).\");\n }\n if (payload.Settings?.Image?.VideoUrl && !payload.Settings.Image.VideoUrl.includes(\"zascdn.me\")) {\n warnings.push(\"VideoUrl nên là đường dẫn CDN chính thức của Zalo Ads (*.zascdn.me).\");\n }\n } else if (payload.Type === VALID_AD_TYPES.ARTICLE) {\n if (!payload.ZaloFeedId && !(payload as any).articleId) {\n errors.push(\"ZaloFeedId hoặc articleId là bắt buộc đối với Quảng cáo Bài Viết (Ad Type 3).\");\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của tham số đổi tên chiến dịch (POST /api/campaign/change-name).\n */\nexport function validateRenameCampaignParams(params: {\n campid?: number;\n campaignId?: number;\n newname?: string;\n newName?: string;\n name?: string;\n}): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const id = params.campid || params.campaignId;\n const name = params.newname || params.newName || params.name;\n\n if (!id || id <= 0) {\n errors.push(\"ID chiến dịch (campid/campaignId) là bắt buộc và phải > 0.\");\n }\n if (!name || !name.trim()) {\n errors.push(\"Tên mới của chiến dịch (newname/name) là bắt buộc và không được để trống.\");\n } else if (name.length > 255) {\n errors.push(`Tên chiến dịch quá dài (${name.length}/255 ký tự).`);\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của trạng thái thay đổi chiến dịch (POST /api/campaign/change-status).\n */\nexport function validateChangeCampaignStatusParams(params: {\n campaignId: number;\n status: number;\n isDraft?: boolean;\n}): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!params.campaignId || params.campaignId <= 0) {\n errors.push(\"campaignId là bắt buộc và phải > 0.\");\n }\n\n // Các trạng thái hỗ trợ: 1 = Tiếp tục / Bật, 0 = Tắt, 2 = Tạm dừng, -2 = Xóa\n if (![0, 1, 2, -2].includes(params.status)) {\n errors.push(`status: ${params.status} không hợp lệ. Các trạng thái hợp lệ: 1 (Bật), 0 (Tắt), 2 (Tạm dừng), -2 (Xóa).`);\n }\n\n // Bẫy HTTP 500 khi tạm dừng chiến dịch nháp chưa có Ad duyệt\n if (params.status === 2 && params.isDraft) {\n warnings.push(\n \"Chiến dịch nháp chưa có quảng cáo hoạt động khi gọi status: 2 (Tạm dừng) sẽ bị máy chủ ném lỗi HTTP 500 Internal Server Error. Để dọn dẹp hãy dùng status: -2 (Xóa).\"\n );\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của tham số nhân bản quảng cáo (POST /zaapi/DuplicateAd).\n */\nexport function validateDuplicateAdParams(params: {\n adid?: number;\n adId?: number;\n}): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n const id = params.adid || params.adId;\n if (!id || id <= 0) {\n errors.push(\"ID mẫu quảng cáo gốc cần nhân bản (adid/adId) là bắt buộc và phải > 0.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của tham số cắt/tải ảnh quảng cáo (POST /api/ads/upload-crop / updateNewAds).\n */\nexport function validateCropCoordinates(\n input: unknown\n): CampaignValidationResult<ZaloAdsUpdateNewAdsRequest> {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu cắt/tải ảnh quảng cáo phải là một đối tượng.\"],\n warnings,\n };\n }\n\n const raw = input as Record<string, unknown>;\n const file = raw.File ?? raw.file;\n\n if (!file) {\n errors.push(\"Trường tệp ảnh ('File') là bắt buộc.\");\n } else if (typeof file === \"string\" && !/^(https?:\\/\\/|data:image\\/)/i.test(file.trim())) {\n errors.push(\"Đường dẫn tệp ảnh ('File') phải là URL HTTP/HTTPS hoặc data URL hợp lệ.\");\n }\n\n const x = raw.x !== undefined ? Number(raw.x) : 0;\n const y = raw.y !== undefined ? Number(raw.y) : 0;\n const width = raw.width !== undefined ? Number(raw.width) : 0;\n const height = raw.height !== undefined ? Number(raw.height) : 0;\n const scale = raw.scale !== undefined ? Number(raw.scale) : 1;\n\n if (isNaN(x) || x < 0) {\n errors.push(`Tọa độ x không hợp lệ: '${raw.x}'. Phải là số không âm (>= 0).`);\n }\n if (isNaN(y) || y < 0) {\n errors.push(`Tọa độ y không hợp lệ: '${raw.y}'. Phải là số không âm (>= 0).`);\n }\n if (isNaN(width) || width < 0) {\n errors.push(`Chiều rộng khung cắt ('width') không hợp lệ: '${raw.width}'. Phải là số không âm.`);\n }\n if (isNaN(height) || height < 0) {\n errors.push(`Chiều cao khung cắt ('height') không hợp lệ: '${raw.height}'. Phải là số không âm.`);\n }\n if (isNaN(scale) || scale <= 0) {\n errors.push(`Tỷ lệ co dãn ('scale') không hợp lệ: '${raw.scale}'. Phải là số dương (> 0).`);\n }\n\n if ((width > 0 && height === 0) || (height > 0 && width === 0)) {\n errors.push(\"Khi đã chỉ định cắt ảnh, cả 'width' và 'height' đều phải lớn hơn 0.\");\n }\n\n if (width > 0 && height > 0) {\n const ratio = width / height;\n const isLandscape = Math.abs(ratio - 1.92) < 0.2 || Math.abs(ratio - 1.91) < 0.2 || Math.abs(ratio - 1.78) < 0.2;\n const isSquare = Math.abs(ratio - 1.0) < 0.05;\n const isVertical = Math.abs(ratio - 0.5625) < 0.1;\n if (!isLandscape && !isSquare && !isVertical) {\n warnings.push(`Tỷ lệ khung cắt (${width}x${height} ~ ${ratio.toFixed(2)}:1) khác các tỷ lệ chuẩn của Zalo Ads (16:9 / 1.92:1 ngang, 1:1 vuông hoặc 9:16 dọc). Hãy kiểm tra hiển thị thực tế.`);\n }\n }\n\n const cleanData: ZaloAdsUpdateNewAdsRequest = {\n File: file as any,\n x,\n y,\n width,\n height,\n scale,\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n\n/**\n * 1. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Commerce (Shop)\n * Bắt buộc: \"Tên chiến dịch\" (name) và tài khoản OA chọn từ \"Danh sách tài khoản OA\" (pageId > 0).\n */\nexport function validateCreateCommerceCampaign(\n payload: Partial<ZaloAdsCreateCommerceCampaignPayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\n }\n\n if (!payload.pageId || payload.pageId <= 0) {\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Commerce (chọn từ Danh sách tài khoản OA, phải > 0).\");\n }\n\n if (payload.productId === undefined || payload.productId === null || payload.productId <= 0) {\n warnings.push(\"Quảng cáo Commerce nên chỉ định productId (hoặc -1/0 khi dùng Instant Page sản phẩm).\");\n }\n\n return { isValid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 2. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Display\n * Bắt buộc: \"Tên chiến dịch\" (name).\n */\nexport function validateCreateDisplayCampaign(\n payload: Partial<ZaloAdsCreateDisplayCampaignPayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\n }\n\n if (payload.targetUrl && !/^https?:\\/\\/.+/i.test(payload.targetUrl)) {\n errors.push(\"targetUrl phải là một đường link hợp lệ bắt đầu bằng http:// hoặc https://.\");\n }\n\n return { isValid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 3. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Website\n * Bắt buộc: \"Tên chiến dịch\" (name), \"Liên kết website\" (targetUrl).\n * Tùy chọn: Tài khoản OA (\"Danh sách tài khoản OA\" - không bắt buộc).\n */\nexport function validateCreateWebsiteCampaign(\n payload: Partial<ZaloAdsCreateWebsiteCampaignPayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\n }\n\n if (!payload.targetUrl || typeof payload.targetUrl !== \"string\" || !payload.targetUrl.trim()) {\n errors.push(\"Liên kết website ('targetUrl') là bắt buộc đối với Quảng cáo Website.\");\n } else if (!/^https?:\\/\\/.+/i.test(payload.targetUrl)) {\n errors.push(\"Liên kết website ('targetUrl') phải là đường link hợp lệ bắt đầu bằng http:// hoặc https://.\");\n }\n\n return { isValid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 4. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Form (Biểu mẫu)\n * Bắt buộc: \"Tên chiến dịch\" (name), tài khoản OA trong \"Danh sách tài khoản OA\" (pageId > 0).\n */\nexport function validateCreateFormCampaign(\n payload: Partial<ZaloAdsCreateFormCampaignPayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\n }\n\n if (!payload.pageId || payload.pageId <= 0) {\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Form (chọn từ Danh sách tài khoản OA, phải > 0).\");\n }\n\n return { isValid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 5. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Tin nhắn\n * Bắt buộc: \"Tên chiến dịch\" (name), tài khoản OA trong \"Danh sách tài khoản OA\" (pageId > 0).\n */\nexport function validateCreateMessageCampaign(\n payload: Partial<ZaloAdsCreateMessageCampaignPayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\n }\n\n if (!payload.pageId || payload.pageId <= 0) {\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Tin nhắn (chọn từ Danh sách tài khoản OA, phải > 0).\");\n }\n\n return { isValid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 6. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Zalo Official Account\n * Bắt buộc: \"Tên chiến dịch\" (name), tài khoản OA trong \"Danh sách tài khoản OA\" (pageId > 0).\n */\nexport function validateCreateOfficialAccountCampaign(\n payload: Partial<ZaloAdsCreateOfficialAccountCampaignPayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\n }\n\n if (!payload.pageId || payload.pageId <= 0) {\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Zalo Official Account (chọn từ Danh sách tài khoản OA, phải > 0).\");\n }\n\n return { isValid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 7. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Bài viết\n * Bắt buộc: \"Tên chiến dịch\" (name), tài khoản OA trong \"Danh sách tài khoản OA\" (pageId > 0), bài viết trong \"Danh sách bài viết của OA đó\" (articleId > 0).\n */\nexport function validateCreateArticleCampaign(\n payload: Partial<ZaloAdsCreateArticleCampaignPayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\n }\n\n if (!payload.pageId || payload.pageId <= 0) {\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Bài viết (chọn từ Danh sách tài khoản OA, phải > 0).\");\n }\n\n if (!payload.articleId || payload.articleId <= 0) {\n errors.push(\"Bài viết ('articleId') là bắt buộc đối với Quảng cáo Bài viết (chọn từ Danh sách bài viết của OA đó, lấy qua getOwnedArticles).\");\n }\n\n return { isValid: errors.length === 0, errors, warnings };\n}\n\n/**\n * 8. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Video\n * Bắt buộc: \"Tên chiến dịch\" (name), \"Liên kết Website\" (targetUrl).\n * Tùy chọn: Tài khoản OA trong \"Danh sách tài khoản OA\" (không bắt buộc).\n */\nexport function validateCreateVideoCampaign(\n payload: Partial<ZaloAdsCreateVideoCampaignPayloadDto>,\n options: ValidateCampaignOptions = {}\n): CampaignValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\n } else if (payload.name.length > 255) {\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\n }\n\n if (!payload.targetUrl || typeof payload.targetUrl !== \"string\" || !payload.targetUrl.trim()) {\n errors.push(\"Liên kết Website ('targetUrl') là bắt buộc đối với Quảng cáo Video.\");\n } else if (!/^https?:\\/\\/.+/i.test(payload.targetUrl)) {\n errors.push(\"Liên kết Website ('targetUrl') phải là đường link hợp lệ bắt đầu bằng http:// hoặc https://.\");\n }\n\n return { isValid: errors.length === 0, errors, warnings };\n}\n\n// -------------------------------------------------------------\n// BỘ HÀM KIỂM TRA TỪNG LOẠI MẪU QUẢNG CÁO CẬP NHẬT (Update Ad)\n// -------------------------------------------------------------\n\nexport function validateUpdateWebsiteAd(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.WEBSITE }, options);\n}\n\nexport function validateUpdateDisplayAd(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.DISPLAY }, options);\n}\n\nexport function validateUpdateVideoAd(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.VIDEO }, options);\n}\n\nexport function validateUpdateCommerceAd(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.COMMERCE }, options);\n}\n\nexport function validateUpdateFormAd(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.FORM }, options);\n}\n\nexport function validateUpdateMessageAd(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.MESSAGE }, options);\n}\n\nexport function validateUpdateOfficialAccountAd(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.OA }, options);\n}\n\nexport function validateUpdateArticleAd(\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\n options: ValidateAdOptions = {}\n): CampaignValidationResult {\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.ARTICLE }, options);\n}\n\n\nexport const ZaloCampaignsValidator = {\n // Generic\n createCampaign: validateCreateCampaignPayload,\n updateAd: validateUpdateAdPayload,\n renameCampaign: validateRenameCampaignParams,\n changeStatus: validateChangeCampaignStatusParams,\n duplicateAd: validateDuplicateAdParams,\n validateCropCoordinates,\n validateUploadCropAdImage: validateCropCoordinates,\n\n // Specific Create Campaign\n createCommerceCampaign: validateCreateCommerceCampaign,\n createDisplayCampaign: validateCreateDisplayCampaign,\n createWebsiteCampaign: validateCreateWebsiteCampaign,\n createFormCampaign: validateCreateFormCampaign,\n createMessageCampaign: validateCreateMessageCampaign,\n createOfficialAccountCampaign: validateCreateOfficialAccountCampaign,\n createArticleCampaign: validateCreateArticleCampaign,\n createVideoCampaign: validateCreateVideoCampaign,\n\n // Specific Update Ad\n updateWebsiteAd: validateUpdateWebsiteAd,\n updateDisplayAd: validateUpdateDisplayAd,\n updateVideoAd: validateUpdateVideoAd,\n updateCommerceAd: validateUpdateCommerceAd,\n updateFormAd: validateUpdateFormAd,\n updateMessageAd: validateUpdateMessageAd,\n updateOfficialAccountAd: validateUpdateOfficialAccountAd,\n updateArticleAd: validateUpdateArticleAd,\n};\n\n","/**\r\n * Dịch vụ Quản lý Chiến dịch & Quảng cáo Zalo Ads (Tạo chiến dịch, đổi trạng thái, cập nhật quảng cáo các định dạng).\r\n */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/ads.dto\";\r\nimport { ZaloCampaignsValidator } from \"../validators/campaigns.validator\";\r\n\r\n\r\nconst OP_ZaloAdsUpdateVideoAd: OperationDefinition = {\r\n operationId: \"ZaloAds_updateVideoAd\",\r\n method: \"POST\",\r\n endpoint: \"/zaapi/UpdateAd\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"data\", \"est\", \"isBoostAd\", \"stt\"]\r\n};\r\n\r\nconst OP_ZaloAdsChangeCampaignStatus: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_changeCampaignStatus\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/campaign/change-status\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"status\",\r\n \"campaignId\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateEcommerceCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createEcommerceCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateForm: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createForm\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/form/create\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateFormCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createFormCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateMessageCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createMessageCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateOfficialAccountCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createOfficialAccountCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreatePostCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createPostCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsGetAdById: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getAdById\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getAdFromAdId\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"adId\",\r\n \"v\",\r\n \"newWard\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetAdChangeLog: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getAdChangeLog\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/ad/log/{adId}\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"adId\"\r\n ],\r\n \"queryFields\": [\r\n \"type\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetApiPlaceGetalldistricts: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getApiPlaceGetalldistricts\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/place/getAllDistricts\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetApiSpellCheckV2: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getApiSpellCheckV2\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/spell-check/v2\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"text\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiCheckcamphasmanyads: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiCheckcamphasmanyads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/checkCampHasManyAds\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"campaignId\",\r\n \"campId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiGetadsfromcampaignid: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiGetadsfromcampaignid\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getAdsFromCampaignId\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"campaignId\",\r\n \"campId\",\r\n \"dataType\",\r\n \"v\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiGetallpages: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiGetallpages\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getAllPages\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiGetownedarticles: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiGetownedarticles\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getOwnedArticles\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"pageId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiGetownedpages: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiGetownedpages\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getOwnedPages\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsListFormsByOfficialAccount: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listFormsByOfficialAccount\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/form/getByOaId\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"isAll\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsListMiniPagesByTemplate: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listMiniPagesByTemplate\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/mini-pages\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"templateIds\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsPostZaapiDeletead: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_postZaapiDeletead\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/deleteAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"adId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"adId\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsRenameCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_renameCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/campaign/change-name\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"campid\",\r\n \"newname\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateEcommerceAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateEcommerceAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateFormAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateFormAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateMessageAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateMessageAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateNewAds: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_UpdateNewAds\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UploadCrop\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [\r\n \"File\"\r\n ],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"File\",\r\n \"x\",\r\n \"y\",\r\n \"width\",\r\n \"height\",\r\n \"scale\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateOfficialAccountAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateOfficialAccountAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdatePostAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updatePostAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateWebsiteCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createWebsiteCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateWebsiteAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateWebsiteAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateDisplayCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createDisplayCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateDisplayAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateDisplayAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateVideoCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createVideoCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsDeleteCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_deleteCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/campaign/change-status\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"campaignId\",\r\n \"status\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsDuplicateAd: OperationDefinition = {\r\n operationId: \"zalo_ads_duplicate_ad\",\r\n method: \"POST\",\r\n endpoint: \"/zaapi/DuplicateAd\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"adid\"]\r\n};\r\n\r\nconst OP_ZaloAdsCreateSpellCheckV3Job: OperationDefinition = {\r\n operationId: \"zalo_ads_create_spell_check_v3_job\",\r\n method: \"POST\",\r\n endpoint: \"/api/spell-check/v3\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"title\", \"caption\"]\r\n};\r\n\r\nconst OP_ZaloAdsGetSpellCheckV3Job: OperationDefinition = {\r\n operationId: \"zalo_ads_get_spell_check_v3_job\",\r\n method: \"GET\",\r\n endpoint: \"/api/spell-check/v3/{jobId}\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [\"jobId\"],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: []\r\n};\r\n\r\nexport class ZaloCampaignsService {\r\n public readonly validator = ZaloCampaignsValidator;\r\n public static readonly validator = ZaloCampaignsValidator;\r\n\r\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\r\n\r\n public updateVideoAd(request: Dto.ZaloAdsUpdateVideoAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateVideoAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateVideoAdResponse>(OP_ZaloAdsUpdateVideoAd, this.client.toTransportInput(OP_ZaloAdsUpdateVideoAd, request as unknown as Record<string, unknown>), options);\r\n }\r\n\r\n public changeCampaignStatus(request: Dto.ZaloAdsChangeCampaignStatusRequest, options?: RequestOptions): Promise<Dto.ZaloAdsChangeCampaignStatusResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsChangeCampaignStatusResponse>(OP_ZaloAdsChangeCampaignStatus, this.client.toTransportInput(OP_ZaloAdsChangeCampaignStatus, request as Record<string, unknown>), options);\r\n }\r\n\r\n public deleteCampaign(request: Dto.ZaloAdsDeleteCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCampaignResponse> {\r\n const payload = { campaignId: request.campaignId, status: request.status ?? -2 };\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsDeleteCampaignResponse>(OP_ZaloAdsDeleteCampaign, this.client.toTransportInput(OP_ZaloAdsDeleteCampaign, payload as Record<string, unknown>), options);\r\n }\r\n\r\n public createWebsiteCampaign(request: Dto.ZaloAdsCreateWebsiteCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateWebsiteCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateWebsiteCampaignResponse>(OP_ZaloAdsCreateWebsiteCampaign, this.client.toTransportInput(OP_ZaloAdsCreateWebsiteCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public updateWebsiteAd(request: Dto.ZaloAdsUpdateWebsiteAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateWebsiteAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateWebsiteAdResponse>(OP_ZaloAdsUpdateWebsiteAd, this.client.toTransportInput(OP_ZaloAdsUpdateWebsiteAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createDisplayCampaign(request: Dto.ZaloAdsCreateDisplayCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateDisplayCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateDisplayCampaignResponse>(OP_ZaloAdsCreateDisplayCampaign, this.client.toTransportInput(OP_ZaloAdsCreateDisplayCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public updateDisplayAd(request: Dto.ZaloAdsUpdateDisplayAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateDisplayAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateDisplayAdResponse>(OP_ZaloAdsUpdateDisplayAd, this.client.toTransportInput(OP_ZaloAdsUpdateDisplayAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createVideoCampaign(request: Dto.ZaloAdsCreateVideoCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateVideoCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateVideoCampaignResponse>(OP_ZaloAdsCreateVideoCampaign, this.client.toTransportInput(OP_ZaloAdsCreateVideoCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createEcommerceCampaign(request: Dto.ZaloAdsCreateEcommerceCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateEcommerceCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateEcommerceCampaignResponse>(OP_ZaloAdsCreateEcommerceCampaign, this.client.toTransportInput(OP_ZaloAdsCreateEcommerceCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_create_commerce_campaign` trong Project Schema Zalo ADS (`campaignType = 22`). */\r\n public createCommerceCampaign(request: Dto.ZaloAdsCreateCommerceCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCommerceCampaignResponse> {\r\n return this.createEcommerceCampaign(request, options);\r\n }\r\n\r\n public createForm(request: Dto.ZaloAdsCreateFormRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateFormResponse>(OP_ZaloAdsCreateForm, this.client.toTransportInput(OP_ZaloAdsCreateForm, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createFormCampaign(request: Dto.ZaloAdsCreateFormCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateFormCampaignResponse>(OP_ZaloAdsCreateFormCampaign, this.client.toTransportInput(OP_ZaloAdsCreateFormCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createMessageCampaign(request: Dto.ZaloAdsCreateMessageCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateMessageCampaignResponse>(OP_ZaloAdsCreateMessageCampaign, this.client.toTransportInput(OP_ZaloAdsCreateMessageCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createOfficialAccountCampaign(request: Dto.ZaloAdsCreateOfficialAccountCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateOfficialAccountCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateOfficialAccountCampaignResponse>(OP_ZaloAdsCreateOfficialAccountCampaign, this.client.toTransportInput(OP_ZaloAdsCreateOfficialAccountCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_create_oa_campaign` trong Project Schema Zalo ADS (`campaignType = 3`). */\r\n public createOaCampaign(request: Dto.ZaloAdsCreateOaCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateOaCampaignResponse> {\r\n return this.createOfficialAccountCampaign(request, options);\r\n }\r\n\r\n public createPostCampaign(request: Dto.ZaloAdsCreatePostCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreatePostCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreatePostCampaignResponse>(OP_ZaloAdsCreatePostCampaign, this.client.toTransportInput(OP_ZaloAdsCreatePostCampaign, request as unknown as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_create_article_campaign` trong Project Schema Zalo ADS (`campaignType = 4`). */\r\n public createArticleCampaign(request: Dto.ZaloAdsCreateArticleCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateArticleCampaignResponse> {\r\n return this.createPostCampaign(request, options);\r\n }\r\n\r\n public getAdById(request: Dto.ZaloAdsGetAdByIdRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetAdByIdResponse> {\r\n const normalized = {\r\n adId: request.adId,\r\n v: request.v ?? 2,\r\n newWard: request.newWard ?? true\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetAdByIdResponse>(OP_ZaloAdsGetAdById, this.client.toTransportInput(OP_ZaloAdsGetAdById, normalized as Record<string, unknown>), options);\r\n }\r\n\r\n public getAdChangeLog(request: Dto.ZaloAdsGetAdChangeLogRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAdChangeLogResponse> {\r\n const normalized = {\r\n adId: request.adId,\r\n type: (request as any).type ?? 1\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetAdChangeLogResponse>(OP_ZaloAdsGetAdChangeLog, this.client.toTransportInput(OP_ZaloAdsGetAdChangeLog, normalized), options);\r\n }\r\n\r\n public getApiPlaceGetalldistricts(request: Dto.ZaloAdsGetApiPlaceGetalldistrictsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiPlaceGetalldistrictsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiPlaceGetalldistrictsResponse>(OP_ZaloAdsGetApiPlaceGetalldistricts, this.client.toTransportInput(OP_ZaloAdsGetApiPlaceGetalldistricts, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getApiSpellCheckV2(request: Dto.ZaloAdsGetApiSpellCheckV2Request, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiSpellCheckV2Response> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiSpellCheckV2Response>(OP_ZaloAdsGetApiSpellCheckV2, this.client.toTransportInput(OP_ZaloAdsGetApiSpellCheckV2, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getZaapiCheckcamphasmanyads(request: Dto.ZaloAdsGetZaapiCheckcamphasmanyadsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiCheckcamphasmanyadsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiCheckcamphasmanyadsResponse>(OP_ZaloAdsGetZaapiCheckcamphasmanyads, this.client.toTransportInput(OP_ZaloAdsGetZaapiCheckcamphasmanyads, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getZaapiGetadsfromcampaignid(request: Dto.ZaloAdsGetZaapiGetadsfromcampaignidRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetadsfromcampaignidResponse> {\r\n const normalized = {\r\n campaignId: request.campaignId ?? request.campId,\r\n dataType: request.dataType ?? 1,\r\n v: request.v ?? 2,\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiGetadsfromcampaignidResponse>(OP_ZaloAdsGetZaapiGetadsfromcampaignid, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetadsfromcampaignid, normalized as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias lấy danh sách quảng cáo của chiến dịch kèm metadata extend và extra.appliedRuleInfo */\r\n public getAdsFromCampaignId(request: Dto.ZaloAdsGetZaapiGetadsfromcampaignidRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetadsfromcampaignidResponse> {\r\n return this.getZaapiGetadsfromcampaignid(request, options);\r\n }\r\n\r\n public getZaapiGetallpages(request: Dto.ZaloAdsGetZaapiGetallpagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetallpagesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiGetallpagesResponse>(OP_ZaloAdsGetZaapiGetallpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetallpages, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getAllPages(request: Dto.ZaloAdsGetZaapiGetallpagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetallpagesResponse> {\r\n return this.getZaapiGetallpages(request, options);\r\n }\r\n\r\n public getZaapiGetownedarticles(request: Dto.ZaloAdsGetZaapiGetownedarticlesRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetownedarticlesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiGetownedarticlesResponse>(OP_ZaloAdsGetZaapiGetownedarticles, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedarticles, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getOwnedArticles(request: Dto.ZaloAdsGetZaapiGetownedarticlesRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetownedarticlesResponse> {\r\n return this.getZaapiGetownedarticles(request, options);\r\n }\r\n\r\n public getZaapiGetownedpages(request: Dto.ZaloAdsGetZaapiGetownedpagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetownedpagesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiGetownedpagesResponse>(OP_ZaloAdsGetZaapiGetownedpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedpages, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getOwnedPages(request: Dto.ZaloAdsGetZaapiGetownedpagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetownedpagesResponse> {\r\n return this.getZaapiGetownedpages(request, options);\r\n }\r\n\r\n public listFormsByOfficialAccount(request: Dto.ZaloAdsListFormsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListFormsByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListFormsByOfficialAccountResponse>(OP_ZaloAdsListFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n\r\n public listMiniPagesByTemplate(request: Dto.ZaloAdsListMiniPagesByTemplateRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListMiniPagesByTemplateResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListMiniPagesByTemplateResponse>(OP_ZaloAdsListMiniPagesByTemplate, this.client.toTransportInput(OP_ZaloAdsListMiniPagesByTemplate, request as Record<string, unknown>), options);\r\n }\r\n\r\n public postZaapiDeletead(request: Dto.ZaloAdsPostZaapiDeleteadRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsPostZaapiDeleteadResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsPostZaapiDeleteadResponse>(OP_ZaloAdsPostZaapiDeletead, this.client.toTransportInput(OP_ZaloAdsPostZaapiDeletead, request as Record<string, unknown>), options);\r\n }\r\n\r\n public renameCampaign(request: Dto.ZaloAdsRenameCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsRenameCampaignResponse> {\r\n const normalized = {\r\n campid: (request as any).campid ?? (request as any).campaignId,\r\n newname: (request as any).newname ?? (request as any).campaignName ?? (request as any).name\r\n };\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsRenameCampaignResponse>(OP_ZaloAdsRenameCampaign, this.client.toTransportInput(OP_ZaloAdsRenameCampaign, normalized), options);\r\n }\r\n\r\n public updateEcommerceAd(request: Dto.ZaloAdsUpdateEcommerceAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateEcommerceAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateEcommerceAdResponse>(OP_ZaloAdsUpdateEcommerceAd, this.client.toTransportInput(OP_ZaloAdsUpdateEcommerceAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_update_commerce_ad` trong Project Schema Zalo ADS (`Type = 23`, gắn `MiniPageId`). */\r\n public updateCommerceAd(request: Dto.ZaloAdsUpdateCommerceAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateCommerceAdResponse> {\r\n return this.updateEcommerceAd(request, options);\r\n }\r\n\r\n public updateFormAd(request: Dto.ZaloAdsUpdateFormAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateFormAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateFormAdResponse>(OP_ZaloAdsUpdateFormAd, this.client.toTransportInput(OP_ZaloAdsUpdateFormAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n public updateMessageAd(request: Dto.ZaloAdsUpdateMessageAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateMessageAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateMessageAdResponse>(OP_ZaloAdsUpdateMessageAd, this.client.toTransportInput(OP_ZaloAdsUpdateMessageAd, request as unknown as Record<string, unknown>), options);\r\n }\r\n\r\n public updateNewAds(request: Dto.ZaloAdsUpdateNewAdsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateNewAdsResponse> {\r\n return this.client.requestMultipart<Dto.ZaloAdsUpdateNewAdsResponse>(OP_ZaloAdsUpdateNewAds, this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request as Record<string, unknown>), options);\r\n }\r\n\r\n public updateOfficialAccountAd(request: Dto.ZaloAdsUpdateOfficialAccountAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateOfficialAccountAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateOfficialAccountAdResponse>(OP_ZaloAdsUpdateOfficialAccountAd, this.client.toTransportInput(OP_ZaloAdsUpdateOfficialAccountAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_update_oa_ad` trong Project Schema Zalo ADS (`Type = 2`, `Action = 6`). */\r\n public updateOaAd(request: Dto.ZaloAdsUpdateOaAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateOaAdResponse> {\r\n return this.updateOfficialAccountAd(request, options);\r\n }\r\n\r\n public updatePostAd(request: Dto.ZaloAdsUpdatePostAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdatePostAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdatePostAdResponse>(OP_ZaloAdsUpdatePostAd, this.client.toTransportInput(OP_ZaloAdsUpdatePostAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_update_article_ad` trong Project Schema Zalo ADS (`Type = 3`, gắn `ZaloFeedId`). */\r\n public updateArticleAd(request: Dto.ZaloAdsUpdateArticleAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateArticleAdResponse> {\r\n return this.updatePostAd(request, options);\r\n }\r\n\r\n /** Xóa quảng cáo */\r\n public deleteAd(...args: Parameters<this[\"postZaapiDeletead\"]>): ReturnType<this[\"postZaapiDeletead\"]> {\r\n return (this.postZaapiDeletead as any)(...args);\r\n }\r\n\r\n /** Danh sách quận/huyện để nhắm mục tiêu */\r\n public getAllDistricts(...args: Parameters<this[\"getApiPlaceGetalldistricts\"]>): ReturnType<this[\"getApiPlaceGetalldistricts\"]> {\r\n return (this.getApiPlaceGetalldistricts as any)(...args);\r\n }\r\n\r\n /** Kiểm tra chính tả văn bản quảng cáo */\r\n public getSpellCheckV2(...args: Parameters<this[\"getApiSpellCheckV2\"]>): ReturnType<this[\"getApiSpellCheckV2\"]> {\r\n return (this.getApiSpellCheckV2 as any)(...args);\r\n }\r\n\r\n /**\r\n * Khởi tạo tác vụ kiểm tra chính tả và vi phạm quy chuẩn quảng cáo AI V3 (POST /api/spell-check/v3).\r\n */\r\n public createSpellCheckV3Job(\r\n request: Dto.ZaloAdsCreateSpellCheckV3JobRequest,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloAdsCreateSpellCheckV3JobResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsCreateSpellCheckV3JobResponse>(\r\n OP_ZaloAdsCreateSpellCheckV3Job,\r\n this.client.toTransportInput(OP_ZaloAdsCreateSpellCheckV3Job, request as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n\r\n /**\r\n * Lấy kết quả kiểm tra chính tả AI V3 theo jobId (GET /api/spell-check/v3/{jobId}).\r\n */\r\n public getSpellCheckV3Job(\r\n request: Dto.ZaloAdsGetSpellCheckV3JobRequest,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloAdsGetSpellCheckV3JobResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetSpellCheckV3JobResponse>(\r\n OP_ZaloAdsGetSpellCheckV3Job,\r\n this.client.toTransportInput(OP_ZaloAdsGetSpellCheckV3Job, request as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n\r\n /**\r\n * Helper kiểm tra chính tả AI V3 trọn gói: Gửi kiểm tra và tự động polling cho đến khi hoàn thành (hoặc timeout).\r\n * @param request Tiêu đề (title) và chú thích (caption) cần kiểm tra.\r\n * @param pollIntervalMs Chu kỳ polling kiểm tra trạng thái (mặc định: 600ms).\r\n * @param timeoutMs Thời gian chờ tối đa (mặc định: 15.000ms = 15 giây).\r\n */\r\n public async checkSpellV3AndWait(\r\n request: Dto.ZaloAdsCreateSpellCheckV3JobRequest,\r\n pollIntervalMs: number = 600,\r\n timeoutMs: number = 15000,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloAdsGetSpellCheckV3JobResponse> {\r\n const jobRes = await this.createSpellCheckV3Job(request, options);\r\n const jobId = jobRes?.data?.jobId;\r\n if (!jobId) {\r\n throw new Error(`[SpellCheckV3] Không nhận được jobId từ Zalo Ads (code: ${jobRes?.code})`);\r\n }\r\n\r\n const startTime = Date.now();\r\n while (Date.now() - startTime < timeoutMs) {\r\n await new Promise(r => setTimeout(r, pollIntervalMs));\r\n const res = await this.getSpellCheckV3Job({ jobId }, options);\r\n if (res?.data?.status === \"COMPLETED\") {\r\n return res;\r\n }\r\n }\r\n throw new Error(`[SpellCheckV3] Quá thời gian chờ (${timeoutMs}ms) cho tác vụ kiểm tra chính tả jobId: ${jobId}`);\r\n }\r\n\r\n\r\n /**\r\n * Nhân bản (sao chép / duplicate) một mẫu quảng cáo đã tồn tại trên Zalo Ads (POST /zaapi/DuplicateAd).\r\n * Giúp tạo nhanh một bản sao Ad mới trong cùng chiến dịch để thực hiện A/B testing.\r\n */\r\n public duplicateAd(\r\n request: Dto.ZaloAdsDuplicateAdRequest,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloAdsDuplicateAdResponse> {\r\n const payload = {\r\n adid: request.adid ?? request.adId\r\n };\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsDuplicateAdResponse>(\r\n OP_ZaloAdsDuplicateAd,\r\n this.client.toTransportInput(OP_ZaloAdsDuplicateAd, payload as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n\r\n}\r\n","/**\n * Dịch vụ Quản lý Tài khoản & Thanh toán Zalo Ads (whoami, transactions, BA accessors, agency).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\n\n\nconst OP_ZaloAdsGetApiWhoami: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiWhoami\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/whoami\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiPaymentTransactionHistory: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiPaymentTransactionHistory\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/payment/transaction-history\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"to\",\n \"from\",\n \"memberId\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiBaAccountAllaccessors: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiBaAccountAllaccessors\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ba/account/allAccessors\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"isShowAll\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiBaAccountAllgrantedmembers: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiBaAccountAllgrantedmembers\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ba/account/allGrantedMembers\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsListAgencyCustomersWithBudget: OperationDefinition = {\n \"operationId\": \"ZaloAds_listAgencyCustomersWithBudget\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ba/agency/customersWithBudget\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"limit\",\n \"offset\",\n \"joinDateAsc\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiBaAgencyEmployees: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiBaAgencyEmployees\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ba/agency/employees\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiNotifiesHeader: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiNotifiesHeader\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/notifies/header\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiLpNews: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiLpNews\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/lp-news\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nexport class ZaloAccountService {\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public getApiWhoami(request: Dto.ZaloAdsGetApiWhoamiRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiWhoamiResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiWhoamiResponse>(OP_ZaloAdsGetApiWhoami, this.client.toTransportInput(OP_ZaloAdsGetApiWhoami, request as Record<string, unknown>), options);\n }\n\n public getApiPaymentTransactionHistory(request: Dto.ZaloAdsGetApiPaymentTransactionHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiPaymentTransactionHistoryResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiPaymentTransactionHistoryResponse>(OP_ZaloAdsGetApiPaymentTransactionHistory, this.client.toTransportInput(OP_ZaloAdsGetApiPaymentTransactionHistory, request as Record<string, unknown>), options);\n }\n\n public getApiBaAccountAllaccessors(request: Dto.ZaloAdsGetApiBaAccountAllaccessorsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAccountAllaccessorsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiBaAccountAllaccessorsResponse>(OP_ZaloAdsGetApiBaAccountAllaccessors, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllaccessors, request as Record<string, unknown>), options);\n }\n\n public getApiBaAccountAllgrantedmembers(request: Dto.ZaloAdsGetApiBaAccountAllgrantedmembersRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAccountAllgrantedmembersResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiBaAccountAllgrantedmembersResponse>(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, request as Record<string, unknown>), options);\n }\n\n public listAgencyCustomersWithBudget(request: Dto.ZaloAdsListAgencyCustomersWithBudgetRequest = { limit: 15, offset: 0, joinDateAsc: true }, options?: RequestOptions): Promise<Dto.ZaloAdsListAgencyCustomersWithBudgetResponse> {\n const normalized: Record<string, unknown> = {\n limit: 15,\n offset: 0,\n joinDateAsc: true,\n ...request,\n };\n return this.client.requestWithoutBody<Dto.ZaloAdsListAgencyCustomersWithBudgetResponse>(OP_ZaloAdsListAgencyCustomersWithBudget, this.client.toTransportInput(OP_ZaloAdsListAgencyCustomersWithBudget, normalized), options);\n }\n\n public getApiBaAgencyEmployees(request: Dto.ZaloAdsGetApiBaAgencyEmployeesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAgencyEmployeesResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiBaAgencyEmployeesResponse>(OP_ZaloAdsGetApiBaAgencyEmployees, this.client.toTransportInput(OP_ZaloAdsGetApiBaAgencyEmployees, request as Record<string, unknown>), options);\n }\n\n public getApiNotifiesHeader(request: Dto.ZaloAdsGetApiNotifiesHeaderRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiNotifiesHeaderResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiNotifiesHeaderResponse>(OP_ZaloAdsGetApiNotifiesHeader, this.client.toTransportInput(OP_ZaloAdsGetApiNotifiesHeader, request as Record<string, unknown>), options);\n }\n\n public getApiLpNews(request: Dto.ZaloAdsGetApiLpNewsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiLpNewsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiLpNewsResponse>(OP_ZaloAdsGetApiLpNews, this.client.toTransportInput(OP_ZaloAdsGetApiLpNews, request as Record<string, unknown>), options);\n }\n\n /** Lấy thông tin tài khoản đang đăng nhập */\n public getWhoami(...args: Parameters<this[\"getApiWhoami\"]>): ReturnType<this[\"getApiWhoami\"]> {\n return (this.getApiWhoami as any)(...args);\n }\n\n /** Lịch sử giao dịch thanh toán */\n public getPaymentTransactionHistory(...args: Parameters<this[\"getApiPaymentTransactionHistory\"]>): ReturnType<this[\"getApiPaymentTransactionHistory\"]> {\n return (this.getApiPaymentTransactionHistory as any)(...args);\n }\n\n /** Danh sách accessor tài khoản BA */\n public getBaAccountAllAccessors(...args: Parameters<this[\"getApiBaAccountAllaccessors\"]>): ReturnType<this[\"getApiBaAccountAllaccessors\"]> {\n return (this.getApiBaAccountAllaccessors as any)(...args);\n }\n\n /** Danh sách thành viên được cấp quyền BA */\n public getBaAccountAllGrantedMembers(...args: Parameters<this[\"getApiBaAccountAllgrantedmembers\"]>): ReturnType<this[\"getApiBaAccountAllgrantedmembers\"]> {\n return (this.getApiBaAccountAllgrantedmembers as any)(...args);\n }\n\n /** Danh sách nhân viên trực thuộc Agency */\n public getBaAgencyEmployees(...args: Parameters<this[\"getApiBaAgencyEmployees\"]>): ReturnType<this[\"getApiBaAgencyEmployees\"]> {\n return (this.getApiBaAgencyEmployees as any)(...args);\n }\n\n /** Thông báo trên thanh tiêu đề */\n public getNotifiesHeader(...args: Parameters<this[\"getApiNotifiesHeader\"]>): ReturnType<this[\"getApiNotifiesHeader\"]> {\n return (this.getApiNotifiesHeader as any)(...args);\n }\n\n /** Tin tức landing page / bảng tin */\n public getLpNews(...args: Parameters<this[\"getApiLpNews\"]>): ReturnType<this[\"getApiLpNews\"]> {\n return (this.getApiLpNews as any)(...args);\n }\n}\n","/**\n * Dịch vụ Quản lý Đối tượng Tùy chỉnh & Ước tính Tiếp cận (Custom Audiences, Phone List, Lookalike, Event Audiences).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\nimport { ZaloAudiencesValidator } from \"../validators/audiences.validator\";\n\n\nconst OP_ZaloAdsCreateCustomAudience: OperationDefinition = {\n \"operationId\": \"ZaloAds_createCustomAudience\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/ad/audience\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"name\",\n \"caType\",\n \"targeting\"\n ]\n};\n\nconst OP_ZaloAdsDeleteCustomAudience: OperationDefinition = {\n \"operationId\": \"ZaloAds_deleteCustomAudience\",\n \"method\": \"DELETE\",\n \"endpoint\": \"/api/ad/audience/{customAudienceId}\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [\n \"customAudienceId\"\n ],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiAdGetlistadadvancetargeting: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiAdGetlistadadvancetargeting\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ad/getListAdAdvanceTargeting\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiCustomAudienceAll: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiCustomAudienceAll\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/custom-audience/all\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"newWard\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsPostApiAdEstimateaudience: OperationDefinition = {\n \"operationId\": \"ZaloAds_postApiAdEstimateaudience\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/ad/estimateAudience\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"gender\",\n \"number\",\n \"ageRanges\",\n \"locations\",\n \"platforms\",\n \"priceType\",\n \"provinces\",\n \"wardsTargeting\",\n \"districtsTargeting\"\n ]\n};\n\nconst OP_ZaloAdsUploadCustomAudiencePhoneList: OperationDefinition = {\n \"operationId\": \"ZaloAds_uploadCustomAudiencePhoneList\",\n \"method\": \"POST\",\n \"endpoint\": \"/zaapi/uploadPhoneList\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [\n \"File\"\n ],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"File\",\n \"isHash\"\n ]\n};\n\nexport class ZaloAudiencesService {\n public static readonly validator = ZaloAudiencesValidator;\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public postApiAdEstimateaudience(request: Dto.ZaloAdsPostApiAdEstimateaudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiAdEstimateaudienceResponse> {\n return this.client.requestJson<Dto.ZaloAdsPostApiAdEstimateaudienceResponse>(OP_ZaloAdsPostApiAdEstimateaudience, this.client.toTransportInput(OP_ZaloAdsPostApiAdEstimateaudience, request as Record<string, unknown>), options);\n }\n\n public getApiAdGetlistadadvancetargeting(request: Dto.ZaloAdsGetApiAdGetlistadadvancetargetingRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiAdGetlistadadvancetargetingResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiAdGetlistadadvancetargetingResponse>(OP_ZaloAdsGetApiAdGetlistadadvancetargeting, this.client.toTransportInput(OP_ZaloAdsGetApiAdGetlistadadvancetargeting, request as Record<string, unknown>), options);\n }\n\n public getApiCustomAudienceAll(request: Dto.ZaloAdsGetApiCustomAudienceAllRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiCustomAudienceAllResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiCustomAudienceAllResponse>(OP_ZaloAdsGetApiCustomAudienceAll, this.client.toTransportInput(OP_ZaloAdsGetApiCustomAudienceAll, request as Record<string, unknown>), options);\n }\n\n public createCustomAudience(request: Dto.ZaloAdsCreateCustomAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCustomAudienceResponse> {\n return this.client.requestJson<Dto.ZaloAdsCreateCustomAudienceResponse>(OP_ZaloAdsCreateCustomAudience, this.client.toTransportInput(OP_ZaloAdsCreateCustomAudience, request as Record<string, unknown>), options);\n }\n\n public deleteCustomAudience(request: Dto.ZaloAdsDeleteCustomAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCustomAudienceResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsDeleteCustomAudienceResponse>(OP_ZaloAdsDeleteCustomAudience, this.client.toTransportInput(OP_ZaloAdsDeleteCustomAudience, request as Record<string, unknown>), options);\n }\n\n public uploadCustomAudiencePhoneList(request: Dto.ZaloAdsUploadCustomAudiencePhoneListRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUploadCustomAudiencePhoneListResponse> {\n return this.client.requestMultipart<Dto.ZaloAdsUploadCustomAudiencePhoneListResponse>(OP_ZaloAdsUploadCustomAudiencePhoneList, this.client.toTransportInput(OP_ZaloAdsUploadCustomAudiencePhoneList, request as Record<string, unknown>), options);\n }\n\n /** Tạo mới 'Nhóm đối tượng đã lưu' (`caType = 1` - `DEFAULT`) trên Zalo Ads (`POST /api/ad/audience`). */\n public createSavedAudience(request: Dto.ZaloAdsCreateSavedAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateSavedAudienceResponse> {\n const targetingStr =\n typeof request.targeting === \"string\"\n ? request.targeting\n : JSON.stringify(request.targeting);\n return this.createCustomAudience(\n {\n name: request.name,\n caType: 1,\n targeting: targetingStr,\n },\n options\n );\n }\n\n /** Tạo mới Nhóm đối tượng từ danh sách Số điện thoại (`caType = 3` - `PHONE_LIST`). */\n public createPhoneAudience(request: Dto.ZaloAdsCreatePhoneAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreatePhoneAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 3, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng tương tự Lookalike (`caType = 6` - `LOOKALIKE`). */\n public createLookalikeAudience(request: Dto.ZaloAdsCreateLookalikeAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateLookalikeAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 6, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Zalo Form (`caType = 12` - `FORM_EVENT_AUDIENCE`). */\n public createFormEventAudience(request: Dto.ZaloAdsCreateFormEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormEventAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 12, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn OA (`caType = 11` - `MESSAGE_AUDIENCE`). */\n public createMessageOaEventAudience(request: Dto.ZaloAdsCreateMessageOaEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageOaEventAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 11, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn cá nhân (`caType = 14` - `MESSAGE_PERSONAL_EVENT_AUDIENCE`). */\n public createMessagePersonalEventAudience(request: Dto.ZaloAdsCreateMessagePersonalEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessagePersonalEventAudienceResponse> {\n let targetingObj: any;\n if (typeof request.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(request.targeting);\n } catch {\n targetingObj = null;\n }\n } else if (request.targeting && typeof request.targeting === \"object\") {\n targetingObj = { ...request.targeting };\n }\n if (targetingObj && typeof targetingObj === \"object\") {\n if (targetingObj.EventId === undefined && targetingObj.EventType !== undefined) {\n targetingObj.EventId = targetingObj.EventType;\n }\n }\n const targetingStr = targetingObj ? JSON.stringify(targetingObj) : (typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting));\n return this.createCustomAudience({ name: request.name, caType: 14, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Zalo Form (`caType = 10` - `FORM_AUDIENCE`). */\n public createFormLeadAudience(request: Dto.ZaloAdsCreateFormLeadAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormLeadAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 10, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Commerce Form (`caType = 15` - `COMMERCE_FORM_AUDIENCE`). */\n public createCommerceFormAudience(request: Dto.ZaloAdsCreateCommerceFormAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCommerceFormAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 15, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Kịch bản Tin nhắn OA (`caType = 13` - `MESSAGE_OA_AUDIENCE`). */\n public createMessageOaLeadAudience(request: Dto.ZaloAdsCreateMessageOaLeadAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageOaLeadAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 13, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Dữ liệu chuyển đổi Lead Signal (`caType = 16` - `LEAD_SIGNAL_AUDIENCE`). */\n public createLeadSignalAudience(request: Dto.ZaloAdsCreateLeadSignalAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateLeadSignalAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 16, targeting: targetingStr }, options);\n }\n\n /** Ước tính quy mô đối tượng tiếp cận */\n public estimateAudience(...args: Parameters<this[\"postApiAdEstimateaudience\"]>): ReturnType<this[\"postApiAdEstimateaudience\"]> {\n return (this.postApiAdEstimateaudience as any)(...args);\n }\n\n /** Danh sách toàn bộ nhóm đối tượng tùy chỉnh */\n public listCustomAudiences(...args: Parameters<this[\"getApiCustomAudienceAll\"]>): ReturnType<this[\"getApiCustomAudienceAll\"]> {\n return (this.getApiCustomAudienceAll as any)(...args);\n }\n\n /** Danh sách cấu hình nhắm mục tiêu nâng cao */\n public getListAdAdvanceTargeting(...args: Parameters<this[\"getApiAdGetlistadadvancetargeting\"]>): ReturnType<this[\"getApiAdGetlistadadvancetargeting\"]> {\n return (this.getApiAdGetlistadadvancetargeting as any)(...args);\n }\n}\n","/**\r\n * Dịch vụ Báo cáo & Thống kê Hiệu quả Zalo Ads (Campaigns, Ads, Demographics, Overview, Custom Reports).\r\n */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/ads.dto\";\r\n\r\n\r\nconst OP_ZaloAdsGetReportapiV2Ads: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportapiV2Ads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/v2/ads\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"to\",\r\n \"from\",\r\n \"filter\",\r\n \"endDate\",\r\n \"refresh\",\r\n \"breakdown\",\r\n \"startDate\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetReportapiV2Campaigns: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportapiV2Campaigns\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/v2/campaigns/{campaignId}\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"campaignId\"\r\n ],\r\n \"queryFields\": [\r\n \"startDate\",\r\n \"endDate\",\r\n \"refresh\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetReportapiV2UniqueUser: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportapiV2UniqueUser\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/v2/unique-user\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"start\",\r\n \"end\",\r\n \"campaignId\",\r\n \"adId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetReportapiV3Campaigns: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportapiV3Campaigns\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/v3/campaigns\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"filter\",\r\n \"endDate\",\r\n \"refresh\",\r\n \"agencyId\",\r\n \"createdBy\",\r\n \"startDate\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetReportOverview: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportOverview\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/report/overview\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"data\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetDemographicsReport: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getDemographicsReport\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/demographics/report\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"campaignId\",\r\n \"adId\",\r\n \"startDate\",\r\n \"endDate\",\r\n \"agencyId\",\r\n \"from\",\r\n \"to\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsDeleteCustomReport: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_deleteCustomReport\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/reportapi/custom-report/delete/{id}\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"id\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsListReportFilters: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listReportFilters\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/api/filter/list\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"model\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiCampaignReportcampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiCampaignReportcampaign\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/Campaign/reportCampaign\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"campaignId\",\r\n \"campId\",\r\n \"from\",\r\n \"to\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsListCustomReports: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listCustomReports\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/custom-report/list\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsUpsertCustomReport: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_upsertCustomReport\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/reportapi/custom-report/update\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"id\",\r\n \"name\",\r\n \"settings\",\r\n \"isDefault\"\r\n ]\r\n};\r\n\r\n\r\nconst OP_ZaloAdsDownloadReport: OperationDefinition = {\r\n operationId: \"zalo_ads_download_report\",\r\n method: \"POST\",\r\n endpoint: \"/api/collect\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\r\n \"t\",\r\n \"adIds\",\r\n \"status\",\r\n \"dateFilter\",\r\n \"reportKind\",\r\n \"et\"\r\n ]\r\n};\r\n\r\nexport class ZaloReportsService {\r\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\r\n\r\n public getReportapiV2Ads(request: Dto.ZaloAdsGetReportapiV2AdsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2AdsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportapiV2AdsResponse>(OP_ZaloAdsGetReportapiV2Ads, this.client.toTransportInput(OP_ZaloAdsGetReportapiV2Ads, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getReportapiV2Campaigns(request: Dto.ZaloAdsGetReportapiV2CampaignsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2CampaignsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportapiV2CampaignsResponse>(OP_ZaloAdsGetReportapiV2Campaigns, this.client.toTransportInput(OP_ZaloAdsGetReportapiV2Campaigns, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getReportapiV2UniqueUser(request: Dto.ZaloAdsGetReportapiV2UniqueUserRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2UniqueUserResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportapiV2UniqueUserResponse>(OP_ZaloAdsGetReportapiV2UniqueUser, this.client.toTransportInput(OP_ZaloAdsGetReportapiV2UniqueUser, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getReportapiV3Campaigns(request: Dto.ZaloAdsGetReportapiV3CampaignsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV3CampaignsResponse> {\r\n const normalized: Record<string, unknown> = {\r\n filter: \"[]\",\r\n ...request,\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportapiV3CampaignsResponse>(OP_ZaloAdsGetReportapiV3Campaigns, this.client.toTransportInput(OP_ZaloAdsGetReportapiV3Campaigns, normalized), options);\r\n }\r\n\r\n public getReportOverview(request: Dto.ZaloAdsGetReportOverviewRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportOverviewResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportOverviewResponse>(OP_ZaloAdsGetReportOverview, this.client.toTransportInput(OP_ZaloAdsGetReportOverview, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getDemographicsReport(request: Dto.ZaloAdsGetDemographicsReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetDemographicsReportResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetDemographicsReportResponse>(OP_ZaloAdsGetDemographicsReport, this.client.toTransportInput(OP_ZaloAdsGetDemographicsReport, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getZaapiCampaignReportcampaign(request: Dto.ZaloAdsGetZaapiCampaignReportcampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiCampaignReportcampaignResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiCampaignReportcampaignResponse>(OP_ZaloAdsGetZaapiCampaignReportcampaign, this.client.toTransportInput(OP_ZaloAdsGetZaapiCampaignReportcampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public listCustomReports(request: Dto.ZaloAdsListCustomReportsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListCustomReportsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListCustomReportsResponse>(OP_ZaloAdsListCustomReports, this.client.toTransportInput(OP_ZaloAdsListCustomReports, request as Record<string, unknown>), options);\r\n }\r\n\r\n public upsertCustomReport(request: Dto.ZaloAdsUpsertCustomReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpsertCustomReportResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsUpsertCustomReportResponse>(OP_ZaloAdsUpsertCustomReport, this.client.toTransportInput(OP_ZaloAdsUpsertCustomReport, request as Record<string, unknown>), options);\r\n }\r\n\r\n public deleteCustomReport(request: Dto.ZaloAdsDeleteCustomReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCustomReportResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsDeleteCustomReportResponse>(OP_ZaloAdsDeleteCustomReport, this.client.toTransportInput(OP_ZaloAdsDeleteCustomReport, request as Record<string, unknown>), options);\r\n }\r\n\r\n public listReportFilters(request: Dto.ZaloAdsListReportFiltersRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListReportFiltersResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListReportFiltersResponse>(OP_ZaloAdsListReportFilters, this.client.toTransportInput(OP_ZaloAdsListReportFilters, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Báo cáo hiệu quả chiến dịch (API V3 - Khuyên dùng) */\r\n public getCampaignReportV3(...args: Parameters<this[\"getReportapiV3Campaigns\"]>): ReturnType<this[\"getReportapiV3Campaigns\"]> {\r\n return (this.getReportapiV3Campaigns as any)(...args);\r\n }\r\n\r\n /** Báo cáo hiệu quả chiến dịch (API V2) */\r\n public getCampaignReportV2(...args: Parameters<this[\"getReportapiV2Campaigns\"]>): ReturnType<this[\"getReportapiV2Campaigns\"]> {\r\n return (this.getReportapiV2Campaigns as any)(...args);\r\n }\r\n\r\n /** Báo cáo hiệu quả quảng cáo (API V2) */\r\n public getAdsReportV2(...args: Parameters<this[\"getReportapiV2Ads\"]>): ReturnType<this[\"getReportapiV2Ads\"]> {\r\n return (this.getReportapiV2Ads as any)(...args);\r\n }\r\n\r\n /** Báo cáo người dùng tiếp cận duy nhất (Unique Reach) */\r\n public getUniqueUserReport(...args: Parameters<this[\"getReportapiV2UniqueUser\"]>): ReturnType<this[\"getReportapiV2UniqueUser\"]> {\r\n return (this.getReportapiV2UniqueUser as any)(...args);\r\n }\r\n\r\n /** Báo cáo chiến dịch theo ngày/tháng (Legacy ZAAPI) */\r\n public getCampaignReportLegacy(...args: Parameters<this[\"getZaapiCampaignReportcampaign\"]>): ReturnType<this[\"getZaapiCampaignReportcampaign\"]> {\r\n return (this.getZaapiCampaignReportcampaign as any)(...args);\r\n }\r\n\r\n /** Xuất và tải trực tiếp tệp tin Excel (.xlsx / Blob) báo cáo hiệu quả quảng cáo (POST /api/collect) */\r\n public downloadReport(request: Dto.ZaloAdsDownloadReportRequest, options?: RequestOptions): Promise<Blob> {\r\n const payload = {\r\n t: request.t ?? \"cd.download.report\",\r\n status: request.status ?? 2,\r\n dateFilter: request.dateFilter ?? 0,\r\n reportKind: request.reportKind ?? 100001,\r\n et: request.et ?? Math.floor(Date.now() / 1000),\r\n adIds: request.adIds\r\n };\r\n return this.client.requestJson<Blob>(OP_ZaloAdsDownloadReport, this.client.toTransportInput(OP_ZaloAdsDownloadReport, payload as Record<string, unknown>), options);\r\n }\r\n\r\n}\r\n","/**\n * Dịch vụ Quản lý Chuyển đổi & Zalo Pixel (Conversions, Standard Events, Lead Signals, Pixel Labels).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\n\n\nconst OP_ZaloAdsCreateConversion: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createConversion\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/conversion/add\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"name\",\r\n \"landingPage\",\r\n \"urlType\",\r\n \"labelId\",\r\n \"buttonIds\",\r\n \"elements\",\r\n \"keywords\"\r\n ]\r\n};\n\nconst OP_ZaloAdsDeleteConversion: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_deleteConversion\",\r\n \"method\": \"DELETE\",\r\n \"endpoint\": \"/api/conversion/delete/{conversionId}\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"conversionId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\n\nconst OP_ZaloAdsGetApiConversionAll: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getApiConversionAll\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/conversion/all\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\n\nconst OP_ZaloAdsGetApiConversionStandardEvents: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getApiConversionStandardEvents\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/conversion/standard-events\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\n\nconst OP_ZaloAdsListPersonalPixelLabels: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listPersonalPixelLabels\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/conversion/support-personal-pixel-labels\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\n\nexport class ZaloConversionsService {\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public createConversion(request: Dto.ZaloAdsCreateConversionRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateConversionResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsCreateConversionResponse>(OP_ZaloAdsCreateConversion, this.client.toTransportInput(OP_ZaloAdsCreateConversion, request as Record<string, unknown>), options);\r\n }\r\n\n public deleteConversion(request: Dto.ZaloAdsDeleteConversionRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteConversionResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsDeleteConversionResponse>(OP_ZaloAdsDeleteConversion, this.client.toTransportInput(OP_ZaloAdsDeleteConversion, request as Record<string, unknown>), options);\r\n }\r\n\n public getApiConversionAll(request: Dto.ZaloAdsGetApiConversionAllRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiConversionAllResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiConversionAllResponse>(OP_ZaloAdsGetApiConversionAll, this.client.toTransportInput(OP_ZaloAdsGetApiConversionAll, request as Record<string, unknown>), options);\r\n }\r\n\n public getApiConversionStandardEvents(request: Dto.ZaloAdsGetApiConversionStandardEventsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiConversionStandardEventsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiConversionStandardEventsResponse>(OP_ZaloAdsGetApiConversionStandardEvents, this.client.toTransportInput(OP_ZaloAdsGetApiConversionStandardEvents, request as Record<string, unknown>), options);\r\n }\r\n\n public listPersonalPixelLabels(request: Dto.ZaloAdsListPersonalPixelLabelsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListPersonalPixelLabelsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListPersonalPixelLabelsResponse>(OP_ZaloAdsListPersonalPixelLabels, this.client.toTransportInput(OP_ZaloAdsListPersonalPixelLabels, request as Record<string, unknown>), options);\r\n }\r\n\n /** Lấy danh sách tài khoản Zalo Official Account (OA) có dữ liệu chuyển đổi (Lead Signal) (`GET /api/ad/audience/leadSignal/oas`). */\r\n public listLeadSignalOas(options?: RequestOptions): Promise<Dto.ZaloAdsListLeadSignalOasResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListLeadSignalOasResponse>(\r\n {\r\n operationId: \"ZaloAds_listLeadSignalOas\",\r\n method: \"GET\",\r\n endpoint: \"/api/ad/audience/leadSignal/oas\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [],\r\n },\r\n undefined,\r\n options\r\n );\r\n }\r\n\n /** Lấy danh sách rút gọn gồm ID và tên của toàn bộ các sự kiện chuyển đổi (Conversion) đã tạo trên tài khoản quảng cáo Zalo Ads (`GET /api/conversion/names`). */\r\n public listConversionNames(request: Dto.ZaloAdsListConversionNamesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListConversionNamesResponse> {\r\n const op: OperationDefinition = {\r\n operationId: \"ZaloAds_listConversionNames\",\r\n method: \"GET\",\r\n endpoint: \"/api/conversion/names\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [],\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListConversionNamesResponse>(\r\n op,\r\n this.client.toTransportInput(op, request as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n\n /** Alias cho `listConversionNames` (`GET /api/conversion/names`). */\r\n public getApiConversionNames(request: Dto.ZaloAdsListConversionNamesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListConversionNamesResponse> {\r\n return this.listConversionNames(request, options);\r\n }\r\n\n /** Danh sách toàn bộ sự kiện chuyển đổi */\n public listConversions(...args: Parameters<this[\"getApiConversionAll\"]>): ReturnType<this[\"getApiConversionAll\"]> {\n return (this.getApiConversionAll as any)(...args);\n }\n\n /** Danh sách sự kiện chuyển đổi tiêu chuẩn */\n public getConversionStandardEvents(...args: Parameters<this[\"getApiConversionStandardEvents\"]>): ReturnType<this[\"getApiConversionStandardEvents\"]> {\n return (this.getApiConversionStandardEvents as any)(...args);\n }\n}\n","/**\n * Dịch vụ Quản lý Quy tắc Tự động Zalo Ads (Automated Rules CRUD, Status, History).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\n\nconst OP_ZaloAdsListAutomatedRules: OperationDefinition = {\n \"operationId\": \"ZaloAds_listAutomatedRules\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/automatedrules/list\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"ruleName\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetAutomatedRuleDetail: OperationDefinition = {\n \"operationId\": \"ZaloAds_getAutomatedRuleDetail\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/automatedrules/{automatedRuleId}\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [\n \"automatedRuleId\"\n ],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsCreateAutomatedRule: OperationDefinition = {\n \"operationId\": \"ZaloAds_createAutomatedRule\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/automatedrules/create\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"scope\",\n \"appliedTo\",\n \"ruleName\",\n \"action\",\n \"conditions\",\n \"frequency\",\n \"appliedIds\",\n \"schedule\",\n \"campaignIds\",\n \"adIds\"\n ]\n};\n\nconst OP_ZaloAdsUpdateAutomatedRule: OperationDefinition = {\n \"operationId\": \"ZaloAds_updateAutomatedRule\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/ad/automatedrules/update\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"automatedRuleId\",\n \"scope\",\n \"ruleName\",\n \"action\",\n \"conditions\",\n \"frequency\",\n \"appliedItems\",\n \"appliedIds\",\n \"rowVersion\",\n \"appliedTo\",\n \"schedule\",\n \"campaignIds\",\n \"adIds\"\n ]\n};\n\nconst OP_ZaloAdsChangeAutomatedRuleStatus: OperationDefinition = {\n \"operationId\": \"ZaloAds_changeAutomatedRuleStatus\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/automatedrules/change-status\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"automatedRuleId\",\n \"automatedRuleIds\",\n \"status\"\n ]\n};\n\nconst OP_ZaloAdsGetAutomatedRuleHistory: OperationDefinition = {\n \"operationId\": \"ZaloAds_getAutomatedRuleHistory\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/automatedrules/history/{automatedRuleId}\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [\n \"automatedRuleId\"\n ],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsDeleteAutomatedRule: OperationDefinition = {\n \"operationId\": \"ZaloAds_deleteAutomatedRule\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/automatedrules/delete\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"automatedRuleIds\"\n ]\n};\n\nexport class ZaloAutomatedRulesService {\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public listAutomatedRules(request: Dto.ZaloAdsListAutomatedRulesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListAutomatedRulesResponse> {\n const queryInput = { query_param: { ruleName: request.ruleName ?? \"\" } };\n return this.client.requestWithoutBody<Dto.ZaloAdsListAutomatedRulesResponse>(OP_ZaloAdsListAutomatedRules, queryInput, options);\n }\n\n public getAutomatedRuleDetail(request: Dto.ZaloAdsGetAutomatedRuleDetailRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAutomatedRuleDetailResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetAutomatedRuleDetailResponse>(OP_ZaloAdsGetAutomatedRuleDetail, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleDetail, request as Record<string, unknown>), options);\n }\n\n public createAutomatedRule(request: Dto.ZaloAdsCreateAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateAutomatedRuleResponse> {\n return this.client.requestJson<Dto.ZaloAdsCreateAutomatedRuleResponse>(OP_ZaloAdsCreateAutomatedRule, this.client.toTransportInput(OP_ZaloAdsCreateAutomatedRule, request as Record<string, unknown>), options);\n }\n\n public updateAutomatedRule(request: Dto.ZaloAdsUpdateAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateAutomatedRuleResponse> {\n return this.client.requestJson<Dto.ZaloAdsUpdateAutomatedRuleResponse>(OP_ZaloAdsUpdateAutomatedRule, this.client.toTransportInput(OP_ZaloAdsUpdateAutomatedRule, request as Record<string, unknown>), options);\n }\n\n public changeAutomatedRuleStatus(request: Dto.ZaloAdsChangeAutomatedRuleStatusRequest, options?: RequestOptions): Promise<Dto.ZaloAdsChangeAutomatedRuleStatusResponse> {\n return this.client.requestJson<Dto.ZaloAdsChangeAutomatedRuleStatusResponse>(OP_ZaloAdsChangeAutomatedRuleStatus, this.client.toTransportInput(OP_ZaloAdsChangeAutomatedRuleStatus, request as Record<string, unknown>), options);\n }\n\n public getAutomatedRuleHistory(request: Dto.ZaloAdsGetAutomatedRuleHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAutomatedRuleHistoryResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetAutomatedRuleHistoryResponse>(OP_ZaloAdsGetAutomatedRuleHistory, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleHistory, request as Record<string, unknown>), options);\n }\n\n public deleteAutomatedRule(request: Dto.ZaloAdsDeleteAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteAutomatedRuleResponse> {\n return this.client.requestJson<Dto.ZaloAdsDeleteAutomatedRuleResponse>(OP_ZaloAdsDeleteAutomatedRule, this.client.toTransportInput(OP_ZaloAdsDeleteAutomatedRule, request as Record<string, unknown>), options);\n }\n}\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Zalo Message Flows:\n * 1. listFlowsByOfficialAccount (GET /api/flow/getByOaId)\n * 2. createFlow (POST /api/flow/create)\n * 3. updateFlow (POST /api/flow/update)\n *\n * Được thiết kế theo dạng hàm thuần (pure functions) độc lập, xuất ra ngoài để backend\n * (NestJS/Express/Fastify), middleware hoặc AI Agent sử dụng xác thực dữ liệu trước khi gọi Zalo Ads.\n */\nimport type * as Dto from \"../dtos/ads.dto\";\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\n\n/** Giới hạn số nguyên 32-bit có dấu của Play Framework (Java Integer.MAX_VALUE). */\nconst MAX_INT_32 = 2147483647;\n\nfunction is32BitPositiveInteger(val: unknown): boolean {\n if (typeof val === \"number\") {\n return Number.isInteger(val) && val > 0 && val <= MAX_INT_32;\n }\n if (typeof val === \"string\" && val.trim() !== \"\") {\n const num = Number(val);\n return Number.isInteger(num) && num > 0 && num <= MAX_INT_32;\n }\n return false;\n}\n\nfunction isPositiveInteger(val: unknown): boolean {\n if (typeof val === \"number\") return Number.isInteger(val) && val > 0;\n if (typeof val === \"string\" && val.trim() !== \"\") {\n const num = Number(val);\n return Number.isInteger(num) && num > 0;\n }\n return false;\n}\n\nfunction isNonNegativeInteger(val: unknown): boolean {\n if (typeof val === \"number\") return Number.isInteger(val) && val >= 0;\n if (typeof val === \"string\" && val.trim() !== \"\") {\n const num = Number(val);\n return Number.isInteger(num) && num >= 0;\n }\n return false;\n}\n\nfunction toPositiveInteger(val: unknown): number {\n return typeof val === \"number\" ? Math.floor(val) : parseInt(String(val), 10);\n}\n\n// ============================================================================\n// Helper validate cấu trúc nút bấm (ZaloAdsFlowButtonDto)\n// ============================================================================\nfunction validateFlowButtons(buttons: unknown, errors: string[], prefix: string): Dto.ZaloAdsFlowButtonDto[] {\n if (!Array.isArray(buttons)) {\n errors.push(`${prefix}: Trường 'buttons' phải là một mảng.`);\n return [];\n }\n\n const cleanButtons: Dto.ZaloAdsFlowButtonDto[] = [];\n\n buttons.forEach((btn, idx) => {\n const btnPrefix = `${prefix}.buttons[${idx}]`;\n if (!btn || typeof btn !== \"object\") {\n errors.push(`${btnPrefix}: Nút bấm phải là một đối tượng.`);\n return;\n }\n const b = btn as Record<string, unknown>;\n\n // 1. Nhãn nút\n if (typeof b.text !== \"string\" || b.text.trim() === \"\") {\n errors.push(`${btnPrefix}: Nhãn nút 'text' là bắt buộc và không được để trống.`);\n }\n\n // 2. Loại nút: 3 (nhánh), 10 (website), 12 (hotline)\n const btnType = Number(b.type);\n if (![3, 10, 12].includes(btnType)) {\n errors.push(`${btnPrefix}: Loại nút 'type' phải là 3 (nhánh hội thoại), 10 (mở website), hoặc 12 (gọi hotline).`);\n }\n\n const cleanBtn: Dto.ZaloAdsFlowButtonDto = {\n type: btnType,\n text: String(b.text ?? \"\").trim(),\n editable: b.editable !== false\n };\n\n // Chi tiết theo loại nút\n if (btnType === 10) {\n if (typeof b.url !== \"string\" || b.url.trim() === \"\") {\n errors.push(`${btnPrefix}: Nút loại 10 (mở website) bắt buộc phải có trường 'url' hợp lệ.`);\n } else {\n cleanBtn.url = b.url.trim();\n }\n } else if (btnType === 12) {\n if (typeof b.phone !== \"string\" || b.phone.trim() === \"\") {\n errors.push(`${btnPrefix}: Nút loại 12 (gọi hotline) bắt buộc phải có trường 'phone' hợp lệ.`);\n } else {\n cleanBtn.phone = b.phone.trim();\n }\n } else if (btnType === 3) {\n if (!Array.isArray(b.messages) || b.messages.length === 0) {\n errors.push(`${btnPrefix}: Nút loại 3 (nhánh hội thoại) bắt buộc phải có mảng 'messages' chứa ít nhất 1 tin nhắn con phản hồi.`);\n } else {\n const cleanChildMsgs: Dto.ZaloAdsFlowChildMessageDto[] = [];\n b.messages.forEach((child, cIdx) => {\n const childPrefix = `${btnPrefix}.messages[${cIdx}]`;\n if (!child || typeof child !== \"object\") {\n errors.push(`${childPrefix}: Tin nhắn con phải là một đối tượng.`);\n return;\n }\n const c = child as Record<string, unknown>;\n if (typeof c.text !== \"string\" || c.text.trim() === \"\") {\n errors.push(`${childPrefix}: Nội dung tin nhắn con 'text' không được để trống.`);\n } else if (c.text.length > 1961) {\n errors.push(`${childPrefix}: Nội dung tin nhắn con vượt quá 1961 ký tự (hiện có ${c.text.length} ký tự).`);\n }\n cleanChildMsgs.push({\n type: 8,\n text: String(c.text ?? \"\").trim()\n });\n });\n cleanBtn.messages = cleanChildMsgs;\n }\n }\n\n cleanButtons.push(cleanBtn);\n });\n\n return cleanButtons;\n}\n\n// ============================================================================\n// Helper validate tin nhắn kịch bản (ZaloAdsFlowMessageDto)\n// ============================================================================\nfunction validateFlowMessages(messages: unknown, errors: string[]): Dto.ZaloAdsFlowMessageDto[] {\n if (!Array.isArray(messages)) {\n errors.push(\"Trường 'messages' phải là một mảng chứa tin nhắn kịch bản.\");\n return [];\n }\n\n if (messages.length !== 1) {\n errors.push(`Zalo Ads chỉ cho phép kịch bản chứa DUY NHẤT 1 tin nhắn chào mừng cấp cao (hiện có ${messages.length} tin nhắn). Các nhánh hội thoại tiếp theo phải cấu hình bên trong nút bấm loại 3 (type=3).`);\n return [];\n }\n\n const msg = messages[0];\n if (!msg || typeof msg !== \"object\") {\n errors.push(\"Tin nhắn kịch bản phải là một đối tượng.\");\n return [];\n }\n const m = msg as Record<string, unknown>;\n\n const msgType = Number(m.type);\n if (![1, 2].includes(msgType)) {\n errors.push(\"Loại tin nhắn 'type' phải là 1 (văn bản) hoặc 2 (kèm hình ảnh).\");\n }\n\n if (typeof m.text !== \"string\" || m.text.trim() === \"\") {\n errors.push(\"Nội dung tin nhắn 'text' là bắt buộc và không được để trống.\");\n } else if (m.text.length > 1961) {\n errors.push(`Nội dung tin nhắn vượt quá 1961 ký tự (hiện có ${m.text.length} ký tự).`);\n }\n\n const cleanMsg: Dto.ZaloAdsFlowMessageDto = {\n type: msgType,\n text: String(m.text ?? \"\").trim()\n };\n\n if (msgType === 2) {\n if (typeof m.url !== \"string\" || m.url.trim() === \"\") {\n errors.push(\"Tin nhắn loại 2 (kèm ảnh) bắt buộc phải có trường 'url' chứa đường dẫn hình ảnh.\");\n } else {\n cleanMsg.url = m.url.trim();\n }\n }\n\n if (m.buttons !== undefined && m.buttons !== null) {\n cleanMsg.buttons = validateFlowButtons(m.buttons, errors, \"messages[0]\");\n }\n\n return [cleanMsg];\n}\n\n// ============================================================================\n// 1. listFlowsByOfficialAccount (GET /api/flow/getByOaId)\n// ============================================================================\nexport function validateListFlowsByOfficialAccountRequest(input: unknown): ValidationResult<Dto.ZaloAdsListFlowsByOfficialAccountRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy danh sách kịch bản phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n // oaId: 32-bit positive integer (internal pageId)\n if (!is32BitPositiveInteger(obj.oaId)) {\n errors.push(\"Trường 'oaId' là bắt buộc và phải là mã pageId nội bộ kiểu số nguyên 32-bit (<= 2,147,483,647). Không truyền chuỗi noisedId công khai (18 chữ số) vì backend Play Framework sẽ từ chối.\");\n }\n\n // limit: positive integer\n if (!isPositiveInteger(obj.limit)) {\n errors.push(\"Trường 'limit' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n // offset: non-negative integer (optional)\n if (obj.offset !== undefined && obj.offset !== null && !isNonNegativeInteger(obj.offset)) {\n errors.push(\"Trường 'offset' nếu có phải là số nguyên không âm (>= 0).\");\n }\n\n // flowId: positive integer (optional)\n if (obj.flowId !== undefined && obj.flowId !== null && !isPositiveInteger(obj.flowId)) {\n errors.push(\"Trường 'flowId' nếu có phải là số nguyên dương (> 0).\");\n }\n\n const cleanData: Dto.ZaloAdsListFlowsByOfficialAccountRequest = {\n oaId: toPositiveInteger(obj.oaId),\n limit: toPositiveInteger(obj.limit)\n };\n if (obj.offset !== undefined && obj.offset !== null) cleanData.offset = toPositiveInteger(obj.offset);\n if (obj.flowId !== undefined && obj.flowId !== null) cleanData.flowId = toPositiveInteger(obj.flowId);\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined\n };\n}\n\n// ============================================================================\n// 2. createFlow (POST /api/flow/create)\n// ============================================================================\nexport function validateCreateFlowRequest(input: unknown): ValidationResult<Dto.ZaloAdsCreateFlowRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu tạo kịch bản phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n // oaId: 32-bit integer\n if (!is32BitPositiveInteger(obj.oaId)) {\n errors.push(\"Trường 'oaId' là bắt buộc và phải là mã pageId nội bộ kiểu số nguyên 32-bit (<= 2,147,483,647).\");\n }\n\n // name: string, 1 <= length <= 50\n if (typeof obj.name !== \"string\" || obj.name.trim() === \"\") {\n errors.push(\"Trường 'name' (tên kịch bản) là bắt buộc và không được để trống.\");\n } else if (obj.name.trim().length > 50) {\n errors.push(`Tên kịch bản không được vượt quá 50 ký tự (hiện có ${obj.name.trim().length} ký tự).`);\n }\n\n // messages: exactly 1 message\n const cleanMessages = validateFlowMessages(obj.messages, errors);\n\n const cleanData: Dto.ZaloAdsCreateFlowRequest = {\n oaId: toPositiveInteger(obj.oaId),\n id: null,\n name: String(obj.name ?? \"\").trim(),\n messages: cleanMessages\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined\n };\n}\n\n// ============================================================================\n// 3. updateFlow (POST /api/flow/update)\n// ============================================================================\nexport function validateUpdateFlowRequest(input: unknown): ValidationResult<Dto.ZaloAdsUpdateFlowRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu cập nhật kịch bản phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n // id: positive integer\n if (!isPositiveInteger(obj.id)) {\n errors.push(\"Trường 'id' (ID Flow cần cập nhật) là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n // oaId: 32-bit integer\n if (!is32BitPositiveInteger(obj.oaId)) {\n errors.push(\"Trường 'oaId' là bắt buộc và phải là mã pageId nội bộ kiểu số nguyên 32-bit (<= 2,147,483,647).\");\n }\n\n // name: string, 1 <= length <= 50\n if (typeof obj.name !== \"string\" || obj.name.trim() === \"\") {\n errors.push(\"Trường 'name' (tên kịch bản) là bắt buộc và không được để trống.\");\n } else if (obj.name.trim().length > 50) {\n errors.push(`Tên kịch bản không được vượt quá 50 ký tự (hiện có ${obj.name.trim().length} ký tự).`);\n }\n\n // messages: exactly 1 message\n const cleanMessages = validateFlowMessages(obj.messages, errors);\n\n const cleanData: Dto.ZaloAdsUpdateFlowRequest = {\n id: toPositiveInteger(obj.id),\n oaId: toPositiveInteger(obj.oaId),\n name: String(obj.name ?? \"\").trim(),\n messages: cleanMessages\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined\n };\n}\n\n/**\n * Đối tượng gom nhóm các hàm kiểm tra tính hợp lệ dữ liệu cho Message Flows APIs.\n */\nexport const ZaloFlowsValidator = {\n listFlowsByOfficialAccount: validateListFlowsByOfficialAccountRequest,\n createFlow: validateCreateFlowRequest,\n updateFlow: validateUpdateFlowRequest\n} as const;\n\n","/**\n * Dịch vụ Quản lý Kịch bản Tin nhắn OA (Message Flows get/create/update).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\nimport { ZaloFlowsValidator } from \"../validators/flows.validator\";\n\n\nconst OP_ZaloAdsListFlowsByOfficialAccount: OperationDefinition = {\r\n operationId: \"ZaloAds_listFlowsByOfficialAccount\",\r\n method: \"GET\",\r\n endpoint: \"/api/flow/getByOaId\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [\"oaId\", \"limit\", \"offset\", \"flowId\"],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: []\r\n};\n\nconst OP_ZaloAdsCreateFlow: OperationDefinition = {\r\n operationId: \"ZaloAds_createFlow\",\r\n method: \"POST\",\r\n endpoint: \"/api/flow/create\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"oaId\", \"id\", \"name\", \"messages\"]\r\n};\n\nconst OP_ZaloAdsUpdateFlow: OperationDefinition = {\r\n operationId: \"ZaloAds_updateFlow\",\r\n method: \"POST\",\r\n endpoint: \"/api/flow/update\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"oaId\", \"id\", \"name\", \"messages\"]\r\n};\n\nexport class ZaloFlowsService {\n /**\n * Bộ công cụ kiểm tra tính hợp lệ dữ liệu (Standalone Validators) cho Message Flows APIs.\n * Dùng để validate dữ liệu đầu vào trước khi lưu DB hoặc gọi Zalo Ads.\n */\n public static readonly validator = ZaloFlowsValidator;\n public readonly validator = ZaloFlowsValidator;\n\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public listFlowsByOfficialAccount(request: Dto.ZaloAdsListFlowsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListFlowsByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListFlowsByOfficialAccountResponse>(OP_ZaloAdsListFlowsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFlowsByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n\n public createFlow(request: Dto.ZaloAdsCreateFlowRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFlowResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsCreateFlowResponse>(OP_ZaloAdsCreateFlow, this.client.toTransportInput(OP_ZaloAdsCreateFlow, request as unknown as Record<string, unknown>), options);\r\n }\r\n\n public updateFlow(request: Dto.ZaloAdsUpdateFlowRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateFlowResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsUpdateFlowResponse>(OP_ZaloAdsUpdateFlow, this.client.toTransportInput(OP_ZaloAdsUpdateFlow, request as unknown as Record<string, unknown>), options);\r\n }\r\n\n}\n","/**\n * Zalo Ads Media & Assets Service (`https://ads.zalo.me`).\n * Quản lý kho hình ảnh, video, upload CDN, lưu thư viện Media, cắt ảnh (crop)\n * và cung cấp các tiện ích upload+save trọn gói cùng bộ validation độc lập cho backend.\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions, FileInput } from \"../types\";\nimport { ZaloSdkError } from \"../types\";\nimport type * as Dto from \"../dtos/media.dto\";\n\nconst OP_ZaloAdsGetApiMediaItems: OperationDefinition = {\n operationId: \"ZaloAds_getApiMediaItems\",\n method: \"GET\",\n endpoint: \"/api/media/items\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [],\n pathFields: [],\n queryFields: [\"endDate\", \"startDate\"],\n headerFields: [],\n cookieFields: [],\n bodyFields: [],\n};\n\nconst OP_ZaloAdsGetApiMemberFiles: OperationDefinition = {\n operationId: \"ZaloAds_getApiMemberFiles\",\n method: \"GET\",\n endpoint: \"/api/member/files\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [],\n};\n\nconst OP_ZaloAdsGetApiFilegroups: OperationDefinition = {\n operationId: \"ZaloAds_getApiFilegroups\",\n method: \"GET\",\n endpoint: \"/api/filegroups\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [],\n};\n\nconst OP_ZaloAdsPostApiMediaSave: OperationDefinition = {\n operationId: \"ZaloAds_postApiMediaSave\",\n method: \"POST\",\n endpoint: \"/api/media/save\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [\"data\"],\n};\n\nconst OP_ZaloAdsPostApiMemberUploadImage: OperationDefinition = {\n operationId: \"ZaloAds_postApiMemberUploadImage\",\n method: \"POST\",\n endpoint: \"/api/member/upload-image\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [\"File\"],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [\"File\"],\n};\n\nconst OP_ZaloAdsUploadVideo: OperationDefinition = {\n operationId: \"ZaloAds_uploadVideo\",\n method: \"POST\",\n endpoint: \"/api/member/upload-video\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [\"File\"],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [\"File\"],\n};\n\nconst OP_ZaloAdsUpdateNewAds: OperationDefinition = {\n operationId: \"ZaloAds_UpdateNewAds\",\n method: \"POST\",\n endpoint: \"/zaapi/UploadCrop\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [\"File\"],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [\"File\", \"x\", \"y\", \"width\", \"height\", \"scale\"],\n};\n\n/**\n * Helper trích xuất kích thước từ header binary JPEG (SOF marker)\n */\nfunction extractJpegDimensions(buffer: Uint8Array): { width: number; height: number } | null {\n let i = 2;\n while (i < buffer.length - 8) {\n if (buffer[i] !== 0xff) {\n i++;\n continue;\n }\n const marker = buffer[i + 1];\n if (marker === 0xc0 || marker === 0xc1 || marker === 0xc2) {\n const height = (buffer[i + 5] << 8) | buffer[i + 6];\n const width = (buffer[i + 7] << 8) | buffer[i + 8];\n return { width, height };\n }\n const len = (buffer[i + 2] << 8) | buffer[i + 3];\n i += 2 + len;\n }\n return null;\n}\n\n/**\n * Helper trích xuất kích thước từ chunk IHDR của PNG\n */\nfunction extractPngDimensions(buffer: Uint8Array): { width: number; height: number } | null {\n if (\n buffer.length >= 24 &&\n buffer[0] === 0x89 &&\n buffer[1] === 0x50 &&\n buffer[2] === 0x4e &&\n buffer[3] === 0x47\n ) {\n const width = (buffer[16] << 24) | (buffer[17] << 16) | (buffer[18] << 8) | buffer[19];\n const height = (buffer[20] << 24) | (buffer[21] << 16) | (buffer[22] << 8) | buffer[23];\n return { width, height };\n }\n return null;\n}\n\n/**\n * Kiểm tra đối tượng có phải là Uint8Array hoặc Node.js Buffer hay không (Type Guard an toàn không phụ thuộc @types/node)\n */\nfunction isUint8Array(val: unknown): val is Uint8Array {\n if (val instanceof Uint8Array) {\n return true;\n }\n if (\n typeof val === \"object\" &&\n val !== null &&\n typeof (val as { constructor?: { isBuffer?: (o: unknown) => boolean } }).constructor?.isBuffer === \"function\"\n ) {\n return (val as { constructor: { isBuffer: (o: unknown) => boolean } }).constructor.isBuffer(val);\n }\n return false;\n}\n\n/**\n * Trích xuất tên tệp từ đường dẫn, URL hoặc FileInput\n */\nfunction resolveFileName(input: unknown, defaultPrefix = \"media\"): string {\n if (typeof input === \"string\") {\n const clean = input.split(/[?#]/)[0];\n const match = clean.match(/[^/\\\\]+$/);\n if (match && match[0]) return match[0];\n }\n if (input && typeof input === \"object\") {\n const record = input as Record<string, unknown>;\n if (typeof record.name === \"string\" && record.name) return record.name;\n if (typeof record.originalname === \"string\" && record.originalname) return record.originalname;\n if (typeof record.fileName === \"string\" && record.fileName) return record.fileName;\n }\n return `${defaultPrefix}_${Date.now()}.jpg`;\n}\n\nexport class ZaloMediaService {\n public constructor(private readonly client: ZaloSdkHttpClient) {}\n\n // ==========================================================================\n // 1. RAW API METHODS (Chuẩn theo OpenAPI spec media-and-assets, không validate)\n // ==========================================================================\n\n /**\n * Lấy danh sách ảnh, video trong thư viện Zalo Ads theo khoảng thời gian (`GET /api/media/items`).\n */\n public getApiMediaItems(\n request: Dto.ZaloAdsGetApiMediaItemsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiMediaItemsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiMediaItemsResponse>(\n OP_ZaloAdsGetApiMediaItems,\n this.client.toTransportInput(OP_ZaloAdsGetApiMediaItems, request as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `getApiMediaItems`.\n */\n public listMediaItems(\n request: Dto.ZaloAdsGetApiMediaItemsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiMediaItemsResponse> {\n return this.getApiMediaItems(request, options);\n }\n\n /**\n * Lấy các tệp do thành viên hiện tại quản lý trong tài khoản quảng cáo (`GET /api/member/files`).\n */\n public getApiMemberFiles(\n request: Dto.ZaloAdsGetApiMemberFilesRequest = {},\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiMemberFilesResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiMemberFilesResponse>(\n OP_ZaloAdsGetApiMemberFiles,\n this.client.toTransportInput(OP_ZaloAdsGetApiMemberFiles, request as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `getApiMemberFiles`.\n */\n public listMemberFiles(\n request: Dto.ZaloAdsGetApiMemberFilesRequest = {},\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiMemberFilesResponse> {\n return this.getApiMemberFiles(request, options);\n }\n\n /**\n * Lấy danh sách nhóm tệp trong kho media (`GET /api/filegroups`).\n */\n public getApiFilegroups(\n request: Dto.ZaloAdsGetApiFilegroupsRequest = {},\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiFilegroupsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiFilegroupsResponse>(\n OP_ZaloAdsGetApiFilegroups,\n this.client.toTransportInput(OP_ZaloAdsGetApiFilegroups, request as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `getApiFilegroups`.\n */\n public listFilegroups(\n request: Dto.ZaloAdsGetApiFilegroupsRequest = {},\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiFilegroupsResponse> {\n return this.getApiFilegroups(request, options);\n }\n\n /**\n * Lưu tài nguyên media vào thư viện Zalo Ads sau khi đã có URL ảnh/video và metadata (`POST /api/media/save`).\n * Phản hồi trả về `{ code: 0, data: <MediaId> }`.\n */\n public postApiMediaSave(\n request: Dto.ZaloAdsPostApiMediaSaveRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsPostApiMediaSaveResponse> {\n const normalized = {\n ...request,\n data: typeof request.data === \"string\" ? request.data : JSON.stringify(request.data),\n };\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsPostApiMediaSaveResponse>(\n OP_ZaloAdsPostApiMediaSave,\n this.client.toTransportInput(OP_ZaloAdsPostApiMediaSave, normalized as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `postApiMediaSave`.\n */\n public saveMedia(\n request: Dto.ZaloAdsPostApiMediaSaveRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsPostApiMediaSaveResponse> {\n return this.postApiMediaSave(request, options);\n }\n\n /**\n * Tải ảnh lên kho media của tài khoản quảng cáo (`POST /api/member/upload-image`).\n * Sử dụng multipart/form-data với trường `File` (chữ hoa). Trả về URL CDN Adtima.\n */\n public postApiMemberUploadImage(\n request: Dto.ZaloAdsPostApiMemberUploadImageRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsPostApiMemberUploadImageResponse> {\n const file = request.File ?? request.file;\n if (typeof file === \"string\" && !/^(https?:|data:)/i.test(file)) {\n throw new ZaloSdkError(\n \"Đường dẫn tệp cục bộ trên ổ cứng không được hỗ trợ. Vui lòng truyền Buffer/Uint8Array (ví dụ: req.file.buffer từ Multer), Web Blob/File hoặc URL ảnh công khai (http/https).\",\n 400,\n \"postApiMemberUploadImage\",\n null\n );\n }\n const normalized = {\n File: file,\n };\n return this.client.requestMultipart<Dto.ZaloAdsPostApiMemberUploadImageResponse>(\n OP_ZaloAdsPostApiMemberUploadImage,\n this.client.toTransportInput(OP_ZaloAdsPostApiMemberUploadImage, normalized),\n options\n );\n }\n\n /**\n * Alias cho `postApiMemberUploadImage`.\n */\n public uploadImage(\n request: Dto.ZaloAdsPostApiMemberUploadImageRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsPostApiMemberUploadImageResponse> {\n return this.postApiMemberUploadImage(request, options);\n }\n\n /**\n * Tải video lên kho media của tài khoản quảng cáo (`POST /api/member/upload-video`).\n * Định dạng chuẩn .MP4 (H.264), tối đa 150MB. Trả về URL video trên Adtima CDN.\n */\n public uploadVideo(\n request: Dto.ZaloAdsUploadVideoRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsUploadVideoResponse> {\n const file = request.File ?? request.file;\n if (typeof file === \"string\" && !/^(https?:|data:)/i.test(file)) {\n throw new ZaloSdkError(\n \"Đường dẫn tệp cục bộ trên ổ cứng không được hỗ trợ. Vui lòng truyền Buffer/Uint8Array (ví dụ: req.file.buffer), Web Blob/File hoặc URL video công khai (http/https).\",\n 400,\n \"uploadVideo\",\n null\n );\n }\n const normalized = {\n File: file,\n };\n return this.client.requestMultipart<Dto.ZaloAdsUploadVideoResponse>(\n OP_ZaloAdsUploadVideo,\n this.client.toTransportInput(OP_ZaloAdsUploadVideo, normalized),\n options\n );\n }\n\n /**\n * Tải ảnh và thiết lập vùng crop tạo asset dùng cho quảng cáo Zalo Ads (`POST /zaapi/UploadCrop`).\n */\n public updateNewAds(\n request: Dto.ZaloAdsUpdateNewAdsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsUpdateNewAdsResponse> {\n return this.client.requestMultipart<Dto.ZaloAdsUpdateNewAdsResponse>(\n OP_ZaloAdsUpdateNewAds,\n this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `updateNewAds` (`POST /zaapi/UploadCrop`).\n */\n public uploadCrop(\n request: Dto.ZaloAdsUpdateNewAdsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsUpdateNewAdsResponse> {\n return this.updateNewAds(request, options);\n }\n\n // ==========================================================================\n // 2. CONVENIENCE CUSTOM METHODS: UPLOAD + SAVE TRỌN GÓI\n // ==========================================================================\n\n /**\n * Method tiện ích trọn gói: Tự động tải ảnh lên CDN (`/api/member/upload-image`)\n * VÀ lưu vào Thư viện Zalo Ads (`/api/media/save`) trong cùng 1 lời gọi duy nhất.\n * \n * Trả về MediaId, URL CDN và kích thước để gắn ngay vào Creative/Quảng cáo.\n */\n public async uploadAndSaveImage(\n request: Dto.ZaloUploadAndSaveImageRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloUploadAndSaveImageResult> {\n if (!request.file) {\n throw new ZaloSdkError(\n \"ZaloMediaService: `file` là tham số bắt buộc trong uploadAndSaveImage.\",\n 400,\n \"uploadAndSaveImage\",\n null\n );\n }\n\n // Không hỗ trợ đường dẫn tệp cục bộ trên ổ cứng\n if (typeof request.file === \"string\" && !/^(https?:|data:)/i.test(request.file)) {\n throw new ZaloSdkError(\n \"Đường dẫn tệp cục bộ trên ổ cứng không được hỗ trợ. Vui lòng truyền Buffer/Uint8Array (ví dụ: req.file.buffer từ Multer), Web Blob/File hoặc URL ảnh công khai (http/https).\",\n 400,\n \"uploadAndSaveImage\",\n null\n );\n }\n\n // 1. Tự động nhận diện tên file nếu chưa truyền\n const fileName = request.fileName || resolveFileName(request.file, \"image\");\n\n // 2. Tự động đọc kích thước (Width, Height) từ binary Buffer/Uint8Array nếu chưa truyền\n let width = request.width;\n let height = request.height;\n\n if ((!width || !height) && isUint8Array(request.file)) {\n const dims = extractJpegDimensions(request.file) || extractPngDimensions(request.file);\n if (dims) {\n width = width || dims.width;\n height = height || dims.height;\n }\n }\n\n // Fallback kích thước chuẩn nếu không trích xuất được\n const resolvedWidth = width && width > 0 ? width : 1200;\n const resolvedHeight = height && height > 0 ? height : 710;\n\n // 3. BƯỚC 1: Tải ảnh lên CDN\n const uploadRes = await this.postApiMemberUploadImage({ File: request.file }, options);\n if (!uploadRes || uploadRes.code !== 0 || !uploadRes.data) {\n throw new ZaloSdkError(\n uploadRes?.msg || \"Tải ảnh lên Zalo Ads thất bại ở bước upload CDN.\",\n uploadRes?.code || 500,\n \"uploadAndSaveImage_upload\",\n uploadRes\n );\n }\n const cdnUrl = uploadRes.data;\n\n // 4. BƯỚC 2: Lưu vào Thư viện Media\n const mediaType = request.type !== undefined ? request.type : 1; // 1 = Ảnh\n const savePayload: Dto.ZaloAdsMediaSavePayloadDto = {\n Name: fileName,\n Type: mediaType,\n Settings: {\n Url: cdnUrl,\n Width: resolvedWidth,\n Height: resolvedHeight,\n ...(request.thumbUrl ? { ThumbUrl: request.thumbUrl } : {}),\n },\n };\n\n const saveRes = await this.postApiMediaSave({ data: savePayload }, options);\n if (!saveRes || saveRes.code !== 0 || typeof saveRes.data !== \"number\") {\n throw new ZaloSdkError(\n \"Lưu ảnh vào Thư viện Media Zalo Ads thất bại ở bước save.\",\n saveRes?.code || 500,\n \"uploadAndSaveImage_save\",\n saveRes\n );\n }\n\n return {\n code: 0,\n mediaId: saveRes.data,\n cdnUrl,\n name: fileName,\n width: resolvedWidth,\n height: resolvedHeight,\n type: mediaType,\n rawUploadResponse: uploadRes,\n rawSaveResponse: saveRes,\n };\n }\n\n /**\n * Method tiện ích trọn gói cho Video: Tự động tải video lên CDN (`/api/member/upload-video`)\n * VÀ lưu vào Thư viện Zalo Ads (`/api/media/save`) để cấp MediaId.\n */\n public async uploadAndSaveVideo(\n request: Dto.ZaloUploadAndSaveVideoRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloUploadAndSaveVideoResult> {\n if (!request.file) {\n throw new ZaloSdkError(\n \"ZaloMediaService: `file` là tham số bắt buộc trong uploadAndSaveVideo.\",\n 400,\n \"uploadAndSaveVideo\",\n null\n );\n }\n\n if (typeof request.file === \"string\" && !/^(https?:|data:)/i.test(request.file)) {\n throw new ZaloSdkError(\n \"Đường dẫn tệp cục bộ trên ổ cứng không được hỗ trợ. Vui lòng truyền Buffer/Uint8Array, Web Blob/File hoặc URL video công khai (http/https).\",\n 400,\n \"uploadAndSaveVideo\",\n null\n );\n }\n\n const fileName = request.fileName || resolveFileName(request.file, \"video\");\n const width = request.width || 1920;\n const height = request.height || 1080;\n const duration = request.duration || 30;\n\n // 1. BƯỚC 1: Tải video lên CDN\n const uploadRes = await this.uploadVideo({ File: request.file }, options);\n if (!uploadRes || uploadRes.code !== 0 || !uploadRes.data) {\n throw new ZaloSdkError(\n uploadRes?.msg || \"Tải video lên Zalo Ads thất bại ở bước upload CDN.\",\n uploadRes?.code || 500,\n \"uploadAndSaveVideo_upload\",\n uploadRes\n );\n }\n const cdnUrl = uploadRes.data;\n\n // 2. BƯỚC 2: Lưu vào Thư viện Media (Type = 2: Video)\n const savePayload: Dto.ZaloAdsMediaSavePayloadDto = {\n Name: fileName,\n Type: 2, // 2 = Video\n Settings: {\n Url: cdnUrl,\n Width: width,\n Height: height,\n Duration: duration,\n ...(request.thumbUrl ? { ThumbUrl: request.thumbUrl } : {}),\n },\n };\n\n const saveRes = await this.postApiMediaSave({ data: savePayload }, options);\n if (!saveRes || saveRes.code !== 0 || typeof saveRes.data !== \"number\") {\n throw new ZaloSdkError(\n \"Lưu video vào Thư viện Media Zalo Ads thất bại ở bước save.\",\n saveRes?.code || 500,\n \"uploadAndSaveVideo_save\",\n saveRes\n );\n }\n\n return {\n code: 0,\n mediaId: saveRes.data,\n cdnUrl,\n name: fileName,\n width,\n height,\n duration,\n type: 2,\n rawUploadResponse: uploadRes,\n rawSaveResponse: saveRes,\n };\n }\n\n // ==========================================================================\n // 3. STANDALONE VALIDATION METHODS (Cho Backend sử dụng độc lập, không chặn API)\n // ==========================================================================\n\n /**\n * Kiểm tra tính hợp lệ của tệp Ảnh theo quy chuẩn Zalo Ads:\n * - \"No file chosen\": Bắt buộc phải có tệp.\n * - Dung lượng: Tối đa 2MB (2 * 1024 * 1024 bytes).\n * - Kích thước: Tối thiểu 150x150 pixels.\n * - Định dạng: Hỗ trợ .JPG, .JPEG, .PNG.\n * \n * Trả về `{ isValid: boolean, status: 'VALID' | 'INVALID', errors: string[], metadata: {...} }`.\n */\n public validateImage(input: Dto.ValidateImageInput): Dto.MediaValidationResult {\n const errors: string[] = [];\n\n // 1. Phân tích sự tồn tại của file & dung lượng\n let sizeBytes = input.sizeBytes;\n let fileName = input.fileName;\n let format = input.format;\n let width = input.width;\n let height = input.height;\n\n const file = input.file;\n const hasFile = Boolean(\n file !== null &&\n file !== undefined &&\n (typeof file !== \"string\" || file.trim() !== \"\")\n );\n\n if (!hasFile && sizeBytes === undefined) {\n errors.push(\"No file chosen\");\n return {\n isValid: false,\n status: \"INVALID\",\n errors,\n metadata: { fileDetected: false },\n };\n }\n\n // Trích xuất metadata từ file object (multer/buffer) nếu có\n if (file && typeof file === \"object\") {\n const rec = file as Record<string, unknown>;\n if (typeof rec.size === \"number\" && sizeBytes === undefined) {\n sizeBytes = rec.size;\n }\n if (typeof rec.originalname === \"string\" && !fileName) {\n fileName = rec.originalname;\n }\n if (typeof rec.mimetype === \"string\" && !format) {\n format = rec.mimetype;\n }\n if (isUint8Array(rec.buffer)) {\n if (sizeBytes === undefined) sizeBytes = rec.buffer.byteLength;\n const dims = extractJpegDimensions(rec.buffer) || extractPngDimensions(rec.buffer);\n if (dims) {\n width = width || dims.width;\n height = height || dims.height;\n }\n } else if (isUint8Array(file)) {\n if (sizeBytes === undefined) sizeBytes = file.byteLength;\n const dims = extractJpegDimensions(file) || extractPngDimensions(file);\n if (dims) {\n width = width || dims.width;\n height = height || dims.height;\n }\n }\n } else if (typeof file === \"string\" && !fileName) {\n fileName = resolveFileName(file);\n }\n\n // Kiểm tra dung lượng = 0\n if (sizeBytes !== undefined && sizeBytes <= 0) {\n errors.push(\"No file chosen\");\n }\n\n // 2. Kiểm tra dung lượng tối đa 2MB\n const MAX_IMAGE_BYTES = 2 * 1024 * 1024; // 2,097,152 bytes\n if (sizeBytes !== undefined && sizeBytes > MAX_IMAGE_BYTES) {\n const sizeMB = (sizeBytes / (1024 * 1024)).toFixed(2);\n errors.push(`Dung lượng ảnh vượt quá giới hạn tối đa 2MB (dung lượng hiện tại: ${sizeMB}MB).`);\n }\n\n // 3. Kiểm tra kích thước tối thiểu 150x150\n if (width !== undefined && height !== undefined) {\n if (width < 150 || height < 150) {\n errors.push(`Kích thước ảnh tối thiểu 150x150 (kích thước hiện tại: ${width}x${height} pixels).`);\n }\n }\n\n // 4. Kiểm tra định dạng ảnh (.JPG, .JPEG, .PNG)\n const nameToCheck = (fileName || format || \"\").toLowerCase();\n if (nameToCheck) {\n const isAllowedFormat =\n nameToCheck.endsWith(\".jpg\") ||\n nameToCheck.endsWith(\".jpeg\") ||\n nameToCheck.endsWith(\".png\") ||\n nameToCheck.includes(\"image/jpeg\") ||\n nameToCheck.includes(\"image/jpg\") ||\n nameToCheck.includes(\"image/png\");\n\n if (!isAllowedFormat) {\n errors.push(\"Định dạng ảnh không hợp lệ, yêu cầu định dạng .JPG, .JPEG hoặc .PNG.\");\n }\n }\n\n const isValid = errors.length === 0;\n return {\n isValid,\n status: isValid ? \"VALID\" : \"INVALID\",\n errors,\n metadata: {\n fileDetected: true,\n sizeBytes,\n width,\n height,\n format: format || (fileName ? fileName.split(\".\").pop() : undefined),\n },\n };\n }\n\n /**\n * Kiểm tra tính hợp lệ của tệp Video theo quy chuẩn Zalo Ads:\n * - \"No file chosen\": Bắt buộc phải có tệp.\n * - Định dạng: .MP4 H.264.\n * - Dung lượng: Tối đa 150MB (150 * 1024 * 1024 bytes).\n * - Thời lượng: Tối đa 60 giây.\n * - Tỉ lệ khung hình: 16:9, 9:16 hoặc 1:1.\n * \n * Trả về `{ isValid: boolean, status: 'VALID' | 'INVALID', errors: string[], metadata: {...} }`.\n */\n public validateVideo(input: Dto.ValidateVideoInput): Dto.MediaValidationResult {\n const errors: string[] = [];\n\n let sizeBytes = input.sizeBytes;\n let fileName = input.fileName;\n let format = input.format;\n const durationSeconds = input.durationSeconds;\n const width = input.width;\n const height = input.height;\n\n const file = input.file;\n const hasFile = Boolean(\n file !== null &&\n file !== undefined &&\n (typeof file !== \"string\" || file.trim() !== \"\")\n );\n\n if (!hasFile && sizeBytes === undefined) {\n errors.push(\"No file chosen\");\n return {\n isValid: false,\n status: \"INVALID\",\n errors,\n metadata: { fileDetected: false },\n };\n }\n\n if (file && typeof file === \"object\") {\n const rec = file as Record<string, unknown>;\n if (typeof rec.size === \"number\" && sizeBytes === undefined) {\n sizeBytes = rec.size;\n }\n if (typeof rec.originalname === \"string\" && !fileName) {\n fileName = rec.originalname;\n }\n if (typeof rec.mimetype === \"string\" && !format) {\n format = rec.mimetype;\n }\n if (isUint8Array(rec.buffer)) {\n if (sizeBytes === undefined) sizeBytes = rec.buffer.byteLength;\n } else if (isUint8Array(file)) {\n if (sizeBytes === undefined) sizeBytes = file.byteLength;\n }\n } else if (typeof file === \"string\" && !fileName) {\n fileName = resolveFileName(file);\n }\n\n // Kiểm tra dung lượng = 0\n if (sizeBytes !== undefined && sizeBytes <= 0) {\n errors.push(\"No file chosen\");\n }\n\n // 1. Định dạng: .MP4 H.264\n const nameToCheck = (fileName || format || \"\").toLowerCase();\n if (nameToCheck) {\n const isMp4 =\n nameToCheck.endsWith(\".mp4\") ||\n nameToCheck.includes(\"video/mp4\") ||\n nameToCheck.includes(\"h264\");\n\n if (!isMp4) {\n errors.push(\"Định dạng video không hợp lệ, yêu cầu định dạng .MP4 (H.264).\");\n }\n }\n\n // 2. Dung lượng: Tối đa 150MB\n const MAX_VIDEO_BYTES = 150 * 1024 * 1024; // 157,286,400 bytes\n if (sizeBytes !== undefined && sizeBytes > MAX_VIDEO_BYTES) {\n const sizeMB = (sizeBytes / (1024 * 1024)).toFixed(2);\n errors.push(`Dung lượng video vượt quá giới hạn tối đa 150MB (dung lượng hiện tại: ${sizeMB}MB).`);\n }\n\n // 3. Thời lượng tối đa 60 giây\n if (durationSeconds !== undefined && durationSeconds > 60) {\n errors.push(`Thời lượng video vượt quá giới hạn tối đa 60 giây (thời lượng hiện tại: ${durationSeconds} giây).`);\n }\n\n // 4. Tỉ lệ khung hình: 16:9, 9:16 hoặc 1:1\n let ratioLabel: string | undefined;\n if (width !== undefined && height !== undefined && width > 0 && height > 0) {\n const ratio = width / height;\n const is16_9 = Math.abs(ratio - 16 / 9) <= 0.06; // ~1.78\n const is9_16 = Math.abs(ratio - 9 / 16) <= 0.04; // ~0.56\n const is1_1 = Math.abs(ratio - 1.0) <= 0.05; // ~1.00\n\n if (is16_9) ratioLabel = \"16:9\";\n else if (is9_16) ratioLabel = \"9:16\";\n else if (is1_1) ratioLabel = \"1:1\";\n else {\n ratioLabel = `${width}:${height} (~${ratio.toFixed(2)})`;\n errors.push(`Tỉ lệ khung hình video phải là 16:9, 9:16 hoặc 1:1 (tỉ lệ hiện tại: ${width}x${height} - ${ratioLabel}).`);\n }\n }\n\n const isValid = errors.length === 0;\n return {\n isValid,\n status: isValid ? \"VALID\" : \"INVALID\",\n errors,\n metadata: {\n fileDetected: true,\n sizeBytes,\n width,\n height,\n durationSeconds,\n format: format || (fileName ? fileName.split(\".\").pop() : undefined),\n aspectRatio: ratioLabel,\n },\n };\n }\n}\n","/**\n * Zalo Ads API facade service.\n * Kế thừa toàn bộ API Chiến dịch & Quảng cáo từ `ZaloCampaignsService`,\n * đồng thời tích hợp và điều phối các module chuyên biệt:\n * - `account`: Quản lý tài khoản, phân quyền BA, thanh toán (`ZaloAccountService`)\n * - `audiences`: Nhóm đối tượng tùy chỉnh, Lookalike, Event/Lead Audiences (`ZaloAudiencesService`)\n * - `reports`: Báo cáo chiến dịch, quảng cáo, nhân khẩu học, báo cáo tùy chỉnh (`ZaloReportsService`)\n * - `conversions`: Sự kiện chuyển đổi, Zalo Pixel (`ZaloConversionsService`)\n * - `automatedRules`: Quy tắc tự động (`ZaloAutomatedRulesService`)\n * - `flows`: Kịch bản tin nhắn OA (`ZaloFlowsService`)\n * - `media`: Thư viện tài nguyên & tải lên ảnh/video (`ZaloMediaService`)\n */\nimport { ZaloSdkHttpClient } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\nimport type {\n ZaloUploadAndSaveImageRequest,\n ZaloUploadAndSaveImageResult,\n ZaloUploadAndSaveVideoRequest,\n ZaloUploadAndSaveVideoResult,\n MediaValidationResult,\n ValidateImageInput,\n ValidateVideoInput,\n} from \"../dtos/media.dto\";\n\nimport { ZaloCampaignsService } from \"./campaigns.service\";\nimport { ZaloAccountService } from \"./account.service\";\nimport { ZaloAudiencesService } from \"./audiences.service\";\nimport { ZaloReportsService } from \"./reports.service\";\nimport { ZaloConversionsService } from \"./conversions.service\";\nimport { ZaloAutomatedRulesService } from \"./automated-rules.service\";\nimport { ZaloFlowsService } from \"./flows.service\";\nimport { ZaloMediaService } from \"./media.service\";\n\nexport class ZaloAdsService extends ZaloCampaignsService {\n public readonly account: ZaloAccountService;\n public readonly audiences: ZaloAudiencesService;\n public readonly targeting: ZaloAudiencesService;\n public readonly reports: ZaloReportsService;\n public readonly conversions: ZaloConversionsService;\n public readonly pixel: ZaloConversionsService;\n public readonly automatedRules: ZaloAutomatedRulesService;\n public readonly rules: ZaloAutomatedRulesService;\n public readonly flows: ZaloFlowsService;\n public readonly media: ZaloMediaService;\n public readonly campaigns: ZaloCampaignsService;\n\n public constructor(client: ZaloSdkHttpClient) {\n super(client);\n this.account = new ZaloAccountService(client);\n this.audiences = new ZaloAudiencesService(client);\n this.targeting = this.audiences;\n this.reports = new ZaloReportsService(client);\n this.conversions = new ZaloConversionsService(client);\n this.pixel = this.conversions;\n this.automatedRules = new ZaloAutomatedRulesService(client);\n this.rules = this.automatedRules;\n this.flows = new ZaloFlowsService(client);\n this.media = new ZaloMediaService(client);\n this.campaigns = this;\n }\n\n // =========================================================================\n // Delegations -> this.account\n // =========================================================================\n\n public getApiWhoami(request: Dto.ZaloAdsGetApiWhoamiRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiWhoamiResponse> {\n return (this.account.getApiWhoami as any)(request, options);\n }\n\n public getApiPaymentTransactionHistory(request: Dto.ZaloAdsGetApiPaymentTransactionHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiPaymentTransactionHistoryResponse> {\n return (this.account.getApiPaymentTransactionHistory as any)(request, options);\n }\n\n public getApiBaAccountAllaccessors(request: Dto.ZaloAdsGetApiBaAccountAllaccessorsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAccountAllaccessorsResponse> {\n return (this.account.getApiBaAccountAllaccessors as any)(request, options);\n }\n\n public getApiBaAccountAllgrantedmembers(request: Dto.ZaloAdsGetApiBaAccountAllgrantedmembersRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAccountAllgrantedmembersResponse> {\n return (this.account.getApiBaAccountAllgrantedmembers as any)(request, options);\n }\n\n public listAgencyCustomersWithBudget(request: Dto.ZaloAdsListAgencyCustomersWithBudgetRequest = { limit: 15, offset: 0, joinDateAsc: true }, options?: RequestOptions): Promise<Dto.ZaloAdsListAgencyCustomersWithBudgetResponse> {\n return (this.account.listAgencyCustomersWithBudget as any)(request, options);\n }\n\n public getApiBaAgencyEmployees(request: Dto.ZaloAdsGetApiBaAgencyEmployeesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAgencyEmployeesResponse> {\n return (this.account.getApiBaAgencyEmployees as any)(request, options);\n }\n\n public getBaAgencyEmployees(...args: Parameters<this[\"getApiBaAgencyEmployees\"]>): ReturnType<this[\"getApiBaAgencyEmployees\"]> {\n return (this.account.getBaAgencyEmployees as any)(...args);\n }\n\n public getApiNotifiesHeader(request: Dto.ZaloAdsGetApiNotifiesHeaderRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiNotifiesHeaderResponse> {\n return (this.account.getApiNotifiesHeader as any)(request, options);\n }\n\n public getApiLpNews(request: Dto.ZaloAdsGetApiLpNewsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiLpNewsResponse> {\n return (this.account.getApiLpNews as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.audiences\n // =========================================================================\n\n public postApiAdEstimateaudience(request: Dto.ZaloAdsPostApiAdEstimateaudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiAdEstimateaudienceResponse> {\n return (this.audiences.postApiAdEstimateaudience as any)(request, options);\n }\n\n public getApiAdGetlistadadvancetargeting(request: Dto.ZaloAdsGetApiAdGetlistadadvancetargetingRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiAdGetlistadadvancetargetingResponse> {\n return (this.audiences.getApiAdGetlistadadvancetargeting as any)(request, options);\n }\n\n public getApiCustomAudienceAll(request: Dto.ZaloAdsGetApiCustomAudienceAllRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiCustomAudienceAllResponse> {\n return (this.audiences.getApiCustomAudienceAll as any)(request, options);\n }\n\n public createCustomAudience(request: Dto.ZaloAdsCreateCustomAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCustomAudienceResponse> {\n return (this.audiences.createCustomAudience as any)(request, options);\n }\n\n public deleteCustomAudience(request: Dto.ZaloAdsDeleteCustomAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCustomAudienceResponse> {\n return (this.audiences.deleteCustomAudience as any)(request, options);\n }\n\n public uploadCustomAudiencePhoneList(request: Dto.ZaloAdsUploadCustomAudiencePhoneListRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUploadCustomAudiencePhoneListResponse> {\n return (this.audiences.uploadCustomAudiencePhoneList as any)(request, options);\n }\n\n /** Tạo mới 'Nhóm đối tượng đã lưu' (`caType = 1` - `DEFAULT`) trên Zalo Ads (`POST /api/ad/audience`). */\r\n public createSavedAudience(request: Dto.ZaloAdsCreateSavedAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateSavedAudienceResponse> {\n return (this.audiences.createSavedAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ danh sách Số điện thoại (`caType = 3` - `PHONE_LIST`). */\r\n public createPhoneAudience(request: Dto.ZaloAdsCreatePhoneAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreatePhoneAudienceResponse> {\n return (this.audiences.createPhoneAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng tương tự Lookalike (`caType = 6` - `LOOKALIKE`). */\r\n public createLookalikeAudience(request: Dto.ZaloAdsCreateLookalikeAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateLookalikeAudienceResponse> {\n return (this.audiences.createLookalikeAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Zalo Form (`caType = 12` - `FORM_EVENT_AUDIENCE`). */\r\n public createFormEventAudience(request: Dto.ZaloAdsCreateFormEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormEventAudienceResponse> {\n return (this.audiences.createFormEventAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn OA (`caType = 11` - `MESSAGE_AUDIENCE`). */\r\n public createMessageOaEventAudience(request: Dto.ZaloAdsCreateMessageOaEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageOaEventAudienceResponse> {\n return (this.audiences.createMessageOaEventAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn cá nhân (`caType = 14` - `MESSAGE_PERSONAL_EVENT_AUDIENCE`). */\r\n public createMessagePersonalEventAudience(request: Dto.ZaloAdsCreateMessagePersonalEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessagePersonalEventAudienceResponse> {\n return (this.audiences.createMessagePersonalEventAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Zalo Form (`caType = 10` - `FORM_AUDIENCE`). */\r\n public createFormLeadAudience(request: Dto.ZaloAdsCreateFormLeadAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormLeadAudienceResponse> {\n return (this.audiences.createFormLeadAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Commerce Form (`caType = 15` - `COMMERCE_FORM_AUDIENCE`). */\r\n public createCommerceFormAudience(request: Dto.ZaloAdsCreateCommerceFormAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCommerceFormAudienceResponse> {\n return (this.audiences.createCommerceFormAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Kịch bản Tin nhắn OA (`caType = 13` - `MESSAGE_OA_AUDIENCE`). */\r\n public createMessageOaLeadAudience(request: Dto.ZaloAdsCreateMessageOaLeadAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageOaLeadAudienceResponse> {\n return (this.audiences.createMessageOaLeadAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Dữ liệu chuyển đổi Lead Signal (`caType = 16` - `LEAD_SIGNAL_AUDIENCE`). */\r\n public createLeadSignalAudience(request: Dto.ZaloAdsCreateLeadSignalAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateLeadSignalAudienceResponse> {\n return (this.audiences.createLeadSignalAudience as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.reports\n // =========================================================================\n\n public getReportapiV2Ads(request: Dto.ZaloAdsGetReportapiV2AdsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2AdsResponse> {\n return (this.reports.getReportapiV2Ads as any)(request, options);\n }\n\n public getReportapiV2Campaigns(request: Dto.ZaloAdsGetReportapiV2CampaignsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2CampaignsResponse> {\n return (this.reports.getReportapiV2Campaigns as any)(request, options);\n }\n\n public getReportapiV2UniqueUser(request: Dto.ZaloAdsGetReportapiV2UniqueUserRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2UniqueUserResponse> {\n return (this.reports.getReportapiV2UniqueUser as any)(request, options);\n }\n\n public getReportapiV3Campaigns(request: Dto.ZaloAdsGetReportapiV3CampaignsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV3CampaignsResponse> {\n return (this.reports.getReportapiV3Campaigns as any)(request, options);\n }\n\n public getReportOverview(request: Dto.ZaloAdsGetReportOverviewRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportOverviewResponse> {\n return (this.reports.getReportOverview as any)(request, options);\n }\n\n public getDemographicsReport(request: Dto.ZaloAdsGetDemographicsReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetDemographicsReportResponse> {\n return (this.reports.getDemographicsReport as any)(request, options);\n }\n\n public getZaapiCampaignReportcampaign(request: Dto.ZaloAdsGetZaapiCampaignReportcampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiCampaignReportcampaignResponse> {\n return (this.reports.getZaapiCampaignReportcampaign as any)(request, options);\n }\n\n public listCustomReports(request: Dto.ZaloAdsListCustomReportsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListCustomReportsResponse> {\n return (this.reports.listCustomReports as any)(request, options);\n }\n\n public upsertCustomReport(request: Dto.ZaloAdsUpsertCustomReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpsertCustomReportResponse> {\n return (this.reports.upsertCustomReport as any)(request, options);\n }\n\n public deleteCustomReport(request: Dto.ZaloAdsDeleteCustomReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCustomReportResponse> {\n return (this.reports.deleteCustomReport as any)(request, options);\n }\n\n public listReportFilters(request: Dto.ZaloAdsListReportFiltersRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListReportFiltersResponse> {\n return (this.reports.listReportFilters as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.conversions\n // =========================================================================\n\n public createConversion(request: Dto.ZaloAdsCreateConversionRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateConversionResponse> {\n return (this.conversions.createConversion as any)(request, options);\n }\n\n public deleteConversion(request: Dto.ZaloAdsDeleteConversionRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteConversionResponse> {\n return (this.conversions.deleteConversion as any)(request, options);\n }\n\n public getApiConversionAll(request: Dto.ZaloAdsGetApiConversionAllRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiConversionAllResponse> {\n return (this.conversions.getApiConversionAll as any)(request, options);\n }\n\n public getApiConversionStandardEvents(request: Dto.ZaloAdsGetApiConversionStandardEventsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiConversionStandardEventsResponse> {\n return (this.conversions.getApiConversionStandardEvents as any)(request, options);\n }\n\n public listPersonalPixelLabels(request: Dto.ZaloAdsListPersonalPixelLabelsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListPersonalPixelLabelsResponse> {\n return (this.conversions.listPersonalPixelLabels as any)(request, options);\n }\n\n /** Lấy danh sách tài khoản Zalo Official Account (OA) có dữ liệu chuyển đổi (Lead Signal) (`GET /api/ad/audience/leadSignal/oas`). */\r\n public listLeadSignalOas(options?: RequestOptions): Promise<Dto.ZaloAdsListLeadSignalOasResponse> {\n return (this.conversions.listLeadSignalOas as any)(options);\n }\n\n /** Lấy danh sách rút gọn gồm ID và tên của toàn bộ các sự kiện chuyển đổi (Conversion) đã tạo trên tài khoản quảng cáo Zalo Ads (`GET /api/conversion/names`). */\r\n public listConversionNames(request: Dto.ZaloAdsListConversionNamesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListConversionNamesResponse> {\n return (this.conversions.listConversionNames as any)(request, options);\n }\n\n /** Alias cho `listConversionNames` (`GET /api/conversion/names`). */\r\n public getApiConversionNames(request: Dto.ZaloAdsListConversionNamesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListConversionNamesResponse> {\n return (this.conversions.getApiConversionNames as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.automatedRules\r\n // =========================================================================\r\n\r\n public listAutomatedRules(request: Dto.ZaloAdsListAutomatedRulesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListAutomatedRulesResponse> {\r\n return (this.automatedRules.listAutomatedRules as any)(request, options);\r\n }\r\n\r\n public getAutomatedRuleDetail(request: Dto.ZaloAdsGetAutomatedRuleDetailRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAutomatedRuleDetailResponse> {\r\n return (this.automatedRules.getAutomatedRuleDetail as any)(request, options);\r\n }\r\n\r\n public createAutomatedRule(request: Dto.ZaloAdsCreateAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateAutomatedRuleResponse> {\n return (this.automatedRules.createAutomatedRule as any)(request, options);\n }\n\n public updateAutomatedRule(request: Dto.ZaloAdsUpdateAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateAutomatedRuleResponse> {\n return (this.automatedRules.updateAutomatedRule as any)(request, options);\n }\n\n public changeAutomatedRuleStatus(request: Dto.ZaloAdsChangeAutomatedRuleStatusRequest, options?: RequestOptions): Promise<Dto.ZaloAdsChangeAutomatedRuleStatusResponse> {\n return (this.automatedRules.changeAutomatedRuleStatus as any)(request, options);\n }\n\n public getAutomatedRuleHistory(request: Dto.ZaloAdsGetAutomatedRuleHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAutomatedRuleHistoryResponse> {\n return (this.automatedRules.getAutomatedRuleHistory as any)(request, options);\n }\n\n public deleteAutomatedRule(request: Dto.ZaloAdsDeleteAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteAutomatedRuleResponse> {\n return (this.automatedRules.deleteAutomatedRule as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.flows\n // =========================================================================\n\n public listFlowsByOfficialAccount(request: Dto.ZaloAdsListFlowsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListFlowsByOfficialAccountResponse> {\n return (this.flows.listFlowsByOfficialAccount as any)(request, options);\n }\n\n public createFlow(request: Dto.ZaloAdsCreateFlowRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFlowResponse> {\n return (this.flows.createFlow as any)(request, options);\n }\n\n public updateFlow(request: Dto.ZaloAdsUpdateFlowRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateFlowResponse> {\n return (this.flows.updateFlow as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.media\n // =========================================================================\n\n public getApiFilegroups(request: Dto.ZaloAdsGetApiFilegroupsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiFilegroupsResponse> {\n return (this.media.getApiFilegroups as any)(request, options);\n }\n\n public getApiMediaItems(request: Dto.ZaloAdsGetApiMediaItemsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiMediaItemsResponse> {\n return (this.media.getApiMediaItems as any)(request, options);\n }\n\n public getApiMemberFiles(request: Dto.ZaloAdsGetApiMemberFilesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiMemberFilesResponse> {\n return (this.media.getApiMemberFiles as any)(request, options);\n }\n\n public postApiMediaSave(request: Dto.ZaloAdsPostApiMediaSaveRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiMediaSaveResponse> {\n return (this.media.postApiMediaSave as any)(request, options);\n }\n\n public postApiMemberUploadImage(request: Dto.ZaloAdsPostApiMemberUploadImageRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiMemberUploadImageResponse> {\n return (this.media.postApiMemberUploadImage as any)(request, options);\n }\n\n /** Alias tiện lợi cho `postApiMemberUploadImage` (`POST /api/member/upload-image`). */\r\n public uploadImage(request: Dto.ZaloAdsPostApiMemberUploadImageRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiMemberUploadImageResponse> {\n return (this.media.uploadImage as any)(request, options);\n }\n\n public uploadVideo(request: Dto.ZaloAdsUploadVideoRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUploadVideoResponse> {\n return (this.media.uploadVideo as any)(request, options);\n }\n\n /**\r\n * Kiểm tra tính hợp lệ của tệp Ảnh theo quy chuẩn Zalo Ads (độc lập cho backend).\r\n * Tiêu chí: Có file, Dung lượng tối đa 2MB, Kích thước tối thiểu 150x150, Định dạng JPG/PNG.\r\n */\r\n public validateImage(input: ValidateImageInput): MediaValidationResult {\n return (this.media.validateImage as any)(input);\n }\n\n /**\r\n * Kiểm tra tính hợp lệ của tệp Video theo quy chuẩn Zalo Ads (độc lập cho backend).\r\n * Tiêu chí: Có file, Định dạng .MP4 H.264, Dung lượng tối đa 150MB, Thời lượng tối đa 60s, Tỉ lệ 16:9, 9:16 hoặc 1:1.\r\n */\r\n public validateVideo(input: ValidateVideoInput): MediaValidationResult {\n return (this.media.validateVideo as any)(input);\n }\n}\n","/** Zalo Chat Widget API service. Each API explicitly selects its own request transport. */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/chat-widget.dto\";\r\n\r\nconst OP_ZaloChatWidgetGetChatWidgetLoginConfig: OperationDefinition = {\r\n \"operationId\": \"ZaloChatWidget_getChatWidgetLoginConfig\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/login-tab\",\r\n \"baseUrl\": \"https://widget.chat.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nexport class ZaloChatWidgetService {\r\n public constructor(private readonly client: ZaloSdkHttpClient) {}\r\n public getChatWidgetLoginConfig(request: Dto.ZaloChatWidgetGetChatWidgetLoginConfigRequest, options?: RequestOptions): Promise<Dto.ZaloChatWidgetGetChatWidgetLoginConfigResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloChatWidgetGetChatWidgetLoginConfigResponse>(OP_ZaloChatWidgetGetChatWidgetLoginConfig, this.client.toTransportInput(OP_ZaloChatWidgetGetChatWidgetLoginConfig, request as Record<string, unknown>), options);\r\n }\r\n /** Alias theo tên tool chuẩn `zalo_chat_widget_get_login_config` trong Project Schema Zalo ADS. */\r\n public getLoginConfig(request: Dto.ZaloChatWidgetGetLoginConfigRequest, options?: RequestOptions): Promise<Dto.ZaloChatWidgetGetLoginConfigResponse> {\r\n return this.getChatWidgetLoginConfig(request, options);\r\n }\r\n}\r\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Zalo Forms & Leads:\n * 1. createForm (POST https://ads.zalo.me/api/form/create)\n * 2. listFormsByOfficialAccount (GET https://ads.zalo.me/api/form/getByOaId)\n * 3. listFormLeads (GET https://form.ads.zalo.me/client/manage/api/manageForm/getFormLeads)\n * 4. listConversationLeads (GET https://form.ads.zalo.me/client/manage/api/manageConversation/getConversationLeads)\n * 5. leadNotification (POST enable/disable/updateInterval)\n *\n * Tích hợp toàn bộ giới hạn độ dài ký tự và quy tắc nghiệp vụ trích xuất từ DOM Angular thực tế.\n */\n\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\nexport interface ZaloFormQuestionAnswerInput {\n type: number; // 7 = Họ tên, 13 = SĐT chuẩn, 2 = SĐT phụ\n placeHolder?: string;\n value?: string | null;\n priority?: number;\n}\n\nexport interface ZaloFormQuestionInput {\n title: string;\n type?: number; // 1 = Chuẩn\n isRequired?: boolean;\n editDisabled?: boolean;\n priority?: number;\n answers: ZaloFormQuestionAnswerInput[];\n}\n\nexport interface ZaloFormSectionInput {\n type: number; // 0 = tổng quan; 1 = chi tiết; 2 = bảng giá; 3 = ưu điểm; 4 = ưu đãi\n title?: string;\n disable?: boolean;\n expand?: boolean;\n content?: {\n title?: string;\n description?: string;\n table?: Array<{ key: string; value: string }>;\n images?: Array<{ url: string; title?: string; caption?: string }>;\n videos?: unknown[];\n };\n}\n\nexport interface ZaloCreateFormCleanPayload {\n oaId: string;\n title: string;\n formName: string;\n description?: string;\n coverPhoto: string;\n submitTitle: string;\n thanks: string;\n gotoActionType: number;\n gotoText: string;\n website?: string;\n reviewSubmit: boolean;\n questions: ZaloFormQuestionInput[];\n sections?: ZaloFormSectionInput[];\n useCustomConsent?: boolean;\n consentName?: string;\n consentUrl?: string;\n [key: string]: unknown;\n}\n\nexport interface ZaloCreateFormRequestInput {\n data?: string | ZaloCreateFormCleanPayload;\n [key: string]: unknown;\n}\n\nfunction isValidUrl(val: unknown): boolean {\n if (typeof val !== \"string\" || val.trim() === \"\") return false;\n try {\n const url = new URL(val);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\n/**\n * Kiểm tra tính hợp lệ dữ liệu khi tạo mới Zalo Form (POST /api/form/create)\n */\nexport function validateCreateFormRequest(input: unknown): ValidationResult<ZaloCreateFormCleanPayload> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu tạo Form phải là một object.\"],\n data: undefined\n };\n }\n\n // Hỗ trợ cả { data: JSON.stringify(...) } lẫn payload trực tiếp\n let raw: Record<string, unknown> = input as Record<string, unknown>;\n if (typeof (input as any).data === \"string\") {\n try {\n raw = JSON.parse((input as any).data);\n } catch {\n errors.push(\"Trường 'data' không phải là chuỗi JSON hợp lệ.\");\n return { isValid: false, errors, data: undefined };\n }\n } else if (typeof (input as any).data === \"object\" && (input as any).data !== null) {\n raw = (input as any).data;\n }\n\n // 1. Kiểm tra oaId (Bắt buộc là chuỗi số pageId nội bộ)\n const oaIdRaw = raw.oaId;\n let cleanOaId = \"\";\n if (typeof oaIdRaw === \"string\" && /^[0-9]+$/.test(oaIdRaw.trim())) {\n cleanOaId = oaIdRaw.trim();\n } else if (typeof oaIdRaw === \"number\" && Number.isInteger(oaIdRaw) && oaIdRaw > 0) {\n cleanOaId = String(oaIdRaw);\n } else {\n errors.push(\"Trường 'oaId' bắt buộc phải là chuỗi số nguyên dương đại diện cho pageId nội bộ của OA (ví dụ: '429753475').\");\n }\n\n // 2. Kiểm tra title (2 - 40 ký tự)\n const title = typeof raw.title === \"string\" ? raw.title.trim() : \"\";\n if (!title) {\n errors.push(\"Trường 'title' (tiêu đề form) là bắt buộc.\");\n } else if (title.length < 2 || title.length > 40) {\n errors.push(`Trường 'title' phải có độ dài từ 2 đến 40 ký tự (hiện tại: ${title.length} ký tự).`);\n }\n\n // 3. Kiểm tra formName (2 - 100 ký tự)\n const formName = typeof raw.formName === \"string\" ? raw.formName.trim() : \"\";\n if (!formName) {\n errors.push(\"Trường 'formName' (tên quản trị form) là bắt buộc.\");\n } else if (formName.length < 2 || formName.length > 100) {\n errors.push(`Trường 'formName' phải có độ dài từ 2 đến 100 ký tự (hiện tại: ${formName.length} ký tự).`);\n }\n\n // 4. Kiểm tra description (tối đa 600 ký tự)\n let cleanDescription: string | undefined = undefined;\n if (raw.description !== undefined && raw.description !== null) {\n const desc = String(raw.description).trim();\n if (desc.length > 600) {\n errors.push(`Trường 'description' không được vượt quá 600 ký tự (hiện tại: ${desc.length} ký tự).`);\n } else {\n cleanDescription = desc;\n }\n }\n\n // 5. Kiểm tra coverPhoto (URL hợp lệ)\n const coverPhoto = typeof raw.coverPhoto === \"string\" ? raw.coverPhoto.trim() : \"\";\n if (!coverPhoto) {\n errors.push(\"Trường 'coverPhoto' (ảnh bìa form) là bắt buộc.\");\n } else if (!isValidUrl(coverPhoto)) {\n errors.push(`Trường 'coverPhoto' phải là URL hợp lệ (http:// hoặc https://).`);\n }\n\n // 6. Kiểm tra submitTitle (tối đa 90 ký tự) & thanks (tối đa 255 ký tự)\n const submitTitle = typeof raw.submitTitle === \"string\" && raw.submitTitle.trim() !== \"\"\n ? raw.submitTitle.trim()\n : \"Gửi thông tin thành công\";\n if (submitTitle.length > 90) {\n errors.push(`Trường 'submitTitle' không được vượt quá 90 ký tự (hiện tại: ${submitTitle.length} ký tự).`);\n }\n\n const thanks = typeof raw.thanks === \"string\" && raw.thanks.trim() !== \"\"\n ? raw.thanks.trim()\n : \"Cảm ơn bạn đã gửi thông tin. Chúng tôi sẽ liên hệ trong thời gian sớm nhất.\";\n if (thanks.length > 255) {\n errors.push(`Trường 'thanks' không được vượt quá 255 ký tự (hiện tại: ${thanks.length} ký tự).`);\n }\n\n // 7. Kiểm tra gotoActionType (0 hoặc 1) & website\n const gotoActionType = raw.gotoActionType === 0 ? 0 : 1;\n const gotoText = typeof raw.gotoText === \"string\" && raw.gotoText.trim() !== \"\"\n ? raw.gotoText.trim()\n : (gotoActionType === 1 ? \"Xem trang Web\" : \"Đóng lại\");\n\n let cleanWebsite: string | undefined = undefined;\n if (gotoActionType === 1) {\n if (!raw.website || !isValidUrl(raw.website)) {\n errors.push(\"Khi 'gotoActionType' = 1 (mở website), trường 'website' là bắt buộc và phải là URL hợp lệ.\");\n } else {\n cleanWebsite = String(raw.website).trim();\n }\n }\n\n // 8. Kiểm tra consent (Điều khoản & chính sách)\n const useCustomConsent = Boolean(raw.useCustomConsent);\n let cleanConsentName: string | undefined = undefined;\n let cleanConsentUrl: string | undefined = undefined;\n if (useCustomConsent) {\n const cName = typeof raw.consentName === \"string\" ? raw.consentName.trim() : \"\";\n if (!cName) {\n errors.push(\"Khi 'useCustomConsent' = true, trường 'consentName' (tiêu đề điều khoản) là bắt buộc.\");\n } else if (cName.length > 255) {\n errors.push(`Trường 'consentName' không được vượt quá 255 ký tự (hiện tại: ${cName.length} ký tự).`);\n } else {\n cleanConsentName = cName;\n }\n\n if (!raw.consentUrl || !isValidUrl(raw.consentUrl)) {\n errors.push(\"Khi 'useCustomConsent' = true, trường 'consentUrl' phải là URL hợp lệ chứa chính sách bảo mật.\");\n } else {\n cleanConsentUrl = String(raw.consentUrl).trim();\n }\n }\n\n // 9. Kiểm tra câu hỏi (questions) & Quy tắc SĐT\n if (!Array.isArray(raw.questions) || raw.questions.length === 0) {\n errors.push(\"Biểu mẫu bắt buộc phải có ít nhất 1 câu hỏi trong mảng 'questions'.\");\n }\n\n const cleanQuestions: ZaloFormQuestionInput[] = [];\n let hasPhonePrimary = false;\n let hasPhoneSecondary = false;\n\n if (Array.isArray(raw.questions)) {\n raw.questions.forEach((q: any, idx: number) => {\n const qPrefix = `Câu hỏi [${idx}]`;\n if (!q || typeof q !== \"object\") {\n errors.push(`${qPrefix} phải là một object.`);\n return;\n }\n\n const qTitle = typeof q.title === \"string\" ? q.title.trim() : \"\";\n if (qTitle.length < 2 || qTitle.length > 180) {\n errors.push(`${qPrefix}: Tiêu đề 'title' phải có độ dài từ 2 đến 180 ký tự.`);\n }\n\n if (!Array.isArray(q.answers) || q.answers.length === 0) {\n errors.push(`${qPrefix}: Phải có ít nhất 1 đáp án trong mảng 'answers'.`);\n return;\n }\n\n const cleanAnswers: ZaloFormQuestionAnswerInput[] = [];\n q.answers.forEach((ans: any, aIdx: number) => {\n const aType = Number(ans?.type);\n if (![2, 7, 13].includes(aType)) {\n errors.push(`${qPrefix} đáp án [${aIdx}]: 'type' phải là 7 (Họ tên), 13 (SĐT chuẩn), hoặc 2 (SĐT phụ).`);\n }\n if (aType === 13) hasPhonePrimary = true;\n if (aType === 2) hasPhoneSecondary = true;\n\n cleanAnswers.push({\n type: aType,\n placeHolder: ans?.placeHolder ? String(ans.placeHolder).trim() : undefined,\n value: ans?.value ? String(ans.value).trim() : null,\n priority: typeof ans?.priority === \"number\" ? ans.priority : 500\n });\n });\n\n cleanQuestions.push({\n title: qTitle,\n type: typeof q.type === \"number\" ? q.type : 1,\n isRequired: q.isRequired !== undefined ? Boolean(q.isRequired) : true,\n editDisabled: Boolean(q.editDisabled),\n priority: typeof q.priority === \"number\" ? q.priority : (idx + 1) * 100,\n answers: cleanAnswers\n });\n });\n }\n\n // Áp dụng quy tắc ngầm: Nếu có SĐT phụ (type 2), SĐT chuẩn (type 13) PHẢI khóa cứng editDisabled = true\n if (hasPhoneSecondary) {\n cleanQuestions.forEach(q => {\n if (q.answers.some(a => a.type === 13)) {\n q.editDisabled = true;\n }\n });\n }\n\n // 10. Kiểm tra sections\n const cleanSections: ZaloFormSectionInput[] = [];\n if (Array.isArray(raw.sections)) {\n raw.sections.forEach((sec: any, sIdx: number) => {\n const sPrefix = `Section [${sIdx}]`;\n const sType = Number(sec?.type);\n if (isNaN(sType) || sType < 0 || sType > 4) {\n errors.push(`${sPrefix}: 'type' phải là số từ 0 đến 4 (0=tổng quan, 1=chi tiết, 2=bảng giá, 3=ưu điểm, 4=ưu đãi).`);\n }\n\n const sTitle = typeof sec?.title === \"string\" ? sec.title.trim() : \"\";\n if (sTitle.length > 60) {\n errors.push(`${sPrefix}: 'title' không được vượt quá 60 ký tự.`);\n }\n\n cleanSections.push({\n type: sType,\n title: sTitle,\n disable: Boolean(sec?.disable),\n expand: Boolean(sec?.expand),\n content: sec?.content ? sec.content : {}\n });\n });\n }\n\n const cleanData: ZaloCreateFormCleanPayload = {\n oaId: cleanOaId,\n title,\n formName,\n description: cleanDescription,\n coverPhoto,\n submitTitle,\n thanks,\n gotoActionType,\n gotoText,\n website: cleanWebsite,\n reviewSubmit: raw.reviewSubmit !== undefined ? Boolean(raw.reviewSubmit) : true,\n questions: cleanQuestions,\n sections: cleanSections.length > 0 ? cleanSections : undefined,\n useCustomConsent,\n consentName: cleanConsentName,\n consentUrl: cleanConsentUrl\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ dữ liệu lấy danh sách Form theo OA (GET /api/form/getByOaId)\n */\nexport function validateListFormsByOfficialAccountRequest(input: unknown): ValidationResult<{ oaId: string; isAll?: boolean }> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n let cleanOaId = \"\";\n if (typeof raw.oaId === \"string\" && /^[0-9]+$/.test(raw.oaId.trim())) {\n cleanOaId = raw.oaId.trim();\n } else if (typeof raw.oaId === \"number\" && Number.isInteger(raw.oaId) && raw.oaId > 0) {\n cleanOaId = String(raw.oaId);\n } else {\n errors.push(\"Trường 'oaId' bắt buộc phải là chuỗi số nguyên dương đại diện cho pageId của OA.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { oaId: cleanOaId, isAll: raw.isAll !== undefined ? Boolean(raw.isAll) : true } : undefined\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ dữ liệu tra cứu Form Leads (GET /client/manage/api/manageForm/getFormLeads)\n */\nexport function validateListFormLeadsRequest(input: unknown): ValidationResult<{\n oaId: string;\n type: number;\n limit: number;\n offset: number;\n status: string;\n fromTime: number;\n toTime: number;\n formIds?: string;\n keyword?: string;\n reason?: string;\n labelIds?: string;\n isCommerce?: boolean;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n\n // oaId trong Lead Center bắt buộc là mã chữ (alphanumeric ID từ session)\n const oaId = typeof raw.oaId === \"string\" ? raw.oaId.trim() : \"\";\n if (!oaId) {\n errors.push(\"Trường 'oaId' là bắt buộc (mã chữ từ getAuthSession, ví dụ 'J4UB9MRE497YDQKKK').\");\n } else if (/^[0-9]+$/.test(oaId)) {\n errors.push(\"Trường 'oaId' trên Lead Center phải là mã chữ alphanumeric từ getAuthSession, không dùng chuỗi số pageId (sẽ bị lỗi 403 Forbidden).\");\n }\n\n const type = Number(raw.type);\n if (![1, 5].includes(type)) {\n errors.push(\"Trường 'type' phải là 1 (ZALOFORM) hoặc 5 (COMMERCE).\");\n }\n\n const limit = typeof raw.limit === \"number\" && raw.limit > 0 ? Math.floor(raw.limit) : 20;\n const offset = typeof raw.offset === \"number\" && raw.offset >= 0 ? Math.floor(raw.offset) : 0;\n\n const status = typeof raw.status === \"string\" && raw.status.trim() !== \"\"\n ? raw.status.trim()\n : \"2,6,1,0,7,4,5,3\";\n\n const now = Math.floor(Date.now() / 1000);\n const fromTime = typeof raw.fromTime === \"number\" && raw.fromTime >= 0\n ? (raw.fromTime >= 10000000000 ? Math.floor(raw.fromTime / 1000) : Math.floor(raw.fromTime))\n : now - 90 * 86400;\n const toTime = typeof raw.toTime === \"number\" && raw.toTime >= 0\n ? (raw.toTime >= 10000000000 ? Math.floor(raw.toTime / 1000) : Math.floor(raw.toTime))\n : now;\n\n if (toTime < fromTime) {\n errors.push(\"Mốc thời gian kết thúc 'toTime' phải lớn hơn hoặc bằng 'fromTime'.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n oaId,\n type,\n limit,\n offset,\n status,\n fromTime,\n toTime,\n formIds: raw.formIds ? String(raw.formIds).trim() : undefined,\n keyword: raw.keyword ? String(raw.keyword).trim() : undefined,\n reason: raw.reason ? String(raw.reason).trim() : undefined,\n labelIds: raw.labelIds ? String(raw.labelIds).trim() : undefined,\n isCommerce: raw.isCommerce !== undefined ? Boolean(raw.isCommerce) : false\n } : undefined\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của yêu cầu bật/tắt nhận thông báo khách hàng tiềm năng (POST /client/manage/api/manageForm/enable, disable).\n */\nexport function validateToggleLeadNotificationRequest(\n input: unknown\n): ValidationResult<{ formId: string }> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu bật/tắt thông báo lead phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const formId = typeof raw.formId === \"string\" ? raw.formId.trim() : (raw.formId ? String(raw.formId).trim() : \"\");\n\n if (!formId) {\n errors.push(\"Mã biểu mẫu ('formId') là bắt buộc và không được để trống.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { formId } : undefined,\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của yêu cầu cập nhật chu kỳ thông báo khách hàng tiềm năng (POST /client/manage/api/manageForm/updateInterval).\n */\nexport function validateUpdateLeadNotificationIntervalRequest(\n input: unknown\n): ValidationResult<{ oaId: string; formId: string; interval: number }> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu cập nhật chu kỳ thông báo lead phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const oaId = typeof raw.oaId === \"string\" ? raw.oaId.trim() : (raw.oaId ? String(raw.oaId).trim() : \"\");\n const formId = typeof raw.formId === \"string\" ? raw.formId.trim() : (raw.formId ? String(raw.formId).trim() : \"\");\n\n if (!oaId) {\n errors.push(\"Mã Official Account ('oaId') là bắt buộc và không được để trống.\");\n }\n if (!formId) {\n errors.push(\"Mã biểu mẫu ('formId') là bắt buộc và không được để trống.\");\n }\n\n const interval = Number(raw.interval);\n if (isNaN(interval) || ![0, 1, 6].includes(interval)) {\n errors.push(`Chu kỳ thông báo lead ('interval') '${raw.interval}' không hợp lệ. Phải là số nguyên thuộc [0, 1, 6] (0: Ngay lập tức khi có lead / INSTANT, 1 hoặc 6: Tổng hợp theo ngày / DAILY).`);\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { oaId, formId, interval } : undefined,\n };\n}\n\n/**\n * Gom nhóm toàn bộ Validators cho Form & Lead APIs.\n */\nexport const ZaloFormsValidator = {\n createForm: validateCreateFormRequest,\n listFormsByOfficialAccount: validateListFormsByOfficialAccountRequest,\n listFormLeads: validateListFormLeadsRequest,\n enableLeadNotification: validateToggleLeadNotificationRequest,\n disableLeadNotification: validateToggleLeadNotificationRequest,\n updateLeadNotificationInterval: validateUpdateLeadNotificationIntervalRequest,\n validateLeadNotificationInterval: validateUpdateLeadNotificationIntervalRequest,\n} as const;\n","/** Zalo Forms API service. Each API explicitly selects its own request transport. */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/forms.dto\";\r\nimport type * as AdsDto from \"../dtos/ads.dto\";\r\nimport { ZaloFormsValidator, type ZaloCreateFormCleanPayload } from \"../validators/forms.validator\";\r\n\r\nconst OP_ZaloAdsCreateForm: OperationDefinition = {\r\n operationId: \"zalo_ads_create_form\",\r\n method: \"POST\",\r\n endpoint: \"/api/form/create\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"data\"]\r\n};\r\n\r\nconst OP_ZaloAdsListFormsByOfficialAccount: OperationDefinition = {\r\n operationId: \"zalo_ads_list_forms_by_official_account\",\r\n method: \"GET\",\r\n endpoint: \"/api/form/getByOaId\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [\"oaId\", \"isAll\"],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: []\r\n};\r\n\r\nconst OP_ZaloFormsDisableFormLeadNotification: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_disableFormLeadNotification\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/client/manage/api/notifyLead/disable\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"formId\"\r\n ]\r\n};\r\nconst OP_ZaloFormsEnableFormLeadNotification: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_enableFormLeadNotification\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/client/manage/api/notifyLead/enable\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"formId\"\r\n ]\r\n};\r\nconst OP_ZaloFormsExportFormLeadReport: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_exportFormLeadReport\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getReport\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"formId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListAudienceExclusionTargeting: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listAudienceExclusionTargeting\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getListAudiExcldTargeting\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListConversationLeads: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listConversationLeads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageConversation/getConversationLeads\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"limit\",\r\n \"offset\",\r\n \"status\",\r\n \"toTime\",\r\n \"keyword\",\r\n \"fromTime\",\r\n \"labelIds\",\r\n \"sceneIds\",\r\n \"reason\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListFormLeads: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listFormLeads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getFormLeads\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"type\",\r\n \"limit\",\r\n \"offset\",\r\n \"status\",\r\n \"toTime\",\r\n \"formIds\",\r\n \"keyword\",\r\n \"fromTime\",\r\n \"labelIds\",\r\n \"isCommerce\",\r\n \"reason\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListManagedFormsByOfficialAccount: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listManagedFormsByOfficialAccount\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getByOaId\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"toTime\",\r\n \"fromTime\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListSimpleFormsByOfficialAccount: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listSimpleFormsByOfficialAccount\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getSimpleFormsByOaId\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"type\",\r\n \"toTime\",\r\n \"fromTime\",\r\n \"isCommerce\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListScenariosByOfficialAccount: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listScenariosByOfficialAccount\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageConversation/getScenariosByOaId\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsUpdateFormLeadNotificationInterval: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_updateFormLeadNotificationInterval\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/client/manage/api/notifyLead/updateInterval\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"oaId\",\r\n \"formId\",\r\n \"interval\"\r\n ]\r\n};\r\nconst OP_ZaloFormsGetAuthSession: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_getAuthSession\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/auth/session\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloFormsTrackManageFormEvent: OperationDefinition = {\r\n operationId: \"zalo_forms_track_manage_form_event\",\r\n method: \"GET\",\r\n endpoint: \"/client/manage/api/manageForm/tracking\",\r\n baseUrl: \"https://form.ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [\"eventId\", \"oaId\", \"formId\"],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: []\r\n};\r\n\r\nexport class ZaloFormsService {\r\n public readonly validator = ZaloFormsValidator;\r\n public static readonly validator = ZaloFormsValidator;\r\n\r\n public constructor(private readonly client: ZaloSdkHttpClient) {}\r\n\r\n /**\r\n * Tạo biểu mẫu mới gắn với Official Account (POST https://ads.zalo.me/api/form/create).\r\n * Hỗ trợ truyền thẳng Typed Payload (tự động validate qua ZaloFormsValidator và mã hóa urlencoded)\r\n * hoặc object dạng `{ data: JSON.stringify(...) }`.\r\n */\r\n public async createForm(\r\n request: AdsDto.ZaloAdsCreateFormRequest | ZaloCreateFormCleanPayload | Record<string, unknown>,\r\n options?: RequestOptions\r\n ): Promise<AdsDto.ZaloAdsCreateFormResponse> {\r\n let payloadStr: string;\r\n if (typeof (request as any).data === \"string\") {\r\n payloadStr = (request as any).data;\r\n } else {\r\n const val = ZaloFormsValidator.createForm(request);\r\n if (!val.isValid || !val.data) {\r\n throw new Error(`[ZaloFormsValidator] Dữ liệu tạo form không hợp lệ:\\n - ${val.errors.join(\"\\n - \")}`);\r\n }\r\n payloadStr = JSON.stringify(val.data);\r\n }\r\n return this.client.requestFormUrlEncoded<AdsDto.ZaloAdsCreateFormResponse>(\r\n OP_ZaloAdsCreateForm,\r\n this.client.toTransportInput(OP_ZaloAdsCreateForm, { data: payloadStr }),\r\n options\r\n );\r\n }\r\n\r\n /**\r\n * Lấy danh sách biểu mẫu Zalo Ads theo Official Account (GET https://ads.zalo.me/api/form/getByOaId).\r\n */\r\n public listFormsByOfficialAccount(\r\n request: AdsDto.ZaloAdsListFormsByOfficialAccountRequest,\r\n options?: RequestOptions\r\n ): Promise<AdsDto.ZaloAdsListFormsByOfficialAccountResponse> {\r\n const val = ZaloFormsValidator.listFormsByOfficialAccount(request);\r\n const cleanInput = val.isValid && val.data ? val.data : request;\r\n return this.client.requestWithoutBody<AdsDto.ZaloAdsListFormsByOfficialAccountResponse>(\r\n OP_ZaloAdsListFormsByOfficialAccount,\r\n this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, cleanInput as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n public getAuthSession(options?: RequestOptions): Promise<Dto.ZaloFormsGetAuthSessionResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsGetAuthSessionResponse>(OP_ZaloFormsGetAuthSession, undefined, options);\r\n }\r\n public disableFormLeadNotification(request: Dto.ZaloFormsDisableFormLeadNotificationRequest, options?: RequestOptions): Promise<Dto.ZaloFormsDisableFormLeadNotificationResponse> {\r\n return this.client.requestJson<Dto.ZaloFormsDisableFormLeadNotificationResponse>(OP_ZaloFormsDisableFormLeadNotification, this.client.toTransportInput(OP_ZaloFormsDisableFormLeadNotification, request as Record<string, unknown>), options);\r\n }\r\n public enableFormLeadNotification(request: Dto.ZaloFormsEnableFormLeadNotificationRequest, options?: RequestOptions): Promise<Dto.ZaloFormsEnableFormLeadNotificationResponse> {\r\n return this.client.requestJson<Dto.ZaloFormsEnableFormLeadNotificationResponse>(OP_ZaloFormsEnableFormLeadNotification, this.client.toTransportInput(OP_ZaloFormsEnableFormLeadNotification, request as Record<string, unknown>), options);\r\n }\r\n public exportFormLeadReport(request: Dto.ZaloFormsExportFormLeadReportRequest, options?: RequestOptions): Promise<Dto.ZaloFormsExportFormLeadReportResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsExportFormLeadReportResponse>(OP_ZaloFormsExportFormLeadReport, this.client.toTransportInput(OP_ZaloFormsExportFormLeadReport, request as Record<string, unknown>), options);\r\n }\r\n public listAudienceExclusionTargeting(request: Dto.ZaloFormsListAudienceExclusionTargetingRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListAudienceExclusionTargetingResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListAudienceExclusionTargetingResponse>(OP_ZaloFormsListAudienceExclusionTargeting, this.client.toTransportInput(OP_ZaloFormsListAudienceExclusionTargeting, request as Record<string, unknown>), options);\r\n }\r\n public listConversationLeads(request: Dto.ZaloFormsListConversationLeadsRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListConversationLeadsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListConversationLeadsResponse>(OP_ZaloFormsListConversationLeads, this.client.toTransportInput(OP_ZaloFormsListConversationLeads, request as Record<string, unknown>), options);\r\n }\r\n public listFormLeads(request: Dto.ZaloFormsListFormLeadsRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListFormLeadsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListFormLeadsResponse>(OP_ZaloFormsListFormLeads, this.client.toTransportInput(OP_ZaloFormsListFormLeads, request as Record<string, unknown>), options);\r\n }\r\n public listManagedFormsByOfficialAccount(request: Dto.ZaloFormsListManagedFormsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListManagedFormsByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListManagedFormsByOfficialAccountResponse>(OP_ZaloFormsListManagedFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloFormsListManagedFormsByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n public listSimpleFormsByOfficialAccount(request: Dto.ZaloFormsListSimpleFormsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListSimpleFormsByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListSimpleFormsByOfficialAccountResponse>(OP_ZaloFormsListSimpleFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloFormsListSimpleFormsByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n public listScenariosByOfficialAccount(request: Dto.ZaloFormsListScenariosByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListScenariosByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListScenariosByOfficialAccountResponse>(OP_ZaloFormsListScenariosByOfficialAccount, this.client.toTransportInput(OP_ZaloFormsListScenariosByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n public updateFormLeadNotificationInterval(request: Dto.ZaloFormsUpdateFormLeadNotificationIntervalRequest, options?: RequestOptions): Promise<Dto.ZaloFormsUpdateFormLeadNotificationIntervalResponse> {\r\n return this.client.requestJson<Dto.ZaloFormsUpdateFormLeadNotificationIntervalResponse>(OP_ZaloFormsUpdateFormLeadNotificationInterval, this.client.toTransportInput(OP_ZaloFormsUpdateFormLeadNotificationInterval, request as Record<string, unknown>), options);\r\n }\r\n\r\n /**\r\n * Ghi nhận sự kiện tương tác trên Lead Center (GET /client/manage/api/manageForm/tracking).\r\n */\r\n public trackManageFormEvent(\r\n request: Dto.ZaloFormsTrackManageFormEventRequest,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloFormsTrackManageFormEventResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsTrackManageFormEventResponse>(\r\n OP_ZaloFormsTrackManageFormEvent,\r\n this.client.toTransportInput(OP_ZaloFormsTrackManageFormEvent, request as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n}\r\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho 13 API Zalo Instant Pages.\n * Được thiết kế để xuất ra ngoài cho backend (NestJS/Express/Fastify), middleware hoặc AI Agent\n * sử dụng để xác thực dữ liệu đầu vào trước khi lưu trữ hoặc gọi API Zalo Ads.\n *\n * Lưu ý: Các hàm validate này là độc lập (pure functions), KHÔNG bị nhúng cứng bên trong\n * các hàm gọi HTTP của ZaloInstantPagesService, giúp giữ cho Service gọn gàng và unopinionated.\n */\nimport type * as Dto from \"../dtos/instant-pages.dto\";\n\n/** Kết quả xác thực dữ liệu đầu vào của API. */\nexport interface ValidationResult<T = unknown> {\n /** True nếu dữ liệu hợp lệ và thỏa mãn quy chuẩn; False nếu có ít nhất 1 lỗi. */\n isValid: boolean;\n /** Danh sách các thông báo lỗi chi tiết. Rỗng nếu isValid = true. */\n errors: string[];\n /** Dữ liệu sau khi làm sạch và ép kiểu chuẩn (nếu hợp lệ). */\n data?: T;\n}\n\n/** Helper kiểm tra giá trị có phải là số nguyên dương > 0. */\nfunction isPositiveInteger(val: unknown): boolean {\n if (typeof val === \"number\") return Number.isInteger(val) && val > 0;\n if (typeof val === \"string\" && val.trim() !== \"\") {\n const num = Number(val);\n return Number.isInteger(num) && num > 0;\n }\n return false;\n}\n\n/** Helper ép kiểu về số nguyên dương. */\nfunction toPositiveInteger(val: unknown): number {\n return typeof val === \"number\" ? Math.floor(val) : parseInt(String(val), 10);\n}\n\n// ============================================================================\n// 1. createInstantPage\n// ============================================================================\nexport function validateCreateInstantPageRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesCreateInstantPageRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu tạo Instant Page phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n const validTemplates = [1, 3, 4, 5];\n if (!isPositiveInteger(obj.templateId) || !validTemplates.includes(Number(obj.templateId))) {\n errors.push(`Trường 'templateId' là bắt buộc và phải thuộc danh mục mẫu hợp lệ: ${validTemplates.join(\", \")} (1: Sản phẩm form nhúng, 3: Sản phẩm popup, 4: Kịch bản tin nhắn, 5: Mua sắm).`);\n }\n\n if (obj.oaId !== undefined && obj.oaId !== null) {\n const oaIdStr = String(obj.oaId).trim();\n if (!oaIdStr) {\n errors.push(\"Trường 'oaId' nếu cung cấp không được để trống.\");\n } else if (oaIdStr.length < 10) {\n errors.push(\"Trường 'oaId' trên domain page.ads.zalo.me bắt buộc phải là chuỗi định danh 64-bit của Official Account (lấy từ GET /api/official-accounts), không dùng ID số nguyên ngắn.\");\n }\n }\n\n const data: Dto.ZaloInstantPagesCreateInstantPageRequest = {\n templateId: toPositiveInteger(obj.templateId) as any,\n oaId: obj.oaId ? String(obj.oaId).trim() : undefined,\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? data : undefined,\n };\n}\n\n// ============================================================================\n// 2. cloneInstantPage\n// ============================================================================\nexport function validateCloneInstantPageRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesCloneInstantPageRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu sao chép Instant Page phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : undefined,\n };\n}\n\n// ============================================================================\n// 2. getInstantPageDetail\n// ============================================================================\nexport function validateGetInstantPageDetailRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesGetInstantPageDetailRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy chi tiết Instant Page phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : undefined,\n };\n}\n\n// ============================================================================\n// 3. getInstantPageSharedUser\n// ============================================================================\nexport function validateGetInstantPageSharedUserRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesGetInstantPageSharedUserRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy thông tin người dùng chia sẻ phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n if (!isPositiveInteger(obj.userId)) {\n errors.push(\"Trường 'userId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n instantPageId: toPositiveInteger(obj.instantPageId),\n userId: toPositiveInteger(obj.userId),\n } : undefined,\n };\n}\n\n// ============================================================================\n// 4. listInstantPageEditHistory\n// ============================================================================\nexport function validateListInstantPageEditHistoryRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageEditHistoryRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy lịch sử chỉnh sửa phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n let limit: number | undefined = undefined;\n if (obj.limit !== undefined && obj.limit !== null) {\n if (!isPositiveInteger(obj.limit)) {\n errors.push(\"Trường 'limit' nếu có phải là số nguyên >= 1.\");\n } else {\n limit = toPositiveInteger(obj.limit);\n }\n }\n\n let offset: number | undefined = undefined;\n if (obj.offset !== undefined && obj.offset !== null) {\n const num = Number(obj.offset);\n if (!Number.isInteger(num) || num < 0) {\n errors.push(\"Trường 'offset' nếu có phải là số nguyên >= 0.\");\n } else {\n offset = num;\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n instantPageId: toPositiveInteger(obj.instantPageId),\n ...(limit !== undefined ? { limit } : {}),\n ...(offset !== undefined ? { offset } : {}),\n } : undefined,\n };\n}\n\n// ============================================================================\n// 5. listInstantPageFormRecords\n// ============================================================================\nexport function validateListInstantPageFormRecordsRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageFormRecordsRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu tải bản ghi form phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : undefined,\n };\n}\n\n// ============================================================================\n// 6. listInstantPageShares\n// ============================================================================\nexport function validateListInstantPageSharesRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageSharesRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy danh sách người được chia sẻ phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : undefined,\n };\n}\n\n// ============================================================================\n// 7. listInstantPageUsers\n// ============================================================================\nexport function validateListInstantPageUsersRequest(input?: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageUsersRequest> {\n if (input !== undefined && input !== null && typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy danh sách người dùng phải là một đối tượng hoặc để trống.\"] };\n }\n return { isValid: true, errors: [], data: {} };\n}\n\n// ============================================================================\n// 8. listMiniPageTemplates\n// ============================================================================\nexport function validateListMiniPageTemplatesRequest(input?: unknown): ValidationResult<Dto.ZaloInstantPagesListMiniPageTemplatesRequest> {\n if (input !== undefined && input !== null && typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy mẫu giao diện phải là một đối tượng hoặc để trống.\"] };\n }\n return { isValid: true, errors: [], data: {} };\n}\n\n// ============================================================================\n// 9. searchInstantPages\n// ============================================================================\nexport function validateSearchInstantPagesRequest(input?: unknown): ValidationResult<Dto.ZaloInstantPagesSearchInstantPagesRequest> {\n const errors: string[] = [];\n if (input === undefined || input === null) {\n return { isValid: true, errors: [], data: {} };\n }\n if (typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu tìm kiếm Instant Page phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n const data: Dto.ZaloInstantPagesSearchInstantPagesRequest = {};\n\n if (obj.id !== undefined && obj.id !== null && obj.id !== \"\") {\n if (!isPositiveInteger(obj.id)) {\n errors.push(\"Bộ lọc 'id' nếu có phải là số nguyên dương (> 0).\");\n } else {\n data.id = toPositiveInteger(obj.id);\n }\n }\n\n if (obj.name !== undefined && obj.name !== null) {\n if (typeof obj.name !== \"string\") {\n errors.push(\"Bộ lọc 'name' nếu có phải là chuỗi ký tự.\");\n } else {\n data.name = obj.name;\n }\n }\n\n if (obj.group !== undefined && obj.group !== null && obj.group !== \"\") {\n const grp = Number(obj.group);\n if (grp !== 1 && grp !== 2) {\n errors.push(\"Bộ lọc 'group' chỉ nhận giá trị 1 (Trang sản phẩm) hoặc 2 (Kịch bản tin nhắn).\");\n } else {\n data.group = grp as 1 | 2;\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? data : undefined,\n };\n}\n\n// ============================================================================\n// 10. updateInstantPage\n// ============================================================================\n\n/**\n * Làm sạch key của dictionary data (khử dấu ngoặc kép thừa do parse lỗi hoặc serialize nhầm, ví dụ: '\"1\"' -> '1').\n */\nexport function sanitizeCanvasKeys(data: Record<string, unknown>): Record<string, unknown> {\n const cleanData: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n const cleanKey = key.replace(/^[\"']+|[\"']+$/g, \"\").trim();\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n const valObj = value as Record<string, unknown>;\n const sanitizedSub: Record<string, unknown> = { ...valObj };\n if (sanitizedSub.images && typeof sanitizedSub.images === \"object\" && !Array.isArray(sanitizedSub.images)) {\n sanitizedSub.images = sanitizeCanvasKeys(sanitizedSub.images as Record<string, unknown>);\n }\n if (sanitizedSub.videos && typeof sanitizedSub.videos === \"object\" && !Array.isArray(sanitizedSub.videos)) {\n sanitizedSub.videos = sanitizeCanvasKeys(sanitizedSub.videos as Record<string, unknown>);\n }\n cleanData[cleanKey] = sanitizedSub;\n } else {\n cleanData[cleanKey] = value;\n }\n }\n return cleanData;\n}\n\n/**\n * Kiểm tra tính hợp lệ toàn vẹn của một Canvas Instant Page (renderList, data matching, block rules).\n */\nexport function validateInstantPageCanvas(\n input: unknown,\n isPublishing: boolean = false\n): ValidationResult<Dto.InstantPageCanvas> {\n const errors: string[] = [];\n if (!input) {\n return { isValid: false, errors: [\"Canvas Instant Page không được để trống.\"] };\n }\n\n let canvasObj: Record<string, unknown>;\n if (typeof input === \"string\") {\n if (input.trim() === \"\") {\n return { isValid: false, errors: [\"Chuỗi Canvas JSON không được rỗng.\"] };\n }\n try {\n canvasObj = JSON.parse(input);\n } catch (e) {\n return { isValid: false, errors: [`Canvas JSON không hợp lệ: ${(e as Error).message}`] };\n }\n } else if (typeof input === \"object\" && input !== null) {\n canvasObj = input as Record<string, unknown>;\n } else {\n return { isValid: false, errors: [\"Canvas phải là đối tượng (Object) hoặc chuỗi JSON hợp lệ.\"] };\n }\n\n // 1. Kiểm tra renderList\n if (!canvasObj.renderList || !Array.isArray(canvasObj.renderList)) {\n errors.push(\"Canvas bắt buộc phải có mảng 'renderList' định nghĩa thứ tự hiển thị các khối giao diện (ví dụ: ['0', '1', '2']). Không được dùng { blocks: [] }.\");\n } else if (canvasObj.renderList.length === 0) {\n errors.push(\"Mảng 'renderList' không được rỗng, phải chứa ít nhất 1 ID khối giao diện.\");\n }\n\n // 2. Kiểm tra data\n if (!canvasObj.data || typeof canvasObj.data !== \"object\" || Array.isArray(canvasObj.data)) {\n errors.push(\"Canvas bắt buộc phải có đối tượng 'data' chứa cấu hình chi tiết của từng khối giao diện.\");\n }\n\n if (errors.length > 0) {\n return { isValid: false, errors };\n }\n\n // 3. Khử escape key và kiểm tra toàn vẹn 1-1\n const renderList = (canvasObj.renderList as unknown[]).map((id) =>\n String(id).replace(/^[\"']+|[\"']+$/g, \"\").trim()\n );\n const rawData = canvasObj.data as Record<string, unknown>;\n const cleanData = sanitizeCanvasKeys(rawData);\n\n for (const blockId of renderList) {\n if (!(blockId in cleanData)) {\n errors.push(`Khối ID '${blockId}' có trong 'renderList' nhưng không tồn tại trong từ điển 'data'.`);\n } else {\n const block = cleanData[blockId] as Record<string, unknown>;\n if (!block || typeof block !== \"object\") {\n errors.push(`Khối dữ liệu data['${blockId}'] phải là một đối tượng.`);\n } else if (block.type === undefined || typeof block.type !== \"number\") {\n errors.push(`Khối data['${blockId}'] bắt buộc phải có trường 'type' là mã số nguyên (Block Type).`);\n }\n }\n }\n\n // 4. Kiểm tra điều kiện xuất bản (Pre-publish guard khi isPublishing = true)\n if (isPublishing) {\n for (const blockId of renderList) {\n const block = cleanData[blockId] as Record<string, unknown>;\n if (!block) continue;\n\n // Type 28: SHOP_INFO\n if (block.type === 28) {\n const name = typeof block.name === \"string\" ? block.name.trim() : \"\";\n if (name.length < 2 || name.length > 30) {\n errors.push(`Khối Thông tin Mini Shop (ID: '${blockId}'): Tên Mini Shop ('name') phải từ 2 đến 30 ký tự.`);\n }\n const img = block.image as Record<string, unknown> | undefined;\n if (!img || typeof img.url !== \"string\" || !img.url.startsWith(\"http\")) {\n errors.push(`Khối Thông tin Mini Shop (ID: '${blockId}'): Bắt buộc phải có ảnh logo với URL hợp lệ ('image.url').`);\n }\n }\n\n // Type 29: SHOP_DESCRIPTION\n if (block.type === 29) {\n const len = typeof block.length === \"number\" ? block.length : 0;\n const html = typeof block.outputHtml === \"string\" ? block.outputHtml.trim() : \"\";\n if (len === 0 && html === \"\") {\n errors.push(`Khối Mô tả (ID: '${blockId}'): Không được để trống nội dung mô tả.`);\n }\n }\n\n // Type 1: CAROUSEL\n if (block.type === 1) {\n const indexes = Array.isArray(block.indexes) ? block.indexes : [];\n const images =\n block.images && typeof block.images === \"object\"\n ? (block.images as Record<string, Record<string, unknown>>)\n : {};\n for (const idx of indexes) {\n const img = images[String(idx)];\n if (img && typeof img.url === \"string\" && img.url.trim() === \"\") {\n errors.push(`Khối Carousel (ID: '${blockId}'): Ảnh tại chỉ mục '${idx}' không được để URL rỗng.`);\n }\n }\n }\n\n // Type 21: DEFAULT_MESSAGE\n if (block.type === 21) {\n const msg = typeof block.content === \"string\" ? block.content.trim() : \"\";\n if (msg.length === 0 || msg.length > 40) {\n errors.push(`Khối Tin nhắn mặc định (ID: '${blockId}'): Nội dung tin nhắn phải từ 1 đến 40 ký tự.`);\n }\n }\n }\n }\n\n const resultCanvas: Dto.InstantPageCanvas = {\n version: (typeof canvasObj.version === \"number\" || typeof canvasObj.version === \"string\") ? canvasObj.version : \"1\",\n renderList,\n data: cleanData as Record<string, Dto.InstantPageBlock>,\n ...(canvasObj.freezedTop !== undefined ? { freezedTop: Number(canvasObj.freezedTop) } : {}),\n ...(canvasObj.freezedBottom !== undefined ? { freezedBottom: Number(canvasObj.freezedBottom) } : {}),\n ...(canvasObj.pageTitle !== undefined ? { pageTitle: String(canvasObj.pageTitle) } : {}),\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? resultCanvas : undefined,\n };\n}\n\n// ============================================================================\n// 10. updateInstantPage\n// ============================================================================\nexport function validateUpdateInstantPageRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesUpdateInstantPageRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu cập nhật Instant Page phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n\n // ID validation\n const instantPageId = obj.instantPageId ?? obj.id;\n if (!isPositiveInteger(instantPageId)) {\n errors.push(\"Trường 'instantPageId' (hoặc 'id') là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n const numericId = toPositiveInteger(instantPageId);\n const data: Dto.ZaloInstantPagesUpdateInstantPageRequest = {\n instantPageId: numericId,\n id: numericId,\n };\n\n // Name validation\n if (obj.name !== undefined && obj.name !== null) {\n if (typeof obj.name !== \"string\") {\n errors.push(\"Trường 'name' phải là chuỗi ký tự.\");\n } else {\n data.name = obj.name;\n }\n }\n\n // oaId validation\n if (obj.oaId !== undefined && obj.oaId !== null) {\n if (typeof obj.oaId !== \"string\") {\n errors.push(\"Trường 'oaId' phải là chuỗi ký tự (hoặc chuỗi rỗng \\\"\\\").\");\n } else {\n data.oaId = obj.oaId;\n }\n }\n\n // Active validation: BẮT BUỘC số nguyên 0 hoặc 1, KHÔNG nhận boolean\n if (obj.active !== undefined && obj.active !== null) {\n if (typeof obj.active === \"boolean\") {\n errors.push(\"Trường 'active' bắt buộc là số nguyên 0 (Tắt) hoặc 1 (Bật), không được truyền kiểu boolean (true/false) vì Zalo Ads API sẽ trả về lỗi HTTP 400.\");\n } else if (obj.active !== 0 && obj.active !== 1) {\n errors.push(\"Trường 'active' chỉ nhận giá trị số nguyên 0 (Tắt) hoặc 1 (Bật).\");\n } else {\n data.active = obj.active as Dto.ZaloInstantPageActive;\n }\n }\n\n // Status validation: 0, 1, 2, 3\n let isPublishing = false;\n if (obj.status !== undefined && obj.status !== null) {\n const st = Number(obj.status);\n if (![0, 1, 2, 3].includes(st)) {\n errors.push(\"Trường 'status' phải là một trong các mã: 0 (Bản sao mới tạo chưa lưu), 1 (Đang hoạt động / Đã xuất bản), 3 (Đã kết thúc / Lưu trữ).\");\n } else {\n data.status = st as Dto.ZaloInstantPageStatus;\n if (st === 1) isPublishing = true;\n }\n }\n\n // Draft validation & Canvas Integrity\n let validatedDraftCanvas: Dto.InstantPageCanvas | undefined;\n if (obj.draft !== undefined && obj.draft !== null) {\n const canvasRes = validateInstantPageCanvas(obj.draft, isPublishing);\n if (!canvasRes.isValid) {\n errors.push(...canvasRes.errors.map(err => `[draft] ${err}`));\n } else {\n validatedDraftCanvas = canvasRes.data;\n data.draft = JSON.stringify(canvasRes.data);\n }\n }\n\n // Content validation & Canvas Integrity\n let validatedContentCanvas: Dto.InstantPageCanvas | undefined;\n if (obj.content !== undefined && obj.content !== null) {\n const canvasRes = validateInstantPageCanvas(obj.content, isPublishing);\n if (!canvasRes.isValid) {\n errors.push(...canvasRes.errors.map(err => `[content] ${err}`));\n } else {\n validatedContentCanvas = canvasRes.data;\n data.content = JSON.stringify(canvasRes.data);\n }\n }\n\n // Tự động đồng bộ nội dung khi Xuất bản Live (status === 1)\n if (isPublishing) {\n if (data.draft && !data.content) {\n data.content = data.draft;\n } else if (data.content && !data.draft) {\n data.draft = data.content;\n } else if (!data.draft && !data.content) {\n // Khi status = 1 mà không gửi draft lẫn content, cảnh báo cần có nội dung\n // (Trừ khi người dùng chỉ đổi tên hoặc bật active)\n }\n }\n\n // Kiểm tra ít nhất 1 trường cần cập nhật\n const hasUpdateField = data.name !== undefined || data.oaId !== undefined || data.active !== undefined || data.status !== undefined || data.draft !== undefined || data.content !== undefined;\n if (!hasUpdateField) {\n errors.push(\"Yêu cầu cập nhật Instant Page phải có ít nhất một trường thay đổi: 'name', 'oaId', 'active', 'status', 'draft', hoặc 'content'.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? data : undefined,\n };\n}\n\n// ============================================================================\n// 11. listInstantPageLeads\n// ============================================================================\nexport function validateListInstantPageLeadsRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageLeadsRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy thống kê leads phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n let idsString = \"\";\n if (typeof obj.ids === \"string\" && obj.ids.trim() !== \"\") {\n idsString = obj.ids.trim();\n } else if (Array.isArray(obj.ids) && obj.ids.length > 0) {\n idsString = obj.ids.join(\",\");\n } else {\n errors.push(\"Trường 'ids' là bắt buộc và phải là chuỗi các ID phân tách bằng dấu phẩy (ví dụ: '81433,76292') hoặc mảng các ID.\");\n }\n\n if (idsString) {\n const idParts = idsString.split(\",\").map(s => s.trim()).filter(Boolean);\n if (idParts.length === 0) {\n errors.push(\"Trường 'ids' không chứa bất kỳ ID hợp lệ nào.\");\n } else {\n for (const id of idParts) {\n if (!isPositiveInteger(id)) {\n errors.push(`Mã trang '${id}' trong danh sách 'ids' không phải là số nguyên dương hợp lệ.`);\n }\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { ids: idsString } : undefined,\n };\n}\n\n// ============================================================================\n// 12. listOfficialAccounts\n// ============================================================================\nexport function validateListOfficialAccountsRequest(input?: unknown): ValidationResult<Dto.ZaloInstantPagesListOfficialAccountsRequest> {\n if (input !== undefined && input !== null && typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy danh sách Official Accounts phải là một đối tượng hoặc để trống.\"] };\n }\n return { isValid: true, errors: [], data: {} };\n}\n\n// ============================================================================\n// 13. upsertInstantPageForm\n// ============================================================================\nexport function validateUpsertInstantPageFormRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesUpsertInstantPageFormRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu cấu hình biểu mẫu Instant Page phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n if (!obj.oaId || typeof obj.oaId !== \"string\" || !/^\\d+$/.test(obj.oaId.trim())) {\n errors.push(\"Trường 'oaId' là bắt buộc và phải là chuỗi số định danh Zalo Official Account.\");\n }\n\n if (!obj.formName || typeof obj.formName !== \"string\" || obj.formName.trim() === \"\") {\n errors.push(\"Trường 'formName' là bắt buộc và không được để trống.\");\n }\n\n if (!Array.isArray(obj.questions) || obj.questions.length === 0) {\n errors.push(\"Trường 'questions' là bắt buộc và phải chứa ít nhất một câu hỏi (minItems: 1).\");\n } else {\n obj.questions.forEach((q, idx) => {\n if (!q || typeof q !== \"object\") {\n errors.push(`Câu hỏi số ${idx + 1} phải là một đối tượng.`);\n return;\n }\n const question = q as Record<string, unknown>;\n if (question.type !== 1 && question.type !== 2) {\n errors.push(`Câu hỏi số ${idx + 1}: Trường 'type' bắt buộc là 1 (nhập liệu) hoặc 2 (lựa chọn phương án).`);\n }\n if (!question.title || typeof question.title !== \"string\" || question.title.trim() === \"\") {\n errors.push(`Câu hỏi số ${idx + 1}: Trường 'title' không được để trống.`);\n }\n if (!Array.isArray(question.answers) || question.answers.length === 0) {\n errors.push(`Câu hỏi số ${idx + 1}: Trường 'answers' phải chứa ít nhất một phương án/ô nhập liệu.`);\n } else {\n question.answers.forEach((ans, ansIdx) => {\n if (!ans || typeof ans !== \"object\") {\n errors.push(`Câu hỏi số ${idx + 1}, phương án ${ansIdx + 1}: Phải là một đối tượng.`);\n return;\n }\n const answer = ans as Record<string, unknown>;\n if (answer.type === undefined || typeof answer.type !== \"number\") {\n errors.push(`Câu hỏi số ${idx + 1}, phương án ${ansIdx + 1}: Trường 'type' bắt buộc là số nguyên.`);\n }\n });\n }\n });\n }\n\n const useCustomConsent = typeof obj.useCustomConsent === \"boolean\" ? obj.useCustomConsent : false;\n let consentConfig = obj.consentConfig as Dto.ZaloInstantPagesUpsertInstantPageFormRequest[\"consentConfig\"] | undefined;\n\n if (useCustomConsent) {\n if (!consentConfig || typeof consentConfig !== \"object\") {\n errors.push(\"Khi 'useCustomConsent' = true, trường 'consentConfig' là bắt buộc.\");\n } else {\n if (!consentConfig.address || typeof consentConfig.address !== \"string\") errors.push(\"Cấu hình điều khoản: 'address' không được để trống.\");\n if (!consentConfig.ownerName || typeof consentConfig.ownerName !== \"string\") errors.push(\"Cấu hình điều khoản: 'ownerName' không được để trống.\");\n if (!consentConfig.ownerEmail || typeof consentConfig.ownerEmail !== \"string\") errors.push(\"Cấu hình điều khoản: 'ownerEmail' không được để trống.\");\n if (!consentConfig.ownerPhone || typeof consentConfig.ownerPhone !== \"string\") errors.push(\"Cấu hình điều khoản: 'ownerPhone' không được để trống.\");\n }\n }\n\n const data: Dto.ZaloInstantPagesUpsertInstantPageFormRequest = {\n instantPageId: toPositiveInteger(obj.instantPageId),\n oaId: String(obj.oaId).trim(),\n formName: String(obj.formName).trim(),\n questions: (obj.questions as Dto.ZaloInstantPagesUpsertInstantPageFormRequest[\"questions\"]) ?? [],\n useCustomConsent,\n consentConfig: consentConfig as Dto.ZaloInstantPagesUpsertInstantPageFormRequest[\"consentConfig\"],\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? data : undefined,\n };\n}\n\n// ============================================================================\n// 15. updateInstantPageShares\n// ============================================================================\nexport function validateUpdateInstantPageSharesRequest(\n input: unknown\n): ValidationResult<Dto.ZaloInstantPagesUpdateInstantPageSharesRequest> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu cập nhật quyền chia sẻ Instant Page phải là một đối tượng.\"],\n };\n }\n\n const obj = input as Record<string, unknown>;\n\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n if (!Array.isArray(obj.shares) || obj.shares.length === 0) {\n errors.push(\"Trường 'shares' là bắt buộc và phải chứa ít nhất một người dùng được phân quyền (minItems: 1).\");\n } else {\n const validPermissions = [1, 2, 3, 4];\n const seenUserIds = new Set<number>();\n\n obj.shares.forEach((item, idx) => {\n if (!item || typeof item !== \"object\") {\n errors.push(`Phần tử thứ ${idx + 1} trong danh sách 'shares' phải là một đối tượng.`);\n return;\n }\n const share = item as Record<string, unknown>;\n const userId = Number(share.userId);\n if (!Number.isInteger(userId) || userId <= 0) {\n errors.push(`Phần tử thứ ${idx + 1}: Trường 'userId' phải là số nguyên dương định danh Zalo (hiện tại: ${share.userId}).`);\n } else if (seenUserIds.has(userId)) {\n errors.push(`Phần tử thứ ${idx + 1}: ID người dùng '${userId}' bị trùng lặp trong danh sách phân quyền.`);\n } else {\n seenUserIds.add(userId);\n }\n\n const permission = Number(share.permission);\n if (!validPermissions.includes(permission)) {\n errors.push(`Phần tử thứ ${idx + 1}: Quyền 'permission' không hợp lệ: ${share.permission}. Phải thuộc [1, 2, 3, 4] (1: ADMIN, 2: UPDATE_PAGE, 3: DOWNLOAD_INFO, 4: READ_ONLY).`);\n }\n });\n }\n\n const cleanData: Dto.ZaloInstantPagesUpdateInstantPageSharesRequest = {\n instantPageId: toPositiveInteger(obj.instantPageId),\n shares: (obj.shares as Dto.ZaloInstantPagesShareMemberDto[]) || [],\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n// ============================================================================\n// Master Validator Container\n// ============================================================================\nexport const ZaloInstantPagesValidator = {\n validateCreateInstantPage: validateCreateInstantPageRequest,\n validateCloneInstantPage: validateCloneInstantPageRequest,\n validateGetInstantPageDetail: validateGetInstantPageDetailRequest,\n validateGetInstantPageSharedUser: validateGetInstantPageSharedUserRequest,\n validateListInstantPageEditHistory: validateListInstantPageEditHistoryRequest,\n validateListInstantPageFormRecords: validateListInstantPageFormRecordsRequest,\n validateListInstantPageShares: validateListInstantPageSharesRequest,\n validateUpdateInstantPageShares: validateUpdateInstantPageSharesRequest,\n validateUpdateShares: validateUpdateInstantPageSharesRequest,\n validateListInstantPageUsers: validateListInstantPageUsersRequest,\n validateListMiniPageTemplates: validateListMiniPageTemplatesRequest,\n validateSearchInstantPages: validateSearchInstantPagesRequest,\n validateUpdateInstantPage: validateUpdateInstantPageRequest,\n validateListInstantPageLeads: validateListInstantPageLeadsRequest,\n validateListOfficialAccounts: validateListOfficialAccountsRequest,\n validateUpsertInstantPageForm: validateUpsertInstantPageFormRequest,\n};\n","/** Zalo Instant Pages API service. Each API explicitly selects its own request transport. */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/instant-pages.dto\";\r\nimport { ZaloInstantPagesValidator } from \"../validators/instant-pages.validator\";\r\n\r\nconst OP_ZaloInstantPagesCreateInstantPage: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_createInstantPage\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/instant-pages\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"templateId\",\r\n \"oaId\"\r\n ]\r\n};\r\nconst OP_ZaloInstantPagesCloneInstantPage: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_cloneInstantPage\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/clone\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesGetInstantPageDetail: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_getInstantPageDetail\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesGetInstantPageSharedUser: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_getInstantPageSharedUser\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/sharedUser\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [\r\n \"userId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageEditHistory: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageEditHistory\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/edit-history\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [\r\n \"limit\",\r\n \"offset\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageFormRecords: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageFormRecords\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/form/records\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageShares: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageShares\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/shares\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesUpdateInstantPageShares: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_updateInstantPageShares\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/shares\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageUsers: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageUsers\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/users\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListMiniPageTemplates: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listMiniPageTemplates\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/templates\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesSearchInstantPages: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_searchInstantPages\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"id\",\r\n \"name\",\r\n \"group\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesUpdateInstantPage: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_updateInstantPage\",\r\n \"method\": \"PUT\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"id\",\r\n \"name\",\r\n \"oaId\",\r\n \"draft\",\r\n \"active\",\r\n \"status\",\r\n \"content\"\r\n ]\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageLeads: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageLeads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/leads\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"ids\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListOfficialAccounts: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listOfficialAccounts\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/official-accounts\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesUpsertInstantPageForm: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_upsertInstantPageForm\",\r\n \"method\": \"PUT\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/form\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"oaId\",\r\n \"formName\",\r\n \"questions\",\r\n \"useCustomConsent\",\r\n \"consentConfig\"\r\n ]\r\n};\r\n\r\nexport class ZaloInstantPagesService {\r\n /**\r\n * Bộ công cụ kiểm tra tính hợp lệ dữ liệu (Standalone Validators) cho 13 API Instant Pages.\r\n * Dùng ở backend (NestJS/Express/Fastify), middleware hoặc AI Agent để verify payload trước khi gọi SDK.\r\n */\r\n public static readonly validator = ZaloInstantPagesValidator;\r\n\r\n public constructor(private readonly client: ZaloSdkHttpClient) {}\r\n public createInstantPage(request: Dto.ZaloInstantPagesCreateInstantPageRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesCreateInstantPageResponse> {\r\n return this.client.requestJson<Dto.ZaloInstantPagesCreateInstantPageResponse>(OP_ZaloInstantPagesCreateInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCreateInstantPage, request as Record<string, unknown>), options);\r\n }\r\n public cloneInstantPage(request: Dto.ZaloInstantPagesCloneInstantPageRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesCloneInstantPageResponse> {\r\n return this.client.requestJson<Dto.ZaloInstantPagesCloneInstantPageResponse>(OP_ZaloInstantPagesCloneInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCloneInstantPage, request as Record<string, unknown>), options);\r\n }\r\n public getInstantPageDetail(request: Dto.ZaloInstantPagesGetInstantPageDetailRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesGetInstantPageDetailResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesGetInstantPageDetailResponse>(OP_ZaloInstantPagesGetInstantPageDetail, this.client.toTransportInput(OP_ZaloInstantPagesGetInstantPageDetail, request as Record<string, unknown>), options);\r\n }\r\n public getInstantPageSharedUser(request: Dto.ZaloInstantPagesGetInstantPageSharedUserRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesGetInstantPageSharedUserResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesGetInstantPageSharedUserResponse>(OP_ZaloInstantPagesGetInstantPageSharedUser, this.client.toTransportInput(OP_ZaloInstantPagesGetInstantPageSharedUser, request as Record<string, unknown>), options);\r\n }\r\n public listInstantPageEditHistory(request: Dto.ZaloInstantPagesListInstantPageEditHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageEditHistoryResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageEditHistoryResponse>(OP_ZaloInstantPagesListInstantPageEditHistory, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageEditHistory, request as Record<string, unknown>), options);\r\n }\r\n public listInstantPageFormRecords(request: Dto.ZaloInstantPagesListInstantPageFormRecordsRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageFormRecordsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageFormRecordsResponse>(OP_ZaloInstantPagesListInstantPageFormRecords, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageFormRecords, request as Record<string, unknown>), options);\r\n }\r\n public listInstantPageShares(request: Dto.ZaloInstantPagesListInstantPageSharesRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageSharesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageSharesResponse>(OP_ZaloInstantPagesListInstantPageShares, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageShares, request as Record<string, unknown>), options);\r\n }\r\n public updateInstantPageShares(request: Dto.ZaloInstantPagesUpdateInstantPageSharesRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesUpdateInstantPageSharesResponse> {\r\n const transportInput = {\r\n path_param: { instantPageId: request.instantPageId },\r\n body: request.shares\r\n };\r\n return this.client.requestJson<Dto.ZaloInstantPagesUpdateInstantPageSharesResponse>(OP_ZaloInstantPagesUpdateInstantPageShares, transportInput, options);\r\n }\r\n public listInstantPageUsers(request: Dto.ZaloInstantPagesListInstantPageUsersRequest = {}, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageUsersResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageUsersResponse>(OP_ZaloInstantPagesListInstantPageUsers, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageUsers, request as Record<string, unknown>), options);\r\n }\r\n public listMiniPageTemplates(request: Dto.ZaloInstantPagesListMiniPageTemplatesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListMiniPageTemplatesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListMiniPageTemplatesResponse>(OP_ZaloInstantPagesListMiniPageTemplates, this.client.toTransportInput(OP_ZaloInstantPagesListMiniPageTemplates, request as Record<string, unknown>), options);\r\n }\r\n public searchInstantPages(request: Dto.ZaloInstantPagesSearchInstantPagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloInstantPagesSearchInstantPagesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesSearchInstantPagesResponse>(OP_ZaloInstantPagesSearchInstantPages, this.client.toTransportInput(OP_ZaloInstantPagesSearchInstantPages, request as Record<string, unknown>), options);\r\n }\r\n public updateInstantPage(request: Dto.ZaloInstantPagesUpdateInstantPageRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesUpdateInstantPageResponse> {\r\n return this.client.requestJson<Dto.ZaloInstantPagesUpdateInstantPageResponse>(OP_ZaloInstantPagesUpdateInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesUpdateInstantPage, request as Record<string, unknown>), options);\r\n }\r\n public listInstantPageLeads(request: Dto.ZaloInstantPagesListInstantPageLeadsRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageLeadsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageLeadsResponse>(OP_ZaloInstantPagesListInstantPageLeads, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageLeads, request as Record<string, unknown>), options);\r\n }\r\n public listOfficialAccounts(request: Dto.ZaloInstantPagesListOfficialAccountsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListOfficialAccountsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListOfficialAccountsResponse>(OP_ZaloInstantPagesListOfficialAccounts, this.client.toTransportInput(OP_ZaloInstantPagesListOfficialAccounts, request as Record<string, unknown>), options);\r\n }\r\n public upsertInstantPageForm(request: Dto.ZaloInstantPagesUpsertInstantPageFormRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesUpsertInstantPageFormResponse> {\r\n return this.client.requestJson<Dto.ZaloInstantPagesUpsertInstantPageFormResponse>(OP_ZaloInstantPagesUpsertInstantPageForm, this.client.toTransportInput(OP_ZaloInstantPagesUpsertInstantPageForm, request as Record<string, unknown>), options);\r\n }\r\n}\r\n","/** Zalo Profile Ads API service (`https://profile.ads.zalo.me`). Each API explicitly selects its own request transport. */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/profile-ads.dto\";\n\nconst OP_ZaloProfileAdsCreateOaPage: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_createOaPage\",\n \"method\": \"POST\",\n \"endpoint\": \"/oa\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"option\",\n \"crsf-token\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"typeId\",\n \"tier\",\n \"typeName\",\n \"categoryId\",\n \"subCategoryId\",\n \"oaName\",\n \"description\",\n \"contactName\",\n \"contactPhone\",\n \"coverId\",\n \"avatarId\",\n \"province\",\n \"district\",\n \"address\",\n \"agreeTerm\"\n ]\n};\n\nconst OP_ZaloProfileAdsUploadOaAvatar: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_uploadOaAvatar\",\n \"method\": \"POST\",\n \"endpoint\": \"/ajax/avatar/upload\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [\n \"avatar-file\"\n ],\n \"pathFields\": [],\n \"queryFields\": [\n \"option\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"avatar-file\",\n \"is-new\"\n ]\n};\n\nconst OP_ZaloProfileAdsUploadOaCover: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_uploadOaCover\",\n \"method\": \"POST\",\n \"endpoint\": \"/ajax/cover/upload\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [\n \"cover-file\"\n ],\n \"pathFields\": [],\n \"queryFields\": [\n \"option\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"cover-file\",\n \"is-new\"\n ]\n};\n\nconst OP_ZaloProfileAdsGetProvinces: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_getProvinces\",\n \"method\": \"GET\",\n \"endpoint\": \"/ajax/get-province\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloProfileAdsGetDistricts: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_getDistricts\",\n \"method\": \"GET\",\n \"endpoint\": \"/ajax/get-district\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"provinceId\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nexport class ZaloProfileAdsService {\n public constructor(private readonly client: ZaloSdkHttpClient) {}\n\n public async createOaPage(\n request: Dto.ZaloProfileAdsCreateOaPageRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsCreateOaPageResponse> {\n let csrfToken = request[\"crsf-token\"];\n if (!csrfToken && this.client.authManager) {\n const session = await this.client.authManager.getSession(\"profile.ads.zalo.me\");\n csrfToken = session.cookies[\"CSRF_TOKEN\"] ?? session.xsrfToken;\n }\n const normalizedRequest: Record<string, unknown> = {\n option: \"createpage\",\n typeId: 2,\n tier: 0,\n typeName: \"store\",\n categoryId: 10003,\n agreeTerm: true,\n ...request,\n ...(csrfToken ? { \"crsf-token\": csrfToken } : {}),\n };\n return this.client.requestFormUrlEncoded<Dto.ZaloProfileAdsCreateOaPageResponse>(\n OP_ZaloProfileAdsCreateOaPage,\n this.client.toTransportInput(OP_ZaloProfileAdsCreateOaPage, normalizedRequest),\n options\n );\n }\n\n public uploadOaAvatar(\n request: Dto.ZaloProfileAdsUploadOaAvatarRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsUploadOaAvatarResponse> {\n const normalizedRequest: Record<string, unknown> = {\n option: \"update\",\n \"is-new\": \"true\",\n ...request,\n };\n return this.client.requestMultipart<Dto.ZaloProfileAdsUploadOaAvatarResponse>(\n OP_ZaloProfileAdsUploadOaAvatar,\n this.client.toTransportInput(OP_ZaloProfileAdsUploadOaAvatar, normalizedRequest),\n options\n );\n }\n\n public uploadOaCover(\n request: Dto.ZaloProfileAdsUploadOaCoverRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsUploadOaCoverResponse> {\n const normalizedRequest: Record<string, unknown> = {\n option: \"update\",\n \"is-new\": \"true\",\n ...request,\n };\n return this.client.requestMultipart<Dto.ZaloProfileAdsUploadOaCoverResponse>(\n OP_ZaloProfileAdsUploadOaCover,\n this.client.toTransportInput(OP_ZaloProfileAdsUploadOaCover, normalizedRequest),\n options\n );\n }\n\n public getProvinces(\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsGetProvincesResponse> {\n return this.client.requestWithoutBody<Dto.ZaloProfileAdsGetProvincesResponse>(\n OP_ZaloProfileAdsGetProvinces,\n {},\n options\n );\n }\n\n public getDistricts(\n request: Dto.ZaloProfileAdsGetDistrictsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsGetDistrictsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloProfileAdsGetDistrictsResponse>(\n OP_ZaloProfileAdsGetDistricts,\n this.client.toTransportInput(OP_ZaloProfileAdsGetDistricts, request as unknown as Record<string, unknown>),\n options\n );\n }\n}\n","/** Zalo Widget API API service. Each API explicitly selects its own request transport. */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/widget.dto\";\r\n\r\nconst OP_ZaloWidgetAPIGetOfficialAccountInfo: OperationDefinition = {\r\n \"operationId\": \"ZaloWidgetAPI_getOfficialAccountInfo\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/v1/oa\",\r\n \"baseUrl\": \"https://api.widget.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaid\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloWidgetAPIGetWidgetUserProfile: OperationDefinition = {\r\n \"operationId\": \"ZaloWidgetAPI_getWidgetUserProfile\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/v1/zuser\",\r\n \"baseUrl\": \"https://api.widget.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloWidgetAPIListStickerCategories: OperationDefinition = {\r\n \"operationId\": \"ZaloWidgetAPI_listStickerCategories\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/v1/stk-cate\",\r\n \"baseUrl\": \"https://api.widget.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloWidgetAPIListStickersByCategory: OperationDefinition = {\r\n \"operationId\": \"ZaloWidgetAPI_listStickersByCategory\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/v1/stk-cate/stickers\",\r\n \"baseUrl\": \"https://api.widget.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"cate_id\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nexport class ZaloWidgetApiService {\r\n public constructor(private readonly client: ZaloSdkHttpClient) {}\r\n public getOfficialAccountInfo(request: Dto.ZaloWidgetAPIGetOfficialAccountInfoRequest, options?: RequestOptions): Promise<Dto.ZaloWidgetAPIGetOfficialAccountInfoResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloWidgetAPIGetOfficialAccountInfoResponse>(OP_ZaloWidgetAPIGetOfficialAccountInfo, this.client.toTransportInput(OP_ZaloWidgetAPIGetOfficialAccountInfo, request as Record<string, unknown>), options);\r\n }\r\n public getWidgetUserProfile(request: Dto.ZaloWidgetAPIGetWidgetUserProfileRequest, options?: RequestOptions): Promise<Dto.ZaloWidgetAPIGetWidgetUserProfileResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloWidgetAPIGetWidgetUserProfileResponse>(OP_ZaloWidgetAPIGetWidgetUserProfile, this.client.toTransportInput(OP_ZaloWidgetAPIGetWidgetUserProfile, request as Record<string, unknown>), options);\r\n }\r\n public listStickerCategories(request: Dto.ZaloWidgetAPIListStickerCategoriesRequest, options?: RequestOptions): Promise<Dto.ZaloWidgetAPIListStickerCategoriesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloWidgetAPIListStickerCategoriesResponse>(OP_ZaloWidgetAPIListStickerCategories, this.client.toTransportInput(OP_ZaloWidgetAPIListStickerCategories, request as Record<string, unknown>), options);\r\n }\r\n public listStickersByCategory(request: Dto.ZaloWidgetAPIListStickersByCategoryRequest, options?: RequestOptions): Promise<Dto.ZaloWidgetAPIListStickersByCategoryResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloWidgetAPIListStickersByCategoryResponse>(OP_ZaloWidgetAPIListStickersByCategory, this.client.toTransportInput(OP_ZaloWidgetAPIListStickersByCategory, request as Record<string, unknown>), options);\r\n }\r\n}\r\n","import type { ZaloAuthDomain, ZaloAuthManager, ZaloDomainSession, ZaloSsoAuthOptions } from \"./auth\";\nimport { ZaloSdkHttpClient } from \"./client\";\nimport { ZaloAdsService } from \"./services/ads.service\";\nimport { ZaloCampaignsService } from \"./services/campaigns.service\";\nimport { ZaloAccountService } from \"./services/account.service\";\nimport { ZaloAudiencesService } from \"./services/audiences.service\";\nimport { ZaloReportsService } from \"./services/reports.service\";\nimport { ZaloConversionsService } from \"./services/conversions.service\";\nimport { ZaloAutomatedRulesService } from \"./services/automated-rules.service\";\nimport { ZaloFlowsService } from \"./services/flows.service\";\nimport { ZaloChatWidgetService } from \"./services/chat-widget.service\";\nimport { ZaloFormsService } from \"./services/forms.service\";\nimport { ZaloInstantPagesService } from \"./services/instant-pages.service\";\nimport { ZaloProfileAdsService } from \"./services/profile-ads.service\";\nimport { ZaloWidgetApiService } from \"./services/widget.service\";\nimport { ZaloMediaService } from \"./services/media.service\";\nimport type { ZaloAccountScope, ZaloAdsSdkOptions, ZaloSdkAuth } from \"./types\";\n\n/**\n * Entry point for the Zalo Ads ecosystem SDK (`ads.zalo.me`, `page.ads.zalo.me`, `form.ads.zalo.me`,\n * `profile.ads.zalo.me`, `api.widget.zalo.me`, `widget.chat.zalo.me`).\n *\n * Hỗ trợ 2 chế độ xác thực:\n * 1. **Tự động Silent OAuth2 PKCE SSO qua `zpsid`** (Khuyên dùng):\n * `new ZaloAdsSdk({ zpsid: \"g_kQ.330114198...\" })` — SDK tự động đổi `zpsid` lấy `PLAY_SESSION`,\n * `XSRF-TOKEN`, `zf_id` và `Authorization` token riêng cho từng domain và tự động làm mới khi gặp 401.\n * 2. **Tự truyền Header/Cookie thủ công**:\n * Qua `auth`, `authByHost`, hoặc `setAuth` / `setAuthForHost`.\n */\nexport class ZaloAdsSdk {\n private readonly client: ZaloSdkHttpClient;\n public readonly ads: ZaloAdsService;\n public readonly campaigns: ZaloCampaignsService;\n public readonly account: ZaloAccountService;\n public readonly audiences: ZaloAudiencesService;\n public readonly targeting: ZaloAudiencesService;\n public readonly reports: ZaloReportsService;\n public readonly conversions: ZaloConversionsService;\n public readonly pixel: ZaloConversionsService;\n public readonly automatedRules: ZaloAutomatedRulesService;\n public readonly rules: ZaloAutomatedRulesService;\n public readonly flows: ZaloFlowsService;\n public readonly media: ZaloMediaService;\n public readonly forms: ZaloFormsService;\n public readonly instantPages: ZaloInstantPagesService;\n public readonly profileAds: ZaloProfileAdsService;\n public readonly profile: ZaloProfileAdsService;\n public readonly widget: ZaloWidgetApiService;\n public readonly chatWidget: ZaloChatWidgetService;\n\n public constructor(options: ZaloAdsSdkOptions | string = {}) {\n const resolvedOptions: ZaloAdsSdkOptions =\n typeof options === \"string\" ? { zpsid: options } : options;\n this.client = new ZaloSdkHttpClient(resolvedOptions);\n this.ads = new ZaloAdsService(this.client);\n this.campaigns = this.ads;\n this.account = this.ads.account;\n this.audiences = this.ads.audiences;\n this.targeting = this.ads.audiences;\n this.reports = this.ads.reports;\n this.conversions = this.ads.conversions;\n this.pixel = this.ads.conversions;\n this.automatedRules = this.ads.automatedRules;\n this.rules = this.ads.automatedRules;\n this.flows = this.ads.flows;\n this.media = this.ads.media;\n this.forms = new ZaloFormsService(this.client);\n this.instantPages = new ZaloInstantPagesService(this.client);\n this.profileAds = new ZaloProfileAdsService(this.client);\n this.profile = this.profileAds;\n this.widget = new ZaloWidgetApiService(this.client);\n this.chatWidget = new ZaloChatWidgetService(this.client);\n }\n\n /**\n * Trình quản lý xác thực `ZaloAuthManager` đang gắn với SDK (nếu khởi tạo bằng `zpsid` / `ssoAuth` / `authManager`).\n */\n public get authManager(): ZaloAuthManager | undefined {\n return this.client.authManager;\n }\n\n /**\n * Phạm vi tài khoản quảng cáo cô lập (Isolated Workspace) đang gắn với instance SDK.\n */\n public get accountScope(): ZaloAccountScope | undefined {\n return this.client.accountScope;\n }\n\n /**\n * Cập nhật phạm vi tài khoản quảng cáo cô lập.\n */\n public setAccountScope(scope?: ZaloAccountScope): void {\n this.client.accountScope = scope;\n if (this.client.authManager) {\n this.client.authManager.setAccountScope(scope);\n }\n }\n\n /**\n * Cập nhật cookie `zpsid` gốc (hoặc chuỗi Cookie trình duyệt) để tự động xác thực cho toàn bộ các domain Zalo Ads.\n */\n public setZpsid(zpsidInput: string, ssoOptions?: Omit<ZaloSsoAuthOptions, \"zpsid\">): ZaloAuthManager {\n return this.client.setZpsid(zpsidInput, ssoOptions);\n }\n\n /**\n * Chủ động thực hiện OAuth2 PKCE Handshake trước cho một domain cụ thể.\n */\n public authenticateDomain(domain: ZaloAuthDomain, forceRefresh = false): Promise<ZaloDomainSession> {\n if (!this.client.authManager) {\n throw new Error(\"ZaloAdsSdk: `authManager` is not configured. Call `sdk.setZpsid(...)` or pass `zpsid` in constructor.\");\n }\n return this.client.authManager.authenticateDomain(domain, forceRefresh);\n }\n\n /**\n * Chủ động thực hiện OAuth2 PKCE Handshake đồng thời cho nhiều domain (`ads.zalo.me`, `page.ads.zalo.me`, `form.ads.zalo.me`).\n */\n public authenticateAll(domains?: ZaloAuthDomain[]): Promise<Record<string, ZaloDomainSession>> {\n if (!this.client.authManager) {\n throw new Error(\"ZaloAdsSdk: `authManager` is not configured. Call `sdk.setZpsid(...)` or pass `zpsid` in constructor.\");\n }\n return this.client.authManager.authenticateAll(domains);\n }\n\n public setAuth(auth?: ZaloSdkAuth): void { this.client.setAuth(auth); }\n public setAuthForHost(host: string, auth?: ZaloSdkAuth): void { this.client.setAuthForHost(host, auth); }\n}\n","import {\n deriveAccountKeyFromZpsid,\n parseZaloCookieInput,\n type ZaloAdsWhoamiProfile,\n type ZaloAuthDomain,\n type ZaloDomainSession,\n type ZaloFormSessionProfile,\n} from \"./auth\";\nimport type { ZaloInstantPagesOfficialAccountItem } from \"./dtos/instant-pages.dto\";\nimport { ZaloAdsSdk } from \"./sdk\";\nimport {\n MemoryZaloSessionStore,\n TieredZaloSessionStore,\n type ZaloRedisLikeClient,\n type ZaloSessionStore,\n} from \"./store\";\nimport type { ZaloAccountScope, ZaloAdsSdkOptions } from \"./types\";\n\nexport interface ZaloIntegrationCredentials {\n /**\n * Giá trị cookie `zpsid` gốc của Zalo (hoặc nguyên chuỗi Cookie trình duyệt có chứa `zpsid=...`).\n */\n zpsid: string;\n /**\n * Cookie phụ `zoaw_sek` (tùy chọn, dùng cho các API thuộc `api.widget.zalo.me` / `widget.chat.zalo.me`).\n */\n zoawSek?: string;\n /**\n * Các cookie bổ sung muốn gắn kèm.\n */\n extraCookies?: Record<string, string>;\n /**\n * Phạm vi tài khoản quảng cáo cô lập (Isolated Workspace) - chứa accountId, memberId, agencyId, accountType.\n */\n accountScope?: ZaloAccountScope;\n}\n\nexport interface ZaloAdsClientRequest extends ZaloIntegrationCredentials {\n /**\n * Định danh Integration (`integrationId`) hoặc `accountKey` của người dùng trong hệ thống Backend.\n */\n integrationId: string;\n}\n\nexport interface ZaloIntegrationVerificationResult {\n /** Định danh tài khoản / Integration ID */\n accountKey: string;\n /** Thông tin tài khoản quảng cáo trên ads.zalo.me (/api/whoami) */\n adsProfile?: ZaloAdsWhoamiProfile;\n /** Danh sách Official Accounts trên page.ads.zalo.me (/api/official-accounts) */\n officialAccounts: ZaloInstantPagesOfficialAccountItem[];\n /** Thông tin phiên & danh sách OA mã hóa trên form.ads.zalo.me (/client/manage/api/auth/session) */\n formProfile?: ZaloFormSessionProfile;\n /** Toàn bộ các phiên đã khởi tạo và lưu vào cache (RAM/Redis) */\n sessions: Record<string, ZaloDomainSession>;\n}\n\nexport interface ZaloAdsIntegrationManagerOptions {\n /**\n * Tầng lưu trữ session dùng chung cho toàn bộ các tài khoản/integrations.\n * Nếu không truyền `sessionStore` và `redis`, mặc định dùng `MemoryZaloSessionStore` (RAM LRU).\n */\n sessionStore?: ZaloSessionStore;\n /**\n * Truyền trực tiếp `RedisService` (của `redai-v201-be-app-staging`) hoặc `ioredis` client.\n * Tự động kích hoạt `TieredZaloSessionStore` (L1 RAM + L2 Redis + Distributed Lock).\n */\n redis?: ZaloRedisLikeClient;\n /**\n * Tiền tố key trên Redis (mặc định: `'zalo_ads:sso'`).\n */\n redisKeyPrefix?: string;\n /**\n * Thời gian sống tối đa của L1 RAM cache (giây) khi dùng chế độ Tiered (RAM + Redis). Mặc định: 300s (5 phút).\n */\n l1MaxTtlSeconds?: number;\n /**\n * Thời gian sống mặc định của mỗi phiên OAuth domain (mili-giây). Mặc định: 45 phút.\n */\n sessionTtlMs?: number;\n /**\n * Số lượng instance SDK / tài khoản tối đa giữ trong Pool RAM (LRU). Mặc định: 500.\n */\n maxAccountsInMemory?: number;\n /**\n * Hàm callback giải mã / đọc `zpsid` từ Database hoặc Credential Vault của Backend theo `integrationId`.\n * Khi cấu hình hàm này, chỉ cần gọi `await manager.forIntegration(integrationId)` mà không cần truyền lại `zpsid`.\n */\n resolveCredentials?: (\n integrationId: string\n ) => Promise<ZaloIntegrationCredentials | string> | ZaloIntegrationCredentials | string;\n /**\n * Hook được gọi mỗi khi một tài khoản/integration làm mới phiên của một domain.\n */\n onSessionRefreshed?: (\n integrationId: string,\n domain: ZaloAuthDomain,\n session: ZaloDomainSession\n ) => Promise<void> | void;\n fetch?: typeof fetch;\n baseUrls?: ZaloAdsSdkOptions[\"baseUrls\"];\n}\n\n/**\n * Trình quản lý Đa Tài Khoản / Đa Integration (`ZaloAdsIntegrationManager`) dành cho Backend (`redai-v201-be-app-staging`).\n *\n * Tính năng:\n * 1. Quản lý hàng trăm/nghìn `integrationId` khác nhau của nhiều người dùng mà không bị lẫn lộn session.\n * 2. Hỗ trợ lưu trữ phiên trên RAM (`MemoryZaloSessionStore` có LRU eviction) hoặc 2 tầng L1 RAM + L2 Redis (`TieredZaloSessionStore`).\n * 3. Có Distributed Lock trên Redis giúp nhiều worker/pod backend không gọi trùng OAuth handshake của cùng 1 `integrationId`.\n * 4. Tự động phát hiện khi người dùng cập nhật `zpsid` mới cho `integrationId` cũ để xóa cache cũ và handshake lại.\n */\nexport class ZaloAdsIntegrationManager {\n public readonly sessionStore: ZaloSessionStore;\n private readonly sdkPool = new Map<string, { sdk: ZaloAdsSdk; zpsid: string }>();\n private readonly maxAccountsInMemory: number;\n private readonly sessionTtlMs?: number;\n private readonly resolveCredentialsFn?: ZaloAdsIntegrationManagerOptions[\"resolveCredentials\"];\n private readonly onSessionRefreshedFn?: ZaloAdsIntegrationManagerOptions[\"onSessionRefreshed\"];\n private readonly fetchImpl?: typeof fetch;\n private readonly baseUrls?: ZaloAdsSdkOptions[\"baseUrls\"];\n\n public constructor(options: ZaloAdsIntegrationManagerOptions = {}) {\n this.maxAccountsInMemory = options.maxAccountsInMemory ?? 500;\n this.sessionTtlMs = options.sessionTtlMs;\n this.resolveCredentialsFn = options.resolveCredentials;\n this.onSessionRefreshedFn = options.onSessionRefreshed;\n this.fetchImpl = options.fetch;\n this.baseUrls = options.baseUrls;\n\n if (options.sessionStore) {\n this.sessionStore = options.sessionStore;\n } else if (options.redis) {\n this.sessionStore = new TieredZaloSessionStore(options.redis, {\n maxAccounts: this.maxAccountsInMemory,\n keyPrefix: options.redisKeyPrefix,\n l1MaxTtlSeconds: options.l1MaxTtlSeconds,\n defaultTtlSeconds: options.sessionTtlMs ? Math.floor(options.sessionTtlMs / 1000) : undefined,\n });\n } else {\n this.sessionStore = new MemoryZaloSessionStore({\n maxAccounts: this.maxAccountsInMemory,\n });\n }\n }\n\n /**\n * Lấy hoặc khởi tạo instance `ZaloAdsSdk` gắn với một `integrationId` và `zpsid` cụ thể.\n * Instance được giữ trong LRU Pool và tự động dùng chung `sessionStore` (RAM / Redis).\n */\n public getClient(request: ZaloAdsClientRequest): ZaloAdsSdk {\n const { integrationId } = request;\n const parsed = parseZaloCookieInput(request.zpsid);\n const cleanZpsid = parsed.zpsid;\n\n const existing = this.sdkPool.get(integrationId);\n if (existing) {\n // Cập nhật thứ tự LRU\n this.sdkPool.delete(integrationId);\n if (existing.zpsid !== cleanZpsid) {\n existing.sdk.setZpsid(request.zpsid);\n existing.zpsid = cleanZpsid;\n }\n if (request.accountScope) {\n existing.sdk.setAccountScope(request.accountScope);\n }\n this.sdkPool.set(integrationId, existing);\n return existing.sdk;\n }\n\n if (this.sdkPool.size >= this.maxAccountsInMemory) {\n const oldestKey = this.sdkPool.keys().next().value;\n if (oldestKey !== undefined) {\n this.sdkPool.delete(oldestKey);\n }\n }\n\n const extraCookies: Record<string, string> = {\n ...parsed.extractedCookies,\n ...(request.extraCookies ?? {}),\n ...(request.zoawSek ? { zoaw_sek: request.zoawSek } : {}),\n };\n if (request.accountScope?.memberId && String(request.accountScope.memberId) !== \"0\") {\n extraCookies.ads_user_id = String(request.accountScope.memberId);\n }\n\n const sdk = new ZaloAdsSdk({\n integrationId,\n zpsid: cleanZpsid,\n accountScope: request.accountScope,\n sessionStore: this.sessionStore,\n fetch: this.fetchImpl,\n baseUrls: this.baseUrls,\n ssoAuth: {\n integrationId,\n zpsid: cleanZpsid,\n accountScope: request.accountScope,\n extraCookies,\n sessionStore: this.sessionStore,\n sessionTtlMs: this.sessionTtlMs,\n onSessionRefreshed: this.onSessionRefreshedFn\n ? (domain, session) => this.onSessionRefreshedFn!(integrationId, domain, session)\n : undefined,\n },\n });\n\n this.sdkPool.set(integrationId, { sdk, zpsid: cleanZpsid });\n return sdk;\n }\n\n /**\n * Lấy `ZaloAdsSdk` theo `integrationId`.\n * - Nếu truyền `credentialsOverride`, dùng luôn credential đó.\n * - Nếu không truyền và đã cấu hình `resolveCredentials` (đọc từ DB/Vault của Backend), tự động gọi `resolveCredentials(integrationId)`.\n * - Nếu instance đã có sẵn trong Pool RAM, trả về instance đó.\n */\n public async forIntegration(\n integrationId: string,\n credentialsOverride?: ZaloIntegrationCredentials | string\n ): Promise<ZaloAdsSdk> {\n if (credentialsOverride) {\n const normalized: ZaloIntegrationCredentials =\n typeof credentialsOverride === \"string\"\n ? { zpsid: credentialsOverride }\n : credentialsOverride;\n return this.getClient({ integrationId, ...normalized });\n }\n\n if (this.resolveCredentialsFn) {\n const resolved = await this.resolveCredentialsFn(integrationId);\n const normalized: ZaloIntegrationCredentials =\n typeof resolved === \"string\" ? { zpsid: resolved } : resolved;\n return this.getClient({ integrationId, ...normalized });\n }\n\n const cached = this.sdkPool.get(integrationId);\n if (cached) {\n this.sdkPool.delete(integrationId);\n this.sdkPool.set(integrationId, cached);\n return cached.sdk;\n }\n\n throw new Error(\n `ZaloAdsIntegrationManager: Cannot resolve credentials for integration \"${integrationId}\". Pass credentials or configure \\`resolveCredentials\\` option.`\n );\n }\n\n /**\n * Lấy `ZaloAdsSdk` nhanh chỉ bằng `zpsid` (tự động trích xuất `accountKey` duy nhất từ `zpsid`, ví dụ `zalo_330114198_...`).\n */\n public forZpsid(zpsidOrCookie: string, extraCookies?: Record<string, string>): ZaloAdsSdk {\n const parsed = parseZaloCookieInput(zpsidOrCookie);\n const accountKey = deriveAccountKeyFromZpsid(parsed.zpsid);\n return this.getClient({\n integrationId: accountKey,\n zpsid: zpsidOrCookie,\n extraCookies,\n });\n }\n\n /**\n * Xóa sạch cache phiên (trên cả L1 RAM và L2 Redis) của một `integrationId`.\n * Dùng khi người dùng ngắt kết nối hoặc cập nhật lại thông tin xác thực của Integration.\n */\n public async invalidateIntegration(\n integrationId: string,\n domain?: ZaloAuthDomain\n ): Promise<void> {\n const existing = this.sdkPool.get(integrationId);\n if (existing?.sdk.authManager) {\n if (domain) {\n await existing.sdk.authManager.invalidateDomainAsync(domain);\n } else {\n await existing.sdk.authManager.clearSessionsAsync();\n }\n return;\n }\n await this.sessionStore.delete(integrationId, domain);\n }\n\n /**\n * Xóa hẳn `integrationId` khỏi Pool trong RAM và xóa toàn bộ phiên trên RAM/Redis.\n */\n public async removeIntegration(integrationId: string): Promise<void> {\n await this.invalidateIntegration(integrationId);\n this.sdkPool.delete(integrationId);\n }\n\n /**\n * Kiểm tra kết nối (Test Connection / Auth Connect Flow) cho một tài khoản Zalo Ads:\n * - Tự động chạy Silent OAuth2 PKCE Handshake trên `ads.zalo.me`, `page.ads.zalo.me`, `form.ads.zalo.me`.\n * - Trả về thông tin tài khoản quảng cáo (`adsProfile`), danh sách OA (`officialAccounts`), và `formProfile`.\n * - Lưu sẵn toàn bộ phiên vào RAM/Redis để các lệnh gọi API tiếp theo đạt tốc độ tức thì (0ms handshake).\n */\n public async verifyIntegration(params: {\n integrationId?: string;\n zpsid: string;\n zoawSek?: string;\n extraCookies?: Record<string, string>;\n accountScope?: ZaloAccountScope;\n }): Promise<ZaloIntegrationVerificationResult> {\n const parsed = parseZaloCookieInput(params.zpsid);\n const accountKey = params.integrationId ?? deriveAccountKeyFromZpsid(parsed.zpsid);\n const sdk = this.getClient({\n integrationId: accountKey,\n zpsid: params.zpsid,\n zoawSek: params.zoawSek,\n extraCookies: params.extraCookies,\n accountScope: params.accountScope,\n });\n\n const sessions = await sdk.authenticateAll([\n \"ads.zalo.me\",\n \"page.ads.zalo.me\",\n \"form.ads.zalo.me\",\n ]);\n\n const oasResponse = await sdk.instantPages\n .listOfficialAccounts()\n .catch(() => ({ data: [] as ZaloInstantPagesOfficialAccountItem[] }));\n\n return {\n accountKey,\n adsProfile: sessions[\"ads.zalo.me\"]?.adsProfile,\n officialAccounts: Array.isArray(oasResponse?.data) ? oasResponse.data : [],\n formProfile: sessions[\"form.ads.zalo.me\"]?.formProfile,\n sessions,\n };\n }\n\n /**\n * Số lượng instance SDK đang giữ trong Pool RAM.\n */\n public get poolSize(): number {\n return this.sdkPool.size;\n }\n}\n\nexport { ZaloAdsIntegrationManager as ZaloAdsAccountPool };\n","/** DTOs for Zalo Instant Pages. Request fields are flattened; services route them automatically. */\r\nimport type { FileInput } from \"../types\";\r\n\r\n/**\r\n * Mã trạng thái kỹ thuật & nghiệp vụ của Instant Page:\r\n * - 0: Bản sao mới tạo (Clone Draft) - vừa nhân bản từ template hoặc trang khác, chưa từng sửa và chưa xuất bản (máy chủ lọc bỏ khỏi danh sách tìm kiếm)\r\n * - 1: Đang hoạt động / Đã xuất bản (Active / Published) - trang chính thức, nội dung live nằm trong trường content, máy chủ cấp timestamp published\r\n * - 2: Mã trạng thái trung gian cũ trên giao diện\r\n * - 3: Lưu trữ / Đã kết thúc (Archived / Ended) - trang đã ngưng hoạt động hoặc kết thúc chiến dịch\r\n */\r\nexport type ZaloInstantPageStatus = 0 | 1 | 2 | 3;\r\n\r\n/**\r\n * Cờ trạng thái hoạt động của Instant Page:\r\n * - 0: Tắt (tạm khóa, không cho người dùng truy cập)\r\n * - 1: Bật (cho phép xem trang qua https://page.zalo.me/p/{publicId})\r\n * Bắt buộc kiểu số nguyên 0 | 1, không truyền boolean true/false.\r\n */\r\nexport type ZaloInstantPageActive = 0 | 1;\r\n\r\n/**\r\n * Danh mục mã định danh các loại khối giao diện (Block Types) trong Instant Page Canvas (trường draft và content):\r\n */\r\n/** Cấu trúc đối tượng hình ảnh lưu trữ trên CDN Zalo Ads (adtima-media.zascdn.me). */\nexport interface ZaloMediaImage {\n name: string;\n url: string;\n mediaId?: number;\n}\n\n/** Cấu trúc JSON Canvas chuẩn của một Instant Page trên Zalo Ads (page.ads.zalo.me). */\n/** Khối 1: Trình chiếu ảnh / Video xoay vòng (Carousel Slider) */\nexport interface InstantPageCarouselBlock {\n id?: string;\n type: 1 | ZaloInstantPageBlockType.CAROUSEL_SLIDER;\n indexes: string[];\n images: Record<string, ZaloMediaImage>;\n videos?: Record<string, { url: string; name?: string; thumbnail?: string }>;\n textEditor?: {\n delta?: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n outputHtml?: string;\n };\n [key: string]: unknown;\n}\n\n/** Khối 2: Đồng hồ đếm ngược Flash sale / Thời gian ưu đãi */\nexport interface InstantPageCountdownBlock {\n id?: string;\n type: 2 | ZaloInstantPageBlockType.COUNTDOWN;\n discountValue?: number;\n countdownType?: number;\n startDate?: number;\n loopDays?: number;\n label?: string;\n labelDelta?: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n visibility?: {\n days?: boolean;\n hours?: boolean;\n minutes?: boolean;\n seconds?: boolean;\n };\n marginTop?: number;\n marginBottom?: number;\n visible?: boolean;\n [key: string]: unknown;\n}\n\n/** Khối 4: Văn bản mô tả định dạng giàu (Rich Text / Quill Delta) */\nexport interface InstantPageRichTextBlock {\n id?: string;\n type: 4 | ZaloInstantPageBlockType.RICH_TEXT;\n delta?: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n outputHtml?: string;\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 6: Hình ảnh đơn hoặc Video minh họa sản phẩm (Hero Media) */\nexport interface InstantPageHeroMediaBlock {\n id?: string;\n type: 6 | ZaloInstantPageBlockType.HERO_IMAGE;\n mediaType?: \"image\" | \"video\";\n image?: ZaloMediaImage;\n videoSetting?: {\n autoPlay?: boolean;\n loop?: boolean;\n };\n [key: string]: unknown;\n}\n\n/** Khối 7: Form nhập Họ và tên khách hàng */\nexport interface InstantPageFormNameBlock {\n id?: string;\n type: 7 | ZaloInstantPageBlockType.FORM_NAME;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value?: string;\n placeHolder?: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 8: Nút CTA đặt hàng cố định chân trang hoặc mở form popup */\nexport interface InstantPageStickyButtonBlock {\n id?: string;\n type: 8 | ZaloInstantPageBlockType.ORDER_CTA_BUTTON;\n content2: string;\n background?: string;\n borderColor?: string;\n borderRadius?: number;\n borderSize?: number;\n showBorder?: boolean;\n formPopup?: boolean;\n fixedPosition?: boolean;\n image?: ZaloMediaImage;\n [key: string]: unknown;\n}\n\n/** Khối 9: Form nhập Số điện thoại liên hệ */\nexport interface InstantPageFormPhoneBlock {\n id?: string;\n type: 9 | ZaloInstantPageBlockType.FORM_PHONE;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value?: string;\n placeHolder?: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 10: Form nhập Địa chỉ giao hàng */\nexport interface InstantPageFormAddressBlock {\n id?: string;\n type: 10 | ZaloInstantPageBlockType.FORM_ADDRESS;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value?: string;\n placeHolder?: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 14: Chân trang thương hiệu (Địa chỉ, Hotline, Email, Website) */\nexport interface InstantPageFooterBlock {\n id?: string;\n type: 14 | ZaloInstantPageBlockType.FOOTER;\n backgroundColor?: string;\n textDelta?: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n textHtml?: string;\n detailings?: Array<{\n image?: ZaloMediaImage;\n textDelta?: { ops: Array<{ insert: string }> };\n textHtml?: string;\n }>;\n [key: string]: unknown;\n}\n\n/** Khối 16: Form chọn Số lượng mua */\nexport interface InstantPageQuantityBlock {\n id?: string;\n type: 16 | ZaloInstantPageBlockType.FORM_QUANTITY;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value?: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 18: Phân loại / Biến thể sản phẩm (Màu sắc, Size, Combo) */\nexport interface InstantPageProductVariantBlock {\n id?: string;\n type: 18 | ZaloInstantPageBlockType.PRODUCT_VARIANT;\n visible?: boolean;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 19: Tiêu đề sản phẩm & Giá bán */\nexport interface InstantPageProductTitlePriceBlock {\n id?: string;\n type: 19 | ZaloInstantPageBlockType.PRODUCT_TITLE_PRICE;\n name: string;\n price: number;\n rawPrice?: number;\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 20: Danh sách câu hỏi gợi ý nhanh (FAQ pills) */\nexport interface InstantPageQuickQuestionsBlock {\n id?: string;\n type: 20 | ZaloInstantPageBlockType.QUICK_QUESTIONS;\n list: string[];\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 21: Nút / Khung gửi tin nhắn trực tiếp đến Zalo OA */\nexport interface InstantPageDefaultMessageBlock {\n id?: string;\n type: 21 | ZaloInstantPageBlockType.MESSAGE_CTA_BUTTON;\n content: string;\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 23: Nút gọi Hotline liên hệ nhanh */\nexport interface InstantPageCallHotlineBlock {\n id?: string;\n type: 23 | ZaloInstantPageBlockType.CALL_HOTLINE_BUTTON;\n content: string;\n phone: string;\n actionType?: string;\n background?: string;\n color?: string;\n borderColor?: string;\n borderRadius?: number;\n borderSize?: number;\n showBorder?: boolean;\n fixedPosition?: boolean;\n visible?: boolean;\n image?: ZaloMediaImage;\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 25: Bảng thông số kỹ thuật 2 cột (Key-Value) */\nexport interface InstantPageKeyValueTableBlock {\n id?: string;\n type: 25 | ZaloInstantPageBlockType.KEY_VALUE_TABLE;\n rows: Array<{ id: number; left: string; right: string }>;\n [key: string]: unknown;\n}\n\n/** Khối 27: Điều khoản đồng thuận thu thập dữ liệu cá nhân (NĐ 13) */\nexport interface InstantPageConsentNoticeBlock {\n id?: string;\n type: 27 | ZaloInstantPageBlockType.CONSENT_NOTICE;\n useCustomConsent?: boolean;\n [key: string]: unknown;\n}\n\n/** Khối 28: Thông tin Mini Shop TMĐT (Logo & Tên Shop) */\nexport interface InstantPageShopInfoBlock {\n id?: string;\n type: 28 | ZaloInstantPageBlockType.SHOP_INFO;\n name: string;\n image: ZaloMediaImage;\n [key: string]: unknown;\n}\n\n/** Khối 29: Mô tả giới thiệu sản phẩm TMĐT */\nexport interface InstantPageShopDescriptionBlock {\n id?: string;\n type: 29 | ZaloInstantPageBlockType.SHOP_DESCRIPTION;\n delta: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n outputHtml: string;\n length: number;\n [key: string]: unknown;\n}\n\n/** Discriminated Union cho toàn bộ 19 loại Block giao diện trên Zalo Instant Page */\nexport type InstantPageBlock =\n | InstantPageCarouselBlock\n | InstantPageCountdownBlock\n | InstantPageRichTextBlock\n | InstantPageHeroMediaBlock\n | InstantPageFormNameBlock\n | InstantPageStickyButtonBlock\n | InstantPageFormPhoneBlock\n | InstantPageFormAddressBlock\n | InstantPageFooterBlock\n | InstantPageQuantityBlock\n | InstantPageProductVariantBlock\n | InstantPageProductTitlePriceBlock\n | InstantPageQuickQuestionsBlock\n | InstantPageDefaultMessageBlock\n | InstantPageCallHotlineBlock\n | InstantPageKeyValueTableBlock\n | InstantPageConsentNoticeBlock\n | InstantPageShopInfoBlock\n | InstantPageShopDescriptionBlock;\n\n/** Cấu trúc JSON Canvas chuẩn của một Instant Page trên Zalo Ads (page.ads.zalo.me). */\nexport interface InstantPageCanvas<TBlock = InstantPageBlock> {\n /** Phiên bản schema của canvas (thường là 1 hoặc '1') */\n version: string | number;\n /** Danh sách ID các khối giao diện theo thứ tự hiển thị */\n renderList: string[];\n /** Bảng tra cứu dữ liệu chi tiết của từng khối giao diện, index bằng ID khối */\n data: Record<string, TBlock>;\n /** Số khối ghim cố định ở đầu trang */\n freezedTop?: number;\n /** Số khối ghim cố định ở cuối chân trang (ví dụ: nút đặt hàng hoặc khung chat) */\n freezedBottom?: number;\n /** Tiêu đề hiển thị trên thanh header mobile */\n pageTitle?: string;\n}\n\nexport enum ZaloInstantPageBlockType {\r\n /** Slide ảnh/video banner trình chiếu sản phẩm */\r\n CAROUSEL_SLIDER = 1,\r\n /** Đồng hồ đếm ngược Flash sale / thời gian khuyến mãi */\r\n COUNTDOWN = 2,\r\n /** Văn bản mô tả giàu định dạng (HTML / Quill Delta ops) */\r\n RICH_TEXT = 4,\r\n /** Hình ảnh đơn / banner minh họa (Hero image) */\r\n HERO_IMAGE = 6,\r\n /** Form field: Ô nhập họ và tên khách hàng */\r\n FORM_NAME = 7,\r\n /** Nút CTA Đặt hàng ngay (cố định chân trang hoặc mở form popup) */\r\n ORDER_CTA_BUTTON = 8,\r\n /** Form field: Ô nhập số điện thoại */\r\n FORM_PHONE = 9,\r\n /** Form field: Ô nhập địa chỉ giao hàng */\r\n FORM_ADDRESS = 10,\r\n /** Chân trang thương hiệu (Hotline, Email, Website, Địa chỉ) */\r\n FOOTER = 14,\r\n /** Form field: Ô chọn số lượng sản phẩm mua */\r\n FORM_QUANTITY = 16,\r\n /** Phân loại / Biến thể sản phẩm (Màu sắc, Size, Combo) */\r\n PRODUCT_VARIANT = 18,\r\n /** Tiêu đề sản phẩm & Giá bán (name, rawPrice, price) */\r\n PRODUCT_TITLE_PRICE = 19,\r\n /** Câu hỏi gợi ý nhanh (FAQ quick replies) */\r\n QUICK_QUESTIONS = 20,\r\n /** Nút CTA nhắn tin trực tiếp đến Zalo Official Account */\r\n MESSAGE_CTA_BUTTON = 21,\r\n /** Tiêu đề phân đoạn (Section Heading) */\r\n SECTION_HEADING = 22,\r\n /** Nút Hotline gọi điện thoại tư vấn viên */\r\n CALL_HOTLINE_BUTTON = 23,\r\n /** Bảng thông số / Ưu đãi 2 cột (Key-Value rows) */\r\n KEY_VALUE_TABLE = 25,\r\n /** Điều khoản đồng thuận thu thập dữ liệu cá nhân theo NĐ 13 */\r\n CONSENT_NOTICE = 27,\n /** Đầu trang TMĐT: Logo & Tên Mini Shop (Template 5) */\n SHOP_INFO = 28,\n /** Đoạn giới thiệu mô tả sản phẩm TMĐT (Template 5) */\n SHOP_DESCRIPTION = 29,\r\n}\r\n\r\n/** Sao chép một Instant Page hiện có và trả về bản Instant Page mới cùng toàn bộ draft được sao chép. Đây là mutation tool thuộc lane zalo-ads-content; dùng khi cần tạo bản làm việc độc lập trước khi chỉnh sửa nội dung hoặc trạng thái. Bản sao có id và publicId mới, không ghi đè Instant Page nguồn. */\r\nexport type ZaloInstantPagesCloneInstantPageRequest = {\r\n /** ID Instant Page nguồn cần sao chép. */\r\n instantPageId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesCloneInstantPageResponse = {\r\n /** Instant Page mới được tạo từ bản sao. */\r\n data: {\r\n /** ID nội bộ mới của Instant Page bản sao; dùng để đọc, cập nhật hoặc clone tiếp. */\r\n id: number;\r\n /** Mã chế độ của Instant Page. */\r\n mode: number;\r\n /** Tên bản sao, thường có tiền tố 'Sao chép từ'. */\r\n name: string;\r\n /** ID Official Account liên kết; có thể rỗng. */\r\n oaId: string;\r\n /** Chuỗi JSON cấu hình bản nháp đã được sao chép, gồm data các block/section, renderList và các thiết lập layout. Đây chưa tự đại diện cho nội dung public đã phát hành. */\r\n draft: string;\r\n /** Cờ bật/tắt của Instant Page: 0 = Tắt, 1 = Bật. */\r\n active: ZaloInstantPageActive;\r\n /** ID form liên kết; có thể rỗng. */\r\n formId: string;\r\n /** Mã trạng thái Instant Page: 0 = Bản sao mới tạo, 1 = Bản nháp, 2 = Đã xuất bản, 3 = Lưu trữ. */\r\n status: ZaloInstantPageStatus | number;\r\n /** ID người dùng sở hữu Instant Page. */\r\n userId: number;\r\n /** Nội dung đã phát hành/được lưu ngoài draft; có thể rỗng. */\r\n content: string;\r\n /** Thời điểm tạo bản sao, Unix timestamp tính bằng giây. */\r\n created: number;\r\n /** Phiên bản dữ liệu Instant Page. */\r\n version: number;\r\n /** Thời điểm cập nhật gần nhất, Unix timestamp tính bằng giây. */\r\n modified: number;\r\n /** ID công khai mới dùng cho URL preview/phát hành. */\r\n publicId: string;\r\n /** ID người tạo bản sao. */\r\n createdBy: number;\r\n /** Thời điểm phát hành, Unix timestamp tính bằng giây; 0 khi chưa phát hành. */\r\n published: number;\r\n /** ID template nguồn của Instant Page. */\r\n templateId: number;\r\n};\r\n};\r\n\r\n/** Lấy chi tiết Instant Page theo ID, gồm cấu hình đang dùng, bản nháp, template và trạng thái phát hành. Đây là detail tool thuộc lane zalo-ads-content; dùng khi đã có Instant Page ID và cần xem hoặc so sánh content với draft trước khi chỉnh sửa. */\r\nexport type ZaloInstantPagesGetInstantPageDetailRequest = {\r\n /** ID nội bộ Instant Page cần xem chi tiết. */\r\n instantPageId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesGetInstantPageDetailResponse = {\r\n data: {\r\n /** ID nội bộ Instant Page. */\r\n id: number;\r\n /** Chế độ vận hành page. */\r\n mode: number;\r\n /** Tên Instant Page. */\r\n name: string;\r\n /** ID Official Account liên kết, khi có. */\r\n oaId: string;\r\n /** Bản nháp cấu hình Instant Page chưa được phát hành hoặc chưa áp dụng làm nội dung chính; dạng chuỗi JSON/serialized payload. Dùng để so sánh hoặc tiếp tục chỉnh sửa, không tự xem là bản public. */\r\n draft: string;\r\n /** Trạng thái kích hoạt: 0 = Tắt, 1 = Bật. */\r\n active: ZaloInstantPageActive;\r\n /** ID form liên kết, khi có. */\r\n formId: string;\r\n /** Trạng thái nghiệp vụ: 0 = Bản sao mới tạo, 1 = Bản nháp, 2 = Đã xuất bản, 3 = Lưu trữ. */\r\n status: ZaloInstantPageStatus | number;\r\n /** ID người dùng sở hữu page. */\r\n userId: number;\r\n /** Nội dung/cấu hình Instant Page đang được lưu, dạng chuỗi JSON hoặc serialized payload. */\r\n content: string;\r\n /** Thời điểm tạo, Unix timestamp theo giây. */\r\n created: number;\r\n /** Phiên bản cấu hình page. */\r\n version: number;\r\n /** Thời điểm chỉnh sửa cuối, Unix timestamp theo giây. */\r\n modified: number;\r\n /** ID công khai dùng cho preview hoặc truy cập page. */\r\n publicId: string;\r\n /** ID người tạo page. */\r\n createdBy: number;\r\n /** Thời điểm phát hành, Unix timestamp theo giây. */\r\n published: number;\r\n /** ID template dùng để khởi tạo page. */\r\n templateId: number;\r\n};\r\n};\r\n\r\n/** Lấy thông tin quyền chi tiết của một người dùng được chia sẻ trên Instant Page, gồm quyền Official Account và các cờ khả năng sử dụng tính năng. Đây là detail tool thuộc lane zalo-ads-content; dùng sau khi có userId từ danh sách chia sẻ để kiểm tra điều kiện quyền của đúng người dùng. Khác với tool danh sách shares, kết quả này trả extraFlags của một người cụ thể. */\r\nexport type ZaloInstantPagesGetInstantPageSharedUserRequest = {\r\n /** ID Instant Page có người dùng được chia sẻ quyền. */\r\n instantPageId: number;\r\n /** ID người dùng cần lấy quyền chi tiết; lấy từ data[].userId của ZaloAds_listInstantPageShares. */\r\n userId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesGetInstantPageSharedUserResponse = {\r\n data: {\r\n /** Tên hiển thị của người dùng. */\r\n name: string;\r\n extraFlags: {\r\n /** Người dùng có được phép sử dụng template quảng cáo mua sắm hay không. */\r\n canUseShoppingAdTemplate: boolean;\r\n};\r\n /** Mã quyền của người dùng trên Official Account liên kết; ý nghĩa chi tiết phụ thuộc quy ước Zalo Ads. */\r\n oaPermission: number;\r\n};\r\n};\r\n\r\n/** Lấy lịch sử chỉnh sửa của một Instant Page theo từng trang dữ liệu. Đây là detail tool thuộc lane zalo-ads-content; dùng khi đã có instantPageId và cần kiểm tra các thay đổi trước đó, với limit và offset để duyệt danh sách. */\r\nexport type ZaloInstantPagesListInstantPageEditHistoryRequest = {\r\n /** ID nội bộ Instant Page cần xem lịch sử chỉnh sửa. */\r\n instantPageId: number;\r\n /** Số bản ghi lịch sử tối đa trong một trang; giá trị quan sát được là 10. */\r\n limit?: number;\r\n /** Vị trí bắt đầu của trang lịch sử, tính từ 0. */\r\n offset?: number;\r\n};\r\n\r\nexport type ZaloInstantPagesListInstantPageEditHistoryResponse = {\r\n /** Trang dữ liệu lịch sử chỉnh sửa. */\r\n data: {\r\n /** Các bản ghi chỉnh sửa trong trang hiện tại. */\r\n items: Array<{\r\n /** Mã loại thao tác lịch sử. API quan sát trả về 1; ý nghĩa các mã khác chưa được xác minh. */\r\n action: number;\r\n /** ID Instant Page được chỉnh sửa. */\r\n pageId: number;\r\n /** ID người dùng thực hiện thao tác. */\r\n userId: number;\r\n /** Thời điểm tạo bản ghi, Unix timestamp theo giây. */\r\n created: number;\r\n /** Tên hiển thị của người dùng thực hiện thao tác. */\r\n userName: string;\r\n }>;\r\n metadata: {\r\n /** Giới hạn bản ghi của trang đã trả về. */\r\n limit: number;\r\n /** Tổng số bản ghi lịch sử. */\r\n total: number;\r\n /** Vị trí bắt đầu của trang đã trả về. */\r\n offset: number;\r\n };\r\n };\r\n};\r\n\r\n/** Lấy danh sách bản ghi gửi form của một Instant Page. Đây là detail tool thuộc lane zalo-ads-content; dùng khi cần xem dữ liệu khách hàng đã gửi từ form gắn với trang cụ thể. */\r\nexport type ZaloInstantPagesListInstantPageFormRecordsRequest = {\r\n /** ID Instant Page có form cần lấy bản ghi gửi. */\r\n instantPageId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesFormRecordItem = {\r\n id: string;\r\n pageId: number;\r\n userId?: string;\r\n userName?: string;\r\n phone?: string;\r\n created: number;\r\n answers: Array<{\r\n questionId: string;\r\n title: string;\r\n value: string;\r\n }>;\r\n};\r\n\r\nexport type ZaloInstantPagesListInstantPageFormRecordsResponse =\r\n | Blob\r\n | {\r\n data: {\r\n items: Array<ZaloInstantPagesFormRecordItem>;\r\n total: number;\r\n };\r\n };\r\n\r\n/** Lấy danh sách người dùng được chia sẻ quyền truy cập một Instant Page, gồm quyền trên trang và quyền Official Account. Đây là detail tool thuộc lane zalo-ads-content; dùng để kiểm tra quyền cộng tác trước khi chia sẻ, chỉnh sửa hoặc thu hồi quyền. Mỗi phần tử xác định người dùng bằng userId và thông tin hiển thị. */\r\nexport type ZaloInstantPagesListInstantPageSharesRequest = {\r\n /** ID Instant Page cần xem người dùng được chia sẻ quyền. */\r\n instantPageId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesListInstantPageSharesResponse = {\r\n /** Danh sách người dùng được chia sẻ quyền trên Instant Page. */\r\n data: Array<{\r\n /** Tên hiển thị của người dùng. */\r\n name: string;\r\n /** Tên tệp hoặc URL ảnh đại diện của người dùng. */\r\n avatar: string;\r\n /** ID người dùng được chia sẻ quyền. */\r\n userId: number;\r\n /** Mã quyền của người dùng trên Instant Page; ý nghĩa chi tiết phụ thuộc quy ước phân quyền Zalo Ads. */\r\n permission: number;\r\n /** Mã quyền của người dùng trên Official Account liên kết; ý nghĩa chi tiết phụ thuộc quy ước Zalo Ads. */\r\n oaPermission: number;\r\n}>;\r\n};\r\n\r\n/**\r\n * Danh mục mã phân quyền người dùng được chia sẻ trên Instant Page (POST /api/instant-pages/{instantPageId}/shares):\r\n * - ADMIN (1): Quản trị viên (Toàn quyền quản trị, phân quyền thành viên, gắn quảng cáo, xuất bản trang).\r\n * - UPDATE_PAGE (2): Chỉnh sửa trang (Quyền chỉnh sửa nội dung giao diện trang).\r\n * - DOWNLOAD_INFO (3): Tải thông tin khách hàng (Quyền tải file lead/đơn hàng).\r\n * - READ_ONLY (4): Chỉ xem (Chỉ xem trước trang và báo cáo).\r\n */\r\nexport const ZaloInstantPageSharePermission = {\r\n /** Quản trị viên: Toàn quyền quản trị, chỉnh sửa, phân quyền và gắn quảng cáo. */\r\n ADMIN: 1,\r\n /** Biên tập viên: Quyền chỉnh sửa nội dung trang. */\r\n UPDATE_PAGE: 2,\r\n /** Tải dữ liệu: Quyền tải thông tin khách hàng / Leads. */\r\n DOWNLOAD_INFO: 3,\r\n /** Chỉ xem: Quyền xem trước và thống kê. */\r\n READ_ONLY: 4,\r\n} as const;\r\n\r\nexport type ZaloInstantPageSharePermissionValue = typeof ZaloInstantPageSharePermission[keyof typeof ZaloInstantPageSharePermission];\r\n\r\n/** Thông tin phân quyền cho một thành viên trên Instant Page. */\r\nexport type ZaloInstantPagesShareMemberDto = {\r\n /** ID người dùng được phân quyền (ví dụ: 2394323333639486). */\r\n userId: number;\r\n /** Mã phân quyền: 1 (ADMIN), 2 (UPDATE_PAGE), 3 (DOWNLOAD_INFO), 4 (READ_ONLY). */\r\n permission: ZaloInstantPageSharePermissionValue | number;\r\n};\r\n\r\n/** Cập nhật danh sách người dùng được phân quyền / chia sẻ trên Instant Page (`POST /api/instant-pages/{instantPageId}/shares`). */\r\nexport type ZaloInstantPagesUpdateInstantPageSharesRequest = {\r\n /** ID Instant Page cần phân quyền chia sẻ. */\r\n instantPageId: number;\r\n /** Danh sách thành viên và mã quyền tương ứng. Body HTTP là JSON Array: `[{ userId, permission }]`. */\r\n shares: Array<ZaloInstantPagesShareMemberDto>;\r\n};\r\n\r\nexport type ZaloInstantPagesUpdateInstantPageSharesResponse = {\r\n /** Danh sách thành viên được chia sẻ sau khi cập nhật. */\r\n data?: Array<{\r\n userId: number;\r\n permission: number;\r\n name?: string;\r\n avatar?: string;\r\n oaPermission?: number;\r\n }>;\r\n code?: number;\r\n msg?: string;\r\n};\r\n\r\n/** Lấy các danh sách người dùng có thể dùng trong Instant Page, gồm chủ sở hữu, người tạo và người được chia sẻ. Đây là entry tool thuộc lane zalo-ads-content; dùng để chọn hoặc đối chiếu người dùng trước khi lọc, chia sẻ hay kiểm tra quyền trên Instant Page cụ thể. Khác với tool shares của một trang, kết quả này là danh mục người dùng theo vai trò trên phạm vi Instant Page. */\r\nexport type ZaloInstantPagesListInstantPageUsersRequest = Record<string, never>;\r\n\r\nexport type ZaloInstantPagesListInstantPageUsersResponse = {\r\n data: {\r\n /** Danh sách chủ sở hữu Instant Page. */\r\n owners: Array<{\r\n /** ID người dùng. */\r\n id: number;\r\n /** Tên hiển thị người dùng; có thể là nhãn hệ thống khi chưa có người được chia sẻ. */\r\n name: string;\r\n}>;\r\n /** Danh sách người dùng được chia sẻ hoặc nhãn trạng thái chia sẻ. */\r\n shares: Array<{\r\n /** ID người dùng. */\r\n id: number;\r\n /** Tên hiển thị người dùng; có thể là nhãn hệ thống khi chưa có người được chia sẻ. */\r\n name: string;\r\n}>;\r\n /** Danh sách người tạo Instant Page. */\r\n creators: Array<{\r\n /** ID người dùng. */\r\n id: number;\r\n /** Tên hiển thị người dùng; có thể là nhãn hệ thống khi chưa có người được chia sẻ. */\r\n name: string;\r\n}>;\r\n};\r\n};\r\n\r\n/** Lấy danh sách template mini page, gồm tên, mô tả, thumbnail, preview và nội dung cấu hình. Đây là entry tool thuộc lane zalo-ads-content; dùng khi chọn template trước khi tạo hoặc cấu hình mini page. */\r\nexport type ZaloInstantPagesListMiniPageTemplatesRequest = Record<string, never>;\r\n\r\nexport type ZaloInstantPagesListMiniPageTemplatesResponse = {\r\n data: Array<{\r\n id: number;\r\n name: string;\r\n /** Nội dung cấu hình template dạng chuỗi. */\r\n content: string;\r\n preview: string;\r\n thumbnail: string;\r\n description: string;\r\n}>;\r\n};\r\n\r\n/** Lấy danh sách Instant Page mà tài khoản hiện tại có quyền truy cập, với bộ lọc tên, ID hoặc nhóm nội dung. Đây là entry tool thuộc lane zalo-ads-content; dùng để tìm instantPageId trước khi xem chi tiết, quản lý quyền, xem lịch sử hoặc cập nhật trạng thái. */\r\nexport type ZaloInstantPagesSearchInstantPagesRequest = {\r\n /** ID Instant Page cần tìm chính xác; bỏ qua để không lọc theo ID. */\r\n id?: number;\r\n /** Từ khóa tìm trong tên Instant Page; bỏ qua để không lọc tên. */\r\n name?: string;\r\n /** Nhóm nội dung: 1 là Trang sản phẩm, 2 là Kịch bản tin nhắn; bỏ qua để lấy tất cả. */\r\n group?: 1 | 2;\r\n};\r\n\r\nexport type ZaloInstantPagesSearchInstantPagesResponse = {\r\n data: Array<{\r\n /** ID nội bộ Instant Page; dùng cho các API chi tiết, cập nhật, quyền và lịch sử. */\r\n id: number;\r\n /** Tên Instant Page. */\r\n name: string;\r\n /** ID Official Account liên kết; có thể rỗng. */\r\n oaId: string;\r\n /** Tên hiển thị chủ sở hữu. */\r\n owner: string;\r\n /** Trạng thái bật/tắt: 0 = Tắt, 1 = Bật. */\r\n active: ZaloInstantPageActive;\r\n /** ID form liên kết; có thể rỗng. */\r\n formId: string;\r\n /** Tên các người dùng được chia sẻ quyền. */\r\n shares: Array<string>;\r\n /** Mã trạng thái: 0 = Bản sao mới tạo, 1 = Bản nháp, 2 = Đã xuất bản, 3 = Lưu trữ. */\r\n status: ZaloInstantPageStatus | number;\r\n /** Unix timestamp theo giây lúc tạo. */\r\n created: number;\r\n /** Tên hiển thị người tạo. */\r\n creator: string;\r\n /** ID chủ sở hữu. */\r\n ownerId: number;\r\n /** Unix timestamp theo giây lúc cập nhật. */\r\n modified: number;\r\n /** Mã công khai 12 ký tự của Instant Page (dùng trên https://page.zalo.me/p/{publicId}). */\r\n publicId: string;\r\n /** Unix timestamp theo giây lúc xuất bản (0 nếu chưa xuất bản). */\r\n published: number;\r\n /** Quyền trực tiếp trên Instant Page khi API trả về. */\r\n permission?: number;\r\n /** ID template tạo Page. */\r\n templateId: number;\r\n /** Quyền trên OA khi API trả về. */\r\n oaPermission?: number;\r\n [key: string]: unknown;\r\n}>;\r\n [key: string]: unknown;\r\n};\r\n\r\n/**\r\n * Cập nhật thông tin, cấu hình bản nháp (draft), nội dung chính thức (content) hoặc bật/tắt trạng thái (active) của Instant Page theo ID.\r\n *\r\n * Hỗ trợ 4 loại thao tác nghiệp vụ:\r\n * - **Loại 1 (Bật/Tắt nhanh)**: `{ id, active: 0 | 1 }` (0: Tắt, 1: Bật)\r\n * - **Loại 2 (Đổi tên / Đổi OA)**: `{ id, name?: string, oaId?: string }`\r\n * - **Loại 3 (Lưu bản nháp - Save Draft)**: `{ id, name?: string, status: 1, draft: string }`\r\n * - **Loại 4 (Xuất bản - Publish Live)**: `{ id, name?: string, status: 2, draft: string, content: string }`\r\n */\r\nexport type ZaloInstantPagesUpdateInstantPageRequest = {\r\n /** ID Instant Page cần cập nhật. */\r\n instantPageId: number;\r\n /** ID Instant Page trong payload; bắt buộc và phải trùng path_param.instantPageId. */\r\n id: number;\r\n /** Tên Instant Page mới; giao diện giới hạn tối đa 40 ký tự. Chỉ gửi khi cần đổi tên. */\r\n name?: string;\r\n /** ID Official Account liên kết; truyền chuỗi rỗng \"\" nếu trang chưa liên kết OA hoặc không dùng OA. */\r\n oaId?: string;\r\n /**\r\n * Chuỗi JSON bản nháp cấu hình Instant Page đang biên tập trên Canvas Editor (chưa xuất bản).\r\n * Gồm renderList (mảng ID thứ tự hiển thị), data (map ID -> block object), freezedTop, freezedBottom, version.\r\n * Danh mục block types:\r\n * 1: CAROUSEL_SLIDER | 2: COUNTDOWN | 4: RICH_TEXT | 6: HERO_IMAGE | 7: FORM_NAME |\r\n * 8: ORDER_CTA_BUTTON | 9: FORM_PHONE | 10: FORM_ADDRESS | 14: FOOTER | 16: FORM_QUANTITY |\r\n * 18: PRODUCT_VARIANT | 19: PRODUCT_TITLE_PRICE | 20: QUICK_QUESTIONS | 21: MESSAGE_CTA_BUTTON |\r\n * 22: SECTION_HEADING | 23: CALL_HOTLINE_BUTTON | 25: KEY_VALUE_TABLE | 27: CONSENT_NOTICE\r\n */\r\n draft?: string | InstantPageCanvas;\r\n /** Thao tác bật/tắt Instant Page: 0 là tắt, 1 là bật. BẮT BUỘC là số nguyên 0 | 1, không truyền kiểu boolean. */\r\n active?: ZaloInstantPageActive;\r\n /** Mã trạng thái của Instant Page: 1 = Lưu bản nháp (Draft), 2 = Xuất bản chính thức (Published). */\r\n status?: ZaloInstantPageStatus | number;\r\n /**\r\n * Chuỗi JSON cấu hình nội dung chính thức đang chạy ở Production của Instant Page (sau khi xuất bản).\r\n * Chỉ gửi khi xuất bản chính thức (status = 2). Cấu trúc tương tự draft.\r\n */\r\n content?: string | InstantPageCanvas;\r\n};\r\n\r\nexport type ZaloInstantPagesUpdateInstantPageResponse = {\r\n /** Thông điệp kết quả nếu API trả envelope có msg. */\r\n msg?: string;\r\n /** Mã kết quả nếu API trả envelope có code. */\r\n code?: number;\r\n /** Dữ liệu Instant Page hoặc kết quả cập nhật nếu API trả trong data. */\r\n data?: unknown;\r\n [key: string]: unknown;\r\n};\r\n\r\n/** Lấy thống kê tổng số lượt gửi form (totalSubmit) và thời gian gửi gần nhất (lastSubmitTime) theo danh sách các Instant Page ID (ids). */\r\nexport type ZaloInstantPagesListInstantPageLeadsRequest = {\r\n /** Danh sách ID của các trang Instant Page phân tách bằng dấu phẩy (ví dụ: \"81433,76292\"). */\r\n ids: string;\r\n};\r\n\r\nexport type ZaloInstantPagesListInstantPageLeadsResponse = {\r\n data: Array<{\r\n /** ID trang Instant Page. */\r\n id: number;\r\n /** Tổng số lượt khách hàng điền form trên trang Instant Page. */\r\n totalSubmit: number;\r\n /** Thời điểm điền form gần nhất (Unix timestamp theo giây, hoặc 0 nếu chưa có). */\r\n lastSubmitTime: number;\r\n [key: string]: unknown;\r\n }>;\r\n [key: string]: unknown;\r\n};\r\n\r\n/** Lấy danh sách Zalo Official Accounts (OA) khả dụng trên hệ thống Instant Pages (page.ads.zalo.me). */\r\nexport type ZaloInstantPagesListOfficialAccountsRequest = Record<string, never>;\r\n\r\nexport type ZaloInstantPagesOfficialAccountItem = {\r\n id: string;\r\n name: string;\r\n avatar: string;\r\n status: number;\r\n type: number;\r\n createdTime: number;\r\n config?: Record<string, unknown>;\r\n roles?: number[];\r\n [key: string]: unknown;\r\n};\r\n\r\nexport type ZaloInstantPagesListOfficialAccountsResponse = {\r\n data: ZaloInstantPagesOfficialAccountItem[];\r\n [key: string]: unknown;\r\n};\r\n\r\n/** Cấu hình hoặc cập nhật biểu mẫu thu thập thông tin và đặt hàng gắn liền với một Instant Page, bao gồm danh sách câu hỏi, lựa chọn trả lời và điều khoản bảo vệ dữ liệu cá nhân. Đây là mutation tool thuộc lane zalo-ads-content. Dùng khi đã có instantPageId cùng oaId và cần lưu cấu trúc câu hỏi biểu mẫu trước khi gắn ID câu hỏi vào block nội dung của Instant Page. */\r\nexport type ZaloInstantPagesUpsertInstantPageFormRequest = {\r\n /** ID nội bộ của Instant Page cần cấu hình biểu mẫu (lấy từ công cụ tìm kiếm, chi tiết hoặc sao chép Instant Page). */\r\n instantPageId: number;\r\n /** ID Zalo Official Account liên kết với biểu mẫu của Instant Page (chuỗi số định danh dài). */\r\n oaId: string;\r\n /** Tên biểu mẫu gắn với Instant Page (ví dụ: 'Trang sản phẩm - 14/10/2026 18:51'). */\r\n formName: string;\r\n /** Danh sách các câu hỏi và trường thông tin trong biểu mẫu của Instant Page. */\r\n questions: Array<{\r\n /** Mã định danh câu hỏi (tùy chọn khi cập nhật câu hỏi đã tồn tại). */\r\n id?: string;\r\n /** Loại câu hỏi: 1 là câu hỏi nhập liệu (số lượng, họ tên, số điện thoại, địa chỉ), 2 là câu hỏi lựa chọn phương án (phiên bản, kích thước, combo). */\r\n type: 1 | 2 | number;\r\n /** Tiêu đề câu hỏi hiển thị trên biểu mẫu. */\r\n title: string;\r\n /** Danh sách các phương án lựa chọn hoặc cấu hình ô nhập liệu của câu hỏi. */\r\n answers: Array<{\r\n /** Mã định danh phương án trả lời (tùy chọn khi cập nhật phương án đã tồn tại). */\r\n id?: string;\r\n /** Loại ô trả lời: 1 là lựa chọn cố định (option), 5 là số lượng, 7 là họ và tên, 13 là số điện thoại, 15 là địa chỉ. */\r\n type: 1 | 5 | 7 | 13 | 15 | number;\r\n /** Giá trị phương án trả lời (dùng cho câu hỏi lựa chọn type=2, để chuỗi rỗng với ô nhập liệu). */\r\n value?: string;\r\n /** Thứ tự ưu tiên của phương án trả lời (bắt đầu từ 0). */\r\n priority: number;\r\n /** Văn bản gợi ý trong ô nhập liệu (dùng cho họ tên, số điện thoại, địa chỉ). */\r\n placeHolder?: string;\r\n }>;\r\n /** Trạng thái vô hiệu hóa câu hỏi (false là đang kích hoạt). */\r\n disable: boolean;\r\n /** Thứ tự ưu tiên hiển thị của câu hỏi (bắt đầu từ 0). */\r\n priority: number;\r\n /** Bắt buộc người dùng trả lời câu hỏi này hay không. */\r\n isRequired: boolean;\r\n /** Mô tả phụ của câu hỏi (có thể để chuỗi rỗng). */\r\n description: string;\r\n }>;\r\n /** Sử dụng cấu hình điều khoản đồng ý tùy chỉnh hay mặc định (mặc định: false). */\r\n useCustomConsent?: boolean;\r\n /** Cấu hình thông tin pháp lý và phạm vi thu thập dữ liệu cá nhân của biểu mẫu (bắt buộc khi useCustomConsent = true). */\r\n consentConfig?: {\r\n /** Địa chỉ liên hệ của bên kiểm soát hoặc sở hữu dữ liệu. */\r\n address: string;\r\n /** Tên cá nhân hoặc đơn vị sở hữu dữ liệu. */\r\n ownerName: string;\r\n /** Email liên hệ của bên kiểm soát hoặc sở hữu dữ liệu. */\r\n ownerEmail: string;\r\n /** Số điện thoại liên hệ của bên sở hữu dữ liệu (ví dụ: '84977682707'). */\r\n ownerPhone: string;\r\n /** Danh sách mã loại dữ liệu cá nhân cơ bản thu thập (ví dụ: [0,1,2,3,4,5]). */\r\n regularDataTypes: Array<number>;\r\n /** Danh sách mã mục đích xử lý dữ liệu (ví dụ: [0,1,2,3]). */\r\n dataUsagePurposes: Array<number>;\r\n /** Danh sách mã loại dữ liệu cá nhân nhạy cảm thu thập (ví dụ: [0,1]). */\r\n sensitiveDataTypes: Array<number>;\r\n };\r\n};\r\n\r\nexport type ZaloInstantPagesUpsertInstantPageFormResponse = {\r\n /** Danh sách câu hỏi và phương án trả lời của biểu mẫu Instant Page sau khi đã lưu kèm mã định danh (id) do hệ thống sinh ra. */\r\n data: Array<{\r\n /** Mã định danh câu hỏi do hệ thống sinh ra (ví dụ: '6VUZYGPQ66KYVG796M'), dùng để gắn vào cấu hình block form của Instant Page. */\r\n id: string;\r\n /** Loại câu hỏi (1: nhập liệu, 2: lựa chọn). */\r\n type: number;\r\n /** Tiêu đề câu hỏi. */\r\n title: string;\r\n /** Danh sách phương án trả lời hoặc ô nhập liệu của câu hỏi. */\r\n answers: Array<{\r\n /** Mã định danh phương án trả lời do hệ thống sinh ra (ví dụ: 'ERUR9ZVA9ZAQ8RQEQ'). */\r\n id: string;\r\n /** Loại ô trả lời (1: lựa chọn, 5: số lượng, 7: họ tên, 13: số điện thoại, 15: địa chỉ). */\r\n type: number;\r\n /** Giá trị của phương án lựa chọn. */\r\n value?: string;\r\n /** Thứ tự hiển thị của phương án trả lời (bắt đầu từ 0). */\r\n priority: number;\r\n /** Văn bản gợi ý hiển thị trong ô nhập liệu. */\r\n placeHolder?: string;\r\n [key: string]: unknown;\r\n }>;\r\n /** Trạng thái vô hiệu hóa câu hỏi. */\r\n disable: boolean;\r\n /** Thứ tự hiển thị của câu hỏi trên biểu mẫu. */\r\n priority: number;\r\n /** Cờ bắt buộc trả lời câu hỏi. */\r\n isRequired: boolean;\r\n /** Mô tả phụ của câu hỏi. */\r\n description: string;\r\n [key: string]: unknown;\r\n }>;\r\n [key: string]: unknown;\r\n};\r\n\r\n/**\r\n * Khởi tạo một Instant Page mới từ Template mẫu trên domain page.ads.zalo.me.\r\n * \r\n * Bẫy kỹ thuật & nghiệp vụ:\r\n * - templateId = 4: Kịch bản giới thiệu thương hiệu / Tin nhắn (bắt buộc dùng cho Quảng cáo Tin nhắn Type 30).\r\n * - oaId: Bắt buộc là chuỗi ID 64-bit của Official Account (ví dụ: '4411301888544366414' từ GET /api/official-accounts), KHÔNG dùng ID số nguyên ngắn.\r\n * - Sau khi tạo, Instant Page ở trạng thái nháp (status: 0). Cần gọi updateInstantPage với status: 1 (truyền đồng thời cả draft và content) để xuất bản Live.\r\n */\r\nexport type ZaloInstantPagesCreateInstantPageRequest = {\r\n /** Mã mẫu giao diện: 1 (Trang bán sản phẩm form trực tiếp), 3 (Trang bán sản phẩm form popup), 4 (Kịch bản tin nhắn), 5 (Trang đệm mua sắm). */\r\n templateId: 1 | 3 | 4 | 5 | number;\r\n /** Mã định danh 64-bit của Official Account liên kết (Lấy từ GET /api/official-accounts). */\r\n oaId?: string;\r\n};\r\n\r\nexport type ZaloInstantPagesCreateInstantPageResponse = {\r\n /** Bản ghi Instant Page mới được khởi tạo từ template. */\r\n data: {\r\n /** Mã số định danh nội bộ của Instant Page mới được cấp phát. */\r\n id: number;\r\n /** Mã public dùng cho URL người dùng cuối (https://page.zalo.me/p/{publicId}). */\r\n publicId: string;\r\n /** Tên mặc định của Instant Page theo template. */\r\n name: string;\r\n /** Cờ hoạt động: 0 = Tắt, 1 = Bật. */\r\n active: ZaloInstantPageActive | number;\r\n /** Mã trạng thái: 0 = Nháp mới tạo, 1 = Đã xuất bản Live. */\r\n status: ZaloInstantPageStatus | number;\r\n /** Phiên bản cấu trúc trang. */\r\n version: number;\r\n /** Mã mẫu giao diện đã dùng để khởi tạo. */\r\n templateId: number;\r\n /** Mã định danh 64-bit của Official Account liên kết. */\r\n oaId?: string;\r\n [key: string]: unknown;\r\n };\r\n [key: string]: unknown;\r\n};\r\n","/**\n * Factory tiện ích khởi tạo cấu trúc Instant Page Canvas hợp lệ cho Zalo Ads.\n * Tự động nạp sẵn (hydrate) các giá trị mặc định chuẩn chỉnh (thương hiệu, logo, hình ảnh, văn bản Quill),\n * đảm bảo 100% trang đích khi tạo không bao giờ bị lỗi viền đỏ (data-section-error=\"true\")\n * hay lỗi crash React khi mở trên domain page.ads.zalo.me.\n */\nimport type { InstantPageCanvas, ZaloMediaImage } from \"../dtos/instant-pages.dto\";\n\nexport interface HydrateInstantPageOptions {\n /** Tên thương hiệu / Shop (từ 2 - 30 ký tự) */\n brandName?: string;\n /** URL ảnh logo thương hiệu (kích thước tối thiểu 150x150) */\n brandLogoUrl?: string;\n /** Tên sản phẩm / dịch vụ chính */\n productName?: string;\n /** Giá bán sản phẩm (VND) */\n price?: number;\n /** Giá niêm yết / giá gốc (VND) */\n rawPrice?: number;\n /** Đoạn mô tả giới thiệu chi tiết sản phẩm / dịch vụ */\n description?: string;\n /** Danh sách URL ảnh sản phẩm trình chiếu Carousel (tối thiểu 1 ảnh) */\n carouselImages?: Array<{ url: string; name?: string }>;\n /** Tin nhắn mẫu gửi tới Zalo Official Account */\n defaultMessage?: string;\n /** Số hotline liên hệ */\n hotline?: string;\n /** Địa chỉ doanh nghiệp */\n address?: string;\n}\n\nexport class InstantPageFactory {\n /**\n * Khởi tạo Canvas hoàn chỉnh từ Template ID (1, 3, 4, 5) được điền sẵn dữ liệu hợp lệ.\n */\n static createFromTemplate(\n templateId: 1 | 3 | 4 | 5 | number,\n options: HydrateInstantPageOptions = {}\n ): InstantPageCanvas {\n const brandName = options.brandName || \"RedAI Official Store\";\n const brandLogoUrl =\n options.brandLogoUrl ||\n \"https://adtima-media.zascdn.me/2023/10/58117541-e206-4f9d-b4cf-69e50f963288.svg\";\n const productName = options.productName || \"Sản phẩm / Dịch vụ Đột phá 2026\";\n const price = options.price ?? 299000;\n const rawPrice = options.rawPrice ?? 499000;\n const defaultMsg =\n options.defaultMessage ||\n \"Tôi muốn tìm hiểu thêm về sản phẩm này\";\n\n const defaultImages = [\n \"https://adtima-media.zascdn.me/2023/06/84cba4c9-be13-425a-8daa-40e695ca9805.jpg\",\n \"https://adtima-media.zascdn.me/2023/06/805587cd-4699-47e6-a9bb-3cbbb4039b40.jpg\",\n \"https://adtima-media.zascdn.me/2023/06/aca98d2c-1739-4f03-a366-43a6d6c4ef53.jpg\",\n \"https://adtima-media.zascdn.me/2023/06/8cc5692b-2899-4862-9957-d3f66e8778cd.jpg\",\n ];\n\n switch (templateId) {\n case 5: {\n // Template 5: Trang đệm mua sắm TMĐT (Shopping Ad Bridge)\n const carouselImgs =\n options.carouselImages && options.carouselImages.length > 0\n ? options.carouselImages\n : defaultImages.map((url, i) => ({ url, name: `image-${i + 1}.jpg` }));\n\n const indexes = carouselImgs.map((_, i) => String(i));\n const imagesMap: Record<string, ZaloMediaImage> = {};\n carouselImgs.forEach((img, i) => {\n imagesMap[String(i)] = {\n name: img.name || `image-${i + 1}.jpg`,\n url: img.url,\n };\n });\n\n const descText =\n options.description ||\n \"Hệ sinh thái công nghệ tự động hóa RedAI. Tích hợp đa kênh Zalo OA, Website & CRM; hỗ trợ tự động phản hồi và chốt đơn 24/7.\";\n\n return {\n version: 1,\n renderList: [\"1\", \"2\", \"3\", \"4\"],\n freezedBottom: 4,\n pageTitle: \"Chi tiết\",\n data: {\n \"1\": {\n id: \"-1\",\n type: 28,\n name: brandName,\n image: {\n name: \"logo.png\",\n url: brandLogoUrl,\n },\n },\n \"2\": {\n id: \"-1\",\n type: 29,\n delta: {\n ops: [\n { attributes: { bold: true, size: \"18px\" }, insert: `${brandName}\\n` },\n { insert: `\\n${descText}\\n` },\n ],\n },\n outputHtml: `<p><strong style=\"font-size: 18px;\">${brandName}</strong></p><p><br>${descText}</p>`,\n length: brandName.length + descText.length + 10,\n },\n \"3\": {\n id: \"-1\",\n type: 1,\n indexes,\n images: imagesMap,\n videos: {\n \"0\": { name: \"\", thumbnail: \"\", url: \"\" },\n },\n },\n \"4\": {\n id: \"-1\",\n type: 21,\n content: defaultMsg,\n marginTop: 0,\n marginBottom: 0,\n },\n },\n };\n }\n\n case 4: {\n // Template 4: Kịch bản giới thiệu thương hiệu / Tin nhắn\n return {\n version: 4,\n renderList: [\"1\", \"2\", \"3\"],\n freezedBottom: 3,\n data: {\n \"1\": {\n id: \"-1\",\n indexes: [\"0\", \"1\", \"2\"],\n images: {\n \"1\": { name: \"banner-1.jpg\", url: defaultImages[0] },\n \"2\": { name: \"banner-2.jpg\", url: defaultImages[1] },\n },\n textEditor: {\n delta: {\n ops: [\n { attributes: { bold: true }, insert: `Chào mừng bạn đến với ${brandName}` },\n { insert: \"\\n\\nBạn đang quan tâm giải pháp nào để chuyên viên hỗ trợ ngay?\\n\\n\" },\n ],\n },\n outputHtml: `<p><strong>Chào mừng bạn đến với ${brandName}</strong></p><p><br></p><p>Bạn đang quan tâm giải pháp nào để chuyên viên hỗ trợ ngay?</p>`,\n },\n type: 1,\n videos: {\n \"0\": { name: \"\", thumbnail: \"\", url: \"\" },\n },\n },\n \"2\": {\n rows: [{ id: 0, left: \"Ưu đãi trải nghiệm\", right: \"Dùng thử miễn phí\" }],\n type: 25,\n },\n \"3\": {\n list: [\n \"Tư vấn giải pháp tự động hóa\",\n \"Báo giá chi tiết gói doanh nghiệp\",\n \"Hỗ trợ kỹ thuật 24/7\",\n ],\n marginBottom: 16,\n marginTop: 0,\n type: 20,\n },\n },\n };\n }\n\n case 3:\n case 1:\n default: {\n // Template 1 & 3: Bán sản phẩm đặt hàng trực tiếp / pop-up\n return {\n version: \"1\",\n renderList: [\n \"0\", \"1\", \"2\", \"11\", \"16\", \"17\", \"18\", \"26\", \"3\", \"4\", \"5\", \"7\", \"8\", \"9\", \"12\", \"10\", \"27\"\n ],\n freezedTop: 3,\n freezedBottom: 10,\n data: {\n \"0\": {\n id: \"-1\",\n type: 1,\n indexes: [\"0\", \"1\", \"2\"],\n images: {\n \"0\": { name: \"prod-1.jpg\", url: defaultImages[0] },\n \"1\": { name: \"prod-2.jpg\", url: defaultImages[1] },\n \"2\": { name: \"prod-3.jpg\", url: defaultImages[2] },\n },\n videos: { \"5\": { name: \"\", thumbnail: \"\", url: \"\" } },\n },\n \"1\": {\n id: \"-1\",\n discountValue: 35,\n visible: true,\n countdownType: 4,\n type: 2,\n startDate: Date.now(),\n loopDays: 1,\n label: \"<p>Thời gian ưu đãi còn lại:</p>\",\n labelDelta: { ops: [{ insert: \"Thời gian ưu đãi còn lại:\\n\" }] },\n marginTop: 8,\n marginBottom: 0,\n visibility: { days: true, hours: true, minutes: true, seconds: true },\n },\n \"2\": {\n type: 19,\n name: productName,\n price,\n rawPrice,\n marginTop: 8,\n marginBottom: 8,\n },\n \"3\": {\n id: \"-1\",\n type: 18,\n visible: true,\n formQuestion: {\n type: 2,\n title: \"Phiên bản\",\n isRequired: true,\n disable: false,\n answers: [\n { type: 1, value: \"Bản Tiêu Chuẩn\", priority: 0 },\n { type: 1, value: \"Bản Cao Cấp\", priority: 1 },\n ],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"4\": {\n id: \"-1\",\n type: 18,\n visible: true,\n formQuestion: {\n type: 2,\n title: \"Gói dung lượng\",\n isRequired: true,\n disable: false,\n answers: [\n { type: 1, value: \"Gói 1 Tháng\", priority: 0 },\n { type: 1, value: \"Gói 1 Năm\", priority: 1 },\n ],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"5\": {\n id: \"-1\",\n type: 16,\n formQuestion: {\n type: 1,\n title: \"Số lượng\",\n isRequired: true,\n disable: false,\n answers: [{ type: 5, value: \"\", priority: 0 }],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"7\": {\n id: \"-1\",\n type: 7,\n formQuestion: {\n type: 1,\n title: \"Họ và tên\",\n isRequired: true,\n disable: false,\n answers: [{ type: 7, value: \"\", placeHolder: \"Nhập họ và tên của bạn\", priority: 0 }],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"8\": {\n id: \"-1\",\n type: 9,\n formQuestion: {\n type: 1,\n title: \"Số điện thoại\",\n isRequired: true,\n disable: false,\n answers: [{ type: 13, value: \"\", placeHolder: \"Nhập số điện thoại liên hệ\", priority: 0 }],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"9\": {\n id: \"-1\",\n type: 10,\n formQuestion: {\n type: 1,\n title: \"Địa chỉ\",\n isRequired: true,\n disable: false,\n answers: [{ type: 15, value: \"\", placeHolder: \"Nhập địa chỉ giao hàng hoặc nhận tư vấn\", priority: 0 }],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"10\": {\n id: \"-1\",\n type: 8,\n background: \"#008FE5\",\n borderColor: \"#000000\",\n borderRadius: 4,\n borderSize: 1,\n showBorder: false,\n formPopup: templateId === 3,\n fixedPosition: true,\n image: {\n name: \"cart.svg\",\n url: \"https://adtima-media.zascdn.me/2023/10/58117541-e206-4f9d-b4cf-69e50f963288.svg\",\n },\n content2: \"Đặt hàng ngay\",\n },\n \"11\": {\n id: \"-1\",\n type: 4,\n delta: {\n ops: [\n { attributes: { color: \"#bf2600\", bold: true }, insert: \"ƯU ĐÃI ĐẶC BIỆT HÔM NAY\\n\" },\n { insert: `Trải nghiệm trọn bộ tính năng vượt trội của ${productName}.\\n` },\n ],\n },\n marginTop: 16,\n marginBottom: 16,\n outputHtml: `<p><strong style=\"color: rgb(191, 38, 0);\">ƯU ĐÃI ĐẶC BIỆT HÔM NAY</strong></p><p>Trải nghiệm trọn bộ tính năng vượt trội của ${productName}.</p>`,\n },\n \"12\": {\n id: \"-1\",\n type: 23,\n actionType: \"1\",\n content: \"Liên hệ Hotline\",\n borderColor: \"#008fe5\",\n borderRadius: 4,\n borderSize: 2,\n showBorder: true,\n fixedPosition: true,\n visible: true,\n phone: options.hotline || \"\",\n image: {\n name: \"phone.svg\",\n url: \"https://adtima-media.zascdn.me/2023/10/03d065a4-90b2-4deb-b684-5ff61407a47d.svg\",\n },\n color: \"#008fe5\",\n background: \"#ffffff\",\n marginTop: 16,\n marginBottom: 16,\n },\n \"16\": {\n id: \"-1\",\n type: 6,\n mediaType: \"image\",\n image: { url: defaultImages[0], name: \"hero-1.png\" },\n videoSetting: { autoPlay: true, loop: true },\n },\n \"17\": {\n id: \"-1\",\n type: 6,\n mediaType: \"image\",\n image: { url: defaultImages[1], name: \"hero-2.png\" },\n videoSetting: { autoPlay: true, loop: true },\n },\n \"18\": {\n id: \"-1\",\n type: 6,\n mediaType: \"image\",\n image: { url: defaultImages[2], name: \"hero-3.png\" },\n videoSetting: { autoPlay: true, loop: true },\n },\n \"26\": {\n id: \"-1\",\n type: 14,\n backgroundColor: \"#f2f3f3\",\n textDelta: { ops: [{ attributes: { size: \"18px\", bold: true }, insert: `${brandName}\\n` }] },\n textHtml: `<p><strong style=\"font-size: 18px;\">${brandName}</strong></p>`,\n detailings: [\n {\n image: {\n url: \"https://adtima-media.zascdn.me/2023/10/cba64b4d-0bd5-4504-8b6d-5f2d2562854a.png\",\n name: \"home.png\",\n },\n textDelta: { ops: [{ insert: `Địa chỉ: ${options.address || \"Hà Nội / TP.HCM\"}\\n` }] },\n textHtml: `<p>Địa chỉ: ${options.address || \"Hà Nội / TP.HCM\"}</p>`,\n },\n {\n image: {\n url: \"https://adtima-media.zascdn.me/2023/10/d538811f-9232-4ef0-a130-ea2b1dda05d2.png\",\n name: \"phone.png\",\n },\n textDelta: { ops: [{ insert: `Hotline: ${options.hotline || \"1900 xxxx\"}\\n` }] },\n textHtml: `<p>Hotline: ${options.hotline || \"1900 xxxx\"}</p>`,\n },\n ],\n },\n \"27\": {\n id: \"-1\",\n type: 27,\n useCustomConsent: false,\n },\n },\n };\n }\n }\n }\n}\n","/**\n * Bộ kiểm tra tính hợp lệ và chuẩn hóa tham số Quy tắc tự động (Automated Rules Validator) cho Zalo Ads.\n * Reverse-engineered và kiểm chứng trực tiếp từ Zalo Ads Web Frontend (chunk 183) & Backend API.\n */\n\nexport enum AutomatedRuleScopeEnum {\n Ads = 1, // Quảng cáo (Phạm vi duy nhất hiện được hỗ trợ)\n}\n\nexport enum AutomatedRuleActionTypeEnum {\n Resume = 1, // Tiếp tục chạy quảng cáo (Bật)\n Pause = 2, // Tạm dừng quảng cáo (Tắt)\n IncreaseByAmount = 3, // Tăng giá đấu thầu theo số tiền cố định (VNĐ)\n DecreaseByAmount = 4, // Giảm giá đấu thầu theo số tiền cố định (VNĐ)\n IncreaseByPercentage = 5, // Tăng giá đấu thầu theo %\n DecreaseByPercentage = 6, // Giảm giá đấu thầu theo %\n}\n\nexport enum AutomatedRuleFrequencyEnum {\n OneHour = 1, // Mỗi tiếng / lần sau lần thực thi trước (1 giờ)\n HalfDay = 12, // 12 giờ / lần sau lần thực thi trước (12 giờ)\n OneDay = 24, // Mỗi ngày / lần sau lần thực thi trước (24 giờ)\n OneWeek = 168, // Mỗi tuần / lần sau lần thực thi trước (168 giờ = 7 ngày)\n}\n\nexport enum AutomatedRuleConditionFieldEnum {\n Status = 1, // Trạng thái quảng cáo (Đang chạy / Tạm dừng)\n Impression = 11, // Lượt hiển thị (tối thiểu 500)\n Click = 16, // Lượt nhấn (tối thiểu 10)\n CTR = 9999, // CTR (%)\n Cost = 100001, // Đã chi tiêu (VNĐ - tối thiểu 49.999đ)\n}\n\nexport enum AutomatedRuleOperatorEnum {\n GreaterThan = 1, // Lớn hơn (>)\n LessThan = 2, // Nhỏ hơn (<)\n Between = 3, // Trong khoảng\n NotBetween = 4, // Không trong khoảng\n Include = 5, // Bao gồm\n Exclude = 6, // Không bao gồm\n}\n\nexport enum AutomatedRuleTimeRangeEnum {\n AllTime = 1, // Từ lúc bắt đầu tới hiện tại (Lifetime)\n AllTimeExcludeToday = 2, // Từ lúc bắt đầu tới hết hôm qua\n Today = 3, // Trong ngày hôm nay\n Yesterday = 4, // Trong ngày hôm qua\n Previous2Day = 1002, // 2 ngày trước tới hiện tại\n Previous3Day = 1003, // 3 ngày trước tới hiện tại\n Previous4Day = 1004, // 4 ngày trước tới hiện tại\n Previous5Day = 1005, // 5 ngày trước tới hiện tại\n Previous6Day = 1006, // 6 ngày trước tới hiện tại\n Previous7Day = 1007, // 7 ngày trước tới hiện tại\n Previous14Day = 1014, // 14 ngày trước tới hiện tại\n Previous21Day = 1021, // 21 ngày trước tới hiện tại\n Previous30Day = 1030, // 30 ngày trước tới hiện tại\n}\n\nexport interface AutomatedRuleValidationResult<T = any> {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n sanitizedData?: T;\n}\n\nexport class ZaloAutomatedRulesValidator {\n /**\n * Kiểm tra và chuẩn hóa payload tạo mới quy tắc tự động (`POST /api/automatedrules/create`)\n */\n public static validateCreateRule(payload: any): AutomatedRuleValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload || typeof payload !== 'object') {\n return { isValid: false, errors: ['Payload quy tắc tự động phải là một object.'], warnings };\n }\n\n // 1. Tên quy tắc (ruleName)\n const ruleName = String(payload.ruleName || '').trim();\n if (!ruleName) {\n errors.push('Tên quy tắc (ruleName) không được để trống.');\n } else if (ruleName.length > 100) {\n errors.push(`Tên quy tắc không được vượt quá 100 ký tự (hiện có ${ruleName.length} ký tự).`);\n }\n\n // 2. Phạm vi (scope)\n const scope = payload.scope !== undefined ? Number(payload.scope) : 1;\n if (scope !== 1) {\n errors.push('Zalo Ads hiện chỉ hỗ trợ scope: 1 (Áp dụng cho Quảng cáo).');\n }\n\n // 3. Hành động (action)\n if (!payload.action || typeof payload.action !== 'object') {\n errors.push('Thiếu cấu hình hành động (action).');\n } else {\n const act = payload.action;\n const actType = Number(act.type);\n if (![3, 4, 5, 6].includes(actType)) {\n if ([1, 2].includes(actType)) {\n errors.push(`Hành động ${actType === 1 ? 'Tiếp tục' : 'Tạm dừng'} quảng cáo (type: ${actType}) hiện chưa được backend Zalo Ads kích hoạt trong scope này.`);\n } else {\n errors.push(`Loại hành động không hợp lệ: ${act.type}. Chỉ hỗ trợ 3 (Tăng giá đ), 4 (Giảm giá đ), 5 (Tăng giá %), 6 (Giảm giá %).`);\n }\n }\n\n // Kiểm tra values\n if (!Array.isArray(act.values) || act.values.length === 0 || Number(act.values[0]) <= 0) {\n errors.push('Giá trị thay đổi giá thầu (action.values) phải là mảng chứa số dương > 0.');\n } else {\n const val = Number(act.values[0]);\n if ([5, 6].includes(actType) && (val < 1 || val > 100)) {\n errors.push(`Thay đổi theo % (type: ${actType}) yêu cầu giá trị trong khoảng từ 1% đến 100% (hiện là ${val}%).`);\n }\n }\n\n // Kiểm tra hạn mức (limit)\n if (act.limit !== undefined && Number(act.limit) <= 0) {\n errors.push('Hạn mức giá thầu (action.limit) nếu có phải là số tiền dương > 0 VNĐ.');\n }\n }\n\n // 4. Tần suất hành động (frequency)\n const frequency = payload.frequency !== undefined ? Number(payload.frequency) : 12;\n const actType = payload.action ? Number(payload.action.type) : 0;\n if ([3, 4, 5, 6].includes(actType)) {\n if (![1, 12, 24, 168].includes(frequency)) {\n errors.push(`Tần suất hành động cho điều chỉnh giá thầu phải thuộc [1 (1 giờ), 12 (12 giờ), 24 (1 ngày), 168 (1 tuần)]. Giá trị ${frequency} sẽ bị từ chối với lỗi \"Tần suất hành động không hợp lệ.\"`);\n }\n }\n\n // 5. Điều kiện chỉ số (conditions)\n if (!Array.isArray(payload.conditions) || payload.conditions.length === 0) {\n errors.push('Quy tắc tự động phải có ít nhất 1 điều kiện chỉ số (conditions).');\n } else {\n payload.conditions.forEach((c: any, idx: number) => {\n const f = Number(c.field);\n if (![1, 11, 16, 9999, 100001].includes(f)) {\n errors.push(`Điều kiện [${idx + 1}]: Chỉ số không hợp lệ (field: ${c.field}). Hỗ trợ: 1 (Status), 11 (Impression), 16 (Click), 9999 (CTR), 100001 (Cost).`);\n }\n const op = Number(c.operator);\n if (![1, 2, 3, 4, 5, 6].includes(op)) {\n errors.push(`Điều kiện [${idx + 1}]: Phép toán không hợp lệ (operator: ${c.operator}). Hỗ trợ 1 (>), 2 (<), 3 (between), 4 (not between), 5 (include), 6 (exclude).`);\n }\n if (!Array.isArray(c.values) || c.values.length === 0) {\n errors.push(`Điều kiện [${idx + 1}]: values phải là mảng giá trị ngưỡng.`);\n }\n if (f !== 1 && !c.timeRange) {\n warnings.push(`Điều kiện [${idx + 1}]: Thiếu timeRange, hệ thống sẽ mặc định là 1 (Lifetime).`);\n }\n });\n }\n\n const sanitizedData = {\n ruleName,\n scope: 1,\n action: {\n type: Number(payload.action?.type),\n field: 1,\n values: payload.action?.values?.map(Number) || [10],\n limit: payload.action?.limit !== undefined ? Number(payload.action.limit) : 1000000,\n },\n conditions: (payload.conditions || []).map((c: any) => ({\n field: Number(c.field),\n operator: Number(c.operator),\n values: c.values.map(Number),\n timeRange: c.timeRange !== undefined ? Number(c.timeRange) : 1,\n })),\n frequency,\n appliedIds: Array.isArray(payload.appliedIds) ? payload.appliedIds.map(Number) : [],\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n sanitizedData: errors.length === 0 ? sanitizedData : undefined,\n };\n }\n\n /**\n * Kiểm tra và chuẩn hóa payload cập nhật quy tắc tự động (`POST /api/ad/automatedrules/update`)\n */\n public static validateUpdateRule(payload: any): AutomatedRuleValidationResult {\n const base = this.validateCreateRule(payload);\n const errors = [...base.errors];\n const warnings = [...base.warnings];\n\n if (!payload.automatedRuleId || Number(payload.automatedRuleId) <= 0) {\n errors.unshift('ID quy tắc tự động (automatedRuleId) là bắt buộc khi cập nhật.');\n }\n\n const appliedItems = Array.isArray(payload.appliedItems)\n ? payload.appliedItems.map((item: any) => ({\n appliedId: Number(item.appliedId),\n mode: Number(item.mode) === -1 ? -1 : 1, // -1: Unapply, 1: Apply\n }))\n : [];\n\n const sanitizedData = base.sanitizedData\n ? {\n automatedRuleId: Number(payload.automatedRuleId),\n ...base.sanitizedData,\n appliedItems,\n }\n : undefined;\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n sanitizedData,\n };\n }\n}\n","/**\n * Bộ kiểm tra tính hợp lệ và chuẩn hóa tham số Sự kiện chuyển đổi & Zalo Pixel (Conversions Validator) cho Zalo Ads.\n * Reverse-engineered và kiểm chứng trực tiếp từ Zalo Ads Web Frontend (chunk 602, chunk 804) & Backend API.\n */\n\nexport enum ConversionLabelEnum {\n AddToCart = 2, // Thêm vào giỏ hàng\n CompleteRegistration = 4, // Hoàn tất đăng ký\n Contact = 5, // Liên hệ\n InitiateCheckout = 9, // Bắt đầu thanh toán\n Lead = 10, // Trở thành khách hàng tiềm năng\n Purchase = 11, // Hoàn tất mua hàng\n Other = 19, // Khác\n}\n\nexport enum ConversionUrlTypeEnum {\n Exact = 0, // URL chính xác\n Contains = 1, // URL chứa từ khóa / đường dẫn tương đối\n}\n\nexport interface ConversionValidationResult<T = any> {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n sanitizedData?: T;\n}\n\nexport class ZaloConversionsValidator {\n /**\n * Danh mục 7 nhãn chuẩn được Zalo Ads hỗ trợ chính thức\n */\n public static readonly SUPPORTED_LABELS: Record<number, string> = {\n [ConversionLabelEnum.Lead]: 'Trở thành khách hàng tiềm năng',\n [ConversionLabelEnum.Purchase]: 'Hoàn tất mua hàng',\n [ConversionLabelEnum.Contact]: 'Liên hệ',\n [ConversionLabelEnum.CompleteRegistration]: 'Hoàn tất đăng ký',\n [ConversionLabelEnum.InitiateCheckout]: 'Bắt đầu thanh toán',\n [ConversionLabelEnum.AddToCart]: 'Thêm vào giỏ hàng',\n [ConversionLabelEnum.Other]: 'Khác',\n };\n\n /**\n * Kiểm tra và chuẩn hóa payload tạo mới Conversion (`POST /api/conversion/add`)\n */\n public static validateCreateConversion(payload: any): ConversionValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload || typeof payload !== 'object') {\n return { isValid: false, errors: ['Payload conversion phải là một object.'], warnings };\n }\n\n // 1. Tên conversion (name)\n const name = String(payload.name || '').trim();\n if (!name) {\n errors.push('Tên conversion (name) không được để trống.');\n } else if (name.length > 180) {\n errors.push(`Tên conversion không được vượt quá 180 ký tự (hiện có ${name.length} ký tự).`);\n }\n\n // 2. Trang đích (landingPage)\n const landingPage = String(payload.landingPage || '').trim();\n if (!landingPage) {\n errors.push('Trang đích (landingPage) không được để trống.');\n } else {\n const urlPattern = /^https?:\\/\\/.+/i;\n if (!urlPattern.test(landingPage)) {\n errors.push('Trang đích (landingPage) phải là một URL hợp lệ bắt đầu bằng http:// hoặc https:// (ví dụ: https://redai.vn).');\n }\n }\n\n // 3. Loại URL (urlType)\n const urlType = payload.urlType !== undefined ? Number(payload.urlType) : 1;\n if (![0, 1].includes(urlType)) {\n errors.push(`Loại URL không hợp lệ: ${payload.urlType}. Chỉ hỗ trợ 0 (Exact URL) hoặc 1 (Contains keywords).`);\n }\n\n // 4. Nhãn sự kiện (labelId)\n const labelId = payload.labelId !== undefined ? Number(payload.labelId) : 10;\n if (!Object.keys(this.SUPPORTED_LABELS).map(Number).includes(labelId)) {\n errors.push(`Nhãn conversion không hợp lệ (labelId: ${payload.labelId}). Zalo Ads chỉ hỗ trợ: 10 (Lead), 11 (Purchase), 5 (Contact), 4 (Registration), 9 (Checkout), 2 (AddToCart), 19 (Other).`);\n }\n\n // 5. Cơ chế kích hoạt sự kiện (Tối thiểu 1 trong: keywords, buttonIds, elements)\n const buttonIds: string[] = Array.isArray(payload.buttonIds) ? payload.buttonIds.map(String).map((s: string) => s.trim()).filter((s: string) => Boolean(s)) : [];\n const elements: any[] = Array.isArray(payload.elements) ? payload.elements : [];\n const keywords: string[] = Array.isArray(payload.keywords) ? payload.keywords.map(String).map((s: string) => s.trim()).filter((s: string) => Boolean(s)) : [];\n\n if (buttonIds.length === 0 && elements.length === 0 && keywords.length === 0) {\n errors.push('Conversion bắt buộc phải có ít nhất 1 cơ chế nhận diện sự kiện: URL chứa từ khóa (keywords), ID nút bấm (buttonIds), hoặc phần tử giao diện (elements).');\n }\n\n // Sanitize elements\n const sanitizedElements = elements.map(el => {\n if (typeof el === 'object' && Array.isArray(el.class)) {\n return { class: el.class.map(String).map((s: string) => s.trim()).filter((s: string) => Boolean(s)) };\n }\n return el;\n });\n\n const sanitizedData = {\n name,\n landingPage,\n urlType,\n labelId,\n buttonIds,\n elements: sanitizedElements,\n keywords,\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n sanitizedData: errors.length === 0 ? sanitizedData : undefined,\n };\n }\n}\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Zalo Profile Ads (https://profile.ads.zalo.me):\n * 1. createOaPage (POST /ajax/create-page)\n * 2. uploadOaAvatar (POST /ajax/upload-avatar)\n * 3. uploadOaCover (POST /ajax/upload-cover)\n *\n * Tích hợp toàn bộ quy chuẩn, danh mục 22 SubCategories, 34 Provinces, định dạng CCCD/SĐT,\n * và chính sách xét duyệt Official Account cửa hàng/doanh nghiệp.\n */\n\nimport type {\n ZaloProfileAdsCreateOaPageRequest,\n ZaloProfileAdsProvinceId,\n ZaloProfileAdsSubCategoryId,\n} from \"../dtos/profile-ads.dto\";\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\n/**\n * Danh mục 22 mã SubCategory chuẩn trên Zalo Ads Profile\n */\nexport const ZALO_PROFILE_ADS_SUB_CATEGORIES: Record<number, string> = {\n 10043: \"Bất động sản\",\n 10018: \"Công nghệ & Thiết bị\",\n 10097: \"Dịch vụ tiện ích\",\n 10020: \"Du lịch & Lưu trú\",\n 10021: \"Giáo dục & Đào tạo\",\n 10024: \"Mua sắm & Bán lẻ\",\n 10019: \"Mỹ phẩm & Làm đẹp\",\n 10014: \"Nhà hàng & Quán\",\n 10094: \"Ô tô & Xe máy\",\n 10098: \"Sản xuất & Chế tạo\",\n 10044: \"Tài chính & Ngân hàng\",\n 10099: \"Thiết kế & Thi công\",\n 10017: \"Thời trang & May mặc\",\n 10023: \"Thực phẩm & Đồ uống\",\n 10016: \"Truyền thông & Giải trí\",\n 10092: \"Truyền thông nội bộ\",\n 10101: \"Tuyển dụng & Việc làm\",\n 10100: \"Tư vấn & Quản lý\",\n 10095: \"Vận tải\",\n 10093: \"Viễn thông\",\n 10022: \"Y tế & Dược phẩm\",\n 10025: \"Dịch vụ khác\",\n};\n\n/**\n * Danh mục 34 Tỉnh/Thành phố chuẩn trên Zalo Ads Profile (GET /ajax/get-province)\n */\nexport const ZALO_PROFILE_ADS_PROVINCES: Record<number, string> = {\n 1: \"Thành phố Hà Nội\",\n 4: \"Tỉnh Cao Bằng\",\n 8: \"Tỉnh Tuyên Quang\",\n 11: \"Tỉnh Điện Biên\",\n 12: \"Tỉnh Lai Châu\",\n 14: \"Tỉnh Sơn La\",\n 15: \"Tỉnh Lào Cai\",\n 19: \"Tỉnh Thái Nguyên\",\n 20: \"Tỉnh Lạng Sơn\",\n 22: \"Tỉnh Quảng Ninh\",\n 24: \"Tỉnh Bắc Ninh\",\n 25: \"Tỉnh Phú Thọ\",\n 31: \"Thành phố Hải Phòng\",\n 33: \"Tỉnh Hưng Yên\",\n 37: \"Tỉnh Ninh Bình\",\n 38: \"Tỉnh Thanh Hóa\",\n 40: \"Tỉnh Nghệ An\",\n 42: \"Tỉnh Hà Tĩnh\",\n 44: \"Tỉnh Quảng Trị\",\n 46: \"Thành phố Huế\",\n 48: \"Thành phố Đà Nẵng\",\n 51: \"Tỉnh Quảng Ngãi\",\n 52: \"Tỉnh Gia Lai\",\n 56: \"Tỉnh Khánh Hòa\",\n 66: \"Tỉnh Đắk Lắk\",\n 68: \"Tỉnh Lâm Đồng\",\n 75: \"Tỉnh Đồng Nai\",\n 79: \"Thành phố Hồ Chí Minh\",\n 80: \"Tỉnh Tây Ninh\",\n 82: \"Tỉnh Đồng Tháp\",\n 86: \"Tỉnh Vĩnh Long\",\n 91: \"Tỉnh An Giang\",\n 92: \"Thành phố Cần Thơ\",\n 96: \"Tỉnh Cà Mau\",\n};\n\n/**\n * Biểu thức Regex kiểm tra số điện thoại di động Việt Nam (10 số, đầu 03, 05, 07, 08, 09 hoặc 843, 845,...)\n */\nexport const VIETNAM_PHONE_REGEX = /^(84|0)(3[2-9]|5[2689]|7[06-9]|8[1-9]|9[0-9])[0-9]{7}$/;\n\n/**\n * Helper kiểm tra URL hợp lệ\n */\nfunction isValidUrl(val: string): boolean {\n return /^(https?:\\/\\/|data:image\\/)/i.test(val);\n}\n\n// ============================================================================\n// 1. validateCreateOaPageRequest\n// ============================================================================\nexport function validateCreateOaPageRequest(input: unknown): ValidationResult<ZaloProfileAdsCreateOaPageRequest> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu khởi tạo Zalo Official Account phải là một đối tượng (object).\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n\n // 1. oaName: Tên hiển thị của trang OA (2 - 40 ký tự)\n const oaName = typeof raw.oaName === \"string\" ? raw.oaName.trim() : \"\";\n if (!oaName) {\n errors.push(\"Tên trang Official Account ('oaName') là bắt buộc và không được để trống.\");\n } else if (oaName.length < 2 || oaName.length > 40) {\n errors.push(`Tên trang Official Account phải từ 2 đến 40 ký tự (hiện tại: ${oaName.length} ký tự).`);\n } else {\n // Không dùng chữ in hoa toàn bộ (trừ viết tắt thương hiệu ngắn <= 5 ký tự)\n if (oaName.length > 5 && oaName === oaName.toUpperCase() && /[A-Z]/.test(oaName)) {\n errors.push(\"Tên trang Official Account không được viết in hoa toàn bộ các từ. Vui lòng viết theo ngữ pháp tiếng Việt chuẩn.\");\n }\n // Cấm các từ ngữ chung chung hoặc từ khóa nhạy cảm\n const forbiddenKeywords = [\"số 1\", \"nhất việt nam\", \"cam kết 100%\", \"trị dứt điểm\"];\n for (const kw of forbiddenKeywords) {\n if (oaName.toLowerCase().includes(kw)) {\n errors.push(`Tên trang Official Account chứa từ ngữ cam kết/phô trương không hợp lệ: '${kw}'.`);\n }\n }\n }\n\n // 2. description: Mô tả hoạt động (20 - 500 ký tự)\n const description = typeof raw.description === \"string\" ? raw.description.trim() : \"\";\n if (!description) {\n errors.push(\"Thông tin mô tả hoạt động ('description') là bắt buộc.\");\n } else if (description.length < 20 || description.length > 500) {\n errors.push(`Thông tin mô tả hoạt động phải từ 20 đến 500 ký tự (hiện tại: ${description.length} ký tự).`);\n }\n\n // 3. contactName: Tên người liên hệ (tối thiểu 2 từ)\n const contactName = typeof raw.contactName === \"string\" ? raw.contactName.trim() : \"\";\n if (!contactName) {\n errors.push(\"Họ và tên người liên hệ ('contactName') là bắt buộc.\");\n } else if (contactName.split(/\\s+/).length < 2) {\n errors.push(\"Họ và tên người liên hệ phải có ít nhất 2 từ (họ và tên).\");\n }\n\n // 4. contactPhone: Số điện thoại liên hệ (10 chữ số chuẩn VN)\n const contactPhone = typeof raw.contactPhone === \"string\" ? raw.contactPhone.trim() : String(raw.contactPhone || \"\").trim();\n if (!contactPhone) {\n errors.push(\"Số điện thoại liên hệ ('contactPhone') là bắt buộc.\");\n } else {\n const cleanPhone = contactPhone.replace(/\\s+/g, \"\");\n if (!VIETNAM_PHONE_REGEX.test(cleanPhone)) {\n errors.push(`Số điện thoại liên hệ '${contactPhone}' không hợp lệ. Phải là số di động Việt Nam 10 chữ số (ví dụ: 0901234567 hoặc 84901234567).`);\n }\n }\n\n // 5. subCategoryId: 1 trong 22 mã chuẩn\n const subCatId = Number(raw.subCategoryId);\n if (!subCatId || !ZALO_PROFILE_ADS_SUB_CATEGORIES[subCatId]) {\n errors.push(\n `Mã danh mục hoạt động ('subCategoryId') '${raw.subCategoryId}' không hợp lệ. Phải thuộc 22 mã danh mục chuẩn trên Zalo Ads Profile (ví dụ: 10018: Công nghệ & Thiết bị, 10043: Bất động sản, 10024: Mua sắm & Bán lẻ).`\n );\n }\n\n // 6. province: 1 trong 34 mã tỉnh thành chuẩn\n const provinceId = Number(raw.province);\n if (!provinceId || !ZALO_PROFILE_ADS_PROVINCES[provinceId]) {\n errors.push(\n `Mã Tỉnh/Thành phố ('province') '${raw.province}' không hợp lệ. Phải thuộc 34 mã hành chính chuẩn trên Zalo Ads Profile (ví dụ: 1: Hà Nội, 79: TP.HCM, 48: Đà Nẵng).`\n );\n }\n\n // 7. district: Phường/Xã (số nguyên dương > 0)\n const district = Number(raw.district);\n if (!district || !Number.isInteger(district) || district <= 0) {\n errors.push(\"Mã Phường/Xã ('district') là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n // 8. address: Địa chỉ chi tiết (tối thiểu 5 ký tự)\n const address = typeof raw.address === \"string\" ? raw.address.trim() : \"\";\n if (!address || address.length < 5) {\n errors.push(\"Địa chỉ hoạt động chi tiết ('address') phải có độ dài tối thiểu 5 ký tự.\");\n }\n\n // 9. avatarId & coverId: Chuỗi fileId không rỗng\n const avatarId = typeof raw.avatarId === \"string\" ? raw.avatarId.trim() : \"\";\n if (!avatarId) {\n errors.push(\"Mã định danh ảnh đại diện ('avatarId') là bắt buộc. Hãy tải ảnh qua API uploadOaAvatar trước.\");\n }\n\n const coverId = typeof raw.coverId === \"string\" ? raw.coverId.trim() : \"\";\n if (!coverId) {\n errors.push(\"Mã định danh ảnh bìa ('coverId') là bắt buộc. Hãy tải ảnh qua API uploadOaCover trước.\");\n }\n\n const cleanData: ZaloProfileAdsCreateOaPageRequest = {\n option: \"createpage\",\n typeId: raw.typeId !== undefined ? Number(raw.typeId) : 2,\n typeName: typeof raw.typeName === \"string\" ? raw.typeName : \"store\",\n tier: raw.tier !== undefined ? Number(raw.tier) : 0,\n categoryId: raw.categoryId !== undefined ? Number(raw.categoryId) : 10003,\n subCategoryId: subCatId as ZaloProfileAdsSubCategoryId,\n oaName,\n description,\n contactName,\n contactPhone,\n avatarId,\n coverId,\n province: provinceId as ZaloProfileAdsProvinceId,\n district,\n address,\n agreeTerm: raw.agreeTerm !== undefined ? Boolean(raw.agreeTerm) : true,\n ...(typeof raw[\"crsf-token\"] === \"string\" ? { \"crsf-token\": raw[\"crsf-token\"] } : {}),\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n// ============================================================================\n// 2. validateUploadMediaRequest (Avatar & Cover)\n// ============================================================================\nexport interface ValidateUploadMediaOptions {\n mediaType: \"avatar\" | \"cover\";\n maxSizeBytes?: number;\n minWidth?: number;\n minHeight?: number;\n}\n\nexport function validateUploadMediaRequest(\n input: unknown,\n options: ValidateUploadMediaOptions\n): ValidationResult<{ file: unknown; isNew?: string; option?: string }> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu tải ảnh lên phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const fileField = options.mediaType === \"avatar\" ? (raw[\"avatar-file\"] ?? raw.file ?? raw.File) : (raw[\"cover-file\"] ?? raw.file ?? raw.File);\n\n if (!fileField) {\n errors.push(`Trường tệp ảnh ('${options.mediaType === \"avatar\" ? \"avatar-file\" : \"cover-file\"}') là bắt buộc.`);\n return { isValid: false, errors };\n }\n\n // Kiểm tra nếu là URL chuỗi\n if (typeof fileField === \"string\") {\n const trimmed = fileField.trim();\n if (!trimmed) {\n errors.push(\"Đường dẫn tệp ảnh không được để trống.\");\n } else if (!isValidUrl(trimmed)) {\n errors.push(`Đường dẫn tệp '${trimmed}' không hợp lệ. Phải là URL HTTP/HTTPS công khai hoặc data URL.`);\n }\n }\n\n // Kiểm tra kích thước và giới hạn dung lượng\n const maxBytes = options.maxSizeBytes || 15 * 1024 * 1024; // Mặc định 15MB\n if (typeof raw.sizeBytes === \"number\" && raw.sizeBytes > maxBytes) {\n const sizeMb = (raw.sizeBytes / (1024 * 1024)).toFixed(2);\n errors.push(`Dung lượng ảnh vượt quá giới hạn tối đa 15MB (dung lượng: ${sizeMb}MB).`);\n }\n\n const minW = options.minWidth || (options.mediaType === \"avatar\" ? 150 : 320);\n const minH = options.minHeight || (options.mediaType === \"avatar\" ? 150 : 180);\n\n if (typeof raw.width === \"number\" && raw.width < minW) {\n errors.push(`Chiều rộng ảnh tối thiểu ${minW}px (hiện tại: ${raw.width}px).`);\n }\n if (typeof raw.height === \"number\" && raw.height < minH) {\n errors.push(`Chiều cao ảnh tối thiểu ${minH}px (hiện tại: ${raw.height}px).`);\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0\n ? {\n file: fileField,\n isNew: typeof raw[\"is-new\"] === \"string\" ? raw[\"is-new\"] : \"true\",\n option: typeof raw.option === \"string\" ? raw.option : \"update\",\n }\n : undefined,\n };\n}\n\n/**\n * ZaloProfileAdsValidator: Gom nhóm các hàm xác thực cho Zalo Profile Ads\n */\nexport const ZaloProfileAdsValidator = {\n validateCreateOaPage: validateCreateOaPageRequest,\n validateUploadMedia: validateUploadMediaRequest,\n validateUploadAvatar: (input: unknown) =>\n validateUploadMediaRequest(input, { mediaType: \"avatar\", minWidth: 150, minHeight: 150 }),\n validateUploadCover: (input: unknown) =>\n validateUploadMediaRequest(input, { mediaType: \"cover\", minWidth: 320, minHeight: 180 }),\n};\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Báo cáo (Reports) trên Zalo Ads:\n * 1. upsertCustomReport (POST /api/report/upsertCustomReport)\n * 2. validateDateRangeReport: Xác thực khoảng thời gian truy vấn báo cáo (v2/v3 campaigns, ads, unique-user, demographics)\n *\n * Tích hợp quy chuẩn giới hạn thời gian tối đa 90 ngày của Zalo Ads Report Engine,\n * định dạng Unix timestamp giây/mili-giây và danh mục các cột chỉ số báo cáo.\n */\n\nimport type { ZaloAdsUpsertCustomReportRequest } from \"../dtos/ads.dto\";\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\n/**\n * 90 ngày tính bằng giây (90 * 24 * 3600)\n */\nexport const MAX_REPORT_RANGE_SECONDS = 90 * 86400;\n\n/**\n * 90 ngày tính bằng mili-giây\n */\nexport const MAX_REPORT_RANGE_MS = MAX_REPORT_RANGE_SECONDS * 1000;\n\n// ============================================================================\n// 1. validateUpsertCustomReportRequest\n// ============================================================================\nexport function validateUpsertCustomReportRequest(\n input: unknown\n): ValidationResult<ZaloAdsUpsertCustomReportRequest> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu cấu hình báo cáo tùy chỉnh phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n\n // 1. id: 0 khi tạo mới, số nguyên dương khi cập nhật\n let id = 0;\n if (raw.id !== undefined && raw.id !== null) {\n const parsedId = Number(raw.id);\n if (!Number.isInteger(parsedId) || parsedId < 0) {\n errors.push(\"Trường 'id' phải là số nguyên không âm (0 khi tạo mới, > 0 khi cập nhật).\");\n } else {\n id = parsedId;\n }\n }\n\n // 2. name: Tên báo cáo tùy chỉnh (1 - 100 ký tự)\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name) {\n errors.push(\"Tên báo cáo tùy chỉnh ('name') là bắt buộc và không được để trống.\");\n } else if (name.length > 100) {\n errors.push(`Tên báo cáo tùy chỉnh không được vượt quá 100 ký tự (hiện tại: ${name.length} ký tự).`);\n }\n\n // 3. settings: Danh sách mã cột/chỉ số (Array<number>, minItems: 1)\n const settings: number[] = [];\n if (!Array.isArray(raw.settings) || raw.settings.length === 0) {\n errors.push(\"Danh sách chỉ số cột ('settings') là bắt buộc và phải có ít nhất 1 chỉ số.\");\n } else {\n for (const item of raw.settings) {\n const colId = Number(item);\n if (!Number.isInteger(colId) || colId <= 0) {\n errors.push(`Mã chỉ số cột '${item}' không hợp lệ. Phải là số nguyên dương.`);\n } else {\n if (!settings.includes(colId)) {\n settings.push(colId);\n }\n }\n }\n }\n\n // 4. isDefault: Cờ báo cáo mặc định\n const isDefault = Boolean(raw.isDefault);\n\n const cleanData: ZaloAdsUpsertCustomReportRequest = {\n id,\n name,\n settings,\n isDefault,\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n// ============================================================================\n// 2. validateDateRangeReportRequest\n// ============================================================================\nexport interface DateRangeReportQuery {\n startDate?: number;\n endDate?: number;\n from?: number;\n to?: number;\n campaignId?: number;\n [key: string]: unknown;\n}\n\nexport interface CleanDateRangeReport {\n startDate: number;\n endDate: number;\n isMilliseconds: boolean;\n campaignId?: number;\n}\n\nexport function validateDateRangeReportRequest(\n input: unknown\n): ValidationResult<CleanDateRangeReport> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Tham số truy vấn khoảng thời gian báo cáo phải là một đối tượng.\"],\n };\n }\n\n const raw = input as DateRangeReportQuery;\n\n // Lấy start/end (hỗ trợ cả cặp startDate/endDate và from/to)\n const rawStart = raw.startDate ?? raw.from;\n const rawEnd = raw.endDate ?? raw.to;\n\n if (rawStart === undefined || rawStart === null) {\n errors.push(\"Mốc thời gian bắt đầu ('startDate' hoặc 'from') là bắt buộc.\");\n }\n if (rawEnd === undefined || rawEnd === null) {\n errors.push(\"Mốc thời gian kết thúc ('endDate' hoặc 'to') là bắt buộc.\");\n }\n\n if (errors.length > 0) {\n return { isValid: false, errors };\n }\n\n const startNum = Number(rawStart);\n const endNum = Number(rawEnd);\n\n if (isNaN(startNum) || startNum <= 0) {\n errors.push(`Mốc thời gian bắt đầu '${rawStart}' không hợp lệ. Phải là Unix timestamp dương.`);\n }\n if (isNaN(endNum) || endNum <= 0) {\n errors.push(`Mốc thời gian kết thúc '${rawEnd}' không hợp lệ. Phải là Unix timestamp dương.`);\n }\n\n if (errors.length > 0) {\n return { isValid: false, errors };\n }\n\n // Nhận diện đang dùng giây hay mili-giây\n // Nếu > 10,000,000,000 (10 chữ số) => mili-giây (năm 2286 ở dạng giây)\n const isMs = startNum > 10000000000 || endNum > 10000000000;\n const maxRange = isMs ? MAX_REPORT_RANGE_MS : MAX_REPORT_RANGE_SECONDS;\n\n if (endNum < startNum) {\n errors.push(\"Mốc thời gian kết thúc phải lớn hơn hoặc bằng mốc thời gian bắt đầu.\");\n } else {\n const diff = endNum - startNum;\n if (diff > maxRange) {\n const days = isMs ? Math.round(diff / (86400 * 1000)) : Math.round(diff / 86400);\n errors.push(`Khoảng thời gian truy vấn báo cáo không được vượt quá 90 ngày theo chính sách Zalo Ads (khoảng thời gian hiện tại: ${days} ngày).`);\n }\n }\n\n let campaignId: number | undefined;\n if (raw.campaignId !== undefined && raw.campaignId !== null) {\n const parsedCampId = Number(raw.campaignId);\n if (!Number.isInteger(parsedCampId) || parsedCampId <= 0) {\n errors.push(\"Mã chiến dịch ('campaignId') phải là số nguyên dương (> 0).\");\n } else {\n campaignId = parsedCampId;\n }\n }\n\n const cleanData: CleanDateRangeReport = {\n startDate: startNum,\n endDate: endNum,\n isMilliseconds: isMs,\n ...(campaignId !== undefined ? { campaignId } : {}),\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n/**\n * ZaloReportsValidator: Gom nhóm các hàm xác thực cho Zalo Ads Reporting\n */\nexport const ZaloReportsValidator = {\n validateUpsertCustomReport: validateUpsertCustomReportRequest,\n validateDateRangeReport: validateDateRangeReportRequest,\n};\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Thư viện Media trên Zalo Ads:\n * 1. saveMedia (POST /api/media/save)\n *\n * Kiểm tra cấu trúc metadata lưu trữ Media (Name, Type: 1-Ảnh / 2-Video, Settings: Url, Width, Height, Duration, ThumbUrl).\n */\n\nimport type { ZaloAdsMediaSavePayloadDto } from \"../dtos/ads.dto\";\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\n/**\n * Helper kiểm tra URL hợp lệ\n */\nfunction isValidUrl(val: unknown): boolean {\n if (typeof val !== \"string\") return false;\n return /^https?:\\/\\/.+/i.test(val.trim());\n}\n\n// ============================================================================\n// 1. validateSaveMediaRequest\n// ============================================================================\nexport function validateSaveMediaRequest(\n input: unknown\n): ValidationResult<ZaloAdsMediaSavePayloadDto> {\n const errors: string[] = [];\n\n if (!input) {\n return {\n isValid: false,\n errors: [\"Dữ liệu lưu Media ('saveMedia') không được để trống.\"],\n };\n }\n\n // Hỗ trợ trường hợp input là JSON string hoặc bọc trong { data: ... }\n let targetObj: unknown = input;\n if (typeof input === \"string\") {\n try {\n targetObj = JSON.parse(input);\n } catch {\n return {\n isValid: false,\n errors: [\"Chuỗi JSON dữ liệu Media ('data') không đúng định dạng.\"],\n };\n }\n }\n\n if (!targetObj || typeof targetObj !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu Media phải là một đối tượng.\"],\n };\n }\n\n const rawObj = targetObj as Record<string, unknown>;\n // Nếu có wrapper 'data' bên ngoài\n let raw = rawObj;\n if (rawObj.data && typeof rawObj.data === \"object\") {\n raw = rawObj.data as Record<string, unknown>;\n } else if (typeof rawObj.data === \"string\") {\n try {\n raw = JSON.parse(rawObj.data);\n } catch {\n return {\n isValid: false,\n errors: [\"Chuỗi JSON trong trường 'data' không đúng định dạng.\"],\n };\n }\n }\n\n // 1. Name: Tên media (1 - 255 ký tự)\n const name = typeof raw.Name === \"string\" ? raw.Name.trim() : (typeof raw.name === \"string\" ? raw.name.trim() : \"\");\n if (!name) {\n errors.push(\"Tên tệp media ('Name') là bắt buộc và không được để trống.\");\n } else if (name.length > 255) {\n errors.push(`Tên tệp media không được vượt quá 255 ký tự (hiện tại: ${name.length} ký tự).`);\n }\n\n // 2. Type: 1 (Ảnh) hoặc 2 (Video)\n const typeVal = raw.Type !== undefined ? Number(raw.Type) : (raw.type !== undefined ? Number(raw.type) : NaN);\n if (typeVal !== 1 && typeVal !== 2) {\n errors.push(`Loại media ('Type') không hợp lệ: '${raw.Type ?? raw.type}'. Chỉ hỗ trợ 1 (Ảnh) hoặc 2 (Video).`);\n }\n\n // 3. Settings: Cấu hình chi tiết\n const rawSettings = (raw.Settings ?? raw.settings) as Record<string, unknown> | undefined;\n if (!rawSettings || typeof rawSettings !== \"object\") {\n errors.push(\"Cấu hình tệp media ('Settings') là bắt buộc.\");\n return { isValid: false, errors };\n }\n\n // Settings.Url: Bắt buộc là URL CDN hợp lệ\n const url = typeof rawSettings.Url === \"string\" ? rawSettings.Url.trim() : (typeof rawSettings.url === \"string\" ? rawSettings.url.trim() : \"\");\n if (!url) {\n errors.push(\"Đường dẫn tệp media ('Settings.Url') là bắt buộc.\");\n } else if (!isValidUrl(url)) {\n errors.push(`Đường dẫn tệp media ('Settings.Url') không hợp lệ: '${url}'. Phải là URL HTTP hoặc HTTPS bắt đầu bằng http:// hoặc https://.`);\n }\n\n // Settings.Width & Settings.Height: Số nguyên dương\n const width = Number(rawSettings.Width ?? rawSettings.width);\n if (!Number.isInteger(width) || width <= 0) {\n errors.push(`Chiều rộng tệp media ('Settings.Width') phải là số nguyên dương (> 0). Hiện tại: ${rawSettings.Width ?? rawSettings.width}`);\n }\n\n const height = Number(rawSettings.Height ?? rawSettings.height);\n if (!Number.isInteger(height) || height <= 0) {\n errors.push(`Chiều cao tệp media ('Settings.Height') phải là số nguyên dương (> 0). Hiện tại: ${rawSettings.Height ?? rawSettings.height}`);\n }\n\n // Nếu là Video (Type = 2): Kiểm tra thời lượng Duration & ThumbUrl\n let duration: number | undefined;\n let thumbUrl: string | undefined;\n\n if (typeVal === 2) {\n const dur = Number(rawSettings.Duration ?? rawSettings.duration);\n if (!isNaN(dur) && dur > 0) {\n if (dur > 600) {\n errors.push(`Thời lượng video ('Settings.Duration') không được vượt quá 600 giây (hiện tại: ${dur}s).`);\n } else {\n duration = dur;\n }\n } else {\n errors.push(\"Với loại media Video (Type = 2), thời lượng video ('Settings.Duration') là bắt buộc và phải là số dương (> 0).\");\n }\n\n const thumb = typeof rawSettings.ThumbUrl === \"string\" ? rawSettings.ThumbUrl.trim() : (typeof rawSettings.thumbUrl === \"string\" ? rawSettings.thumbUrl.trim() : \"\");\n if (thumb) {\n if (!isValidUrl(thumb)) {\n errors.push(`Ảnh thu nhỏ của video ('Settings.ThumbUrl') không hợp lệ: '${thumb}'. Phải là URL HTTP/HTTPS.`);\n } else {\n thumbUrl = thumb;\n }\n }\n }\n\n const cleanData: ZaloAdsMediaSavePayloadDto = {\n Name: name,\n Type: typeVal,\n Settings: {\n Url: url,\n Width: width,\n Height: height,\n ...(duration !== undefined ? { Duration: duration } : {}),\n ...(thumbUrl !== undefined ? { ThumbUrl: thumbUrl } : {}),\n },\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n/**\n * ZaloMediaValidator: Gom nhóm các hàm xác thực cho Thư viện Media\n */\nexport const ZaloMediaValidator = {\n validateSaveMedia: validateSaveMediaRequest,\n};\n"],"mappings":";AA2FO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YAAY,SAAiB,SAAS,KAAK,cAAc,WAAW,eAAwB,MAAM;AAChG,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,cAAc;AACnB,SAAK,eAAe;AAAA,EACtB;AACF;;;ACxDO,IAAM,uBAAiD;AAAA,EAC5D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAaO,IAAM,yBAAN,MAAyD;AAAA,EAC7C,QAAQ,oBAAI,IAAmD;AAAA,EAC/D;AAAA,EAEV,YAAY,UAAyC,CAAC,GAAG;AAC9D,SAAK,cAAc,QAAQ,eAAe;AAAA,EAC5C;AAAA,EAEO,IAAI,YAAoB,QAAiD;AAC9E,UAAM,aAAa,KAAK,MAAM,IAAI,UAAU;AAC5C,QAAI,CAAC,WAAY,QAAO;AAGxB,SAAK,MAAM,OAAO,UAAU;AAC5B,SAAK,MAAM,IAAI,YAAY,UAAU;AAErC,UAAM,UAAU,WAAW,IAAI,MAAM;AACrC,QAAI,CAAC,QAAS,QAAO;AAErB,QAAI,KAAK,IAAI,KAAK,QAAQ,WAAW;AACnC,iBAAW,OAAO,MAAM;AACxB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEO,IACL,YACA,QACA,SACA,YACM;AACN,QAAI,aAAa,KAAK,MAAM,IAAI,UAAU;AAC1C,QAAI,YAAY;AACd,WAAK,MAAM,OAAO,UAAU;AAAA,IAC9B,OAAO;AACL,UAAI,KAAK,MAAM,QAAQ,KAAK,aAAa;AACvC,cAAM,YAAY,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AAC3C,YAAI,cAAc,QAAW;AAC3B,eAAK,MAAM,OAAO,SAAS;AAAA,QAC7B;AAAA,MACF;AACA,mBAAa,oBAAI,IAAsC;AAAA,IACzD;AAEA,UAAM,gBAAmC,aACrC,EAAE,GAAG,SAAS,WAAW,KAAK,IAAI,QAAQ,WAAW,KAAK,IAAI,IAAI,aAAa,GAAI,EAAE,IACrF;AAEJ,eAAW,IAAI,QAAQ,aAAa;AACpC,SAAK,MAAM,IAAI,YAAY,UAAU;AAAA,EACvC;AAAA,EAEO,OAAO,YAAoB,QAA8B;AAC9D,QAAI,CAAC,QAAQ;AACX,WAAK,MAAM,OAAO,UAAU;AAC5B;AAAA,IACF;AACA,UAAM,aAAa,KAAK,MAAM,IAAI,UAAU;AAC5C,QAAI,YAAY;AACd,iBAAW,OAAO,MAAM;AACxB,UAAI,WAAW,SAAS,GAAG;AACzB,aAAK,MAAM,OAAO,UAAU;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAAA,EAEO,OAAO,YAAuE;AACnF,UAAM,aAAa,KAAK,MAAM,IAAI,UAAU;AAC5C,QAAI,CAAC,WAAY,QAAO,CAAC;AACzB,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,SAA4D,CAAC;AACnE,eAAW,CAAC,QAAQ,OAAO,KAAK,WAAW,QAAQ,GAAG;AACpD,UAAI,MAAM,QAAQ,WAAW;AAC3B,eAAO,MAAM,IAAI;AAAA,MACnB,OAAO;AACL,mBAAW,OAAO,MAAM;AAAA,MAC1B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGO,WAAiB;AACtB,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA,EAGA,IAAW,OAAe;AACxB,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AAqBO,IAAM,wBAAN,MAAwD;AAAA,EAItD,YACY,OACjB,UAAwC,CAAC,GACzC;AAFiB;AAGjB,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,oBAAoB,QAAQ,qBAAqB,KAAK;AAAA,EAC7D;AAAA,EATiB;AAAA,EACA;AAAA,EAUT,gBAAgB,YAAoB,QAA+B;AACzE,WAAO,GAAG,KAAK,SAAS,YAAY,UAAU,IAAI,MAAM;AAAA,EAC1D;AAAA,EAEQ,aAAa,YAAoB,QAA+B;AACtE,WAAO,GAAG,KAAK,SAAS,SAAS,UAAU,IAAI,MAAM;AAAA,EACvD;AAAA,EAEA,MAAa,IAAI,YAAoB,QAA0D;AAC7F,UAAM,MAAM,KAAK,gBAAgB,YAAY,MAAM;AACnD,UAAM,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG;AACpC,QAAI,CAAC,IAAK,QAAO;AAEjB,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAI,CAAC,UAAU,OAAO,WAAW,YAAY,KAAK,IAAI,KAAK,OAAO,WAAW;AAC3E,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAa,IACX,YACA,QACA,SACA,YACe;AACf,UAAM,MAAM,KAAK,gBAAgB,YAAY,MAAM;AACnD,UAAM,mBAAmB,KAAK,OAAO,QAAQ,YAAY,KAAK,IAAI,KAAK,GAAI;AAC3E,UAAM,eAAe,KAAK,IAAI,GAAG,eAAe,mBAAmB,IAAI,mBAAmB,KAAK,kBAAkB;AACjH,UAAM,aAAa,KAAK,UAAU,OAAO;AAEzC,QAAI,OAAO,KAAK,MAAM,kBAAkB,YAAY;AAClD,YAAM,KAAK,MAAM,cAAc,KAAK,YAAY,YAAY;AAC5D;AAAA,IACF;AACA,QAAI,OAAO,KAAK,MAAM,UAAU,YAAY;AAC1C,YAAM,KAAK,MAAM,MAAM,KAAK,cAAc,UAAU;AACpD;AAAA,IACF;AACA,QAAI,OAAO,KAAK,MAAM,QAAQ,YAAY;AACxC,YAAM,KAAK,MAAM,IAAI,KAAK,YAAY,MAAM,YAAY;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,MAAa,OAAO,YAAoB,QAAuC;AAC7E,QAAI,QAAQ;AACV,YAAM,KAAK,MAAM,IAAI,KAAK,gBAAgB,YAAY,MAAM,CAAC;AAC7D;AAAA,IACF;AACA,UAAM,OAAO,qBAAqB,IAAI,OAAK,KAAK,gBAAgB,YAAY,CAAC,CAAC;AAC9E,UAAM,QAAQ,IAAI,KAAK,IAAI,OAAK,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC;AAAA,EACpD;AAAA,EAEA,MAAa,OAAO,YAAgF;AAClG,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,qBAAqB,IAAI,OAAM,WAAU;AACvC,cAAM,UAAU,MAAM,KAAK,IAAI,YAAY,MAAM;AACjD,eAAO,CAAC,QAAQ,OAAO;AAAA,MACzB,CAAC;AAAA,IACH;AACA,UAAM,SAA4D,CAAC;AACnE,eAAW,CAAC,QAAQ,OAAO,KAAK,SAAS;AACvC,UAAI,SAAS;AACX,eAAO,MAAM,IAAI;AAAA,MACnB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,YACX,YACA,QACA,aAAa,IACK;AAClB,UAAM,UAAU,KAAK,aAAa,YAAY,MAAM;AACpD,UAAM,YAAY,GAAG,KAAK,IAAI,CAAC;AAC/B,QAAI,OAAO,KAAK,MAAM,UAAU,YAAY;AAC1C,aAAO,QAAQ,MAAM,KAAK,MAAM,MAAM,SAAS,WAAW,UAAU,CAAC;AAAA,IACvE;AACA,QAAI,OAAO,KAAK,MAAM,QAAQ,YAAY;AACxC,YAAM,MAAM,MAAM,KAAK,MAAM,IAAI,SAAS,WAAW,MAAM,YAAY,IAAI;AAC3E,aAAO,QAAQ,QAAQ,QAAQ;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,YAAY,YAAoB,QAAsC;AACjF,UAAM,UAAU,KAAK,aAAa,YAAY,MAAM;AACpD,QAAI;AACF,YAAM,KAAK,MAAM,IAAI,OAAO;AAAA,IAC9B,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAgBO,IAAM,yBAAN,MAAyD;AAAA,EAC9C;AAAA,EACA;AAAA,EACC;AAAA,EAEV,YACL,OACA,UAAyC,CAAC,GAC1C;AACA,SAAK,WAAW,IAAI,uBAAuB,EAAE,aAAa,QAAQ,YAAY,CAAC;AAC/E,SAAK,UAAU,IAAI,sBAAsB,OAAO;AAAA,MAC9C,WAAW,QAAQ;AAAA,MACnB,mBAAmB,QAAQ;AAAA,IAC7B,CAAC;AACD,SAAK,kBAAkB,QAAQ,mBAAmB;AAAA,EACpD;AAAA,EAEA,MAAa,IAAI,YAAoB,QAA0D;AAC7F,UAAM,SAAS,KAAK,SAAS,IAAI,YAAY,MAAM;AACnD,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,MAAM,KAAK,QAAQ,IAAI,YAAY,MAAM;AACxD,QAAI,QAAQ;AACV,WAAK,SAAS,IAAI,YAAY,QAAQ,QAAQ,KAAK,eAAe;AAClE,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,IACX,YACA,QACA,SACA,YACe;AACf,SAAK,SAAS,IAAI,YAAY,QAAQ,SAAS,cAAc,KAAK,eAAe;AACjF,UAAM,KAAK,QAAQ,IAAI,YAAY,QAAQ,SAAS,UAAU;AAAA,EAChE;AAAA,EAEA,MAAa,OAAO,YAAoB,QAAuC;AAC7E,SAAK,SAAS,OAAO,YAAY,MAAM;AACvC,UAAM,KAAK,QAAQ,OAAO,YAAY,MAAM;AAAA,EAC9C;AAAA,EAEA,MAAa,OAAO,YAAgF;AAClG,UAAM,SAAS,MAAM,KAAK,QAAQ,OAAO,UAAU;AACnD,eAAW,CAAC,QAAQ,OAAO,KAAK,OAAO,QAAQ,MAAM,GAA2C;AAC9F,UAAI,SAAS;AACX,aAAK,SAAS,IAAI,YAAY,QAAQ,SAAS,KAAK,eAAe;AAAA,MACrE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEO,YAAY,YAAoB,QAAuB,aAAa,IAAsB;AAC/F,WAAO,KAAK,QAAQ,YAAY,YAAY,QAAQ,UAAU;AAAA,EAChE;AAAA,EAEO,YAAY,YAAoB,QAAsC;AAC3E,WAAO,KAAK,QAAQ,YAAY,YAAY,MAAM;AAAA,EACpD;AACF;AAOO,IAAM,kCAAkC,IAAI,uBAAuB;AAAA,EACxE,aAAa;AACf,CAAC;;;ACxOD,IAAM,qBACJ;AAEF,IAAM,yBAAyB,KAAK,KAAK;AAKlC,SAAS,wBAAwB,OAAuB;AAC7D,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAQ,MAAM,WAAW,CAAC;AAC1B,WAAO,KAAK,KAAK,MAAM,QAAU;AAAA,EACnC;AACA,UAAQ,SAAS,GAAG,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAClD;AAMO,SAAS,0BAA0B,OAAuB;AAC/D,QAAM,QAAQ,MAAM,KAAK,EAAE,MAAM,GAAG;AACpC,QAAM,eAAe,MAAM,UAAU,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI;AAC9E,SAAO,QAAQ,YAAY,IAAI,wBAAwB,MAAM,KAAK,CAAC,CAAC;AACtE;AAKO,SAAS,qBAAqB,mBAA+D;AAClG,MAAI;AACF,UAAM,QAAQ,kBAAkB,QAAQ,kBAAkB,EAAE,EAAE,KAAK;AACnE,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,SAAS,UAAU,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AAC7D,UAAM,SAAS,OAAO,OAAO,OAAO,UAAW,IAAK,OAAO,SAAS,KAAM,GAAI,GAAG;AACjF,UAAM,YAAY,WAAW,KAAK,MAAM;AACxC,UAAM,QAAQ,WAAW,KAAK,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,CAAC;AACjE,UAAM,UAAU,IAAI,YAAY,OAAO,EAAE,OAAO,KAAK;AACrD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,qBAAqB,UAGnC;AACA,QAAM,UAAU,SAAS,KAAK;AAC9B,QAAM,mBAA2C,CAAC;AAElD,MAAI,CAAC,QAAQ,SAAS,GAAG,KAAK,CAAC,QAAQ,SAAS,GAAG,GAAG;AACpD,WAAO,EAAE,OAAO,SAAS,iBAAiB;AAAA,EAC5C;AAEA,aAAW,QAAQ,QAAQ,MAAM,GAAG,GAAG;AACrC,UAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,QAAI,QAAQ,GAAG;AACb,YAAM,IAAI,KAAK,MAAM,GAAG,KAAK,EAAE,KAAK;AACpC,YAAM,IAAI,KAAK,MAAM,QAAQ,CAAC,EAAE,KAAK;AACrC,UAAI,KAAK,EAAG,kBAAiB,CAAC,IAAI;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,QAAQ,iBAAiB,OAAO,KAAK,QAAQ,QAAQ,YAAY,EAAE,EAAE,KAAK;AAChF,SAAO,EAAE,OAAO,iBAAiB;AACnC;AASO,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACS;AAAA,EACT;AAAA,EACS;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAKA,WAAW,oBAAI,IAAuC;AAAA,EACtD,qBAAqB,oBAAI,IAAgD;AAAA,EAEnF,YAAY,SAAsC;AACvD,UAAM,oBACJ,OAAO,YAAY,WAAW,EAAE,OAAO,QAAQ,IAAI;AAErD,SAAK,YAAY,kBAAkB,SAAS,WAAW;AACvD,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,yEAAyE;AAAA,IAC3F;AAEA,SAAK,qBAAqB,kBAAkB,iBAAiB,kBAAkB;AAC/E,SAAK,eAAe,kBAAkB;AACtC,SAAK,eAAe,EAAE,GAAI,kBAAkB,gBAAgB,CAAC,EAAG;AAEhE,QAAI,kBAAkB,OAAO;AAC3B,YAAM,SAAS,qBAAqB,kBAAkB,KAAK;AAC3D,WAAK,QAAQ,OAAO;AACpB,iBAAW,WAAW,CAAC,YAAY,aAAa,QAAQ,aAAa,GAAG;AACtE,YAAI,OAAO,iBAAiB,OAAO,KAAK,CAAC,KAAK,aAAa,OAAO,GAAG;AACnE,eAAK,aAAa,OAAO,IAAI,OAAO,iBAAiB,OAAO;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAEA,SAAK,aAAa,kBAAkB;AACpC,SAAK,eAAe,kBAAkB,gBAAgB;AACtD,SAAK,YAAY,kBAAkB,aAAa;AAChD,SAAK,qBAAqB,kBAAkB;AAE5C,QAAI,kBAAkB,cAAc;AAClC,WAAK,eAAe,kBAAkB;AAAA,IACxC,WAAW,kBAAkB,OAAO;AAClC,WAAK,eAAe,IAAI,uBAAuB,kBAAkB,OAAO;AAAA,QACtE,WAAW,kBAAkB;AAAA,MAC/B,CAAC;AAAA,IACH,OAAO;AACL,WAAK,eAAe;AAAA,IACtB;AAEA,QAAI,kBAAkB,iBAAiB;AACrC,iBAAW,CAAC,QAAQ,OAAO,KAAK,OAAO,QAAQ,kBAAkB,eAAe,GAAG;AACjF,YAAI,QAAS,MAAK,SAAS,IAAI,QAA0B,OAAO;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAwB;AAC7B,QAAI,KAAK,oBAAoB;AAC3B,aAAO,KAAK;AAAA,IACd;AACA,QAAI,KAAK,OAAO;AACd,aAAO,0BAA0B,KAAK,KAAK;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,kBAAoC;AACzC,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,kBAAgD;AACrD,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,gBAAgB,OAAgC;AACrD,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKO,SAAS,YAA0B;AACxC,UAAM,SAAS,qBAAqB,UAAU;AAC9C,UAAM,YAAY,KAAK;AACvB,SAAK,QAAQ,OAAO;AACpB,eAAW,WAAW,CAAC,YAAY,aAAa,QAAQ,aAAa,GAAG;AACtE,UAAI,OAAO,iBAAiB,OAAO,GAAG;AACpC,aAAK,aAAa,OAAO,IAAI,OAAO,iBAAiB,OAAO;AAAA,MAC9D;AAAA,IACF;AACA,QAAI,cAAc,KAAK,OAAO;AAC5B,WAAK,cAAc;AAAA,IACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAiB,cAA4B;AAClD,UAAM,SAAS,KAAK,gBAAgB,YAAY;AAChD,SAAK,SAAS,OAAO,MAAM;AAC3B,UAAM,aAAa,KAAK,cAAc;AACtC,SAAK,QAAQ,QAAQ,KAAK,aAAa,OAAO,YAAY,MAAM,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,EAC1F;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,sBAAsB,cAAqC;AACtE,UAAM,SAAS,KAAK,gBAAgB,YAAY;AAChD,SAAK,SAAS,OAAO,MAAM;AAC3B,UAAM,aAAa,KAAK,cAAc;AACtC,UAAM,KAAK,aAAa,OAAO,YAAY,MAAM;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAsB;AAC3B,SAAK,SAAS,MAAM;AACpB,UAAM,aAAa,KAAK,cAAc;AACtC,SAAK,QAAQ,QAAQ,KAAK,aAAa,OAAO,UAAU,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,qBAAoC;AAC/C,SAAK,SAAS,MAAM;AACpB,UAAM,aAAa,KAAK,cAAc;AACtC,UAAM,KAAK,aAAa,OAAO,UAAU;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAqE;AAC1E,UAAM,SAA6D,CAAC;AACpE,eAAW,CAAC,QAAQ,OAAO,KAAK,KAAK,SAAS,QAAQ,GAAG;AACvD,aAAO,MAAM,IAAI;AAAA,IACnB;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,eAAe,UAAoE;AACxF,UAAM,aAAa,KAAK,cAAc;AACtC,eAAW,CAAC,QAAQ,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACxD,UAAI,SAAS;AACX,aAAK,SAAS,IAAI,QAA0B,OAAO;AACnD,aAAK,QAAQ;AAAA,UACX,KAAK,aAAa,IAAI,YAAY,QAA0B,OAAO;AAAA,QACrE,EAAE,MAAM,MAAM,MAAS;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,WAAW,cAAsB,eAAe,OAAmC;AAC9F,UAAM,SAAS,KAAK,gBAAgB,YAAY;AAChD,UAAM,QAAQ,MAAM,KAAK,aAAa;AACtC,UAAM,qBAAqB,wBAAwB,KAAK;AACxD,UAAM,aAAa,KAAK,cAAc;AAEtC,QAAI,CAAC,cAAc;AACjB,YAAM,eAAe,KAAK,SAAS,IAAI,MAAM;AAC7C,UAAI,gBAAgB,KAAK,eAAe,cAAc,kBAAkB,GAAG;AACzE,eAAO;AAAA,MACT;AAEA,YAAM,gBAAgB,MAAM,KAAK,aAAa,IAAI,YAAY,MAAM;AACpE,UAAI,iBAAiB,KAAK,eAAe,eAAe,kBAAkB,GAAG;AAC3E,aAAK,SAAS,IAAI,QAAQ,aAAa;AACvC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,KAAK,mBAAmB,QAAQ,YAAY;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,gBACX,UAA4B,CAAC,eAAe,oBAAoB,kBAAkB,GAClF,eAAe,MAC6B;AAC5C,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,QAAQ,IAAI,OAAO,MAAM,CAAC,GAAG,MAAM,KAAK,mBAAmB,GAAG,YAAY,CAAC,CAAU;AAAA,IACvF;AACA,WAAO,OAAO,YAAY,OAAO;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,mBACX,cACA,eAAe,OACa;AAC5B,UAAM,SAAS,KAAK,gBAAgB,YAAY;AAChD,UAAM,QAAQ,MAAM,KAAK,aAAa;AACtC,UAAM,qBAAqB,wBAAwB,KAAK;AACxD,UAAM,aAAa,KAAK,cAAc;AAEtC,QAAI,CAAC,cAAc;AACjB,YAAM,WAAW,KAAK,SAAS,IAAI,MAAM;AACzC,UAAI,YAAY,KAAK,eAAe,UAAU,kBAAkB,GAAG;AACjE,eAAO;AAAA,MACT;AACA,YAAM,YAAY,MAAM,KAAK,aAAa,IAAI,YAAY,MAAM;AAChE,UAAI,aAAa,KAAK,eAAe,WAAW,kBAAkB,GAAG;AACnE,aAAK,SAAS,IAAI,QAAQ,SAAS;AACnC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,mBAAmB,IAAI,MAAM;AACnD,QAAI,SAAU,QAAO;AAErB,UAAM,UAAU,KAAK;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,QAAQ,MAAM;AACd,WAAK,mBAAmB,OAAO,MAAM;AAAA,IACvC,CAAC;AAED,SAAK,mBAAmB,IAAI,QAAQ,OAAO;AAC3C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,eACX,aACA,eAAe,OACkB;AACjC,UAAM,SAAS,KAAK,2BAA2B,WAAW;AAC1D,UAAM,UAAU,MAAM,KAAK,WAAW,QAAQ,YAAY;AAC1D,WAAO;AAAA,MACL,GAAG,QAAQ;AAAA,MACX,QAAQ,KAAK,mBAAmB,QAAQ,OAAO;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,WACX,aACA,eAAe,OACkB;AACjC,UAAM,SAAS,KAAK,2BAA2B,WAAW;AAC1D,UAAM,UAAU,MAAM,KAAK,WAAW,QAAQ,YAAY;AAC1D,WAAO,EAAE,GAAG,QAAQ,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKO,YAAyB;AAC9B,WAAO;AAAA,MACL,YAAY,OAAO,YAAgC;AACjD,cAAM,UAAU,MAAM,KAAK,WAAW,QAAQ,MAAM,KAAK;AACzD,eAAO,EAAE,GAAG,QAAQ,QAAQ;AAAA,MAC9B;AAAA,MACA,YAAY,OAAO,YAAgC;AACjD,cAAM,UAAU,MAAM,KAAK,WAAW,QAAQ,MAAM,KAAK;AACzD,eAAO,EAAE,GAAG,QAAQ,QAAQ;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,QAAQ,KAAa,OAAoB,CAAC,GAAsB;AAC3E,UAAM,SAAS,KAAK,2BAA2B,GAAG;AAClD,UAAM,eAAe,OAAO,iBAA6C;AACvE,YAAM,cAAc,MAAM,KAAK,eAAe,QAAQ,YAAY;AAClE,YAAM,gBAAgB,IAAI,QAAQ,WAAW;AAC7C,UAAI,KAAK,SAAS;AAChB,cAAM,gBAAgB,IAAI,QAAQ,KAAK,OAAO;AAC9C,sBAAc,QAAQ,CAAC,OAAO,QAAQ,cAAc,IAAI,KAAK,KAAK,CAAC;AAAA,MACrE;AACA,aAAO,KAAK,UAAU,KAAK;AAAA,QACzB,GAAG;AAAA,QACH,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,MAAM,aAAa,KAAK;AACzC,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,KAAK,sBAAsB,MAAM;AACvC,aAAO,aAAa,IAAI;AAAA,IAC1B;AAGA,QAAI,WAAW,oBAAoB;AACjC,YAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,UAAI,YAAY,SAAS,MAAM,GAAG;AAChC,cAAM,SAAS,SAAS,MAAM;AAC9B,cAAM,OAAQ,MAAM,OAAO,KAAK,EAAE,MAAM,MAAM,IAAI;AAClD,YAAI,QAAQ,KAAK,SAAS,KAAK;AAC7B,gBAAM,KAAK,sBAAsB,MAAM;AACvC,iBAAO,aAAa,IAAI;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,SAA4B,oBAAqC;AACtF,QAAI,KAAK,IAAI,KAAK,QAAQ,WAAW;AACnC,aAAO;AAAA,IACT;AACA,QAAI,QAAQ,oBAAoB,QAAQ,qBAAqB,oBAAoB;AAC/E,aAAO;AAAA,IACT;AAGA,QACE,QAAQ,WAAW,iBACnB,KAAK,cAAc,YACnB,OAAO,KAAK,aAAa,QAAQ,MAAM,OACvC,CAAC,KAAK,aAAa,QACnB;AACA,YAAM,mBAAmB,OAAO,KAAK,aAAa,QAAQ;AAC1D,YAAM,iBAAiB,OAAO,QAAQ,oBAAoB,MAAM,MAAM,EAAE;AACxE,UAAI,kBAAkB,mBAAmB,kBAAkB;AACzD,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,eAAgC;AAC5C,QAAI,KAAK,YAAY;AACnB,YAAM,aAAa,MAAM,KAAK,WAAW;AACzC,UAAI,YAAY;AACd,cAAM,SAAS,qBAAqB,UAAU;AAC9C,aAAK,QAAQ,OAAO;AACpB,mBAAW,WAAW,CAAC,YAAY,aAAa,QAAQ,aAAa,GAAG;AACtE,cAAI,OAAO,iBAAiB,OAAO,KAAK,CAAC,KAAK,aAAa,OAAO,GAAG;AACnE,iBAAK,aAAa,OAAO,IAAI,OAAO,iBAAiB,OAAO;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,KAAK,OAAO;AACf,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,oCACZ,YACA,QACA,OACA,oBACA,cAC4B;AAC5B,QAAI,KAAK,aAAa,eAAe,KAAK,aAAa,aAAa;AAClE,YAAM,eAAe,MAAM,KAAK,aAC7B,YAAY,YAAY,QAAQ,EAAE,EAClC,MAAM,MAAM,IAAI;AAEnB,UAAI,CAAC,gBAAgB,CAAC,cAAc;AAElC,iBAAS,UAAU,GAAG,UAAU,GAAG,WAAW;AAC5C,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG,CAAC;AACvD,gBAAM,gBAAgB,MAAM,KAAK,aAAa,IAAI,YAAY,MAAM;AACpE,cAAI,iBAAiB,KAAK,eAAe,eAAe,kBAAkB,GAAG;AAC3E,iBAAK,SAAS,IAAI,QAAQ,aAAa;AACvC,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,UAAI;AACF,eAAO,MAAM,KAAK,iBAAiB,YAAY,QAAQ,OAAO,kBAAkB;AAAA,MAClF,UAAE;AACA,YAAI,cAAc;AAChB,gBAAM,KAAK,aAAa,YAAY,YAAY,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,QAC/E;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK,iBAAiB,YAAY,QAAQ,OAAO,kBAAkB;AAAA,EAC5E;AAAA,EAEA,MAAc,iBACZ,YACA,QACA,OACA,kBAC4B;AAC5B,UAAM,UAAkC;AAAA,MACtC,GAAG,KAAK;AAAA,MACR;AAAA,IACF;AAEA,UAAM,UAAkC;AAAA,MACtC,cAAc,KAAK;AAAA,IACrB;AAEA,QAAI;AACJ,QAAI;AAEJ,QAAI,WAAW,eAAe;AAC5B,YAAM,sBAAsB,KAAK,cAAc,gBAAgB,QAAQ,cAAc;AAErF,UAAI,CAAC,qBAAqB;AACxB,cAAM,KAAK,qBAAqB,iCAAiC,SAAS,IAAI;AAAA,MAChF;AAEA,YAAM,YAAY,MAAM,KAAK,UAAU,kCAAkC;AAAA,QACvE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,QAAQ,KAAK,mBAAmB,OAAO;AAAA,UACvC,cAAc,KAAK;AAAA,UACnB,QAAQ;AAAA,QACV;AAAA,MACF,CAAC;AACD,WAAK,gBAAgB,WAAW,OAAO;AAEvC,UAAI,qBAAqB;AACvB,gBAAQ,cAAc,IAAI;AAAA,MAC5B;AACA,YAAM,aAAc,MAAM,UAAU,KAAK,EAAE,MAAM,MAAM,IAAI;AAI3D,UAAI,YAAY,MAAM;AACpB,qBAAa,WAAW;AAAA,MAC1B;AAGA,YAAM,kBAAkB;AAAA,QACtB,qBAAqB,QAAQ,cAAc,KAAK,EAAE,GAAG,MAAM,MAAM;AAAA,MACnE;AACA,YAAM,sBAAsB;AAAA,QAC1B,KAAK,cAAc,YACnB,OAAO,KAAK,aAAa,QAAQ,MAAM,OACvC,CAAC,KAAK,aAAa,WAClB,CAAC,uBAAwB,mBAAmB,oBAAoB,OAAO,KAAK,aAAa,QAAQ;AAAA,MACpG;AAEA,UAAI,qBAAqB;AACvB,cAAM,cAAc,OAAO,KAAK,aAAc,QAAQ;AACtD,cAAM,aAAuB,CAAC;AAC9B,YAAI,KAAK,aAAc,gBAAgB,YAAY;AACjD,qBAAW,KAAK,sDAAsD,WAAW,EAAE;AAAA,QACrF,WACE,KAAK,aAAc,gBAAgB,mBACnC,KAAK,aAAc,gBAAgB,YACnC,KAAK,aAAc,gBAAgB,sBACnC;AACA,qBAAW,KAAK,oDAAoD,WAAW,EAAE;AACjF,qBAAW,KAAK,sDAAsD,WAAW,EAAE;AAAA,QACrF,OAAO;AACL,qBAAW,KAAK,oDAAoD,WAAW,EAAE;AACjF,qBAAW,KAAK,sDAAsD,WAAW,EAAE;AAAA,QACrF;AAEA,mBAAW,aAAa,YAAY;AAClC,cAAI;AACF,kBAAM,YAAY,MAAM,KAAK,UAAU,WAAW;AAAA,cAChD,QAAQ;AAAA,cACR,SAAS;AAAA,gBACP,QAAQ,KAAK,mBAAmB,OAAO;AAAA,gBACvC,cAAc,KAAK;AAAA,gBACnB,QAAQ;AAAA,cACV;AAAA,cACA,UAAU;AAAA,YACZ,CAAC;AACD,iBAAK,gBAAgB,WAAW,OAAO;AACvC,kBAAM,WAAW,UAAU,QAAQ,IAAI,UAAU,KAAK;AACtD,gBAAI,YAAY,CAAC,SAAS,SAAS,gBAAgB,GAAG;AACpD,oBAAM,oBAAoB,MAAM,KAAK,UAAU,kCAAkC;AAAA,gBAC/E,QAAQ;AAAA,gBACR,SAAS;AAAA,kBACP,QAAQ,KAAK,mBAAmB,OAAO;AAAA,kBACvC,cAAc,KAAK;AAAA,kBACnB,QAAQ;AAAA,gBACV;AAAA,cACF,CAAC;AACD,mBAAK,gBAAgB,mBAAmB,OAAO;AAC/C,oBAAM,eAAgB,MAAM,kBAAkB,KAAK,EAAE,MAAM,MAAM,IAAI;AAIrE,kBAAI,cAAc,MAAM;AACtB,6BAAa,aAAa;AAAA,cAC5B;AACA;AAAA,YACF;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,cAAc,YAAY,OAAO,KAAK,aAAa,QAAQ,MAAM,KAAK;AAC7E,gBAAQ,aAAa,IAAI,OAAO,KAAK,aAAa,QAAQ;AAAA,MAC5D,WAAW,KAAK,cAAc,aAAa;AACzC,gBAAQ,aAAa,IAAI,OAAO,KAAK,aAAa,WAAW;AAAA,MAC/D,WAAW,YAAY,IAAI;AACzB,gBAAQ,aAAa,IAAI,OAAO,WAAW,EAAE;AAAA,MAC/C;AAAA,IACF,WAAW,WAAW,oBAAoB;AACxC,YAAM,KAAK,qBAAqB,sCAAsC,SAAS,KAAK;AAAA,IACtF,WAAW,WAAW,oBAAoB;AACxC,YAAM,WACJ,iEACA,mBAAmB,wCAAwC;AAC7D,YAAM,KAAK,qBAAqB,UAAU,SAAS,KAAK;AAExD,YAAM,aAAa,MAAM,KAAK;AAAA,QAC5B;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,QAAQ,KAAK,mBAAmB,OAAO;AAAA,YACvC,cAAc,KAAK;AAAA,YACnB,QAAQ;AAAA,UACV;AAAA,QACF;AAAA,MACF;AACA,WAAK,gBAAgB,YAAY,OAAO;AACxC,YAAM,cAAe,MAAM,WAAW,KAAK,EAAE,MAAM,MAAM,IAAI;AAI7D,UAAI,aAAa,MAAM;AACrB,sBAAc,YAAY;AAAA,MAC5B;AAAA,IACF,WAAW,WAAW,uBAAuB;AAC3C,YAAM,aAAa,MAAM,KAAK,qBAAqB,gCAAgC,SAAS,KAAK;AACjG,UAAI,YAAY;AACd,cAAM,OAAO,MAAM,WAAW,KAAK,EAAE,MAAM,MAAM,EAAE;AACnD,cAAM,YAAY,KAAK,MAAM,mCAAmC;AAChE,YAAI,YAAY,CAAC,GAAG;AAClB,kBAAQ,YAAY,IAAI,UAAU,CAAC;AAAA,QACrC;AAAA,MACF;AACA,cAAQ,QAAQ,IAAI;AACpB,cAAQ,SAAS,IAAI;AAAA,IACvB,WAAW,WAAW,wBAAwB,WAAW,uBAAuB;AAC9E,cAAQ,QAAQ,IAAI;AACpB,cAAQ,SAAS,IAAI;AAAA,IACvB;AAEA,UAAM,YAAY,QAAQ,YAAY,KAAK,QAAQ,YAAY;AAC/D,QAAI,QAAQ,YAAY,GAAG;AACzB,cAAQ,cAAc,IAAI,QAAQ,YAAY;AAAA,IAChD;AAEA,UAAM,cAAc,aAAa;AACjC,QAAI,aAAa;AACf,cAAQ,eAAe,IAAI;AAAA,IAC7B;AAEA,UAAM,qBAAqB,QAAQ,cAAc,IAC7C,qBAAqB,QAAQ,cAAc,CAAC,IAC5C;AAEJ,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,WAAW,oBAAoB,MAAM,mBAAmB,MAAM,MAAO,MAAS;AACpF,UAAM,YACJ,YAAY,WAAW,MAAM,KAAK,IAAI,UAAU,MAAM,KAAK,YAAY,IAAI,MAAM,KAAK;AAExF,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX;AAAA,IACF;AAEA,SAAK,SAAS,IAAI,QAAQ,OAAO;AACjC,UAAM,KAAK,aAAa,IAAI,YAAY,QAAQ,OAAO;AAEvD,QAAI,KAAK,oBAAoB;AAC3B,YAAM,KAAK,mBAAmB,QAAQ,OAAO;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,qBACZ,UACA,SACA,oBAC+B;AAC/B,QAAI,aAAa;AACjB,QAAI;AACJ,aAAS,OAAO,GAAG,QAAQ,GAAG,QAAQ;AACpC,YAAM,MAAM,MAAM,KAAK,UAAU,YAAY;AAAA,QAC3C,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,QAAQ,KAAK,mBAAmB,OAAO;AAAA,UACvC,cAAc,KAAK;AAAA,UACnB,QAAQ;AAAA,QACV;AAAA,QACA,UAAU;AAAA,MACZ,CAAC;AACD,qBAAe;AAEf,WAAK,gBAAgB,KAAK,OAAO;AAEjC,UAAI,WAAW,IAAI,QAAQ,IAAI,UAAU;AAKzC,UACE,CAAC,YACD,IAAI,WAAW,OACf,WAAW,SAAS,iCAAiC,GACrD;AACA,cAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,cAAM,YAAY,KAAK,MAAM,uCAAuC;AACpE,YAAI,aAAa,KAAK,SAAS,kBAAkB,GAAG;AAClD,gBAAM,aAAa,KAAK,MAAM,kCAAkC;AAChE,gBAAM,iBAAiB,IAAI,IAAI,UAAU;AACzC,gBAAM,cAAc,IAAI,gBAAgB;AAAA,YACtC,YAAY,UAAU,CAAC;AAAA,YACvB,QAAQ,eAAe,aAAa,IAAI,QAAQ,KAAK;AAAA,YACrD,cAAc,eAAe,aAAa,IAAI,cAAc,KAAK;AAAA,YACjE,SAAS;AAAA,YACT,UAAU;AAAA,YACV,UAAU;AAAA,YACV,SAAS;AAAA,YACT,KAAK;AAAA,YACL,KAAK;AAAA,YACL,kBAAkB;AAAA,YAClB,OAAO,aAAa,WAAW,CAAC,IAAI,eAAe,aAAa,IAAI,OAAO,KAAK;AAAA,YAChF,UAAU;AAAA,YACV,aAAa;AAAA,UACf,CAAC;AAED,gBAAM,aAAa,MAAM,KAAK,UAAU,YAAY;AAAA,YAClD,QAAQ;AAAA,YACR,SAAS;AAAA,cACP,QAAQ,KAAK,mBAAmB,OAAO;AAAA,cACvC,cAAc,KAAK;AAAA,cACnB,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,SAAS;AAAA,YACX;AAAA,YACA,MAAM,YAAY,SAAS;AAAA,YAC3B,UAAU;AAAA,UACZ,CAAC;AACD,yBAAe;AAEf,eAAK,gBAAgB,YAAY,OAAO;AACxC,qBAAW,WAAW,QAAQ,IAAI,UAAU;AAC5C,cAAI,CAAC,YAAY,WAAW,SAAS,OAAO,WAAW,UAAU,KAAK;AACpE;AAAA,UACF;AAAA,QACF,OAAO;AACL;AAAA,QACF;AAAA,MACF,WAAW,CAAC,YAAY,IAAI,SAAS,OAAO,IAAI,UAAU,KAAK;AAC7D;AAAA,MACF;AAEA,UACE,sBACA,SAAS,SAAS,mBAAmB,KACrC,SAAS,SAAS,qBAAqB,GACvC;AACA,mBAAW,SACR,QAAQ,wBAAwB,EAAE,EAClC,QAAQ,wBAAwB,EAAE,EAClC,QAAQ,wBAAwB,GAAG;AAAA,MACxC;AAEA,UAAI,SAAS,WAAW,4BAA4B,GAAG;AACrD,mBAAW,SAAS,QAAQ,cAAc,UAAU;AAAA,MACtD;AAEA,mBAAa,SAAS,WAAW,MAAM,IACnC,WACA,IAAI,IAAI,UAAU,UAAU,EAAE,SAAS;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,KAAe,QAAsC;AAC3E,UAAM,uBAAuB,IAAI;AAGjC,UAAM,gBACJ,OAAO,qBAAqB,iBAAiB,aACzC,qBAAqB,aAAa,IAClC,IAAI,QAAQ,IAAI,YAAY,IAC1B,CAAC,IAAI,QAAQ,IAAI,YAAY,CAAW,IACxC,CAAC;AAET,eAAW,OAAO,eAAe;AAC/B,YAAM,CAAC,SAAS,IAAI,IAAI,MAAM,GAAG;AACjC,YAAM,QAAQ,UAAU,QAAQ,GAAG;AACnC,UAAI,QAAQ,GAAG;AACb,cAAM,MAAM,UAAU,MAAM,GAAG,KAAK,EAAE,KAAK;AAC3C,cAAM,MAAM,UAAU,MAAM,QAAQ,CAAC,EAAE,KAAK;AAE5C,YAAI,KAAK;AACP,iBAAO,GAAG,IAAI;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,mBAAmB,SAAyC;AAClE,WAAO,OAAO,QAAQ,OAAO,EAC1B,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,UAAa,MAAM,EAAE,EAC7C,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAC3B,KAAK,IAAI;AAAA,EACd;AAAA,EAEQ,2BAA2B,aAAqC;AACtE,QAAI,YAAY,WAAW,SAAS,KAAK,YAAY,WAAW,UAAU,GAAG;AAC3E,aAAO,KAAK,gBAAgB,IAAI,IAAI,WAAW,EAAE,QAAQ;AAAA,IAC3D;AACA,WAAO,KAAK,gBAAgB,WAAW;AAAA,EACzC;AAAA,EAEQ,gBAAgB,MAA8B;AACpD,UAAM,QAAQ,KAAK,YAAY,EAAE,KAAK,EAAE,QAAQ,SAAS,EAAE;AAC3D,YAAQ,OAAO;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AACF;AAKO,SAAS,kBAAkB,SAAmD;AACnF,QAAM,UAAU,IAAI,gBAAgB,OAAO;AAC3C,SAAO,QAAQ,UAAU;AAC3B;;;AC/9BA,IAAM,oBAAoB;AAAA,EACxB,KAAK;AAAA,EACL,OAAO;AAAA,EACP,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,YAAY;AACd;AAEO,IAAM,oBAAN,MAAwB;AAAA,EACZ;AAAA,EACA;AAAA,EACT;AAAA,EACS,aAAa,oBAAI,IAAyB;AAAA,EACnD;AAAA,EACS;AAAA,EACV;AAAA,EAEP,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,YAAY,QAAQ,SAAS,WAAW;AAC7C,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,yEAAyE;AAC9G,SAAK,WAAW,EAAE,GAAG,mBAAmB,GAAI,QAAQ,YAAY,CAAC,EAAG;AACpE,SAAK,iBAAiB,QAAQ,kBAAkB;AAChD,SAAK,eAAe,QAAQ;AAE5B,QAAI,QAAQ,aAAa;AACvB,WAAK,sBAAsB,QAAQ;AACnC,UAAI,QAAQ,gBAAgB,CAAC,KAAK,oBAAoB,gBAAgB,GAAG;AACvE,aAAK,oBAAoB,gBAAgB,QAAQ,YAAY;AAAA,MAC/D;AAAA,IACF,WAAW,QAAQ,SAAS,QAAQ,SAAS;AAC3C,YAAM,eAAuC;AAAA,QAC3C,GAAI,QAAQ,SAAS,gBAAgB,CAAC;AAAA,QACtC,GAAI,QAAQ,UAAU,EAAE,UAAU,QAAQ,QAAQ,IAAI,CAAC;AAAA,MACzD;AACA,UAAI,QAAQ,cAAc,YAAY,OAAO,QAAQ,aAAa,QAAQ,MAAM,KAAK;AACnF,qBAAa,aAAa,IAAI,OAAO,QAAQ,aAAa,QAAQ;AAAA,MACpE;AACA,WAAK,sBAAsB,IAAI,gBAAgB;AAAA,QAC7C,OAAO,KAAK;AAAA,QACZ,eAAe,QAAQ;AAAA,QACvB,YAAY,QAAQ;AAAA,QACpB,cAAc,QAAQ,gBAAgB,QAAQ,SAAS;AAAA,QACvD,cAAc,QAAQ;AAAA,QACtB,OAAO,QAAQ;AAAA,QACf,gBAAgB,QAAQ;AAAA,QACxB,GAAI,QAAQ,WAAW,CAAC;AAAA,QACxB;AAAA,QACA,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,MAClD,CAAC;AAAA,IACH;AAEA,SAAK,cAAc,QAAQ,QAAQ,KAAK,qBAAqB,UAAU;AACvE,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,QAAQ,cAAc,CAAC,CAAC,EAAG,MAAK,WAAW,IAAI,MAAM,IAAI;AAAA,EACrG;AAAA,EAEA,IAAW,cAA2C;AACpD,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,eAAe,SAAiC;AACrD,SAAK,sBAAsB;AAC3B,SAAK,cAAc,SAAS,UAAU;AAAA,EACxC;AAAA,EAEO,SAAS,YAAoB,YAAiE;AACnG,QAAI,KAAK,uBAAuB,CAAC,YAAY;AAC3C,WAAK,oBAAoB,SAAS,UAAU;AAAA,IAC9C,OAAO;AACL,WAAK,sBAAsB,IAAI,gBAAgB;AAAA,QAC7C,OAAO,KAAK;AAAA,QACZ,GAAI,cAAc,CAAC;AAAA,QACnB,OAAO;AAAA,MACT,CAAC;AACD,WAAK,cAAc,KAAK,oBAAoB,UAAU;AAAA,IACxD;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,QAAQ,MAA0B;AAAE,SAAK,cAAc;AAAA,EAAM;AAAA,EAC7D,eAAe,MAAc,MAA0B;AAC5D,QAAI,KAAM,MAAK,WAAW,IAAI,MAAM,IAAI;AAAA,QAAQ,MAAK,WAAW,OAAO,IAAI;AAAA,EAC7E;AAAA,EACO,eAAe,SAAyB;AAC7C,UAAM,QAAQ,OAAO,OAAO,KAAK,QAAQ,EAAE,KAAK,CAAC,UAAU,UAAU,OAAO;AAC5E,WAAO,SAAS;AAAA,EAClB;AAAA,EAEO,YAAuB,WAAgC,QAAiC,CAAC,GAAG,UAA0B,CAAC,GAAuB;AACnJ,WAAO,KAAK,QAAmB,WAAW,OAAO,QAAQ,OAAO;AAAA,EAClE;AAAA,EAEO,sBAAiC,WAAgC,QAAiC,CAAC,GAAG,UAA0B,CAAC,GAAuB;AAC7J,WAAO,KAAK,QAAmB,WAAW,OAAO,cAAc,OAAO;AAAA,EACxE;AAAA,EAEO,iBAA4B,WAAgC,QAAiC,CAAC,GAAG,UAA0B,CAAC,GAAuB;AACxJ,WAAO,KAAK,QAAmB,WAAW,OAAO,aAAa,OAAO;AAAA,EACvE;AAAA,EAEO,mBAA8B,WAAgC,QAAiC,CAAC,GAAG,UAA0B,CAAC,GAAuB;AAC1J,WAAO,KAAK,QAAmB,WAAW,OAAO,QAAQ,OAAO;AAAA,EAClE;AAAA,EAEA,MAAc,QACZ,WACA,OACA,UACA,SACA,UAAU,OACU;AACpB,UAAM,OAAO,EAAE,GAAG,SAAS,MAAM,UAAU,EAAE;AAC7C,UAAM,WAAW,UAAU,SAAS,QAAQ,gBAAgB,CAAC,QAAQ,QAAgB,mBAAmB,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC;AAC1H,UAAM,MAAM,IAAI,IAAI,UAAU,UAAU,OAAO;AAC/C,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,MAAM,WAAW,CAAC,EAAG,aAAY,IAAI,cAAc,KAAK,KAAK;AAChH,UAAM,UAA8B,EAAE,KAAK,IAAI,SAAS,GAAG,MAAM,IAAI,MAAM,aAAa,UAAU,aAAa,QAAQ,UAAU,OAAO;AACxI,UAAM,OAAO,KAAK,WAAW,IAAI,IAAI,IAAI,KAAK,KAAK;AACnD,UAAM,UAAU,IAAI,QAAQ,MAAM,eAAe,MAAM,OAAO,CAAC;AAC/D,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,WAAW,CAAC,CAAC,EAAG,SAAQ,IAAI,KAAK,KAAK;AACxF,UAAM,UAAU,MAAM,eAAe,MAAM,OAAO;AAClD,QAAI,OAAO,KAAK,OAAO,EAAE,UAAU,CAAC,QAAQ,IAAI,QAAQ,GAAG;AACzD,cAAQ,IAAI,UAAU,OAAO,QAAQ,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,UAAa,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IACtI;AAEA,UAAM,OAAoB,EAAE,QAAQ,UAAU,QAAQ,SAAS,QAAQ,QAAQ,OAAO;AACtF,UAAM,OAAO,SAAS,MAAM,IAAI;AAChC,QAAI,aAAa,QAAQ;AACvB,cAAQ,IAAI,gBAAgB,QAAQ,IAAI,cAAc,KAAK,kBAAkB;AAC7E,YAAM,cAAc,MAAM,SAAS,SAAY,MAAM,OAAO;AAC5D,WAAK,OAAO,KAAK,UAAU,WAAW;AAAA,IACxC,WAAW,aAAa,cAAc;AACpC,cAAQ,IAAI,gBAAgB,QAAQ,IAAI,cAAc,KAAK,iDAAiD;AAC5G,YAAM,UAAU,IAAI,gBAAgB;AACpC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,YAAI,UAAU,OAAW;AACzB,gBAAQ,IAAI,KAAK,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK,CAAC;AAAA,MAC5E;AACA,WAAK,OAAO;AAAA,IACd,WAAW,aAAa,aAAa;AACnC,YAAM,OAAO,IAAI,SAAS;AAC1B,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,YAAI,UAAU,OAAW;AACzB,YAAI,UAAU,aAAa,SAAS,GAAG,EAAG,MAAK,OAAO,KAAK,MAAM,KAAK,YAAY,KAAkB,GAAG,aAAa,KAAK,CAAC;AAAA,YACrH,MAAK,OAAO,KAAK,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK,CAAC;AAAA,MACjF;AACA,cAAQ,OAAO,cAAc;AAC7B,WAAK,OAAO;AAAA,IACd;AAEA,UAAM,WAAW,MAAM,KAAK,UAAU,KAAK,IAAI;AAC/C,UAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,UAAM,eAAwB,YAAY,SAAS,MAAM,IAAI,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,MAAS,IAAI,MAAM,SAAS,KAAK;AAEhI,UAAM,qBACJ,IAAI,SAAS,sBACb,iBAAiB,QACjB,OAAO,iBAAiB,YACvB,aAAoC,SAAS;AAEhD,SAAK,SAAS,WAAW,OAAO,uBAAuB,CAAC,WAAW,KAAK,kBAAkB,KAAK,qBAAqB;AAClH,YAAM,KAAK,oBAAoB,sBAAsB,IAAI,IAAI;AAC7D,aAAO,KAAK,QAAmB,WAAW,OAAO,UAAU,SAAS,IAAI;AAAA,IAC1E;AAEA,QAAI,CAAC,SAAS,GAAI,OAAM,IAAI,aAAa,iCAAiC,SAAS,MAAM,KAAK,SAAS,QAAQ,UAAU,aAAa,YAAY;AAClJ,WAAO;AAAA,EACT;AAAA;AAAA,EAGO,iBAAiB,WAAgC,KAAuD;AAC7G,UAAM,SAAkC,CAAC;AACzC,UAAM,MAAM,CAAC,UAAkB,UAAoB;AACjD,UAAI,CAAC,MAAM,OAAQ;AACnB,YAAM,SAAkC,CAAC;AACzC,iBAAW,QAAQ,MAAO,KAAI,IAAI,IAAI,MAAM,OAAW,QAAO,IAAI,IAAI,IAAI,IAAI;AAC9E,aAAO,QAAQ,IAAI;AAAA,IACrB;AACA,QAAI,cAAc,UAAU,UAAU;AACtC,QAAI,eAAe,UAAU,WAAW;AACxC,QAAI,gBAAgB,UAAU,YAAY;AAC1C,QAAI,gBAAgB,UAAU,YAAY;AAC1C,QAAI,QAAQ,UAAU,UAAU;AAGhC,QAAI,KAAK,gBAAgB,OAAO,aAAa;AAC3C,YAAM,QAAQ,OAAO;AACrB,YAAM,kBACJ,KAAK,aAAa,gBAAgB,wBAClC,KAAK,aAAa,gBAAgB,mBAClC,KAAK,aAAa,gBAAgB,YAClC,QAAQ,KAAK,aAAa,QAAQ;AAEpC,UACE,UAAU,YAAY,SAAS,UAAU,KACzC,MAAM,aAAa,UACnB,mBACA,KAAK,aAAa,UAClB;AACA,cAAM,WAAW,OAAO,KAAK,aAAa,QAAQ;AAAA,MACpD;AAEA,UACE,UAAU,YAAY,SAAS,WAAW,KAC1C,MAAM,cAAc,UACpB,KAAK,aAAa,gBAAgB,wBAClC,KAAK,aAAa,YAClB,OAAO,KAAK,aAAa,QAAQ,MAAM,KACvC;AACA,cAAM,YAAY,OAAO,KAAK,aAAa,QAAQ;AAAA,MACrD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,YAAY,OAAiC;AACzD,QAAI,OAAO,UAAU,UAAU;AAC7B,UAAI,oBAAoB,KAAK,KAAK,GAAG;AACnC,cAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAC3C,YAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,yCAAyC,SAAS,MAAM,GAAG;AAC7F,eAAO,SAAS,KAAK;AAAA,MACvB;AAEA,YAAM,KAAK,MAAM,OAAO,aAAkB;AAC1C,YAAMA,SAAQ,MAAM,GAAG,SAAS,KAAK;AACrC,YAAM,OAAO,IAAI,WAAWA,OAAM,UAAU;AAC5C,WAAK,IAAIA,MAAK;AACd,aAAO,IAAI,KAAK,CAAC,KAAK,MAAM,GAAG,EAAE,MAAM,cAAc,KAAK,EAAE,CAAC;AAAA,IAC/D;AACA,QAAI,iBAAiB,KAAM,QAAO;AAClC,QAAI,iBAAiB,YAAa,QAAO,IAAI,KAAK,CAAC,KAAK,CAAC;AAEzD,UAAM,QAAQ,IAAI,WAAW,MAAM,UAAU;AAC7C,UAAM,IAAI,KAAK;AACf,WAAO,IAAI,KAAK,CAAC,MAAM,MAAM,CAAC;AAAA,EAChC;AACF;AAEA,SAAS,SAAS,OAAyC;AACzD,SAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAI,QAAmC,CAAC;AAC3G;AACA,SAAS,YAAY,QAAyB,KAAa,OAAsB;AAC/E,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GAAI;AAC3D,MAAI,MAAM,QAAQ,KAAK,GAAG;AAAE,eAAW,QAAQ,MAAO,QAAO,OAAO,KAAK,OAAO,IAAI,CAAC;AAAG;AAAA,EAAQ;AAChG,SAAO,IAAI,KAAK,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK,CAAC;AACnF;AACA,SAAS,aAAa,OAAwB;AAC5C,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,YAAY,KAAK,KAAK,GAAG;AAC3B,UAAI;AAAE,eAAO,IAAI,IAAI,KAAK,EAAE,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;AAAA,MAAU,QAAQ;AAAE,eAAO;AAAA,MAAU;AAAA,IAChG;AACA,UAAM,OAAO,MAAM,MAAM,OAAO,EAAE,IAAI;AACtC,WAAO,QAAQ;AAAA,EACjB;AACA,MAAI,SAAS,OAAO,UAAU,YAAY,UAAU,SAAS,OAAQ,MAA6B,SAAS,UAAU;AACnH,WAAQ,MAA2B;AAAA,EACrC;AACA,MAAI,iBAAiB,QAAQ,MAAM,MAAM;AACvC,UAAM,MAAM,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,QAAQ,QAAQ,KAAK;AAC3D,QAAI,IAAK,QAAO,UAAU,GAAG;AAAA,EAC/B;AACA,SAAO;AACT;AACA,SAAS,cAAc,UAA0B;AAC/C,QAAM,QAAQ,SAAS,YAAY;AACnC,MAAI,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,OAAO,EAAG,QAAO;AAC9D,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,MAAI,MAAM,SAAS,OAAO,EAAG,QAAO;AACpC,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,SAAO;AACT;AACA,eAAe,eAAe,MAA+B,SAA8D;AACzH,SAAO,EAAE,GAAI,MAAM,WAAW,CAAC,GAAI,GAAK,MAAM,MAAM,aAAa,OAAO,KAAM,CAAC,EAAG;AACpF;AACA,eAAe,eAAe,MAA+B,SAA8D;AACzH,SAAO,EAAE,GAAI,MAAM,WAAW,CAAC,GAAI,GAAK,MAAM,MAAM,aAAa,OAAO,KAAM,CAAC,EAAG;AACpF;;;ACjRO,IAAM,6BAAuD;AAAA,EAClE,GAAG;AAAA,IACD;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IACxE;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IACxE;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,EAC1D;AAAA,EACA,GAAG;AAAA,IACD;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IACxE;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,EAC1C;AAAA,EACA,GAAG;AAAA,IACD;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IACxE;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,IAAQ;AAAA,EAClE;AACF;AAQO,IAAM,iCAA2D;AAAA,EACtE,GAAG,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EAClJ,GAAG,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EAClE,GAAG,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AACpE;AAGO,IAAM,8BAAmG;AAAA,EAC9G,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,iGAAoD;AAAA,EAChG,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,2GAA2D;AAAA,EACvG,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,gGAAiD;AAAA,EAC7F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,yEAA8C;AAAA,EAC1F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,4EAAiD;AAAA,EAC7F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,gFAA6C;AAAA,EACzF,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,4FAAkD;AAAA,EAC9F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,iFAA+C;AAAA,EAC3F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,gFAAgD;AAAA,EAC5F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,yFAA+C;AAAA,EAC3F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,sFAA+C;AAAA,EAC3F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,0FAA6C;AAAA,EACzF,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,qFAAkD;AAAA,EAC9F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,4FAAkD;AAAA,EAC9F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,oFAA+C;AAAA,EAC3F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,gFAAgD;AAAA,EAC5F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,8FAAiD;AAAA,EAC7F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,iGAA+C;AAAA,EAC3F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,yFAA+C;AAAA,EAC3F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,kFAA+C;AAAA,EAC3F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,uFAA6C;AAAA,EACzF,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,iFAAiD;AAAA,EAC7F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,0FAAkD;AAAA,EAC9F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,gGAAiD;AAAA,EAC7F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,4FAAkD;AAAA,EAC9F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,qFAAiD;AAAA,EAC7F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,sFAAgD;AAAA,EAC5F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,kFAA+C;AAAA,EAC3F,MAAM,EAAE,SAAS,QAAQ,UAAU,GAAG,MAAM,mFAAkD;AAChG;AAKO,SAAS,mCAAmC,OAIhD;AACD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,+EAAwC;AAAA,EACtD,WAAW,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK;AAC/C,WAAO,KAAK,0GAAoD;AAAA,EAClE;AAEA,MAAI;AACJ,MAAI,OAAO,IAAI,cAAc,UAAU;AACrC,QAAI;AACF,qBAAe,KAAK,MAAM,IAAI,SAAS;AAAA,IACzC,QAAQ;AACN,aAAO,KAAK,+EAAgD;AAC5D,qBAAe,CAAC;AAAA,IAClB;AAAA,EACF,WAAW,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AAC7D,mBAAe,IAAI;AAAA,EACrB,OAAO;AACL,WAAO,KAAK,sHAA6E;AACzF,mBAAe,CAAC;AAAA,EAClB;AAGA,QAAM,SAAS,OAAO,aAAa,WAAW,WAAW,aAAa,SAAS;AAC/E,MAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,MAAM,GAAG;AAC/B,WAAO,KAAK,iGAA2D;AAAA,EACzE;AAEA,QAAM,mBAAmB,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AACzE,QAAM,eAAe,MAAM,QAAQ,aAAa,YAAY,KAAK,aAAa,aAAa,SAAS,IAChG,aAAa,aAAa,IAAI,MAAM,IACpC;AAEJ,aAAW,OAAO,cAAc;AAC9B,QAAI,CAAC,iBAAiB,SAAS,GAAG,GAAG;AACnC,aAAO,KAAK,iCAAe,GAAG,0DAAoC,iBAAiB,KAAK,IAAI,CAAC,GAAG;AAAA,IAClG;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,GAAG,GAAG,GAAG,CAAC;AAC5B,QAAM,KAAK,MAAM,QAAQ,aAAa,EAAE,KAAK,aAAa,GAAG,SAAS,IAClE,aAAa,GAAG,IAAI,MAAM,IAC1B,CAAC,GAAG,GAAG,CAAC;AAEZ,aAAW,KAAK,IAAI;AAClB,QAAI,CAAC,SAAS,SAAS,CAAC,GAAG;AACzB,aAAO,KAAK,yCAAoB,CAAC,4EAA+D;AAAA,IAClG;AAAA,EACF;AAGA,MAAI,WAAgB,aAAa;AACjC,MAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAC7C,eAAW;AAAA,MACT,WAAW,CAAC;AAAA,MACZ,QAAQ,CAAC;AAAA,MACT,mBAAmB,EAAE,UAAU,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,MAChD,eAAe,EAAE,UAAU,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,MAC5C,mBAAmB;AAAA,IACrB;AAAA,EACF,OAAO;AACL,UAAM,UAAU,SAAS,iBAAiB,OAAO,SAAS,kBAAkB,WACxE,SAAS,gBACT;AACJ,UAAM,cAAc,SAAS,qBAAqB,OAAO,SAAS,sBAAsB,WACpF,SAAS,oBACT;AACJ,UAAM,gBAAgB,WAAW,eAAe,EAAE,UAAU,CAAC,GAAG,UAAU,CAAC,EAAE;AAE7E,eAAW;AAAA,MACT,WAAW,MAAM,QAAQ,SAAS,SAAS,IAAI,SAAS,YAAY,CAAC;AAAA,MACrE,QAAQ,MAAM,QAAQ,SAAS,MAAM,IAAI,SAAS,SAAS,CAAC;AAAA,MAC5D,mBAAmB,eAAe;AAAA,MAClC,eAAe,WAAW;AAAA,MAC1B,mBAAmB,SAAS,sBAAsB,SAAY,QAAQ,SAAS,iBAAiB,IAAI;AAAA,IACtG;AAEA,UAAM,WAAW,SAAS,cAAc,YAAY,SAAS,kBAAkB;AAC/E,QAAI,YAAY,CAAC,MAAM,QAAQ,QAAQ,GAAG;AACxC,aAAO,KAAK,4IAAsG;AAAA,IACpH,WAAW,MAAM,QAAQ,QAAQ,GAAG;AAClC,iBAAW,OAAO,UAAU;AAC1B,YAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,OAAO,IAAI,EAAE,CAAC,GAAG;AACvC,iBAAO,KAAK,+BAAoB,IAAI,EAAE,4FAA2D;AAAA,QACnG;AACA,YAAI,IAAI,aAAa,CAAC,MAAM,QAAQ,IAAI,SAAS,GAAG;AAClD,iBAAO,KAAK,2DAAyC,IAAI,EAAE,yDAA+B;AAAA,QAC5F,WAAW,MAAM,QAAQ,IAAI,SAAS,GAAG;AACvC,qBAAW,QAAQ,IAAI,WAAW;AAChC,gBAAI,CAAC,KAAK,MAAM,OAAO,KAAK,OAAO,UAAU;AAC3C,qBAAO,KAAK,yBAAiB,KAAK,UAAU,IAAI,CAAC,6BAAqB,IAAI,EAAE,+EAAgD;AAAA,YAC9H,OAAO;AACL,oBAAM,YAAY,4BAA4B,KAAK,EAAE;AACrD,kBAAI,WAAW;AACb,uBAAO;AAAA,kBACL,oBAAY,KAAK,EAAE,MAAM,UAAU,IAAI,8FAA+C,UAAU,OAAO,oDAC3E,UAAU,OAAO;AAAA,gBAC/C;AAAA,cACF,OAAO;AACL,sBAAM,sBAAsB,+BAA+B,OAAO,IAAI,EAAE,CAAC,KAAK,CAAC;AAC/E,oBAAI,CAAC,oBAAoB,SAAS,KAAK,EAAE,GAAG;AAC1C,wBAAM,eAAe,OAAO,KAAK,8BAA8B,EAAE,KAAK,OAAK,+BAA+B,OAAO,CAAC,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;AACtI,yBAAO;AAAA,oBACL,oBAAY,KAAK,EAAE,sFAAoD,IAAI,EAAE,qFAC5E,eAAe,mCAAqB,YAAY,OAAO;AAAA,kBAC1D;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AACA,gBAAI,KAAK,aAAa,CAAC,MAAM,QAAQ,KAAK,SAAS,GAAG;AACpD,qBAAO,KAAK,mDAA+B,KAAK,EAAE,qFAA+C;AAAA,YACnG;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,iBAAiB;AAAA,IACrB,GAAG;AAAA,IACH,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,IAAI;AAAA,IACJ,UAAU;AAAA,EACZ;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B;AAAA,MACA,QAAQ;AAAA,MACR,WAAW,KAAK,UAAU,cAAc;AAAA,IAC1C,IAAI;AAAA,EACN;AACF;AAKO,SAAS,mCAAmC,OAIhD;AACD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,MAAI,CAAC,QAAQ,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK;AACjD,WAAO,KAAK,0GAAoD;AAAA,EAClE;AAEA,MAAI,eAAwC,CAAC;AAC7C,MAAI,OAAO,IAAI,cAAc,UAAU;AACrC,QAAI;AACF,qBAAe,KAAK,MAAM,IAAI,SAAS;AAAA,IACzC,QAAQ;AACN,aAAO,KAAK,+EAAgD;AAAA,IAC9D;AAAA,EACF,WAAW,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AAC7D,mBAAe,IAAI;AAAA,EACrB,OAAO;AACL,WAAO,KAAK,wDAAiC;AAAA,EAC/C;AAEA,QAAM,OAAO,OAAO,aAAa,SAAS,WAAW,aAAa,KAAK,KAAK,IAAI;AAChF,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,kFAA2D;AAAA,EACzE;AAEA,QAAM,QAAQ,OAAO,aAAa,UAAU,WAAW,aAAa,QAAQ;AAC5E,MAAI,SAAS,GAAG;AACd,WAAO,KAAK,uGAA0D;AAAA,EACxE;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B;AAAA,MACA,QAAQ;AAAA,MACR,WAAW,KAAK,UAAU;AAAA,QACxB,MAAM,OAAO,aAAa,QAAQ,YAAY;AAAA,QAC9C,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ,OAAO,aAAa,UAAU,CAAC;AAAA,QACvC,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH,IAAI;AAAA,EACN;AACF;AAKO,SAAS,uCAAuC,OAIpD;AACD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,MAAI,CAAC,QAAQ,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK;AACjD,WAAO,KAAK,0GAAoD;AAAA,EAClE;AAEA,MAAI,eAAwC,CAAC;AAC7C,MAAI,OAAO,IAAI,cAAc,UAAU;AACrC,QAAI;AACF,qBAAe,KAAK,MAAM,IAAI,SAAS;AAAA,IACzC,QAAQ;AACN,aAAO,KAAK,+EAAgD;AAAA,IAC9D;AAAA,EACF,WAAW,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AAC7D,mBAAe,IAAI;AAAA,EACrB,OAAO;AACL,WAAO,KAAK,wDAAiC;AAAA,EAC/C;AAEA,QAAM,iBAAiB,OAAO,aAAa,cAAc;AACzD,MAAI,CAAC,kBAAkB,kBAAkB,GAAG;AAC1C,WAAO,KAAK,0HAAkE;AAAA,EAChF;AAEA,QAAM,QAAQ,OAAO,aAAa,KAAK;AACvC,MAAI,CAAC,CAAC,KAAS,MAAS,GAAO,EAAE,SAAS,KAAK,GAAG;AAChD,WAAO,KAAK,qIAA0F;AAAA,EACxG;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B;AAAA,MACA,QAAQ;AAAA,MACR,WAAW,KAAK,UAAU;AAAA,QACxB,gBAAgB;AAAA,QAChB,OAAO;AAAA,QACP,MAAM,OAAO,aAAa,QAAQ,oBAAoB;AAAA,QACtD,MAAM,OAAO,aAAa,QAAQ,EAAE;AAAA,MACtC,CAAC;AAAA,IACH,IAAI;AAAA,EACN;AACF;AAKO,SAAS,uCAAuC,OAIpD;AACD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,MAAI,CAAC,QAAQ,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK;AACjD,WAAO,KAAK,0GAAoD;AAAA,EAClE;AAEA,MAAI,eAAwC,CAAC;AAC7C,MAAI,OAAO,IAAI,cAAc,UAAU;AACrC,QAAI;AACF,qBAAe,KAAK,MAAM,IAAI,SAAS;AAAA,IACzC,QAAQ;AACN,aAAO,KAAK,+EAAgD;AAAA,IAC9D;AAAA,EACF,WAAW,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AAC7D,mBAAe,IAAI;AAAA,EACrB;AAEA,QAAM,YAAY,OAAO,aAAa,SAAS;AAC/C,MAAI,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,SAAS,SAAS,GAAG;AACrC,WAAO,KAAK,iLAAyG;AAAA,EACvH;AAEA,QAAM,OAAO,OAAO,aAAa,SAAS,WAAW,aAAa,KAAK,KAAK,IAAI,OAAO,aAAa,QAAQ,EAAE;AAC9G,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,6GAAkE;AAAA,EAChF;AAEA,QAAM,UAAU,OAAO,aAAa,OAAO;AAC3C,MAAI,MAAM,OAAO,KAAK,UAAU,KAAK,UAAU,IAAI;AACjD,WAAO,KAAK,qGAA0D;AAAA,EACxE;AAEA,QAAM,UAAU,MAAM,QAAQ,aAAa,OAAO,IAAI,aAAa,UAAU,CAAC;AAC9E,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,KAAK,2EAA+C;AAAA,EAC7D;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B;AAAA,MACA,QAAQ;AAAA,MACR,WAAW,KAAK,UAAU;AAAA,QACxB,WAAW;AAAA,QACX,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,IACH,IAAI;AAAA,EACN;AACF;AAKO,SAAS,4CAA4C,OAIzD;AACD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,MAAI,CAAC,QAAQ,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK;AACjD,WAAO,KAAK,0GAAoD;AAAA,EAClE;AAEA,MAAI,eAAwC,CAAC;AAC7C,MAAI,OAAO,IAAI,cAAc,UAAU;AACrC,QAAI;AACF,qBAAe,KAAK,MAAM,IAAI,SAAS;AAAA,IACzC,QAAQ;AACN,aAAO,KAAK,+EAAgD;AAAA,IAC9D;AAAA,EACF,WAAW,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AAC7D,mBAAe,IAAI;AAAA,EACrB;AAEA,QAAM,UAAU,OAAO,aAAa,WAAW,aAAa,aAAa,CAAC;AAC1E,QAAM,OAAO,OAAO,aAAa,SAAS,WAAW,aAAa,KAAK,KAAK,IAAI,OAAO,aAAa,QAAQ,EAAE;AAC9G,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,sGAAgE;AAAA,EAC9E;AAEA,QAAM,UAAU,OAAO,aAAa,OAAO;AAC3C,MAAI,MAAM,OAAO,KAAK,UAAU,KAAK,UAAU,IAAI;AACjD,WAAO,KAAK,qGAA0D;AAAA,EACxE;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B;AAAA,MACA,QAAQ;AAAA,MACR,WAAW,KAAK,UAAU;AAAA,QACxB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH,IAAI;AAAA,EACN;AACF;AAKO,SAAS,kDAAkD,OAI/D;AACD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,MAAI,CAAC,QAAQ,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK;AACjD,WAAO,KAAK,0GAAoD;AAAA,EAClE;AAEA,MAAI,eAAwC,CAAC;AAC7C,MAAI,OAAO,IAAI,cAAc,UAAU;AACrC,QAAI;AACF,qBAAe,KAAK,MAAM,IAAI,SAAS;AAAA,IACzC,QAAQ;AACN,aAAO,KAAK,+EAAgD;AAAA,IAC9D;AAAA,EACF,WAAW,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AAC7D,mBAAe,IAAI;AAAA,EACrB;AAEA,QAAM,UAAU,OAAO,aAAa,WAAW,aAAa,aAAa,CAAC;AAC1E,MAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,OAAO,GAAG;AAChC,WAAO,KAAK,8KAAyG;AAAA,EACvH;AAEA,QAAM,UAAU,OAAO,aAAa,OAAO;AAC3C,MAAI,MAAM,OAAO,KAAK,UAAU,KAAK,UAAU,IAAI;AACjD,WAAO,KAAK,qGAA0D;AAAA,EACxE;AAEA,QAAM,UAAU,MAAM,QAAQ,aAAa,OAAO,IAAI,aAAa,QAAQ,IAAI,MAAM,IAAI,CAAC;AAC1F,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,KAAK,0FAAwD;AAAA,EACtE;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B;AAAA,MACA,QAAQ;AAAA,MACR,WAAW,KAAK,UAAU;AAAA,QACxB,SAAS;AAAA,QACT,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,IACH,IAAI;AAAA,EACN;AACF;AAKO,SAAS,gCAAgC,OAS7C;AACD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AAEZ,QAAM,SAAS,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS;AAC7D,MAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,MAAM,GAAG;AAC/B,WAAO,KAAK,6DAAsC;AAAA,EACpD;AAEA,QAAM,YAAY,MAAM,QAAQ,IAAI,SAAS,KAAK,IAAI,UAAU,SAAS,IACrE,IAAI,UAAU,IAAI,MAAM,IACxB,CAAC,OAAO,OAAO,OAAO,OAAO,KAAK;AAEtC,QAAM,YAAY,MAAM,QAAQ,IAAI,SAAS,KAAK,IAAI,UAAU,SAAS,IACrE,IAAI,UAAU,IAAI,MAAM,IACxB,CAAC,GAAG,GAAG,CAAC;AAEZ,QAAM,YAAY,OAAO,IAAI,cAAc,WAAW,IAAI,YAAY;AAEtE,QAAM,iBAAiB,OAAO,IAAI,mBAAmB,YAAY,IAAI,eAAe,KAAK,IACrF,IAAI,eAAe,KAAK,IACxB,KAAK,UAAU,EAAE,UAAU,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC;AAEjD,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,OAAO,IAAI,cAAc,WAAW,IAAI,YAAY;AAAA,MAC/D,WAAW,MAAM,QAAQ,IAAI,SAAS,IAAI,IAAI,UAAU,IAAI,MAAM,IAAI,CAAC;AAAA,MACvE;AAAA,MACA;AAAA,MACA,QAAQ,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS,OAAO,IAAI,UAAU,GAAG;AAAA,IAChF,IAAI;AAAA,EACN;AACF;AAKO,SAAS,6CACd,OAC+D;AAC/D,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,mJAAoE;AAAA,IAC/E;AAAA,EACF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,IAAI,QAAQ,IAAI;AAE7B,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,6GAA0D;AACtE,WAAO,EAAE,SAAS,OAAO,OAAO;AAAA,EAClC;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,SAAS;AACZ,aAAO,KAAK,6IAA4D;AAAA,IAC1E,WAAW,CAAC,kBAAkB,KAAK,OAAO,GAAG;AAC3C,aAAO,KAAK,2CAAkB,OAAO,wEAA8C;AAAA,IACrF;AAEA,UAAM,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC,EAAE,YAAY;AACnD,QAAI,CAAC,SAAS,SAAS,MAAM,KAAK,CAAC,SAAS,SAAS,MAAM,GAAG;AAC5D,aAAO,KAAK,uHAA+D;AAAA,IAC7E;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,WAAW,SAAY,OAAO,IAAI,MAAM,EAAE,KAAK,IAAI;AACzE,MAAI,cAAc,OAAO,cAAc,KAAK;AAC1C,WAAO,KAAK,wDAAmC,IAAI,MAAM,mHAAoE;AAAA,EAC/H;AAEA,QAAM,YAAyD;AAAA,IAC7D,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAKO,SAAS,oCACd,OACsD;AACtD,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,sJAA0E;AAAA,IACrF;AAAA,EACF;AAEA,QAAM,MAAM;AACZ,QAAM,SAAS,OAAO,IAAI,MAAM;AAEhC,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,mCAAmC,GAAG;AAAA,IAC/C,KAAK;AACH,aAAO,mCAAmC,GAAG;AAAA,IAC/C,KAAK;AACH,aAAO,uCAAuC,GAAG;AAAA,IACnD,KAAK;AACH,aAAO,uCAAuC,GAAG;AAAA,IACnD,KAAK;AACH,aAAO,4CAA4C,GAAG;AAAA,IACxD,KAAK;AACH,aAAO,kDAAkD,GAAG;AAAA,IAC9D,SAAS;AACP,YAAM,SAAmB,CAAC;AAC1B,YAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,UAAI,CAAC,MAAM;AACT,eAAO,KAAK,kFAAyC;AAAA,MACvD,WAAW,KAAK,SAAS,KAAK;AAC5B,eAAO,KAAK,2IAA8D,KAAK,MAAM,kBAAU;AAAA,MACjG;AACA,UAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,GAAG;AAC5C,eAAO,KAAK,mGAAqD,IAAI,MAAM,GAAG;AAAA,MAChF;AACA,UAAI,CAAC,IAAI,aAAa,OAAO,IAAI,cAAc,UAAU;AACvD,eAAO,KAAK,qFAAmD;AAAA,MACjE;AACA,aAAO;AAAA,QACL,SAAS,OAAO,WAAW;AAAA,QAC3B;AAAA,QACA,MAAM,OAAO,WAAW,IAAK,MAAwD;AAAA,MACvF;AAAA,IACF;AAAA,EACF;AACF;AAKO,IAAM,yBAAyB;AAAA,EACpC,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,yBAAyB;AAAA,EACzB,yBAAyB;AAAA,EACzB,8BAA8B;AAAA,EAC9B,oCAAoC;AAAA,EACpC,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,yBAAyB;AAAA,EACzB,uCAAuC;AACzC;;;ACrsBO,IAAM,6BAAN,MAAiC;AAAA;AAAA,EAEtC;AAAA;AAAA,EAEA;AACF;AAGO,IAAM,uBAAN,MAA2B;AAAA;AAAA,EAEhC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF;AAGO,IAAM,wBAAN,MAA4B;AAAA;AAAA,EAEjC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF;AAGO,IAAM,2BAAN,MAA+B;AAAA;AAAA,EAEpC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF;AAEO,IAAM,4BAAN,MAAgC;AAAA;AAAA,EAErC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF;AAqQO,IAAM,oBAAoB;AAAA,EAC/B,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA;AAAA,EAEV,aAAa;AACf;AAGO,IAAM,kBAAkB;AAAA,EAC7B,QAAQ;AAAA;AAAA,EAER,YAAY;AAAA;AAAA,EAEZ,aAAa;AACf;AAKO,IAAM,4BAA4B;AAAA;AAAA,EAEvC,gBAAgB;AAAA;AAAA,EAEhB,OAAO;AACT;AAKO,IAAM,oBAAoB;AAAA,EAC/B,UAAU;AAAA,EACV,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,SAAS;AACX;AAGO,IAAM,cAAc;AAAA,EACzB,SAAS;AAAA,EACT,KAAK;AAAA,EACL,IAAI;AACN;AAKO,IAAM,kBAAkB;AAAA;AAAA,EAE7B,OAAO;AAAA;AAAA,EAEP,SAAS;AAAA;AAAA,EAET,OAAO;AACT;AAOO,IAAM,sBAAsB;AAAA;AAAA,EAEjC,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa;AAAA,EACb,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA;AAAA,EAGR,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA;AAAA,EAGX,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,UAAU;AACZ;AAuBO,IAAM,sBAAsB;AAAA;AAAA,EAEjC,UAAU;AAAA;AAAA,EAEV,UAAU;AAAA;AAAA,EAEV,aAAa;AACf;AASO,IAAM,wBAAwB;AAAA;AAAA,EAEnC,UAAU;AAAA;AAAA,EAEV,MAAM;AAAA;AAAA,EAEN,aAAa;AACf;AAgBO,IAAM,mBAAmB;AAAA,EAC9B,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,OAAO;AACT;AASO,IAAM,wBAAwB;AAAA;AAAA,EAEnC,WAAW;AAAA;AAAA,EAEX,OAAO;AACT;AASO,IAAM,oBAAoB;AAAA;AAAA,EAE/B,UAAU;AAAA;AAAA,EAEV,OAAO;AAAA;AAAA,EAEP,YAAY;AAAA;AAAA,EAEZ,gBAAgB;AAAA;AAAA,EAEhB,cAAc;AAAA;AAAA,EAEd,0BAA0B;AAAA;AAAA,EAE1B,cAAc;AAAA;AAAA,EAEd,cAAc;AAChB;AAaO,IAAM,oBAAoB;AAAA;AAAA,EAE/B,YAAY;AAAA;AAAA,EAEZ,WAAW;AAAA;AAAA,EAEX,WAAW;AAAA;AAAA,EAEX,WAAW;AAAA;AAAA,EAEX,WAAW;AACb;AAcO,IAAM,uBAAuB;AAAA;AAAA,EAElC,SAAS;AAAA;AAAA,EAET,KAAK;AAAA;AAAA,EAEL,WAAW;AAAA;AAAA,EAEX,UAAU;AAAA;AAAA,EAEV,SAAS;AAAA;AAAA,EAET,eAAe;AAAA;AAAA,EAEf,cAAc;AAChB;AA0MO,IAAM,8BAAN,MAAkC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,+BAAN,MAAmC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF;AA2CO,IAAM,wBAAwB;AAAA,EACnC,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AACX;AA2JO,IAAM,mCAAN,MAAuC;AAAA;AAAA,EAE5C;AACF;AAEO,IAAM,oCAAN,MAAwC;AAAA,EAC7C;AAAA;AAAA,EAEA;AAAA,EACA;AACF;AA06CO,IAAM,gCAAN,MAAoC;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,gCAAN,MAAoC;AAAA;AAAA,EAEzC;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF;AAEO,IAAM,iCAAN,MAAqC;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AACF;;;ACv7EO,IAAM,uBAAuB;AAAA,EAClC,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AACX;AAGO,IAAM,iBAAiB;AAAA,EAC5B,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,UAAU;AAAA;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AACX;AAGO,IAAM,2BAAqD;AAAA;AAAA,EAEhE,CAAC,eAAe,OAAO,GAAG;AAAA,IACxB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,EACpB;AAAA;AAAA,EAEA,CAAC,eAAe,KAAK,GAAG;AAAA,IACtB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,EACpB;AAAA;AAAA,EAEA,CAAC,eAAe,OAAO,GAAG;AAAA,IACxB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,EACpB;AAAA;AAAA,EAEA,CAAC,eAAe,IAAI,GAAG;AAAA,IACrB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,EACpB;AAAA;AAAA,EAEA,CAAC,eAAe,QAAQ,GAAG;AAAA,IACzB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,EACpB;AAAA;AAAA,EAEA,CAAC,eAAe,EAAE,GAAG,CAAC,kBAAkB,WAAW;AACrD;AAKO,SAAS,8BACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAG5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2FAA0C;AAAA,EACxD,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4EAAqC;AAAA,EACnD;AAGA,QAAM,aAAa,OAAO,OAAO,oBAAoB;AACrD,MAAI,QAAQ,iBAAiB,UAAa,QAAQ,iBAAiB,MAAM;AACvE,WAAO,KAAK,wCAA2B;AAAA,EACzC,WAAW,CAAC,WAAW,SAAS,QAAQ,YAAmB,GAAG;AAC5D,WAAO;AAAA,MACL,iBAAiB,QAAQ,YAAY;AAAA,IACvC;AAAA,EACF;AAKA,QAAM,6BAA6B;AAAA,IACjC,qBAAqB;AAAA,IACrB,qBAAqB;AAAA,IACrB,qBAAqB;AAAA,IACrB,qBAAqB;AAAA,IACrB,qBAAqB;AAAA,EACvB;AACA,MAAI,QAAQ,iBAAiB,UAAa,2BAA2B,SAAS,QAAQ,YAAmB,GAAG;AAC1G,QAAI,CAAC,QAAQ,UAAU,QAAQ,UAAU,GAAG;AAC1C,aAAO,KAAK,8LAAiH;AAAA,IAC/H;AAAA,EACF,WAAW,QAAQ,iBAAiB,qBAAqB,SAAS;AAChE,QAAI,QAAQ,WAAW,MAAM,QAAQ,WAAW,KAAK,CAAC,QAAQ,QAAQ;AACpE,eAAS,KAAK,2EAA+C;AAAA,IAC/D;AAAA,EACF;AAGA,UAAQ,QAAQ,cAAc;AAAA,IAC5B,KAAK,qBAAqB;AACxB,UAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,cAAc,YAAY,CAAC,QAAQ,UAAU,KAAK,GAAG;AAC5F,eAAO,KAAK,sFAAkD;AAAA,MAChE,WAAW,CAAC,kBAAkB,KAAK,QAAQ,SAAS,GAAG;AACrD,eAAO,KAAK,4IAA6E;AAAA,MAC3F;AACA;AAAA,IAEF,KAAK,qBAAqB;AACxB,UAAI,CAAC,QAAQ,aAAa,QAAQ,aAAa,GAAG;AAChD,eAAO,KAAK,kJAAuF;AAAA,MACrG;AACA;AAAA,IAEF,KAAK,qBAAqB;AACxB,UAAI,QAAQ,cAAc,UAAa,QAAQ,cAAc,MAAM;AACjE,iBAAS,KAAK,mIAAuF;AAAA,MACvG;AACA;AAAA,IAEF,KAAK,qBAAqB;AAAA,IAC1B,KAAK,qBAAqB;AAExB;AAAA,EACJ;AAGA,MAAI,QAAQ,eAAe,UAAa,QAAQ,gBAAgB,QAAW;AACzE,QAAI,QAAQ,eAAe,GAAG;AAE5B,UAAI,QAAQ,cAAc,KAAK,QAAQ,cAAc,KAAQ;AAC3D,eAAO,KAAK,6FAAwD;AAAA,MACtE;AAAA,IACF,WAAW,QAAQ,eAAe,GAAG;AAEnC,UAAI,QAAQ,cAAc,KAAK,QAAQ,cAAc,IAAI;AACvD,iBAAS,KAAK,0JAAoE;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,QAAQ,cAAc,QAAQ,aAAa,GAAG;AAChD,QAAI,QAAQ,SAAS,GAAG;AACtB,eAAS,KAAK,uHAAwE;AAAA,IACxF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,wBACd,SACA,UAA6B,CAAC,GACJ;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAG5B,MAAI,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,GAAG;AACtC,WAAO,KAAK,gDAA8B;AAAA,EAC5C;AACA,MAAI,CAAC,QAAQ,cAAc,QAAQ,cAAc,GAAG;AAClD,WAAO,KAAK,sDAAoC;AAAA,EAClD;AAGA,MAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAAO,KAAK,GAAG;AAC7C,WAAO,KAAK,6FAA4C;AAAA,EAC1D,WAAW,QAAQ,OAAO,SAAS,KAAK;AACtC,WAAO,KAAK,yBAAmB,QAAQ,OAAO,MAAM,sBAAc;AAAA,EACpE;AAGA,QAAM,SAAS,QAAQ,UAAU;AACjC,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK,2CAA8B;AAAA,EAC5C,OAAO;AAEL,QAAI,CAAC,OAAO,WAAW,CAAC,OAAO,QAAQ,KAAK,GAAG;AAC7C,aAAO,KAAK,mDAAsC;AAAA,IACpD,OAAO;AACL,YAAM,aAAa,OAAO,QAAQ,KAAK,EAAE;AACzC,UAAI,aAAa,IAAI;AACnB,eAAO,KAAK,6CAAqC,UAAU,yCAAuB;AAAA,MACpF,WAAW,aAAa,IAAI;AAC1B,eAAO,KAAK,0CAAoC,UAAU,sCAAoB;AAAA,MAChF;AAAA,IACF;AAGA,UAAM,cAAc,OAAO,eAAe,OAAO;AACjD,QAAI,gBAAgB,UAAa,gBAAgB,QAAQ,YAAY,KAAK,EAAE,SAAS,GAAG;AACtF,YAAM,iBAAiB,YAAY,KAAK,EAAE;AAC1C,UAAI,iBAAiB,IAAI;AACvB,eAAO;AAAA,UACL,qFAA6D,cAAc;AAAA,QAC7E;AAAA,MACF,WAAW,iBAAiB,KAAM;AAChC,eAAO;AAAA,UACL,kFAA4D,cAAc;AAAA,QAC5E;AAAA,MACF;AAGA,UAAI,OAAO,cAAc,MAAM,QAAQ,OAAO,UAAU,KAAK,CAAC,OAAO,WAAW,SAAS,EAAE,GAAG;AAC5F,iBAAS;AAAA,UACP;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,WAAW,UAAa,QAAQ,MAAM;AAC/C,YAAM,cAAc,yBAAyB,QAAQ,IAAI;AACzD,UAAI,eAAe,CAAC,YAAY,SAAS,OAAO,MAAM,GAAG;AACvD,iBAAS;AAAA,UACP,wCAAwB,OAAO,MAAM,iGAA+D,QAAQ,IAAI;AAAA,QAClH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,QAAQ,QAAQ,UAAU;AAChC,MAAI,CAAC,OAAO;AACV,WAAO,KAAK,0CAA6B;AAAA,EAC3C,OAAO;AAEL,QAAI,QAAQ,SAAS,eAAe,SAAS;AAC3C,UAAI,MAAM,SAAS,GAAG;AACpB,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,cAAc,GAAG;AACzB,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,QAAQ,SAAS,eAAe,OAAO;AAEhD,UAAI,MAAM,SAAS,KAAK,MAAM,SAAS,GAAG;AACxC,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK,IAAI;AAC/C,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF,WACE,QAAQ,SAAS,eAAe,YAChC,QAAQ,SAAS,eAAe,WAChC,QAAQ,SAAS,eAAe,MAChC;AACA,UAAI,MAAM,SAAS,GAAG;AACpB,eAAO;AAAA,UACL,kCAAmB,QAAQ,IAAI;AAAA,QACjC;AAAA,MACF;AAAA,IACF,WAAW,QAAQ,SAAS,eAAe,IAAI;AAE7C,UAAI,MAAM,SAAS,KAAK,MAAM,SAAS,GAAG;AACxC,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,SAAS,GAAG;AAEpB,YAAI,MAAM,mBAAmB,KAAK,MAAM,mBAAmB,QAAW;AACpE,iBAAO;AAAA,YACL;AAAA,UACF;AAAA,QACF;AACA,YAAI,MAAM,QAAQ,UAAa,MAAM,MAAM,KAAK;AAC9C,iBAAO;AAAA,YACL,6LAAyG,MAAM,GAAG;AAAA,UACpH;AAAA,QACF;AACA,YAAI,MAAM,UAAU,UAAa,MAAM,QAAQ,IAAI;AACjD,iBAAO;AAAA,YACL,+KAAmG,MAAM,KAAK;AAAA,UAChH;AAAA,QACF,WAAW,MAAM,UAAU,UAAa,MAAM,QAAQ,KAAM;AAC1D,mBAAS;AAAA,YACP,6SAAuL,MAAM,KAAK;AAAA,UACpM;AAAA,QACF;AAAA,MACF,WAAW,MAAM,SAAS,GAAG;AAI3B,YAAI,MAAM,mBAAmB,GAAG;AAE9B,cAAI,MAAM,QAAQ,UAAa,MAAM,QAAQ,GAAG;AAC9C,mBAAO;AAAA,cACL;AAAA,YACF;AAAA,UACF;AACA,cAAI,MAAM,UAAU,UAAa,MAAM,QAAQ,KAAQ;AACrD,mBAAO;AAAA,cACL,yMAAkI,MAAM,KAAK;AAAA,YAC/I;AAAA,UACF;AAAA,QACF,WAAW,MAAM,mBAAmB,GAAG;AAErC,cAAI,MAAM,QAAQ,UAAa,MAAM,MAAM,KAAO;AAChD,mBAAO;AAAA,cACL,oOAAqI,MAAM,GAAG;AAAA,YAChJ;AAAA,UACF;AACA,cAAI,MAAM,UAAU,UAAa,MAAM,QAAQ,KAAK;AAClD,mBAAO;AAAA,cACL,2KAAoG,MAAM,KAAK;AAAA,YACjH;AAAA,UACF,WAAW,MAAM,UAAU,UAAa,MAAM,QAAQ,KAAM;AAC1D,qBAAS;AAAA,cACP;AAAA,YACF;AAAA,UACF;AAAA,QACF,WAAW,MAAM,mBAAmB,QAAW;AAC7C,iBAAO;AAAA,YACL;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,QAAQ,SAAS,eAAe,SAAS;AAElD,UAAI,MAAM,SAAS,KAAK,MAAM,SAAS,GAAG;AACxC,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,SAAS,GAAG;AACpB,YAAI,MAAM,mBAAmB,GAAG;AAC9B,iBAAO;AAAA,YACL;AAAA,UACF;AAAA,QACF;AACA,YAAI,MAAM,QAAQ,UAAa,MAAM,QAAQ,GAAG;AAC9C,iBAAO;AAAA,YACL;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,UAAU,UAAa,MAAM,QAAQ,KAAK,MAAM,QAAQ,KAAQ;AACxE,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,QAAQ,YAAa,QAAQ,SAAiB,iBAAiB,QAAW;AAC5E,YAAM,eAAgB,QAAQ,SAAiB;AAC/C,UAAI,iBAAiB,KAAK,iBAAiB,GAAG;AAC5C,eAAO,KAAK,yKAA8G;AAAA,MAC5H;AACA,WAAK,MAAM,cAAc,KAAK,MAAM,cAAc,MAAM,iBAAiB,GAAG;AAC1E,iBAAS,KAAK,gLAA+G;AAAA,MAC/H;AAAA,IACF;AAGA,QAAI,MAAM,mBAAmB,KAAK,MAAM,UAAU,UAAa,MAAM,QAAQ,KAAK,MAAM,QAAQ,IAAI;AAClG,eAAS,KAAK,2IAA4D;AAAA,IAC5E;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,UAAU;AACpC,MAAI,WAAW;AAEb,UAAM,UAAU,UAAU;AAC1B,UAAM,UAAU,UAAU;AAC1B,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,YAAM,kBAAkB,CAAC,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,WAAW,SAAS,SAAS,SAAS,SAAS,SAAS,OAAO;AAC9I,YAAM,UAAU,QAAQ,OAAO,OAAK,CAAC,gBAAgB,SAAS,OAAO,CAAC,CAAC,CAAC;AACxE,UAAI,QAAQ,SAAS,GAAG;AACtB,iBAAS,KAAK,mDAAmC,QAAQ,KAAK,IAAI,CAAC,GAAG;AAAA,MACxE;AAAA,IACF,WAAW,WAAW,QAAQ,SAAS,GAAG;AACxC,YAAM,YAAY,OAAO,OAAO,iBAAiB;AACjD,YAAM,cAAc,QAAQ,OAAO,OAAK,CAAC,UAAU,SAAS,CAAQ,CAAC;AACrE,UAAI,YAAY,SAAS,GAAG;AAC1B,eAAO,KAAK,0DAAgC,YAAY,KAAK,IAAI,CAAC,uBAAa,UAAU,KAAK,IAAI,CAAC,GAAG;AAAA,MACxG;AAAA,IACF;AAGA,UAAM,SAAS,UAAU,MAAM,UAAU;AACzC,QAAI,UAAU,OAAO,SAAS,GAAG;AAC/B,YAAM,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC;AAC3B,YAAM,YAAY,OAAO,OAAO,QAAM,CAAC,QAAQ,SAAS,OAAO,EAAE,CAAC,CAAC;AACnE,UAAI,UAAU,SAAS,GAAG;AACxB,eAAO,KAAK,mEAAiC,UAAU,KAAK,IAAI,CAAC,mDAAyC;AAAA,MAC5G;AAAA,IACF;AAGA,UAAM,eAAgB,QAAQ,UAAkB;AAChD,QACE,iBAAiB,UACjB,iBAAiB,oBAAoB,YACrC,iBAAiB,oBAAoB,UACrC;AACA,eAAS;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAGA,UAAM,WAAW,UAAU;AAC3B,QAAI,UAAU;AACZ,YAAM,YAAY,SAAS,iBAAiB,SAAS;AACrD,UAAI,aAAa,MAAM,QAAQ,UAAU,QAAQ,GAAG;AAClD,cAAM,eAAyB,CAAC,GAAG,GAAG,CAAC;AACvC,mBAAW,QAAQ,UAAU,UAAU;AACrC,cAAI,CAAC,aAAa,SAAS,OAAO,KAAK,EAAE,CAAC,GAAG;AAC3C,qBAAS;AAAA,cACP,gCAAqB,KAAK,EAAE;AAAA,YAC9B;AAAA,UACF;AACA,cAAI,KAAK,aAAa,CAAC,MAAM,QAAQ,KAAK,SAAS,GAAG;AACpD,qBAAS,KAAK,2DAAyC,KAAK,EAAE,yDAA+B;AAAA,UAC/F,WAAW,MAAM,QAAQ,KAAK,SAAS,GAAG;AACxC,uBAAW,QAAQ,KAAK,WAAW;AACjC,kBAAI,CAAC,KAAK,MAAM,OAAO,KAAK,OAAO,UAAU;AAC3C,yBAAS;AAAA,kBACP,yBAAiB,KAAK,UAAU,IAAI,CAAC,6BAAqB,KAAK,EAAE;AAAA,gBACnE;AAAA,cACF,OAAO;AACL,sBAAM,YAAY,4BAA4B,KAAK,EAAE;AACrD,oBAAI,WAAW;AACb,yBAAO;AAAA,oBACL,oBAAY,KAAK,EAAE,MAAM,UAAU,IAAI,8FAA+C,UAAU,OAAO,oDAC3E,UAAU,OAAO;AAAA,kBAC/C;AAAA,gBACF,OAAO;AACL,wBAAM,sBAAsB,+BAA+B,OAAO,KAAK,EAAE,CAAC,KAAK,CAAC;AAChF,sBAAI,CAAC,oBAAoB,SAAS,KAAK,EAAE,GAAG;AAC1C,0BAAM,eAAe,OAAO,KAAK,8BAA8B,EAAE,KAAK,OAAK,+BAA+B,OAAO,CAAC,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;AACtI,2BAAO;AAAA,sBACL,oBAAY,KAAK,EAAE,sFAAoD,KAAK,EAAE,qFAC7E,eAAe,mCAAqB,YAAY,OAAO;AAAA,oBAC1D;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AACA,kBAAI,KAAK,aAAa,CAAC,MAAM,QAAQ,KAAK,SAAS,GAAG;AACpD,yBAAS,KAAK,mDAA+B,KAAK,EAAE,qFAA+C;AAAA,cACrG;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,QAAQ,kBAAkB,QAAW;AACvC,UAAM,sBAAgC,OAAO,OAAO,oBAAoB;AACxE,QAAI,CAAC,oBAAoB,SAAS,QAAQ,aAAuB,GAAG;AAClE,eAAS;AAAA,QACP,kBAAkB,QAAQ,aAAa;AAAA,MACzC;AAAA,IACF;AACA,QAAI,QAAQ,kBAAkB,qBAAqB,QAAQ,CAAC,QAAQ,gBAAgB,QAAQ,gBAAgB,IAAI;AAC9G,eAAS;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,eAAe,MAAM;AACxC,QAAI,CAAC,QAAQ,cAAc,CAAC,QAAQ,WAAW,KAAK,GAAG;AACrD,aAAO,KAAK,iGAA6D;AAAA,IAC3E;AAAA,EACF,WAAW,QAAQ,SAAS,eAAe,SAAS;AAClD,QAAI,CAAC,QAAQ,UAAU,OAAO,SAAS;AACrC,aAAO,KAAK,sHAA6E;AAAA,IAC3F;AACA,QAAI,CAAC,QAAQ,cAAc,QAAQ,cAAc,GAAG;AAClD,aAAO;AAAA,QACL;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,QAAQ,YAAY;AACvB,eAAS,KAAK,uNAAmH;AAAA,IACnI;AACA,QAAK,QAAQ,UAAU,OAAe,aAAc,QAAQ,UAAU,OAAe,UAAU,SAAS,GAAG;AACzG,aAAO;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,QAAQ,SAAS,eAAe,UAAU;AACnD,QAAI,CAAC,QAAQ,cAAc,QAAQ,cAAc,GAAG;AAClD,aAAO,KAAK,qHAAiF;AAAA,IAC/F;AAAA,EACF,WAAW,QAAQ,SAAS,eAAe,OAAO;AAChD,QAAI,CAAC,QAAQ,eAAe,CAAC,QAAQ,UAAU,OAAO,UAAU;AAC9D,aAAO,KAAK,qIAA4F;AAAA,IAC1G;AACA,QAAI,QAAQ,UAAU,OAAO,YAAY,CAAC,QAAQ,SAAS,MAAM,SAAS,SAAS,WAAW,GAAG;AAC/F,eAAS,KAAK,6GAAsE;AAAA,IACtF;AAAA,EACF,WAAW,QAAQ,SAAS,eAAe,SAAS;AAClD,QAAI,CAAC,QAAQ,cAAc,CAAE,QAAgB,WAAW;AACtD,aAAO,KAAK,gIAA+E;AAAA,IAC7F;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,6BAA6B,QAMhB;AAC3B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,QAAM,KAAK,OAAO,UAAU,OAAO;AACnC,QAAM,OAAO,OAAO,WAAW,OAAO,WAAW,OAAO;AAExD,MAAI,CAAC,MAAM,MAAM,GAAG;AAClB,WAAO,KAAK,2FAA4D;AAAA,EAC1E;AACA,MAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,GAAG;AACzB,WAAO,KAAK,mJAA2E;AAAA,EACzF,WAAW,KAAK,SAAS,KAAK;AAC5B,WAAO,KAAK,8CAA2B,KAAK,MAAM,sBAAc;AAAA,EAClE;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,mCAAmC,QAItB;AAC3B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,OAAO,cAAc,OAAO,cAAc,GAAG;AAChD,WAAO,KAAK,0DAAqC;AAAA,EACnD;AAGA,MAAI,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE,EAAE,SAAS,OAAO,MAAM,GAAG;AAC1C,WAAO,KAAK,WAAW,OAAO,MAAM,0IAAiF;AAAA,EACvH;AAGA,MAAI,OAAO,WAAW,KAAK,OAAO,SAAS;AACzC,aAAS;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,0BAA0B,QAGb;AAC3B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,QAAM,KAAK,OAAO,QAAQ,OAAO;AACjC,MAAI,CAAC,MAAM,MAAM,GAAG;AAClB,WAAO,KAAK,4HAAwE;AAAA,EACtF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,wBACd,OACsD;AACtD,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,wIAA8D;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,IAAI,QAAQ,IAAI;AAE7B,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,uEAAsC;AAAA,EACpD,WAAW,OAAO,SAAS,YAAY,CAAC,+BAA+B,KAAK,KAAK,KAAK,CAAC,GAAG;AACxF,WAAO,KAAK,8HAAyE;AAAA,EACvF;AAEA,QAAM,IAAI,IAAI,MAAM,SAAY,OAAO,IAAI,CAAC,IAAI;AAChD,QAAM,IAAI,IAAI,MAAM,SAAY,OAAO,IAAI,CAAC,IAAI;AAChD,QAAM,QAAQ,IAAI,UAAU,SAAY,OAAO,IAAI,KAAK,IAAI;AAC5D,QAAM,SAAS,IAAI,WAAW,SAAY,OAAO,IAAI,MAAM,IAAI;AAC/D,QAAM,QAAQ,IAAI,UAAU,SAAY,OAAO,IAAI,KAAK,IAAI;AAE5D,MAAI,MAAM,CAAC,KAAK,IAAI,GAAG;AACrB,WAAO,KAAK,uDAA2B,IAAI,CAAC,mDAAgC;AAAA,EAC9E;AACA,MAAI,MAAM,CAAC,KAAK,IAAI,GAAG;AACrB,WAAO,KAAK,uDAA2B,IAAI,CAAC,mDAAgC;AAAA,EAC9E;AACA,MAAI,MAAM,KAAK,KAAK,QAAQ,GAAG;AAC7B,WAAO,KAAK,6EAAiD,IAAI,KAAK,4CAAyB;AAAA,EACjG;AACA,MAAI,MAAM,MAAM,KAAK,SAAS,GAAG;AAC/B,WAAO,KAAK,wEAAiD,IAAI,MAAM,4CAAyB;AAAA,EAClG;AACA,MAAI,MAAM,KAAK,KAAK,SAAS,GAAG;AAC9B,WAAO,KAAK,mEAAyC,IAAI,KAAK,mDAA4B;AAAA,EAC5F;AAEA,MAAK,QAAQ,KAAK,WAAW,KAAO,SAAS,KAAK,UAAU,GAAI;AAC9D,WAAO,KAAK,uIAAqE;AAAA,EACnF;AAEA,MAAI,QAAQ,KAAK,SAAS,GAAG;AAC3B,UAAM,QAAQ,QAAQ;AACtB,UAAM,cAAc,KAAK,IAAI,QAAQ,IAAI,IAAI,OAAO,KAAK,IAAI,QAAQ,IAAI,IAAI,OAAO,KAAK,IAAI,QAAQ,IAAI,IAAI;AAC7G,UAAM,WAAW,KAAK,IAAI,QAAQ,CAAG,IAAI;AACzC,UAAM,aAAa,KAAK,IAAI,QAAQ,MAAM,IAAI;AAC9C,QAAI,CAAC,eAAe,CAAC,YAAY,CAAC,YAAY;AAC5C,eAAS,KAAK,mCAAoB,KAAK,IAAI,MAAM,MAAM,MAAM,QAAQ,CAAC,CAAC,yLAAsH;AAAA,IAC/L;AAAA,EACF;AAEA,QAAM,YAAwC;AAAA,IAC5C,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAOO,SAAS,+BACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2HAA6D;AAAA,EAC3E,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4GAAwD;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,UAAU,QAAQ,UAAU,GAAG;AAC1C,WAAO,KAAK,kLAA4G;AAAA,EAC1H;AAEA,MAAI,QAAQ,cAAc,UAAa,QAAQ,cAAc,QAAQ,QAAQ,aAAa,GAAG;AAC3F,aAAS,KAAK,mIAAuF;AAAA,EACvG;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,SAAS;AAC1D;AAMO,SAAS,8BACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2HAA6D;AAAA,EAC3E,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4GAAwD;AAAA,EACtE;AAEA,MAAI,QAAQ,aAAa,CAAC,kBAAkB,KAAK,QAAQ,SAAS,GAAG;AACnE,WAAO,KAAK,4IAA6E;AAAA,EAC3F;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,SAAS;AAC1D;AAOO,SAAS,8BACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2HAA6D;AAAA,EAC3E,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4GAAwD;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,cAAc,YAAY,CAAC,QAAQ,UAAU,KAAK,GAAG;AAC5F,WAAO,KAAK,mHAAuE;AAAA,EACrF,WAAW,CAAC,kBAAkB,KAAK,QAAQ,SAAS,GAAG;AACrD,WAAO,KAAK,gKAA8F;AAAA,EAC5G;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,SAAS;AAC1D;AAMO,SAAS,2BACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2HAA6D;AAAA,EAC3E,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4GAAwD;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,UAAU,QAAQ,UAAU,GAAG;AAC1C,WAAO,KAAK,8KAAwG;AAAA,EACtH;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,SAAS;AAC1D;AAMO,SAAS,8BACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2HAA6D;AAAA,EAC3E,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4GAAwD;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,UAAU,QAAQ,UAAU,GAAG;AAC1C,WAAO,KAAK,uLAA4G;AAAA,EAC1H;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,SAAS;AAC1D;AAMO,SAAS,sCACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2HAA6D;AAAA,EAC3E,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4GAAwD;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,UAAU,QAAQ,UAAU,GAAG;AAC1C,WAAO,KAAK,+LAAyH;AAAA,EACvI;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,SAAS;AAC1D;AAMO,SAAS,8BACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2HAA6D;AAAA,EAC3E,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4GAAwD;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,UAAU,QAAQ,UAAU,GAAG;AAC1C,WAAO,KAAK,0LAA4G;AAAA,EAC1H;AAEA,MAAI,CAAC,QAAQ,aAAa,QAAQ,aAAa,GAAG;AAChD,WAAO,KAAK,4NAAiI;AAAA,EAC/I;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,SAAS;AAC1D;AAOO,SAAS,4BACd,SACA,UAAmC,CAAC,GACV;AAC1B,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,QAAQ,KAAK,KAAK,GAAG;AAC7E,WAAO,KAAK,2HAA6D;AAAA,EAC3E,WAAW,QAAQ,KAAK,SAAS,KAAK;AACpC,WAAO,KAAK,4GAAwD;AAAA,EACtE;AAEA,MAAI,CAAC,QAAQ,aAAa,OAAO,QAAQ,cAAc,YAAY,CAAC,QAAQ,UAAU,KAAK,GAAG;AAC5F,WAAO,KAAK,iHAAqE;AAAA,EACnF,WAAW,CAAC,kBAAkB,KAAK,QAAQ,SAAS,GAAG;AACrD,WAAO,KAAK,gKAA8F;AAAA,EAC5G;AAEA,SAAO,EAAE,SAAS,OAAO,WAAW,GAAG,QAAQ,SAAS;AAC1D;AAMO,SAAS,wBACd,SACA,UAA6B,CAAC,GACJ;AAC1B,SAAO,wBAAwB,EAAE,GAAG,SAAS,MAAM,eAAe,QAAQ,GAAG,OAAO;AACtF;AAEO,SAAS,wBACd,SACA,UAA6B,CAAC,GACJ;AAC1B,SAAO,wBAAwB,EAAE,GAAG,SAAS,MAAM,eAAe,QAAQ,GAAG,OAAO;AACtF;AAEO,SAAS,sBACd,SACA,UAA6B,CAAC,GACJ;AAC1B,SAAO,wBAAwB,EAAE,GAAG,SAAS,MAAM,eAAe,MAAM,GAAG,OAAO;AACpF;AAEO,SAAS,yBACd,SACA,UAA6B,CAAC,GACJ;AAC1B,SAAO,wBAAwB,EAAE,GAAG,SAAS,MAAM,eAAe,SAAS,GAAG,OAAO;AACvF;AAEO,SAAS,qBACd,SACA,UAA6B,CAAC,GACJ;AAC1B,SAAO,wBAAwB,EAAE,GAAG,SAAS,MAAM,eAAe,KAAK,GAAG,OAAO;AACnF;AAEO,SAAS,wBACd,SACA,UAA6B,CAAC,GACJ;AAC1B,SAAO,wBAAwB,EAAE,GAAG,SAAS,MAAM,eAAe,QAAQ,GAAG,OAAO;AACtF;AAEO,SAAS,gCACd,SACA,UAA6B,CAAC,GACJ;AAC1B,SAAO,wBAAwB,EAAE,GAAG,SAAS,MAAM,eAAe,GAAG,GAAG,OAAO;AACjF;AAEO,SAAS,wBACd,SACA,UAA6B,CAAC,GACJ;AAC1B,SAAO,wBAAwB,EAAE,GAAG,SAAS,MAAM,eAAe,QAAQ,GAAG,OAAO;AACtF;AAGO,IAAM,yBAAyB;AAAA;AAAA,EAEpC,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,aAAa;AAAA,EACb;AAAA,EACA,2BAA2B;AAAA;AAAA,EAG3B,wBAAwB;AAAA,EACxB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,+BAA+B;AAAA,EAC/B,uBAAuB;AAAA,EACvB,qBAAqB;AAAA;AAAA,EAGrB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,yBAAyB;AAAA,EACzB,iBAAiB;AACnB;;;ACniCA,IAAM,0BAA+C;AAAA,EACnD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,QAAQ,OAAO,aAAa,KAAK;AAChD;AAEA,IAAM,iCAAsD;AAAA,EAC1D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,uBAA4C;AAAA,EAChD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,+BAAoD;AAAA,EACxD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,kCAAuD;AAAA,EAC3D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,0CAA+D;AAAA,EACnE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,+BAAoD;AAAA,EACxD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,sBAA2C;AAAA,EAC/C,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,2BAAgD;AAAA,EACpD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,uCAA4D;AAAA,EAChE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,+BAAoD;AAAA,EACxD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,wCAA6D;AAAA,EACjE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,yCAA8D;AAAA,EAClE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,qCAA0D;AAAA,EAC9D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,kCAAuD;AAAA,EAC3D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,uCAA4D;AAAA,EAChE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,8BAAmD;AAAA,EACvD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,2BAAgD;AAAA,EACpD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,8BAAmD;AAAA,EACvD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,yBAA8C;AAAA,EAClD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,4BAAiD;AAAA,EACrD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,yBAA8C;AAAA,EAClD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB;AAAA,IACd;AAAA,EACF;AAAA,EACA,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,yBAA8C;AAAA,EAClD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,kCAAuD;AAAA,EAC3D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,4BAAiD;AAAA,EACrD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,kCAAuD;AAAA,EAC3D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,4BAAiD;AAAA,EACrD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAM,2BAAgD;AAAA,EACpD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,wBAA6C;AAAA,EACjD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,MAAM;AACrB;AAEA,IAAM,kCAAuD;AAAA,EAC3D,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,SAAS,SAAS;AACjC;AAEA,IAAM,+BAAoD;AAAA,EACxD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,OAAO;AAAA,EACpB,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AACf;AAEO,IAAM,uBAAN,MAA2B;AAAA,EAIzB,YAA+B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EAHlD,YAAY;AAAA,EAC5B,OAAuB,YAAY;AAAA,EAI1B,cAAc,SAA0C,SAAqE;AACpI,WAAO,KAAK,OAAO,sBAAwD,yBAAyB,KAAK,OAAO,iBAAiB,yBAAyB,OAA6C,GAAG,OAAO;AAAA,EACnN;AAAA,EAES,qBAAqB,SAAiD,SAA4E;AACzJ,WAAO,KAAK,OAAO,sBAA+D,gCAAgC,KAAK,OAAO,iBAAiB,gCAAgC,OAAkC,GAAG,OAAO;AAAA,EAC7N;AAAA,EAES,eAAe,SAA2C,SAAsE;AACvI,UAAM,UAAU,EAAE,YAAY,QAAQ,YAAY,QAAQ,QAAQ,UAAU,GAAG;AAC/E,WAAO,KAAK,OAAO,sBAAyD,0BAA0B,KAAK,OAAO,iBAAiB,0BAA0B,OAAkC,GAAG,OAAO;AAAA,EAC3M;AAAA,EAES,sBAAsB,SAAkD,SAA6E;AAC5J,WAAO,KAAK,OAAO,sBAAgE,iCAAiC,KAAK,OAAO,iBAAiB,iCAAiC,OAAkC,GAAG,OAAO;AAAA,EAChO;AAAA,EAES,gBAAgB,SAA4C,SAAuE;AAC1I,WAAO,KAAK,OAAO,sBAA0D,2BAA2B,KAAK,OAAO,iBAAiB,2BAA2B,OAAkC,GAAG,OAAO;AAAA,EAC9M;AAAA,EAES,sBAAsB,SAAkD,SAA6E;AAC5J,WAAO,KAAK,OAAO,sBAAgE,iCAAiC,KAAK,OAAO,iBAAiB,iCAAiC,OAAkC,GAAG,OAAO;AAAA,EAChO;AAAA,EAES,gBAAgB,SAA4C,SAAuE;AAC1I,WAAO,KAAK,OAAO,sBAA0D,2BAA2B,KAAK,OAAO,iBAAiB,2BAA2B,OAAkC,GAAG,OAAO;AAAA,EAC9M;AAAA,EAES,oBAAoB,SAAgD,SAA2E;AACtJ,WAAO,KAAK,OAAO,sBAA8D,+BAA+B,KAAK,OAAO,iBAAiB,+BAA+B,OAAkC,GAAG,OAAO;AAAA,EAC1N;AAAA,EAES,wBAAwB,SAAoD,SAA+E;AAClK,WAAO,KAAK,OAAO,sBAAkE,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACtO;AAAA;AAAA,EAGS,uBAAuB,SAAmD,SAA8E;AAC/J,WAAO,KAAK,wBAAwB,SAAS,OAAO;AAAA,EACtD;AAAA,EAES,WAAW,SAAuC,SAAkE;AAC3H,WAAO,KAAK,OAAO,sBAAqD,sBAAsB,KAAK,OAAO,iBAAiB,sBAAsB,OAAkC,GAAG,OAAO;AAAA,EAC/L;AAAA,EAES,mBAAmB,SAA+C,SAA0E;AACnJ,WAAO,KAAK,OAAO,sBAA6D,8BAA8B,KAAK,OAAO,iBAAiB,8BAA8B,OAAkC,GAAG,OAAO;AAAA,EACvN;AAAA,EAES,sBAAsB,SAAkD,SAA6E;AAC5J,WAAO,KAAK,OAAO,sBAAgE,iCAAiC,KAAK,OAAO,iBAAiB,iCAAiC,OAAkC,GAAG,OAAO;AAAA,EAChO;AAAA,EAES,8BAA8B,SAA0D,SAAqF;AACpL,WAAO,KAAK,OAAO,sBAAwE,yCAAyC,KAAK,OAAO,iBAAiB,yCAAyC,OAAkC,GAAG,OAAO;AAAA,EACxP;AAAA;AAAA,EAGS,iBAAiB,SAA6C,SAAwE;AAC7I,WAAO,KAAK,8BAA8B,SAAS,OAAO;AAAA,EAC5D;AAAA,EAES,mBAAmB,SAA+C,SAA0E;AACnJ,WAAO,KAAK,OAAO,sBAA6D,8BAA8B,KAAK,OAAO,iBAAiB,8BAA8B,OAA6C,GAAG,OAAO;AAAA,EAClO;AAAA;AAAA,EAGS,sBAAsB,SAAkD,SAA6E;AAC5J,WAAO,KAAK,mBAAmB,SAAS,OAAO;AAAA,EACjD;AAAA,EAES,UAAU,UAAuC,CAAC,GAAG,SAAiE;AAC7H,UAAM,aAAa;AAAA,MACjB,MAAM,QAAQ;AAAA,MACd,GAAG,QAAQ,KAAK;AAAA,MAChB,SAAS,QAAQ,WAAW;AAAA,IAC9B;AACA,WAAO,KAAK,OAAO,mBAAiD,qBAAqB,KAAK,OAAO,iBAAiB,qBAAqB,UAAqC,GAAG,OAAO;AAAA,EAC5L;AAAA,EAES,eAAe,SAA2C,SAAsE;AACvI,UAAM,aAAa;AAAA,MACjB,MAAM,QAAQ;AAAA,MACd,MAAO,QAAgB,QAAQ;AAAA,IACjC;AACA,WAAO,KAAK,OAAO,mBAAsD,0BAA0B,KAAK,OAAO,iBAAiB,0BAA0B,UAAU,GAAG,OAAO;AAAA,EAChL;AAAA,EAES,2BAA2B,UAAwD,CAAC,GAAG,SAAkF;AAChL,WAAO,KAAK,OAAO,mBAAkE,sCAAsC,KAAK,OAAO,iBAAiB,sCAAsC,OAAkC,GAAG,OAAO;AAAA,EAC5O;AAAA,EAES,mBAAmB,SAA+C,SAA0E;AACnJ,WAAO,KAAK,OAAO,mBAA0D,8BAA8B,KAAK,OAAO,iBAAiB,8BAA8B,OAAkC,GAAG,OAAO;AAAA,EACpN;AAAA,EAES,4BAA4B,UAAyD,CAAC,GAAG,SAAmF;AACnL,WAAO,KAAK,OAAO,mBAAmE,uCAAuC,KAAK,OAAO,iBAAiB,uCAAuC,OAAkC,GAAG,OAAO;AAAA,EAC/O;AAAA,EAES,6BAA6B,UAA0D,CAAC,GAAG,SAAoF;AACtL,UAAM,aAAa;AAAA,MACjB,YAAY,QAAQ,cAAc,QAAQ;AAAA,MAC1C,UAAU,QAAQ,YAAY;AAAA,MAC9B,GAAG,QAAQ,KAAK;AAAA,IAClB;AACA,WAAO,KAAK,OAAO,mBAAoE,wCAAwC,KAAK,OAAO,iBAAiB,wCAAwC,UAAqC,GAAG,OAAO;AAAA,EACrP;AAAA;AAAA,EAGO,qBAAqB,UAA0D,CAAC,GAAG,SAAoF;AAC5K,WAAO,KAAK,6BAA6B,SAAS,OAAO;AAAA,EAC3D;AAAA,EAES,oBAAoB,UAAiD,CAAC,GAAG,SAA2E;AAC3J,WAAO,KAAK,OAAO,mBAA2D,+BAA+B,KAAK,OAAO,iBAAiB,+BAA+B,OAAkC,GAAG,OAAO;AAAA,EACvN;AAAA,EAES,YAAY,UAAiD,CAAC,GAAG,SAA2E;AACnJ,WAAO,KAAK,oBAAoB,SAAS,OAAO;AAAA,EAClD;AAAA,EAES,yBAAyB,SAAqD,SAAgF;AACrK,WAAO,KAAK,OAAO,mBAAgE,oCAAoC,KAAK,OAAO,iBAAiB,oCAAoC,OAAkC,GAAG,OAAO;AAAA,EACtO;AAAA,EAES,iBAAiB,SAAqD,SAAgF;AAC7J,WAAO,KAAK,yBAAyB,SAAS,OAAO;AAAA,EACvD;AAAA,EAES,sBAAsB,UAAmD,CAAC,GAAG,SAA6E;AACjK,WAAO,KAAK,OAAO,mBAA6D,iCAAiC,KAAK,OAAO,iBAAiB,iCAAiC,OAAkC,GAAG,OAAO;AAAA,EAC7N;AAAA,EAES,cAAc,UAAmD,CAAC,GAAG,SAA6E;AACzJ,WAAO,KAAK,sBAAsB,SAAS,OAAO;AAAA,EACpD;AAAA,EAES,2BAA2B,SAAuD,SAAkF;AAC3K,WAAO,KAAK,OAAO,mBAAkE,sCAAsC,KAAK,OAAO,iBAAiB,sCAAsC,OAAkC,GAAG,OAAO;AAAA,EAC5O;AAAA,EAES,wBAAwB,SAAoD,SAA+E;AAClK,WAAO,KAAK,OAAO,mBAA+D,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACnO;AAAA,EAES,kBAAkB,UAA+C,CAAC,GAAG,SAAyE;AACrJ,WAAO,KAAK,OAAO,mBAAyD,6BAA6B,KAAK,OAAO,iBAAiB,6BAA6B,OAAkC,GAAG,OAAO;AAAA,EACjN;AAAA,EAES,eAAe,SAA2C,SAAsE;AACvI,UAAM,aAAa;AAAA,MACjB,QAAS,QAAgB,UAAW,QAAgB;AAAA,MACpD,SAAU,QAAgB,WAAY,QAAgB,gBAAiB,QAAgB;AAAA,IACzF;AACA,WAAO,KAAK,OAAO,sBAAyD,0BAA0B,KAAK,OAAO,iBAAiB,0BAA0B,UAAU,GAAG,OAAO;AAAA,EACnL;AAAA,EAES,kBAAkB,SAA8C,SAAyE;AAChJ,WAAO,KAAK,OAAO,sBAA4D,6BAA6B,KAAK,OAAO,iBAAiB,6BAA6B,OAAkC,GAAG,OAAO;AAAA,EACpN;AAAA;AAAA,EAGS,iBAAiB,SAA6C,SAAwE;AAC7I,WAAO,KAAK,kBAAkB,SAAS,OAAO;AAAA,EAChD;AAAA,EAES,aAAa,SAAyC,SAAoE;AACjI,WAAO,KAAK,OAAO,sBAAuD,wBAAwB,KAAK,OAAO,iBAAiB,wBAAwB,OAAkC,GAAG,OAAO;AAAA,EACrM;AAAA,EAES,gBAAgB,SAA4C,SAAuE;AAC1I,WAAO,KAAK,OAAO,sBAA0D,2BAA2B,KAAK,OAAO,iBAAiB,2BAA2B,OAA6C,GAAG,OAAO;AAAA,EACzN;AAAA,EAES,aAAa,SAAyC,SAAoE;AACjI,WAAO,KAAK,OAAO,iBAAkD,wBAAwB,KAAK,OAAO,iBAAiB,wBAAwB,OAAkC,GAAG,OAAO;AAAA,EAChM;AAAA,EAES,wBAAwB,SAAoD,SAA+E;AAClK,WAAO,KAAK,OAAO,sBAAkE,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACtO;AAAA;AAAA,EAGS,WAAW,SAAuC,SAAkE;AAC3H,WAAO,KAAK,wBAAwB,SAAS,OAAO;AAAA,EACtD;AAAA,EAES,aAAa,SAAyC,SAAoE;AACjI,WAAO,KAAK,OAAO,sBAAuD,wBAAwB,KAAK,OAAO,iBAAiB,wBAAwB,OAAkC,GAAG,OAAO;AAAA,EACrM;AAAA;AAAA,EAGS,gBAAgB,SAA4C,SAAuE;AAC1I,WAAO,KAAK,aAAa,SAAS,OAAO;AAAA,EAC3C;AAAA;AAAA,EAGO,YAAY,MAAoF;AACrG,WAAQ,KAAK,kBAA0B,GAAG,IAAI;AAAA,EAChD;AAAA;AAAA,EAGO,mBAAmB,MAAsG;AAC9H,WAAQ,KAAK,2BAAmC,GAAG,IAAI;AAAA,EACzD;AAAA;AAAA,EAGO,mBAAmB,MAAsF;AAC9G,WAAQ,KAAK,mBAA2B,GAAG,IAAI;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKO,sBACL,SACA,SACmD;AACnD,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,iCAAiC,OAAkC;AAAA,MAChG;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,mBACL,SACA,SACgD;AAChD,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,8BAA8B,OAAkC;AAAA,MAC7F;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,oBACX,SACA,iBAAyB,KACzB,YAAoB,MACpB,SACgD;AAChD,UAAM,SAAS,MAAM,KAAK,sBAAsB,SAAS,OAAO;AAChE,UAAM,QAAQ,QAAQ,MAAM;AAC5B,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,uFAA2D,QAAQ,IAAI,GAAG;AAAA,IAC5F;AAEA,UAAM,YAAY,KAAK,IAAI;AAC3B,WAAO,KAAK,IAAI,IAAI,YAAY,WAAW;AACzC,YAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,cAAc,CAAC;AACpD,YAAM,MAAM,MAAM,KAAK,mBAAmB,EAAE,MAAM,GAAG,OAAO;AAC5D,UAAI,KAAK,MAAM,WAAW,aAAa;AACrC,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,IAAI,MAAM,kDAAqC,SAAS,gEAA2C,KAAK,EAAE;AAAA,EAClH;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,YACL,SACA,SACyC;AACzC,UAAM,UAAU;AAAA,MACd,MAAM,QAAQ,QAAQ,QAAQ;AAAA,IAChC;AACA,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,uBAAuB,OAAkC;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AAEF;;;ACh2BA,IAAM,yBAA8C;AAAA,EAClD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,4CAAiE;AAAA,EACrE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,wCAA6D;AAAA,EACjE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,6CAAkE;AAAA,EACtE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,0CAA+D;AAAA,EACnE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,iCAAsD;AAAA,EAC1D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,yBAA8C;AAAA,EAClD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEO,IAAM,qBAAN,MAAyB;AAAA,EACvB,YAA+B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EAE3D,aAAa,UAA0C,CAAC,GAAG,SAAoE;AACpI,WAAO,KAAK,OAAO,mBAAoD,wBAAwB,KAAK,OAAO,iBAAiB,wBAAwB,OAAkC,GAAG,OAAO;AAAA,EAClM;AAAA,EAEO,gCAAgC,SAA4D,SAAuF;AACxL,WAAO,KAAK,OAAO,mBAAuE,2CAA2C,KAAK,OAAO,iBAAiB,2CAA2C,OAAkC,GAAG,OAAO;AAAA,EAC3P;AAAA,EAEO,4BAA4B,UAAyD,CAAC,GAAG,SAAmF;AACjL,WAAO,KAAK,OAAO,mBAAmE,uCAAuC,KAAK,OAAO,iBAAiB,uCAAuC,OAAkC,GAAG,OAAO;AAAA,EAC/O;AAAA,EAEO,iCAAiC,UAA8D,CAAC,GAAG,SAAwF;AAChM,WAAO,KAAK,OAAO,mBAAwE,4CAA4C,KAAK,OAAO,iBAAiB,4CAA4C,OAAkC,GAAG,OAAO;AAAA,EAC9P;AAAA,EAEO,8BAA8B,UAA2D,EAAE,OAAO,IAAI,QAAQ,GAAG,aAAa,KAAK,GAAG,SAAqF;AAChO,UAAM,aAAsC;AAAA,MAC1C,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,GAAG;AAAA,IACL;AACA,WAAO,KAAK,OAAO,mBAAqE,yCAAyC,KAAK,OAAO,iBAAiB,yCAAyC,UAAU,GAAG,OAAO;AAAA,EAC7N;AAAA,EAEO,wBAAwB,UAAqD,CAAC,GAAG,SAA+E;AACrK,WAAO,KAAK,OAAO,mBAA+D,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACnO;AAAA,EAEO,qBAAqB,UAAkD,CAAC,GAAG,SAA4E;AAC5J,WAAO,KAAK,OAAO,mBAA4D,gCAAgC,KAAK,OAAO,iBAAiB,gCAAgC,OAAkC,GAAG,OAAO;AAAA,EAC1N;AAAA,EAEO,aAAa,UAA0C,CAAC,GAAG,SAAoE;AACpI,WAAO,KAAK,OAAO,mBAAoD,wBAAwB,KAAK,OAAO,iBAAiB,wBAAwB,OAAkC,GAAG,OAAO;AAAA,EAClM;AAAA;AAAA,EAGO,aAAa,MAA0E;AAC5F,WAAQ,KAAK,aAAqB,GAAG,IAAI;AAAA,EAC3C;AAAA;AAAA,EAGO,gCAAgC,MAAgH;AACrJ,WAAQ,KAAK,gCAAwC,GAAG,IAAI;AAAA,EAC9D;AAAA;AAAA,EAGO,4BAA4B,MAAwG;AACzI,WAAQ,KAAK,4BAAoC,GAAG,IAAI;AAAA,EAC1D;AAAA;AAAA,EAGO,iCAAiC,MAAkH;AACxJ,WAAQ,KAAK,iCAAyC,GAAG,IAAI;AAAA,EAC/D;AAAA;AAAA,EAGO,wBAAwB,MAAgG;AAC7H,WAAQ,KAAK,wBAAgC,GAAG,IAAI;AAAA,EACtD;AAAA;AAAA,EAGO,qBAAqB,MAA0F;AACpH,WAAQ,KAAK,qBAA6B,GAAG,IAAI;AAAA,EACnD;AAAA;AAAA,EAGO,aAAa,MAA0E;AAC5F,WAAQ,KAAK,aAAqB,GAAG,IAAI;AAAA,EAC3C;AACF;;;AC5LA,IAAM,iCAAsD;AAAA,EAC1D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,iCAAsD;AAAA,EAC1D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,8CAAmE;AAAA,EACvE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,sCAA2D;AAAA,EAC/D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,0CAA+D;AAAA,EACnE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB;AAAA,IACd;AAAA,EACF;AAAA,EACA,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,uBAAN,MAA2B;AAAA,EAEzB,YAA+B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EADlE,OAAuB,YAAY;AAAA,EAG1B,0BAA0B,SAAsD,SAAiF;AACxK,WAAO,KAAK,OAAO,YAA0D,qCAAqC,KAAK,OAAO,iBAAiB,qCAAqC,OAAkC,GAAG,OAAO;AAAA,EAClO;AAAA,EAES,kCAAkC,UAA+D,CAAC,GAAG,SAAyF;AACrM,WAAO,KAAK,OAAO,mBAAyE,6CAA6C,KAAK,OAAO,iBAAiB,6CAA6C,OAAkC,GAAG,OAAO;AAAA,EACjQ;AAAA,EAES,wBAAwB,UAAqD,CAAC,GAAG,SAA+E;AACvK,WAAO,KAAK,OAAO,mBAA+D,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACnO;AAAA,EAES,qBAAqB,SAAiD,SAA4E;AACzJ,WAAO,KAAK,OAAO,YAAqD,gCAAgC,KAAK,OAAO,iBAAiB,gCAAgC,OAAkC,GAAG,OAAO;AAAA,EACnN;AAAA,EAES,qBAAqB,SAAiD,SAA4E;AACzJ,WAAO,KAAK,OAAO,mBAA4D,gCAAgC,KAAK,OAAO,iBAAiB,gCAAgC,OAAkC,GAAG,OAAO;AAAA,EAC1N;AAAA,EAES,8BAA8B,SAA0D,SAAqF;AACpL,WAAO,KAAK,OAAO,iBAAmE,yCAAyC,KAAK,OAAO,iBAAiB,yCAAyC,OAAkC,GAAG,OAAO;AAAA,EACnP;AAAA;AAAA,EAGS,oBAAoB,SAAgD,SAA2E;AACtJ,UAAM,eACJ,OAAO,QAAQ,cAAc,WACzB,QAAQ,YACR,KAAK,UAAU,QAAQ,SAAS;AACtC,WAAO,KAAK;AAAA,MACV;AAAA,QACE,MAAM,QAAQ;AAAA,QACd,QAAQ;AAAA,QACR,WAAW;AAAA,MACb;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGS,oBAAoB,SAAgD,SAA2E;AACtJ,UAAM,eAAe,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AACjH,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,GAAG,WAAW,aAAa,GAAG,OAAO;AAAA,EACtG;AAAA;AAAA,EAGS,wBAAwB,SAAoD,SAA+E;AAClK,UAAM,eAAe,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AACjH,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,GAAG,WAAW,aAAa,GAAG,OAAO;AAAA,EACtG;AAAA;AAAA,EAGS,wBAAwB,SAAoD,SAA+E;AAClK,UAAM,eAAe,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AACjH,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,IAAI,WAAW,aAAa,GAAG,OAAO;AAAA,EACvG;AAAA;AAAA,EAGS,6BAA6B,SAAyD,SAAoF;AACjL,UAAM,eAAe,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AACjH,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,IAAI,WAAW,aAAa,GAAG,OAAO;AAAA,EACvG;AAAA;AAAA,EAGO,mCAAmC,SAA+D,SAA0F;AACjM,QAAI;AACJ,QAAI,OAAO,QAAQ,cAAc,UAAU;AACzC,UAAI;AACF,uBAAe,KAAK,MAAM,QAAQ,SAAS;AAAA,MAC7C,QAAQ;AACN,uBAAe;AAAA,MACjB;AAAA,IACF,WAAW,QAAQ,aAAa,OAAO,QAAQ,cAAc,UAAU;AACrE,qBAAe,EAAE,GAAG,QAAQ,UAAU;AAAA,IACxC;AACA,QAAI,gBAAgB,OAAO,iBAAiB,UAAU;AACpD,UAAI,aAAa,YAAY,UAAa,aAAa,cAAc,QAAW;AAC9E,qBAAa,UAAU,aAAa;AAAA,MACtC;AAAA,IACF;AACA,UAAM,eAAe,eAAe,KAAK,UAAU,YAAY,IAAK,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AAChK,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,IAAI,WAAW,aAAa,GAAG,OAAO;AAAA,EACvG;AAAA;AAAA,EAGS,uBAAuB,SAAmD,SAA8E;AAC/J,UAAM,eAAe,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AACjH,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,IAAI,WAAW,aAAa,GAAG,OAAO;AAAA,EACvG;AAAA;AAAA,EAGS,2BAA2B,SAAuD,SAAkF;AAC3K,UAAM,eAAe,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AACjH,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,IAAI,WAAW,aAAa,GAAG,OAAO;AAAA,EACvG;AAAA;AAAA,EAGS,4BAA4B,SAAwD,SAAmF;AAC9K,UAAM,eAAe,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AACjH,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,IAAI,WAAW,aAAa,GAAG,OAAO;AAAA,EACvG;AAAA;AAAA,EAGS,yBAAyB,SAAqD,SAAgF;AACrK,UAAM,eAAe,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY,KAAK,UAAU,QAAQ,SAAS;AACjH,WAAO,KAAK,qBAAqB,EAAE,MAAM,QAAQ,MAAM,QAAQ,IAAI,WAAW,aAAa,GAAG,OAAO;AAAA,EACvG;AAAA;AAAA,EAGO,oBAAoB,MAAoG;AAC7H,WAAQ,KAAK,0BAAkC,GAAG,IAAI;AAAA,EACxD;AAAA;AAAA,EAGO,uBAAuB,MAAgG;AAC5H,WAAQ,KAAK,wBAAgC,GAAG,IAAI;AAAA,EACtD;AAAA;AAAA,EAGO,6BAA6B,MAAoH;AACtJ,WAAQ,KAAK,kCAA0C,GAAG,IAAI;AAAA,EAChE;AACF;;;ACrOA,IAAM,8BAAmD;AAAA,EACvD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,qCAA0D;AAAA,EAC9D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,8BAAmD;AAAA,EACvD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,kCAAuD;AAAA,EAC3D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,+BAAoD;AAAA,EACxD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,8BAAmD;AAAA,EACvD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,2CAAgE;AAAA,EACpE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,8BAAmD;AAAA,EACvD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,+BAAoD;AAAA,EACxD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGA,IAAM,2BAAgD;AAAA,EACpD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,qBAAN,MAAyB;AAAA,EACvB,YAA+B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EAEzD,kBAAkB,SAA8C,SAAyE;AAChJ,WAAO,KAAK,OAAO,mBAAyD,6BAA6B,KAAK,OAAO,iBAAiB,6BAA6B,OAAkC,GAAG,OAAO;AAAA,EACjN;AAAA,EAES,wBAAwB,UAAqD,CAAC,GAAG,SAA+E;AACvK,WAAO,KAAK,OAAO,mBAA+D,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACnO;AAAA,EAES,yBAAyB,SAAqD,SAAgF;AACrK,WAAO,KAAK,OAAO,mBAAgE,oCAAoC,KAAK,OAAO,iBAAiB,oCAAoC,OAAkC,GAAG,OAAO;AAAA,EACtO;AAAA,EAES,wBAAwB,SAAoD,SAA+E;AAClK,UAAM,aAAsC;AAAA,MAC1C,QAAQ;AAAA,MACR,GAAG;AAAA,IACL;AACA,WAAO,KAAK,OAAO,mBAA+D,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,UAAU,GAAG,OAAO;AAAA,EAC3M;AAAA,EAES,kBAAkB,SAA8C,SAAyE;AAChJ,WAAO,KAAK,OAAO,mBAAyD,6BAA6B,KAAK,OAAO,iBAAiB,6BAA6B,OAAkC,GAAG,OAAO;AAAA,EACjN;AAAA,EAES,sBAAsB,SAAkD,SAA6E;AAC5J,WAAO,KAAK,OAAO,mBAA6D,iCAAiC,KAAK,OAAO,iBAAiB,iCAAiC,OAAkC,GAAG,OAAO;AAAA,EAC7N;AAAA,EAES,+BAA+B,SAA2D,SAAsF;AACvL,WAAO,KAAK,OAAO,mBAAsE,0CAA0C,KAAK,OAAO,iBAAiB,0CAA0C,OAAkC,GAAG,OAAO;AAAA,EACxP;AAAA,EAES,kBAAkB,UAA+C,CAAC,GAAG,SAAyE;AACrJ,WAAO,KAAK,OAAO,mBAAyD,6BAA6B,KAAK,OAAO,iBAAiB,6BAA6B,OAAkC,GAAG,OAAO;AAAA,EACjN;AAAA,EAES,mBAAmB,SAA+C,SAA0E;AACnJ,WAAO,KAAK,OAAO,YAAmD,8BAA8B,KAAK,OAAO,iBAAiB,8BAA8B,OAAkC,GAAG,OAAO;AAAA,EAC7M;AAAA,EAES,mBAAmB,SAA+C,SAA0E;AACnJ,WAAO,KAAK,OAAO,YAAmD,8BAA8B,KAAK,OAAO,iBAAiB,8BAA8B,OAAkC,GAAG,OAAO;AAAA,EAC7M;AAAA,EAES,kBAAkB,SAA8C,SAAyE;AAChJ,WAAO,KAAK,OAAO,mBAAyD,6BAA6B,KAAK,OAAO,iBAAiB,6BAA6B,OAAkC,GAAG,OAAO;AAAA,EACjN;AAAA;AAAA,EAGO,uBAAuB,MAAgG;AAC5H,WAAQ,KAAK,wBAAgC,GAAG,IAAI;AAAA,EACtD;AAAA;AAAA,EAGO,uBAAuB,MAAgG;AAC5H,WAAQ,KAAK,wBAAgC,GAAG,IAAI;AAAA,EACtD;AAAA;AAAA,EAGO,kBAAkB,MAAoF;AAC3G,WAAQ,KAAK,kBAA0B,GAAG,IAAI;AAAA,EAChD;AAAA;AAAA,EAGO,uBAAuB,MAAkG;AAC9H,WAAQ,KAAK,yBAAiC,GAAG,IAAI;AAAA,EACvD;AAAA;AAAA,EAGO,2BAA2B,MAA8G;AAC9I,WAAQ,KAAK,+BAAuC,GAAG,IAAI;AAAA,EAC7D;AAAA;AAAA,EAGO,eAAe,SAA2C,SAAyC;AACxG,UAAM,UAAU;AAAA,MACd,GAAG,QAAQ,KAAK;AAAA,MAChB,QAAQ,QAAQ,UAAU;AAAA,MAC1B,YAAY,QAAQ,cAAc;AAAA,MAClC,YAAY,QAAQ,cAAc;AAAA,MAClC,IAAI,QAAQ,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,MAC9C,OAAO,QAAQ;AAAA,IACjB;AACA,WAAO,KAAK,OAAO,YAAkB,0BAA0B,KAAK,OAAO,iBAAiB,0BAA0B,OAAkC,GAAG,OAAO;AAAA,EACpK;AAEF;;;AC/SA,IAAM,6BAAkD;AAAA,EACtD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,6BAAkD;AAAA,EACtD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,2CAAgE;AAAA,EACpE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEO,IAAM,yBAAN,MAA6B;AAAA,EAC3B,YAA+B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EAEzD,iBAAiB,SAA6C,SAAwE;AAC7I,WAAO,KAAK,OAAO,YAAiD,4BAA4B,KAAK,OAAO,iBAAiB,4BAA4B,OAAkC,GAAG,OAAO;AAAA,EACvM;AAAA,EAES,iBAAiB,SAA6C,SAAwE;AAC7I,WAAO,KAAK,OAAO,mBAAwD,4BAA4B,KAAK,OAAO,iBAAiB,4BAA4B,OAAkC,GAAG,OAAO;AAAA,EAC9M;AAAA,EAES,oBAAoB,UAAiD,CAAC,GAAG,SAA2E;AAC3J,WAAO,KAAK,OAAO,mBAA2D,+BAA+B,KAAK,OAAO,iBAAiB,+BAA+B,OAAkC,GAAG,OAAO;AAAA,EACvN;AAAA,EAES,+BAA+B,UAA4D,CAAC,GAAG,SAAsF;AAC5L,WAAO,KAAK,OAAO,mBAAsE,0CAA0C,KAAK,OAAO,iBAAiB,0CAA0C,OAAkC,GAAG,OAAO;AAAA,EACxP;AAAA,EAES,wBAAwB,UAAqD,CAAC,GAAG,SAA+E;AACvK,WAAO,KAAK,OAAO,mBAA+D,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACnO;AAAA;AAAA,EAGS,kBAAkB,SAAyE;AAClG,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,QACE,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,SAAS;AAAA,QACT,cAAc,CAAC;AAAA,QACf,YAAY,CAAC;AAAA,QACb,aAAa,CAAC;AAAA,QACd,cAAc,CAAC;AAAA,QACf,cAAc,CAAC;AAAA,QACf,YAAY,CAAC;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGS,oBAAoB,UAAiD,CAAC,GAAG,SAA2E;AAC3J,UAAM,KAA0B;AAAA,MAC9B,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,SAAS;AAAA,MACT,cAAc,CAAC;AAAA,MACf,YAAY,CAAC;AAAA,MACb,aAAa,CAAC;AAAA,MACd,cAAc,CAAC;AAAA,MACf,cAAc,CAAC;AAAA,MACf,YAAY,CAAC;AAAA,IACf;AACA,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,IAAI,OAAkC;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGS,sBAAsB,UAAiD,CAAC,GAAG,SAA2E;AAC7J,WAAO,KAAK,oBAAoB,SAAS,OAAO;AAAA,EAClD;AAAA;AAAA,EAGO,mBAAmB,MAAwF;AAChH,WAAQ,KAAK,oBAA4B,GAAG,IAAI;AAAA,EAClD;AAAA;AAAA,EAGO,+BAA+B,MAA8G;AAClJ,WAAQ,KAAK,+BAAuC,GAAG,IAAI;AAAA,EAC7D;AACF;;;AC1JA,IAAM,+BAAoD;AAAA,EACxD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,mCAAwD;AAAA,EAC5D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,sCAA2D;AAAA,EAC/D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AAEO,IAAM,4BAAN,MAAgC;AAAA,EAC9B,YAA+B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EAE3D,mBAAmB,UAAgD,CAAC,GAAG,SAA0E;AACtJ,UAAM,aAAa,EAAE,aAAa,EAAE,UAAU,QAAQ,YAAY,GAAG,EAAE;AACvE,WAAO,KAAK,OAAO,mBAA0D,8BAA8B,YAAY,OAAO;AAAA,EAChI;AAAA,EAEO,uBAAuB,SAAmD,SAA8E;AAC7J,WAAO,KAAK,OAAO,mBAA8D,kCAAkC,KAAK,OAAO,iBAAiB,kCAAkC,OAAkC,GAAG,OAAO;AAAA,EAChO;AAAA,EAEO,oBAAoB,SAAgD,SAA2E;AACpJ,WAAO,KAAK,OAAO,YAAoD,+BAA+B,KAAK,OAAO,iBAAiB,+BAA+B,OAAkC,GAAG,OAAO;AAAA,EAChN;AAAA,EAEO,oBAAoB,SAAgD,SAA2E;AACpJ,WAAO,KAAK,OAAO,YAAoD,+BAA+B,KAAK,OAAO,iBAAiB,+BAA+B,OAAkC,GAAG,OAAO;AAAA,EAChN;AAAA,EAEO,0BAA0B,SAAsD,SAAiF;AACtK,WAAO,KAAK,OAAO,YAA0D,qCAAqC,KAAK,OAAO,iBAAiB,qCAAqC,OAAkC,GAAG,OAAO;AAAA,EAClO;AAAA,EAEO,wBAAwB,SAAoD,SAA+E;AAChK,WAAO,KAAK,OAAO,mBAA+D,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACnO;AAAA,EAEO,oBAAoB,SAAgD,SAA2E;AACpJ,WAAO,KAAK,OAAO,YAAoD,+BAA+B,KAAK,OAAO,iBAAiB,+BAA+B,OAAkC,GAAG,OAAO;AAAA,EAChN;AACF;;;ACxJA,IAAM,aAAa;AAEnB,SAAS,uBAAuB,KAAuB;AACrD,MAAI,OAAO,QAAQ,UAAU;AAC3B,WAAO,OAAO,UAAU,GAAG,KAAK,MAAM,KAAK,OAAO;AAAA,EACpD;AACA,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,IAAI;AAChD,UAAM,MAAM,OAAO,GAAG;AACtB,WAAO,OAAO,UAAU,GAAG,KAAK,MAAM,KAAK,OAAO;AAAA,EACpD;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,KAAuB;AAChD,MAAI,OAAO,QAAQ,SAAU,QAAO,OAAO,UAAU,GAAG,KAAK,MAAM;AACnE,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,IAAI;AAChD,UAAM,MAAM,OAAO,GAAG;AACtB,WAAO,OAAO,UAAU,GAAG,KAAK,MAAM;AAAA,EACxC;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,KAAuB;AACnD,MAAI,OAAO,QAAQ,SAAU,QAAO,OAAO,UAAU,GAAG,KAAK,OAAO;AACpE,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,IAAI;AAChD,UAAM,MAAM,OAAO,GAAG;AACtB,WAAO,OAAO,UAAU,GAAG,KAAK,OAAO;AAAA,EACzC;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,KAAsB;AAC/C,SAAO,OAAO,QAAQ,WAAW,KAAK,MAAM,GAAG,IAAI,SAAS,OAAO,GAAG,GAAG,EAAE;AAC7E;AAKA,SAAS,oBAAoB,SAAkB,QAAkB,QAA4C;AAC3G,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO,KAAK,GAAG,MAAM,kEAAsC;AAC3D,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,eAA2C,CAAC;AAElD,UAAQ,QAAQ,CAAC,KAAK,QAAQ;AAC5B,UAAM,YAAY,GAAG,MAAM,YAAY,GAAG;AAC1C,QAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,aAAO,KAAK,GAAG,SAAS,2EAAkC;AAC1D;AAAA,IACF;AACA,UAAM,IAAI;AAGV,QAAI,OAAO,EAAE,SAAS,YAAY,EAAE,KAAK,KAAK,MAAM,IAAI;AACtD,aAAO,KAAK,GAAG,SAAS,8GAAuD;AAAA,IACjF;AAGA,UAAM,UAAU,OAAO,EAAE,IAAI;AAC7B,QAAI,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,SAAS,OAAO,GAAG;AAClC,aAAO,KAAK,GAAG,SAAS,oIAAwF;AAAA,IAClH;AAEA,UAAM,WAAqC;AAAA,MACzC,MAAM;AAAA,MACN,MAAM,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK;AAAA,MAChC,UAAU,EAAE,aAAa;AAAA,IAC3B;AAGA,QAAI,YAAY,IAAI;AAClB,UAAI,OAAO,EAAE,QAAQ,YAAY,EAAE,IAAI,KAAK,MAAM,IAAI;AACpD,eAAO,KAAK,GAAG,SAAS,qHAAkE;AAAA,MAC5F,OAAO;AACL,iBAAS,MAAM,EAAE,IAAI,KAAK;AAAA,MAC5B;AAAA,IACF,WAAW,YAAY,IAAI;AACzB,UAAI,OAAO,EAAE,UAAU,YAAY,EAAE,MAAM,KAAK,MAAM,IAAI;AACxD,eAAO,KAAK,GAAG,SAAS,wHAAqE;AAAA,MAC/F,OAAO;AACL,iBAAS,QAAQ,EAAE,MAAM,KAAK;AAAA,MAChC;AAAA,IACF,WAAW,YAAY,GAAG;AACxB,UAAI,CAAC,MAAM,QAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,WAAW,GAAG;AACzD,eAAO,KAAK,GAAG,SAAS,+KAAuG;AAAA,MACjI,OAAO;AACL,cAAM,iBAAmD,CAAC;AAC1D,UAAE,SAAS,QAAQ,CAAC,OAAO,SAAS;AAClC,gBAAM,cAAc,GAAG,SAAS,aAAa,IAAI;AACjD,cAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,mBAAO,KAAK,GAAG,WAAW,6EAAuC;AACjE;AAAA,UACF;AACA,gBAAM,IAAI;AACV,cAAI,OAAO,EAAE,SAAS,YAAY,EAAE,KAAK,KAAK,MAAM,IAAI;AACtD,mBAAO,KAAK,GAAG,WAAW,gGAAqD;AAAA,UACjF,WAAW,EAAE,KAAK,SAAS,MAAM;AAC/B,mBAAO,KAAK,GAAG,WAAW,+FAAwD,EAAE,KAAK,MAAM,kBAAU;AAAA,UAC3G;AACA,yBAAe,KAAK;AAAA,YAClB,MAAM;AAAA,YACN,MAAM,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK;AAAA,UAClC,CAAC;AAAA,QACH,CAAC;AACD,iBAAS,WAAW;AAAA,MACtB;AAAA,IACF;AAEA,iBAAa,KAAK,QAAQ;AAAA,EAC5B,CAAC;AAED,SAAO;AACT;AAKA,SAAS,qBAAqB,UAAmB,QAA+C;AAC9F,MAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,WAAO,KAAK,4GAA4D;AACxE,WAAO,CAAC;AAAA,EACV;AAEA,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO,KAAK,4IAAsF,SAAS,MAAM,mJAA4F;AAC7M,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,MAAM,SAAS,CAAC;AACtB,MAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,WAAO,KAAK,0FAA0C;AACtD,WAAO,CAAC;AAAA,EACV;AACA,QAAM,IAAI;AAEV,QAAM,UAAU,OAAO,EAAE,IAAI;AAC7B,MAAI,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,OAAO,GAAG;AAC7B,WAAO,KAAK,6GAAiE;AAAA,EAC/E;AAEA,MAAI,OAAO,EAAE,SAAS,YAAY,EAAE,KAAK,KAAK,MAAM,IAAI;AACtD,WAAO,KAAK,yHAA8D;AAAA,EAC5E,WAAW,EAAE,KAAK,SAAS,MAAM;AAC/B,WAAO,KAAK,yFAAkD,EAAE,KAAK,MAAM,kBAAU;AAAA,EACvF;AAEA,QAAM,WAAsC;AAAA,IAC1C,MAAM;AAAA,IACN,MAAM,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK;AAAA,EAClC;AAEA,MAAI,YAAY,GAAG;AACjB,QAAI,OAAO,EAAE,QAAQ,YAAY,EAAE,IAAI,KAAK,MAAM,IAAI;AACpD,aAAO,KAAK,iKAAkF;AAAA,IAChG,OAAO;AACL,eAAS,MAAM,EAAE,IAAI,KAAK;AAAA,IAC5B;AAAA,EACF;AAEA,MAAI,EAAE,YAAY,UAAa,EAAE,YAAY,MAAM;AACjD,aAAS,UAAU,oBAAoB,EAAE,SAAS,QAAQ,aAAa;AAAA,EACzE;AAEA,SAAO,CAAC,QAAQ;AAClB;AAKO,SAAS,0CAA0C,OAAgF;AACxI,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,oIAA+D,EAAE;AAAA,EACrG;AACA,QAAM,MAAM;AAGZ,MAAI,CAAC,uBAAuB,IAAI,IAAI,GAAG;AACrC,WAAO,KAAK,iSAAyL;AAAA,EACvM;AAGA,MAAI,CAAC,kBAAkB,IAAI,KAAK,GAAG;AACjC,WAAO,KAAK,kHAA8D;AAAA,EAC5E;AAGA,MAAI,IAAI,WAAW,UAAa,IAAI,WAAW,QAAQ,CAAC,qBAAqB,IAAI,MAAM,GAAG;AACxF,WAAO,KAAK,mGAA2D;AAAA,EACzE;AAGA,MAAI,IAAI,WAAW,UAAa,IAAI,WAAW,QAAQ,CAAC,kBAAkB,IAAI,MAAM,GAAG;AACrF,WAAO,KAAK,mGAAuD;AAAA,EACrE;AAEA,QAAM,YAA0D;AAAA,IAC9D,MAAM,kBAAkB,IAAI,IAAI;AAAA,IAChC,OAAO,kBAAkB,IAAI,KAAK;AAAA,EACpC;AACA,MAAI,IAAI,WAAW,UAAa,IAAI,WAAW,KAAM,WAAU,SAAS,kBAAkB,IAAI,MAAM;AACpG,MAAI,IAAI,WAAW,UAAa,IAAI,WAAW,KAAM,WAAU,SAAS,kBAAkB,IAAI,MAAM;AAEpG,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAKO,SAAS,0BAA0B,OAAgE;AACxG,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,uHAAqD,EAAE;AAAA,EAC3F;AACA,QAAM,MAAM;AAGZ,MAAI,CAAC,uBAAuB,IAAI,IAAI,GAAG;AACrC,WAAO,KAAK,6JAAiG;AAAA,EAC/G;AAGA,MAAI,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,KAAK,MAAM,IAAI;AAC1D,WAAO,KAAK,0IAAkE;AAAA,EAChF,WAAW,IAAI,KAAK,KAAK,EAAE,SAAS,IAAI;AACtC,WAAO,KAAK,kHAAsD,IAAI,KAAK,KAAK,EAAE,MAAM,kBAAU;AAAA,EACpG;AAGA,QAAM,gBAAgB,qBAAqB,IAAI,UAAU,MAAM;AAE/D,QAAM,YAA0C;AAAA,IAC9C,MAAM,kBAAkB,IAAI,IAAI;AAAA,IAChC,IAAI;AAAA,IACJ,MAAM,OAAO,IAAI,QAAQ,EAAE,EAAE,KAAK;AAAA,IAClC,UAAU;AAAA,EACZ;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAKO,SAAS,0BAA0B,OAAgE;AACxG,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,iIAA0D,EAAE;AAAA,EAChG;AACA,QAAM,MAAM;AAGZ,MAAI,CAAC,kBAAkB,IAAI,EAAE,GAAG;AAC9B,WAAO,KAAK,qJAAkF;AAAA,EAChG;AAGA,MAAI,CAAC,uBAAuB,IAAI,IAAI,GAAG;AACrC,WAAO,KAAK,6JAAiG;AAAA,EAC/G;AAGA,MAAI,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,KAAK,MAAM,IAAI;AAC1D,WAAO,KAAK,0IAAkE;AAAA,EAChF,WAAW,IAAI,KAAK,KAAK,EAAE,SAAS,IAAI;AACtC,WAAO,KAAK,kHAAsD,IAAI,KAAK,KAAK,EAAE,MAAM,kBAAU;AAAA,EACpG;AAGA,QAAM,gBAAgB,qBAAqB,IAAI,UAAU,MAAM;AAE/D,QAAM,YAA0C;AAAA,IAC9C,IAAI,kBAAkB,IAAI,EAAE;AAAA,IAC5B,MAAM,kBAAkB,IAAI,IAAI;AAAA,IAChC,MAAM,OAAO,IAAI,QAAQ,EAAE,EAAE,KAAK;AAAA,IAClC,UAAU;AAAA,EACZ;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAKO,IAAM,qBAAqB;AAAA,EAChC,4BAA4B;AAAA,EAC5B,YAAY;AAAA,EACZ,YAAY;AACd;;;ACnTA,IAAM,uCAA4D;AAAA,EAChE,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC,QAAQ,SAAS,UAAU,QAAQ;AAAA,EACjD,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AACf;AAEA,IAAM,uBAA4C;AAAA,EAChD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,QAAQ,MAAM,QAAQ,UAAU;AAC/C;AAEA,IAAM,uBAA4C;AAAA,EAChD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,QAAQ,MAAM,QAAQ,UAAU;AAC/C;AAEO,IAAM,mBAAN,MAAuB;AAAA,EAQrB,YAA+B,QAA2B;AAA3B;AAAA,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA,EAHlE,OAAuB,YAAY;AAAA,EACnB,YAAY;AAAA,EAInB,2BAA2B,SAAuD,SAAkF;AAC3K,WAAO,KAAK,OAAO,mBAAkE,sCAAsC,KAAK,OAAO,iBAAiB,sCAAsC,OAAkC,GAAG,OAAO;AAAA,EAC5O;AAAA,EAES,WAAW,SAAuC,SAAkE;AAC3H,WAAO,KAAK,OAAO,YAA2C,sBAAsB,KAAK,OAAO,iBAAiB,sBAAsB,OAA6C,GAAG,OAAO;AAAA,EAChM;AAAA,EAES,WAAW,SAAuC,SAAkE;AAC3H,WAAO,KAAK,OAAO,YAA2C,sBAAsB,KAAK,OAAO,iBAAiB,sBAAsB,OAA6C,GAAG,OAAO;AAAA,EAChM;AAEF;;;AC5DA,IAAM,6BAAkD;AAAA,EACtD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC,WAAW,WAAW;AAAA,EACpC,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AACf;AAEA,IAAM,8BAAmD;AAAA,EACvD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AACf;AAEA,IAAM,6BAAkD;AAAA,EACtD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AACf;AAEA,IAAM,6BAAkD;AAAA,EACtD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,MAAM;AACrB;AAEA,IAAM,qCAA0D;AAAA,EAC9D,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC,MAAM;AAAA,EACrB,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,MAAM;AACrB;AAEA,IAAM,wBAA6C;AAAA,EACjD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC,MAAM;AAAA,EACrB,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,MAAM;AACrB;AAEA,IAAMC,0BAA8C;AAAA,EAClD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC,MAAM;AAAA,EACrB,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,QAAQ,KAAK,KAAK,SAAS,UAAU,OAAO;AAC3D;AAKA,SAAS,sBAAsB,QAA8D;AAC3F,MAAI,IAAI;AACR,SAAO,IAAI,OAAO,SAAS,GAAG;AAC5B,QAAI,OAAO,CAAC,MAAM,KAAM;AACtB;AACA;AAAA,IACF;AACA,UAAM,SAAS,OAAO,IAAI,CAAC;AAC3B,QAAI,WAAW,OAAQ,WAAW,OAAQ,WAAW,KAAM;AACzD,YAAM,SAAU,OAAO,IAAI,CAAC,KAAK,IAAK,OAAO,IAAI,CAAC;AAClD,YAAM,QAAS,OAAO,IAAI,CAAC,KAAK,IAAK,OAAO,IAAI,CAAC;AACjD,aAAO,EAAE,OAAO,OAAO;AAAA,IACzB;AACA,UAAM,MAAO,OAAO,IAAI,CAAC,KAAK,IAAK,OAAO,IAAI,CAAC;AAC/C,SAAK,IAAI;AAAA,EACX;AACA,SAAO;AACT;AAKA,SAAS,qBAAqB,QAA8D;AAC1F,MACE,OAAO,UAAU,MACjB,OAAO,CAAC,MAAM,OACd,OAAO,CAAC,MAAM,MACd,OAAO,CAAC,MAAM,MACd,OAAO,CAAC,MAAM,IACd;AACA,UAAM,QAAS,OAAO,EAAE,KAAK,KAAO,OAAO,EAAE,KAAK,KAAO,OAAO,EAAE,KAAK,IAAK,OAAO,EAAE;AACrF,UAAM,SAAU,OAAO,EAAE,KAAK,KAAO,OAAO,EAAE,KAAK,KAAO,OAAO,EAAE,KAAK,IAAK,OAAO,EAAE;AACtF,WAAO,EAAE,OAAO,OAAO;AAAA,EACzB;AACA,SAAO;AACT;AAKA,SAAS,aAAa,KAAiC;AACrD,MAAI,eAAe,YAAY;AAC7B,WAAO;AAAA,EACT;AACA,MACE,OAAO,QAAQ,YACf,QAAQ,QACR,OAAQ,IAAiE,aAAa,aAAa,YACnG;AACA,WAAQ,IAA+D,YAAY,SAAS,GAAG;AAAA,EACjG;AACA,SAAO;AACT;AAKA,SAAS,gBAAgB,OAAgB,gBAAgB,SAAiB;AACxE,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,QAAQ,MAAM,MAAM,MAAM,EAAE,CAAC;AACnC,UAAM,QAAQ,MAAM,MAAM,UAAU;AACpC,QAAI,SAAS,MAAM,CAAC,EAAG,QAAO,MAAM,CAAC;AAAA,EACvC;AACA,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,SAAS;AACf,QAAI,OAAO,OAAO,SAAS,YAAY,OAAO,KAAM,QAAO,OAAO;AAClE,QAAI,OAAO,OAAO,iBAAiB,YAAY,OAAO,aAAc,QAAO,OAAO;AAClF,QAAI,OAAO,OAAO,aAAa,YAAY,OAAO,SAAU,QAAO,OAAO;AAAA,EAC5E;AACA,SAAO,GAAG,aAAa,IAAI,KAAK,IAAI,CAAC;AACvC;AAEO,IAAM,mBAAN,MAAuB;AAAA,EACrB,YAA6B,QAA2B;AAA3B;AAAA,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASzD,iBACL,SACA,SAC8C;AAC9C,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,4BAA4B,OAAkC;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,eACL,SACA,SAC8C;AAC9C,WAAO,KAAK,iBAAiB,SAAS,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKO,kBACL,UAA+C,CAAC,GAChD,SAC+C;AAC/C,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,6BAA6B,OAAkC;AAAA,MAC5F;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,gBACL,UAA+C,CAAC,GAChD,SAC+C;AAC/C,WAAO,KAAK,kBAAkB,SAAS,OAAO;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKO,iBACL,UAA8C,CAAC,GAC/C,SAC8C;AAC9C,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,4BAA4B,OAAkC;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,eACL,UAA8C,CAAC,GAC/C,SAC8C;AAC9C,WAAO,KAAK,iBAAiB,SAAS,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,iBACL,SACA,SAC8C;AAC9C,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,MAAM,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO,KAAK,UAAU,QAAQ,IAAI;AAAA,IACrF;AACA,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,4BAA4B,UAAqC;AAAA,MAC9F;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,UACL,SACA,SAC8C;AAC9C,WAAO,KAAK,iBAAiB,SAAS,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,yBACL,SACA,SACsD;AACtD,UAAM,OAAO,QAAQ,QAAQ,QAAQ;AACrC,QAAI,OAAO,SAAS,YAAY,CAAC,oBAAoB,KAAK,IAAI,GAAG;AAC/D,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,aAAa;AAAA,MACjB,MAAM;AAAA,IACR;AACA,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,oCAAoC,UAAU;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,YACL,SACA,SACsD;AACtD,WAAO,KAAK,yBAAyB,SAAS,OAAO;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,YACL,SACA,SACyC;AACzC,UAAM,OAAO,QAAQ,QAAQ,QAAQ;AACrC,QAAI,OAAO,SAAS,YAAY,CAAC,oBAAoB,KAAK,IAAI,GAAG;AAC/D,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,aAAa;AAAA,MACjB,MAAM;AAAA,IACR;AACA,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,uBAAuB,UAAU;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,aACL,SACA,SAC0C;AAC1C,WAAO,KAAK,OAAO;AAAA,MACjBA;AAAA,MACA,KAAK,OAAO,iBAAiBA,yBAAwB,OAAkC;AAAA,MACvF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,WACL,SACA,SAC0C;AAC1C,WAAO,KAAK,aAAa,SAAS,OAAO;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,mBACX,SACA,SAC2C;AAC3C,QAAI,CAAC,QAAQ,MAAM;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,QAAQ,SAAS,YAAY,CAAC,oBAAoB,KAAK,QAAQ,IAAI,GAAG;AAC/E,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAGA,UAAM,WAAW,QAAQ,YAAY,gBAAgB,QAAQ,MAAM,OAAO;AAG1E,QAAI,QAAQ,QAAQ;AACpB,QAAI,SAAS,QAAQ;AAErB,SAAK,CAAC,SAAS,CAAC,WAAW,aAAa,QAAQ,IAAI,GAAG;AACrD,YAAM,OAAO,sBAAsB,QAAQ,IAAI,KAAK,qBAAqB,QAAQ,IAAI;AACrF,UAAI,MAAM;AACR,gBAAQ,SAAS,KAAK;AACtB,iBAAS,UAAU,KAAK;AAAA,MAC1B;AAAA,IACF;AAGA,UAAM,gBAAgB,SAAS,QAAQ,IAAI,QAAQ;AACnD,UAAM,iBAAiB,UAAU,SAAS,IAAI,SAAS;AAGvD,UAAM,YAAY,MAAM,KAAK,yBAAyB,EAAE,MAAM,QAAQ,KAAK,GAAG,OAAO;AACrF,QAAI,CAAC,aAAa,UAAU,SAAS,KAAK,CAAC,UAAU,MAAM;AACzD,YAAM,IAAI;AAAA,QACR,WAAW,OAAO;AAAA,QAClB,WAAW,QAAQ;AAAA,QACnB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,UAAU;AAGzB,UAAM,YAAY,QAAQ,SAAS,SAAY,QAAQ,OAAO;AAC9D,UAAM,cAA8C;AAAA,MAClD,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,QACR,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,MAC3D;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,KAAK,iBAAiB,EAAE,MAAM,YAAY,GAAG,OAAO;AAC1E,QAAI,CAAC,WAAW,QAAQ,SAAS,KAAK,OAAO,QAAQ,SAAS,UAAU;AACtE,YAAM,IAAI;AAAA,QACR;AAAA,QACA,SAAS,QAAQ;AAAA,QACjB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,QAAQ;AAAA,MACjB;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,mBACX,SACA,SAC2C;AAC3C,QAAI,CAAC,QAAQ,MAAM;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,QAAQ,SAAS,YAAY,CAAC,oBAAoB,KAAK,QAAQ,IAAI,GAAG;AAC/E,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,QAAQ,YAAY,gBAAgB,QAAQ,MAAM,OAAO;AAC1E,UAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAM,SAAS,QAAQ,UAAU;AACjC,UAAM,WAAW,QAAQ,YAAY;AAGrC,UAAM,YAAY,MAAM,KAAK,YAAY,EAAE,MAAM,QAAQ,KAAK,GAAG,OAAO;AACxE,QAAI,CAAC,aAAa,UAAU,SAAS,KAAK,CAAC,UAAU,MAAM;AACzD,YAAM,IAAI;AAAA,QACR,WAAW,OAAO;AAAA,QAClB,WAAW,QAAQ;AAAA,QACnB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,UAAU;AAGzB,UAAM,cAA8C;AAAA,MAClD,MAAM;AAAA,MACN,MAAM;AAAA;AAAA,MACN,UAAU;AAAA,QACR,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,MAC3D;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,KAAK,iBAAiB,EAAE,MAAM,YAAY,GAAG,OAAO;AAC1E,QAAI,CAAC,WAAW,QAAQ,SAAS,KAAK,OAAO,QAAQ,SAAS,UAAU;AACtE,YAAM,IAAI;AAAA,QACR;AAAA,QACA,SAAS,QAAQ;AAAA,QACjB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,QAAQ;AAAA,MACjB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeO,cAAc,OAA0D;AAC7E,UAAM,SAAmB,CAAC;AAG1B,QAAI,YAAY,MAAM;AACtB,QAAI,WAAW,MAAM;AACrB,QAAI,SAAS,MAAM;AACnB,QAAI,QAAQ,MAAM;AAClB,QAAI,SAAS,MAAM;AAEnB,UAAM,OAAO,MAAM;AACnB,UAAM,UAAU;AAAA,MACd,SAAS,QACT,SAAS,WACR,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM;AAAA,IAC/C;AAEA,QAAI,CAAC,WAAW,cAAc,QAAW;AACvC,aAAO,KAAK,gBAAgB;AAC5B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR;AAAA,QACA,UAAU,EAAE,cAAc,MAAM;AAAA,MAClC;AAAA,IACF;AAGA,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,YAAM,MAAM;AACZ,UAAI,OAAO,IAAI,SAAS,YAAY,cAAc,QAAW;AAC3D,oBAAY,IAAI;AAAA,MAClB;AACA,UAAI,OAAO,IAAI,iBAAiB,YAAY,CAAC,UAAU;AACrD,mBAAW,IAAI;AAAA,MACjB;AACA,UAAI,OAAO,IAAI,aAAa,YAAY,CAAC,QAAQ;AAC/C,iBAAS,IAAI;AAAA,MACf;AACA,UAAI,aAAa,IAAI,MAAM,GAAG;AAC5B,YAAI,cAAc,OAAW,aAAY,IAAI,OAAO;AACpD,cAAM,OAAO,sBAAsB,IAAI,MAAM,KAAK,qBAAqB,IAAI,MAAM;AACjF,YAAI,MAAM;AACR,kBAAQ,SAAS,KAAK;AACtB,mBAAS,UAAU,KAAK;AAAA,QAC1B;AAAA,MACF,WAAW,aAAa,IAAI,GAAG;AAC7B,YAAI,cAAc,OAAW,aAAY,KAAK;AAC9C,cAAM,OAAO,sBAAsB,IAAI,KAAK,qBAAqB,IAAI;AACrE,YAAI,MAAM;AACR,kBAAQ,SAAS,KAAK;AACtB,mBAAS,UAAU,KAAK;AAAA,QAC1B;AAAA,MACF;AAAA,IACF,WAAW,OAAO,SAAS,YAAY,CAAC,UAAU;AAChD,iBAAW,gBAAgB,IAAI;AAAA,IACjC;AAGA,QAAI,cAAc,UAAa,aAAa,GAAG;AAC7C,aAAO,KAAK,gBAAgB;AAAA,IAC9B;AAGA,UAAM,kBAAkB,IAAI,OAAO;AACnC,QAAI,cAAc,UAAa,YAAY,iBAAiB;AAC1D,YAAM,UAAU,aAAa,OAAO,OAAO,QAAQ,CAAC;AACpD,aAAO,KAAK,yIAAqE,MAAM,MAAM;AAAA,IAC/F;AAGA,QAAI,UAAU,UAAa,WAAW,QAAW;AAC/C,UAAI,QAAQ,OAAO,SAAS,KAAK;AAC/B,eAAO,KAAK,6GAA0D,KAAK,IAAI,MAAM,WAAW;AAAA,MAClG;AAAA,IACF;AAGA,UAAM,eAAe,YAAY,UAAU,IAAI,YAAY;AAC3D,QAAI,aAAa;AACf,YAAM,kBACJ,YAAY,SAAS,MAAM,KAC3B,YAAY,SAAS,OAAO,KAC5B,YAAY,SAAS,MAAM,KAC3B,YAAY,SAAS,YAAY,KACjC,YAAY,SAAS,WAAW,KAChC,YAAY,SAAS,WAAW;AAElC,UAAI,CAAC,iBAAiB;AACpB,eAAO,KAAK,mIAAsE;AAAA,MACpF;AAAA,IACF;AAEA,UAAM,UAAU,OAAO,WAAW;AAClC,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,UAAU,UAAU;AAAA,MAC5B;AAAA,MACA,UAAU;AAAA,QACR,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,WAAW,WAAW,SAAS,MAAM,GAAG,EAAE,IAAI,IAAI;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYO,cAAc,OAA0D;AAC7E,UAAM,SAAmB,CAAC;AAE1B,QAAI,YAAY,MAAM;AACtB,QAAI,WAAW,MAAM;AACrB,QAAI,SAAS,MAAM;AACnB,UAAM,kBAAkB,MAAM;AAC9B,UAAM,QAAQ,MAAM;AACpB,UAAM,SAAS,MAAM;AAErB,UAAM,OAAO,MAAM;AACnB,UAAM,UAAU;AAAA,MACd,SAAS,QACT,SAAS,WACR,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM;AAAA,IAC/C;AAEA,QAAI,CAAC,WAAW,cAAc,QAAW;AACvC,aAAO,KAAK,gBAAgB;AAC5B,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR;AAAA,QACA,UAAU,EAAE,cAAc,MAAM;AAAA,MAClC;AAAA,IACF;AAEA,QAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,YAAM,MAAM;AACZ,UAAI,OAAO,IAAI,SAAS,YAAY,cAAc,QAAW;AAC3D,oBAAY,IAAI;AAAA,MAClB;AACA,UAAI,OAAO,IAAI,iBAAiB,YAAY,CAAC,UAAU;AACrD,mBAAW,IAAI;AAAA,MACjB;AACA,UAAI,OAAO,IAAI,aAAa,YAAY,CAAC,QAAQ;AAC/C,iBAAS,IAAI;AAAA,MACf;AACA,UAAI,aAAa,IAAI,MAAM,GAAG;AAC5B,YAAI,cAAc,OAAW,aAAY,IAAI,OAAO;AAAA,MACtD,WAAW,aAAa,IAAI,GAAG;AAC7B,YAAI,cAAc,OAAW,aAAY,KAAK;AAAA,MAChD;AAAA,IACF,WAAW,OAAO,SAAS,YAAY,CAAC,UAAU;AAChD,iBAAW,gBAAgB,IAAI;AAAA,IACjC;AAGA,QAAI,cAAc,UAAa,aAAa,GAAG;AAC7C,aAAO,KAAK,gBAAgB;AAAA,IAC9B;AAGA,UAAM,eAAe,YAAY,UAAU,IAAI,YAAY;AAC3D,QAAI,aAAa;AACf,YAAM,QACJ,YAAY,SAAS,MAAM,KAC3B,YAAY,SAAS,WAAW,KAChC,YAAY,SAAS,MAAM;AAE7B,UAAI,CAAC,OAAO;AACV,eAAO,KAAK,kHAA+D;AAAA,MAC7E;AAAA,IACF;AAGA,UAAM,kBAAkB,MAAM,OAAO;AACrC,QAAI,cAAc,UAAa,YAAY,iBAAiB;AAC1D,YAAM,UAAU,aAAa,OAAO,OAAO,QAAQ,CAAC;AACpD,aAAO,KAAK,wIAAyE,MAAM,MAAM;AAAA,IACnG;AAGA,QAAI,oBAAoB,UAAa,kBAAkB,IAAI;AACzD,aAAO,KAAK,uJAA2E,eAAe,YAAS;AAAA,IACjH;AAGA,QAAI;AACJ,QAAI,UAAU,UAAa,WAAW,UAAa,QAAQ,KAAK,SAAS,GAAG;AAC1E,YAAM,QAAQ,QAAQ;AACtB,YAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,CAAC,KAAK;AAC3C,YAAM,SAAS,KAAK,IAAI,QAAQ,IAAI,EAAE,KAAK;AAC3C,YAAM,QAAQ,KAAK,IAAI,QAAQ,CAAG,KAAK;AAEvC,UAAI,OAAQ,cAAa;AAAA,eAChB,OAAQ,cAAa;AAAA,eACrB,MAAO,cAAa;AAAA,WACxB;AACH,qBAAa,GAAG,KAAK,IAAI,MAAM,MAAM,MAAM,QAAQ,CAAC,CAAC;AACrD,eAAO,KAAK,qHAAuE,KAAK,IAAI,MAAM,MAAM,UAAU,IAAI;AAAA,MACxH;AAAA,IACF;AAEA,UAAM,UAAU,OAAO,WAAW;AAClC,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,UAAU,UAAU;AAAA,MAC5B;AAAA,MACA,UAAU;AAAA,QACR,cAAc;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,WAAW,WAAW,SAAS,MAAM,GAAG,EAAE,IAAI,IAAI;AAAA,QAC1D,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;;;ACvvBO,IAAM,iBAAN,cAA6B,qBAAqB;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAA2B;AAC5C,UAAM,MAAM;AACZ,SAAK,UAAU,IAAI,mBAAmB,MAAM;AAC5C,SAAK,YAAY,IAAI,qBAAqB,MAAM;AAChD,SAAK,YAAY,KAAK;AACtB,SAAK,UAAU,IAAI,mBAAmB,MAAM;AAC5C,SAAK,cAAc,IAAI,uBAAuB,MAAM;AACpD,SAAK,QAAQ,KAAK;AAClB,SAAK,iBAAiB,IAAI,0BAA0B,MAAM;AAC1D,SAAK,QAAQ,KAAK;AAClB,SAAK,QAAQ,IAAI,iBAAiB,MAAM;AACxC,SAAK,QAAQ,IAAI,iBAAiB,MAAM;AACxC,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAMO,aAAa,UAA0C,CAAC,GAAG,SAAoE;AACpI,WAAQ,KAAK,QAAQ,aAAqB,SAAS,OAAO;AAAA,EAC5D;AAAA,EAEO,gCAAgC,SAA4D,SAAuF;AACxL,WAAQ,KAAK,QAAQ,gCAAwC,SAAS,OAAO;AAAA,EAC/E;AAAA,EAEO,4BAA4B,UAAyD,CAAC,GAAG,SAAmF;AACjL,WAAQ,KAAK,QAAQ,4BAAoC,SAAS,OAAO;AAAA,EAC3E;AAAA,EAEO,iCAAiC,UAA8D,CAAC,GAAG,SAAwF;AAChM,WAAQ,KAAK,QAAQ,iCAAyC,SAAS,OAAO;AAAA,EAChF;AAAA,EAEO,8BAA8B,UAA2D,EAAE,OAAO,IAAI,QAAQ,GAAG,aAAa,KAAK,GAAG,SAAqF;AAChO,WAAQ,KAAK,QAAQ,8BAAsC,SAAS,OAAO;AAAA,EAC7E;AAAA,EAEO,wBAAwB,UAAqD,CAAC,GAAG,SAA+E;AACrK,WAAQ,KAAK,QAAQ,wBAAgC,SAAS,OAAO;AAAA,EACvE;AAAA,EAEO,wBAAwB,MAAgG;AAC7H,WAAQ,KAAK,QAAQ,qBAA6B,GAAG,IAAI;AAAA,EAC3D;AAAA,EAEO,qBAAqB,UAAkD,CAAC,GAAG,SAA4E;AAC5J,WAAQ,KAAK,QAAQ,qBAA6B,SAAS,OAAO;AAAA,EACpE;AAAA,EAEO,aAAa,UAA0C,CAAC,GAAG,SAAoE;AACpI,WAAQ,KAAK,QAAQ,aAAqB,SAAS,OAAO;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAMO,0BAA0B,SAAsD,SAAiF;AACtK,WAAQ,KAAK,UAAU,0BAAkC,SAAS,OAAO;AAAA,EAC3E;AAAA,EAEO,kCAAkC,UAA+D,CAAC,GAAG,SAAyF;AACnM,WAAQ,KAAK,UAAU,kCAA0C,SAAS,OAAO;AAAA,EACnF;AAAA,EAEO,wBAAwB,UAAqD,CAAC,GAAG,SAA+E;AACrK,WAAQ,KAAK,UAAU,wBAAgC,SAAS,OAAO;AAAA,EACzE;AAAA,EAEO,qBAAqB,SAAiD,SAA4E;AACvJ,WAAQ,KAAK,UAAU,qBAA6B,SAAS,OAAO;AAAA,EACtE;AAAA,EAEO,qBAAqB,SAAiD,SAA4E;AACvJ,WAAQ,KAAK,UAAU,qBAA6B,SAAS,OAAO;AAAA,EACtE;AAAA,EAEO,8BAA8B,SAA0D,SAAqF;AAClL,WAAQ,KAAK,UAAU,8BAAsC,SAAS,OAAO;AAAA,EAC/E;AAAA;AAAA,EAGO,oBAAoB,SAAgD,SAA2E;AACpJ,WAAQ,KAAK,UAAU,oBAA4B,SAAS,OAAO;AAAA,EACrE;AAAA;AAAA,EAGO,oBAAoB,SAAgD,SAA2E;AACpJ,WAAQ,KAAK,UAAU,oBAA4B,SAAS,OAAO;AAAA,EACrE;AAAA;AAAA,EAGO,wBAAwB,SAAoD,SAA+E;AAChK,WAAQ,KAAK,UAAU,wBAAgC,SAAS,OAAO;AAAA,EACzE;AAAA;AAAA,EAGO,wBAAwB,SAAoD,SAA+E;AAChK,WAAQ,KAAK,UAAU,wBAAgC,SAAS,OAAO;AAAA,EACzE;AAAA;AAAA,EAGO,6BAA6B,SAAyD,SAAoF;AAC/K,WAAQ,KAAK,UAAU,6BAAqC,SAAS,OAAO;AAAA,EAC9E;AAAA;AAAA,EAGO,mCAAmC,SAA+D,SAA0F;AACjM,WAAQ,KAAK,UAAU,mCAA2C,SAAS,OAAO;AAAA,EACpF;AAAA;AAAA,EAGO,uBAAuB,SAAmD,SAA8E;AAC7J,WAAQ,KAAK,UAAU,uBAA+B,SAAS,OAAO;AAAA,EACxE;AAAA;AAAA,EAGO,2BAA2B,SAAuD,SAAkF;AACzK,WAAQ,KAAK,UAAU,2BAAmC,SAAS,OAAO;AAAA,EAC5E;AAAA;AAAA,EAGO,4BAA4B,SAAwD,SAAmF;AAC5K,WAAQ,KAAK,UAAU,4BAAoC,SAAS,OAAO;AAAA,EAC7E;AAAA;AAAA,EAGO,yBAAyB,SAAqD,SAAgF;AACnK,WAAQ,KAAK,UAAU,yBAAiC,SAAS,OAAO;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA,EAMO,kBAAkB,SAA8C,SAAyE;AAC9I,WAAQ,KAAK,QAAQ,kBAA0B,SAAS,OAAO;AAAA,EACjE;AAAA,EAEO,wBAAwB,UAAqD,CAAC,GAAG,SAA+E;AACrK,WAAQ,KAAK,QAAQ,wBAAgC,SAAS,OAAO;AAAA,EACvE;AAAA,EAEO,yBAAyB,SAAqD,SAAgF;AACnK,WAAQ,KAAK,QAAQ,yBAAiC,SAAS,OAAO;AAAA,EACxE;AAAA,EAEO,wBAAwB,SAAoD,SAA+E;AAChK,WAAQ,KAAK,QAAQ,wBAAgC,SAAS,OAAO;AAAA,EACvE;AAAA,EAEO,kBAAkB,SAA8C,SAAyE;AAC9I,WAAQ,KAAK,QAAQ,kBAA0B,SAAS,OAAO;AAAA,EACjE;AAAA,EAEO,sBAAsB,SAAkD,SAA6E;AAC1J,WAAQ,KAAK,QAAQ,sBAA8B,SAAS,OAAO;AAAA,EACrE;AAAA,EAEO,+BAA+B,SAA2D,SAAsF;AACrL,WAAQ,KAAK,QAAQ,+BAAuC,SAAS,OAAO;AAAA,EAC9E;AAAA,EAEO,kBAAkB,UAA+C,CAAC,GAAG,SAAyE;AACnJ,WAAQ,KAAK,QAAQ,kBAA0B,SAAS,OAAO;AAAA,EACjE;AAAA,EAEO,mBAAmB,SAA+C,SAA0E;AACjJ,WAAQ,KAAK,QAAQ,mBAA2B,SAAS,OAAO;AAAA,EAClE;AAAA,EAEO,mBAAmB,SAA+C,SAA0E;AACjJ,WAAQ,KAAK,QAAQ,mBAA2B,SAAS,OAAO;AAAA,EAClE;AAAA,EAEO,kBAAkB,SAA8C,SAAyE;AAC9I,WAAQ,KAAK,QAAQ,kBAA0B,SAAS,OAAO;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAMO,iBAAiB,SAA6C,SAAwE;AAC3I,WAAQ,KAAK,YAAY,iBAAyB,SAAS,OAAO;AAAA,EACpE;AAAA,EAEO,iBAAiB,SAA6C,SAAwE;AAC3I,WAAQ,KAAK,YAAY,iBAAyB,SAAS,OAAO;AAAA,EACpE;AAAA,EAEO,oBAAoB,UAAiD,CAAC,GAAG,SAA2E;AACzJ,WAAQ,KAAK,YAAY,oBAA4B,SAAS,OAAO;AAAA,EACvE;AAAA,EAEO,+BAA+B,UAA4D,CAAC,GAAG,SAAsF;AAC1L,WAAQ,KAAK,YAAY,+BAAuC,SAAS,OAAO;AAAA,EAClF;AAAA,EAEO,wBAAwB,UAAqD,CAAC,GAAG,SAA+E;AACrK,WAAQ,KAAK,YAAY,wBAAgC,SAAS,OAAO;AAAA,EAC3E;AAAA;AAAA,EAGO,kBAAkB,SAAyE;AAChG,WAAQ,KAAK,YAAY,kBAA0B,OAAO;AAAA,EAC5D;AAAA;AAAA,EAGO,oBAAoB,UAAiD,CAAC,GAAG,SAA2E;AACzJ,WAAQ,KAAK,YAAY,oBAA4B,SAAS,OAAO;AAAA,EACvE;AAAA;AAAA,EAGO,sBAAsB,UAAiD,CAAC,GAAG,SAA2E;AAC3J,WAAQ,KAAK,YAAY,sBAA8B,SAAS,OAAO;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAMO,mBAAmB,UAAgD,CAAC,GAAG,SAA0E;AACtJ,WAAQ,KAAK,eAAe,mBAA2B,SAAS,OAAO;AAAA,EACzE;AAAA,EAEO,uBAAuB,SAAmD,SAA8E;AAC7J,WAAQ,KAAK,eAAe,uBAA+B,SAAS,OAAO;AAAA,EAC7E;AAAA,EAEO,oBAAoB,SAAgD,SAA2E;AACpJ,WAAQ,KAAK,eAAe,oBAA4B,SAAS,OAAO;AAAA,EAC1E;AAAA,EAEO,oBAAoB,SAAgD,SAA2E;AACpJ,WAAQ,KAAK,eAAe,oBAA4B,SAAS,OAAO;AAAA,EAC1E;AAAA,EAEO,0BAA0B,SAAsD,SAAiF;AACtK,WAAQ,KAAK,eAAe,0BAAkC,SAAS,OAAO;AAAA,EAChF;AAAA,EAEO,wBAAwB,SAAoD,SAA+E;AAChK,WAAQ,KAAK,eAAe,wBAAgC,SAAS,OAAO;AAAA,EAC9E;AAAA,EAEO,oBAAoB,SAAgD,SAA2E;AACpJ,WAAQ,KAAK,eAAe,oBAA4B,SAAS,OAAO;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA,EAMO,2BAA2B,SAAuD,SAAkF;AACzK,WAAQ,KAAK,MAAM,2BAAmC,SAAS,OAAO;AAAA,EACxE;AAAA,EAEO,WAAW,SAAuC,SAAkE;AACzH,WAAQ,KAAK,MAAM,WAAmB,SAAS,OAAO;AAAA,EACxD;AAAA,EAEO,WAAW,SAAuC,SAAkE;AACzH,WAAQ,KAAK,MAAM,WAAmB,SAAS,OAAO;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAMO,iBAAiB,UAA8C,CAAC,GAAG,SAAwE;AAChJ,WAAQ,KAAK,MAAM,iBAAyB,SAAS,OAAO;AAAA,EAC9D;AAAA,EAEO,iBAAiB,SAA6C,SAAwE;AAC3I,WAAQ,KAAK,MAAM,iBAAyB,SAAS,OAAO;AAAA,EAC9D;AAAA,EAEO,kBAAkB,UAA+C,CAAC,GAAG,SAAyE;AACnJ,WAAQ,KAAK,MAAM,kBAA0B,SAAS,OAAO;AAAA,EAC/D;AAAA,EAEO,iBAAiB,SAA6C,SAAwE;AAC3I,WAAQ,KAAK,MAAM,iBAAyB,SAAS,OAAO;AAAA,EAC9D;AAAA,EAEO,yBAAyB,SAAqD,SAAgF;AACnK,WAAQ,KAAK,MAAM,yBAAiC,SAAS,OAAO;AAAA,EACtE;AAAA;AAAA,EAGO,YAAY,SAAqD,SAAgF;AACtJ,WAAQ,KAAK,MAAM,YAAoB,SAAS,OAAO;AAAA,EACzD;AAAA,EAEO,YAAY,SAAwC,SAAmE;AAC5H,WAAQ,KAAK,MAAM,YAAoB,SAAS,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,cAAc,OAAkD;AACrE,WAAQ,KAAK,MAAM,cAAsB,KAAK;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,cAAc,OAAkD;AACrE,WAAQ,KAAK,MAAM,cAAsB,KAAK;AAAA,EAChD;AACF;;;ACtWA,IAAM,4CAAiE;AAAA,EACrE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEO,IAAM,wBAAN,MAA4B;AAAA,EAC1B,YAA6B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EACzD,yBAAyB,SAA4D,SAAuF;AACjL,WAAO,KAAK,OAAO,mBAAuE,2CAA2C,KAAK,OAAO,iBAAiB,2CAA2C,OAAkC,GAAG,OAAO;AAAA,EAC3P;AAAA;AAAA,EAEO,eAAe,SAAkD,SAA6E;AACnJ,WAAO,KAAK,yBAAyB,SAAS,OAAO;AAAA,EACvD;AACF;;;ACuCA,SAAS,WAAW,KAAuB;AACzC,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,GAAI,QAAO;AACzD,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,GAAG;AACvB,WAAO,IAAI,aAAa,WAAW,IAAI,aAAa;AAAA,EACtD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,0BAA0B,OAA8D;AACtG,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,kFAA8C;AAAA,MACvD,MAAM;AAAA,IACR;AAAA,EACF;AAGA,MAAI,MAA+B;AACnC,MAAI,OAAQ,MAAc,SAAS,UAAU;AAC3C,QAAI;AACF,YAAM,KAAK,MAAO,MAAc,IAAI;AAAA,IACtC,QAAQ;AACN,aAAO,KAAK,oFAAgD;AAC5D,aAAO,EAAE,SAAS,OAAO,QAAQ,MAAM,OAAU;AAAA,IACnD;AAAA,EACF,WAAW,OAAQ,MAAc,SAAS,YAAa,MAAc,SAAS,MAAM;AAClF,UAAO,MAAc;AAAA,EACvB;AAGA,QAAM,UAAU,IAAI;AACpB,MAAI,YAAY;AAChB,MAAI,OAAO,YAAY,YAAY,WAAW,KAAK,QAAQ,KAAK,CAAC,GAAG;AAClE,gBAAY,QAAQ,KAAK;AAAA,EAC3B,WAAW,OAAO,YAAY,YAAY,OAAO,UAAU,OAAO,KAAK,UAAU,GAAG;AAClF,gBAAY,OAAO,OAAO;AAAA,EAC5B,OAAO;AACL,WAAO,KAAK,uMAA8G;AAAA,EAC5H;AAGA,QAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,MAAM,KAAK,IAAI;AACjE,MAAI,CAAC,OAAO;AACV,WAAO,KAAK,gFAA4C;AAAA,EAC1D,WAAW,MAAM,SAAS,KAAK,MAAM,SAAS,IAAI;AAChD,WAAO,KAAK,8HAA8D,MAAM,MAAM,kBAAU;AAAA,EAClG;AAGA,QAAM,WAAW,OAAO,IAAI,aAAa,WAAW,IAAI,SAAS,KAAK,IAAI;AAC1E,MAAI,CAAC,UAAU;AACb,WAAO,KAAK,wFAAoD;AAAA,EAClE,WAAW,SAAS,SAAS,KAAK,SAAS,SAAS,KAAK;AACvD,WAAO,KAAK,kIAAkE,SAAS,MAAM,kBAAU;AAAA,EACzG;AAGA,MAAI,mBAAuC;AAC3C,MAAI,IAAI,gBAAgB,UAAa,IAAI,gBAAgB,MAAM;AAC7D,UAAM,OAAO,OAAO,IAAI,WAAW,EAAE,KAAK;AAC1C,QAAI,KAAK,SAAS,KAAK;AACrB,aAAO,KAAK,4HAAiE,KAAK,MAAM,kBAAU;AAAA,IACpG,OAAO;AACL,yBAAmB;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,aAAa,OAAO,IAAI,eAAe,WAAW,IAAI,WAAW,KAAK,IAAI;AAChF,MAAI,CAAC,YAAY;AACf,WAAO,KAAK,gFAAiD;AAAA,EAC/D,WAAW,CAAC,WAAW,UAAU,GAAG;AAClC,WAAO,KAAK,kGAAiE;AAAA,EAC/E;AAGA,QAAM,cAAc,OAAO,IAAI,gBAAgB,YAAY,IAAI,YAAY,KAAK,MAAM,KAClF,IAAI,YAAY,KAAK,IACrB;AACJ,MAAI,YAAY,SAAS,IAAI;AAC3B,WAAO,KAAK,2HAAgE,YAAY,MAAM,kBAAU;AAAA,EAC1G;AAEA,QAAM,SAAS,OAAO,IAAI,WAAW,YAAY,IAAI,OAAO,KAAK,MAAM,KACnE,IAAI,OAAO,KAAK,IAChB;AACJ,MAAI,OAAO,SAAS,KAAK;AACvB,WAAO,KAAK,uHAA4D,OAAO,MAAM,kBAAU;AAAA,EACjG;AAGA,QAAM,iBAAiB,IAAI,mBAAmB,IAAI,IAAI;AACtD,QAAM,WAAW,OAAO,IAAI,aAAa,YAAY,IAAI,SAAS,KAAK,MAAM,KACzE,IAAI,SAAS,KAAK,IACjB,mBAAmB,IAAI,kBAAkB;AAE9C,MAAI,eAAmC;AACvC,MAAI,mBAAmB,GAAG;AACxB,QAAI,CAAC,IAAI,WAAW,CAAC,WAAW,IAAI,OAAO,GAAG;AAC5C,aAAO,KAAK,6IAA4F;AAAA,IAC1G,OAAO;AACL,qBAAe,OAAO,IAAI,OAAO,EAAE,KAAK;AAAA,IAC1C;AAAA,EACF;AAGA,QAAM,mBAAmB,QAAQ,IAAI,gBAAgB;AACrD,MAAI,mBAAuC;AAC3C,MAAI,kBAAsC;AAC1C,MAAI,kBAAkB;AACpB,UAAM,QAAQ,OAAO,IAAI,gBAAgB,WAAW,IAAI,YAAY,KAAK,IAAI;AAC7E,QAAI,CAAC,OAAO;AACV,aAAO,KAAK,0IAAuF;AAAA,IACrG,WAAW,MAAM,SAAS,KAAK;AAC7B,aAAO,KAAK,4HAAiE,MAAM,MAAM,kBAAU;AAAA,IACrG,OAAO;AACL,yBAAmB;AAAA,IACrB;AAEA,QAAI,CAAC,IAAI,cAAc,CAAC,WAAW,IAAI,UAAU,GAAG;AAClD,aAAO,KAAK,iJAAgG;AAAA,IAC9G,OAAO;AACL,wBAAkB,OAAO,IAAI,UAAU,EAAE,KAAK;AAAA,IAChD;AAAA,EACF;AAGA,MAAI,CAAC,MAAM,QAAQ,IAAI,SAAS,KAAK,IAAI,UAAU,WAAW,GAAG;AAC/D,WAAO,KAAK,sHAAqE;AAAA,EACnF;AAEA,QAAM,iBAA0C,CAAC;AACjD,MAAI,kBAAkB;AACtB,MAAI,oBAAoB;AAExB,MAAI,MAAM,QAAQ,IAAI,SAAS,GAAG;AAChC,QAAI,UAAU,QAAQ,CAAC,GAAQ,QAAgB;AAC7C,YAAM,UAAU,oBAAY,GAAG;AAC/B,UAAI,CAAC,KAAK,OAAO,MAAM,UAAU;AAC/B,eAAO,KAAK,GAAG,OAAO,mCAAsB;AAC5C;AAAA,MACF;AAEA,YAAM,SAAS,OAAO,EAAE,UAAU,WAAW,EAAE,MAAM,KAAK,IAAI;AAC9D,UAAI,OAAO,SAAS,KAAK,OAAO,SAAS,KAAK;AAC5C,eAAO,KAAK,GAAG,OAAO,+GAAsD;AAAA,MAC9E;AAEA,UAAI,CAAC,MAAM,QAAQ,EAAE,OAAO,KAAK,EAAE,QAAQ,WAAW,GAAG;AACvD,eAAO,KAAK,GAAG,OAAO,kFAAkD;AACxE;AAAA,MACF;AAEA,YAAM,eAA8C,CAAC;AACrD,QAAE,QAAQ,QAAQ,CAAC,KAAU,SAAiB;AAC5C,cAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,YAAI,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,SAAS,KAAK,GAAG;AAC/B,iBAAO,KAAK,GAAG,OAAO,uBAAY,IAAI,0GAAiE;AAAA,QACzG;AACA,YAAI,UAAU,GAAI,mBAAkB;AACpC,YAAI,UAAU,EAAG,qBAAoB;AAErC,qBAAa,KAAK;AAAA,UAChB,MAAM;AAAA,UACN,aAAa,KAAK,cAAc,OAAO,IAAI,WAAW,EAAE,KAAK,IAAI;AAAA,UACjE,OAAO,KAAK,QAAQ,OAAO,IAAI,KAAK,EAAE,KAAK,IAAI;AAAA,UAC/C,UAAU,OAAO,KAAK,aAAa,WAAW,IAAI,WAAW;AAAA,QAC/D,CAAC;AAAA,MACH,CAAC;AAED,qBAAe,KAAK;AAAA,QAClB,OAAO;AAAA,QACP,MAAM,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO;AAAA,QAC5C,YAAY,EAAE,eAAe,SAAY,QAAQ,EAAE,UAAU,IAAI;AAAA,QACjE,cAAc,QAAQ,EAAE,YAAY;AAAA,QACpC,UAAU,OAAO,EAAE,aAAa,WAAW,EAAE,YAAY,MAAM,KAAK;AAAA,QACpE,SAAS;AAAA,MACX,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAGA,MAAI,mBAAmB;AACrB,mBAAe,QAAQ,OAAK;AAC1B,UAAI,EAAE,QAAQ,KAAK,OAAK,EAAE,SAAS,EAAE,GAAG;AACtC,UAAE,eAAe;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,gBAAwC,CAAC;AAC/C,MAAI,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAC/B,QAAI,SAAS,QAAQ,CAAC,KAAU,SAAiB;AAC/C,YAAM,UAAU,YAAY,IAAI;AAChC,YAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,UAAI,MAAM,KAAK,KAAK,QAAQ,KAAK,QAAQ,GAAG;AAC1C,eAAO,KAAK,GAAG,OAAO,sKAA4F;AAAA,MACpH;AAEA,YAAM,SAAS,OAAO,KAAK,UAAU,WAAW,IAAI,MAAM,KAAK,IAAI;AACnE,UAAI,OAAO,SAAS,IAAI;AACtB,eAAO,KAAK,GAAG,OAAO,gFAAyC;AAAA,MACjE;AAEA,oBAAc,KAAK;AAAA,QACjB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS,QAAQ,KAAK,OAAO;AAAA,QAC7B,QAAQ,QAAQ,KAAK,MAAM;AAAA,QAC3B,SAAS,KAAK,UAAU,IAAI,UAAU,CAAC;AAAA,MACzC,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,QAAM,YAAwC;AAAA,IAC5C,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,cAAc,IAAI,iBAAiB,SAAY,QAAQ,IAAI,YAAY,IAAI;AAAA,IAC3E,WAAW;AAAA,IACX,UAAU,cAAc,SAAS,IAAI,gBAAgB;AAAA,IACrD;AAAA,IACA,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAKO,SAAS,0CAA0C,OAAqE;AAC7H,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AACZ,MAAI,YAAY;AAChB,MAAI,OAAO,IAAI,SAAS,YAAY,WAAW,KAAK,IAAI,KAAK,KAAK,CAAC,GAAG;AACpE,gBAAY,IAAI,KAAK,KAAK;AAAA,EAC5B,WAAW,OAAO,IAAI,SAAS,YAAY,OAAO,UAAU,IAAI,IAAI,KAAK,IAAI,OAAO,GAAG;AACrF,gBAAY,OAAO,IAAI,IAAI;AAAA,EAC7B,OAAO;AACL,WAAO,KAAK,yJAAkF;AAAA,EAChG;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,EAAE,MAAM,WAAW,OAAO,IAAI,UAAU,SAAY,QAAQ,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,EAChH;AACF;AAKO,SAAS,6BAA6B,OAa1C;AACD,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wCAA2B,GAAG,MAAM,OAAU;AAAA,EAClF;AAEA,QAAM,MAAM;AAGZ,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,8HAAkF;AAAA,EAChG,WAAW,WAAW,KAAK,IAAI,GAAG;AAChC,WAAO,KAAK,sMAAqI;AAAA,EACnJ;AAEA,QAAM,OAAO,OAAO,IAAI,IAAI;AAC5B,MAAI,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,IAAI,GAAG;AAC1B,WAAO,KAAK,8EAAuD;AAAA,EACrE;AAEA,QAAM,QAAQ,OAAO,IAAI,UAAU,YAAY,IAAI,QAAQ,IAAI,KAAK,MAAM,IAAI,KAAK,IAAI;AACvF,QAAM,SAAS,OAAO,IAAI,WAAW,YAAY,IAAI,UAAU,IAAI,KAAK,MAAM,IAAI,MAAM,IAAI;AAE5F,QAAM,SAAS,OAAO,IAAI,WAAW,YAAY,IAAI,OAAO,KAAK,MAAM,KACnE,IAAI,OAAO,KAAK,IAChB;AAEJ,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAM,WAAW,OAAO,IAAI,aAAa,YAAY,IAAI,YAAY,IAChE,IAAI,YAAY,OAAc,KAAK,MAAM,IAAI,WAAW,GAAI,IAAI,KAAK,MAAM,IAAI,QAAQ,IACxF,MAAM,KAAK;AACf,QAAM,SAAS,OAAO,IAAI,WAAW,YAAY,IAAI,UAAU,IAC1D,IAAI,UAAU,OAAc,KAAK,MAAM,IAAI,SAAS,GAAI,IAAI,KAAK,MAAM,IAAI,MAAM,IAClF;AAEJ,MAAI,SAAS,UAAU;AACrB,WAAO,KAAK,+GAAoE;AAAA,EAClF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,IAAI,UAAU,OAAO,IAAI,OAAO,EAAE,KAAK,IAAI;AAAA,MACpD,SAAS,IAAI,UAAU,OAAO,IAAI,OAAO,EAAE,KAAK,IAAI;AAAA,MACpD,QAAQ,IAAI,SAAS,OAAO,IAAI,MAAM,EAAE,KAAK,IAAI;AAAA,MACjD,UAAU,IAAI,WAAW,OAAO,IAAI,QAAQ,EAAE,KAAK,IAAI;AAAA,MACvD,YAAY,IAAI,eAAe,SAAY,QAAQ,IAAI,UAAU,IAAI;AAAA,IACvE,IAAI;AAAA,EACN;AACF;AAKO,SAAS,sCACd,OACsC;AACtC,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,kIAA+D;AAAA,IAC1E;AAAA,EACF;AAEA,QAAM,MAAM;AACZ,QAAM,SAAS,OAAO,IAAI,WAAW,WAAW,IAAI,OAAO,KAAK,IAAK,IAAI,SAAS,OAAO,IAAI,MAAM,EAAE,KAAK,IAAI;AAE9G,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK,0HAA4D;AAAA,EAC1E;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,EAAE,OAAO,IAAI;AAAA,EAC3C;AACF;AAKO,SAAS,8CACd,OACsE;AACtE,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,+IAAuE;AAAA,IAClF;AAAA,EACF;AAEA,QAAM,MAAM;AACZ,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAK,IAAI,OAAO,OAAO,IAAI,IAAI,EAAE,KAAK,IAAI;AACpG,QAAM,SAAS,OAAO,IAAI,WAAW,WAAW,IAAI,OAAO,KAAK,IAAK,IAAI,SAAS,OAAO,IAAI,MAAM,EAAE,KAAK,IAAI;AAE9G,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,sHAAkE;AAAA,EAChF;AACA,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK,0HAA4D;AAAA,EAC1E;AAEA,QAAM,WAAW,OAAO,IAAI,QAAQ;AACpC,MAAI,MAAM,QAAQ,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,QAAQ,GAAG;AACpD,WAAO,KAAK,kDAAuC,IAAI,QAAQ,mMAAkI;AAAA,EACnM;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,EAAE,MAAM,QAAQ,SAAS,IAAI;AAAA,EAC3D;AACF;AAKO,IAAM,qBAAqB;AAAA,EAChC,YAAY;AAAA,EACZ,4BAA4B;AAAA,EAC5B,eAAe;AAAA,EACf,wBAAwB;AAAA,EACxB,yBAAyB;AAAA,EACzB,gCAAgC;AAAA,EAChC,kCAAkC;AACpC;;;AC1eA,IAAMC,wBAA4C;AAAA,EAChD,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC;AAAA,EACd,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC,MAAM;AACrB;AAEA,IAAMC,wCAA4D;AAAA,EAChE,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC,QAAQ,OAAO;AAAA,EAC7B,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AACf;AAEA,IAAM,0CAA+D;AAAA,EACnE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AACA,IAAM,yCAA8D;AAAA,EAClE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AACF;AACA,IAAM,mCAAwD;AAAA,EAC5D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,6CAAkE;AAAA,EACtE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,oCAAyD;AAAA,EAC7D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,4BAAiD;AAAA,EACrD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,gDAAqE;AAAA,EACzE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,+CAAoE;AAAA,EACxE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,6CAAkE;AAAA,EACtE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,iDAAsE;AAAA,EAC1E,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AACA,IAAM,6BAAkD;AAAA,EACtD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,mCAAwD;AAAA,EAC5D,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AAAA,EACb,aAAa,CAAC,WAAW,QAAQ,QAAQ;AAAA,EACzC,cAAc,CAAC;AAAA,EACf,cAAc,CAAC;AAAA,EACf,YAAY,CAAC;AACf;AAEO,IAAM,mBAAN,MAAuB;AAAA,EAIrB,YAA6B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EAHhD,YAAY;AAAA,EAC5B,OAAuB,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnC,MAAa,WACX,SACA,SAC2C;AAC3C,QAAI;AACJ,QAAI,OAAQ,QAAgB,SAAS,UAAU;AAC7C,mBAAc,QAAgB;AAAA,IAChC,OAAO;AACL,YAAM,MAAM,mBAAmB,WAAW,OAAO;AACjD,UAAI,CAAC,IAAI,WAAW,CAAC,IAAI,MAAM;AAC7B,cAAM,IAAI,MAAM;AAAA,KAA2D,IAAI,OAAO,KAAK,OAAO,CAAC,EAAE;AAAA,MACvG;AACA,mBAAa,KAAK,UAAU,IAAI,IAAI;AAAA,IACtC;AACA,WAAO,KAAK,OAAO;AAAA,MACjBD;AAAA,MACA,KAAK,OAAO,iBAAiBA,uBAAsB,EAAE,MAAM,WAAW,CAAC;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,2BACL,SACA,SAC2D;AAC3D,UAAM,MAAM,mBAAmB,2BAA2B,OAAO;AACjE,UAAM,aAAa,IAAI,WAAW,IAAI,OAAO,IAAI,OAAO;AACxD,WAAO,KAAK,OAAO;AAAA,MACjBC;AAAA,MACA,KAAK,OAAO,iBAAiBA,uCAAsC,UAAqC;AAAA,MACxG;AAAA,IACF;AAAA,EACF;AAAA,EACO,eAAe,SAAwE;AAC5F,WAAO,KAAK,OAAO,mBAAwD,4BAA4B,QAAW,OAAO;AAAA,EAC3H;AAAA,EACO,4BAA4B,SAA0D,SAAqF;AAChL,WAAO,KAAK,OAAO,YAA8D,yCAAyC,KAAK,OAAO,iBAAiB,yCAAyC,OAAkC,GAAG,OAAO;AAAA,EAC9O;AAAA,EACO,2BAA2B,SAAyD,SAAoF;AAC7K,WAAO,KAAK,OAAO,YAA6D,wCAAwC,KAAK,OAAO,iBAAiB,wCAAwC,OAAkC,GAAG,OAAO;AAAA,EAC3O;AAAA,EACO,qBAAqB,SAAmD,SAA8E;AAC3J,WAAO,KAAK,OAAO,mBAA8D,kCAAkC,KAAK,OAAO,iBAAiB,kCAAkC,OAAkC,GAAG,OAAO;AAAA,EAChO;AAAA,EACO,+BAA+B,SAA6D,SAAwF;AACzL,WAAO,KAAK,OAAO,mBAAwE,4CAA4C,KAAK,OAAO,iBAAiB,4CAA4C,OAAkC,GAAG,OAAO;AAAA,EAC9P;AAAA,EACO,sBAAsB,SAAoD,SAA+E;AAC9J,WAAO,KAAK,OAAO,mBAA+D,mCAAmC,KAAK,OAAO,iBAAiB,mCAAmC,OAAkC,GAAG,OAAO;AAAA,EACnO;AAAA,EACO,cAAc,SAA4C,SAAuE;AACtI,WAAO,KAAK,OAAO,mBAAuD,2BAA2B,KAAK,OAAO,iBAAiB,2BAA2B,OAAkC,GAAG,OAAO;AAAA,EAC3M;AAAA,EACO,kCAAkC,SAAgE,SAA2F;AAClM,WAAO,KAAK,OAAO,mBAA2E,+CAA+C,KAAK,OAAO,iBAAiB,+CAA+C,OAAkC,GAAG,OAAO;AAAA,EACvQ;AAAA,EACO,iCAAiC,SAA+D,SAA0F;AAC/L,WAAO,KAAK,OAAO,mBAA0E,8CAA8C,KAAK,OAAO,iBAAiB,8CAA8C,OAAkC,GAAG,OAAO;AAAA,EACpQ;AAAA,EACO,+BAA+B,SAA6D,SAAwF;AACzL,WAAO,KAAK,OAAO,mBAAwE,4CAA4C,KAAK,OAAO,iBAAiB,4CAA4C,OAAkC,GAAG,OAAO;AAAA,EAC9P;AAAA,EACO,mCAAmC,SAAiE,SAA4F;AACrM,WAAO,KAAK,OAAO,YAAqE,gDAAgD,KAAK,OAAO,iBAAiB,gDAAgD,OAAkC,GAAG,OAAO;AAAA,EACnQ;AAAA;AAAA;AAAA;AAAA,EAKO,qBACL,SACA,SACoD;AACpD,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,kCAAkC,OAAkC;AAAA,MACjG;AAAA,IACF;AAAA,EACF;AACF;;;AC7SA,SAASC,mBAAkB,KAAuB;AAChD,MAAI,OAAO,QAAQ,SAAU,QAAO,OAAO,UAAU,GAAG,KAAK,MAAM;AACnE,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,IAAI;AAChD,UAAM,MAAM,OAAO,GAAG;AACtB,WAAO,OAAO,UAAU,GAAG,KAAK,MAAM;AAAA,EACxC;AACA,SAAO;AACT;AAGA,SAASC,mBAAkB,KAAsB;AAC/C,SAAO,OAAO,QAAQ,WAAW,KAAK,MAAM,GAAG,IAAI,SAAS,OAAO,GAAG,GAAG,EAAE;AAC7E;AAKO,SAAS,iCAAiC,OAAgF;AAC/H,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,0HAAkE,EAAE;AAAA,EACxG;AACA,QAAM,MAAM;AACZ,QAAM,iBAAiB,CAAC,GAAG,GAAG,GAAG,CAAC;AAClC,MAAI,CAACD,mBAAkB,IAAI,UAAU,KAAK,CAAC,eAAe,SAAS,OAAO,IAAI,UAAU,CAAC,GAAG;AAC1F,WAAO,KAAK,8HAAsE,eAAe,KAAK,IAAI,CAAC,4HAAiF;AAAA,EAC9L;AAEA,MAAI,IAAI,SAAS,UAAa,IAAI,SAAS,MAAM;AAC/C,UAAM,UAAU,OAAO,IAAI,IAAI,EAAE,KAAK;AACtC,QAAI,CAAC,SAAS;AACZ,aAAO,KAAK,sGAAiD;AAAA,IAC/D,WAAW,QAAQ,SAAS,IAAI;AAC9B,aAAO,KAAK,4PAA4K;AAAA,IAC1L;AAAA,EACF;AAEA,QAAM,OAAqD;AAAA,IACzD,YAAYC,mBAAkB,IAAI,UAAU;AAAA,IAC5C,MAAM,IAAI,OAAO,OAAO,IAAI,IAAI,EAAE,KAAK,IAAI;AAAA,EAC7C;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,OAAO;AAAA,EACrC;AACF;AAKO,SAAS,gCAAgC,OAA+E;AAC7H,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,6HAAuE,EAAE;AAAA,EAC7G;AACA,QAAM,MAAM;AACZ,MAAI,CAACD,mBAAkB,IAAI,aAAa,GAAG;AACzC,WAAO,KAAK,0HAAsE;AAAA,EACpF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,EAAE,eAAeC,mBAAkB,IAAI,aAAa,EAAE,IAAI;AAAA,EACxF;AACF;AAKO,SAAS,oCAAoC,OAAmF;AACrI,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,wIAA2E,EAAE;AAAA,EACjH;AACA,QAAM,MAAM;AACZ,MAAI,CAACD,mBAAkB,IAAI,aAAa,GAAG;AACzC,WAAO,KAAK,0HAAsE;AAAA,EACpF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,EAAE,eAAeC,mBAAkB,IAAI,aAAa,EAAE,IAAI;AAAA,EACxF;AACF;AAKO,SAAS,wCAAwC,OAAuF;AAC7I,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,+JAAkF,EAAE;AAAA,EACxH;AACA,QAAM,MAAM;AACZ,MAAI,CAACD,mBAAkB,IAAI,aAAa,GAAG;AACzC,WAAO,KAAK,0HAAsE;AAAA,EACpF;AACA,MAAI,CAACA,mBAAkB,IAAI,MAAM,GAAG;AAClC,WAAO,KAAK,mHAA+D;AAAA,EAC7E;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B,eAAeC,mBAAkB,IAAI,aAAa;AAAA,MAClD,QAAQA,mBAAkB,IAAI,MAAM;AAAA,IACtC,IAAI;AAAA,EACN;AACF;AAKO,SAAS,0CAA0C,OAAyF;AACjJ,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,mJAAuE,EAAE;AAAA,EAC7G;AACA,QAAM,MAAM;AACZ,MAAI,CAACD,mBAAkB,IAAI,aAAa,GAAG;AACzC,WAAO,KAAK,0HAAsE;AAAA,EACpF;AAEA,MAAI,QAA4B;AAChC,MAAI,IAAI,UAAU,UAAa,IAAI,UAAU,MAAM;AACjD,QAAI,CAACA,mBAAkB,IAAI,KAAK,GAAG;AACjC,aAAO,KAAK,iFAA+C;AAAA,IAC7D,OAAO;AACL,cAAQC,mBAAkB,IAAI,KAAK;AAAA,IACrC;AAAA,EACF;AAEA,MAAI,SAA6B;AACjC,MAAI,IAAI,WAAW,UAAa,IAAI,WAAW,MAAM;AACnD,UAAM,MAAM,OAAO,IAAI,MAAM;AAC7B,QAAI,CAAC,OAAO,UAAU,GAAG,KAAK,MAAM,GAAG;AACrC,aAAO,KAAK,kFAAgD;AAAA,IAC9D,OAAO;AACL,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI;AAAA,MAC1B,eAAeA,mBAAkB,IAAI,aAAa;AAAA,MAClD,GAAI,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC;AAAA,MACvC,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3C,IAAI;AAAA,EACN;AACF;AAKO,SAAS,0CAA0C,OAAyF;AACjJ,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,+HAAkE,EAAE;AAAA,EACxG;AACA,QAAM,MAAM;AACZ,MAAI,CAACD,mBAAkB,IAAI,aAAa,GAAG;AACzC,WAAO,KAAK,0HAAsE;AAAA,EACpF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,EAAE,eAAeC,mBAAkB,IAAI,aAAa,EAAE,IAAI;AAAA,EACxF;AACF;AAKO,SAAS,qCAAqC,OAAoF;AACvI,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,2KAAkF,EAAE;AAAA,EACxH;AACA,QAAM,MAAM;AACZ,MAAI,CAACD,mBAAkB,IAAI,aAAa,GAAG;AACzC,WAAO,KAAK,0HAAsE;AAAA,EACpF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,EAAE,eAAeC,mBAAkB,IAAI,aAAa,EAAE,IAAI;AAAA,EACxF;AACF;AAKO,SAAS,oCAAoC,OAAoF;AACtI,MAAI,UAAU,UAAa,UAAU,QAAQ,OAAO,UAAU,UAAU;AACtE,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,2KAA+E,EAAE;AAAA,EACrH;AACA,SAAO,EAAE,SAAS,MAAM,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE;AAC/C;AAKO,SAAS,qCAAqC,OAAqF;AACxI,MAAI,UAAU,UAAa,UAAU,QAAQ,OAAO,UAAU,UAAU;AACtE,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,8JAAwE,EAAE;AAAA,EAC9G;AACA,SAAO,EAAE,SAAS,MAAM,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE;AAC/C;AAKO,SAAS,kCAAkC,OAAkF;AAClI,QAAM,SAAmB,CAAC;AAC1B,MAAI,UAAU,UAAa,UAAU,MAAM;AACzC,WAAO,EAAE,SAAS,MAAM,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE;AAAA,EAC/C;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,yGAAsD,EAAE;AAAA,EAC5F;AACA,QAAM,MAAM;AACZ,QAAM,OAAsD,CAAC;AAE7D,MAAI,IAAI,OAAO,UAAa,IAAI,OAAO,QAAQ,IAAI,OAAO,IAAI;AAC5D,QAAI,CAACD,mBAAkB,IAAI,EAAE,GAAG;AAC9B,aAAO,KAAK,+FAAmD;AAAA,IACjE,OAAO;AACL,WAAK,KAAKC,mBAAkB,IAAI,EAAE;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,IAAI,SAAS,UAAa,IAAI,SAAS,MAAM;AAC/C,QAAI,OAAO,IAAI,SAAS,UAAU;AAChC,aAAO,KAAK,kFAA2C;AAAA,IACzD,OAAO;AACL,WAAK,OAAO,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,MAAI,IAAI,UAAU,UAAa,IAAI,UAAU,QAAQ,IAAI,UAAU,IAAI;AACrE,UAAM,MAAM,OAAO,IAAI,KAAK;AAC5B,QAAI,QAAQ,KAAK,QAAQ,GAAG;AAC1B,aAAO,KAAK,0IAAgF;AAAA,IAC9F,OAAO;AACL,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,OAAO;AAAA,EACrC;AACF;AASO,SAAS,mBAAmB,MAAwD;AACzF,QAAM,YAAqC,CAAC;AAC5C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,UAAM,WAAW,IAAI,QAAQ,kBAAkB,EAAE,EAAE,KAAK;AACxD,QAAI,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AAC/D,YAAM,SAAS;AACf,YAAM,eAAwC,EAAE,GAAG,OAAO;AAC1D,UAAI,aAAa,UAAU,OAAO,aAAa,WAAW,YAAY,CAAC,MAAM,QAAQ,aAAa,MAAM,GAAG;AACzG,qBAAa,SAAS,mBAAmB,aAAa,MAAiC;AAAA,MACzF;AACA,UAAI,aAAa,UAAU,OAAO,aAAa,WAAW,YAAY,CAAC,MAAM,QAAQ,aAAa,MAAM,GAAG;AACzG,qBAAa,SAAS,mBAAmB,aAAa,MAAiC;AAAA,MACzF;AACA,gBAAU,QAAQ,IAAI;AAAA,IACxB,OAAO;AACL,gBAAU,QAAQ,IAAI;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,0BACd,OACA,eAAwB,OACiB;AACzC,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,2EAA0C,EAAE;AAAA,EAChF;AAEA,MAAI;AACJ,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,MAAM,KAAK,MAAM,IAAI;AACvB,aAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,gEAAoC,EAAE;AAAA,IAC1E;AACA,QAAI;AACF,kBAAY,KAAK,MAAM,KAAK;AAAA,IAC9B,SAAS,GAAG;AACV,aAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,0CAA8B,EAAY,OAAO,EAAE,EAAE;AAAA,IACzF;AAAA,EACF,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,gBAAY;AAAA,EACd,OAAO;AACL,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,2GAA2D,EAAE;AAAA,EACjG;AAGA,MAAI,CAAC,UAAU,cAAc,CAAC,MAAM,QAAQ,UAAU,UAAU,GAAG;AACjE,WAAO,KAAK,uPAAmJ;AAAA,EACjK,WAAW,UAAU,WAAW,WAAW,GAAG;AAC5C,WAAO,KAAK,mIAA2E;AAAA,EACzF;AAGA,MAAI,CAAC,UAAU,QAAQ,OAAO,UAAU,SAAS,YAAY,MAAM,QAAQ,UAAU,IAAI,GAAG;AAC1F,WAAO,KAAK,sKAA0F;AAAA,EACxG;AAEA,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO,EAAE,SAAS,OAAO,OAAO;AAAA,EAClC;AAGA,QAAM,aAAc,UAAU,WAAyB;AAAA,IAAI,CAAC,OAC1D,OAAO,EAAE,EAAE,QAAQ,kBAAkB,EAAE,EAAE,KAAK;AAAA,EAChD;AACA,QAAM,UAAU,UAAU;AAC1B,QAAM,YAAY,mBAAmB,OAAO;AAE5C,aAAW,WAAW,YAAY;AAChC,QAAI,EAAE,WAAW,YAAY;AAC3B,aAAO,KAAK,iBAAY,OAAO,uGAAmE;AAAA,IACpG,OAAO;AACL,YAAM,QAAQ,UAAU,OAAO;AAC/B,UAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,eAAO,KAAK,qCAAsB,OAAO,4DAA2B;AAAA,MACtE,WAAW,MAAM,SAAS,UAAa,OAAO,MAAM,SAAS,UAAU;AACrE,eAAO,KAAK,mBAAc,OAAO,2GAAiE;AAAA,MACpG;AAAA,IACF;AAAA,EACF;AAGA,MAAI,cAAc;AAChB,eAAW,WAAW,YAAY;AAChC,YAAM,QAAQ,UAAU,OAAO;AAC/B,UAAI,CAAC,MAAO;AAGZ,UAAI,MAAM,SAAS,IAAI;AACrB,cAAM,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,KAAK,KAAK,IAAI;AAClE,YAAI,KAAK,SAAS,KAAK,KAAK,SAAS,IAAI;AACvC,iBAAO,KAAK,0CAAkC,OAAO,mFAAoD;AAAA,QAC3G;AACA,cAAM,MAAM,MAAM;AAClB,YAAI,CAAC,OAAO,OAAO,IAAI,QAAQ,YAAY,CAAC,IAAI,IAAI,WAAW,MAAM,GAAG;AACtE,iBAAO,KAAK,0CAAkC,OAAO,mGAA6D;AAAA,QACpH;AAAA,MACF;AAGA,UAAI,MAAM,SAAS,IAAI;AACrB,cAAM,MAAM,OAAO,MAAM,WAAW,WAAW,MAAM,SAAS;AAC9D,cAAM,OAAO,OAAO,MAAM,eAAe,WAAW,MAAM,WAAW,KAAK,IAAI;AAC9E,YAAI,QAAQ,KAAK,SAAS,IAAI;AAC5B,iBAAO,KAAK,iCAAoB,OAAO,uFAAyC;AAAA,QAClF;AAAA,MACF;AAGA,UAAI,MAAM,SAAS,GAAG;AACpB,cAAM,UAAU,MAAM,QAAQ,MAAM,OAAO,IAAI,MAAM,UAAU,CAAC;AAChE,cAAM,SACJ,MAAM,UAAU,OAAO,MAAM,WAAW,WACnC,MAAM,SACP,CAAC;AACP,mBAAW,OAAO,SAAS;AACzB,gBAAM,MAAM,OAAO,OAAO,GAAG,CAAC;AAC9B,cAAI,OAAO,OAAO,IAAI,QAAQ,YAAY,IAAI,IAAI,KAAK,MAAM,IAAI;AAC/D,mBAAO,KAAK,4BAAuB,OAAO,4CAAwB,GAAG,4DAA2B;AAAA,UAClG;AAAA,QACF;AAAA,MACF;AAGA,UAAI,MAAM,SAAS,IAAI;AACrB,cAAM,MAAM,OAAO,MAAM,YAAY,WAAW,MAAM,QAAQ,KAAK,IAAI;AACvE,YAAI,IAAI,WAAW,KAAK,IAAI,SAAS,IAAI;AACvC,iBAAO,KAAK,yDAAgC,OAAO,qFAA+C;AAAA,QACpG;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAsC;AAAA,IAC1C,SAAU,OAAO,UAAU,YAAY,YAAY,OAAO,UAAU,YAAY,WAAY,UAAU,UAAU;AAAA,IAChH;AAAA,IACA,MAAM;AAAA,IACN,GAAI,UAAU,eAAe,SAAY,EAAE,YAAY,OAAO,UAAU,UAAU,EAAE,IAAI,CAAC;AAAA,IACzF,GAAI,UAAU,kBAAkB,SAAY,EAAE,eAAe,OAAO,UAAU,aAAa,EAAE,IAAI,CAAC;AAAA,IAClG,GAAI,UAAU,cAAc,SAAY,EAAE,WAAW,OAAO,UAAU,SAAS,EAAE,IAAI,CAAC;AAAA,EACxF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,eAAe;AAAA,EAC7C;AACF;AAKO,SAAS,iCAAiC,OAAgF;AAC/H,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,oHAA+D,EAAE;AAAA,EACrG;AACA,QAAM,MAAM;AAGZ,QAAM,gBAAgB,IAAI,iBAAiB,IAAI;AAC/C,MAAI,CAACD,mBAAkB,aAAa,GAAG;AACrC,WAAO,KAAK,2IAAkF;AAAA,EAChG;AAEA,QAAM,YAAYC,mBAAkB,aAAa;AACjD,QAAM,OAAqD;AAAA,IACzD,eAAe;AAAA,IACf,IAAI;AAAA,EACN;AAGA,MAAI,IAAI,SAAS,UAAa,IAAI,SAAS,MAAM;AAC/C,QAAI,OAAO,IAAI,SAAS,UAAU;AAChC,aAAO,KAAK,mEAAoC;AAAA,IAClD,OAAO;AACL,WAAK,OAAO,IAAI;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,IAAI,SAAS,UAAa,IAAI,SAAS,MAAM;AAC/C,QAAI,OAAO,IAAI,SAAS,UAAU;AAChC,aAAO,KAAK,uGAA2D;AAAA,IACzE,OAAO;AACL,WAAK,OAAO,IAAI;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,IAAI,WAAW,UAAa,IAAI,WAAW,MAAM;AACnD,QAAI,OAAO,IAAI,WAAW,WAAW;AACnC,aAAO,KAAK,kPAAiJ;AAAA,IAC/J,WAAW,IAAI,WAAW,KAAK,IAAI,WAAW,GAAG;AAC/C,aAAO,KAAK,qHAAkE;AAAA,IAChF,OAAO;AACL,WAAK,SAAS,IAAI;AAAA,IACpB;AAAA,EACF;AAGA,MAAI,eAAe;AACnB,MAAI,IAAI,WAAW,UAAa,IAAI,WAAW,MAAM;AACnD,UAAM,KAAK,OAAO,IAAI,MAAM;AAC5B,QAAI,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG;AAC9B,aAAO,KAAK,4PAAsI;AAAA,IACpJ,OAAO;AACL,WAAK,SAAS;AACd,UAAI,OAAO,EAAG,gBAAe;AAAA,IAC/B;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,IAAI,UAAU,UAAa,IAAI,UAAU,MAAM;AACjD,UAAM,YAAY,0BAA0B,IAAI,OAAO,YAAY;AACnE,QAAI,CAAC,UAAU,SAAS;AACtB,aAAO,KAAK,GAAG,UAAU,OAAO,IAAI,SAAO,WAAW,GAAG,EAAE,CAAC;AAAA,IAC9D,OAAO;AACL,6BAAuB,UAAU;AACjC,WAAK,QAAQ,KAAK,UAAU,UAAU,IAAI;AAAA,IAC5C;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,IAAI,YAAY,UAAa,IAAI,YAAY,MAAM;AACrD,UAAM,YAAY,0BAA0B,IAAI,SAAS,YAAY;AACrE,QAAI,CAAC,UAAU,SAAS;AACtB,aAAO,KAAK,GAAG,UAAU,OAAO,IAAI,SAAO,aAAa,GAAG,EAAE,CAAC;AAAA,IAChE,OAAO;AACL,+BAAyB,UAAU;AACnC,WAAK,UAAU,KAAK,UAAU,UAAU,IAAI;AAAA,IAC9C;AAAA,EACF;AAGA,MAAI,cAAc;AAChB,QAAI,KAAK,SAAS,CAAC,KAAK,SAAS;AAC/B,WAAK,UAAU,KAAK;AAAA,IACtB,WAAW,KAAK,WAAW,CAAC,KAAK,OAAO;AACtC,WAAK,QAAQ,KAAK;AAAA,IACpB,WAAW,CAAC,KAAK,SAAS,CAAC,KAAK,SAAS;AAAA,IAGzC;AAAA,EACF;AAGA,QAAM,iBAAiB,KAAK,SAAS,UAAa,KAAK,SAAS,UAAa,KAAK,WAAW,UAAa,KAAK,WAAW,UAAa,KAAK,UAAU,UAAa,KAAK,YAAY;AACpL,MAAI,CAAC,gBAAgB;AACnB,WAAO,KAAK,iMAAiI;AAAA,EAC/I;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,OAAO;AAAA,EACrC;AACF;AAKO,SAAS,oCAAoC,OAAmF;AACrI,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,2HAA2D,EAAE;AAAA,EACjG;AACA,QAAM,MAAM;AAEZ,MAAI,YAAY;AAChB,MAAI,OAAO,IAAI,QAAQ,YAAY,IAAI,IAAI,KAAK,MAAM,IAAI;AACxD,gBAAY,IAAI,IAAI,KAAK;AAAA,EAC3B,WAAW,MAAM,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS,GAAG;AACvD,gBAAY,IAAI,IAAI,KAAK,GAAG;AAAA,EAC9B,OAAO;AACL,WAAO,KAAK,uMAAmH;AAAA,EACjI;AAEA,MAAI,WAAW;AACb,UAAM,UAAU,UAAU,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AACtE,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO,KAAK,wFAA+C;AAAA,IAC7D,OAAO;AACL,iBAAW,MAAM,SAAS;AACxB,YAAI,CAACD,mBAAkB,EAAE,GAAG;AAC1B,iBAAO,KAAK,gBAAa,EAAE,yGAA+D;AAAA,QAC5F;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,EAAE,KAAK,UAAU,IAAI;AAAA,EACnD;AACF;AAKO,SAAS,oCAAoC,OAAoF;AACtI,MAAI,UAAU,UAAa,UAAU,QAAQ,OAAO,UAAU,UAAU;AACtE,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,qKAAsF,EAAE;AAAA,EAC5H;AACA,SAAO,EAAE,SAAS,MAAM,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE;AAC/C;AAKO,SAAS,qCAAqC,OAAoF;AACvI,QAAM,SAAmB,CAAC;AAC1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,4HAA+D,EAAE;AAAA,EACrG;AACA,QAAM,MAAM;AAEZ,MAAI,CAACA,mBAAkB,IAAI,aAAa,GAAG;AACzC,WAAO,KAAK,0HAAsE;AAAA,EACpF;AAEA,MAAI,CAAC,IAAI,QAAQ,OAAO,IAAI,SAAS,YAAY,CAAC,QAAQ,KAAK,IAAI,KAAK,KAAK,CAAC,GAAG;AAC/E,WAAO,KAAK,sIAAgF;AAAA,EAC9F;AAEA,MAAI,CAAC,IAAI,YAAY,OAAO,IAAI,aAAa,YAAY,IAAI,SAAS,KAAK,MAAM,IAAI;AACnF,WAAO,KAAK,kHAAuD;AAAA,EACrE;AAEA,MAAI,CAAC,MAAM,QAAQ,IAAI,SAAS,KAAK,IAAI,UAAU,WAAW,GAAG;AAC/D,WAAO,KAAK,yIAAgF;AAAA,EAC9F,OAAO;AACL,QAAI,UAAU,QAAQ,CAAC,GAAG,QAAQ;AAChC,UAAI,CAAC,KAAK,OAAO,MAAM,UAAU;AAC/B,eAAO,KAAK,2BAAc,MAAM,CAAC,0DAAyB;AAC1D;AAAA,MACF;AACA,YAAM,WAAW;AACjB,UAAI,SAAS,SAAS,KAAK,SAAS,SAAS,GAAG;AAC9C,eAAO,KAAK,2BAAc,MAAM,CAAC,qIAAwE;AAAA,MAC3G;AACA,UAAI,CAAC,SAAS,SAAS,OAAO,SAAS,UAAU,YAAY,SAAS,MAAM,KAAK,MAAM,IAAI;AACzF,eAAO,KAAK,2BAAc,MAAM,CAAC,kFAAuC;AAAA,MAC1E;AACA,UAAI,CAAC,MAAM,QAAQ,SAAS,OAAO,KAAK,SAAS,QAAQ,WAAW,GAAG;AACrE,eAAO,KAAK,2BAAc,MAAM,CAAC,4HAAiE;AAAA,MACpG,OAAO;AACL,iBAAS,QAAQ,QAAQ,CAAC,KAAK,WAAW;AACxC,cAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,mBAAO,KAAK,2BAAc,MAAM,CAAC,4BAAe,SAAS,CAAC,2DAA0B;AACpF;AAAA,UACF;AACA,gBAAM,SAAS;AACf,cAAI,OAAO,SAAS,UAAa,OAAO,OAAO,SAAS,UAAU;AAChE,mBAAO,KAAK,2BAAc,MAAM,CAAC,4BAAe,SAAS,CAAC,uEAAwC;AAAA,UACpG;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,OAAO,IAAI,qBAAqB,YAAY,IAAI,mBAAmB;AAC5F,MAAI,gBAAgB,IAAI;AAExB,MAAI,kBAAkB;AACpB,QAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU;AACvD,aAAO,KAAK,2FAAoE;AAAA,IAClF,OAAO;AACL,UAAI,CAAC,cAAc,WAAW,OAAO,cAAc,YAAY,SAAU,QAAO,KAAK,6GAAqD;AAC1I,UAAI,CAAC,cAAc,aAAa,OAAO,cAAc,cAAc,SAAU,QAAO,KAAK,+GAAuD;AAChJ,UAAI,CAAC,cAAc,cAAc,OAAO,cAAc,eAAe,SAAU,QAAO,KAAK,gHAAwD;AACnJ,UAAI,CAAC,cAAc,cAAc,OAAO,cAAc,eAAe,SAAU,QAAO,KAAK,gHAAwD;AAAA,IACrJ;AAAA,EACF;AAEA,QAAM,OAAyD;AAAA,IAC7D,eAAeC,mBAAkB,IAAI,aAAa;AAAA,IAClD,MAAM,OAAO,IAAI,IAAI,EAAE,KAAK;AAAA,IAC5B,UAAU,OAAO,IAAI,QAAQ,EAAE,KAAK;AAAA,IACpC,WAAY,IAAI,aAA+E,CAAC;AAAA,IAChG;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,OAAO;AAAA,EACrC;AACF;AAKO,SAAS,uCACd,OACsE;AACtE,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,mJAA4E;AAAA,IACvF;AAAA,EACF;AAEA,QAAM,MAAM;AAEZ,MAAI,CAACD,mBAAkB,IAAI,aAAa,GAAG;AACzC,WAAO,KAAK,0HAAsE;AAAA,EACpF;AAEA,MAAI,CAAC,MAAM,QAAQ,IAAI,MAAM,KAAK,IAAI,OAAO,WAAW,GAAG;AACzD,WAAO,KAAK,qLAAgG;AAAA,EAC9G,OAAO;AACL,UAAM,mBAAmB,CAAC,GAAG,GAAG,GAAG,CAAC;AACpC,UAAM,cAAc,oBAAI,IAAY;AAEpC,QAAI,OAAO,QAAQ,CAAC,MAAM,QAAQ;AAChC,UAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,eAAO,KAAK,8BAAe,MAAM,CAAC,sFAAkD;AACpF;AAAA,MACF;AACA,YAAM,QAAQ;AACd,YAAM,SAAS,OAAO,MAAM,MAAM;AAClC,UAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,GAAG;AAC5C,eAAO,KAAK,8BAAe,MAAM,CAAC,+HAAuE,MAAM,MAAM,IAAI;AAAA,MAC3H,WAAW,YAAY,IAAI,MAAM,GAAG;AAClC,eAAO,KAAK,8BAAe,MAAM,CAAC,iCAAoB,MAAM,oEAA4C;AAAA,MAC1G,OAAO;AACL,oBAAY,IAAI,MAAM;AAAA,MACxB;AAEA,YAAM,aAAa,OAAO,MAAM,UAAU;AAC1C,UAAI,CAAC,iBAAiB,SAAS,UAAU,GAAG;AAC1C,eAAO,KAAK,8BAAe,MAAM,CAAC,wDAAsC,MAAM,UAAU,iGAAuF;AAAA,MACjL;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,YAAgE;AAAA,IACpE,eAAeC,mBAAkB,IAAI,aAAa;AAAA,IAClD,QAAS,IAAI,UAAmD,CAAC;AAAA,EACnE;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAKO,IAAM,4BAA4B;AAAA,EACvC,2BAA2B;AAAA,EAC3B,0BAA0B;AAAA,EAC1B,8BAA8B;AAAA,EAC9B,kCAAkC;AAAA,EAClC,oCAAoC;AAAA,EACpC,oCAAoC;AAAA,EACpC,+BAA+B;AAAA,EAC/B,iCAAiC;AAAA,EACjC,sBAAsB;AAAA,EACtB,8BAA8B;AAAA,EAC9B,+BAA+B;AAAA,EAC/B,4BAA4B;AAAA,EAC5B,2BAA2B;AAAA,EAC3B,8BAA8B;AAAA,EAC9B,8BAA8B;AAAA,EAC9B,+BAA+B;AACjC;;;AC7vBA,IAAM,uCAA4D;AAAA,EAChE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AACA,IAAM,sCAA2D;AAAA,EAC/D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,0CAA+D;AAAA,EACnE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,8CAAmE;AAAA,EACvE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,gDAAqE;AAAA,EACzE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,gDAAqE;AAAA,EACzE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,2CAAgE;AAAA,EACpE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,6CAAkE;AAAA,EACtE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,0CAA+D;AAAA,EACnE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,2CAAgE;AAAA,EACpE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,wCAA6D;AAAA,EACjE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,uCAA4D;AAAA,EAChE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AACA,IAAM,0CAA+D;AAAA,EACnE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,0CAA+D;AAAA,EACnE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,2CAAgE;AAAA,EACpE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,EACF;AAAA,EACA,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,0BAAN,MAA8B;AAAA,EAO5B,YAA6B,QAA2B;AAA3B;AAAA,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA,EAFhE,OAAuB,YAAY;AAAA,EAG5B,kBAAkB,SAAuD,SAAkF;AAChK,WAAO,KAAK,OAAO,YAA2D,sCAAsC,KAAK,OAAO,iBAAiB,sCAAsC,OAAkC,GAAG,OAAO;AAAA,EACrO;AAAA,EACO,iBAAiB,SAAsD,SAAiF;AAC7J,WAAO,KAAK,OAAO,YAA0D,qCAAqC,KAAK,OAAO,iBAAiB,qCAAqC,OAAkC,GAAG,OAAO;AAAA,EAClO;AAAA,EACO,qBAAqB,SAA0D,SAAqF;AACzK,WAAO,KAAK,OAAO,mBAAqE,yCAAyC,KAAK,OAAO,iBAAiB,yCAAyC,OAAkC,GAAG,OAAO;AAAA,EACrP;AAAA,EACO,yBAAyB,SAA8D,SAAyF;AACrL,WAAO,KAAK,OAAO,mBAAyE,6CAA6C,KAAK,OAAO,iBAAiB,6CAA6C,OAAkC,GAAG,OAAO;AAAA,EACjQ;AAAA,EACO,2BAA2B,SAAgE,SAA2F;AAC3L,WAAO,KAAK,OAAO,mBAA2E,+CAA+C,KAAK,OAAO,iBAAiB,+CAA+C,OAAkC,GAAG,OAAO;AAAA,EACvQ;AAAA,EACO,2BAA2B,SAAgE,SAA2F;AAC3L,WAAO,KAAK,OAAO,mBAA2E,+CAA+C,KAAK,OAAO,iBAAiB,+CAA+C,OAAkC,GAAG,OAAO;AAAA,EACvQ;AAAA,EACO,sBAAsB,SAA2D,SAAsF;AAC5K,WAAO,KAAK,OAAO,mBAAsE,0CAA0C,KAAK,OAAO,iBAAiB,0CAA0C,OAAkC,GAAG,OAAO;AAAA,EACxP;AAAA,EACO,wBAAwB,SAA6D,SAAwF;AAClL,UAAM,iBAAiB;AAAA,MACrB,YAAY,EAAE,eAAe,QAAQ,cAAc;AAAA,MACnD,MAAM,QAAQ;AAAA,IAChB;AACA,WAAO,KAAK,OAAO,YAAiE,4CAA4C,gBAAgB,OAAO;AAAA,EACzJ;AAAA,EACO,qBAAqB,UAA2D,CAAC,GAAG,SAAqF;AAC9K,WAAO,KAAK,OAAO,mBAAqE,yCAAyC,KAAK,OAAO,iBAAiB,yCAAyC,OAAkC,GAAG,OAAO;AAAA,EACrP;AAAA,EACO,sBAAsB,UAA4D,CAAC,GAAG,SAAsF;AACjL,WAAO,KAAK,OAAO,mBAAsE,0CAA0C,KAAK,OAAO,iBAAiB,0CAA0C,OAAkC,GAAG,OAAO;AAAA,EACxP;AAAA,EACO,mBAAmB,UAAyD,CAAC,GAAG,SAAmF;AACxK,WAAO,KAAK,OAAO,mBAAmE,uCAAuC,KAAK,OAAO,iBAAiB,uCAAuC,OAAkC,GAAG,OAAO;AAAA,EAC/O;AAAA,EACO,kBAAkB,SAAuD,SAAkF;AAChK,WAAO,KAAK,OAAO,YAA2D,sCAAsC,KAAK,OAAO,iBAAiB,sCAAsC,OAAkC,GAAG,OAAO;AAAA,EACrO;AAAA,EACO,qBAAqB,SAA0D,SAAqF;AACzK,WAAO,KAAK,OAAO,mBAAqE,yCAAyC,KAAK,OAAO,iBAAiB,yCAAyC,OAAkC,GAAG,OAAO;AAAA,EACrP;AAAA,EACO,qBAAqB,UAA2D,CAAC,GAAG,SAAqF;AAC9K,WAAO,KAAK,OAAO,mBAAqE,yCAAyC,KAAK,OAAO,iBAAiB,yCAAyC,OAAkC,GAAG,OAAO;AAAA,EACrP;AAAA,EACO,sBAAsB,SAA2D,SAAsF;AAC5K,WAAO,KAAK,OAAO,YAA+D,0CAA0C,KAAK,OAAO,iBAAiB,0CAA0C,OAAkC,GAAG,OAAO;AAAA,EACjP;AACF;;;AC7RA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,kCAAuD;AAAA,EAC3D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB;AAAA,IACd;AAAA,EACF;AAAA,EACA,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,iCAAsD;AAAA,EAC1D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB;AAAA,IACd;AAAA,EACF;AAAA,EACA,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEA,IAAM,gCAAqD;AAAA,EACzD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEO,IAAM,wBAAN,MAA4B;AAAA,EAC1B,YAA6B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EAEhE,MAAa,aACX,SACA,SACiD;AACjD,QAAI,YAAY,QAAQ,YAAY;AACpC,QAAI,CAAC,aAAa,KAAK,OAAO,aAAa;AACzC,YAAM,UAAU,MAAM,KAAK,OAAO,YAAY,WAAW,qBAAqB;AAC9E,kBAAY,QAAQ,QAAQ,YAAY,KAAK,QAAQ;AAAA,IACvD;AACA,UAAM,oBAA6C;AAAA,MACjD,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,GAAG;AAAA,MACH,GAAI,YAAY,EAAE,cAAc,UAAU,IAAI,CAAC;AAAA,IACjD;AACA,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,+BAA+B,iBAAiB;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AAAA,EAEO,eACL,SACA,SACmD;AACnD,UAAM,oBAA6C;AAAA,MACjD,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,GAAG;AAAA,IACL;AACA,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,iCAAiC,iBAAiB;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AAAA,EAEO,cACL,SACA,SACkD;AAClD,UAAM,oBAA6C;AAAA,MACjD,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,GAAG;AAAA,IACL;AACA,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,gCAAgC,iBAAiB;AAAA,MAC9E;AAAA,IACF;AAAA,EACF;AAAA,EAEO,aACL,SACiD;AACjD,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAAA,EAEO,aACL,SACA,SACiD;AACjD,WAAO,KAAK,OAAO;AAAA,MACjB;AAAA,MACA,KAAK,OAAO,iBAAiB,+BAA+B,OAA6C;AAAA,MACzG;AAAA,IACF;AAAA,EACF;AACF;;;ACrLA,IAAM,yCAA8D;AAAA,EAClE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,uCAA4D;AAAA,EAChE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,wCAA6D;AAAA,EACjE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe,CAAC;AAAA,EAChB,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AACA,IAAM,yCAA8D;AAAA,EAClE,eAAe;AAAA,EACf,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AAAA,EACf,eAAe;AAAA,IACb;AAAA,EACF;AAAA,EACA,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC;AAAA,EACjB,cAAc,CAAC;AACjB;AAEO,IAAM,uBAAN,MAA2B;AAAA,EACzB,YAA6B,QAA2B;AAA3B;AAAA,EAA4B;AAAA,EACzD,uBAAuB,SAAyD,SAAoF;AACzK,WAAO,KAAK,OAAO,mBAAoE,wCAAwC,KAAK,OAAO,iBAAiB,wCAAwC,OAAkC,GAAG,OAAO;AAAA,EAClP;AAAA,EACO,qBAAqB,SAAuD,SAAkF;AACnK,WAAO,KAAK,OAAO,mBAAkE,sCAAsC,KAAK,OAAO,iBAAiB,sCAAsC,OAAkC,GAAG,OAAO;AAAA,EAC5O;AAAA,EACO,sBAAsB,SAAwD,SAAmF;AACtK,WAAO,KAAK,OAAO,mBAAmE,uCAAuC,KAAK,OAAO,iBAAiB,uCAAuC,OAAkC,GAAG,OAAO;AAAA,EAC/O;AAAA,EACO,uBAAuB,SAAyD,SAAoF;AACzK,WAAO,KAAK,OAAO,mBAAoE,wCAAwC,KAAK,OAAO,iBAAiB,wCAAwC,OAAkC,GAAG,OAAO;AAAA,EAClP;AACF;;;AC3CO,IAAM,aAAN,MAAiB;AAAA,EACL;AAAA,EACD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,UAAsC,CAAC,GAAG;AAC3D,UAAM,kBACJ,OAAO,YAAY,WAAW,EAAE,OAAO,QAAQ,IAAI;AACrD,SAAK,SAAS,IAAI,kBAAkB,eAAe;AACnD,SAAK,MAAM,IAAI,eAAe,KAAK,MAAM;AACzC,SAAK,YAAY,KAAK;AACtB,SAAK,UAAU,KAAK,IAAI;AACxB,SAAK,YAAY,KAAK,IAAI;AAC1B,SAAK,YAAY,KAAK,IAAI;AAC1B,SAAK,UAAU,KAAK,IAAI;AACxB,SAAK,cAAc,KAAK,IAAI;AAC5B,SAAK,QAAQ,KAAK,IAAI;AACtB,SAAK,iBAAiB,KAAK,IAAI;AAC/B,SAAK,QAAQ,KAAK,IAAI;AACtB,SAAK,QAAQ,KAAK,IAAI;AACtB,SAAK,QAAQ,KAAK,IAAI;AACtB,SAAK,QAAQ,IAAI,iBAAiB,KAAK,MAAM;AAC7C,SAAK,eAAe,IAAI,wBAAwB,KAAK,MAAM;AAC3D,SAAK,aAAa,IAAI,sBAAsB,KAAK,MAAM;AACvD,SAAK,UAAU,KAAK;AACpB,SAAK,SAAS,IAAI,qBAAqB,KAAK,MAAM;AAClD,SAAK,aAAa,IAAI,sBAAsB,KAAK,MAAM;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,cAA2C;AACpD,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,eAA6C;AACtD,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAgB,OAAgC;AACrD,SAAK,OAAO,eAAe;AAC3B,QAAI,KAAK,OAAO,aAAa;AAC3B,WAAK,OAAO,YAAY,gBAAgB,KAAK;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,SAAS,YAAoB,YAAiE;AACnG,WAAO,KAAK,OAAO,SAAS,YAAY,UAAU;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKO,mBAAmB,QAAwB,eAAe,OAAmC;AAClG,QAAI,CAAC,KAAK,OAAO,aAAa;AAC5B,YAAM,IAAI,MAAM,uGAAuG;AAAA,IACzH;AACA,WAAO,KAAK,OAAO,YAAY,mBAAmB,QAAQ,YAAY;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAgB,SAAwE;AAC7F,QAAI,CAAC,KAAK,OAAO,aAAa;AAC5B,YAAM,IAAI,MAAM,uGAAuG;AAAA,IACzH;AACA,WAAO,KAAK,OAAO,YAAY,gBAAgB,OAAO;AAAA,EACxD;AAAA,EAEO,QAAQ,MAA0B;AAAE,SAAK,OAAO,QAAQ,IAAI;AAAA,EAAG;AAAA,EAC/D,eAAe,MAAc,MAA0B;AAAE,SAAK,OAAO,eAAe,MAAM,IAAI;AAAA,EAAG;AAC1G;;;ACfO,IAAM,4BAAN,MAAgC;AAAA,EACrB;AAAA,EACC,UAAU,oBAAI,IAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEV,YAAY,UAA4C,CAAC,GAAG;AACjE,SAAK,sBAAsB,QAAQ,uBAAuB;AAC1D,SAAK,eAAe,QAAQ;AAC5B,SAAK,uBAAuB,QAAQ;AACpC,SAAK,uBAAuB,QAAQ;AACpC,SAAK,YAAY,QAAQ;AACzB,SAAK,WAAW,QAAQ;AAExB,QAAI,QAAQ,cAAc;AACxB,WAAK,eAAe,QAAQ;AAAA,IAC9B,WAAW,QAAQ,OAAO;AACxB,WAAK,eAAe,IAAI,uBAAuB,QAAQ,OAAO;AAAA,QAC5D,aAAa,KAAK;AAAA,QAClB,WAAW,QAAQ;AAAA,QACnB,iBAAiB,QAAQ;AAAA,QACzB,mBAAmB,QAAQ,eAAe,KAAK,MAAM,QAAQ,eAAe,GAAI,IAAI;AAAA,MACtF,CAAC;AAAA,IACH,OAAO;AACL,WAAK,eAAe,IAAI,uBAAuB;AAAA,QAC7C,aAAa,KAAK;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,UAAU,SAA2C;AAC1D,UAAM,EAAE,cAAc,IAAI;AAC1B,UAAM,SAAS,qBAAqB,QAAQ,KAAK;AACjD,UAAM,aAAa,OAAO;AAE1B,UAAM,WAAW,KAAK,QAAQ,IAAI,aAAa;AAC/C,QAAI,UAAU;AAEZ,WAAK,QAAQ,OAAO,aAAa;AACjC,UAAI,SAAS,UAAU,YAAY;AACjC,iBAAS,IAAI,SAAS,QAAQ,KAAK;AACnC,iBAAS,QAAQ;AAAA,MACnB;AACA,UAAI,QAAQ,cAAc;AACxB,iBAAS,IAAI,gBAAgB,QAAQ,YAAY;AAAA,MACnD;AACA,WAAK,QAAQ,IAAI,eAAe,QAAQ;AACxC,aAAO,SAAS;AAAA,IAClB;AAEA,QAAI,KAAK,QAAQ,QAAQ,KAAK,qBAAqB;AACjD,YAAM,YAAY,KAAK,QAAQ,KAAK,EAAE,KAAK,EAAE;AAC7C,UAAI,cAAc,QAAW;AAC3B,aAAK,QAAQ,OAAO,SAAS;AAAA,MAC/B;AAAA,IACF;AAEA,UAAM,eAAuC;AAAA,MAC3C,GAAG,OAAO;AAAA,MACV,GAAI,QAAQ,gBAAgB,CAAC;AAAA,MAC7B,GAAI,QAAQ,UAAU,EAAE,UAAU,QAAQ,QAAQ,IAAI,CAAC;AAAA,IACzD;AACA,QAAI,QAAQ,cAAc,YAAY,OAAO,QAAQ,aAAa,QAAQ,MAAM,KAAK;AACnF,mBAAa,cAAc,OAAO,QAAQ,aAAa,QAAQ;AAAA,IACjE;AAEA,UAAM,MAAM,IAAI,WAAW;AAAA,MACzB;AAAA,MACA,OAAO;AAAA,MACP,cAAc,QAAQ;AAAA,MACtB,cAAc,KAAK;AAAA,MACnB,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,SAAS;AAAA,QACP;AAAA,QACA,OAAO;AAAA,QACP,cAAc,QAAQ;AAAA,QACtB;AAAA,QACA,cAAc,KAAK;AAAA,QACnB,cAAc,KAAK;AAAA,QACnB,oBAAoB,KAAK,uBACrB,CAAC,QAAQ,YAAY,KAAK,qBAAsB,eAAe,QAAQ,OAAO,IAC9E;AAAA,MACN;AAAA,IACF,CAAC;AAED,SAAK,QAAQ,IAAI,eAAe,EAAE,KAAK,OAAO,WAAW,CAAC;AAC1D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,eACX,eACA,qBACqB;AACrB,QAAI,qBAAqB;AACvB,YAAM,aACJ,OAAO,wBAAwB,WAC3B,EAAE,OAAO,oBAAoB,IAC7B;AACN,aAAO,KAAK,UAAU,EAAE,eAAe,GAAG,WAAW,CAAC;AAAA,IACxD;AAEA,QAAI,KAAK,sBAAsB;AAC7B,YAAM,WAAW,MAAM,KAAK,qBAAqB,aAAa;AAC9D,YAAM,aACJ,OAAO,aAAa,WAAW,EAAE,OAAO,SAAS,IAAI;AACvD,aAAO,KAAK,UAAU,EAAE,eAAe,GAAG,WAAW,CAAC;AAAA,IACxD;AAEA,UAAM,SAAS,KAAK,QAAQ,IAAI,aAAa;AAC7C,QAAI,QAAQ;AACV,WAAK,QAAQ,OAAO,aAAa;AACjC,WAAK,QAAQ,IAAI,eAAe,MAAM;AACtC,aAAO,OAAO;AAAA,IAChB;AAEA,UAAM,IAAI;AAAA,MACR,0EAA0E,aAAa;AAAA,IACzF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,SAAS,eAAuB,cAAmD;AACxF,UAAM,SAAS,qBAAqB,aAAa;AACjD,UAAM,aAAa,0BAA0B,OAAO,KAAK;AACzD,WAAO,KAAK,UAAU;AAAA,MACpB,eAAe;AAAA,MACf,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,sBACX,eACA,QACe;AACf,UAAM,WAAW,KAAK,QAAQ,IAAI,aAAa;AAC/C,QAAI,UAAU,IAAI,aAAa;AAC7B,UAAI,QAAQ;AACV,cAAM,SAAS,IAAI,YAAY,sBAAsB,MAAM;AAAA,MAC7D,OAAO;AACL,cAAM,SAAS,IAAI,YAAY,mBAAmB;AAAA,MACpD;AACA;AAAA,IACF;AACA,UAAM,KAAK,aAAa,OAAO,eAAe,MAAM;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,kBAAkB,eAAsC;AACnE,UAAM,KAAK,sBAAsB,aAAa;AAC9C,SAAK,QAAQ,OAAO,aAAa;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,kBAAkB,QAMgB;AAC7C,UAAM,SAAS,qBAAqB,OAAO,KAAK;AAChD,UAAM,aAAa,OAAO,iBAAiB,0BAA0B,OAAO,KAAK;AACjF,UAAM,MAAM,KAAK,UAAU;AAAA,MACzB,eAAe;AAAA,MACf,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO;AAAA,IACvB,CAAC;AAED,UAAM,WAAW,MAAM,IAAI,gBAAgB;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,cAAc,MAAM,IAAI,aAC3B,qBAAqB,EACrB,MAAM,OAAO,EAAE,MAAM,CAAC,EAA2C,EAAE;AAEtE,WAAO;AAAA,MACL;AAAA,MACA,YAAY,SAAS,aAAa,GAAG;AAAA,MACrC,kBAAkB,MAAM,QAAQ,aAAa,IAAI,IAAI,YAAY,OAAO,CAAC;AAAA,MACzE,aAAa,SAAS,kBAAkB,GAAG;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,WAAmB;AAC5B,WAAO,KAAK,QAAQ;AAAA,EACtB;AACF;;;AC0BO,IAAK,2BAAL,kBAAKC,8BAAL;AAEL,EAAAA,oDAAA,qBAAkB,KAAlB;AAEA,EAAAA,oDAAA,eAAY,KAAZ;AAEA,EAAAA,oDAAA,eAAY,KAAZ;AAEA,EAAAA,oDAAA,gBAAa,KAAb;AAEA,EAAAA,oDAAA,eAAY,KAAZ;AAEA,EAAAA,oDAAA,sBAAmB,KAAnB;AAEA,EAAAA,oDAAA,gBAAa,KAAb;AAEA,EAAAA,oDAAA,kBAAe,MAAf;AAEA,EAAAA,oDAAA,YAAS,MAAT;AAEA,EAAAA,oDAAA,mBAAgB,MAAhB;AAEA,EAAAA,oDAAA,qBAAkB,MAAlB;AAEA,EAAAA,oDAAA,yBAAsB,MAAtB;AAEA,EAAAA,oDAAA,qBAAkB,MAAlB;AAEA,EAAAA,oDAAA,wBAAqB,MAArB;AAEA,EAAAA,oDAAA,qBAAkB,MAAlB;AAEA,EAAAA,oDAAA,yBAAsB,MAAtB;AAEA,EAAAA,oDAAA,qBAAkB,MAAlB;AAEA,EAAAA,oDAAA,oBAAiB,MAAjB;AAEA,EAAAA,oDAAA,eAAY,MAAZ;AAEA,EAAAA,oDAAA,sBAAmB,MAAnB;AAxCU,SAAAA;AAAA,GAAA;AA0PL,IAAM,iCAAiC;AAAA;AAAA,EAE5C,OAAO;AAAA;AAAA,EAEP,aAAa;AAAA;AAAA,EAEb,eAAe;AAAA;AAAA,EAEf,WAAW;AACb;;;AC9kBO,IAAM,qBAAN,MAAyB;AAAA;AAAA;AAAA;AAAA,EAI9B,OAAO,mBACL,YACA,UAAqC,CAAC,GACnB;AACnB,UAAM,YAAY,QAAQ,aAAa;AACvC,UAAM,eACJ,QAAQ,gBACR;AACF,UAAM,cAAc,QAAQ,eAAe;AAC3C,UAAM,QAAQ,QAAQ,SAAS;AAC/B,UAAM,WAAW,QAAQ,YAAY;AACrC,UAAM,aACJ,QAAQ,kBACR;AAEF,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,YAAQ,YAAY;AAAA,MAClB,KAAK,GAAG;AAEN,cAAM,eACJ,QAAQ,kBAAkB,QAAQ,eAAe,SAAS,IACtD,QAAQ,iBACR,cAAc,IAAI,CAAC,KAAK,OAAO,EAAE,KAAK,MAAM,SAAS,IAAI,CAAC,OAAO,EAAE;AAEzE,cAAM,UAAU,aAAa,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC;AACpD,cAAM,YAA4C,CAAC;AACnD,qBAAa,QAAQ,CAAC,KAAK,MAAM;AAC/B,oBAAU,OAAO,CAAC,CAAC,IAAI;AAAA,YACrB,MAAM,IAAI,QAAQ,SAAS,IAAI,CAAC;AAAA,YAChC,KAAK,IAAI;AAAA,UACX;AAAA,QACF,CAAC;AAED,cAAM,WACJ,QAAQ,eACR;AAEF,eAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY,CAAC,KAAK,KAAK,KAAK,GAAG;AAAA,UAC/B,eAAe;AAAA,UACf,WAAW;AAAA,UACX,MAAM;AAAA,YACJ,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,KAAK;AAAA,cACP;AAAA,YACF;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,KAAK;AAAA,kBACH,EAAE,YAAY,EAAE,MAAM,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,SAAS;AAAA,EAAK;AAAA,kBACrE,EAAE,QAAQ;AAAA,EAAK,QAAQ;AAAA,EAAK;AAAA,gBAC9B;AAAA,cACF;AAAA,cACA,YAAY,uCAAuC,SAAS,uBAAuB,QAAQ;AAAA,cAC3F,QAAQ,UAAU,SAAS,SAAS,SAAS;AAAA,YAC/C;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN;AAAA,cACA,QAAQ;AAAA,cACR,QAAQ;AAAA,gBACN,KAAK,EAAE,MAAM,IAAI,WAAW,IAAI,KAAK,GAAG;AAAA,cAC1C;AAAA,YACF;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,SAAS;AAAA,cACT,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MAEA,KAAK,GAAG;AAEN,eAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY,CAAC,KAAK,KAAK,GAAG;AAAA,UAC1B,eAAe;AAAA,UACf,MAAM;AAAA,YACJ,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,SAAS,CAAC,KAAK,KAAK,GAAG;AAAA,cACvB,QAAQ;AAAA,gBACN,KAAK,EAAE,MAAM,gBAAgB,KAAK,cAAc,CAAC,EAAE;AAAA,gBACnD,KAAK,EAAE,MAAM,gBAAgB,KAAK,cAAc,CAAC,EAAE;AAAA,cACrD;AAAA,cACA,YAAY;AAAA,gBACV,OAAO;AAAA,kBACL,KAAK;AAAA,oBACH,EAAE,YAAY,EAAE,MAAM,KAAK,GAAG,QAAQ,qDAAyB,SAAS,GAAG;AAAA,oBAC3E,EAAE,QAAQ,wHAAsE;AAAA,kBAClF;AAAA,gBACF;AAAA,gBACA,YAAY,gEAAoC,SAAS;AAAA,cAC3D;AAAA,cACA,MAAM;AAAA,cACN,QAAQ;AAAA,gBACN,KAAK,EAAE,MAAM,IAAI,WAAW,IAAI,KAAK,GAAG;AAAA,cAC1C;AAAA,YACF;AAAA,YACA,KAAK;AAAA,cACH,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,6CAAsB,OAAO,oCAAoB,CAAC;AAAA,cACxE,MAAM;AAAA,YACR;AAAA,YACA,KAAK;AAAA,cACH,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA,cAAc;AAAA,cACd,WAAW;AAAA,cACX,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MAEA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,SAAS;AAEP,eAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,YACV;AAAA,YAAK;AAAA,YAAK;AAAA,YAAK;AAAA,YAAM;AAAA,YAAM;AAAA,YAAM;AAAA,YAAM;AAAA,YAAM;AAAA,YAAK;AAAA,YAAK;AAAA,YAAK;AAAA,YAAK;AAAA,YAAK;AAAA,YAAK;AAAA,YAAM;AAAA,YAAM;AAAA,UACzF;AAAA,UACA,YAAY;AAAA,UACZ,eAAe;AAAA,UACf,MAAM;AAAA,YACJ,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,SAAS,CAAC,KAAK,KAAK,GAAG;AAAA,cACvB,QAAQ;AAAA,gBACN,KAAK,EAAE,MAAM,cAAc,KAAK,cAAc,CAAC,EAAE;AAAA,gBACjD,KAAK,EAAE,MAAM,cAAc,KAAK,cAAc,CAAC,EAAE;AAAA,gBACjD,KAAK,EAAE,MAAM,cAAc,KAAK,cAAc,CAAC,EAAE;AAAA,cACnD;AAAA,cACA,QAAQ,EAAE,KAAK,EAAE,MAAM,IAAI,WAAW,IAAI,KAAK,GAAG,EAAE;AAAA,YACtD;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,eAAe;AAAA,cACf,SAAS;AAAA,cACT,eAAe;AAAA,cACf,MAAM;AAAA,cACN,WAAW,KAAK,IAAI;AAAA,cACpB,UAAU;AAAA,cACV,OAAO;AAAA,cACP,YAAY,EAAE,KAAK,CAAC,EAAE,QAAQ,wDAA8B,CAAC,EAAE;AAAA,cAC/D,WAAW;AAAA,cACX,cAAc;AAAA,cACd,YAAY,EAAE,MAAM,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,KAAK;AAAA,YACtE;AAAA,YACA,KAAK;AAAA,cACH,MAAM;AAAA,cACN,MAAM;AAAA,cACN;AAAA,cACA;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,SAAS;AAAA,cACT,cAAc;AAAA,gBACZ,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,YAAY;AAAA,gBACZ,SAAS;AAAA,gBACT,SAAS;AAAA,kBACP,EAAE,MAAM,GAAG,OAAO,+BAAkB,UAAU,EAAE;AAAA,kBAChD,EAAE,MAAM,GAAG,OAAO,yBAAe,UAAU,EAAE;AAAA,gBAC/C;AAAA,gBACA,aAAa;AAAA,gBACb,UAAU;AAAA,cACZ;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,SAAS;AAAA,cACT,cAAc;AAAA,gBACZ,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,YAAY;AAAA,gBACZ,SAAS;AAAA,gBACT,SAAS;AAAA,kBACP,EAAE,MAAM,GAAG,OAAO,qBAAe,UAAU,EAAE;AAAA,kBAC7C,EAAE,MAAM,GAAG,OAAO,qBAAa,UAAU,EAAE;AAAA,gBAC7C;AAAA,gBACA,aAAa;AAAA,gBACb,UAAU;AAAA,cACZ;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,cAAc;AAAA,gBACZ,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,YAAY;AAAA,gBACZ,SAAS;AAAA,gBACT,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,IAAI,UAAU,EAAE,CAAC;AAAA,gBAC7C,aAAa;AAAA,gBACb,UAAU;AAAA,cACZ;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,cAAc;AAAA,gBACZ,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,YAAY;AAAA,gBACZ,SAAS;AAAA,gBACT,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,IAAI,aAAa,oDAA0B,UAAU,EAAE,CAAC;AAAA,gBACpF,aAAa;AAAA,gBACb,UAAU;AAAA,cACZ;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,cAAc;AAAA,gBACZ,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,YAAY;AAAA,gBACZ,SAAS;AAAA,gBACT,SAAS,CAAC,EAAE,MAAM,IAAI,OAAO,IAAI,aAAa,+DAA8B,UAAU,EAAE,CAAC;AAAA,gBACzF,aAAa;AAAA,gBACb,UAAU;AAAA,cACZ;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,YACA,KAAK;AAAA,cACH,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,cAAc;AAAA,gBACZ,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,YAAY;AAAA,gBACZ,SAAS;AAAA,gBACT,SAAS,CAAC,EAAE,MAAM,IAAI,OAAO,IAAI,aAAa,sFAA2C,UAAU,EAAE,CAAC;AAAA,gBACtG,aAAa;AAAA,gBACb,UAAU;AAAA,cACZ;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,YACA,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,YAAY;AAAA,cACZ,aAAa;AAAA,cACb,cAAc;AAAA,cACd,YAAY;AAAA,cACZ,YAAY;AAAA,cACZ,WAAW,eAAe;AAAA,cAC1B,eAAe;AAAA,cACf,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,KAAK;AAAA,cACP;AAAA,cACA,UAAU;AAAA,YACZ;AAAA,YACA,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,KAAK;AAAA,kBACH,EAAE,YAAY,EAAE,OAAO,WAAW,MAAM,KAAK,GAAG,QAAQ,2DAA4B;AAAA,kBACpF,EAAE,QAAQ,+FAA+C,WAAW;AAAA,EAAM;AAAA,gBAC5E;AAAA,cACF;AAAA,cACA,WAAW;AAAA,cACX,cAAc;AAAA,cACd,YAAY,gNAAiI,WAAW;AAAA,YAC1J;AAAA,YACA,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,YAAY;AAAA,cACZ,SAAS;AAAA,cACT,aAAa;AAAA,cACb,cAAc;AAAA,cACd,YAAY;AAAA,cACZ,YAAY;AAAA,cACZ,eAAe;AAAA,cACf,SAAS;AAAA,cACT,OAAO,QAAQ,WAAW;AAAA,cAC1B,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,KAAK;AAAA,cACP;AAAA,cACA,OAAO;AAAA,cACP,YAAY;AAAA,cACZ,WAAW;AAAA,cACX,cAAc;AAAA,YAChB;AAAA,YACA,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,WAAW;AAAA,cACX,OAAO,EAAE,KAAK,cAAc,CAAC,GAAG,MAAM,aAAa;AAAA,cACnD,cAAc,EAAE,UAAU,MAAM,MAAM,KAAK;AAAA,YAC7C;AAAA,YACA,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,WAAW;AAAA,cACX,OAAO,EAAE,KAAK,cAAc,CAAC,GAAG,MAAM,aAAa;AAAA,cACnD,cAAc,EAAE,UAAU,MAAM,MAAM,KAAK;AAAA,YAC7C;AAAA,YACA,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,WAAW;AAAA,cACX,OAAO,EAAE,KAAK,cAAc,CAAC,GAAG,MAAM,aAAa;AAAA,cACnD,cAAc,EAAE,UAAU,MAAM,MAAM,KAAK;AAAA,YAC7C;AAAA,YACA,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,iBAAiB;AAAA,cACjB,WAAW,EAAE,KAAK,CAAC,EAAE,YAAY,EAAE,MAAM,QAAQ,MAAM,KAAK,GAAG,QAAQ,GAAG,SAAS;AAAA,EAAK,CAAC,EAAE;AAAA,cAC3F,UAAU,uCAAuC,SAAS;AAAA,cAC1D,YAAY;AAAA,gBACV;AAAA,kBACE,OAAO;AAAA,oBACL,KAAK;AAAA,oBACL,MAAM;AAAA,kBACR;AAAA,kBACA,WAAW,EAAE,KAAK,CAAC,EAAE,QAAQ,2BAAY,QAAQ,WAAW,yBAAiB;AAAA,EAAK,CAAC,EAAE;AAAA,kBACrF,UAAU,8BAAe,QAAQ,WAAW,yBAAiB;AAAA,gBAC/D;AAAA,gBACA;AAAA,kBACE,OAAO;AAAA,oBACL,KAAK;AAAA,oBACL,MAAM;AAAA,kBACR;AAAA,kBACA,WAAW,EAAE,KAAK,CAAC,EAAE,QAAQ,YAAY,QAAQ,WAAW,WAAW;AAAA,EAAK,CAAC,EAAE;AAAA,kBAC/E,UAAU,eAAe,QAAQ,WAAW,WAAW;AAAA,gBACzD;AAAA,cACF;AAAA,YACF;AAAA,YACA,MAAM;AAAA,cACJ,IAAI;AAAA,cACJ,MAAM;AAAA,cACN,kBAAkB;AAAA,YACpB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC/ZO,IAAK,yBAAL,kBAAKC,4BAAL;AACL,EAAAA,gDAAA,SAAM,KAAN;AADU,SAAAA;AAAA,GAAA;AAIL,IAAK,8BAAL,kBAAKC,iCAAL;AACL,EAAAA,0DAAA,YAAS,KAAT;AACA,EAAAA,0DAAA,WAAQ,KAAR;AACA,EAAAA,0DAAA,sBAAmB,KAAnB;AACA,EAAAA,0DAAA,sBAAmB,KAAnB;AACA,EAAAA,0DAAA,0BAAuB,KAAvB;AACA,EAAAA,0DAAA,0BAAuB,KAAvB;AANU,SAAAA;AAAA,GAAA;AASL,IAAK,6BAAL,kBAAKC,gCAAL;AACL,EAAAA,wDAAA,aAAU,KAAV;AACA,EAAAA,wDAAA,aAAU,MAAV;AACA,EAAAA,wDAAA,YAAS,MAAT;AACA,EAAAA,wDAAA,aAAU,OAAV;AAJU,SAAAA;AAAA,GAAA;AAOL,IAAK,kCAAL,kBAAKC,qCAAL;AACL,EAAAA,kEAAA,YAAS,KAAT;AACA,EAAAA,kEAAA,gBAAa,MAAb;AACA,EAAAA,kEAAA,WAAQ,MAAR;AACA,EAAAA,kEAAA,SAAM,QAAN;AACA,EAAAA,kEAAA,UAAO,UAAP;AALU,SAAAA;AAAA,GAAA;AAQL,IAAK,4BAAL,kBAAKC,+BAAL;AACL,EAAAA,sDAAA,iBAAc,KAAd;AACA,EAAAA,sDAAA,cAAW,KAAX;AACA,EAAAA,sDAAA,aAAU,KAAV;AACA,EAAAA,sDAAA,gBAAa,KAAb;AACA,EAAAA,sDAAA,aAAU,KAAV;AACA,EAAAA,sDAAA,aAAU,KAAV;AANU,SAAAA;AAAA,GAAA;AASL,IAAK,6BAAL,kBAAKC,gCAAL;AACL,EAAAA,wDAAA,aAAU,KAAV;AACA,EAAAA,wDAAA,yBAAsB,KAAtB;AACA,EAAAA,wDAAA,WAAQ,KAAR;AACA,EAAAA,wDAAA,eAAY,KAAZ;AACA,EAAAA,wDAAA,kBAAe,QAAf;AACA,EAAAA,wDAAA,kBAAe,QAAf;AACA,EAAAA,wDAAA,kBAAe,QAAf;AACA,EAAAA,wDAAA,kBAAe,QAAf;AACA,EAAAA,wDAAA,kBAAe,QAAf;AACA,EAAAA,wDAAA,kBAAe,QAAf;AACA,EAAAA,wDAAA,mBAAgB,QAAhB;AACA,EAAAA,wDAAA,mBAAgB,QAAhB;AACA,EAAAA,wDAAA,mBAAgB,QAAhB;AAbU,SAAAA;AAAA,GAAA;AAuBL,IAAM,8BAAN,MAAkC;AAAA;AAAA;AAAA;AAAA,EAIvC,OAAc,mBAAmB,SAA6C;AAC5E,UAAM,SAAmB,CAAC;AAC1B,UAAM,WAAqB,CAAC;AAE5B,QAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,aAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,8EAA6C,GAAG,SAAS;AAAA,IAC7F;AAGA,UAAM,WAAW,OAAO,QAAQ,YAAY,EAAE,EAAE,KAAK;AACrD,QAAI,CAAC,UAAU;AACb,aAAO,KAAK,sFAA6C;AAAA,IAC3D,WAAW,SAAS,SAAS,KAAK;AAChC,aAAO,KAAK,6GAAsD,SAAS,MAAM,kBAAU;AAAA,IAC7F;AAGA,UAAM,QAAQ,QAAQ,UAAU,SAAY,OAAO,QAAQ,KAAK,IAAI;AACpE,QAAI,UAAU,GAAG;AACf,aAAO,KAAK,gGAA4D;AAAA,IAC1E;AAGA,QAAI,CAAC,QAAQ,UAAU,OAAO,QAAQ,WAAW,UAAU;AACzD,aAAO,KAAK,8DAAoC;AAAA,IAClD,OAAO;AACL,YAAM,MAAM,QAAQ;AACpB,YAAMC,WAAU,OAAO,IAAI,IAAI;AAC/B,UAAI,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,SAASA,QAAO,GAAG;AACnC,YAAI,CAAC,GAAG,CAAC,EAAE,SAASA,QAAO,GAAG;AAC5B,iBAAO,KAAK,0BAAaA,aAAY,IAAI,uBAAa,oBAAU,6BAAqBA,QAAO,kGAA8D;AAAA,QAC5J,OAAO;AACL,iBAAO,KAAK,+DAAgC,IAAI,IAAI,uIAA8E;AAAA,QACpI;AAAA,MACF;AAGA,UAAI,CAAC,MAAM,QAAQ,IAAI,MAAM,KAAK,IAAI,OAAO,WAAW,KAAK,OAAO,IAAI,OAAO,CAAC,CAAC,KAAK,GAAG;AACvF,eAAO,KAAK,sIAA2E;AAAA,MACzF,OAAO;AACL,cAAM,MAAM,OAAO,IAAI,OAAO,CAAC,CAAC;AAChC,YAAI,CAAC,GAAG,CAAC,EAAE,SAASA,QAAO,MAAM,MAAM,KAAK,MAAM,MAAM;AACtD,iBAAO,KAAK,oCAA0BA,QAAO,sGAA0D,GAAG,KAAK;AAAA,QACjH;AAAA,MACF;AAGA,UAAI,IAAI,UAAU,UAAa,OAAO,IAAI,KAAK,KAAK,GAAG;AACrD,eAAO,KAAK,kIAAuE;AAAA,MACrF;AAAA,IACF;AAGA,UAAM,YAAY,QAAQ,cAAc,SAAY,OAAO,QAAQ,SAAS,IAAI;AAChF,UAAM,UAAU,QAAQ,SAAS,OAAO,QAAQ,OAAO,IAAI,IAAI;AAC/D,QAAI,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,SAAS,OAAO,GAAG;AAClC,UAAI,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,SAAS,SAAS,GAAG;AACzC,eAAO,KAAK,wMAAsH,SAAS,6HAA2D;AAAA,MACxM;AAAA,IACF;AAGA,QAAI,CAAC,MAAM,QAAQ,QAAQ,UAAU,KAAK,QAAQ,WAAW,WAAW,GAAG;AACzE,aAAO,KAAK,+HAAkE;AAAA,IAChF,OAAO;AACL,cAAQ,WAAW,QAAQ,CAAC,GAAQ,QAAgB;AAClD,cAAM,IAAI,OAAO,EAAE,KAAK;AACxB,YAAI,CAAC,CAAC,GAAG,IAAI,IAAI,MAAM,MAAM,EAAE,SAAS,CAAC,GAAG;AAC1C,iBAAO,KAAK,6BAAc,MAAM,CAAC,yDAAkC,EAAE,KAAK,0FAAgF;AAAA,QAC5J;AACA,cAAM,KAAK,OAAO,EAAE,QAAQ;AAC5B,YAAI,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,SAAS,EAAE,GAAG;AACpC,iBAAO,KAAK,6BAAc,MAAM,CAAC,2DAAwC,EAAE,QAAQ,2FAAiF;AAAA,QACtK;AACA,YAAI,CAAC,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,WAAW,GAAG;AACrD,iBAAO,KAAK,6BAAc,MAAM,CAAC,uEAAwC;AAAA,QAC3E;AACA,YAAI,MAAM,KAAK,CAAC,EAAE,WAAW;AAC3B,mBAAS,KAAK,6BAAc,MAAM,CAAC,iGAA2D;AAAA,QAChG;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA,OAAO;AAAA,MACP,QAAQ;AAAA,QACN,MAAM,OAAO,QAAQ,QAAQ,IAAI;AAAA,QACjC,OAAO;AAAA,QACP,QAAQ,QAAQ,QAAQ,QAAQ,IAAI,MAAM,KAAK,CAAC,EAAE;AAAA,QAClD,OAAO,QAAQ,QAAQ,UAAU,SAAY,OAAO,QAAQ,OAAO,KAAK,IAAI;AAAA,MAC9E;AAAA,MACA,aAAa,QAAQ,cAAc,CAAC,GAAG,IAAI,CAAC,OAAY;AAAA,QACtD,OAAO,OAAO,EAAE,KAAK;AAAA,QACrB,UAAU,OAAO,EAAE,QAAQ;AAAA,QAC3B,QAAQ,EAAE,OAAO,IAAI,MAAM;AAAA,QAC3B,WAAW,EAAE,cAAc,SAAY,OAAO,EAAE,SAAS,IAAI;AAAA,MAC/D,EAAE;AAAA,MACF;AAAA,MACA,YAAY,MAAM,QAAQ,QAAQ,UAAU,IAAI,QAAQ,WAAW,IAAI,MAAM,IAAI,CAAC;AAAA,IACpF;AAEA,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,eAAe,OAAO,WAAW,IAAI,gBAAgB;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,mBAAmB,SAA6C;AAC5E,UAAM,OAAO,KAAK,mBAAmB,OAAO;AAC5C,UAAM,SAAS,CAAC,GAAG,KAAK,MAAM;AAC9B,UAAM,WAAW,CAAC,GAAG,KAAK,QAAQ;AAElC,QAAI,CAAC,QAAQ,mBAAmB,OAAO,QAAQ,eAAe,KAAK,GAAG;AACpE,aAAO,QAAQ,2GAAgE;AAAA,IACjF;AAEA,UAAM,eAAe,MAAM,QAAQ,QAAQ,YAAY,IACnD,QAAQ,aAAa,IAAI,CAAC,UAAe;AAAA,MACvC,WAAW,OAAO,KAAK,SAAS;AAAA,MAChC,MAAM,OAAO,KAAK,IAAI,MAAM,KAAK,KAAK;AAAA;AAAA,IACxC,EAAE,IACF,CAAC;AAEL,UAAM,gBAAgB,KAAK,gBACvB;AAAA,MACE,iBAAiB,OAAO,QAAQ,eAAe;AAAA,MAC/C,GAAG,KAAK;AAAA,MACR;AAAA,IACF,IACA;AAEJ,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AChNO,IAAK,sBAAL,kBAAKC,yBAAL;AACL,EAAAA,0CAAA,eAAY,KAAZ;AACA,EAAAA,0CAAA,0BAAuB,KAAvB;AACA,EAAAA,0CAAA,aAAU,KAAV;AACA,EAAAA,0CAAA,sBAAmB,KAAnB;AACA,EAAAA,0CAAA,UAAO,MAAP;AACA,EAAAA,0CAAA,cAAW,MAAX;AACA,EAAAA,0CAAA,WAAQ,MAAR;AAPU,SAAAA;AAAA,GAAA;AAUL,IAAK,wBAAL,kBAAKC,2BAAL;AACL,EAAAA,8CAAA,WAAQ,KAAR;AACA,EAAAA,8CAAA,cAAW,KAAX;AAFU,SAAAA;AAAA,GAAA;AAYL,IAAM,2BAAN,MAA+B;AAAA;AAAA;AAAA;AAAA,EAIpC,OAAuB,mBAA2C;AAAA,IAChE,CAAC,aAAwB,GAAG;AAAA,IAC5B,CAAC,iBAA4B,GAAG;AAAA,IAChC,CAAC,eAA2B,GAAG;AAAA,IAC/B,CAAC,4BAAwC,GAAG;AAAA,IAC5C,CAAC,wBAAoC,GAAG;AAAA,IACxC,CAAC,iBAA6B,GAAG;AAAA,IACjC,CAAC,cAAyB,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,yBAAyB,SAA0C;AAC/E,UAAM,SAAmB,CAAC;AAC1B,UAAM,WAAqB,CAAC;AAE5B,QAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AAC3C,aAAO,EAAE,SAAS,OAAO,QAAQ,CAAC,qDAAwC,GAAG,SAAS;AAAA,IACxF;AAGA,UAAM,OAAO,OAAO,QAAQ,QAAQ,EAAE,EAAE,KAAK;AAC7C,QAAI,CAAC,MAAM;AACT,aAAO,KAAK,gFAA4C;AAAA,IAC1D,WAAW,KAAK,SAAS,KAAK;AAC5B,aAAO,KAAK,2GAAyD,KAAK,MAAM,kBAAU;AAAA,IAC5F;AAGA,UAAM,cAAc,OAAO,QAAQ,eAAe,EAAE,EAAE,KAAK;AAC3D,QAAI,CAAC,aAAa;AAChB,aAAO,KAAK,wFAA+C;AAAA,IAC7D,OAAO;AACL,YAAM,aAAa;AACnB,UAAI,CAAC,WAAW,KAAK,WAAW,GAAG;AACjC,eAAO,KAAK,+KAA+G;AAAA,MAC7H;AAAA,IACF;AAGA,UAAM,UAAU,QAAQ,YAAY,SAAY,OAAO,QAAQ,OAAO,IAAI;AAC1E,QAAI,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,OAAO,GAAG;AAC7B,aAAO,KAAK,4CAA0B,QAAQ,OAAO,4EAAwD;AAAA,IAC/G;AAGA,UAAM,UAAU,QAAQ,YAAY,SAAY,OAAO,QAAQ,OAAO,IAAI;AAC1E,QAAI,CAAC,OAAO,KAAK,KAAK,gBAAgB,EAAE,IAAI,MAAM,EAAE,SAAS,OAAO,GAAG;AACrE,aAAO,KAAK,0DAA0C,QAAQ,OAAO,0IAA2H;AAAA,IAClM;AAGA,UAAM,YAAsB,MAAM,QAAQ,QAAQ,SAAS,IAAI,QAAQ,UAAU,IAAI,MAAM,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,MAAc,QAAQ,CAAC,CAAC,IAAI,CAAC;AAC/J,UAAM,WAAkB,MAAM,QAAQ,QAAQ,QAAQ,IAAI,QAAQ,WAAW,CAAC;AAC9E,UAAM,WAAqB,MAAM,QAAQ,QAAQ,QAAQ,IAAI,QAAQ,SAAS,IAAI,MAAM,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,MAAc,QAAQ,CAAC,CAAC,IAAI,CAAC;AAE5J,QAAI,UAAU,WAAW,KAAK,SAAS,WAAW,KAAK,SAAS,WAAW,GAAG;AAC5E,aAAO,KAAK,0PAAyJ;AAAA,IACvK;AAGA,UAAM,oBAAoB,SAAS,IAAI,QAAM;AAC3C,UAAI,OAAO,OAAO,YAAY,MAAM,QAAQ,GAAG,KAAK,GAAG;AACrD,eAAO,EAAE,OAAO,GAAG,MAAM,IAAI,MAAM,EAAE,IAAI,CAAC,MAAc,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,MAAc,QAAQ,CAAC,CAAC,EAAE;AAAA,MACtG;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,eAAe,OAAO,WAAW,IAAI,gBAAgB;AAAA,IACvD;AAAA,EACF;AACF;;;ACjGO,IAAM,kCAA0D;AAAA,EACrE,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;AAKO,IAAM,6BAAqD;AAAA,EAChE,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAKO,IAAM,sBAAsB;AAKnC,SAASC,YAAW,KAAsB;AACxC,SAAO,+BAA+B,KAAK,GAAG;AAChD;AAKO,SAAS,4BAA4B,OAAqE;AAC/G,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,6HAAwE;AAAA,IACnF;AAAA,EACF;AAEA,QAAM,MAAM;AAGZ,QAAM,SAAS,OAAO,IAAI,WAAW,WAAW,IAAI,OAAO,KAAK,IAAI;AACpE,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK,+HAA2E;AAAA,EACzF,WAAW,OAAO,SAAS,KAAK,OAAO,SAAS,IAAI;AAClD,WAAO,KAAK,yGAAgE,OAAO,MAAM,kBAAU;AAAA,EACrG,OAAO;AAEL,QAAI,OAAO,SAAS,KAAK,WAAW,OAAO,YAAY,KAAK,QAAQ,KAAK,MAAM,GAAG;AAChF,aAAO,KAAK,0LAAiH;AAAA,IAC/H;AAEA,UAAM,oBAAoB,CAAC,aAAQ,2BAAiB,qBAAgB,kCAAc;AAClF,eAAW,MAAM,mBAAmB;AAClC,UAAI,OAAO,YAAY,EAAE,SAAS,EAAE,GAAG;AACrC,eAAO,KAAK,6HAA4E,EAAE,IAAI;AAAA,MAChG;AAAA,IACF;AAAA,EACF;AAGA,QAAM,cAAc,OAAO,IAAI,gBAAgB,WAAW,IAAI,YAAY,KAAK,IAAI;AACnF,MAAI,CAAC,aAAa;AAChB,WAAO,KAAK,+FAAwD;AAAA,EACtE,WAAW,YAAY,SAAS,MAAM,YAAY,SAAS,KAAK;AAC9D,WAAO,KAAK,iIAAiE,YAAY,MAAM,kBAAU;AAAA,EAC3G;AAGA,QAAM,cAAc,OAAO,IAAI,gBAAgB,WAAW,IAAI,YAAY,KAAK,IAAI;AACnF,MAAI,CAAC,aAAa;AAChB,WAAO,KAAK,gGAAsD;AAAA,EACpE,WAAW,YAAY,MAAM,KAAK,EAAE,SAAS,GAAG;AAC9C,WAAO,KAAK,wHAA2D;AAAA,EACzE;AAGA,QAAM,eAAe,OAAO,IAAI,iBAAiB,WAAW,IAAI,aAAa,KAAK,IAAI,OAAO,IAAI,gBAAgB,EAAE,EAAE,KAAK;AAC1H,MAAI,CAAC,cAAc;AACjB,WAAO,KAAK,8FAAqD;AAAA,EACnE,OAAO;AACL,UAAM,aAAa,aAAa,QAAQ,QAAQ,EAAE;AAClD,QAAI,CAAC,oBAAoB,KAAK,UAAU,GAAG;AACzC,aAAO,KAAK,sDAA0B,YAAY,6JAA6F;AAAA,IACjJ;AAAA,EACF;AAGA,QAAM,WAAW,OAAO,IAAI,aAAa;AACzC,MAAI,CAAC,YAAY,CAAC,gCAAgC,QAAQ,GAAG;AAC3D,WAAO;AAAA,MACL,mEAA4C,IAAI,aAAa;AAAA,IAC/D;AAAA,EACF;AAGA,QAAM,aAAa,OAAO,IAAI,QAAQ;AACtC,MAAI,CAAC,cAAc,CAAC,2BAA2B,UAAU,GAAG;AAC1D,WAAO;AAAA,MACL,mDAAmC,IAAI,QAAQ;AAAA,IACjD;AAAA,EACF;AAGA,QAAM,WAAW,OAAO,IAAI,QAAQ;AACpC,MAAI,CAAC,YAAY,CAAC,OAAO,UAAU,QAAQ,KAAK,YAAY,GAAG;AAC7D,WAAO,KAAK,mIAAyE;AAAA,EACvF;AAGA,QAAM,UAAU,OAAO,IAAI,YAAY,WAAW,IAAI,QAAQ,KAAK,IAAI;AACvE,MAAI,CAAC,WAAW,QAAQ,SAAS,GAAG;AAClC,WAAO,KAAK,oJAA0E;AAAA,EACxF;AAGA,QAAM,WAAW,OAAO,IAAI,aAAa,WAAW,IAAI,SAAS,KAAK,IAAI;AAC1E,MAAI,CAAC,UAAU;AACb,WAAO,KAAK,oKAA+F;AAAA,EAC7G;AAEA,QAAM,UAAU,OAAO,IAAI,YAAY,WAAW,IAAI,QAAQ,KAAK,IAAI;AACvE,MAAI,CAAC,SAAS;AACZ,WAAO,KAAK,iJAAwF;AAAA,EACtG;AAEA,QAAM,YAA+C;AAAA,IACnD,QAAQ;AAAA,IACR,QAAQ,IAAI,WAAW,SAAY,OAAO,IAAI,MAAM,IAAI;AAAA,IACxD,UAAU,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;AAAA,IAC5D,MAAM,IAAI,SAAS,SAAY,OAAO,IAAI,IAAI,IAAI;AAAA,IAClD,YAAY,IAAI,eAAe,SAAY,OAAO,IAAI,UAAU,IAAI;AAAA,IACpE,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW,IAAI,cAAc,SAAY,QAAQ,IAAI,SAAS,IAAI;AAAA,IAClE,GAAI,OAAO,IAAI,YAAY,MAAM,WAAW,EAAE,cAAc,IAAI,YAAY,EAAE,IAAI,CAAC;AAAA,EACrF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAYO,SAAS,2BACd,OACA,SACsE;AACtE,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,oHAAoD;AAAA,IAC/D;AAAA,EACF;AAEA,QAAM,MAAM;AACZ,QAAM,YAAY,QAAQ,cAAc,WAAY,IAAI,aAAa,KAAK,IAAI,QAAQ,IAAI,OAAS,IAAI,YAAY,KAAK,IAAI,QAAQ,IAAI;AAExI,MAAI,CAAC,WAAW;AACd,WAAO,KAAK,wCAAoB,QAAQ,cAAc,WAAW,gBAAgB,YAAY,8BAAiB;AAC9G,WAAO,EAAE,SAAS,OAAO,OAAO;AAAA,EAClC;AAGA,MAAI,OAAO,cAAc,UAAU;AACjC,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,CAAC,SAAS;AACZ,aAAO,KAAK,uGAAwC;AAAA,IACtD,WAAW,CAACA,YAAW,OAAO,GAAG;AAC/B,aAAO,KAAK,2CAAkB,OAAO,8FAAiE;AAAA,IACxG;AAAA,EACF;AAGA,QAAM,WAAW,QAAQ,gBAAgB,KAAK,OAAO;AACrD,MAAI,OAAO,IAAI,cAAc,YAAY,IAAI,YAAY,UAAU;AACjE,UAAM,UAAU,IAAI,aAAa,OAAO,OAAO,QAAQ,CAAC;AACxD,WAAO,KAAK,uHAA6D,MAAM,MAAM;AAAA,EACvF;AAEA,QAAM,OAAO,QAAQ,aAAa,QAAQ,cAAc,WAAW,MAAM;AACzE,QAAM,OAAO,QAAQ,cAAc,QAAQ,cAAc,WAAW,MAAM;AAE1E,MAAI,OAAO,IAAI,UAAU,YAAY,IAAI,QAAQ,MAAM;AACrD,WAAO,KAAK,qDAA4B,IAAI,2BAAiB,IAAI,KAAK,MAAM;AAAA,EAC9E;AACA,MAAI,OAAO,IAAI,WAAW,YAAY,IAAI,SAAS,MAAM;AACvD,WAAO,KAAK,+CAA2B,IAAI,2BAAiB,IAAI,MAAM,MAAM;AAAA,EAC9E;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IACpB;AAAA,MACE,MAAM;AAAA,MACN,OAAO,OAAO,IAAI,QAAQ,MAAM,WAAW,IAAI,QAAQ,IAAI;AAAA,MAC3D,QAAQ,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS;AAAA,IACxD,IACA;AAAA,EACN;AACF;AAKO,IAAM,0BAA0B;AAAA,EACrC,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,sBAAsB,CAAC,UACrB,2BAA2B,OAAO,EAAE,WAAW,UAAU,UAAU,KAAK,WAAW,IAAI,CAAC;AAAA,EAC1F,qBAAqB,CAAC,UACpB,2BAA2B,OAAO,EAAE,WAAW,SAAS,UAAU,KAAK,WAAW,IAAI,CAAC;AAC3F;;;ACnSO,IAAM,2BAA2B,KAAK;AAKtC,IAAM,sBAAsB,2BAA2B;AAKvD,SAAS,kCACd,OACoD;AACpD,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,4HAA2D;AAAA,IACtE;AAAA,EACF;AAEA,QAAM,MAAM;AAGZ,MAAI,KAAK;AACT,MAAI,IAAI,OAAO,UAAa,IAAI,OAAO,MAAM;AAC3C,UAAM,WAAW,OAAO,IAAI,EAAE;AAC9B,QAAI,CAAC,OAAO,UAAU,QAAQ,KAAK,WAAW,GAAG;AAC/C,aAAO,KAAK,+HAA2E;AAAA,IACzF,OAAO;AACL,WAAK;AAAA,IACP;AAAA,EACF;AAGA,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAC9D,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,sIAAoE;AAAA,EAClF,WAAW,KAAK,SAAS,KAAK;AAC5B,WAAO,KAAK,oIAAkE,KAAK,MAAM,kBAAU;AAAA,EACrG;AAGA,QAAM,WAAqB,CAAC;AAC5B,MAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,KAAK,IAAI,SAAS,WAAW,GAAG;AAC7D,WAAO,KAAK,wIAA4E;AAAA,EAC1F,OAAO;AACL,eAAW,QAAQ,IAAI,UAAU;AAC/B,YAAM,QAAQ,OAAO,IAAI;AACzB,UAAI,CAAC,OAAO,UAAU,KAAK,KAAK,SAAS,GAAG;AAC1C,eAAO,KAAK,oCAAkB,IAAI,iFAA0C;AAAA,MAC9E,OAAO;AACL,YAAI,CAAC,SAAS,SAAS,KAAK,GAAG;AAC7B,mBAAS,KAAK,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,IAAI,SAAS;AAEvC,QAAM,YAA8C;AAAA,IAClD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAqBO,SAAS,+BACd,OACwC;AACxC,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,6HAAkE;AAAA,IAC7E;AAAA,EACF;AAEA,QAAM,MAAM;AAGZ,QAAM,WAAW,IAAI,aAAa,IAAI;AACtC,QAAM,SAAS,IAAI,WAAW,IAAI;AAElC,MAAI,aAAa,UAAa,aAAa,MAAM;AAC/C,WAAO,KAAK,yGAA8D;AAAA,EAC5E;AACA,MAAI,WAAW,UAAa,WAAW,MAAM;AAC3C,WAAO,KAAK,+FAA2D;AAAA,EACzE;AAEA,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO,EAAE,SAAS,OAAO,OAAO;AAAA,EAClC;AAEA,QAAM,WAAW,OAAO,QAAQ;AAChC,QAAM,SAAS,OAAO,MAAM;AAE5B,MAAI,MAAM,QAAQ,KAAK,YAAY,GAAG;AACpC,WAAO,KAAK,mDAA0B,QAAQ,8EAA+C;AAAA,EAC/F;AACA,MAAI,MAAM,MAAM,KAAK,UAAU,GAAG;AAChC,WAAO,KAAK,6CAA2B,MAAM,8EAA+C;AAAA,EAC9F;AAEA,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO,EAAE,SAAS,OAAO,OAAO;AAAA,EAClC;AAIA,QAAM,OAAO,WAAW,QAAe,SAAS;AAChD,QAAM,WAAW,OAAO,sBAAsB;AAE9C,MAAI,SAAS,UAAU;AACrB,WAAO,KAAK,0IAAsE;AAAA,EACpF,OAAO;AACL,UAAM,OAAO,SAAS;AACtB,QAAI,OAAO,UAAU;AACnB,YAAM,OAAO,OAAO,KAAK,MAAM,QAAQ,QAAQ,IAAK,IAAI,KAAK,MAAM,OAAO,KAAK;AAC/E,aAAO,KAAK,uMAAsH,IAAI,YAAS;AAAA,IACjJ;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,IAAI,eAAe,UAAa,IAAI,eAAe,MAAM;AAC3D,UAAM,eAAe,OAAO,IAAI,UAAU;AAC1C,QAAI,CAAC,OAAO,UAAU,YAAY,KAAK,gBAAgB,GAAG;AACxD,aAAO,KAAK,oGAA6D;AAAA,IAC3E,OAAO;AACL,mBAAa;AAAA,IACf;AAAA,EACF;AAEA,QAAM,YAAkC;AAAA,IACtC,WAAW;AAAA,IACX,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAKO,IAAM,uBAAuB;AAAA,EAClC,4BAA4B;AAAA,EAC5B,yBAAyB;AAC3B;;;AC1LA,SAASC,YAAW,KAAuB;AACzC,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,SAAO,kBAAkB,KAAK,IAAI,KAAK,CAAC;AAC1C;AAKO,SAAS,yBACd,OAC8C;AAC9C,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,sGAAsD;AAAA,IACjE;AAAA,EACF;AAGA,MAAI,YAAqB;AACzB,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI;AACF,kBAAY,KAAK,MAAM,KAAK;AAAA,IAC9B,QAAQ;AACN,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,CAAC,kGAAyD;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,aAAa,OAAO,cAAc,UAAU;AAC/C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC,iFAAsC;AAAA,IACjD;AAAA,EACF;AAEA,QAAM,SAAS;AAEf,MAAI,MAAM;AACV,MAAI,OAAO,QAAQ,OAAO,OAAO,SAAS,UAAU;AAClD,UAAM,OAAO;AAAA,EACf,WAAW,OAAO,OAAO,SAAS,UAAU;AAC1C,QAAI;AACF,YAAM,KAAK,MAAM,OAAO,IAAI;AAAA,IAC9B,QAAQ;AACN,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ,CAAC,+FAAsD;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAGA,QAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAK,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;AAChH,MAAI,CAAC,MAAM;AACT,WAAO,KAAK,qHAA4D;AAAA,EAC1E,WAAW,KAAK,SAAS,KAAK;AAC5B,WAAO,KAAK,mHAA0D,KAAK,MAAM,kBAAU;AAAA,EAC7F;AAGA,QAAM,UAAU,IAAI,SAAS,SAAY,OAAO,IAAI,IAAI,IAAK,IAAI,SAAS,SAAY,OAAO,IAAI,IAAI,IAAI;AACzG,MAAI,YAAY,KAAK,YAAY,GAAG;AAClC,WAAO,KAAK,wDAAsC,IAAI,QAAQ,IAAI,IAAI,gEAAuC;AAAA,EAC/G;AAGA,QAAM,cAAe,IAAI,YAAY,IAAI;AACzC,MAAI,CAAC,eAAe,OAAO,gBAAgB,UAAU;AACnD,WAAO,KAAK,wEAA8C;AAC1D,WAAO,EAAE,SAAS,OAAO,OAAO;AAAA,EAClC;AAGA,QAAM,MAAM,OAAO,YAAY,QAAQ,WAAW,YAAY,IAAI,KAAK,IAAK,OAAO,YAAY,QAAQ,WAAW,YAAY,IAAI,KAAK,IAAI;AAC3I,MAAI,CAAC,KAAK;AACR,WAAO,KAAK,yFAAmD;AAAA,EACjE,WAAW,CAACA,YAAW,GAAG,GAAG;AAC3B,WAAO,KAAK,6FAAuD,GAAG,0GAAoE;AAAA,EAC5I;AAGA,QAAM,QAAQ,OAAO,YAAY,SAAS,YAAY,KAAK;AAC3D,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,SAAS,GAAG;AAC1C,WAAO,KAAK,uIAAoF,YAAY,SAAS,YAAY,KAAK,EAAE;AAAA,EAC1I;AAEA,QAAM,SAAS,OAAO,YAAY,UAAU,YAAY,MAAM;AAC9D,MAAI,CAAC,OAAO,UAAU,MAAM,KAAK,UAAU,GAAG;AAC5C,WAAO,KAAK,kIAAoF,YAAY,UAAU,YAAY,MAAM,EAAE;AAAA,EAC5I;AAGA,MAAI;AACJ,MAAI;AAEJ,MAAI,YAAY,GAAG;AACjB,UAAM,MAAM,OAAO,YAAY,YAAY,YAAY,QAAQ;AAC/D,QAAI,CAAC,MAAM,GAAG,KAAK,MAAM,GAAG;AAC1B,UAAI,MAAM,KAAK;AACb,eAAO,KAAK,6IAAkF,GAAG,KAAK;AAAA,MACxG,OAAO;AACL,mBAAW;AAAA,MACb;AAAA,IACF,OAAO;AACL,aAAO,KAAK,gLAAgH;AAAA,IAC9H;AAEA,UAAM,QAAQ,OAAO,YAAY,aAAa,WAAW,YAAY,SAAS,KAAK,IAAK,OAAO,YAAY,aAAa,WAAW,YAAY,SAAS,KAAK,IAAI;AACjK,QAAI,OAAO;AACT,UAAI,CAACA,YAAW,KAAK,GAAG;AACtB,eAAO,KAAK,0FAA8D,KAAK,oCAA4B;AAAA,MAC7G,OAAO;AACL,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAwC;AAAA,IAC5C,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,MACR,KAAK;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,GAAI,aAAa,SAAY,EAAE,UAAU,SAAS,IAAI,CAAC;AAAA,MACvD,GAAI,aAAa,SAAY,EAAE,UAAU,SAAS,IAAI,CAAC;AAAA,IACzD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA,MAAM,OAAO,WAAW,IAAI,YAAY;AAAA,EAC1C;AACF;AAKO,IAAM,qBAAqB;AAAA,EAChC,mBAAmB;AACrB;","names":["bytes","OP_ZaloAdsUpdateNewAds","OP_ZaloAdsCreateForm","OP_ZaloAdsListFormsByOfficialAccount","isPositiveInteger","toPositiveInteger","ZaloInstantPageBlockType","AutomatedRuleScopeEnum","AutomatedRuleActionTypeEnum","AutomatedRuleFrequencyEnum","AutomatedRuleConditionFieldEnum","AutomatedRuleOperatorEnum","AutomatedRuleTimeRangeEnum","actType","ConversionLabelEnum","ConversionUrlTypeEnum","isValidUrl","isValidUrl"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/store.ts","../src/auth.ts","../src/client.ts","../src/validators/audiences.validator.ts","../src/dtos/ads.dto.ts","../src/validators/campaigns.validator.ts","../src/services/campaigns.service.ts","../src/services/account.service.ts","../src/services/audiences.service.ts","../src/services/reports.service.ts","../src/services/conversions.service.ts","../src/services/automated-rules.service.ts","../src/validators/flows.validator.ts","../src/services/flows.service.ts","../src/services/media.service.ts","../src/services/ads.service.ts","../src/services/chat-widget.service.ts","../src/validators/forms.validator.ts","../src/services/forms.service.ts","../src/validators/instant-pages.validator.ts","../src/services/instant-pages.service.ts","../src/services/profile-ads.service.ts","../src/services/widget.service.ts","../src/sdk.ts","../src/manager.ts","../src/dtos/instant-pages.dto.ts","../src/helpers/instant-page-factory.ts","../src/validators/automated-rules.validator.ts","../src/validators/conversions.validator.ts","../src/validators/profile-ads.validator.ts","../src/validators/reports.validator.ts","../src/validators/media.validator.ts"],"sourcesContent":["import type { ZaloAuthManager, ZaloSsoAuthOptions } from \"./auth\";\nimport type { ZaloRedisLikeClient, ZaloSessionStore } from \"./store\";\n\nexport type HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport type FileInput = string | Blob | ArrayBuffer | Uint8Array;\n\nexport interface ZaloSdkAuthContext {\n readonly url: string;\n readonly host: string;\n readonly operationId: string;\n readonly method: HttpMethod;\n}\n\nexport interface ZaloSdkAuth {\n headers?: Record<string, string>;\n cookies?: Record<string, string>;\n getHeaders?: (context: ZaloSdkAuthContext) => Promise<Record<string, string> | undefined> | Record<string, string> | undefined;\n getCookies?: (context: ZaloSdkAuthContext) => Promise<Record<string, string> | undefined> | Record<string, string> | undefined;\n}\n\nexport interface ZaloAccountScope {\n accountId?: string | number;\n memberId?: string | number;\n agencyId?: string | number;\n accountType?: 'PERSONAL' | 'ACCESSOR' | 'AGENCY' | 'AGENCY_MASTER' | 'AGENCY_SUB_ACCOUNT' | string;\n isRoot?: boolean;\n}\n\nexport interface ZaloAdsSdkOptions {\n /**\n * Phạm vi tài khoản quảng cáo cô lập (Isolated Workspace) - chứa accountId, memberId, agencyId, accountType.\n * Dùng để tự động gài tham số báo cáo (agencyId, createdBy) và cô lập phiên (ads_user_id, PLAY_SESSION).\n */\n accountScope?: ZaloAccountScope;\n /**\n * Định danh Integration (`integrationId`) hoặc `accountKey` để cô lập phiên khi quản lý nhiều tài khoản trên RAM/Redis.\n * Nếu không truyền, SDK tự động tạo `accountKey` duy nhất từ `zpsid`.\n */\n integrationId?: string;\n /**\n * Alias của `integrationId` để định danh tài khoản trong `ZaloSessionStore`.\n */\n accountKey?: string;\n /**\n * Giá trị cookie `zpsid` gốc của Zalo (hoặc nguyên chuỗi Cookie trình duyệt có chứa `zpsid=...`).\n * Khi truyền `zpsid`, SDK sẽ tự động khởi tạo `ZaloAuthManager` để thực hiện Silent OAuth2 PKCE SSO\n * lấy `PLAY_SESSION`, `XSRF-TOKEN`, `zf_id` và `Authorization` token cho từng domain.\n */\n zpsid?: string;\n /**\n * Cookie phụ `zoaw_sek` (tùy chọn, dùng cho các API thuộc `api.widget.zalo.me` / `widget.chat.zalo.me`).\n */\n zoawSek?: string;\n /**\n * Tầng lưu trữ phiên (RAM `MemoryZaloSessionStore`, Redis `RedisZaloSessionStore`, hoặc 2 tầng `TieredZaloSessionStore`).\n * Nếu không truyền `sessionStore` và `redis`, mặc định dùng `defaultSharedMemorySessionStore` (RAM LRU).\n */\n sessionStore?: ZaloSessionStore;\n /**\n * Truyền trực tiếp `RedisService` (của `redai-v201-be-app-staging`) hoặc `ioredis` client\n * để tự động bật lưu trữ 2 tầng (L1 RAM + L2 Redis + Distributed Lock).\n */\n redis?: ZaloRedisLikeClient;\n /**\n * Tiền tố key trên Redis khi sử dụng tùy chọn `redis` (mặc định: `'zalo_ads:sso'`).\n */\n redisKeyPrefix?: string;\n /**\n * Cấu hình nâng cao cho cơ chế tự động xác thực SSO qua `zpsid`.\n */\n ssoAuth?: ZaloSsoAuthOptions;\n /**\n * Instance `ZaloAuthManager` truyền từ ngoài vào (nếu muốn dùng chung giữa nhiều instance SDK).\n */\n authManager?: ZaloAuthManager;\n /**\n * Tự động handshake lại và retry 1 lần khi gặp lỗi 401 Unauthorized (mặc định: `true`).\n */\n autoRetryOn401?: boolean;\n auth?: ZaloSdkAuth;\n authByHost?: Record<string, ZaloSdkAuth>;\n fetch?: typeof fetch;\n baseUrls?: Partial<Record<\"ads\" | \"forms\" | \"instantPages\" | \"profileAds\" | \"widget\" | \"chatWidget\", string>>;\n}\n\nexport interface RequestOptions {\n signal?: AbortSignal;\n headers?: Record<string, string>;\n}\n\nexport class ZaloSdkError extends Error {\n public readonly status: number;\n public readonly operationId: string;\n public readonly responseBody: unknown;\n\n constructor(message: string, status = 500, operationId = \"unknown\", responseBody: unknown = null) {\n super(message);\n this.name = \"ZaloSdkError\";\n this.status = status;\n this.operationId = operationId;\n this.responseBody = responseBody;\n }\n}\n\nexport interface FileDownloadResponse {\n file: Blob;\n filename?: string;\n contentType: string | null;\n}\n","import type { ZaloAdsDomain, ZaloDomainSession } from './auth';\n\n/**\n * Interface tương thích với cả:\n * 1. `RedisService` của `redai-v201-be-app-staging` (`get`, `setWithExpiry`, `set`, `del`, `setNX`)\n * 2. `ioredis` / `node-redis` client tiêu chuẩn (`get`, `setex` / `set`, `del`)\n */\nexport interface ZaloRedisLikeClient {\n get(key: string): Promise<string | null>;\n del(key: string | string[]): Promise< unknown>;\n /** Method của NestJS RedisService trong redai-v201-be-app-staging */\n setWithExpiry?(key: string, value: string, expiryInSeconds: number): Promise<unknown>;\n /** Method của NestJS RedisService trong redai-v201-be-app-staging */\n setNX?(key: string, value: string, expiryInSeconds: number): Promise<boolean>;\n /** Method của ioredis */\n setex?(key: string, seconds: number, value: string): Promise<unknown>;\n /** Method cơ bản của RedisService / ioredis / node-redis */\n set?(key: string, value: string, ...args: unknown[]): Promise<unknown>;\n}\n\n/**\n * Interface chuẩn cho tầng lưu trữ Session Zalo Ads (RAM / Redis / Custom DB).\n * Hỗ trợ đa tài khoản (multi-account / multi-integration) thông qua `accountKey`.\n */\nexport interface ZaloSessionStore {\n /** Lấy phiên của 1 domain thuộc 1 tài khoản/integration */\n get(accountKey: string, domain: ZaloAdsDomain): Promise<ZaloDomainSession | null> | ZaloDomainSession | null;\n\n /** Lưu phiên của 1 domain thuộc 1 tài khoản/integration */\n set(accountKey: string, domain: ZaloAdsDomain, session: ZaloDomainSession, ttlSeconds?: number): Promise<void> | void;\n\n /** Xóa phiên của 1 domain hoặc toàn bộ domain thuộc 1 tài khoản/integration */\n delete(accountKey: string, domain?: ZaloAdsDomain): Promise<void> | void;\n\n /** Lấy toàn bộ phiên các domain của 1 tài khoản/integration */\n getAll?(accountKey: string): Promise<Partial<Record<ZaloAdsDomain, ZaloDomainSession>>> | Partial<Record<ZaloAdsDomain, ZaloDomainSession>>;\n\n /**\n * Distributed lock (tùy chọn, dùng cho Redis multi-instance/cluster)\n * Trả về true nếu chiếm được lock, false nếu tiến trình khác đang giữ lock.\n */\n acquireLock?(accountKey: string, domain: ZaloAdsDomain, ttlSeconds: number): Promise<boolean>;\n\n /** Giải phóng distributed lock */\n releaseLock?(accountKey: string, domain: ZaloAdsDomain): Promise<void>;\n}\n\nexport const ALL_ZALO_ADS_DOMAINS: readonly ZaloAdsDomain[] = [\n 'ads.zalo.me',\n 'page.ads.zalo.me',\n 'form.ads.zalo.me',\n 'profile.ads.zalo.me',\n 'api.widget.zalo.me',\n 'widget.chat.zalo.me',\n];\n\nexport interface MemoryZaloSessionStoreOptions {\n /**\n * Số lượng tài khoản/integration tối đa giữ trong RAM (LRU eviction).\n * Mặc định: 500 tài khoản.\n */\n maxAccounts?: number;\n}\n\n/**\n * Lưu trữ Session trong RAM (L1 Cache) có cơ chế LRU chống tràn bộ nhớ khi quản lý nhiều Integration.\n */\nexport class MemoryZaloSessionStore implements ZaloSessionStore {\n private readonly store = new Map<string, Map<ZaloAdsDomain, ZaloDomainSession>>();\n private readonly maxAccounts: number;\n\n public constructor(options: MemoryZaloSessionStoreOptions = {}) {\n this.maxAccounts = options.maxAccounts ?? 500;\n }\n\n public get(accountKey: string, domain: ZaloAdsDomain): ZaloDomainSession | null {\n const accountMap = this.store.get(accountKey);\n if (!accountMap) return null;\n\n // Cập nhật thứ tự LRU\n this.store.delete(accountKey);\n this.store.set(accountKey, accountMap);\n\n const session = accountMap.get(domain);\n if (!session) return null;\n\n if (Date.now() >= session.expiresAt) {\n accountMap.delete(domain);\n return null;\n }\n\n return session;\n }\n\n public set(\n accountKey: string,\n domain: ZaloAdsDomain,\n session: ZaloDomainSession,\n ttlSeconds?: number,\n ): void {\n let accountMap = this.store.get(accountKey);\n if (accountMap) {\n this.store.delete(accountKey);\n } else {\n if (this.store.size >= this.maxAccounts) {\n const oldestKey = this.store.keys().next().value;\n if (oldestKey !== undefined) {\n this.store.delete(oldestKey);\n }\n }\n accountMap = new Map<ZaloAdsDomain, ZaloDomainSession>();\n }\n\n const storedSession: ZaloDomainSession = ttlSeconds\n ? { ...session, expiresAt: Math.min(session.expiresAt, Date.now() + ttlSeconds * 1000) }\n : session;\n\n accountMap.set(domain, storedSession);\n this.store.set(accountKey, accountMap);\n }\n\n public delete(accountKey: string, domain?: ZaloAdsDomain): void {\n if (!domain) {\n this.store.delete(accountKey);\n return;\n }\n const accountMap = this.store.get(accountKey);\n if (accountMap) {\n accountMap.delete(domain);\n if (accountMap.size === 0) {\n this.store.delete(accountKey);\n }\n }\n }\n\n public getAll(accountKey: string): Partial<Record<ZaloAdsDomain, ZaloDomainSession>> {\n const accountMap = this.store.get(accountKey);\n if (!accountMap) return {};\n const now = Date.now();\n const result: Partial<Record<ZaloAdsDomain, ZaloDomainSession>> = {};\n for (const [domain, session] of accountMap.entries()) {\n if (now < session.expiresAt) {\n result[domain] = session;\n } else {\n accountMap.delete(domain);\n }\n }\n return result;\n }\n\n /** Xóa toàn bộ dữ liệu trong RAM */\n public clearAll(): void {\n this.store.clear();\n }\n\n /** Số lượng tài khoản đang được giữ trong RAM */\n public get size(): number {\n return this.store.size;\n }\n}\n\nexport interface RedisZaloSessionStoreOptions {\n /**\n * Tiền tố key trên Redis.\n * Mặc định: `'zalo_ads:sso'` -> key có dạng `zalo_ads:sso:session:{accountKey}:{domain}`\n */\n keyPrefix?: string;\n /**\n * Thời gian sống mặc định trên Redis (giây) nếu session không có expiresAt.\n * Mặc định: 2700 giây (45 phút).\n */\n defaultTtlSeconds?: number;\n}\n\n/**\n * Lưu trữ Session trên Redis (L2 Shared Cache) kèm Distributed Lock chống race-condition\n * khi nhiều worker/instance backend cùng refresh 1 tài khoản/integration.\n *\n * Tương thích trực tiếp với `RedisService` của `redai-v201-be-app-staging` hoặc `ioredis`.\n */\nexport class RedisZaloSessionStore implements ZaloSessionStore {\n private readonly keyPrefix: string;\n private readonly defaultTtlSeconds: number;\n\n public constructor(\n private readonly redis: ZaloRedisLikeClient,\n options: RedisZaloSessionStoreOptions = {},\n ) {\n this.keyPrefix = options.keyPrefix ?? 'zalo_ads:sso';\n this.defaultTtlSeconds = options.defaultTtlSeconds ?? 45 * 60;\n }\n\n private buildSessionKey(accountKey: string, domain: ZaloAdsDomain): string {\n return `${this.keyPrefix}:session:${accountKey}:${domain}`;\n }\n\n private buildLockKey(accountKey: string, domain: ZaloAdsDomain): string {\n return `${this.keyPrefix}:lock:${accountKey}:${domain}`;\n }\n\n public async get(accountKey: string, domain: ZaloAdsDomain): Promise<ZaloDomainSession | null> {\n const key = this.buildSessionKey(accountKey, domain);\n const raw = await this.redis.get(key);\n if (!raw) return null;\n\n try {\n const parsed = JSON.parse(raw) as ZaloDomainSession;\n if (!parsed || typeof parsed !== 'object' || Date.now() >= parsed.expiresAt) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n }\n\n public async set(\n accountKey: string,\n domain: ZaloAdsDomain,\n session: ZaloDomainSession,\n ttlSeconds?: number,\n ): Promise<void> {\n const key = this.buildSessionKey(accountKey, domain);\n const remainingSeconds = Math.floor((session.expiresAt - Date.now()) / 1000);\n const effectiveTtl = Math.max(1, ttlSeconds ?? (remainingSeconds > 0 ? remainingSeconds : this.defaultTtlSeconds));\n const serialized = JSON.stringify(session);\n\n if (typeof this.redis.setWithExpiry === 'function') {\n await this.redis.setWithExpiry(key, serialized, effectiveTtl);\n return;\n }\n if (typeof this.redis.setex === 'function') {\n await this.redis.setex(key, effectiveTtl, serialized);\n return;\n }\n if (typeof this.redis.set === 'function') {\n await this.redis.set(key, serialized, 'EX', effectiveTtl);\n }\n }\n\n public async delete(accountKey: string, domain?: ZaloAdsDomain): Promise<void> {\n if (domain) {\n await this.redis.del(this.buildSessionKey(accountKey, domain));\n return;\n }\n const keys = ALL_ZALO_ADS_DOMAINS.map(d => this.buildSessionKey(accountKey, d));\n await Promise.all(keys.map(k => this.redis.del(k)));\n }\n\n public async getAll(accountKey: string): Promise<Partial<Record<ZaloAdsDomain, ZaloDomainSession>>> {\n const entries = await Promise.all(\n ALL_ZALO_ADS_DOMAINS.map(async domain => {\n const session = await this.get(accountKey, domain);\n return [domain, session] as const;\n }),\n );\n const result: Partial<Record<ZaloAdsDomain, ZaloDomainSession>> = {};\n for (const [domain, session] of entries) {\n if (session) {\n result[domain] = session;\n }\n }\n return result;\n }\n\n public async acquireLock(\n accountKey: string,\n domain: ZaloAdsDomain,\n ttlSeconds = 15,\n ): Promise<boolean> {\n const lockKey = this.buildLockKey(accountKey, domain);\n const lockValue = `${Date.now()}`;\n if (typeof this.redis.setNX === 'function') {\n return Boolean(await this.redis.setNX(lockKey, lockValue, ttlSeconds));\n }\n if (typeof this.redis.set === 'function') {\n const res = await this.redis.set(lockKey, lockValue, 'EX', ttlSeconds, 'NX');\n return res === 'OK' || res === true;\n }\n return true;\n }\n\n public async releaseLock(accountKey: string, domain: ZaloAdsDomain): Promise<void> {\n const lockKey = this.buildLockKey(accountKey, domain);\n try {\n await this.redis.del(lockKey);\n } catch {\n // Ignore lock release errors\n }\n }\n}\n\nexport interface TieredZaloSessionStoreOptions extends MemoryZaloSessionStoreOptions, RedisZaloSessionStoreOptions {\n /**\n * Thời gian sống tối đa của L1 RAM cache (giây) trước khi đồng bộ lại với L2 Redis.\n * Mặc định: 300 giây (5 phút) để đảm bảo các worker luôn đồng bộ nếu 1 worker khác refresh session.\n */\n l1MaxTtlSeconds?: number;\n}\n\n/**\n * Lưu trữ 2 tầng (L1 RAM + L2 Redis):\n * - Đọc cực nhanh từ RAM (0ms) cho các request liên tiếp trong cùng process.\n * - Tự động đồng bộ xuống Redis để chia sẻ phiên giữa nhiều worker/pod và giữ phiên khi restart server.\n * - Hỗ trợ Distributed Lock qua Redis khi thực hiện OAuth Handshake.\n */\nexport class TieredZaloSessionStore implements ZaloSessionStore {\n public readonly l1Memory: MemoryZaloSessionStore;\n public readonly l2Redis: RedisZaloSessionStore;\n private readonly l1MaxTtlSeconds: number;\n\n public constructor(\n redis: ZaloRedisLikeClient,\n options: TieredZaloSessionStoreOptions = {},\n ) {\n this.l1Memory = new MemoryZaloSessionStore({ maxAccounts: options.maxAccounts });\n this.l2Redis = new RedisZaloSessionStore(redis, {\n keyPrefix: options.keyPrefix,\n defaultTtlSeconds: options.defaultTtlSeconds,\n });\n this.l1MaxTtlSeconds = options.l1MaxTtlSeconds ?? 300;\n }\n\n public async get(accountKey: string, domain: ZaloAdsDomain): Promise<ZaloDomainSession | null> {\n const fromL1 = this.l1Memory.get(accountKey, domain);\n if (fromL1) {\n return fromL1;\n }\n\n const fromL2 = await this.l2Redis.get(accountKey, domain);\n if (fromL2) {\n this.l1Memory.set(accountKey, domain, fromL2, this.l1MaxTtlSeconds);\n return fromL2;\n }\n\n return null;\n }\n\n public async set(\n accountKey: string,\n domain: ZaloAdsDomain,\n session: ZaloDomainSession,\n ttlSeconds?: number,\n ): Promise<void> {\n this.l1Memory.set(accountKey, domain, session, ttlSeconds ?? this.l1MaxTtlSeconds);\n await this.l2Redis.set(accountKey, domain, session, ttlSeconds);\n }\n\n public async delete(accountKey: string, domain?: ZaloAdsDomain): Promise<void> {\n this.l1Memory.delete(accountKey, domain);\n await this.l2Redis.delete(accountKey, domain);\n }\n\n public async getAll(accountKey: string): Promise<Partial<Record<ZaloAdsDomain, ZaloDomainSession>>> {\n const fromL2 = await this.l2Redis.getAll(accountKey);\n for (const [domain, session] of Object.entries(fromL2) as [ZaloAdsDomain, ZaloDomainSession][]) {\n if (session) {\n this.l1Memory.set(accountKey, domain, session, this.l1MaxTtlSeconds);\n }\n }\n return fromL2;\n }\n\n public acquireLock(accountKey: string, domain: ZaloAdsDomain, ttlSeconds = 15): Promise<boolean> {\n return this.l2Redis.acquireLock(accountKey, domain, ttlSeconds);\n }\n\n public releaseLock(accountKey: string, domain: ZaloAdsDomain): Promise<void> {\n return this.l2Redis.releaseLock(accountKey, domain);\n }\n}\n\n/**\n * Default global L1 Memory store dùng chung trong cùng Node.js process.\n * Giúp ngay cả khi khởi tạo `new ZaloAdsSdk({ zpsid })` nhiều lần ở các request khác nhau\n * vẫn tự động tái sử dụng được session trong RAM theo đúng tài khoản (`accountKey`).\n */\nexport const defaultSharedMemorySessionStore = new MemoryZaloSessionStore({\n maxAccounts: 1000,\n});\n","import {\n defaultSharedMemorySessionStore,\n TieredZaloSessionStore,\n type ZaloRedisLikeClient,\n type ZaloSessionStore,\n} from \"./store\";\nimport type { ZaloAccountScope, ZaloSdkAuth, ZaloSdkAuthContext } from \"./types\";\n\nexport type ZaloAuthDomain =\n | \"ads.zalo.me\"\n | \"page.ads.zalo.me\"\n | \"form.ads.zalo.me\"\n | \"profile.ads.zalo.me\"\n | \"api.widget.zalo.me\"\n | \"widget.chat.zalo.me\";\n\nexport type ZaloAdsDomain = ZaloAuthDomain;\n\nexport interface ZaloPlaySessionPayload {\n data?: {\n /** Ads Member ID (trên ads.zalo.me) */\n id?: string;\n /** Role trên ads.zalo.me (ví dụ: \"2\") */\n role?: string;\n /** Root account ID trên ads.zalo.me */\n root?: string;\n /** Instant Page User ID / Owner ID (trên page.ads.zalo.me) */\n nid?: string;\n /** Session ID */\n sid?: string;\n /** Zalo SSO Ticket */\n zpsid?: string;\n [key: string]: unknown;\n };\n nbf?: number;\n iat?: number;\n exp?: number;\n [key: string]: unknown;\n}\n\nexport interface ZaloAdsWhoamiProfile {\n id: number;\n name: string;\n avatar?: string;\n budget?: number;\n role?: string;\n phone?: string;\n sid?: string;\n [key: string]: unknown;\n}\n\nexport interface ZaloFormSessionProfile {\n uid: string;\n fullName: string;\n avatar?: string;\n token: string;\n isInVN?: boolean;\n oas?: Array<{\n oaId: string;\n noisedOaId: string;\n name: string;\n oaAvatar?: string;\n status: number;\n role: number;\n [key: string]: unknown;\n }>;\n [key: string]: unknown;\n}\n\nexport interface ZaloDomainSession {\n domain: ZaloAuthDomain;\n /** Định danh tài khoản hoặc Integration ID sở hữu phiên này */\n accountKey?: string;\n /** Fingerprint của zpsid đã tạo ra phiên này (dùng để tự động phát hiện khi người dùng đổi zpsid mới) */\n zpsidFingerprint?: string;\n cookies: Record<string, string>;\n xsrfToken?: string;\n bearerToken?: string;\n headers: Record<string, string>;\n playSessionPayload?: ZaloPlaySessionPayload;\n adsProfile?: ZaloAdsWhoamiProfile;\n formProfile?: ZaloFormSessionProfile;\n createdAt: number;\n expiresAt: number;\n}\n\nexport interface ZaloSsoAuthOptions {\n /**\n * Định danh tài khoản hoặc `integrationId` (dùng để phân tách cache RAM/Redis khi quản lý nhiều tài khoản).\n * Nếu không truyền, SDK tự động trích xuất từ `zpsid` (ví dụ: `zalo_330114198_...`).\n */\n accountKey?: string;\n /**\n * Phạm vi tài khoản quảng cáo cô lập (Isolated Workspace) - chứa accountId, memberId, agencyId, accountType.\n */\n accountScope?: ZaloAccountScope;\n /**\n * Alias của `accountKey` dành cho hệ thống Multi-Integration trên Backend.\n */\n integrationId?: string;\n /**\n * Giá trị cookie `zpsid` gốc của Zalo (domain `.zalo.me`) hoặc nguyên chuỗi Cookie trình duyệt có chứa `zpsid=...`.\n */\n zpsid?: string;\n /**\n * Callback động để lấy `zpsid` (hữu ích khi đọc từ DB/Redis/Vault theo `integrationId`).\n */\n getZpsid?: () => Promise<string> | string;\n /**\n * Các cookie bổ sung muốn gắn kèm (ví dụ: `zoaw_sek`, `zoaw_type` cho chat widget).\n */\n extraCookies?: Record<string, string>;\n /**\n * Thời gian sống (TTL) của phiên cache cho mỗi domain tính bằng mili-giây (mặc định: 45 phút).\n */\n sessionTtlMs?: number;\n /**\n * Tầng lưu trữ phiên (RAM / Redis / Tiered).\n * Nếu không truyền `sessionStore` và `redis`, mặc định dùng `defaultSharedMemorySessionStore` (RAM LRU).\n */\n sessionStore?: ZaloSessionStore;\n /**\n * Truyền trực tiếp `RedisService` (của NestJS backend) hoặc `ioredis` client để tự động bật cache 2 tầng (L1 RAM + L2 Redis + Distributed Lock).\n */\n redis?: ZaloRedisLikeClient;\n /**\n * Tiền tố key trên Redis khi truyền `redis` (mặc định: `'zalo_ads:sso'`).\n */\n redisKeyPrefix?: string;\n /**\n * Custom fetch implementation (mặc định: `globalThis.fetch`).\n */\n fetch?: typeof fetch;\n /**\n * Custom User-Agent header.\n */\n userAgent?: string;\n /**\n * Hook được gọi mỗi khi một domain hoàn tất handshake và sinh session mới.\n */\n onSessionRefreshed?: (domain: ZaloAuthDomain, session: ZaloDomainSession) => Promise<void> | void;\n /**\n * Khôi phục sẵn danh sách phiên đã cache trước đó.\n */\n initialSessions?: Partial<Record<ZaloAuthDomain, ZaloDomainSession>>;\n}\n\nconst DEFAULT_USER_AGENT =\n \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36\";\n\nconst DEFAULT_SESSION_TTL_MS = 45 * 60 * 1000; // 45 minutes\n\n/**\n * Tạo mã băm ngắn (FNV-1a 32-bit hex) để làm fingerprint cho `zpsid` mà không lưu lộ nguyên chuỗi `zpsid` trên key Redis.\n */\nexport function computeZpsidFingerprint(zpsid: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < zpsid.length; i++) {\n hash ^= zpsid.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n\n/**\n * Tự động trích xuất `accountKey` duy nhất từ `zpsid` (kết hợp Zalo User ID nằm ở phần tử thứ 2 của `zpsid` và mã băm).\n * Ví dụ: `g_kQ.330114198.434.Tme...` -> `zalo_330114198_7f4c9a12`\n */\nexport function deriveAccountKeyFromZpsid(zpsid: string): string {\n const parts = zpsid.trim().split(\".\");\n const uidCandidate = parts.length >= 2 && /^\\d+$/.test(parts[1]) ? parts[1] : \"user\";\n return `zalo_${uidCandidate}_${computeZpsidFingerprint(zpsid.trim())}`;\n}\n\n/**\n * Giải mã payload JWT của cookie `PLAY_SESSION` (không cần secret key) để đọc `id`, `nid`, `sid`, `iat`.\n */\nexport function decodePlaySessionJwt(playSessionCookie: string): ZaloPlaySessionPayload | undefined {\n try {\n const token = playSessionCookie.replace(/^PLAY_SESSION=/, \"\").trim();\n const parts = token.split(\".\");\n if (parts.length < 2) return undefined;\n const base64Url = parts[1];\n const base64 = base64Url.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\");\n const binaryStr = globalThis.atob(padded);\n const bytes = Uint8Array.from(binaryStr, (ch) => ch.charCodeAt(0));\n const jsonStr = new TextDecoder(\"utf-8\").decode(bytes);\n return JSON.parse(jsonStr) as ZaloPlaySessionPayload;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Trích xuất `zpsid` và các cookie phụ từ một chuỗi Cookie đầy đủ hoặc giá trị `zpsid` đơn lẻ.\n */\nexport function parseZaloCookieInput(rawInput: string): {\n zpsid: string;\n extractedCookies: Record<string, string>;\n} {\n const trimmed = rawInput.trim();\n const extractedCookies: Record<string, string> = {};\n\n if (!trimmed.includes(\"=\") && !trimmed.includes(\";\")) {\n return { zpsid: trimmed, extractedCookies };\n }\n\n for (const part of trimmed.split(\";\")) {\n const eqIdx = part.indexOf(\"=\");\n if (eqIdx > 0) {\n const k = part.slice(0, eqIdx).trim();\n const v = part.slice(eqIdx + 1).trim();\n if (k && v) extractedCookies[k] = v;\n }\n }\n\n const zpsid = extractedCookies[\"zpsid\"] ?? trimmed.replace(/^zpsid=/i, \"\").trim();\n return { zpsid, extractedCookies };\n}\n\n/**\n * Trình quản lý xác thực tập trung cho hệ sinh thái Zalo Ads (`ads.zalo.me`, `page.ads.zalo.me`,\n * `form.ads.zalo.me`, `profile.ads.zalo.me`, `api.widget.zalo.me`, `widget.chat.zalo.me`).\n *\n * Hỗ trợ lưu trữ phiên trên RAM (`MemoryZaloSessionStore`), Redis (`RedisZaloSessionStore`),\n * hoặc kết hợp 2 tầng L1 RAM + L2 Redis (`TieredZaloSessionStore`) cho mô hình Multi-Account / Multi-Integration.\n */\nexport class ZaloAuthManager {\n private explicitAccountKey?: string;\n private accountScope?: ZaloAccountScope;\n private zpsid?: string;\n private readonly getZpsidFn?: () => Promise<string> | string;\n private extraCookies: Record<string, string>;\n private readonly sessionTtlMs: number;\n private readonly sessionStore: ZaloSessionStore;\n private readonly fetchImpl: typeof fetch;\n private readonly userAgent: string;\n private readonly onSessionRefreshed?: (\n domain: ZaloAuthDomain,\n session: ZaloDomainSession\n ) => Promise<void> | void;\n\n private readonly sessions = new Map<ZaloAuthDomain, ZaloDomainSession>();\n private readonly inflightHandshakes = new Map<ZaloAuthDomain, Promise<ZaloDomainSession>>();\n\n public constructor(options: ZaloSsoAuthOptions | string) {\n const normalizedOptions: ZaloSsoAuthOptions =\n typeof options === \"string\" ? { zpsid: options } : options;\n\n this.fetchImpl = normalizedOptions.fetch ?? globalThis.fetch;\n if (!this.fetchImpl) {\n throw new Error(\"A Fetch implementation is required (Node.js 18+ provides global fetch).\");\n }\n\n this.explicitAccountKey = normalizedOptions.integrationId ?? normalizedOptions.accountKey;\n this.accountScope = normalizedOptions.accountScope;\n this.extraCookies = { ...(normalizedOptions.extraCookies ?? {}) };\n\n if (normalizedOptions.zpsid) {\n const parsed = parseZaloCookieInput(normalizedOptions.zpsid);\n this.zpsid = parsed.zpsid;\n for (const flagKey of [\"zoaw_sek\", \"zoaw_type\", \"__zi\", \"__zi-legacy\"]) {\n if (parsed.extractedCookies[flagKey] && !this.extraCookies[flagKey]) {\n this.extraCookies[flagKey] = parsed.extractedCookies[flagKey];\n }\n }\n }\n\n this.getZpsidFn = normalizedOptions.getZpsid;\n this.sessionTtlMs = normalizedOptions.sessionTtlMs ?? DEFAULT_SESSION_TTL_MS;\n this.userAgent = normalizedOptions.userAgent ?? DEFAULT_USER_AGENT;\n this.onSessionRefreshed = normalizedOptions.onSessionRefreshed;\n\n if (normalizedOptions.sessionStore) {\n this.sessionStore = normalizedOptions.sessionStore;\n } else if (normalizedOptions.redis) {\n this.sessionStore = new TieredZaloSessionStore(normalizedOptions.redis, {\n keyPrefix: normalizedOptions.redisKeyPrefix,\n });\n } else {\n this.sessionStore = defaultSharedMemorySessionStore;\n }\n\n if (normalizedOptions.initialSessions) {\n for (const [domain, session] of Object.entries(normalizedOptions.initialSessions)) {\n if (session) this.sessions.set(domain as ZaloAuthDomain, session);\n }\n }\n }\n\n /**\n * Trả về `accountKey` hiện tại (hoặc `integrationId` nếu được cấu hình).\n */\n public getAccountKey(): string {\n if (this.explicitAccountKey) {\n return this.explicitAccountKey;\n }\n if (this.zpsid) {\n return deriveAccountKeyFromZpsid(this.zpsid);\n }\n return \"zalo_default_account\";\n }\n\n /**\n * Trả về `sessionStore` đang sử dụng (RAM / Redis / Tiered).\n */\n public getSessionStore(): ZaloSessionStore {\n return this.sessionStore;\n }\n\n public getAccountScope(): ZaloAccountScope | undefined {\n return this.accountScope;\n }\n\n public setAccountScope(scope?: ZaloAccountScope): void {\n this.accountScope = scope;\n }\n\n /**\n * Cập nhật `zpsid` mới và xóa toàn bộ cache phiên cũ trên cả RAM lẫn Redis.\n */\n public setZpsid(zpsidInput: string): void {\n const parsed = parseZaloCookieInput(zpsidInput);\n const prevZpsid = this.zpsid;\n this.zpsid = parsed.zpsid;\n for (const flagKey of [\"zoaw_sek\", \"zoaw_type\", \"__zi\", \"__zi-legacy\"]) {\n if (parsed.extractedCookies[flagKey]) {\n this.extraCookies[flagKey] = parsed.extractedCookies[flagKey];\n }\n }\n if (prevZpsid !== this.zpsid) {\n this.clearSessions();\n }\n }\n\n /**\n * Xóa phiên đã cache của một domain cụ thể (trên cả local RAM và `sessionStore` Redis/Memory).\n */\n public invalidateDomain(hostOrDomain: string): void {\n const domain = this.normalizeDomain(hostOrDomain);\n this.sessions.delete(domain);\n const accountKey = this.getAccountKey();\n void Promise.resolve(this.sessionStore.delete(accountKey, domain)).catch(() => undefined);\n }\n\n /**\n * Xóa phiên bất đồng bộ (đảm bảo đã xóa xong trên Redis trước khi thực hiện bước tiếp theo).\n */\n public async invalidateDomainAsync(hostOrDomain: string): Promise<void> {\n const domain = this.normalizeDomain(hostOrDomain);\n this.sessions.delete(domain);\n const accountKey = this.getAccountKey();\n await this.sessionStore.delete(accountKey, domain);\n }\n\n /**\n * Xóa toàn bộ phiên đã cache của mọi domain thuộc tài khoản này.\n */\n public clearSessions(): void {\n this.sessions.clear();\n const accountKey = this.getAccountKey();\n void Promise.resolve(this.sessionStore.delete(accountKey)).catch(() => undefined);\n }\n\n /**\n * Xóa toàn bộ phiên đã cache của mọi domain thuộc tài khoản này (bất đồng bộ, chờ Redis xóa xong).\n */\n public async clearSessionsAsync(): Promise<void> {\n this.sessions.clear();\n const accountKey = this.getAccountKey();\n await this.sessionStore.delete(accountKey);\n }\n\n /**\n * Xuất toàn bộ phiên đang cache để lưu trữ ngoài.\n */\n public exportSessions(): Partial<Record<ZaloAuthDomain, ZaloDomainSession>> {\n const output: Partial<Record<ZaloAuthDomain, ZaloDomainSession>> = {};\n for (const [domain, session] of this.sessions.entries()) {\n output[domain] = session;\n }\n return output;\n }\n\n /**\n * Nạp lại các phiên đã lưu trữ từ bên ngoài.\n */\n public importSessions(snapshot: Partial<Record<ZaloAuthDomain, ZaloDomainSession>>): void {\n const accountKey = this.getAccountKey();\n for (const [domain, session] of Object.entries(snapshot)) {\n if (session) {\n this.sessions.set(domain as ZaloAuthDomain, session);\n void Promise.resolve(\n this.sessionStore.set(accountKey, domain as ZaloAuthDomain, session)\n ).catch(() => undefined);\n }\n }\n }\n\n /**\n * Lấy phiên hợp lệ của một domain (kiểm tra L1 Instance Map -> L1/L2 SessionStore -> tự động chạy OAuth2 PKCE Handshake nếu chưa có hoặc đã hết hạn).\n */\n public async getSession(hostOrDomain: string, forceRefresh = false): Promise<ZaloDomainSession> {\n const domain = this.normalizeDomain(hostOrDomain);\n const zpsid = await this.resolveZpsid();\n const currentFingerprint = computeZpsidFingerprint(zpsid);\n const accountKey = this.getAccountKey();\n\n if (!forceRefresh) {\n const localSession = this.sessions.get(domain);\n if (localSession && this.isSessionValid(localSession, currentFingerprint)) {\n return localSession;\n }\n\n const storedSession = await this.sessionStore.get(accountKey, domain);\n if (storedSession && this.isSessionValid(storedSession, currentFingerprint)) {\n this.sessions.set(domain, storedSession);\n return storedSession;\n }\n }\n\n return this.authenticateDomain(domain, forceRefresh);\n }\n\n /**\n * Thực hiện đồng thời OAuth2 PKCE Handshake cho nhiều domain (mặc định: `ads.zalo.me`, `page.ads.zalo.me`, `form.ads.zalo.me`).\n */\n public async authenticateAll(\n domains: ZaloAuthDomain[] = [\"ads.zalo.me\", \"page.ads.zalo.me\", \"form.ads.zalo.me\"],\n forceRefresh = true\n ): Promise<Record<string, ZaloDomainSession>> {\n const entries = await Promise.all(\n domains.map(async (d) => [d, await this.authenticateDomain(d, forceRefresh)] as const)\n );\n return Object.fromEntries(entries);\n }\n\n /**\n * Thực hiện OAuth2 PKCE Handshake bằng `zpsid` cho một domain cụ thể.\n * Có chống trùng lặp trong cùng process (in-flight deduplication) VÀ giữa nhiều process/pod qua Redis Distributed Lock.\n */\n public async authenticateDomain(\n hostOrDomain: string,\n forceRefresh = false\n ): Promise<ZaloDomainSession> {\n const domain = this.normalizeDomain(hostOrDomain);\n const zpsid = await this.resolveZpsid();\n const currentFingerprint = computeZpsidFingerprint(zpsid);\n const accountKey = this.getAccountKey();\n\n if (!forceRefresh) {\n const existing = this.sessions.get(domain);\n if (existing && this.isSessionValid(existing, currentFingerprint)) {\n return existing;\n }\n const fromStore = await this.sessionStore.get(accountKey, domain);\n if (fromStore && this.isSessionValid(fromStore, currentFingerprint)) {\n this.sessions.set(domain, fromStore);\n return fromStore;\n }\n }\n\n const inflight = this.inflightHandshakes.get(domain);\n if (inflight) return inflight;\n\n const promise = this.performHandshakeWithDistributedLock(\n accountKey,\n domain,\n zpsid,\n currentFingerprint,\n forceRefresh\n ).finally(() => {\n this.inflightHandshakes.delete(domain);\n });\n\n this.inflightHandshakes.set(domain, promise);\n return promise;\n }\n\n /**\n * Lấy bộ HTTP Headers chuẩn (`Cookie`, `x-xsrf-token`, `Authorization`, ...) cho bất kỳ URL hoặc domain Zalo Ads nào.\n */\n public async getAuthHeaders(\n urlOrDomain: string,\n forceRefresh = false\n ): Promise<Record<string, string>> {\n const domain = this.extractDomainFromUrlOrHost(urlOrDomain);\n const session = await this.getSession(domain, forceRefresh);\n return {\n ...session.headers,\n Cookie: this.formatCookieHeader(session.cookies),\n };\n }\n\n /**\n * Lấy bản đồ Cookie (`Record<string, string>`) đã xác thực của domain.\n */\n public async getCookies(\n urlOrDomain: string,\n forceRefresh = false\n ): Promise<Record<string, string>> {\n const domain = this.extractDomainFromUrlOrHost(urlOrDomain);\n const session = await this.getSession(domain, forceRefresh);\n return { ...session.cookies };\n }\n\n /**\n * Chuyển đổi `ZaloAuthManager` thành đối tượng `ZaloSdkAuth` để gắn trực tiếp vào `ZaloSdkHttpClient`.\n */\n public toSdkAuth(): ZaloSdkAuth {\n return {\n getHeaders: async (context: ZaloSdkAuthContext) => {\n const session = await this.getSession(context.host, false);\n return { ...session.headers };\n },\n getCookies: async (context: ZaloSdkAuthContext) => {\n const session = await this.getSession(context.host, false);\n return { ...session.cookies };\n },\n };\n }\n\n /**\n * Hàm `fetch` độc lập có bọc sẵn xác thực tự động và tự retry 1 lần nếu gặp HTTP 401 hoặc `{ code: 401 }`.\n */\n public async request(url: string, init: RequestInit = {}): Promise<Response> {\n const domain = this.extractDomainFromUrlOrHost(url);\n const executeFetch = async (forceRefresh: boolean): Promise<Response> => {\n const authHeaders = await this.getAuthHeaders(domain, forceRefresh);\n const mergedHeaders = new Headers(authHeaders);\n if (init.headers) {\n const customHeaders = new Headers(init.headers);\n customHeaders.forEach((value, key) => mergedHeaders.set(key, value));\n }\n return this.fetchImpl(url, {\n ...init,\n headers: mergedHeaders,\n });\n };\n\n const response = await executeFetch(false);\n if (response.status === 401) {\n await this.invalidateDomainAsync(domain);\n return executeFetch(true);\n }\n\n // Riêng form.ads.zalo.me trả HTTP 200 kèm JSON {\"msg\":\"Unauthorized\",\"code\":401}\n if (domain === \"form.ads.zalo.me\") {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"json\")) {\n const cloned = response.clone();\n const body = (await cloned.json().catch(() => null)) as { code?: number } | null;\n if (body && body.code === 401) {\n await this.invalidateDomainAsync(domain);\n return executeFetch(true);\n }\n }\n }\n\n return response;\n }\n\n private isSessionValid(session: ZaloDomainSession, currentFingerprint: string): boolean {\n if (Date.now() >= session.expiresAt) {\n return false;\n }\n if (session.zpsidFingerprint && session.zpsidFingerprint !== currentFingerprint) {\n return false;\n }\n // Nếu session thuộc ads.zalo.me và có chỉ định accountScope.memberId (sub-account),\n // bắt buộc JWT trong PLAY_SESSION phải khớp với memberId của sub-account đó.\n if (\n session.domain === \"ads.zalo.me\" &&\n this.accountScope?.memberId &&\n String(this.accountScope.memberId) !== \"0\" &&\n !this.accountScope.isRoot\n ) {\n const expectedMemberId = String(this.accountScope.memberId);\n const activeMemberId = String(session.playSessionPayload?.data?.id ?? \"\");\n if (activeMemberId && activeMemberId !== expectedMemberId) {\n return false;\n }\n }\n return true;\n }\n\n private async resolveZpsid(): Promise<string> {\n if (this.getZpsidFn) {\n const dynamicVal = await this.getZpsidFn();\n if (dynamicVal) {\n const parsed = parseZaloCookieInput(dynamicVal);\n this.zpsid = parsed.zpsid;\n for (const flagKey of [\"zoaw_sek\", \"zoaw_type\", \"__zi\", \"__zi-legacy\"]) {\n if (parsed.extractedCookies[flagKey] && !this.extraCookies[flagKey]) {\n this.extraCookies[flagKey] = parsed.extractedCookies[flagKey];\n }\n }\n }\n }\n if (!this.zpsid) {\n throw new Error(\n \"ZaloAuthManager: Missing `zpsid` cookie. Provide `zpsid` or `getZpsid` in ZaloAdsSdk / ZaloAuthManager options.\"\n );\n }\n return this.zpsid;\n }\n\n private async performHandshakeWithDistributedLock(\n accountKey: string,\n domain: ZaloAuthDomain,\n zpsid: string,\n currentFingerprint: string,\n forceRefresh: boolean\n ): Promise<ZaloDomainSession> {\n if (this.sessionStore.acquireLock && this.sessionStore.releaseLock) {\n const lockAcquired = await this.sessionStore\n .acquireLock(accountKey, domain, 15)\n .catch(() => true);\n\n if (!lockAcquired && !forceRefresh) {\n // Tiến trình/pod khác đang thực hiện handshake cho cùng integrationId + domain -> chờ lấy kết quả từ Redis\n for (let attempt = 0; attempt < 6; attempt++) {\n await new Promise((resolve) => setTimeout(resolve, 350));\n const sharedSession = await this.sessionStore.get(accountKey, domain);\n if (sharedSession && this.isSessionValid(sharedSession, currentFingerprint)) {\n this.sessions.set(domain, sharedSession);\n return sharedSession;\n }\n }\n }\n\n try {\n return await this.performHandshake(accountKey, domain, zpsid, currentFingerprint);\n } finally {\n if (lockAcquired) {\n await this.sessionStore.releaseLock(accountKey, domain).catch(() => undefined);\n }\n }\n }\n\n return this.performHandshake(accountKey, domain, zpsid, currentFingerprint);\n }\n\n private async performHandshake(\n accountKey: string,\n domain: ZaloAuthDomain,\n zpsid: string,\n zpsidFingerprint: string\n ): Promise<ZaloDomainSession> {\n const cookies: Record<string, string> = {\n ...this.extraCookies,\n zpsid,\n };\n\n const headers: Record<string, string> = {\n \"User-Agent\": this.userAgent,\n };\n\n let adsProfile: ZaloAdsWhoamiProfile | undefined;\n let formProfile: ZaloFormSessionProfile | undefined;\n\n if (domain === \"ads.zalo.me\") {\n const explicitPlaySession = this.extraCookies?.PLAY_SESSION || cookies[\"PLAY_SESSION\"];\n // Chỉ thực hiện followOAuthRedirects api/login nếu CHƯA có PLAY_SESSION ủy quyền\n if (!explicitPlaySession) {\n await this.followOAuthRedirects(\"https://ads.zalo.me/api/login\", cookies, true);\n }\n // Gọi /api/whoami để lấy XSRF-TOKEN và thông tin tài khoản quảng cáo\n const whoamiRes = await this.fetchImpl(\"https://ads.zalo.me/api/whoami\", {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"application/json\",\n },\n });\n this.mergeSetCookies(whoamiRes, cookies);\n // Bảo toàn PLAY_SESSION ủy quyền đã truyền vào nếu có\n if (explicitPlaySession) {\n cookies[\"PLAY_SESSION\"] = explicitPlaySession;\n }\n const whoamiJson = (await whoamiRes.json().catch(() => null)) as {\n code?: number;\n data?: ZaloAdsWhoamiProfile;\n } | null;\n if (whoamiJson?.data) {\n adsProfile = whoamiJson.data;\n }\n\n // Tự động chuyển đổi ngữ cảnh tài khoản theo accountScope nếu là tài khoản con hoặc tài khoản ủy quyền\n const currentActiveId = String(\n decodePlaySessionJwt(cookies[\"PLAY_SESSION\"] || \"\")?.data?.id ?? \"\"\n );\n const shouldSwitchContext = Boolean(\n this.accountScope?.memberId &&\n String(this.accountScope.memberId) !== \"0\" &&\n !this.accountScope.isRoot &&\n (!explicitPlaySession || (currentActiveId && currentActiveId !== String(this.accountScope.memberId)))\n );\n\n if (shouldSwitchContext) {\n const memberIdStr = String(this.accountScope!.memberId);\n const switchUrls: string[] = [];\n if (this.accountScope!.accountType === \"ACCESSOR\") {\n switchUrls.push(`https://ads.zalo.me/api/ba/personal/login?memberId=${memberIdStr}`);\n } else if (\n this.accountScope!.accountType === \"AGENCY_MASTER\" ||\n this.accountScope!.accountType === \"AGENCY\" ||\n this.accountScope!.accountType === \"AGENCY_SUB_ACCOUNT\"\n ) {\n switchUrls.push(`https://ads.zalo.me/api/ba/agency/login?memberId=${memberIdStr}`);\n switchUrls.push(`https://ads.zalo.me/api/ba/personal/login?memberId=${memberIdStr}`);\n } else {\n switchUrls.push(`https://ads.zalo.me/api/ba/agency/login?memberId=${memberIdStr}`);\n switchUrls.push(`https://ads.zalo.me/api/ba/personal/login?memberId=${memberIdStr}`);\n }\n\n for (const switchUrl of switchUrls) {\n try {\n const switchRes = await this.fetchImpl(switchUrl, {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"application/json, text/plain, */*\",\n },\n redirect: \"manual\",\n });\n this.mergeSetCookies(switchRes, cookies);\n const location = switchRes.headers.get(\"location\") || \"\";\n if (location && !location.includes(\"/client/denied\")) {\n const switchedWhoamiRes = await this.fetchImpl(\"https://ads.zalo.me/api/whoami\", {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"application/json\",\n },\n });\n this.mergeSetCookies(switchedWhoamiRes, cookies);\n const switchedJson = (await switchedWhoamiRes.json().catch(() => null)) as {\n code?: number;\n data?: ZaloAdsWhoamiProfile;\n } | null;\n if (switchedJson?.data) {\n adsProfile = switchedJson.data;\n }\n break;\n }\n } catch {\n // Tiếp tục thử URL kế tiếp nếu có\n }\n }\n }\n\n if (this.accountScope?.memberId && String(this.accountScope.memberId) !== \"0\") {\n cookies[\"ads_user_id\"] = String(this.accountScope.memberId);\n } else if (this.extraCookies?.ads_user_id) {\n cookies[\"ads_user_id\"] = String(this.extraCookies.ads_user_id);\n } else if (adsProfile?.id) {\n cookies[\"ads_user_id\"] = String(adsProfile.id);\n }\n } else if (domain === \"page.ads.zalo.me\") {\n await this.followOAuthRedirects(\"https://page.ads.zalo.me/api/login\", cookies, false);\n } else if (domain === \"form.ads.zalo.me\") {\n const loginUrl =\n \"https://form.ads.zalo.me/client/manage/api/auth/login?state=\" +\n encodeURIComponent(\"https://form.ads.zalo.me/client/manage\");\n await this.followOAuthRedirects(loginUrl, cookies, false);\n\n const sessionRes = await this.fetchImpl(\n \"https://form.ads.zalo.me/client/manage/api/auth/session\",\n {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"application/json\",\n },\n }\n );\n this.mergeSetCookies(sessionRes, cookies);\n const sessionJson = (await sessionRes.json().catch(() => null)) as {\n code?: number;\n data?: ZaloFormSessionProfile;\n } | null;\n if (sessionJson?.data) {\n formProfile = sessionJson.data;\n }\n } else if (domain === \"profile.ads.zalo.me\") {\n const profileRes = await this.followOAuthRedirects(\"https://profile.ads.zalo.me/\", cookies, false);\n if (profileRes) {\n const html = await profileRes.text().catch(() => \"\");\n const csrfMatch = html.match(/CSRF_TOKEN\\s*=\\s*['\"]([^'\"]+)['\"]/);\n if (csrfMatch?.[1]) {\n cookies[\"CSRF_TOKEN\"] = csrfMatch[1];\n }\n }\n headers[\"Origin\"] = \"https://profile.ads.zalo.me\";\n headers[\"Referer\"] = \"https://profile.ads.zalo.me/\";\n } else if (domain === \"api.widget.zalo.me\" || domain === \"widget.chat.zalo.me\") {\n headers[\"Origin\"] = \"https://ads.zalo.me\";\n headers[\"Referer\"] = \"https://ads.zalo.me/\";\n }\n\n const xsrfToken = cookies[\"XSRF-TOKEN\"] ?? cookies[\"CSRF_TOKEN\"];\n if (cookies[\"XSRF-TOKEN\"]) {\n headers[\"x-xsrf-token\"] = cookies[\"XSRF-TOKEN\"];\n }\n\n const bearerToken = formProfile?.token;\n if (bearerToken) {\n headers[\"Authorization\"] = bearerToken;\n }\n\n const playSessionPayload = cookies[\"PLAY_SESSION\"]\n ? decodePlaySessionJwt(cookies[\"PLAY_SESSION\"])\n : undefined;\n\n const now = Date.now();\n const jwtExpMs = playSessionPayload?.exp ? playSessionPayload.exp * 1000 - 60_000 : undefined;\n const expiresAt =\n jwtExpMs && jwtExpMs > now ? Math.min(jwtExpMs, now + this.sessionTtlMs) : now + this.sessionTtlMs;\n\n const session: ZaloDomainSession = {\n domain,\n accountKey,\n zpsidFingerprint,\n cookies,\n xsrfToken,\n bearerToken,\n headers,\n playSessionPayload,\n adsProfile,\n formProfile,\n createdAt: now,\n expiresAt,\n };\n\n this.sessions.set(domain, session);\n await this.sessionStore.set(accountKey, domain, session);\n\n if (this.onSessionRefreshed) {\n await this.onSessionRefreshed(domain, session);\n }\n return session;\n }\n\n private async followOAuthRedirects(\n startUrl: string,\n cookies: Record<string, string>,\n stripSelectAccount: boolean\n ): Promise<Response | undefined> {\n let currentUrl = startUrl;\n let lastResponse: Response | undefined;\n for (let step = 1; step <= 7; step++) {\n const res = await this.fetchImpl(currentUrl, {\n method: \"GET\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n Accept: \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\",\n },\n redirect: \"manual\",\n });\n lastResponse = res;\n\n this.mergeSetCookies(res, cookies);\n\n let location = res.headers.get(\"location\");\n\n // Nếu tài khoản Zalo mới lần đầu truy cập domain con (ví dụ page.ads.zalo.me) chưa bấm \"Cho phép\",\n // oauth.zaloapp.com/v4/permission sẽ trả về 200 OK chứa <form id=\"zid_consent_form\">.\n // Tự động submit form \"Cho phép\" để lấy 302 Redirect kèm authorization code!\n if (\n !location &&\n res.status === 200 &&\n currentUrl.includes(\"oauth.zaloapp.com/v4/permission\")\n ) {\n const html = await res.text().catch(() => \"\");\n const csrfMatch = html.match(/name=\"csrf_token\"[^>]*value=\"([^\"]+)\"/);\n if (csrfMatch && html.includes(\"zid_consent_form\")) {\n const stateMatch = html.match(/name=\"state\"[^>]*value=\"([^\"]+)\"/);\n const parsedOAuthUrl = new URL(currentUrl);\n const consentForm = new URLSearchParams({\n csrf_token: csrfMatch[1],\n app_id: parsedOAuthUrl.searchParams.get(\"app_id\") ?? \"\",\n redirect_uri: parsedOAuthUrl.searchParams.get(\"redirect_uri\") ?? \"\",\n bndl_id: \"\",\n pkg_name: \"\",\n sign_key: \"\",\n wp_guid: \"\",\n mac: \"\",\n ref: \"\",\n token_login_post: \"\",\n state: stateMatch ? stateMatch[1] : parsedOAuthUrl.searchParams.get(\"state\") ?? \"\",\n ext_info: \"\",\n enable_qgpf: \"\",\n });\n\n const consentRes = await this.fetchImpl(currentUrl, {\n method: \"POST\",\n headers: {\n Cookie: this.formatCookieHeader(cookies),\n \"User-Agent\": this.userAgent,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n Origin: \"https://oauth.zaloapp.com\",\n Referer: currentUrl,\n },\n body: consentForm.toString(),\n redirect: \"manual\",\n });\n lastResponse = consentRes;\n\n this.mergeSetCookies(consentRes, cookies);\n location = consentRes.headers.get(\"location\");\n if (!location || consentRes.status < 300 || consentRes.status >= 400) {\n break;\n }\n } else {\n break;\n }\n } else if (!location || res.status < 300 || res.status >= 400) {\n break;\n }\n\n if (\n stripSelectAccount &&\n location.includes(\"oauth.zaloapp.com\") &&\n location.includes(\"select_account=true\")\n ) {\n location = location\n .replace(\"&select_account=true\", \"\")\n .replace(\"select_account=true&\", \"\")\n .replace(\"?select_account=true\", \"?\");\n }\n\n if (location.startsWith(\"http://profile.ads.zalo.me\")) {\n location = location.replace(/^http:\\/\\//, \"https://\");\n }\n\n currentUrl = location.startsWith(\"http\")\n ? location\n : new URL(location, currentUrl).toString();\n }\n return lastResponse;\n }\n\n private mergeSetCookies(res: Response, target: Record<string, string>): void {\n const headersWithSetCookie = res.headers as Headers & {\n getSetCookie?: () => string[];\n };\n const setCookieList: string[] =\n typeof headersWithSetCookie.getSetCookie === \"function\"\n ? headersWithSetCookie.getSetCookie()\n : res.headers.get(\"set-cookie\")\n ? [res.headers.get(\"set-cookie\") as string]\n : [];\n\n for (const raw of setCookieList) {\n const [firstPart] = raw.split(\";\");\n const eqIdx = firstPart.indexOf(\"=\");\n if (eqIdx > 0) {\n const key = firstPart.slice(0, eqIdx).trim();\n const val = firstPart.slice(eqIdx + 1).trim();\n // Bỏ qua các lệnh xóa cookie rỗng (ví dụ PLAY_SESSION=; Max-Age=0)\n if (val) {\n target[key] = val;\n }\n }\n }\n }\n\n private formatCookieHeader(cookies: Record<string, string>): string {\n return Object.entries(cookies)\n .filter(([, v]) => v !== undefined && v !== \"\")\n .map(([k, v]) => `${k}=${v}`)\n .join(\"; \");\n }\n\n private extractDomainFromUrlOrHost(urlOrDomain: string): ZaloAuthDomain {\n if (urlOrDomain.startsWith(\"http://\") || urlOrDomain.startsWith(\"https://\")) {\n return this.normalizeDomain(new URL(urlOrDomain).hostname);\n }\n return this.normalizeDomain(urlOrDomain);\n }\n\n private normalizeDomain(host: string): ZaloAuthDomain {\n const clean = host.toLowerCase().trim().replace(/:\\d+$/, \"\");\n switch (clean) {\n case \"ads.zalo.me\":\n case \"page.ads.zalo.me\":\n case \"form.ads.zalo.me\":\n case \"profile.ads.zalo.me\":\n case \"api.widget.zalo.me\":\n case \"widget.chat.zalo.me\":\n return clean;\n default:\n return \"ads.zalo.me\";\n }\n }\n}\n\n/**\n * Helper khởi tạo nhanh đối tượng `ZaloSdkAuth` từ `zpsid` hoặc `ZaloSsoAuthOptions`.\n */\nexport function createZaloSsoAuth(options: ZaloSsoAuthOptions | string): ZaloSdkAuth {\n const manager = new ZaloAuthManager(options);\n return manager.toSdkAuth();\n}\n","import { ZaloAuthManager, type ZaloSsoAuthOptions } from \"./auth\";\nimport type { FileInput, HttpMethod, RequestOptions, ZaloAccountScope, ZaloAdsSdkOptions, ZaloSdkAuth, ZaloSdkAuthContext } from \"./types\";\nimport { ZaloSdkError } from \"./types\";\n\nexport type BodyType = \"json\" | \"urlencoded\" | \"multipart\" | \"none\";\n\nexport interface OperationDefinition {\n operationId: string;\n method: HttpMethod;\n endpoint: string;\n baseUrl: string;\n binaryFields: string[];\n pathFields: string[];\n queryFields: string[];\n headerFields: string[];\n cookieFields: string[];\n bodyFields: string[];\n}\n\nconst DEFAULT_BASE_URLS = {\n ads: \"https://ads.zalo.me\",\n forms: \"https://form.ads.zalo.me\",\n instantPages: \"https://page.ads.zalo.me\",\n profileAds: \"https://profile.ads.zalo.me\",\n widget: \"https://api.widget.zalo.me\",\n chatWidget: \"https://widget.chat.zalo.me\"\n} as const;\n\nexport class ZaloSdkHttpClient {\n private readonly fetchImpl: typeof fetch;\n private readonly baseUrls: Record<string, string>;\n private defaultAuth?: ZaloSdkAuth;\n private readonly authByHost = new Map<string, ZaloSdkAuth>();\n private authManagerInstance?: ZaloAuthManager;\n private readonly autoRetryOn401: boolean;\n public accountScope?: ZaloAccountScope;\n\n constructor(options: ZaloAdsSdkOptions = {}) {\n this.fetchImpl = options.fetch ?? globalThis.fetch;\n if (!this.fetchImpl) throw new Error(\"A Fetch implementation is required (Node.js 18+ provides global fetch).\");\n this.baseUrls = { ...DEFAULT_BASE_URLS, ...(options.baseUrls ?? {}) };\n this.autoRetryOn401 = options.autoRetryOn401 ?? true;\n this.accountScope = options.accountScope;\n\n if (options.authManager) {\n this.authManagerInstance = options.authManager;\n if (options.accountScope && !this.authManagerInstance.getAccountScope()) {\n this.authManagerInstance.setAccountScope(options.accountScope);\n }\n } else if (options.zpsid || options.ssoAuth) {\n const extraCookies: Record<string, string> = {\n ...(options.ssoAuth?.extraCookies ?? {}),\n ...(options.zoawSek ? { zoaw_sek: options.zoawSek } : {}),\n };\n if (options.accountScope?.memberId && String(options.accountScope.memberId) !== \"0\") {\n extraCookies[\"ads_user_id\"] = String(options.accountScope.memberId);\n }\n this.authManagerInstance = new ZaloAuthManager({\n fetch: this.fetchImpl,\n integrationId: options.integrationId,\n accountKey: options.accountKey,\n accountScope: options.accountScope ?? options.ssoAuth?.accountScope,\n sessionStore: options.sessionStore,\n redis: options.redis,\n redisKeyPrefix: options.redisKeyPrefix,\n ...(options.ssoAuth ?? {}),\n extraCookies,\n ...(options.zpsid ? { zpsid: options.zpsid } : {}),\n });\n }\n\n this.defaultAuth = options.auth ?? this.authManagerInstance?.toSdkAuth();\n for (const [host, auth] of Object.entries(options.authByHost ?? {})) this.authByHost.set(host, auth);\n }\n\n public get authManager(): ZaloAuthManager | undefined {\n return this.authManagerInstance;\n }\n\n public setAuthManager(manager?: ZaloAuthManager): void {\n this.authManagerInstance = manager;\n this.defaultAuth = manager?.toSdkAuth();\n }\n\n public setZpsid(zpsidInput: string, ssoOptions?: Omit<ZaloSsoAuthOptions, \"zpsid\">): ZaloAuthManager {\n if (this.authManagerInstance && !ssoOptions) {\n this.authManagerInstance.setZpsid(zpsidInput);\n } else {\n this.authManagerInstance = new ZaloAuthManager({\n fetch: this.fetchImpl,\n ...(ssoOptions ?? {}),\n zpsid: zpsidInput\n });\n this.defaultAuth = this.authManagerInstance.toSdkAuth();\n }\n return this.authManagerInstance;\n }\n\n public setAuth(auth?: ZaloSdkAuth): void { this.defaultAuth = auth; }\n public setAuthForHost(host: string, auth?: ZaloSdkAuth): void {\n if (auth) this.authByHost.set(host, auth); else this.authByHost.delete(host);\n }\n public resolveBaseUrl(baseUrl: string): string {\n const found = Object.values(this.baseUrls).find((value) => value === baseUrl);\n return found ?? baseUrl;\n }\n\n public requestJson<TResponse>(operation: OperationDefinition, input: Record<string, unknown> = {}, options: RequestOptions = {}): Promise<TResponse> {\n return this.execute<TResponse>(operation, input, \"json\", options);\n }\n\n public requestFormUrlEncoded<TResponse>(operation: OperationDefinition, input: Record<string, unknown> = {}, options: RequestOptions = {}): Promise<TResponse> {\n return this.execute<TResponse>(operation, input, \"urlencoded\", options);\n }\n\n public requestMultipart<TResponse>(operation: OperationDefinition, input: Record<string, unknown> = {}, options: RequestOptions = {}): Promise<TResponse> {\n return this.execute<TResponse>(operation, input, \"multipart\", options);\n }\n\n public requestWithoutBody<TResponse>(operation: OperationDefinition, input: Record<string, unknown> = {}, options: RequestOptions = {}): Promise<TResponse> {\n return this.execute<TResponse>(operation, input, \"none\", options);\n }\n\n private async execute<TResponse>(\n operation: OperationDefinition,\n input: Record<string, unknown>,\n bodyType: BodyType,\n options: RequestOptions,\n isRetry = false\n ): Promise<TResponse> {\n const path = { ...asRecord(input.path_param) };\n const endpoint = operation.endpoint.replace(/\\{([^}]+)\\}/g, (_match, key: string) => encodeURIComponent(String(path[key])));\n const url = new URL(endpoint, operation.baseUrl);\n for (const [key, value] of Object.entries(asRecord(input.query_param))) appendQuery(url.searchParams, key, value);\n const context: ZaloSdkAuthContext = { url: url.toString(), host: url.host, operationId: operation.operationId, method: operation.method };\n const auth = this.authByHost.get(url.host) ?? this.defaultAuth;\n const headers = new Headers(await resolveHeaders(auth, context));\n for (const [key, value] of Object.entries(options.headers ?? {})) headers.set(key, value);\n const cookies = await resolveCookies(auth, context);\n if (Object.keys(cookies).length && !headers.has(\"cookie\")) {\n headers.set(\"cookie\", Object.entries(cookies).filter(([, v]) => v !== undefined && v !== \"\").map(([k, v]) => `${k}=${v}`).join(\"; \"));\n }\n\n const init: RequestInit = { method: operation.method, headers, signal: options.signal };\n const body = asRecord(input.body);\n if (bodyType === \"json\") {\n headers.set(\"content-type\", headers.get(\"content-type\") ?? \"application/json\");\n const jsonPayload = input.body !== undefined ? input.body : body;\n init.body = JSON.stringify(jsonPayload);\n } else if (bodyType === \"urlencoded\") {\n headers.set(\"content-type\", headers.get(\"content-type\") ?? \"application/x-www-form-urlencoded;charset=UTF-8\");\n const encoded = new URLSearchParams();\n for (const [key, value] of Object.entries(body)) {\n if (value === undefined) continue;\n encoded.set(key, typeof value === \"string\" ? value : JSON.stringify(value));\n }\n init.body = encoded;\n } else if (bodyType === \"multipart\") {\n const form = new FormData();\n for (const [key, value] of Object.entries(body)) {\n if (value === undefined) continue;\n if (operation.binaryFields.includes(key)) form.append(key, await this.resolveFile(value as FileInput), fileNameFrom(value));\n else form.append(key, typeof value === \"string\" ? value : JSON.stringify(value));\n }\n headers.delete(\"content-type\");\n init.body = form;\n }\n\n const response = await this.fetchImpl(url, init);\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n const responseBody: unknown = contentType.includes(\"json\") ? await response.json().catch(() => undefined) : await response.blob();\n\n const isFormUnauthorized =\n url.host === \"form.ads.zalo.me\" &&\n responseBody !== null &&\n typeof responseBody === \"object\" &&\n (responseBody as { code?: unknown }).code === 401;\n\n if ((response.status === 401 || isFormUnauthorized) && !isRetry && this.autoRetryOn401 && this.authManagerInstance) {\n await this.authManagerInstance.invalidateDomainAsync(url.host);\n return this.execute<TResponse>(operation, input, bodyType, options, true);\n }\n\n if (!response.ok) throw new ZaloSdkError(`Zalo request failed with HTTP ${response.status}.`, response.status, operation.operationId, responseBody);\n return responseBody as TResponse;\n }\n\n /** Converts a flat public DTO into the transport locations required by one API. */\n public toTransportInput(operation: OperationDefinition, dto: Record<string, unknown>): Record<string, unknown> {\n const output: Record<string, unknown> = {};\n const add = (location: string, names: string[]) => {\n if (!names.length) return;\n const values: Record<string, unknown> = {};\n for (const name of names) if (dto[name] !== undefined) values[name] = dto[name];\n output[location] = values;\n };\n add(\"path_param\", operation.pathFields);\n add(\"query_param\", operation.queryFields);\n add(\"header_param\", operation.headerFields);\n add(\"cookie_param\", operation.cookieFields);\n add(\"body\", operation.bodyFields);\n\n // Tự động gài context từ accountScope vào query_param nếu caller không truyền thủ công\n if (this.accountScope && output.query_param) {\n const query = output.query_param as Record<string, unknown>;\n const isAgencyContext =\n this.accountScope.accountType === \"AGENCY_SUB_ACCOUNT\" ||\n this.accountScope.accountType === \"AGENCY_MASTER\" ||\n this.accountScope.accountType === \"AGENCY\" ||\n Boolean(this.accountScope.agencyId);\n\n if (\n operation.queryFields.includes(\"agencyId\") &&\n query.agencyId === undefined &&\n isAgencyContext &&\n this.accountScope.agencyId\n ) {\n query.agencyId = Number(this.accountScope.agencyId);\n }\n\n if (\n operation.queryFields.includes(\"createdBy\") &&\n query.createdBy === undefined &&\n this.accountScope.accountType === \"AGENCY_SUB_ACCOUNT\" &&\n this.accountScope.memberId &&\n String(this.accountScope.memberId) !== \"0\"\n ) {\n query.createdBy = Number(this.accountScope.memberId);\n }\n }\n\n return output;\n }\n\n private async resolveFile(input: FileInput): Promise<Blob> {\n if (typeof input === \"string\") {\n if (/^(https?:|data:)/i.test(input)) {\n const response = await this.fetchImpl(input);\n if (!response.ok) throw new Error(`Cannot download upload file URL: HTTP ${response.status}.`);\n return response.blob();\n }\n // Local file path in Node.js runtime\n const fs = await import(\"node:fs/promises\");\n const bytes = await fs.readFile(input);\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return new Blob([copy.buffer], { type: inferMimeType(input) });\n }\n if (input instanceof Blob) return input;\n if (input instanceof ArrayBuffer) return new Blob([input]);\n // Copy first so TypeScript does not retain a SharedArrayBuffer-compatible view.\n const bytes = new Uint8Array(input.byteLength);\n bytes.set(input);\n return new Blob([bytes.buffer]);\n }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value) ? value as Record<string, unknown> : {};\n}\nfunction appendQuery(params: URLSearchParams, key: string, value: unknown): void {\n if (value === undefined || value === null || value === \"\") return;\n if (Array.isArray(value)) { for (const item of value) params.append(key, String(item)); return; }\n params.set(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n}\nfunction fileNameFrom(value: unknown): string {\n if (typeof value === \"string\") {\n if (/^https?:/i.test(value)) {\n try { return new URL(value).pathname.split(\"/\").pop() || \"upload\"; } catch { return \"upload\"; }\n }\n const base = value.split(/[\\\\/]/).pop();\n return base || \"upload\";\n }\n if (value && typeof value === \"object\" && \"name\" in value && typeof (value as { name?: unknown }).name === \"string\") {\n return (value as { name: string }).name;\n }\n if (value instanceof Blob && value.type) {\n const ext = value.type.split(\"/\")[1]?.replace(\"jpeg\", \"jpg\");\n if (ext) return `upload.${ext}`;\n }\n return \"upload\";\n}\nfunction inferMimeType(filePath: string): string {\n const lower = filePath.toLowerCase();\n if (lower.endsWith(\".jpg\") || lower.endsWith(\".jpeg\")) return \"image/jpeg\";\n if (lower.endsWith(\".png\")) return \"image/png\";\n if (lower.endsWith(\".gif\")) return \"image/gif\";\n if (lower.endsWith(\".webp\")) return \"image/webp\";\n if (lower.endsWith(\".mp4\")) return \"video/mp4\";\n if (lower.endsWith(\".txt\")) return \"text/plain\";\n if (lower.endsWith(\".csv\")) return \"text/csv\";\n return \"application/octet-stream\";\n}\nasync function resolveHeaders(auth: ZaloSdkAuth | undefined, context: ZaloSdkAuthContext): Promise<Record<string, string>> {\n return { ...(auth?.headers ?? {}), ...((await auth?.getHeaders?.(context)) ?? {}) };\n}\nasync function resolveCookies(auth: ZaloSdkAuth | undefined, context: ZaloSdkAuthContext): Promise<Record<string, string>> {\n return { ...(auth?.cookies ?? {}), ...((await auth?.getCookies?.(context)) ?? {}) };\n}\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Targeting & Custom Audiences trên Zalo Ads:\n * 1. createSavedAudience (POST /api/ad/audience với caType = 1)\n * 2. createPhoneAudience (POST /api/ad/audience với caType = 3)\n * 3. createLookalikeAudience (POST /api/ad/audience với caType = 6)\n * 4. createFormEventAudience (POST /api/ad/audience với caType = 12)\n * 5. createMessageOaEventAudience (POST /api/ad/audience với caType = 11)\n * 6. createMessagePersonalEventAudience (POST /api/ad/audience với caType = 14)\n * 7. createFormLeadAudience (POST /api/ad/audience với caType = 10)\n * 8. createMessageOaLeadAudience (POST /api/ad/audience với caType = 13)\n * 9. createCommerceFormAudience (POST /api/ad/audience với caType = 15)\n * 10. createLeadSignalAudience (POST /api/ad/audience với caType = 16)\n * 11. estimateAudience (POST /api/ad/estimateAudience)\n * 12. deleteCustomAudience (DELETE /api/ad/audience/{customAudienceId})\n */\n\nimport type { ValidationResult } from \"./instant-pages.validator\";\nimport type {\n ZaloAdsUploadCustomAudiencePhoneListRequest,\n ZaloAdsCreateCustomAudienceRequest,\n} from \"../dtos/ads.dto\";\n\n/**\n * Danh mục mã 63 Tỉnh/Thành phố chuẩn theo 3 Vùng miền trên Zalo Ads Targeting Engine (Danh mục cũ):\n */\nexport const ZALO_REGION_PROVINCE_CODES: Record<number, string[]> = {\n 1: [\n \"VN58\", \"VN44\", \"VN72\", \"VN83\", \"VN50\", \"VN13\", \"VN82\", \"VN70\", \"VN53\", \"VN30\",\n \"VN74\", \"VN34\", \"VN52\", \"VN79\", \"VN80\", \"VN32\", \"VN71\", \"VN59\", \"VN86\", \"VN05\",\n \"VN85\", \"VN39\", \"VN35\", \"VN89\", \"VN81\", \"VN92\", \"VN90\", \"VN68\"\n ],\n 2: [\n \"VN55\", \"VN88\", \"VN47\", \"VN62\", \"VN54\", \"VN61\", \"VN64\", \"VN49\", \"VN63\", \"VN46\",\n \"VN84\", \"VN66\", \"VN91\", \"VN60\", \"VN23\", \"VN78\"\n ],\n 3: [\n \"VN87\", \"VN03\", \"VN76\", \"VN43\", \"VN65\", \"VN21\", \"VN24\", \"VN75\", \"VN45\", \"VN67\",\n \"VN01\", \"VN73\", \"VN77\", \"VN37\", \"VN20\", \"VN09\", \"VN69\", \"VN33\", \"VN93\"\n ]\n};\n\n/**\n * Danh mục 34 Cụm Tỉnh/Thành phố mới sau sáp nhập trên Zalo Ads (newProvinces).\n * Khi cấu hình WardTargeting (từ cải cách hành chính 2026), Zalo Ads Angular UI\n * BẮT BUỘC tra cứu theo 34 mã mới này. Nếu truyền mã tỉnh đã bị gộp (như VN75 - Bình Dương),\n * giao diện Zalo Ads sẽ bị lỗi đỏ: 'Invalid wards params'.\n */\nexport const ZALO_NEW_REGION_PROVINCE_CODES: Record<number, string[]> = {\n 1: [\"VN58\", \"VN44\", \"VN83\", \"VN32\", \"VN59\", \"VN13\", \"VN89\", \"VN30\", \"VN74\", \"VN34\", \"VN52\", \"VN05\", \"VN85\", \"VN39\", \"VN81\", \"VN92\", \"VN90\", \"VN68\"],\n 2: [\"VN66\", \"VN88\", \"VN54\", \"VN64\", \"VN49\", \"VN63\", \"VN23\", \"VN78\"],\n 3: [\"VN20\", \"VN87\", \"VN43\", \"VN33\", \"VN01\", \"VN77\", \"VN09\", \"VN69\"]\n};\n\n/** Bảng tra cứu ánh xạ mã tỉnh cũ sang cụm tỉnh mới sau sáp nhập */\nexport const ZALO_PROVINCE_MERGE_MAPPING: Record<string, { newCode: string; regionId: number; name: string }> = {\n VN75: { newCode: \"VN20\", regionId: 3, name: \"Bình Dương (đã sáp nhập vào cụm Hồ Chí Minh VN20)\" },\n VN45: { newCode: \"VN20\", regionId: 3, name: \"Bà Rịa - Vũng Tàu (đã sáp nhập vào cụm Hồ Chí Minh VN20)\" },\n VN76: { newCode: \"VN43\", regionId: 3, name: \"Bình Phước (đã sáp nhập vào cụm Đồng Nai VN43)\" },\n VN24: { newCode: \"VN33\", regionId: 3, name: \"Long An (đã sáp nhập vào cụm Tây Ninh VN33)\" },\n VN21: { newCode: \"VN01\", regionId: 3, name: \"Kiên Giang (đã sáp nhập vào cụm An Giang VN01)\" },\n VN73: { newCode: \"VN77\", regionId: 3, name: \"Bạc Liêu (đã sáp nhập vào cụm Cà Mau VN77)\" },\n VN37: { newCode: \"VN09\", regionId: 3, name: \"Tiền Giang (đã sáp nhập vào cụm Đồng Tháp VN09)\" },\n VN03: { newCode: \"VN69\", regionId: 3, name: \"Bến Tre (đã sáp nhập vào cụm Vĩnh Long VN69)\" },\n VN67: { newCode: \"VN69\", regionId: 3, name: \"Trà Vinh (đã sáp nhập vào cụm Vĩnh Long VN69)\" },\n VN65: { newCode: \"VN87\", regionId: 3, name: \"Sóc Trăng (đã sáp nhập vào cụm Cần Thơ VN87)\" },\n VN93: { newCode: \"VN87\", regionId: 3, name: \"Hậu Giang (đã sáp nhập vào cụm Cần Thơ VN87)\" },\n VN61: { newCode: \"VN88\", regionId: 2, name: \"Phú Yên (đã sáp nhập vào cụm Đắk Lắk VN88)\" },\n VN60: { newCode: \"VN54\", regionId: 2, name: \"Ninh Thuận (đã sáp nhập vào cụm Khánh Hòa VN54)\" },\n VN62: { newCode: \"VN64\", regionId: 2, name: \"Quảng Bình (đã sáp nhập vào cụm Quảng Trị VN64)\" },\n VN46: { newCode: \"VN49\", regionId: 2, name: \"Bình Định (đã sáp nhập vào cụm Gia Lai VN49)\" },\n VN55: { newCode: \"VN63\", regionId: 2, name: \"Kon Tum (đã sáp nhập vào cụm Quảng Ngãi VN63)\" },\n VN47: { newCode: \"VN23\", regionId: 2, name: \"Bình Thuận (đã sáp nhập vào cụm Lâm Đồng VN23)\" },\n VN91: { newCode: \"VN23\", regionId: 2, name: \"Đắk Nông (đã sáp nhập vào cụm Lâm Đồng VN23)\" },\n VN84: { newCode: \"VN78\", regionId: 2, name: \"Quảng Nam (đã sáp nhập vào cụm Đà Nẵng VN78)\" },\n VN86: { newCode: \"VN83\", regionId: 1, name: \"Ninh Bình (đã sáp nhập vào cụm Phú Thọ VN83)\" },\n VN53: { newCode: \"VN83\", regionId: 1, name: \"Bắc Kạn (đã sáp nhập vào cụm Phú Thọ VN83)\" },\n VN82: { newCode: \"VN59\", regionId: 1, name: \"Bắc Giang (đã sáp nhập vào cụm Ninh Bình VN59)\" },\n VN80: { newCode: \"VN59\", regionId: 1, name: \"Phú Thọ cũ (đã sáp nhập vào cụm Ninh Bình VN59)\" },\n VN79: { newCode: \"VN13\", regionId: 1, name: \"Hải Dương (đã sáp nhập vào cụm Hải Phòng VN13)\" },\n VN71: { newCode: \"VN74\", regionId: 1, name: \"Hưng Yên cũ (đã sáp nhập vào cụm Bắc Ninh VN74)\" },\n VN72: { newCode: \"VN85\", regionId: 1, name: \"Yên Bái (đã sáp nhập vào cụm Thái Nguyên VN85)\" },\n VN35: { newCode: \"VN81\", regionId: 1, name: \"Thái Bình (đã sáp nhập vào cụm Hưng Yên VN81)\" },\n VN70: { newCode: \"VN90\", regionId: 1, name: \"Vĩnh Phúc (đã sáp nhập vào cụm Lào Cai VN90)\" },\n VN50: { newCode: \"VN68\", regionId: 1, name: \"Hòa Bình (đã sáp nhập vào cụm Tuyên Quang VN68)\" }\n};\n\n/**\n * 1. Kiểm tra request Tạo Nhóm đối tượng đã lưu (Saved Audience - caType = 1)\n */\nexport function validateCreateSavedAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 1;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name) {\n errors.push(\"Tên nhóm đối tượng 'name' là bắt buộc.\");\n } else if (name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown>;\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n targetingObj = {};\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n } else {\n errors.push(\"Trường 'targeting' là bắt buộc (chuỗi JSON hoặc Object cấu hình targeting).\");\n targetingObj = {};\n }\n\n // Chuẩn hóa targeting defaults\n const gender = typeof targetingObj.Gender === \"number\" ? targetingObj.Gender : 0;\n if (![0, 1, 2].includes(gender)) {\n errors.push(\"Trường 'Gender' phải là 0 (Tất cả), 1 (Nam), hoặc 2 (Nữ).\");\n }\n\n const VALID_AGE_RANGES = [10282, 10283, 10284, 10285, 10286, 10287, 10288];\n const newAgeRanges = Array.isArray(targetingObj.NewAgeRanges) && targetingObj.NewAgeRanges.length > 0\n ? targetingObj.NewAgeRanges.map(Number)\n : VALID_AGE_RANGES;\n\n for (const age of newAgeRanges) {\n if (!VALID_AGE_RANGES.includes(age)) {\n errors.push(`Mã độ tuổi '${age}' không hợp lệ. Các mã cho phép: ${VALID_AGE_RANGES.join(\", \")}.`);\n }\n }\n\n const VALID_OS = [0, 1, 2, 3];\n const os = Array.isArray(targetingObj.Os) && targetingObj.Os.length > 0\n ? targetingObj.Os.map(Number)\n : [0, 1, 3];\n\n for (const o of os) {\n if (!VALID_OS.includes(o)) {\n errors.push(`Mã hệ điều hành '${o}' không hợp lệ (0: Android, 1: iOS, 2: Windows Phone, 3: PC).`);\n }\n }\n\n // Cấu hình vị trí địa lý\n let location: any = targetingObj.Location;\n if (!location || typeof location !== \"object\") {\n location = {\n Addresses: [],\n Cities: [],\n DistrictTargeting: { Includes: [], Excludes: [] },\n WardTargeting: { Includes: [], Excludes: [] },\n IsConvertedToWard: false,\n };\n } else {\n const rawWard = location.WardTargeting && typeof location.WardTargeting === \"object\"\n ? location.WardTargeting\n : undefined;\n const rawDistrict = location.DistrictTargeting && typeof location.DistrictTargeting === \"object\"\n ? location.DistrictTargeting\n : undefined;\n const baseTargeting = rawWard || rawDistrict || { Includes: [], Excludes: [] };\n\n location = {\n Addresses: Array.isArray(location.Addresses) ? location.Addresses : [],\n Cities: Array.isArray(location.Cities) ? location.Cities : [],\n DistrictTargeting: rawDistrict || baseTargeting,\n WardTargeting: rawWard || baseTargeting,\n IsConvertedToWard: location.IsConvertedToWard !== undefined ? Boolean(location.IsConvertedToWard) : false,\n };\n\n const includes = location.WardTargeting.Includes || location.DistrictTargeting.Includes;\n if (includes && !Array.isArray(includes)) {\n errors.push(\"Trường 'Location.WardTargeting.Includes' (hoặc DistrictTargeting.Includes) phải là một mảng khu vực.\");\n } else if (Array.isArray(includes)) {\n for (const inc of includes) {\n if (![1, 2, 3].includes(Number(inc.Id))) {\n errors.push(`Mã vùng miền Id='${inc.Id}' không hợp lệ (1: Miền Bắc, 2: Miền Trung, 3: Miền Nam).`);\n }\n if (inc.Provinces && !Array.isArray(inc.Provinces)) {\n errors.push(`Trường 'Provinces' trong vùng miền Id=${inc.Id} phải là một mảng tỉnh/thành.`);\n } else if (Array.isArray(inc.Provinces)) {\n for (const prov of inc.Provinces) {\n if (!prov.Id || typeof prov.Id !== \"string\") {\n errors.push(`Mã tỉnh 'Id' (${JSON.stringify(prov)}) trong vùng miền ${inc.Id} phải là chuỗi hợp lệ (ví dụ: 'VN44', 'VN20').`);\n } else {\n const mergeInfo = ZALO_PROVINCE_MERGE_MAPPING[prov.Id];\n if (mergeInfo) {\n errors.push(\n `Mã tỉnh '${prov.Id}' (${mergeInfo.name}) đã được Zalo Ads gộp/sáp nhập vào cụm mã '${mergeInfo.newCode}'. ` +\n `Vui lòng sử dụng mã cụm '${mergeInfo.newCode}' trong WardTargeting, nếu không giao diện Zalo Ads Web sẽ báo lỗi đỏ 'Invalid wards params'.`\n );\n } else {\n const validNewRegionProvs = ZALO_NEW_REGION_PROVINCE_CODES[Number(inc.Id)] || [];\n if (!validNewRegionProvs.includes(prov.Id)) {\n const actualRegion = Object.keys(ZALO_NEW_REGION_PROVINCE_CODES).find(r => ZALO_NEW_REGION_PROVINCE_CODES[Number(r)].includes(prov.Id));\n errors.push(\n `Mã tỉnh '${prov.Id}' không nằm trong 34 Cụm Tỉnh/Thành mới của Vùng ${inc.Id} trên Zalo Ads (sẽ gây lỗi 'Invalid wards params' trên UI). ` +\n (actualRegion ? `Mã này thuộc Vùng ${actualRegion}. ` : \"\")\n );\n }\n }\n }\n if (prov.Districts && !Array.isArray(prov.Districts)) {\n errors.push(`Trường 'Districts' của tỉnh ${prov.Id} phải là một mảng (hoặc [] khi chọn cả tỉnh).`);\n }\n }\n }\n }\n }\n }\n\n const finalTargeting = {\n ...targetingObj,\n CustomAudienceId: 0,\n Gender: gender,\n NewAgeRanges: newAgeRanges,\n Os: os,\n Location: location\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 1,\n targeting: JSON.stringify(finalTargeting)\n } : undefined\n };\n}\n\n/**\n * 2. Kiểm tra request Tạo Nhóm đối tượng từ danh sách Số điện thoại (caType = 3)\n */\nexport function validateCreatePhoneAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 3;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n } else {\n errors.push(\"Trường 'targeting' là bắt buộc.\");\n }\n\n const path = typeof targetingObj.Path === \"string\" ? targetingObj.Path.trim() : \"\";\n if (!path) {\n errors.push(\"Trường 'Path' (URL file .txt sau khi upload) là bắt buộc.\");\n }\n\n const total = typeof targetingObj.Total === \"number\" ? targetingObj.Total : 0;\n if (total <= 0) {\n errors.push(\"Trường 'Total' (số lượng SĐT trong file) phải lớn hơn 0.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 3,\n targeting: JSON.stringify({\n Name: String(targetingObj.Name || \"phones.txt\"),\n Path: path,\n Total: total,\n ZaloId: Number(targetingObj.ZaloId || 0),\n OriginAudience: 0\n })\n } : undefined\n };\n}\n\n/**\n * 3. Kiểm tra request Tạo Nhóm đối tượng tương tự Lookalike (caType = 6)\n */\nexport function validateCreateLookalikeAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 6;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n } else {\n errors.push(\"Trường 'targeting' là bắt buộc.\");\n }\n\n const originAudience = Number(targetingObj.OriginAudience);\n if (!originAudience || originAudience <= 0) {\n errors.push(\"Trường 'OriginAudience' (ID nhóm đối tượng SĐT gốc) là bắt buộc.\");\n }\n\n const total = Number(targetingObj.Total);\n if (![1000000, 1500000, 2000000].includes(total)) {\n errors.push(\"Trường 'Total' của Lookalike chỉ chấp nhận các mốc: 1.000.000, 1.500.000 hoặc 2.000.000.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 6,\n targeting: JSON.stringify({\n OriginAudience: originAudience,\n Total: total,\n Name: String(targetingObj.Name || \"Lookalike Audience\"),\n Path: String(targetingObj.Path || \"\")\n })\n } : undefined\n };\n}\n\n/**\n * 4. Kiểm tra request Tạo Nhóm đối tượng sự kiện Form (caType = 12)\n */\nexport function validateCreateFormEventAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 12;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n }\n\n const eventType = Number(targetingObj.EventType);\n if (![1, 2, 3, 4].includes(eventType)) {\n errors.push(\"Trường 'EventType' phải là 1 (Đã xem chưa gửi), 2 (Đã xem & gửi), 3 (Đã xem), hoặc 4 (Mở chat từ Form).\");\n }\n\n const oaId = typeof targetingObj.OaId === \"string\" ? targetingObj.OaId.trim() : String(targetingObj.OaId || \"\");\n if (!oaId) {\n errors.push(\"Trường 'OaId' (dạng chuỗi của pageId hoặc noisedId) là bắt buộc.\");\n }\n\n const numDays = Number(targetingObj.NumDays);\n if (isNaN(numDays) || numDays < 1 || numDays > 90) {\n errors.push(\"Trường 'NumDays' phải nằm trong khoảng từ 1 đến 90 ngày.\");\n }\n\n const formIds = Array.isArray(targetingObj.FormIds) ? targetingObj.FormIds : [];\n if (formIds.length === 0) {\n errors.push(\"Trường 'FormIds' phải chứa ít nhất 1 ID Form.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 12,\n targeting: JSON.stringify({\n EventType: eventType,\n OaId: oaId,\n NumDays: numDays,\n FormIds: formIds\n })\n } : undefined\n };\n}\n\n/**\n * 5. Kiểm tra request Tạo Nhóm đối tượng sự kiện Tin nhắn OA (caType = 11)\n */\nexport function validateCreateMessageOaEventAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 11;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n }\n\n const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);\n const oaId = typeof targetingObj.OaId === \"string\" ? targetingObj.OaId.trim() : String(targetingObj.OaId || \"\");\n if (!oaId) {\n errors.push(\"Trường 'OaId' (chuỗi pageId hoặc noisedId của OA) là bắt buộc.\");\n }\n\n const numDays = Number(targetingObj.NumDays);\n if (isNaN(numDays) || numDays < 1 || numDays > 90) {\n errors.push(\"Trường 'NumDays' phải nằm trong khoảng từ 1 đến 90 ngày.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 11,\n targeting: JSON.stringify({\n EventId: eventId,\n OaId: oaId,\n NumDays: numDays\n })\n } : undefined\n };\n}\n\n/**\n * 6. Kiểm tra request Tạo Nhóm đối tượng sự kiện Tin nhắn Cá nhân (caType = 14)\n */\nexport function validateCreateMessagePersonalEventAudienceRequest(input: unknown): ValidationResult<{\n name: string;\n caType: 14;\n targeting: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name || name.length < 2 || name.length > 255) {\n errors.push(\"Tên nhóm đối tượng 'name' phải từ 2 đến 255 ký tự.\");\n }\n\n let targetingObj: Record<string, unknown> = {};\n if (typeof raw.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(raw.targeting);\n } catch {\n errors.push(\"Trường 'targeting' là chuỗi JSON không hợp lệ.\");\n }\n } else if (raw.targeting && typeof raw.targeting === \"object\") {\n targetingObj = raw.targeting as Record<string, unknown>;\n }\n\n const eventId = Number(targetingObj.EventId ?? targetingObj.EventType ?? 1);\n if (![1, 2, 3].includes(eventId)) {\n errors.push(\"Trường 'EventId' phải là 1 (Đã liên hệ), 2 (Đã xem không liên hệ), hoặc 3 (Xem carousel không liên hệ).\");\n }\n\n const numDays = Number(targetingObj.NumDays);\n if (isNaN(numDays) || numDays < 1 || numDays > 90) {\n errors.push(\"Trường 'NumDays' phải nằm trong khoảng từ 1 đến 90 ngày.\");\n }\n\n const pageIds = Array.isArray(targetingObj.PageIds) ? targetingObj.PageIds.map(String) : [];\n if (pageIds.length === 0) {\n errors.push(\"Trường 'PageIds' phải chứa ít nhất 1 ID trang cá nhân.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n name,\n caType: 14,\n targeting: JSON.stringify({\n EventId: eventId,\n NumDays: numDays,\n PageIds: pageIds\n })\n } : undefined\n };\n}\n\n/**\n * 7. Kiểm tra request Ước tính quy mô đối tượng (POST /api/ad/estimateAudience)\n */\nexport function validateEstimateAudienceRequest(input: unknown): ValidationResult<{\n gender: number;\n ageRanges: number[];\n platforms: number[];\n locations: string;\n provinces: number[];\n wardsTargeting: string;\n priceType: number;\n number: string;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n\n const gender = typeof raw.gender === \"number\" ? raw.gender : 0;\n if (![0, 1, 2].includes(gender)) {\n errors.push(\"Trường 'gender' phải là 0, 1 hoặc 2.\");\n }\n\n const ageRanges = Array.isArray(raw.ageRanges) && raw.ageRanges.length > 0\n ? raw.ageRanges.map(Number)\n : [10283, 10284, 10285, 10286, 10287];\n\n const platforms = Array.isArray(raw.platforms) && raw.platforms.length > 0\n ? raw.platforms.map(Number)\n : [0, 1, 3];\n\n const priceType = typeof raw.priceType === \"number\" ? raw.priceType : 2;\n\n const wardsTargeting = typeof raw.wardsTargeting === \"string\" && raw.wardsTargeting.trim()\n ? raw.wardsTargeting.trim()\n : JSON.stringify({ Includes: [], Excludes: [] });\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n gender,\n ageRanges,\n platforms,\n locations: typeof raw.locations === \"string\" ? raw.locations : \"\",\n provinces: Array.isArray(raw.provinces) ? raw.provinces.map(Number) : [],\n wardsTargeting,\n priceType,\n number: typeof raw.number === \"string\" ? raw.number : String(raw.number || \"0\")\n } : undefined\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của tệp danh sách số điện thoại tải lên Zalo Ads (POST /api/ad/uploadPhoneList).\n */\nexport function validateUploadCustomAudiencePhoneListRequest(\n input: unknown\n): ValidationResult<ZaloAdsUploadCustomAudiencePhoneListRequest> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu tải danh sách số điện thoại phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const file = raw.File ?? raw.file;\n\n if (!file) {\n errors.push(\"Trường tệp danh sách số điện thoại ('File') là bắt buộc.\");\n return { isValid: false, errors };\n }\n\n if (typeof file === \"string\") {\n const trimmed = file.trim();\n if (!trimmed) {\n errors.push(\"Đường dẫn tệp danh sách số điện thoại không được để trống.\");\n } else if (!/^https?:\\/\\/.+/i.test(trimmed)) {\n errors.push(`Đường dẫn tệp '${trimmed}' không hợp lệ. Phải là URL HTTP hoặc HTTPS.`);\n }\n\n const cleanUrl = trimmed.split(\"?\")[0].toLowerCase();\n if (!cleanUrl.endsWith(\".txt\") && !cleanUrl.endsWith(\".csv\")) {\n errors.push(\"Tệp danh sách số điện thoại phải có định dạng .txt hoặc .csv.\");\n }\n }\n\n const isHashRaw = raw.isHash !== undefined ? String(raw.isHash).trim() : \"0\";\n if (isHashRaw !== \"0\" && isHashRaw !== \"1\") {\n errors.push(`Giá trị 'isHash' không hợp lệ: '${raw.isHash}'. Chỉ hỗ trợ '0' (danh sách SĐT thô) hoặc '1' (danh sách đã băm).`);\n }\n\n const cleanData: ZaloAdsUploadCustomAudiencePhoneListRequest = {\n File: file as any,\n isHash: isHashRaw as \"0\" | \"1\",\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n/**\n * Router kiểm tra tính hợp lệ dữ liệu tạo Custom Audience tổng hợp theo caType (POST /api/ad/audience).\n */\nexport function validateCreateCustomAudienceRequest(\n input: unknown\n): ValidationResult<ZaloAdsCreateCustomAudienceRequest> {\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu tạo đối tượng tùy chỉnh (Custom Audience) phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const caType = Number(raw.caType);\n\n switch (caType) {\n case 1:\n return validateCreateSavedAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 3:\n return validateCreatePhoneAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 6:\n return validateCreateLookalikeAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 12:\n return validateCreateFormEventAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 11:\n return validateCreateMessageOaEventAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n case 14:\n return validateCreateMessagePersonalEventAudienceRequest(raw) as ValidationResult<ZaloAdsCreateCustomAudienceRequest>;\n default: {\n const errors: string[] = [];\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name) {\n errors.push(\"Tên tập đối tượng ('name') là bắt buộc.\");\n } else if (name.length > 100) {\n errors.push(`Tên tập đối tượng không được vượt quá 100 ký tự (hiện tại: ${name.length} ký tự).`);\n }\n if (!Number.isInteger(caType) || caType <= 0) {\n errors.push(`Loại đối tượng tùy chỉnh ('caType') không hợp lệ: ${raw.caType}.`);\n }\n if (!raw.targeting || typeof raw.targeting !== \"object\") {\n errors.push(\"Cấu hình nhắm mục tiêu ('targeting') là bắt buộc.\");\n }\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? (raw as unknown as ZaloAdsCreateCustomAudienceRequest) : undefined,\n };\n }\n }\n}\n\n/**\n * Gom nhóm toàn bộ Validators cho Targeting & Audiences APIs.\n */\nexport const ZaloAudiencesValidator = {\n createCustomAudience: validateCreateCustomAudienceRequest,\n createSavedAudience: validateCreateSavedAudienceRequest,\n createPhoneAudience: validateCreatePhoneAudienceRequest,\n createLookalikeAudience: validateCreateLookalikeAudienceRequest,\n createFormEventAudience: validateCreateFormEventAudienceRequest,\n createMessageOaEventAudience: validateCreateMessageOaEventAudienceRequest,\n createMessagePersonalEventAudience: validateCreateMessagePersonalEventAudienceRequest,\n estimateAudience: validateEstimateAudienceRequest,\n uploadPhoneList: validateUploadCustomAudiencePhoneListRequest,\n validateUploadPhoneList: validateUploadCustomAudiencePhoneListRequest,\n validateUploadCustomAudiencePhoneList: validateUploadCustomAudiencePhoneListRequest,\n} as const;\n","/** DTOs for Zalo Ads. Request fields are flattened; services route them automatically. */\r\nimport type { FileInput } from \"../types\";\r\n\r\n/** Một tin nhắn con được gửi khi người dùng chọn nút tư vấn của kịch bản. */\r\nexport class ZaloAdsFlowChildMessageDto {\r\n /** Mẫu Zalo đã xác minh dùng 8 cho tin nhắn văn bản trong nhánh. */\r\n type!: 8;\r\n /** Nội dung phản hồi trong nhánh. */\r\n text!: string;\r\n}\r\n\r\n/** Nút hành động trong một tin nhắn kịch bản. */\r\nexport class ZaloAdsFlowButtonDto {\r\n /** 3 = Gửi tin nhắn vào nhánh hội thoại; 10 = Mở website; 12 = Thực hiện cuộc gọi. */\r\n type!: 3 | 10 | 12 | number;\r\n /** Nhãn nút hiển thị cho người dùng. */\r\n text!: string;\r\n /** URL website; bắt buộc với type 10. */\r\n url?: string;\r\n /** Cờ của nút website; dùng true với type 10. */\r\n editable?: boolean;\r\n /** Số hotline, bắt buộc khi type là 12. */\r\n phone?: string;\r\n /** Nhánh tin nhắn, bắt buộc khi type là 3. Với type 10 hoặc 12, để null hoặc bỏ qua. */\r\n messages?: ZaloAdsFlowChildMessageDto[] | null;\r\n}\r\n\r\n/** Một bước tin nhắn trong kịch bản. */\r\nexport class ZaloAdsFlowMessageDto {\r\n /** 1 = Tin nhắn văn bản; 2 = Tin nhắn kèm hình ảnh. */\r\n type!: number;\r\n /** Nội dung tin nhắn, tối đa 1961 ký tự. Hỗ trợ biến: {{user_name}}, {{page_name}}, {{user_gender}}, {{user_id}}, {{page_id}}, {{date}}, {{datetime}}. */\r\n text!: string;\r\n /** URL media hoặc null với tin nhắn văn bản thuần. Bắt buộc và không được null khi type = 2. */\r\n url?: string | null;\r\n /** Các nút đi kèm tin nhắn. */\r\n buttons?: ZaloAdsFlowButtonDto[];\r\n}\r\n\r\n/** Tạo một kịch bản tin nhắn mới và nhận ZaloFlowId để gắn vào quảng cáo Tin nhắn. */\r\nexport class ZaloAdsCreateFlowRequest {\r\n /** ID Official Account sở hữu kịch bản. */\r\n oaId!: number;\r\n /** Luôn null khi tạo kịch bản mới. */\r\n id!: null;\r\n /** Tên kịch bản, tối đa 33 ký tự theo giao diện Zalo Ads. */\r\n name!: string;\r\n /** Các tin nhắn được gửi theo thứ tự trong kịch bản. */\r\n messages!: ZaloAdsFlowMessageDto[];\r\n}\r\n\r\nexport class ZaloAdsCreateFlowResponse {\r\n /** 0 khi tạo thành công; 1 khi lỗi (ví dụ: đã tới hạn mức 20 kịch bản). */\r\n code!: number;\r\n /** Thông báo lỗi từ Zalo Ads khi code khác 0. */\r\n msg?: string;\r\n /** ID kịch bản mới, truyền vào data.ZaloFlowId khi cập nhật quảng cáo Tin nhắn. */\r\n data?: { id: number };\r\n}\r\n\r\n/** Cập nhật kịch bản tin nhắn có sẵn của Official Account, gồm tin nhắn văn bản hoặc ảnh, các biến động và nút tương tác. Đây là mutation tool thuộc lane zalo-ads-message; dùng khi đã có Flow ID và cần thay đổi nội dung mà vẫn giữ liên kết quảng cáo. */\r\nexport type ZaloAdsUpdateFlowRequest = {\r\n /** ID Flow cần cập nhật. */\r\n id: number;\r\n /** Tên kịch bản; giao diện hiện giới hạn tối đa 27 ký tự. */\r\n name: string;\r\n /** ID Official Account sở hữu kịch bản. */\r\n oaId: number;\r\n /** Chuỗi tin nhắn của kịch bản. */\r\n messages: ZaloAdsFlowMessageDto[];\r\n};\r\n\r\nexport type ZaloAdsUpdateFlowResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: {\r\n id?: number;\r\n };\r\n};\r\n\r\n/**\r\n * Chế độ phân phối ngân sách quảng cáo trên Zalo Ads (Settings.DeliveryType):\r\n * - 0: Tiêu chuẩn (Standard) - Phân phối ngân sách đồng đều suốt toàn bộ thời gian chạy quảng cáo.\r\n * - 1: Tăng tốc (SpeedUp) - Phân phối quảng cáo nhanh nhất có thể cho tới khi cạn ngân sách.\r\n * \r\n * Lưu ý: Chỉ xuất hiện và có hiệu lực khi Price.LimitType = 1 (Toàn lịch chạy).\r\n */\r\nexport type ZaloAdsDeliveryType = 0 | 1;\r\n\r\nexport interface ZaloAdsAdPriceSettingsDto {\r\n /**\r\n * Mức giá đặt thầu (VNĐ).\r\n * - Đặt 0 khi chọn đấu thầu tự động hoặc khi Price.Type = 5 (CPA - Lượt liên hệ).\r\n * - Bắt buộc > 0 khi chọn đấu thầu thủ công (CPC).\r\n */\r\n Bid: number;\r\n /**\r\n * Phương thức tính tiền:\r\n * - 1: Lượt hiển thị (CPM) - Website Ads legacy.\r\n * - 2: Lượt nhấn (CPC) - Website, Form, Message, OA, Video, Commerce, Article.\r\n * - 5: Lượt liên hệ (CPA) - Dành riêng cho Quảng cáo Tin nhắn (Type 30) khi tối ưu theo lượt khách nhắn tin liên hệ.\r\n */\r\n Type: number;\r\n /**\r\n * Hạn mức chi tiêu (VNĐ).\r\n * - Quảng cáo Tin nhắn yêu cầu ngân sách tối thiểu 600,000 VNĐ.\r\n */\r\n Limit: number;\r\n /**\r\n * Phạm vi áp dụng ngân sách (ZaloAdsPriceLimitType):\r\n * - 1: Toàn lịch chạy (LIFE_TIME - áp dụng ngân sách tổng cho toàn bộ thời gian chạy).\r\n * - 2: Mỗi ngày (DAILY - hạn mức ngân sách phân bổ theo từng ngày).\r\n */\r\n LimitType: number;\r\n /**\r\n * Phương thức chi tiêu / tối ưu hóa:\r\n * - 0: Đặt giá thầu thủ công (Manual Bid).\r\n * - 1: Tự động tối ưu chi phí theo ngân sách (Total budget / Auto optimize, bắt buộc khi Type = 5 CPA).\r\n */\r\n SpendingMethod: number;\r\n}\r\n\r\nexport interface ZaloAdsAdMultiImageItemDto {\r\n Url: string;\r\n Title?: string;\r\n Description?: string;\r\n TargetUrl?: string;\r\n}\r\n\r\nexport interface ZaloAdsAdImageSettingsDto {\r\n LogoUrl?: string;\r\n LandscapeCoverUrl?: string;\r\n BaseLandscapeCoverUrl?: string;\r\n PortraitCoverUrl?: string;\r\n SquareCoverUrl?: string;\r\n ExtraUrls?: Array<string>;\r\n Crops?: Array<unknown>;\r\n VideoUrl?: string;\r\n VideoDuration?: number;\r\n MediaId?: number;\r\n MultiImages?: Array<ZaloAdsAdMultiImageItemDto>;\r\n}\r\n\r\nexport interface ZaloAdsAdInfoSettingsDto {\r\n Title?: string;\r\n Description?: string;\r\n Caption?: string;\r\n /**\r\n * Chú thích mở rộng (không bắt buộc).\r\n * - Quy chuẩn độ dài: Tối thiểu 90 ký tự, tối đa 2000 ký tự (90 - 2,000 ký tự).\r\n * - Nếu để trống \"\" hoặc không truyền: Hợp lệ.\r\n * - Nếu đã nhập: Bắt buộc từ 90 đến 2,000 ký tự.\r\n * - Tự động kích hoạt mã bố cục mở rộng XTemplates = 49 (LONG_CAPTION).\r\n */\r\n LongCaption?: string;\r\n Action?: number;\r\n ButtonText?: string;\r\n MoreInfo?: string;\r\n TargetUrl?: string | { Url?: string; DisplayText?: string };\r\n Phone?: string;\r\n SupportPhone?: string;\r\n Address?: string;\r\n XTemplates?: Array<number>;\r\n Template?: number;\r\n WebsiteCategories?: Array<number>;\r\n AdtimaAdCategories?: Array<number>;\r\n Files?: Array<unknown>;\r\n Size?: number;\r\n ZaloOwner?: string;\r\n AdFormat?: number;\r\n OriginalUrl?: Array<unknown>;\r\n ThirdPartyImpressionUrl?: string | null;\r\n ThirdPartyClickUrl?: string | null;\r\n}\r\n\r\nexport interface ZaloAdsAdAppInfoSettingsDto {\r\n AppType?: number;\r\n OsType?: number;\r\n StoreUrl?: string;\r\n}\r\n\r\nexport interface ZaloAdsAdTargetingProvinceItemDto {\r\n /**\r\n * Mã định danh Tỉnh/Thành phố theo danh mục 34 Cụm Tỉnh mới sau sáp nhập 2026 (`newProvinces` trên Zalo Ads).\r\n * \r\n * QUAN TRỌNG: Giao diện Zalo Ads Angular Web chỉ phân giải cây Xã/Phường theo 34 mã cụm này.\r\n * Nếu truyền mã tỉnh lẻ đã bị sáp nhập (ví dụ: 'VN75' - Bình Dương, 'VN45' - Vũng Tàu, 'VN76' - Bình Phước),\r\n * giao diện web sẽ bị lỗi ngoại lệ popup: 'Invalid wards params'.\r\n * \r\n * Quy tắc ánh xạ mã cụm tỉnh:\r\n * - Cụm 'VN20' (Hồ Chí Minh): Bao gồm TP.HCM, Bình Dương ('VN75'), Bà Rịa - Vũng Tàu ('VN45').\r\n * - Cụm 'VN43' (Đồng Nai): Bao gồm Đồng Nai, Bình Phước ('VN76').\r\n * - Cụm 'VN44' (Hà Nội): Giữ nguyên không sáp nhập.\r\n * - Cụm 'VN33' (Tây Ninh): Bao gồm Tây Ninh, Long An ('VN24').\r\n * - Cụm 'VN01' (An Giang): Bao gồm An Giang, Kiên Giang ('VN21').\r\n * - Cụm 'VN87' (Cần Thơ): Bao gồm Cần Thơ, Sóc Trăng ('VN65'), Hậu Giang ('VN93').\r\n * - Cụm 'VN77' (Cà Mau): Bao gồm Cà Mau, Bạc Liêu ('VN73').\r\n * - Cụm 'VN09' (Đồng Tháp): Bao gồm Đồng Tháp, Tiền Giang ('VN37').\r\n * - Cụm 'VN69' (Vĩnh Long): Bao gồm Vĩnh Long, Bến Tre ('VN03'), Trà Vinh ('VN67').\r\n */\r\n Id: string;\r\n /** Danh sách mã xã/phường mục tiêu (mảng rỗng [] biểu thị chọn toàn bộ tỉnh/thành). */\r\n Districts: Array<number | string>;\r\n}\r\n\r\nexport interface ZaloAdsAdTargetingRegionItemDto {\r\n /**\r\n * Mã vùng miền:\r\n * - 1: Miền Bắc (18 cụm tỉnh mới / 28 tỉnh cũ)\r\n * - 2: Miền Trung (8 cụm tỉnh mới / 16 tỉnh cũ)\r\n * - 3: Miền Nam (8 cụm tỉnh mới / 19 tỉnh cũ)\r\n */\r\n Id: number;\r\n /**\r\n * Danh sách tỉnh/thành phố được chọn trong vùng.\r\n * Theo cơ chế compressAdData của Zalo Ads Client Engine:\r\n * Nếu mảng Provinces là rỗng ([]), hệ thống hiểu là CHỌN TOÀN BỘ VÙNG MIỀN ĐÓ.\r\n */\r\n Provinces: Array<ZaloAdsAdTargetingProvinceItemDto>;\r\n}\r\n\r\nexport interface ZaloAdsAdTargetingLocationContainerDto {\r\n Includes: Array<ZaloAdsAdTargetingRegionItemDto>;\r\n Excludes: Array<ZaloAdsAdTargetingRegionItemDto>;\r\n}\r\n\r\nexport interface ZaloAdsAdLocationSettingsDto {\r\n Cities?: Array<unknown>;\r\n Addresses?: Array<unknown>;\r\n /** Nhắm chọn cấp Tỉnh/Thành theo cấu trúc phân cấp Vùng miền. */\r\n DistrictTargeting?: ZaloAdsAdTargetingLocationContainerDto;\r\n /** Nhắm chọn chi tiết cấp Phường/Xã mới theo quy chuẩn 2026. */\r\n WardTargeting?: ZaloAdsAdTargetingLocationContainerDto;\r\n /** Cờ đánh dấu đã chuyển đổi sang cấp xã/phường. */\r\n IsConvertedToWard?: boolean;\r\n}\r\n\r\nexport interface ZaloAdsAdTargetingSettingsDto {\r\n Gender?: number;\r\n AgeRanges?: Array<number>;\r\n NewAgeRanges?: Array<number>;\r\n Location?: ZaloAdsAdLocationSettingsDto;\r\n Locations?: string;\r\n Provinces?: Array<number>;\r\n DistrictsTargeting?: string;\r\n WardsTargeting?: string;\r\n Platforms?: Array<number>;\r\n NetworkTypes?: Array<number>;\r\n Os?: Array<number>;\r\n OsTypes?: Array<number>;\r\n AdvanceTargeting?: {\r\n Includes?: Array<number>;\r\n Excludes?: Array<number>;\r\n };\r\n AdvanceTargetings?: Array<number>;\r\n CustomAudienceId?: number;\r\n ExcludedAudienceId?: number;\r\n Retargeting?: string;\r\n DmpAudience?: string;\r\n PhoneList?: Array<unknown>;\n SiteTargeting?: {\n WebSite?: number;\n Zone?: number;\n };\r\n CustomAudiences?: Array<number>;\r\n ExcludeCustomAudiences?: Array<number>;\r\n IncludedAudiences?: {\r\n Phones?: Array<unknown>;\r\n LeadSignal?: Array<unknown>;\r\n };\r\n ExcludedAudiences?: {\r\n Phones?: Array<unknown>;\r\n Forms?: Array<unknown>;\r\n Messages?: Array<unknown>;\r\n FormEvents?: Array<unknown>;\r\n MessageOAs?: Array<unknown>;\r\n MessageNonOAEvents?: Array<unknown>;\r\n } | null;\r\n}\r\n\r\nexport interface ZaloAdsAdZVideoSettingsDto {\r\n Url: string;\r\n Duration: number;\r\n Src: number;\r\n Thumbnail: string;\r\n Description: string;\r\n ChannelName: string;\r\n ChannelAvt: string;\r\n VideoThumbnail: string;\r\n ThumbnailIndex: number | null;\r\n}\r\n\r\nexport interface ZaloAdsAdSettingsDto {\r\n Image: ZaloAdsAdImageSettingsDto;\r\n Price: ZaloAdsAdPriceSettingsDto;\r\n AdInfo: ZaloAdsAdInfoSettingsDto;\r\n AppInfo?: ZaloAdsAdAppInfoSettingsDto;\r\n Targeting: ZaloAdsAdTargetingSettingsDto;\r\n ZVideo?: ZaloAdsAdZVideoSettingsDto;\r\n VideoPlatform?: number;\r\n Rating?: number;\r\n NewFeatures?: Array<number>;\r\n CreatedClientVersion?: number;\r\n /**\r\n * Phương thức phân phối quảng cáo (0: Tiêu chuẩn - Standard, 1: Tăng tốc - SpeedUp).\r\n * Chỉ có hiệu lực khi Price.LimitType = 1 (Toàn lịch chạy).\r\n */\r\n DeliveryType?: ZaloAdsDeliveryType | number;\r\n}\r\n\r\nexport interface ZaloAdsAdUpdatePayloadDto {\r\n AdId: number;\r\n CampaignId: number;\r\n MemberId: number;\r\n RowVersion: number;\r\n AdName: string;\r\n Type: number;\r\n Settings: ZaloAdsAdSettingsDto;\r\n Status: number;\r\n StartDate: number;\r\n EndDate: number;\r\n ZaloFlowId?: number;\r\n ZaloPageId?: number;\r\n ZaloFormId?: string;\r\n ZaloFeedId?: string | number;\r\n ZaloVideoId?: number;\r\n MiniPageId?: number;\r\n UseConversion?: ZaloAdsUseConversionValue | number;\r\n ConversionId?: number;\r\n Report?: Record<string, number>;\r\n}\r\n\r\n/** Danh mục mã hành động / nút CTA chuẩn trên Zalo Ads */\r\nexport const ZaloAdsActionType = {\r\n DAT_NGAY: 1,\r\n MUA_NGAY: 2,\r\n THU_NGAY: 3,\r\n TAI_NGAY: 4,\r\n XEM_THEM: 5,\r\n NGHE_NGAY: 6,\r\n CHOI_NGAY: 7,\r\n DANG_KY: 8,\r\n GOI_DIEN: 9,\r\n /** Dành riêng cho Quảng cáo Official Account (Type 2) */\r\n QUAN_TAM_OA: 6,\r\n} as const;\r\n\r\n/** Danh mục mã nguồn video trên Zalo Ads (Settings.ZVideo.Src) */\r\nexport const ZaloAdsVideoSrc = {\r\n UNUSED: -1,\r\n /** Sử dụng mã Zalo Video được cấp từ kênh */\r\n VIDEO_CODE: 1,\r\n /** Tự tải video lên hoặc chọn từ Thư viện Media */\r\n SELF_UPLOAD: 2,\r\n} as const;\r\n\r\nexport type ZaloAdsVideoSrcValue = typeof ZaloAdsVideoSrc[keyof typeof ZaloAdsVideoSrc];\r\n\r\n/** Danh mục chu kỳ áp dụng ngân sách trên Zalo Ads (Settings.Price.LimitType) - Alias của ZaloAdsPriceLimitType */\r\nexport const ZaloAdsBudgetScheduleType = {\r\n /** Toàn lịch chạy */\r\n TOTAL_SCHEDULE: 1,\r\n /** Mỗi ngày */\r\n DAILY: 2,\r\n} as const;\r\n\r\nexport type ZaloAdsBudgetScheduleTypeValue = typeof ZaloAdsBudgetScheduleType[keyof typeof ZaloAdsBudgetScheduleType];\r\n\r\n/** Danh mục mã khoảng tuổi nhắm chọn đối tượng trên Zalo Ads */\r\nexport const ZaloAdsAgeRangeId = {\r\n UNDER_18: 10282,\r\n FROM_18_TO_24: 10283,\r\n FROM_25_TO_34: 10284,\r\n FROM_35_TO_44: 10285,\r\n FROM_45_TO_54: 10286,\r\n FROM_55_TO_64: 10287,\r\n OVER_64: 10288,\r\n} as const;\r\n\r\n/** Danh mục mã hệ điều hành */\r\nexport const ZaloAdsOsId = {\r\n ANDROID: 0,\r\n IOS: 1,\r\n PC: 3,\r\n} as const;\r\n\r\nexport type ZaloAdsOsIdValue = typeof ZaloAdsOsId[keyof typeof ZaloAdsOsId];\r\n\r\n/** Danh mục mã 3 Vùng miền chuẩn trên Zalo Ads Targeting Engine */\r\nexport const ZaloAdsRegionId = {\r\n /** Miền Bắc (28 tỉnh/thành phố) */\r\n NORTH: 1,\r\n /** Miền Trung (16 tỉnh/thành phố) */\r\n CENTRAL: 2,\r\n /** Miền Nam (19 tỉnh/thành phố) */\r\n SOUTH: 3,\r\n} as const;\r\n\r\nexport type ZaloAdsRegionIdValue = typeof ZaloAdsRegionId[keyof typeof ZaloAdsRegionId];\r\n\r\n/**\r\n * Danh mục mã Tỉnh/Thành phố chuẩn trên Zalo Ads Targeting Engine (theo chuẩn ISO 3166-2:VN tiền tố 'VN')\r\n */\r\nexport const ZaloAdsProvinceCode = {\r\n // Miền Bắc (Region 1 - 28 tỉnh/thành)\r\n HANOI: 'VN44',\r\n HAI_PHONG: 'VN13',\r\n BAC_NINH: 'VN74',\r\n QUANG_NINH: 'VN30',\r\n HAI_DUONG: 'VN79',\r\n HUNG_YEN: 'VN81',\r\n VINH_PHUC: 'VN86',\r\n THAI_NGUYEN: 'VN85',\r\n BAC_GIANG: 'VN71',\r\n PHU_THO: 'VN83',\r\n NAM_DINH: 'VN82',\r\n THAI_BINH: 'VN35',\r\n NINH_BINH: 'VN59',\r\n THANH_HOA: 'VN34',\r\n NGHE_AN: 'VN58',\r\n HA_TINH: 'VN52',\r\n HOA_BINH: 'VN53',\r\n SON_LA: 'VN32',\r\n DIEN_BIEN: 'VN92',\r\n LAI_CHAU: 'VN89',\r\n LAO_CAI: 'VN90',\r\n YEN_BAI: 'VN70',\r\n TUYEN_QUANG: 'VN68',\r\n HA_GIANG: 'VN50',\r\n CAO_BANG: 'VN05',\r\n BAC_KAN: 'VN72',\r\n LANG_SON: 'VN39',\r\n HA_NAM: 'VN80',\r\n\r\n // Miền Trung (Region 2 - 16 tỉnh/thành)\r\n DA_NANG: 'VN78',\r\n THUA_THIEN_HUE: 'VN66',\r\n QUANG_NAM: 'VN84',\r\n QUANG_NGAI: 'VN63',\r\n BINH_DINH: 'VN46',\r\n PHU_YEN: 'VN61',\r\n KHANH_HOA: 'VN54',\r\n NINH_THUAN: 'VN60',\r\n BINH_THUAN: 'VN47',\r\n KON_TUM: 'VN55',\r\n GIA_LAI: 'VN49',\r\n DAK_LAK: 'VN88',\r\n DAK_NONG: 'VN91',\r\n LAM_DONG: 'VN23',\r\n QUANG_BINH: 'VN62',\r\n QUANG_TRI: 'VN64',\r\n\r\n // Miền Nam (Region 3 - 19 tỉnh/thành)\r\n HO_CHI_MINH: 'VN20',\r\n BINH_DUONG: 'VN75',\r\n DONG_NAI: 'VN43',\r\n BA_RIA_VUNG_TAU: 'VN45',\r\n LONG_AN: 'VN24',\r\n TIEN_GIANG: 'VN37',\r\n BEN_TRE: 'VN03',\r\n DONG_THAP: 'VN09',\r\n VINH_LONG: 'VN69',\r\n CAN_THO: 'VN87',\r\n HAU_GIANG: 'VN93',\r\n AN_GIANG: 'VN01',\r\n KIEN_GIANG: 'VN21',\r\n SOC_TRANG: 'VN65',\r\n BAC_LIEU: 'VN73',\r\n CA_MAU: 'VN77',\r\n TAY_NINH: 'VN33',\r\n BINH_PHUOC: 'VN76',\r\n TRA_VINH: 'VN67',\r\n} as const;\r\n\r\nexport type ZaloAdsProvinceCodeValue = typeof ZaloAdsProvinceCode[keyof typeof ZaloAdsProvinceCode];\r\n\r\n/**\r\n * Danh mục kiểu phân phối ngân sách quảng cáo (\"Cách phân phối\" trên giao diện Zalo Ads):\r\n * Trường dữ liệu lưu trữ tại: `Settings.DeliveryType` (kiểu số nguyên 0 hoặc 1).\r\n *\r\n * - STANDARD (0): Tiêu chuẩn (Paced Delivery)\r\n * Thuật toán Zalo Ads rải đều ngân sách xuyên suốt các khung giờ trong ngày/toàn lịch chạy\r\n * dựa theo lưu lượng thị trường và tỷ lệ giờ cao điểm. Tự động điều tiết hãm tốc độ cắn tiền\r\n * nếu phát hiện ngân sách tiêu xài quá nhanh. Phù hợp duy trì thương hiệu, ổn định chi phí CPA.\r\n *\r\n * - SPEED_UP / ACCELERATED (1): Tăng tốc (Uncapped Pacing)\r\n * Gỡ bỏ hoàn toàn bộ điều tiết tốc độ. Miễn là có phiên đấu giá (auction) phù hợp với giá thầu\r\n * và tệp đối tượng nhắm chọn, hệ thống sẽ phân phối tối đa ngay lập tức cho đến khi cạn kiệt ngân sách.\r\n * Phù hợp cho chiến dịch Flash Sale, sự kiện ngắn, hoặc cần tối đa hóa tiếp cận trong thời gian ngắn.\r\n *\r\n * ĐIỀU KIỆN NGẦM ĐỂ HIỂN THỊ TRÊN UI (hàm `shouldHaveDeliveryType` trong mã nguồn Angular):\r\n * 1. `Price.Type in [CPC (2), CPA (5)]`: Hình thức tính tiền phải là CPC hoặc CPA.\r\n * 2. `Price.LimitType === LIFE_TIME (1)`: Bắt buộc chọn ngân sách \"Toàn lịch chạy\" (không áp dụng cho ngân sách mỗi ngày).\r\n * 3. `validDaysRun(StartDate, EndDate) >= 2`: Thời gian chạy chiến dịch tối thiểu từ 2 ngày trở lên.\r\n */\r\nexport const ZaloAdsDeliveryType = {\r\n /** Tiêu chuẩn (0): Phân phối đồng đều nhất có thể theo giờ cao điểm (Standard). */\r\n STANDARD: 0,\r\n /** Tăng tốc (1): Phân phối nhanh nhất có thể để tối đa hóa tiếp cận (SpeedUp). */\r\n SPEED_UP: 1,\r\n /** Alias tương thích ngược cho SPEED_UP (1). */\r\n ACCELERATED: 1,\r\n} as const;\r\n\r\nexport type ZaloAdsDeliveryTypeValue = typeof ZaloAdsDeliveryType[keyof typeof ZaloAdsDeliveryType];\r\n\r\n/**\r\n * Danh mục phương thức phân phối ngân sách chi tiêu (`Settings.Price.SpendingMethod`):\r\n * - STANDARD (0): Tiêu chuẩn (rải đều ngân sách).\r\n * - FAST / ACCELERATED (1): Nhanh / Tăng tốc (ưu tiên thắng thầu và phân phối tối đa ngay lập tức).\r\n */\r\nexport const ZaloAdsSpendingMethod = {\r\n /** Tiêu chuẩn (0): Rải đều ngân sách xuyên suốt ngày. */\r\n STANDARD: 0,\r\n /** Tăng tốc (1): Phân phối nhanh, ưu tiên thắng thầu ngay khi có phiên đấu giá. */\r\n FAST: 1,\r\n /** Alias cho FAST (1). */\r\n ACCELERATED: 1,\r\n} as const;\r\n\r\nexport type ZaloAdsSpendingMethodValue = typeof ZaloAdsSpendingMethod[keyof typeof ZaloAdsSpendingMethod];\r\n\r\n/**\r\n * Danh mục phương thức tính tiền quảng cáo (`Settings.Price.Type`):\r\n * - CPM (1): Lượt hiển thị (áp dụng cho Display Ads hoặc tối ưu hiển thị).\r\n * - CPC (2): Lượt nhấn (Click) - Chuẩn cho Website Ads, Commerce Ads.\r\n * - CPI (3): Lượt cài đặt ứng dụng (App Install).\r\n * - CPF (4): Lượt quan tâm Official Account (Follow).\r\n * - CPA (5): Lượt liên hệ / chuyển đổi mục tiêu (Lead / Message).\r\n * - CPO (6): Lượt đặt hàng (Order).\r\n * - CPV (7): Lượt xem video hoàn tất (Complete View).\r\n * - CPD (8): Chi phí cố định theo ngày.\r\n * - CPV1S (9): Lượt xem video từ 1 giây.\r\n */\r\nexport const ZaloAdsPriceType = {\r\n CPM: 1,\r\n CPC: 2,\r\n CPI: 3,\r\n CPF: 4,\r\n CPA: 5,\r\n CPO: 6,\r\n CPV: 7,\r\n CPD: 8,\r\n CPV1S: 9,\r\n} as const;\r\n\r\nexport type ZaloAdsPriceTypeValue = typeof ZaloAdsPriceType[keyof typeof ZaloAdsPriceType];\r\n\r\n/**\r\n * Danh mục kiểu áp dụng ngân sách (`Settings.Price.LimitType`):\r\n * - LIFE_TIME (1): Toàn lịch chạy (ngân sách tổng cho toàn bộ thời gian chiến dịch, tối thiểu 600.000 VNĐ).\r\n * - DAILY (2): Mỗi ngày (ngân sách giới hạn theo từng ngày).\r\n */\r\nexport const ZaloAdsPriceLimitType = {\r\n /** Áp dụng ngân sách cho toàn lịch chạy (Life time budget). */\r\n LIFE_TIME: 1,\r\n /** Áp dụng ngân sách cho mỗi ngày (Daily budget). */\r\n DAILY: 2,\r\n} as const;\r\n\r\nexport type ZaloAdsPriceLimitTypeValue = typeof ZaloAdsPriceLimitType[keyof typeof ZaloAdsPriceLimitType];\r\n\r\n/**\r\n * Danh mục mã giao diện bố cục hiển thị mở rộng (`Settings.AdInfo.XTemplates`):\r\n * Checkbox \"Hiển thị nhiều hình ảnh\" trên UI Zalo Ads chỉ được bật khi mảng XTemplates\r\n * chứa đồng thời cả 42 (Carousel) và 43 (Album): [42, 43].\r\n */\r\nexport const ZaloAdsXTemplates = {\r\n /** Định dạng thẻ quay vòng lướt ngang nhiều hình ảnh. */\r\n CAROUSEL: 42,\r\n /** Định dạng bộ sưu tập album ảnh (lưới 4 ảnh). */\r\n ALBUM: 43,\r\n /** Định dạng video tự động phát trên Feed. */\r\n ZALO_VIDEO: 44,\r\n /** Định dạng ảnh dọc toàn màn hình. */\r\n PORTRAIT_IMAGE: 45,\r\n /** Định dạng ảnh đơn truyền thống (1024x533). */\r\n SINGLE_IMAGE: 46,\r\n /** Định dạng ảnh bìa cho quảng cáo video. */\r\n COVER_IMAGE_FOR_VIDEO_AD: 47,\r\n /** Định dạng ảnh vuông. */\r\n SQUARE_IMAGE: 48,\r\n /** Định dạng chú thích nội dung dài (tối đa 2.000 ký tự). */\r\n LONG_CAPTION: 49,\r\n} as const;\r\n\r\nexport type ZaloAdsXTemplatesValue = typeof ZaloAdsXTemplates[keyof typeof ZaloAdsXTemplates];\r\n\r\n/**\r\n * Danh mục mã tỉ lệ cắt ảnh chuẩn (`Settings.Image.ExtraImgs[i].Crops[j].Ratio`):\r\n * Ma trận 8 lát cắt bắt buộc cho bộ 4 ảnh Album + Carousel:\r\n * - Ảnh 0 (Ảnh bìa): Bắt buộc đủ 3 lát cắt: RATIO_4_3 (1), RATIO_2_1 (2 - Bìa Album), RATIO_1_1 (4).\r\n * (Nếu thiếu RATIO_2_1, UI sẽ báo lỗi: \"Thiếu ảnh cắt tỉ lệ album\").\r\n * - Ảnh 1: Bắt buộc 2 lát cắt: RATIO_4_3 (1), RATIO_1_1 (4).\r\n * - Ảnh 2: Bắt buộc 2 lát cắt: RATIO_4_3 (1), RATIO_1_1 (4).\r\n * - Ảnh 3: Bắt buộc 1 lát cắt: RATIO_1_1 (4).\r\n */\r\nexport const ZaloAdsImageRatio = {\r\n /** Tỉ lệ 16:9 (1024x576 px - Video / Banner phong cảnh). */\r\n RATIO_16_9: 0,\r\n /** Tỉ lệ 4:3 (1024x768 px - Ảnh phụ Album / Carousel). */\r\n RATIO_4_3: 1,\r\n /** Tỉ lệ 2:1 (1024x512 px - ẢNH BÌA NGANG BẮT BUỘC CỦA ALBUM). */\r\n RATIO_2_1: 2,\r\n /** Tỉ lệ 3:2. */\r\n RATIO_3_2: 3,\r\n /** Tỉ lệ 1:1 (1024x1024 px - Ảnh vuông). */\r\n RATIO_1_1: 4,\r\n} as const;\r\n\r\nexport type ZaloAdsImageRatioValue = typeof ZaloAdsImageRatio[keyof typeof ZaloAdsImageRatio];\r\n\r\n/**\r\n * Danh mục cờ và nguồn dữ liệu tối ưu hóa chuyển đổi (`UseConversion`):\r\n * - NOT_USE (0): Không chọn pixel - Tắt tối ưu hóa chuyển đổi. Hệ thống chỉ phân phối theo giá thầu lượt click (CPC) hoặc hiển thị (CPM) mà không quan tâm hành vi người dùng trên website.\r\n * - USE (1): Pixel của tôi - Nguồn dữ liệu từ Zalo Pixel cá nhân do nhà quảng cáo tự chèn mã JavaScript (window.za(...)) vào mã nguồn website (ví dụ: https://redai.vn). Bắt buộc đi kèm `ConversionId` từ GET /api/conversion/all.\r\n * - LADI_PAGE (2): Pixel liên kết Ladipage - Dành cho Landing Page dựng bằng nền tảng LadiPage đã tích hợp Zalo Pixel sẵn. Hệ thống tự động nhận diện sự kiện chuẩn mà không cần tạo conversion thủ công.\r\n * - MINI_APP (3): Zalo Mini App - Dành cho các chiến dịch hướng người dùng vào ứng dụng Zalo Mini App.\r\n * - USE_OFF (-1): Cờ lưu nháp khi tạm thời tắt hoặc hủy chọn Pixel cá nhân.\r\n * - LADI_PAGE_OFF (-2): Cờ lưu nháp khi tắt liên kết Pixel Ladipage.\r\n * - MINI_APP_OFF (-3): Cờ lưu nháp khi tắt liên kết Zalo Mini App.\r\n */\r\nexport const ZaloAdsUseConversion = {\r\n /** Không chọn pixel (0): Tắt tối ưu hóa chuyển đổi. */\r\n NOT_USE: 0,\r\n /** Pixel của tôi (1): Zalo Pixel tự host chèn script, cần kèm ConversionId. */\r\n USE: 1,\r\n /** Pixel liên kết Ladipage (2): Landing Page đối tác LadiPage. */\r\n LADI_PAGE: 2,\r\n /** Zalo Mini App (3): Ứng dụng Zalo Mini App. */\r\n MINI_APP: 3,\r\n /** Tạm thời tắt Pixel của tôi (-1): Cờ lưu nháp. */\r\n USE_OFF: -1,\r\n /** Tạm thời tắt Pixel Ladipage (-2): Cờ lưu nháp. */\r\n LADI_PAGE_OFF: -2,\r\n /** Tạm thời tắt Pixel Mini App (-3): Cờ lưu nháp. */\r\n MINI_APP_OFF: -3,\r\n} as const;\r\n\r\nexport type ZaloAdsUseConversionValue = typeof ZaloAdsUseConversion[keyof typeof ZaloAdsUseConversion];\r\n\r\n\r\nexport interface ZaloAdsAdMutationResultDto {\r\n AdId?: number;\r\n CampaignId?: number;\r\n Status?: number;\r\n RowVersion?: number;\r\n}\r\n\r\n/** Tham số yêu cầu nhân bản mẫu quảng cáo (POST /zaapi/DuplicateAd) */\r\nexport interface ZaloAdsDuplicateAdRequest {\r\n /** ID mẫu quảng cáo gốc cần nhân bản (bắt buộc). */\r\n adid?: number;\r\n /** Alias cho adid. */\r\n adId?: number;\r\n}\r\n\r\n/** Kết quả phản hồi khi nhân bản mẫu quảng cáo */\r\nexport interface ZaloAdsDuplicateAdResponse {\r\n /** Mã trạng thái: 0 = Thành công, khác 0 = Lỗi */\r\n code: number;\r\n /** Chuỗi thông báo kết quả (chứa ID của Ad mới tạo) */\r\n msg?: string;\r\n /** ID số nguyên của Ad mới vừa được nhân bản */\r\n data: number;\r\n}\r\n\r\nexport interface ZaloAdsCampaignCreatePayloadDto {\r\n name: string;\r\n campaignType: number;\r\n pageId: number;\r\n productId: number;\r\n targetUrl?: string;\r\n articleId?: number;\r\n adtype: number;\r\n budgetType: number;\r\n budgetlimit: number;\r\n limitType: number;\r\n campaignObjective: number;\r\n campaignId: number;\r\n adId: number;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Commerce (Shop) */\r\nexport interface ZaloAdsCreateCommerceCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account (OA ID) liên kết (bắt buộc > 0) */\r\n pageId: number;\r\n /** ID sản phẩm Zalo Shop liên kết (tùy chọn; mặc định -1 nếu không gắn) */\r\n productId?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Display */\r\nexport interface ZaloAdsCreateDisplayCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo OA (tùy chọn; mặc định -1) */\r\n pageId?: number;\r\n /** URL trang đích của quảng cáo (tùy chọn) */\r\n targetUrl?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Website */\r\nexport interface ZaloAdsCreateWebsiteCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** URL trang đích của website (bắt buộc) */\r\n targetUrl: string;\r\n /** ID Zalo OA (tùy chọn; không bắt buộc) */\r\n pageId?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Biểu mẫu (Lead Form) */\r\nexport interface ZaloAdsCreateFormCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account sở hữu Form (bắt buộc > 0) */\r\n pageId: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Tin nhắn (Message) */\r\nexport interface ZaloAdsCreateMessageCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account nhận tin nhắn (bắt buộc > 0) */\r\n pageId: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Tăng người quan tâm Zalo Official Account */\r\nexport interface ZaloAdsCreateOfficialAccountCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account cần tăng lượt quan tâm (bắt buộc > 0) */\r\n pageId: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Bài viết OA */\r\nexport interface ZaloAdsCreateArticleCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** ID Zalo Official Account sở hữu bài viết (bắt buộc > 0) */\r\n pageId: number;\r\n /** ID bài viết trên Zalo OA lấy từ getOwnedArticles (bắt buộc > 0) */\r\n articleId: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Payload tạo chiến dịch Quảng cáo Video */\r\nexport interface ZaloAdsCreateVideoCampaignPayloadDto {\r\n /** Tên hiển thị của chiến dịch */\r\n name: string;\r\n /** URL trang đích của website khi click vào video (bắt buộc) */\r\n targetUrl: string;\r\n /** ID Zalo OA (tùy chọn; không bắt buộc) */\r\n pageId?: number;\r\n [key: string]: unknown;\r\n}\r\n\r\n\r\nexport interface ZaloAdsFormSectionTableItemDto {\r\n key: string;\r\n value: string;\r\n}\r\n\r\nexport interface ZaloAdsFormSectionImageItemDto {\r\n url: string;\r\n title?: string;\r\n caption?: string;\r\n}\r\n\r\nexport interface ZaloAdsFormSectionContentDto {\r\n title?: string;\r\n description?: string;\r\n table?: Array<ZaloAdsFormSectionTableItemDto>;\r\n images?: Array<ZaloAdsFormSectionImageItemDto>;\r\n}\r\n\r\nexport interface ZaloAdsFormSectionDto {\r\n type: \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | number;\r\n title: string;\r\n expand: boolean;\r\n disable: boolean;\r\n content: ZaloAdsFormSectionContentDto;\r\n}\r\n\r\nexport interface ZaloAdsFormQuestionUiDto {\r\n icon?: string;\r\n title?: string;\r\n removable?: boolean;\r\n}\r\n\r\nexport interface ZaloAdsFormAnswerDto {\r\n id?: string;\r\n type: \"2\" | \"7\" | \"13\" | number;\r\n value?: string | null;\r\n priority?: number;\r\n placeHolder?: string;\r\n}\r\n\r\nexport interface ZaloAdsFormQuestionDto {\r\n id?: string;\r\n ui?: ZaloAdsFormQuestionUiDto;\r\n type: \"1\" | number;\r\n title: string;\r\n answers: Array<ZaloAdsFormAnswerDto>;\r\n groupIdx?: number;\r\n priority?: number;\r\n isRequired: boolean;\r\n editDisabled?: boolean;\r\n}\r\n\r\nexport interface ZaloAdsCreateFormPayloadDto {\r\n id?: string;\r\n oaId: string;\r\n formName: string;\r\n title?: string;\r\n description?: string;\r\n coverPhoto?: string;\r\n thanks?: string;\r\n gotoText?: string;\r\n gotoActionType?: number;\r\n website?: string;\r\n phone?: string;\r\n submitTitle?: string;\r\n reviewSubmit?: boolean;\r\n oaConsentWidget?: boolean;\r\n useCustomConsent?: boolean;\r\n sections?: Array<ZaloAdsFormSectionDto>;\r\n questions: Array<ZaloAdsFormQuestionDto>;\r\n}\r\n\r\n/** Cập nhật quảng cáo Video; service tự JSON.stringify data rồi gửi form-urlencoded. */\r\nexport class ZaloAdsUpdateVideoAdRequest {\r\n data!: ZaloAdsAdUpdatePayloadDto | string;\r\n est?: string;\r\n isBoostAd?: 0 | 1;\r\n stt?: number;\r\n}\r\n\r\nexport class ZaloAdsUpdateVideoAdResponse {\r\n code!: number;\r\n msg!: string;\r\n data?: ZaloAdsAdMutationResultDto;\r\n}\r\n\r\n/** Lấy danh sách hoặc Flow cụ thể của một Official Account. Dùng flowId khi cần đọc một Flow trước khi cập nhật, hoặc offset và limit khi duyệt danh sách. */\r\nexport type ZaloAdsListFlowsByOfficialAccountRequest = {\r\n /** ID Official Account cần lấy Flow. */\r\n oaId: number;\r\n /** Số Flow tối đa cần trả về. */\r\n limit: number;\r\n /** Vị trí bắt đầu, tính từ 0, khi liệt kê Flow. Không cần gửi khi dùng flowId. */\r\n offset?: number;\r\n /** ID Flow cụ thể cần lấy. Khi gửi tham số này, response extend có thể có index. */\r\n flowId?: number;\r\n};\r\n\r\nexport type ZaloAdsListFlowsByOfficialAccountResponse = {\r\n code: number;\r\n data: Array<{\r\n id: number;\r\n name: string;\r\n createdTime: number;\r\n modified: number;\r\n status: number;\r\n isDraft: boolean;\r\n editable: number;\r\n messages: Array<{\r\n type: number;\r\n text: string;\r\n url?: string;\r\n buttons: Array<{ type: number; text: string; editable: boolean; url?: string; phone?: string; messages: Array<ZaloAdsFlowChildMessageDto> }>;\r\n elements: Array<{ type?: number; title?: string; url?: string }>;\r\n stepId: number;\r\n }>;\r\n }>;\r\n extend: { total: number; index?: number };\r\n};\r\n\r\n/**\r\n * Danh mục mã trạng thái chiến dịch trên Zalo Ads (POST /api/campaign/change-status):\r\n * - OFF (0): Tắt / Dừng chiến dịch (Inactive).\r\n * - ACTIVE (1): Bật / Tiếp tục / Kích hoạt lại chiến dịch (Active).\r\n * - PAUSED (2): Tạm dừng chiến dịch (Lưu ý: Nếu chiến dịch nháp chưa có QC hoạt động sẽ ném HTTP 500).\r\n * - DELETED (-2): Xóa vĩnh viễn chiến dịch.\r\n */\r\nexport const ZaloAdsCampaignStatus = {\r\n OFF: 0,\r\n ACTIVE: 1,\r\n PAUSED: 2,\r\n DELETED: -2,\r\n} as const;\r\n\r\nexport type ZaloAdsCampaignStatusValue = typeof ZaloAdsCampaignStatus[keyof typeof ZaloAdsCampaignStatus];\r\n\r\n/** Thay đổi trạng thái của một chiến dịch Zalo Ads (Bật / Tắt / Tạm dừng / Xóa) theo mã trạng thái được chỉ định (`POST /api/campaign/change-status`). */\r\nexport type ZaloAdsChangeCampaignStatusRequest = {\r\n /** Mã trạng thái cần áp dụng: 1 = Bật lại, 0 = Tắt, 2 = Tạm dừng, -2 = Xóa chiến dịch. */\r\n status: 0 | 1 | 2 | -2 | number;\r\n /** ID chiến dịch cần đổi trạng thái. */\r\n campaignId: number;\r\n};\r\n\r\nexport type ZaloAdsChangeCampaignStatusResponse = {\r\n /** Thông điệp kết quả từ Zalo Ads (ví dụ: 'Thành công', 'Xóa chiến dịch thành công.'). */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị thao tác thành công. */\r\n code: number;\r\n /** Trạng thái mới của chiến dịch sau khi thay đổi (1: Đã bật, 0: Đã tắt). */\r\n data?: number;\r\n};\r\n\r\n/** Tạo audience tùy chỉnh từ điều kiện targeting, tệp nguồn hoặc audience loại trừ/bao gồm đã chọn. Đây là mutation tool thuộc lane zalo-ads-audience; dùng khi cấu trúc targeting và quyền xử lý dữ liệu đã được xác nhận. Targeting được gửi dưới dạng chuỗi JSON theo contentSchema. */\r\nexport type ZaloAdsCreateCustomAudienceRequest = {\r\n /** Tên audience tùy chỉnh. */\r\n name: string;\r\n /** Loại custom audience; đã quan sát 1 và 3, không giới hạn enum vì chưa đủ bằng chứng. */\r\n caType: number;\r\n /** Chuỗi JSON targeting. Xem contentSchema để biết cấu trúc Location, tuổi, nền tảng, targeting nâng cao và audience bao gồm/loại trừ. */\r\n targeting: string;\r\n};\r\n\r\nexport type ZaloAdsCreateCustomAudienceResponse = {\r\n msg: string;\r\n /** ID audience vừa tạo; cùng giá trị với data.CustomAudienceId trong phản hồi đã quan sát. */\r\n caId: number;\r\n code: number;\r\n /** Một audience tùy chỉnh trong Zalo Ads. */\r\n data: {\r\n /** Tên audience. */\r\n Name: string;\r\n /** Loại audience. */\r\n Type: number;\r\n /** Loại quảng cáo liên quan, khi API trả về. */\r\n AdType?: number;\r\n /** ID OA/trang liên quan, khi API trả về. */\r\n PageId?: number;\r\n /** Thời điểm tạo dạng Unix timestamp theo giây. */\r\n Created?: number;\r\n /** ID thành viên sở hữu hoặc tạo audience, khi API trả về. */\r\n MemberId?: number;\r\n /** Thiết lập bổ sung của audience. */\r\n Settings?: string;\r\n /** ID thành viên tạo audience, khi API trả về. */\r\n CreatedBy?: number;\r\n /** Chuỗi JSON mô tả tệp nguồn và cấu hình targeting. */\r\n Targeting?: string;\r\n /** Loại chiến dịch liên quan, khi API trả về. */\r\n CampaignType?: number;\r\n /** ID audience tùy chỉnh; dùng cho thao tác xóa hoặc liên kết audience vào quảng cáo. */\r\n CustomAudienceId: number;\r\n };\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo E-commerce (Commerce) trên Zalo Ads (campaignType = 9). Service tự JSON.stringify nếu truyền object. */\r\nexport type ZaloAdsCreateEcommerceCampaignRequest = {\r\n /** Cấu hình chiến dịch Commerce (object hoặc chuỗi JSON): { name, campaignType: 9, pageId, productId, targetUrl, adtype: -1, budgetType: 1, budgetlimit, limitType: 2, campaignObjective: 0, campaignId: 0, adId: 0 }. */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateEcommerceCampaignResponse = {\r\n msg: string;\r\n code: number;\r\n data?: {\r\n adId?: number;\r\n campaignId?: number;\r\n campaign_id?: number;\r\n };\r\n};\r\n\r\n/** Tạo form gắn Official Account, câu hỏi thu thập thông tin, nội dung section và màn hình cảm ơn. Đây là thao tác mutation; form mới sẽ xuất hiện trong danh sách biểu mẫu của OA. */\r\nexport type ZaloAdsCreateFormRequest = {\r\n /** Cấu hình biểu mẫu thu thập thông tin khách hàng hoặc chuỗi JSON.stringify(CreateFormPayload). */\r\n data: ZaloAdsCreateFormPayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateFormResponse = {\r\n code: \"0\" | 0;\r\n data: {\r\n /** ID form mới tạo, dùng để gắn vào cấu hình quảng cáo. */\r\n id: string;\r\n oaId: string;\r\n ownId?: string;\r\n title?: string;\r\n status: number;\r\n /** Unix epoch giây. */\r\n createAt: number;\r\n formName: string;\r\n sections: Array<ZaloAdsFormSectionDto>;\r\n questions: Array<ZaloAdsFormQuestionDto>;\r\n /** Unix epoch giây. */\r\n updatedAt: number;\r\n description?: string;\r\n };\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo biểu mẫu (Form) trên Zalo Ads (campaignType = 8). Service tự JSON.stringify nếu truyền object. */\r\nexport type ZaloAdsCreateFormCampaignRequest = {\r\n /** Cấu hình chiến dịch biểu mẫu (object hoặc chuỗi JSON). */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateFormCampaignResponse = {\r\n msg: string;\r\n code: number;\r\n data?: {\r\n adId: number;\r\n campaignId: number;\r\n };\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Tin nhắn trên Zalo Ads (campaignType = 10). Service tự JSON.stringify nếu truyền object. */\r\nexport type ZaloAdsCreateMessageCampaignRequest = {\r\n /** Cấu hình chiến dịch Tin nhắn (object hoặc chuỗi JSON). */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateMessageCampaignResponse = {\r\n code?: number;\r\n msg?: string;\r\n data?: {\r\n adId?: number;\r\n campaignId?: number;\r\n campaign_id?: number;\r\n };\r\n error?: number;\r\n message?: string;\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Zalo Official Account (campaignType = 2). Service tự JSON.stringify nếu truyền object. */\r\nexport type ZaloAdsCreateOfficialAccountCampaignRequest = {\r\n /** Cấu hình chiến dịch Official Account (object hoặc chuỗi JSON). */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateOfficialAccountCampaignResponse = {\r\n msg: string;\r\n code: number;\r\n data?: {\r\n adId?: number;\r\n campaignId?: number;\r\n campaign_id?: number;\r\n };\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Bài viết trên Zalo Ads (campaignType = 4). Service tự JSON.stringify payload này vào field form data. */\r\nexport class ZaloAdsCreatePostCampaignRequest {\r\n /** Cấu hình chiến dịch Bài viết (object hoặc chuỗi JSON). */\r\n data!: ZaloAdsCampaignCreatePayloadDto | string;\r\n}\r\n\r\nexport class ZaloAdsCreatePostCampaignResponse {\r\n code!: number;\r\n /** Chuỗi ID quảng cáo mới trong response Zalo Ads. */\r\n msg!: string;\r\n data!: { adId: number; campaignId: number };\r\n}\r\n\r\nexport interface ZaloAdsConversionElementSelectorDto {\r\n class?: Array<string>;\r\n id?: string;\r\n tag?: string;\r\n}\r\n\r\n/** Tạo conversion để đo lường hành động trên trang đích Zalo Ads. Đây là mutation tool thuộc lane zalo-ads-conversion; dùng sau khi đã xác định nhãn conversion, URL trang đích và quy tắc sự kiện click hoặc URL. Chỉ gọi khi cần tạo mới vì mỗi lần gọi sẽ phát sinh một conversion trong tài khoản quảng cáo. */\r\nexport type ZaloAdsCreateConversionRequest = {\r\n /** Tên conversion, phải duy nhất trong tài khoản quảng cáo (2–180 ký tự). */\r\n name: string;\r\n /** Nhãn conversion: 10 khách hàng tiềm năng, 11 mua hàng, 5 liên hệ, 4 đăng ký, 9 bắt đầu thanh toán, 2 thêm giỏ hàng, 19 khác. */\r\n labelId: 2 | 4 | 5 | 9 | 10 | 11 | 19 | number;\r\n /** Kiểu khớp URL: 1 hoặc 2. */\r\n urlType: 1 | 2 | number;\r\n /** Bộ chọn phần tử click; ví dụ [{\"class\":[\"btn\"]}]. Dùng mảng rỗng khi không áp dụng. */\r\n elements: Array<ZaloAdsConversionElementSelectorDto>;\r\n /** Từ khóa URL cần ghi nhận; dùng mảng rỗng khi không áp dụng. */\r\n keywords: Array<string>;\r\n /** Danh sách ID nút theo cấu hình click; dùng mảng rỗng khi không áp dụng. */\r\n buttonIds: Array<string>;\r\n /** URL trang đích có Zalo Pixel. */\r\n landingPage: string;\r\n};\r\n\r\nexport interface ZaloAdsConversionItemDto {\r\n conversionId: number;\r\n name: string;\r\n labelId: number;\r\n urlType?: number;\r\n landingPage?: string;\r\n status?: number;\r\n created?: number;\r\n memberId?: number;\r\n}\r\n\r\nexport type ZaloAdsCreateConversionResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: ZaloAdsConversionItemDto | number;\r\n};\r\n\r\n/** Xóa một conversion đã cấu hình trên Zalo Ads. Đây là destructive tool thuộc lane zalo-ads-conversion; chỉ dùng sau khi đối chiếu ID từ danh sách conversion và xác nhận cần dừng ghi nhận dữ liệu mới. Không dùng để tạm dừng hoặc chỉnh sửa conversion vì thao tác không thể khôi phục. */\r\nexport type ZaloAdsDeleteConversionRequest = {\r\n /** ID conversion cần xóa, lấy từ ZaloAds_getApiConversionAll hoặc trang chi tiết conversion. Thao tác không thể khôi phục. */\r\n conversionId: number;\r\n};\r\n\r\nexport type ZaloAdsDeleteConversionResponse = {\r\n /** Thông báo trạng thái từ Zalo Ads. */\r\n msg: string;\r\n /** Mã thành công đã capture: 0. */\r\n code: 0 | number;\r\n};\r\n\r\n/** Xóa một audience tùy chỉnh theo ID trên Zalo Ads. Đây là destructive tool thuộc lane zalo-ads-audience; chỉ dùng sau khi xác nhận đúng audience và hệ quả không thể hoàn tác. Dùng CustomAudienceId từ tool danh sách hoặc tạo audience. */\r\nexport type ZaloAdsDeleteCustomAudienceRequest = {\r\n /** ID audience tùy chỉnh cần xóa, lấy từ CustomAudienceId của tool danh sách hoặc tool tạo audience. */\r\n customAudienceId: number;\r\n};\r\n\r\nexport type ZaloAdsDeleteCustomAudienceResponse = {\r\n /** Thông điệp kết quả từ Zalo Ads. */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n};\r\n\r\n/** Lấy chi tiết một quảng cáo theo ID (GET /zaapi/getAdFromAdId?adId=...&v=2&newWard=true). */\r\nexport type ZaloAdsGetAdByIdRequest = {\r\n /** ID mẫu quảng cáo cần lấy chi tiết (query param `adId`). */\r\n adId?: number | string;\r\n /** Phiên bản schema cấu trúc dữ liệu trả về (mặc định: 2). */\r\n v?: number | string;\r\n /** Cờ kích hoạt định dạng nhắm chọn cấp Phường/Xã mới (mặc định: true). */\r\n newWard?: boolean | string;\r\n};\r\n\r\n/** Thông tin chiến dịch mở rộng đính kèm trong phản hồi getAdById */\r\nexport interface ZaloAdsCampaignDetailExtendDto {\r\n CampaignId: number;\r\n MemberId: number;\r\n Name: string;\r\n Type: number;\r\n StartDate: number;\r\n EndDate: number;\r\n Status: number;\r\n Modified?: number;\r\n Created?: number;\r\n AdtimaCampaignId?: number;\r\n AdtimaOrderId?: number;\r\n ReadOnly?: number;\r\n CrmCampaignId?: string;\r\n Settings?: {\r\n BudgetLimit?: {\r\n Type?: number;\r\n Amount?: number;\r\n LimitType?: number;\r\n };\r\n };\r\n CreatedBy?: number;\r\n AgencyId?: number;\r\n Username?: string;\r\n ViewType?: string;\r\n}\r\n\r\nexport type ZaloAdsGetAdByIdResponse = {\r\n code?: number;\r\n msg?: string;\r\n data?: ZaloAdsAdUpdatePayloadDto;\r\n extend?: ZaloAdsCampaignDetailExtendDto;\r\n flags?: {\r\n IsOaValidForAd?: boolean;\r\n [key: string]: unknown;\r\n };\r\n report?: number[] | Record<string, number>;\r\n viewdata?: unknown[];\r\n AdId?: number;\r\n CampaignId?: number;\r\n MemberId?: number;\r\n RowVersion?: number;\r\n AdName?: string;\r\n Type?: number;\r\n Settings?: ZaloAdsAdSettingsDto;\r\n Status?: number;\r\n StartDate?: number;\r\n EndDate?: number;\r\n ZaloFlowId?: number;\r\n ZaloPageId?: number;\r\n ZaloFormId?: string;\r\n ZaloFeedId?: string | number;\r\n MiniPageId?: number;\r\n UseConversion?: ZaloAdsUseConversionValue | number;\r\n ConversionId?: number;\r\n Report?: Record<string, number>;\r\n};\r\n\r\n\r\n/** Lấy lịch sử thao tác và các hạng mục thay đổi của một quảng cáo Zalo Ads. Đây là detail tool thuộc lane quản lý quảng cáo; dùng để kiểm tra ai đã tạo hoặc điều chỉnh nội dung, đối tượng, hình/video và conversion. Mỗi bản ghi nêu người thực hiện, thời điểm và danh sách thay đổi chính hoặc bổ sung. */\r\nexport type ZaloAdsGetAdChangeLogRequest = {\r\n /** ID quảng cáo cần xem lịch sử. Có thể lấy từ kết quả tạo quảng cáo hoặc dữ liệu chi tiết quảng cáo. */\r\n adId: number;\r\n /** Mã loại nhật ký (mặc định: 1). */\r\n type?: number;\r\n};\r\n\r\nexport type ZaloAdsGetAdChangeLogResponse = {\r\n /** Thông điệp kết quả từ Zalo Ads. */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị thành công. */\r\n code: number;\r\n /** Danh sách bản ghi lịch sử, sắp xếp theo quy ước của Zalo Ads. */\r\n data: Array<{\r\n /** ID quảng cáo được thay đổi; trùng với adId đã truy vấn. */\r\n ItemId: number;\r\n /** Tên người dùng đã thực hiện thao tác. */\r\n Member: string;\r\n /** Các thay đổi nghiệp vụ chính, ví dụ tạo mới, đối tượng hoặc nội dung quảng cáo. */\r\n Content: Array<string>;\r\n /** Thời điểm ghi nhận thay đổi, Unix timestamp tính bằng giây. */\r\n Created: number;\r\n /** Các thay đổi bổ sung, ví dụ hiển thị nhiều ảnh, video hoặc conversion. */\r\n ExtraContent: Array<string>;\r\n }>;\r\n};\r\n\r\n/** Lấy các lựa chọn nhắm chọn nâng cao có thể dùng khi thiết lập quảng cáo. Đây là entry tool thuộc lane zalo-ads-targeting; dùng để xây dựng bộ tiêu chí audience trước bước ước lượng hoặc cập nhật quảng cáo. */\r\nexport type ZaloAdsGetApiAdGetlistadadvancetargetingRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiAdGetlistadadvancetargetingResponse = {\r\n code: number;\r\n data: Array<{\r\n id: number;\r\n /** Các nhánh targeting con; có thể lồng nhiều cấp. */\r\n subs?: Array<{\r\n id: number;\r\n subs?: Array<{\r\n id: number;\r\n displayName: string;\r\n }>;\r\n displayName: string;\r\n }>;\r\n displayName: string;\r\n }>;\r\n};\r\n\r\nexport interface ZaloAdsAccessorItemDto {\r\n /** ID định danh của thành viên trên Zalo Ads (ví dụ: 257887336). */\r\n memberId: number;\r\n /** Tên hiển thị của thành viên. */\r\n memberName: string;\r\n /** Số điện thoại của thành viên (định dạng 84...). */\r\n memberPhone?: string;\r\n /** URL ảnh đại diện của thành viên. */\r\n memberAvatar?: string;\r\n /** Cấp độ quyền truy cập (0 = Chủ tài khoản gốc). */\r\n accessLevel: number;\r\n}\r\n\r\nexport interface ZaloAdsAccountAgencyInfoDto {\r\n /** Mã định danh của Agency (ví dụ: 277596648). */\r\n agencyId: number;\r\n /** ID tài khoản chủ sở hữu Agency (ví dụ: 257887336). */\r\n ownerId: number;\r\n /** Tên pháp nhân hoặc tên hiển thị của Agency. */\r\n agencyName: string;\r\n /** Thời điểm khởi tạo Agency, định dạng Unix timestamp tính bằng giây. */\r\n created?: number;\r\n /** Cấp độ quyền của tài khoản hiện tại trong Agency (ví dụ: 9 = Chủ sở hữu Agency). */\r\n accessLevel: number;\r\n}\r\n\r\n/** Lấy danh sách tài khoản hoặc thành viên có quyền truy cập/tạo chiến dịch trên tài khoản quảng cáo hiện tại (dùng cho bộ lọc người tạo hoặc chuyển đổi ngữ cảnh tài khoản). Đây là entry tool thuộc lane zalo-ads-account; hỗ trợ tham số isShowAll (0 hoặc 1) và trả về danh sách personalAccessors, agencyInfo, agencyAccessors. */\r\nexport type ZaloAdsGetApiBaAccountAllaccessorsRequest = {\r\n /** Cờ hiển thị toàn bộ danh sách người truy cập (0 = Chỉ hiển thị mặc định/đang hoạt động, 1 = Hiển thị tất cả). Mặc định giao diện Zalo Ads truyền 0. */\r\n isShowAll?: 0 | 1 | number;\r\n};\r\n\r\nexport type ZaloAdsGetApiBaAccountAllaccessorsResponse = {\r\n /** Mã kết quả (0 = Thành công). */\r\n code: number;\r\n /** Thông điệp trạng thái (ví dụ: 'success'). */\r\n msg?: string;\r\n data: {\r\n /** Danh sách thành viên truy cập cấp tài khoản cá nhân (bao gồm chủ tài khoản với accessLevel = 0). */\r\n personalAccessors: Array<ZaloAdsAccessorItemDto>;\r\n /** Thông tin Agency liên kết (nếu có). */\r\n agencyInfo?: ZaloAdsAccountAgencyInfoDto;\r\n /** Danh sách thành viên thuộc Agency có quyền truy cập tài khoản khách hàng này (nếu có). */\r\n agencyAccessors?: Array<ZaloAdsAccessorItemDto>;\r\n };\r\n};\r\n\r\nexport interface ZaloAdsGrantedMemberItemDto {\r\n /** ID định danh của thành viên trên Zalo Ads (ví dụ: 330114198). */\r\n memberId: number;\r\n /** Tên hiển thị của thành viên. */\r\n memberName: string;\r\n /** Số điện thoại liên hệ của thành viên (định dạng 84...). */\r\n memberPhone?: string;\r\n /** URL ảnh đại diện của thành viên. */\r\n memberAvatar?: string;\r\n /** Cấp độ phân quyền truy cập của thành viên (ví dụ: 1 = Quản trị viên, 2 = Nhà quảng cáo, 3 = Người phân tích/Xem báo cáo). */\r\n accessLevel: number;\r\n}\r\n\r\n/** Lấy danh sách toàn bộ thành viên đã được cấp quyền truy cập trong tài khoản quảng cáo cá nhân và Agency hiện tại. Đây là entry tool thuộc lane zalo-ads-account; dùng để kiểm tra thông tin Agency (agencyInfo), danh sách thành viên được cấp quyền cấp cá nhân (personalGrantedAccessMembers) và cấp Agency (agencyGrantedAccessMembers) trước khi phối hợp quản trị. */\r\nexport type ZaloAdsGetApiBaAccountAllgrantedmembersRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiBaAccountAllgrantedmembersResponse = {\r\n /** Mã kết quả (0 = Thành công). */\r\n code: number;\r\n /** Thông điệp trạng thái (ví dụ: 'success'). */\r\n msg?: string;\r\n data: {\r\n /** Danh sách thành viên được cấp quyền truy cập ở cấp tài khoản cá nhân. */\r\n personalGrantedAccessMembers: Array<ZaloAdsGrantedMemberItemDto>;\r\n /** Thông tin đơn vị Agency quản lý tài khoản (nếu tài khoản là Agency hoặc thuộc Agency). */\r\n agencyInfo?: ZaloAdsAccountAgencyInfoDto;\r\n /** Danh sách nhân sự/thành viên thuộc Agency được cấp quyền truy cập. */\r\n agencyGrantedAccessMembers: Array<ZaloAdsGrantedMemberItemDto>;\r\n };\r\n};\r\n\r\nexport interface ZaloAdsAgencyEmployeeItemDto {\r\n /** ID của agency quản lý. */\r\n agencyId: number;\r\n /** ID tài khoản thành viên của nhân viên. */\r\n memberId: number;\r\n /** Họ và tên nhân viên. */\r\n memberName: string;\r\n /** URL ảnh đại diện của nhân viên. */\r\n memberAvatar?: string;\r\n /** Số điện thoại của nhân viên. */\r\n memberPhone?: string;\r\n /** Cấp bậc quyền hạn trong agency (ví dụ: 9 = Quản trị viên/Chủ sở hữu, 8 = Nhân viên quản trị). */\r\n accessLevel: number;\r\n /** Số lượng khách hàng/tài khoản mà nhân viên này được phân công quản lý. */\r\n numberOfGrantedAccessMembers?: number;\r\n /** Thời điểm tham gia agency, Unix timestamp tính bằng giây. */\r\n joinDate?: number;\r\n}\r\n\r\n/** Lấy danh sách nhân viên trực thuộc Agency trên Zalo Ads cùng cấp bậc phân quyền và avatar. */\r\nexport type ZaloAdsGetApiBaAgencyEmployeesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiBaAgencyEmployeesResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsAgencyEmployeeItemDto>;\r\n};\r\n\r\n/** Lấy danh sách nguồn hoặc sự kiện chuyển đổi đã cấu hình. Đây là entry tool thuộc lane zalo-ads-conversion; dùng khi chọn conversion để đo lường hoặc tối ưu chiến dịch. */\r\nexport type ZaloAdsGetApiConversionAllRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiConversionAllResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsConversionItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsStandardEventItemDto {\r\n id: number;\r\n name: string;\r\n code?: string;\r\n description?: string;\r\n}\r\n\r\n/** Lấy danh mục sự kiện chuyển đổi chuẩn mà Zalo Ads hỗ trợ. Đây là helper tool thuộc lane zalo-ads-conversion; dùng khi ánh xạ mục tiêu đo lường vào event chuẩn. */\r\nexport type ZaloAdsGetApiConversionStandardEventsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiConversionStandardEventsResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsStandardEventItemDto>;\r\n};\r\n\r\n/** Lấy danh sách audience tùy chỉnh có thể dùng để nhắm chọn. Đây là entry tool thuộc lane zalo-ads-audience; dùng để chọn, kiểm tra hoặc lấy CustomAudienceId trước khi liên kết hay xóa audience. */\r\nexport type ZaloAdsGetApiCustomAudienceAllRequest = {\r\n /** Bật cách phân loại địa giới hành chính mới khi lấy audience. */\r\n newWard?: boolean;\r\n};\r\n\r\nexport type ZaloAdsGetApiCustomAudienceAllResponse = {\r\n msg: string;\r\n code: number;\r\n /** Các audience tùy chỉnh hiện có. */\r\n data: Array<{\r\n /** Tên audience. */\r\n Name: string;\r\n /** Loại audience. */\r\n Type: number;\r\n /** Loại quảng cáo liên quan, khi API trả về. */\r\n AdType?: number;\r\n /** ID OA/trang liên quan, khi API trả về. */\r\n PageId?: number;\r\n /** Thời điểm tạo dạng Unix timestamp theo giây. */\r\n Created?: number;\r\n /** ID thành viên sở hữu hoặc tạo audience, khi API trả về. */\r\n MemberId?: number;\r\n /** Thiết lập bổ sung của audience. */\r\n Settings?: string;\r\n /** ID thành viên tạo audience, khi API trả về. */\r\n CreatedBy?: number;\r\n /** Chuỗi JSON mô tả tệp nguồn và cấu hình targeting. */\r\n Targeting?: string;\r\n /** Loại chiến dịch liên quan, khi API trả về. */\r\n CampaignType?: number;\r\n /** ID audience tùy chỉnh; dùng cho thao tác xóa hoặc liên kết audience vào quảng cáo. */\r\n CustomAudienceId: number;\r\n }>;\r\n};\r\n\r\nexport interface ZaloAdsFileGroupItemDto {\r\n id: number;\r\n name: string;\r\n memberId?: number;\r\n created?: number;\r\n totalFiles?: number;\r\n}\r\n\r\n/** Lấy các nhóm tệp media hiện có trong tài khoản quảng cáo. Đây là entry tool thuộc lane zalo-ads-media; dùng để tìm nơi chứa tài nguyên trước khi chọn ảnh hoặc video. */\r\nexport type ZaloAdsGetApiFilegroupsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiFilegroupsResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsFileGroupItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsLpNewsButtonDto {\r\n /** Nhãn nút (ví dụ: 'Xem thêm', 'Xem ngay', 'Quảng cáo ngay'). */\r\n label: string;\r\n /** Đường dẫn URL đích khi nhấn nút. */\r\n linkUrl: string;\r\n /** Loại điều hướng (1 = Mở tab mới, 2 = Route nội bộ). */\r\n type: number;\r\n /** Cờ bật/tắt hiển thị nút (dùng cho secondaryButton). */\r\n isDisplayed?: boolean;\r\n}\r\n\r\nexport interface ZaloAdsLpNewsItemDto {\r\n /** Tiêu đề tin tức/sự kiện. */\r\n title: string;\r\n /** Mô tả ngắn của tin tức/sự kiện. */\r\n description: string;\r\n /** URL hình ảnh banner của tin tức. */\r\n imageUrl: string;\r\n /** Cờ cho biết tin tức có hiển thị trên trang Tổng quan (Dashboard) hay không. */\r\n displayOnHomePage?: boolean;\r\n /** Cờ cho biết tin tức có hiển thị trên trang chủ Landing Page hay không. */\r\n displayOnLandingPage?: boolean;\r\n /** Cấu hình nút hành động chính trên Dashboard. */\r\n primaryButton?: ZaloAdsLpNewsButtonDto;\r\n /** Cấu hình nút hành động phụ trên Dashboard. */\r\n secondaryButton?: ZaloAdsLpNewsButtonDto;\r\n /** Cấu hình nút hành động hiển thị trên popup Landing Page. */\r\n landingPageButton?: ZaloAdsLpNewsButtonDto;\r\n}\r\n\r\n/** Lấy thông tin tin tức/sự kiện nổi bật hiển thị dạng popup nổi (balloon) trên trang chủ Landing Page của Zalo Ads. Đây là entry tool thuộc lane zalo-ads-content; trả về đối tượng tin tức trong data (khi code = 0) hoặc thông báo \"Landing page new is empty\" (khi code = 1). */\r\nexport type ZaloAdsGetApiLpNewsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiLpNewsResponse = {\r\n /** Mã trạng thái (0 = Có tin tức trả về trong data, 1 = Không có tin tức nào đang hiển thị trên Landing Page). */\r\n code: number;\r\n /** Thông báo trạng thái (ví dụ: 'Landing page new is empty' khi code = 1). */\r\n msg?: string;\r\n /** Chi tiết bài viết/tin tức nổi bật hiển thị trên Landing Page (chỉ có mặt khi code = 0). */\r\n data?: ZaloAdsLpNewsItemDto;\r\n};\r\n\r\n/** Lấy danh sách ảnh, video hoặc tài nguyên media theo khoảng thời gian. Đây là entry tool thuộc lane zalo-ads-media; dùng khi cần chọn asset đã tải lên cho mẫu quảng cáo. */\r\nexport type ZaloAdsGetApiMediaItemsRequest = {\r\n /** Mốc kết thúc lọc media, Unix timestamp theo giây. */\r\n endDate: number;\r\n /** Mốc bắt đầu lọc media, Unix timestamp theo giây. */\r\n startDate: number;\r\n};\r\n\r\nexport type ZaloAdsGetApiMediaItemsResponse = {\r\n code: number;\r\n data: Array<{\r\n Name: string;\r\n Type: number;\r\n Status: number;\r\n Created: number;\r\n MediaId: number;\r\n MemberId: number;\r\n Settings: {\r\n Url: string;\r\n Width: number;\r\n Height: number;\r\n Duration: number;\r\n ThumbUrl: string;\r\n };\r\n CreatedBy: number;\r\n }>;\r\n};\r\n\r\nexport interface ZaloAdsMemberFileItemDto {\r\n id: number;\r\n name: string;\r\n fileUrl: string;\r\n status?: number;\r\n lineNumber?: number;\r\n created?: number;\r\n memberId?: number;\r\n}\r\n\r\n/** Lấy các tệp do thành viên hiện tại quản lý trong tài khoản quảng cáo. Đây là entry tool thuộc lane zalo-ads-media; dùng để tra cứu asset theo quyền sở hữu hoặc trạng thái. */\r\nexport type ZaloAdsGetApiMemberFilesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiMemberFilesResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsMemberFileItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsNotifyHeaderItemDto {\r\n /** ID định danh của thông báo (ví dụ: 1). */\r\n id: number;\r\n /** Nội dung chi tiết của thông báo hiển thị trên đầu trang. */\r\n text: string;\r\n}\r\n\r\n/** Lấy danh sách thông báo quan trọng hiển thị trên thanh tiêu đề (header announcements) của trình quản lý Zalo Ads. Đây là helper tool thuộc lane zalo-ads-notification; dùng khi cần kiểm tra các cảnh báo hệ thống hoặc nhắc nhở quan tâm OA Hỗ trợ quảng cáo Zalo Ads. */\r\nexport type ZaloAdsGetApiNotifiesHeaderRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiNotifiesHeaderResponse = {\r\n /** Mã kết quả (0 = Thành công). */\r\n code: number;\r\n /** Thông điệp trạng thái (ví dụ: 'success'). */\r\n msg?: string;\r\n /** Danh sách các thông báo hiển thị ở đầu trang (header banner). */\r\n announcements: Array<ZaloAdsNotifyHeaderItemDto>;\r\n};\r\n\r\n/** Lấy lịch sử nạp tiền (charge/payment transaction history) của tài khoản quảng cáo Zalo Ads trong khoảng thời gian tối đa 31 ngày. Đây là entry tool thuộc lane zalo-ads-billing; dùng khi đối soát các giao dịch nạp tiền, ngân hàng, kênh nạp, trạng thái và xuất hóa đơn theo khoảng thời gian xác định. */\r\nexport type ZaloAdsGetApiPaymentTransactionHistoryRequest = {\r\n /** Mốc thời gian kết thúc khoảng tra cứu, định dạng Unix timestamp tính bằng giây (khoảng cách giữa from và to tối đa 31 ngày). */\r\n to: number;\r\n /** Mốc thời gian bắt đầu khoảng tra cứu, định dạng Unix timestamp tính bằng giây (khoảng cách giữa from và to tối đa 31 ngày). */\r\n from: number;\r\n /** ID tài khoản/thành viên cần tra cứu lịch sử nạp tiền. Truyền 0 để lấy theo tài khoản hiện tại đang đăng nhập hoặc truyền ID thành viên cụ thể (ví dụ: 257887336). */\r\n memberId: number;\r\n};\r\n\r\nexport interface ZaloAdsPaymentTransactionItemDto {\r\n /** Số tiền nạp (VNĐ), ví dụ: 1000000. */\r\n amount: number;\r\n /** Tên ngân hàng hoặc nguồn nạp (ví dụ: 'Ngân hàng TMCP Hàng Hải Việt Nam', 'Voucher'). */\r\n bankName: string;\r\n /** Kênh nạp tiền (ví dụ: 'Chuyển khoản', 'ZaloPay', 'Thẻ ATM', 'Voucher'). */\r\n channel: string;\r\n /** Nội dung/ghi chú giao dịch nạp tiền. */\r\n content: string;\r\n /** Thời điểm phát sinh giao dịch nạp tiền, định dạng Unix timestamp tính bằng giây. */\r\n date: number;\r\n /** ID người hoặc hệ thống thực hiện nạp tiền (ví dụ: 257887336). */\r\n createdId: number;\r\n /** Tên người hoặc hệ thống thực hiện nạp tiền (ví dụ: 'Zalo Ads'). */\r\n createdName: string;\r\n /** Tên phụ của đơn vị/người nạp hộ (nếu có). */\r\n secondaryName?: string;\r\n /** ID tài khoản quảng cáo thụ hưởng số tiền nạp. */\r\n memberId: number;\r\n /** Cờ đánh dấu giao dịch có xuất hóa đơn (true = Có, false = Không). */\r\n receipt: boolean;\r\n /** Trạng thái giao dịch nạp tiền (ví dụ: 'Thành công'). */\r\n status: string;\r\n}\r\n\r\nexport type ZaloAdsGetApiPaymentTransactionHistoryResponse = {\r\n /** Mã trạng thái phản hồi (0 = Thành công, 1 = Lỗi tham số hoặc vượt quá 31 ngày). */\r\n code: number;\r\n /** Thông báo trạng thái hoặc chi tiết lỗi từ hệ thống. */\r\n msg?: string;\r\n /** Danh sách các giao dịch nạp tiền trong khoảng thời gian đã chọn. */\r\n data: Array<ZaloAdsPaymentTransactionItemDto>;\r\n /** Thông tin bổ sung của tài khoản được tra cứu (khi xem theo memberId). */\r\n extend?: {\r\n name?: string;\r\n };\r\n};\r\n\r\n/** Lấy danh mục vùng miền, tỉnh thành và ID quận huyện phục vụ nhắm chọn theo vị trí. Đây là helper tool thuộc lane zalo-ads-targeting; dùng khi xây dựng điều kiện địa lý chi tiết. */\r\nexport type ZaloAdsGetApiPlaceGetalldistrictsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiPlaceGetalldistrictsResponse = {\r\n code: number;\r\n /** Map vùng miền, key là ID vùng. */\r\n data: {\r\n [key: string]: {\r\n id: number;\r\n name: string;\r\n dmpId: number;\r\n provinces: {\r\n [key: string]: {\r\n id: string;\r\n name: string;\r\n dmpId: number;\r\n district: Array<number>;\r\n oldProvinceId?: string;\r\n };\r\n };\r\n newProvinces: {\r\n [key: string]: {\r\n id: string;\r\n name: string;\r\n dmpId: number;\r\n district: Array<number>;\r\n oldProvinceId?: string;\r\n };\r\n };\r\n };\r\n };\r\n};\r\n\r\nexport interface ZaloAdsSpellCheckIssueDto {\r\n /** Mã quy tắc lỗi ('111'/'278' = Lỗi chính tả, '113' = Lỗi lạm dụng kí tự, '121' = Lỗi viết hoa, '236'/'237' = Lỗi sử dụng URL/SĐT). */\r\n code?: string;\r\n /** Nhãn mô tả loại lỗi hiển thị cho người dùng. */\r\n label?: string;\r\n /** Vị trí ký tự bắt đầu của cụm từ lỗi (0-indexed). */\r\n start: number;\r\n /** Vị trí ký tự kết thúc của cụm từ lỗi. */\r\n end: number;\r\n /** Cụm từ gốc bị phát hiện lỗi trong văn bản đầu vào. */\r\n originalText: string;\r\n /** Cụm từ gợi ý thay thế (chuỗi rỗng nếu gợi ý xóa bỏ). */\r\n text: string;\r\n /** Cờ đánh dấu gợi ý là xóa bỏ cụm từ lỗi (true khi text rỗng). */\r\n isRemoval?: boolean;\r\n /** Mã phân loại diff (mặc định: 0). */\r\n type?: number;\r\n}\r\n\r\n/** Kiểm tra chính tả và quy định nội dung quảng cáo (viết hoa, lạm dụng ký tự, SĐT/URL) bằng AI cho văn bản quảng cáo (tiêu đề hoặc chú thích). Đây là helper tool thuộc lane zalo-ads-content; bắt buộc truyền query param text và trả về danh sách vị trí lỗi kèm gợi ý chỉnh sửa trong trường data.diffs. */\r\nexport type ZaloAdsGetApiSpellCheckV2Request = {\r\n /** Nội dung văn bản cần kiểm tra chính tả và quy chuẩn quảng cáo (ví dụ: tiêu đề hoặc chú thích mẫu quảng cáo). */\r\n text: string;\r\n};\r\n\r\nexport type ZaloAdsGetApiSpellCheckV2Response = {\r\n /** Mã kết quả HTTP/API (0 = Thành công). */\r\n code: number;\r\n /** Thông báo trạng thái (nếu có). */\r\n msg?: string;\r\n data: {\r\n /** UUID định danh phiên yêu cầu AI kiểm tra chính tả (dùng để gắn vào tracking request_ai_id khi lưu quảng cáo). */\r\n requestAiId: string;\r\n /** Văn bản đầu ra hoàn chỉnh sau khi AI gợi ý chỉnh sửa. */\r\n aiOutput: string;\r\n /** Thời gian xử lý của AI tính bằng mili giây (ms). */\r\n elapsedTime: number;\r\n /** Mã trạng thái dịch vụ AI (0 = SUCCESS, -1 = AI_SERVER_FAILURE, -2 = AI_REQUEST_TIMEOUT). */\r\n error: number;\r\n /** Danh sách các lỗi chính tả hoặc vi phạm quy định từ ngữ phát hiện được trong văn bản. */\r\n diffs: Array<ZaloAdsSpellCheckIssueDto>;\r\n };\r\n};\r\n\r\nexport interface ZaloAdsSpellCheckViolationDto {\r\n start: number;\r\n end: number;\r\n original_text: string;\r\n rules: number[];\r\n suggestion: string;\r\n}\r\n\r\n/** Khởi tạo tác vụ kiểm tra chính tả và vi phạm quy chuẩn quảng cáo AI V3 (POST /api/spell-check/v3). */\r\nexport type ZaloAdsCreateSpellCheckV3JobRequest = {\r\n /** Tiêu đề mẫu quảng cáo (title). */\r\n title: string;\r\n /** Chú thích / mô tả mẫu quảng cáo (caption). */\r\n caption: string;\r\n};\r\n\r\nexport type ZaloAdsCreateSpellCheckV3JobResponse = {\r\n code: 0 | number;\r\n data: {\r\n error: number;\r\n jobId: string;\r\n };\r\n};\r\n\r\n/** Lấy kết quả kiểm tra chính tả và vi phạm quy chuẩn quảng cáo AI V3 theo jobId (GET /api/spell-check/v3/{jobId}). */\r\nexport type ZaloAdsGetSpellCheckV3JobRequest = {\r\n /** Mã tác vụ kiểm tra chính tả dạng http-<uuid>. */\r\n jobId: string;\r\n};\r\n\r\nexport type ZaloAdsGetSpellCheckV3JobResponse = {\r\n code: 0 | number;\r\n data: {\r\n error: number;\r\n jobId: string;\r\n status: \"PROCESSING\" | \"COMPLETED\";\r\n message?: string;\r\n completedAt?: string;\r\n details?: {\r\n violations?: Array<ZaloAdsSpellCheckViolationDto>;\r\n title_merged_violations?: Array<ZaloAdsSpellCheckViolationDto>;\r\n caption_merged_violations?: Array<ZaloAdsSpellCheckViolationDto>;\r\n title_suggestion?: string;\r\n caption_suggestion?: string;\r\n error?: string;\r\n };\r\n };\r\n};\r\n\r\n/** Lấy thông tin tài khoản Zalo Ads hiện được xác thực, gồm ngân sách, hạn mức và các khả năng được cấp. Đây là auth-sensitive entry tool thuộc lane zalo-ads-account; dùng để xác nhận đúng ngữ cảnh tài khoản trước thao tác khác. Dữ liệu cá nhân, hợp đồng và định danh phiên chỉ được xử lý trong phạm vi được ủy quyền. */\r\nexport type ZaloAdsGetApiWhoamiRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetApiWhoamiResponse = {\r\n code: number;\r\n data: {\r\n id: number;\r\n /** Định danh phiên hoặc tài khoản nhạy cảm. */\r\n sid?: string;\r\n name: string;\r\n rank: number;\r\n role: string;\r\n /** Dữ liệu cá nhân. */\r\n phone?: string;\r\n avatar?: string;\r\n budget: number;\r\n /** Thông tin hợp đồng, khi API trả về; chứa dữ liệu nhạy cảm. */\r\n contract?: {\r\n code?: string;\r\n name?: string;\r\n email?: string;\r\n phone?: string;\r\n address?: string;\r\n company?: string;\r\n /** Unix timestamp theo giây. */\r\n confirmedAt?: number;\r\n legalRepresentative?: string;\r\n };\r\n /** Các cờ khả năng của tài khoản. */\r\n extraFlags?: {\r\n canUseCpm?: boolean;\r\n showSurvey?: boolean;\r\n canUseZVideo?: boolean;\r\n canChangeRole?: boolean;\r\n canUseCatalog?: boolean;\r\n canUseCommerceAd?: boolean;\r\n canUseConversion?: boolean;\r\n canUseShoppingAd?: boolean;\r\n canUseEngagementAd?: boolean;\r\n canUseAutomatedRule?: boolean;\r\n canUseExtraTemplate?: boolean;\r\n canUseMiniPageFormAd?: boolean;\r\n usedSimplifiedVersion?: boolean;\r\n canUseMiniPageMessageAd?: boolean;\r\n canUseOptimizeUniversalPixel?: boolean;\r\n /** Cho phép dùng kiểm tra chính tả AI (/api/spell-check/v2). */\r\n canUseSpellCheck?: boolean;\r\n /** Cho phép dùng tính năng tạo nhiều ảnh bằng AI. */\r\n canUseMultiImageAi?: boolean;\r\n /** Cho phép dùng công cụ tạo video. */\r\n canUseVideoCreationTool?: boolean;\r\n };\r\n /** Thông tin Agency quản lý tài khoản; chỉ xuất hiện khi tài khoản thuộc một Agency. */\r\n agencyInfo?: {\r\n /** ID Agency. */\r\n agencyId?: number;\r\n /** Tên Agency. */\r\n agencyName?: string;\r\n /** Cấp quyền của tài khoản trong Agency (quan sát được: 7, 9). */\r\n level?: number;\r\n };\r\n /** Tài khoản gốc liên quan; chứa dữ liệu cá nhân. */\r\n rootMember?: {\r\n id?: number;\r\n name?: string;\r\n avatar?: string;\r\n zaloName?: string;\r\n loginType?: number;\r\n loginLevel?: number;\r\n };\r\n limitedMoney: number;\r\n currentLimitMoney: number;\r\n unreadNotifications?: number;\r\n };\r\n};\r\n\r\n/** Lấy báo cáo hiệu quả theo quảng cáo theo khoảng thời gian, có thể lọc trạng thái và breakdown. Đây là entry tool thuộc lane zalo-ads-reporting; dùng khi cần danh sách quảng cáo cùng metric tổng hợp hoặc trạng thái. filter là chuỗi JSON điều kiện, không truyền object lồng nhau. */\r\nexport type ZaloAdsGetReportapiV2AdsRequest = {\r\n /** Mốc client/report kết thúc, Unix epoch mili giây; là biến thể query đã quan sát ở endpoint này. */\r\n to?: number;\r\n /** Mốc client/report bắt đầu, Unix epoch mili giây; là biến thể query đã quan sát ở endpoint này. */\r\n from?: number;\r\n /** Chuỗi JSON của mảng điều kiện lọc. Mỗi phần tử có Field và Value kiểu chuỗi; ví dụ lọc trạng thái: [{\"Value\":\"3\",\"Field\":\"Status\"}]. Runtime tự URL-encode query string. */\r\n filter?: string;\r\n /** Kết thúc khoảng báo cáo, Unix epoch giây; phải >= startDate. */\r\n endDate: number;\r\n /** Tham số làm mới từ giao diện. Literal undefined đã được quan sát nhưng ý nghĩa upstream chưa xác minh; nên bỏ qua khi không cần mô phỏng UI. */\r\n refresh?: string;\r\n /** Danh sách mã breakdown phân tách bằng dấu phẩy, ví dụ 1002,2001. */\r\n breakdown?: string;\r\n /** Bắt đầu khoảng báo cáo, Unix epoch giây. */\r\n startDate: number;\r\n};\r\n\r\nexport interface ZaloAdsAdReportItemDto {\r\n /** ID quảng cáo; dùng làm adId cho thao tác chi tiết/cập nhật. */\r\n id: number;\r\n name: string;\r\n /** Mã loại quảng cáo upstream; đã quan sát 28. */\r\n adType: number;\r\n /** Mã trạng thái. Khi lọc dùng Value chuỗi, ví dụ \"3\" hoặc \"4\", trong filter. */\r\n status: number;\r\n /** Unix epoch giây. */\r\n endDate: number;\r\n /** URL ảnh bìa. */\r\n coverUrl?: string;\r\n memberId: number;\r\n /** Unix epoch giây. */\r\n modified?: number;\r\n /** Mã read-only upstream; đã quan sát -1, không phải boolean. */\r\n readOnly?: number;\r\n viewType?: number;\r\n createdBy?: number;\r\n /** Unix epoch giây. */\r\n startDate: number;\r\n /** ID chiến dịch chứa quảng cáo. */\r\n campaignId: number;\r\n memberName?: string;\r\n /** Mã loại giá thầu upstream. */\r\n adPriceType?: number;\r\n /** Metric động; key là mã chỉ số Zalo Ads. */\r\n reportTotal: Record<string, number>;\r\n campaignName: string;\r\n campaignType?: number;\r\n conversionId?: number;\r\n reportByDate?: Record<string, Record<string, number>>;\r\n reportBySubId?: Record<string, Record<string, number>>;\r\n adtimaBookingId?: number;\r\n reportTotalByTemplate?: Record<string, Record<string, number>>;\r\n reportBySubIdThenByDate?: Record<string, Record<string, Record<string, number>>>;\r\n reportByTemplateThenByDate?: Record<string, Record<string, Record<string, number>>>;\r\n}\r\n\r\nexport type ZaloAdsGetReportapiV2AdsResponse = {\r\n msg: string;\r\n /** 0 là thành công. */\r\n code: number;\r\n data: Array<ZaloAdsAdReportItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsCampaignReportItemDto {\r\n id: number;\r\n name: string;\r\n status: number;\r\n endDate: number;\r\n memberId: number;\r\n readOnly: number;\r\n viewType: number;\r\n startDate: number;\r\n memberName?: string;\r\n /** Metric động; key là mã chỉ số Zalo Ads. */\r\n reportTotal: Record<string, number>;\r\n campaignType: number;\r\n adtimaCampaignId: number;\r\n reportByDate?: Record<string, Record<string, number>>;\r\n}\r\n\r\n/** Lấy báo cáo chi tiết của một chiến dịch đã biết. Đây là detail tool thuộc lane zalo-ads-reporting; dùng khi đã có campaign ID và cần xem chỉ số hiệu quả của chiến dịch đó. */\r\nexport type ZaloAdsGetReportapiV2CampaignsRequest = {\r\n /** ID chiến dịch cần xem báo cáo. */\r\n campaignId?: number | string;\r\n /** Ngày bắt đầu báo cáo, Unix timestamp theo giây. */\r\n startDate?: number;\r\n /** Ngày kết thúc báo cáo, Unix timestamp theo giây. */\r\n endDate?: number;\r\n /** Mốc làm mới truy vấn, Unix timestamp mili giây. */\r\n refresh?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetReportapiV2CampaignsResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsCampaignReportItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsUniqueUserReportDataDto {\r\n totalUniqueUsers: number;\r\n totalReach?: number;\r\n frequency?: number;\r\n byDate?: Record<string, number>;\r\n}\r\n\r\n/** Lấy thống kê người dùng duy nhất tiếp cận hoặc tương tác với quảng cáo / chiến dịch (GET https://ads.zalo.me/reportapi/v2/unique-user). */\r\nexport type ZaloAdsGetReportapiV2UniqueUserRequest = {\r\n start: number;\r\n end: number;\r\n campaignId?: number | string;\r\n adId?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetReportapiV2UniqueUserResponse = {\r\n code: number;\r\n msg?: string;\r\n data: number;\r\n extend?: Array<{ adId: number; count: number }>;\r\n};\r\n\r\n/** Lấy báo cáo hiệu quả campaign theo phiên bản dữ liệu báo cáo v3. Đây là entry tool thuộc lane zalo-ads-reporting; dùng khi cần tổng hợp hoặc so sánh chỉ số nhiều chiến dịch trong một khoảng thời gian. */\r\nexport type ZaloAdsGetReportapiV3CampaignsRequest = {\r\n /** Chuỗi JSON biểu diễn các bộ lọc Campaigns; dùng \"[]\" khi không có bộ lọc. */\r\n filter?: string;\r\n /** Ngày kết thúc báo cáo, Unix timestamp theo giây. */\r\n endDate: number;\r\n /** Mốc làm mới truy vấn khi upstream yêu cầu, Unix timestamp mili giây. */\r\n refresh?: number;\r\n /** ID agency quản lý tài khoản; dùng 0 khi không thuộc agency. */\r\n agencyId?: number;\r\n /** ID người tạo chiến dịch dùng để lọc danh sách campaign. */\r\n createdBy?: number;\r\n /** Ngày bắt đầu báo cáo, Unix timestamp theo giây. */\r\n startDate: number;\r\n};\r\n\r\nexport type ZaloAdsGetReportapiV3CampaignsResponse = {\r\n msg: string;\r\n code: number;\r\n data: Array<ZaloAdsCampaignReportItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsZaapiCampaignReportItemDto {\r\n AdId: number;\r\n AdName: string;\r\n CampaignId: number;\r\n CampaignName: string;\r\n CampaignType: number;\r\n Date: number;\r\n Cost: number;\r\n Quantity: number;\r\n}\r\n\r\n/** Lấy báo cáo hiệu quả của campaign theo dữ liệu vận hành Zalo Ads (GET https://ads.zalo.me/zaapi/Campaign/reportCampaign). */\r\nexport type ZaloAdsGetZaapiCampaignReportcampaignRequest = {\r\n campaignId: number | string;\r\n from: number;\r\n to: number;\r\n campId?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetZaapiCampaignReportcampaignResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: Array<ZaloAdsZaapiCampaignReportItemDto>;\r\n};\r\n\r\n/** Kiểm tra một chiến dịch có chứa nhiều quảng cáo hay không. Đây là helper tool thuộc lane zalo-ads-campaign; dùng trước khi chọn luồng xem hoặc cập nhật quảng cáo trong campaign. */\r\nexport type ZaloAdsGetZaapiCheckcamphasmanyadsRequest = {\r\n campaignId?: number | string;\r\n campId?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetZaapiCheckcamphasmanyadsResponse = {\r\n code: number;\r\n msg?: string;\r\n data: boolean | number;\r\n};\r\n\r\n/** Lấy danh sách quảng cáo thuộc một chiến dịch. Đây là entry tool thuộc lane zalo-ads-ad; dùng khi đã có campaign ID và cần chọn quảng cáo để xem hoặc chỉnh sửa. */\r\nexport type ZaloAdsGetZaapiGetadsfromcampaignidRequest = {\r\n campaignId?: number | string;\r\n campId?: number | string;\r\n dataType?: number | string;\r\n v?: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetZaapiGetadsfromcampaignidResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsAdUpdatePayloadDto>;\r\n extend?: ZaloAdsCampaignDetailExtendDto;\r\n extra?: {\r\n appliedRuleInfo?: Array<unknown>;\r\n [key: string]: unknown;\r\n };\r\n};\r\n\r\nexport interface ZaloAdsPageConfigDto {\r\n /** Hạng tài khoản OA (ví dụ: 0 = Phổ thông, 1 = Xác thực/Nâng cao). */\r\n tier?: number;\r\n viewStatus?: number;\r\n isVerified?: boolean;\r\n allowMessage?: boolean;\r\n}\r\n\r\n/** Một địa điểm trong `extraInfo.locations` của OA (quan sát trên 67 địa điểm của 64 OA). */\r\nexport interface ZaloAdsOwnedPageLocationDto {\r\n /** Địa chỉ đầy đủ. */\r\n address: string;\r\n /** Mã tỉnh/thành. */\r\n provinceId: number;\r\n /** Mã quận/huyện; chỉ có ở 64/67 địa điểm quan sát được. */\r\n districtId?: number;\r\n /** Vĩ độ. */\r\n lat: number;\r\n /** Kinh độ. */\r\n lng: number;\r\n}\r\n\r\n/** Cấu trúc của chuỗi JSON `extraInfo` sau khi `JSON.parse`. Dữ liệu cá nhân, chỉ xử lý trong phạm vi được ủy quyền. */\r\nexport interface ZaloAdsOwnedPageExtraInfoDto {\r\n website: string | null;\r\n contactName: string;\r\n hotline: string | null;\r\n workingTime: string | null;\r\n /** Số điện thoại liên hệ dạng quốc tế, ví dụ \"84384473007\". */\r\n contactPhone: string;\r\n locations: Array<ZaloAdsOwnedPageLocationDto>;\r\n}\r\n\r\nexport interface ZaloAdsOwnedPageItemDto {\r\n /** ID nội bộ page/OA (trùng với pageId, ví dụ: 429753475). */\r\n id: number;\r\n /** Tên danh mục ngành nghề, khi có. */\r\n cate?: string;\r\n /** Tên page/OA. */\r\n name: string;\r\n /** Loại page/OA (ví dụ: 2 = Doanh nghiệp/Cửa hàng). */\r\n type: number;\r\n /** Cờ store (0 hoặc 1). */\r\n store?: number;\r\n /** Cấu hình phân hạng page/OA thay đổi theo loại. */\r\n config?: ZaloAdsPageConfigDto;\r\n /** ID nội bộ của page/OA dùng trong các API Zalo Ads như tạo chiến dịch (/zaapi/addNewCamp) hoặc lấy danh sách bài viết (/zaapi/getOwnedArticles). */\r\n pageId: number;\r\n /** Trạng thái hoạt động page/OA (ví dụ: 1 = Đang hoạt động). */\r\n status: number;\r\n /** Các ID danh mục ngành nghề (ví dụ: [10018]). */\r\n cateIds?: Array<number>;\r\n /** ID chủ sở hữu, chỉ xử lý trong phạm vi được ủy quyền. */\r\n ownerId?: number;\r\n configAd?: {\r\n /** Trạng thái hiển thị quảng cáo (ví dụ: 1 = Cho phép). */\r\n viewStatus?: number;\r\n };\r\n /** URL ảnh bìa, khi có. */\r\n coverUrl?: string;\r\n /** Mã định danh OA làm nhiễu dạng chuỗi số dài (trùng với pageIdNoised). */\r\n noisedId?: string;\r\n /** Tên hiển thị page/OA. */\r\n pageName: string;\r\n /** URL ảnh đại diện, khi có. */\r\n avatarUrl?: string;\r\n /** Cho biết OA đã chứng thực tích vàng (true) hay chưa (false). */\r\n certified?: boolean;\r\n /** Chuỗi JSON chứa thông tin liên hệ (website, contactName, hotline, contactPhone, workingTime) và danh sách vị trí (locations), khi có. */\r\n extraInfo?: string;\r\n /** Trạng thái vận hành page/OA (ví dụ: 1 = Hoạt động bình thường). */\r\n pageStatus: number;\r\n /** Thời điểm tạo dạng Unix timestamp mili giây. */\r\n createdTime?: number;\r\n /** Mô tả page/OA, khi có. */\r\n description?: string;\r\n /** Thời điểm cập nhật dạng Unix timestamp mili giây. */\r\n updatedTime?: number;\r\n /** Mã định danh OA công khai/làm nhiễu dạng chuỗi số dài (ví dụ: '305001418732969574'), dùng làm oaId trong các API Instant Pages, Zalo Forms và Message Flows. */\r\n pageIdNoised?: string;\r\n}\r\n\r\n/** Lấy danh sách tất cả Zalo Official Account hoặc trang có thể sử dụng. Đây là entry tool thuộc lane zalo-ads-page; dùng khi cần chọn page/OA trước khi tạo chiến dịch hoặc lấy bài viết OA. */\r\nexport type ZaloAdsGetZaapiGetallpagesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetZaapiGetallpagesResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsOwnedPageItemDto>;\r\n};\r\n\r\nexport interface ZaloAdsOwnedArticleItemDto {\r\n /** Mã định danh nội bộ của bài viết (ví dụ: 17050656), dùng để truyền vào trường articleId khi tạo chiến dịch Quảng cáo Bài viết (campaignType = 4) hoặc ZaloFeedId khi cập nhật quảng cáo. */\r\n articleId: number;\r\n /** ID nội bộ của trang Zalo Official Account sở hữu bài viết (ví dụ: 429753475). */\r\n pageId: number;\r\n /** Tiêu đề của bài viết. */\r\n title: string;\r\n /** Đoạn mô tả tóm tắt (sapo) của bài viết. */\r\n description?: string;\r\n /** Đường dẫn URL công khai để xem bài viết trên Zalo OA (ví dụ: 'https://post.oa.zalo.me/d?id=...&pageId=...'). */\r\n viewUrl: string;\r\n /** URL ảnh đại diện thu nhỏ (thumbnail) của bài viết. */\r\n thumbnail?: string;\r\n /** Tổng số lượt xem bài viết. */\r\n numViews?: number;\r\n /** Tổng số lượt chia sẻ bài viết. */\r\n numShares?: number;\r\n /** Cờ đánh dấu bài viết định dạng video (true) hay bài viết thông thường (false). */\r\n isVideoArticle: boolean;\r\n}\r\n\r\n/** Lấy danh sách các bài viết đã xuất bản thuộc một trang Zalo Official Account (OA) cụ thể theo mã pageId nội bộ. Đây là entry tool thuộc lane zalo-ads-content / zalo-ads-article; dùng khi chọn bài viết nguồn cho quảng cáo bài viết (campaignType = 4). */\r\nexport type ZaloAdsGetZaapiGetownedarticlesRequest = {\r\n /** ID nội bộ của trang Zalo Official Account (trường pageId hoặc id kiểu số nguyên lấy từ getZaapiGetownedpages / getZaapiGetallpages, ví dụ: 429753475). Không truyền pageIdNoised. */\r\n pageId: number | string;\r\n};\r\n\r\nexport type ZaloAdsGetZaapiGetownedarticlesResponse = {\r\n code: number;\r\n msg?: string;\r\n data: Array<ZaloAdsOwnedArticleItemDto>;\r\n};\r\n\r\n/** Lấy các OA do tài khoản hiện tại sở hữu hoặc quản lý. Đây là entry tool thuộc lane zalo-ads-page; dùng để lấy page ID hợp lệ trước khi cấu hình campaign hoặc lấy bài viết OA. */\r\nexport type ZaloAdsGetZaapiGetownedpagesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsGetZaapiGetownedpagesResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** Danh sách page/OA. */\r\n data: Array<ZaloAdsOwnedPageItemDto>;\r\n};\r\n\r\n/** Lấy khách hàng thuộc agency cùng ngân sách, hạn mức và trạng thái truy cập. Đây là auth-sensitive entry tool thuộc lane zalo-ads-agency; dùng khi cần đối soát danh sách khách hàng hoặc hạn mức theo agency. Dữ liệu định danh và số điện thoại thành viên chỉ được xử lý trong phạm vi được ủy quyền. */\r\nexport type ZaloAdsListAgencyCustomersWithBudgetRequest = {\r\n /** Số khách hàng tối đa mỗi lần lấy (mặc định: 15). */\r\n limit?: number;\r\n /** Vị trí bắt đầu để phân trang, gốc 0 (mặc định: 0). */\r\n offset?: number;\r\n /** Sắp xếp ngày tham gia tăng dần khi là true (mặc định: true). */\r\n joinDateAsc?: boolean;\r\n};\r\n\r\nexport type ZaloAdsListAgencyCustomersWithBudgetResponse = {\r\n /** Thông điệp kết quả. */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n data: {\r\n /** Tổng số khách hàng phù hợp. */\r\n total: number;\r\n /** ID chủ sở hữu agency; chỉ xử lý trong phạm vi được ủy quyền. */\r\n ownerId: number;\r\n /** ID agency. */\r\n agencyId: number;\r\n /** Tên agency. */\r\n agencyName: string;\r\n /** Các khách hàng/thành viên của agency. */\r\n memberList: Array<{\r\n /** Ngân sách hiện tại. */\r\n budget: number;\r\n /** Trạng thái thành viên. */\r\n status: number;\r\n /** ID agency quản lý thành viên. */\r\n agencyId: number;\r\n /** Thời điểm tham gia, Unix timestamp theo giây. */\r\n joinDate: number;\r\n /** ID khách hàng/thành viên. */\r\n memberId: number;\r\n /** Tên thành viên; dữ liệu cá nhân. */\r\n memberName: string;\r\n /** Cấp quyền truy cập. */\r\n accessLevel: number;\r\n /** Số điện thoại thành viên; dữ liệu cá nhân. */\r\n memberPhone?: string;\r\n /** Giá trị hạn mức đã giới hạn. */\r\n limitedMoney: number;\r\n /** URL ảnh đại diện thành viên; dữ liệu cá nhân. */\r\n memberAvatar?: string;\r\n /** Hạn mức hiện tại. */\r\n currentLimitMoney: number;\r\n /** Số người có quyền truy cập. */\r\n numberOfAccessors: number;\r\n}>;\r\n};\r\n};\r\n\r\n/** Lấy danh sách cấu hình báo cáo tùy chỉnh của tài khoản, gồm tên, chỉ số và trạng thái mặc định. Đây là entry tool thuộc lane zalo-ads-reporting; dùng khi cần chọn hoặc kiểm tra báo cáo đã lưu. */\r\nexport type ZaloAdsListCustomReportsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsListCustomReportsResponse = {\r\n code: number;\r\n data: Array<{\r\n id: number;\r\n name: string;\r\n created: number;\r\n memberId: number;\r\n modified: number;\r\n settings: Array<number>;\r\n isDefault: boolean;\r\n}>;\r\n};\r\n\r\n/** Lấy danh sách biểu mẫu Zalo Ads theo Official Account, gồm trạng thái, câu hỏi, nội dung và thời điểm cập nhật. Đây là auth-sensitive entry tool thuộc lane zalo-ads-form; dùng khi đã có OA ID và cần chọn hoặc kiểm tra biểu mẫu trước khi cấu hình quảng cáo. Nội dung biểu mẫu, thông tin chủ sở hữu và URL liên quan chỉ được dùng trong phạm vi được ủy quyền. */\r\nexport type ZaloAdsListFormsByOfficialAccountRequest = {\r\n /** ID Zalo Official Account cần lấy danh sách biểu mẫu. Dùng chuỗi số để giữ nguyên ID dài. */\r\n oaId: string;\r\n /** Trả về toàn bộ biểu mẫu theo OA khi được bật. */\r\n isAll?: boolean;\r\n};\r\n\r\nexport type ZaloAdsListFormsByOfficialAccountResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** Các biểu mẫu Zalo Ads. */\r\n data: Array<{\r\n /** ID biểu mẫu. */\r\n id: string;\r\n /** Nguồn tạo biểu mẫu, khi API trả về. */\r\n src?: string;\r\n /** ID Official Account của biểu mẫu. */\r\n oaId: string;\r\n /** ID chủ sở hữu hoặc tài khoản liên quan, khi API trả về. */\r\n ownId?: string;\r\n /** Số điện thoại liên hệ, khi có; dữ liệu cá nhân. */\r\n phone?: string;\r\n /** Tiêu đề biểu mẫu, khi có. */\r\n title?: string;\r\n /** Tên Official Account, khi API trả về. */\r\n oaName?: string;\r\n /** Trạng thái biểu mẫu. */\r\n status: number;\r\n /** Nội dung cảm ơn sau khi gửi, khi có. */\r\n thanks?: string;\r\n /** Mã hoặc URL công khai của biểu mẫu, khi có. */\r\n formUrl?: string;\r\n /** Thông tin chủ sở hữu; chỉ xử lý trong phạm vi được ủy quyền. */\r\n ownInfo?: {\r\n avatar?: string;\r\n nickName?: string;\r\n};\r\n /** Website liên kết, khi có. */\r\n website?: string;\r\n /** Thời điểm tạo dạng Unix timestamp theo giây. */\r\n createAt?: number;\r\n /** Tên biểu mẫu. */\r\n formName: string;\r\n /** Nhãn hành động chuyển tiếp. */\r\n gotoText?: string;\r\n /** URL ảnh đại diện Official Account, khi API trả về. */\r\n oaAvatar?: string;\r\n /** Các section nội dung biểu mẫu. */\r\n sections?: Array<{\r\n /** Loại section. */\r\n type: number;\r\n /** Tiêu đề section. */\r\n title: string;\r\n /** Trạng thái mở rộng section. */\r\n expand: boolean;\r\n /** Nội dung section thay đổi theo type, ví dụ images, videos hoặc table. */\r\n content: ZaloAdsFormSectionContentDto;\r\n /** Cho biết section bị vô hiệu hóa hay không. */\r\n disable: boolean;\r\n }>;\r\n /** Danh sách câu hỏi của biểu mẫu. */\r\n questions: Array<{\r\n /** ID câu hỏi. */\r\n id: string;\r\n /** Loại câu hỏi. */\r\n type: number;\r\n /** Nội dung câu hỏi. */\r\n title: string;\r\n /** Các cấu hình câu trả lời. */\r\n answers: Array<{\r\n /** ID câu trả lời. */\r\n id: string;\r\n /** Loại câu trả lời. */\r\n type: number;\r\n /** Thứ tự hiển thị. */\r\n priority: number;\r\n /** Gợi ý nhập liệu, khi có. */\r\n placeHolder?: string;\r\n }>;\r\n /** Thứ tự hiển thị câu hỏi. */\r\n priority: number;\r\n /** Cho biết câu hỏi có bắt buộc hay không. */\r\n isRequired: boolean;\r\n /** Cho biết câu hỏi có bị khóa chỉnh sửa hay không. */\r\n editDisabled?: boolean;\r\n }>;\r\n /** Thời điểm cập nhật dạng Unix timestamp theo giây. */\r\n updatedAt?: number;\r\n /** Các điều kiện bổ sung, khi có. */\r\n conditions?: Array<{\r\n field?: string;\r\n operator?: string;\r\n value?: string | number;\r\n }>;\r\n /** URL ảnh bìa, khi có. */\r\n coverPhoto?: string;\r\n /** Mô tả biểu mẫu, khi có. */\r\n description?: string;\r\n /** Tiêu đề xác nhận gửi, khi có. */\r\n submitTitle?: string;\r\n /** Cờ duyệt trước khi gửi. */\r\n reviewSubmit?: boolean;\r\n /** Loại hành động chuyển tiếp. */\r\n gotoActionType?: number;\r\n /** Nhóm câu hỏi, khi có. */\r\n groupQuestions?: Array<{\r\n groupIdx?: number;\r\n title?: string;\r\n }>;\r\n /** Cờ widget đồng ý OA. */\r\n oaConsentWidget?: boolean;\r\n /** Cờ dùng consent tùy chỉnh. */\r\n useCustomConsent?: boolean;\r\n}>;\r\n extend: {\r\n /** Trang dữ liệu hiện tại. */\r\n page: number;\r\n /** Tổng số biểu mẫu. */\r\n total: number;\r\n };\r\n};\r\n\r\n/** Lấy các mini page theo ID template, gồm trạng thái, URL xem trước và thời điểm phát hành. Đây là auth-sensitive entry tool thuộc lane zalo-ads-content; dùng khi đã biết template ID và cần chọn mini page cho nội dung hoặc quảng cáo. Thông tin chủ sở hữu trong phản hồi chỉ được dùng trong phạm vi được ủy quyền. */\r\nexport type ZaloAdsListMiniPagesByTemplateRequest = {\r\n /** ID template mini page cần lấy. Capture đã quan sát một ID đơn lẻ. */\r\n templateIds: number;\r\n};\r\n\r\nexport type ZaloAdsListMiniPagesByTemplateResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** Các mini page trả về. */\r\n data: Array<{\r\n /** ID nội bộ mini page. */\r\n id: number;\r\n /** Tên mini page. */\r\n name: string;\r\n /** ID Zalo Official Account liên kết, khi API trả về. */\r\n oaId?: string;\r\n /** Trạng thái kích hoạt. */\r\n active: number;\r\n /** ID biểu mẫu liên kết, khi API trả về. */\r\n formId?: string;\r\n /** Trạng thái mini page. */\r\n status: number;\r\n /** ID người dùng liên quan, khi API trả về. */\r\n userId?: number;\r\n /** Thời điểm tạo dạng Unix timestamp theo giây. */\r\n created?: number;\r\n /** Phiên bản mini page. */\r\n version: number;\r\n /** Thời điểm sửa dạng Unix timestamp theo giây. */\r\n modified?: number;\r\n /** ID công khai của mini page. */\r\n publicId: string;\r\n /** Tên chủ sở hữu, khi API trả về; xử lý như dữ liệu cá nhân. */\r\n ownerName?: string;\r\n /** Thời điểm phát hành dạng Unix timestamp theo giây. */\r\n published?: number;\r\n /** URL xem trước mini page. */\r\n previewUrl?: string;\r\n /** Tên hoặc khóa ảnh đại diện chủ sở hữu, khi API trả về; xử lý như dữ liệu cá nhân. */\r\n ownerAvatar?: string;\r\n }>;\r\n};\r\n\r\n/** Lấy danh mục nhãn conversion Personal Pixel mà Zalo Ads hỗ trợ. Đây là helper tool thuộc lane zalo-ads-conversion; dùng khi chọn nhãn sự kiện cho cấu hình đo lường hoặc tối ưu quảng cáo. */\r\nexport type ZaloAdsListPersonalPixelLabelsRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsListPersonalPixelLabelsResponse = {\r\n code: number;\r\n data: Array<{\r\n id: number;\r\n name: string;\r\n }>;\r\n};\r\n\r\n/** Ước lượng quy mô audience và mức giá gợi ý từ điều kiện nhắm chọn đã chọn. Đây là helper tool thuộc lane zalo-ads-targeting; dùng trước khi tạo hoặc cập nhật quảng cáo để đánh giá độ phủ dự kiến. */\r\nexport type ZaloAdsPostApiAdEstimateaudienceRequest = {\r\n /** Mã giới tính target. */\r\n gender: number;\r\n /** Số lượng hoặc tham số audience dạng chuỗi theo API. */\r\n number: string;\r\n /** Các mã nhóm tuổi. */\r\n ageRanges: Array<number>;\r\n /** Chuỗi vị trí bổ sung theo API. */\r\n locations: string;\r\n /** Các mã nền tảng. */\r\n platforms: Array<number>;\r\n /** Loại giá/đấu thầu. */\r\n priceType: number;\r\n /** Danh sách ID tỉnh theo định dạng API. */\r\n provinces: Array<number>;\r\n /** Chuỗi JSON targeting phường/xã gồm Includes/Excludes. */\r\n wardsTargeting: string;\r\n /** Chuỗi JSON targeting gồm Includes/Excludes, vùng/tỉnh và danh sách ID quận/huyện. */\r\n districtsTargeting: string;\r\n};\r\n\r\nexport type ZaloAdsPostApiAdEstimateaudienceResponse = {\r\n msg: string;\r\n code: number;\r\n data: {\r\n /** Quy mô audience đã định dạng. */\r\n totalAudience: string;\r\n suggestedPrice: {\r\n min: number;\r\n lower: number;\r\n upper: number;\r\n };\r\n };\r\n};\r\n\r\nexport interface ZaloAdsMediaSaveSettingsDto {\r\n Url: string;\r\n Width: number;\r\n Height: number;\r\n Duration?: number;\r\n ThumbUrl?: string;\r\n}\r\n\r\nexport interface ZaloAdsMediaSavePayloadDto {\r\n Name: string;\r\n Type: number;\r\n Settings: ZaloAdsMediaSaveSettingsDto;\r\n}\r\n\r\n/** Lưu tài nguyên media vào thư viện Zalo Ads sau khi đã có URL ảnh hoặc video và metadata kích thước. Đây là mutation tool thuộc lane zalo-ads-media; dùng sau bước upload để nhận MediaId cho cấu hình quảng cáo. */\r\nexport type ZaloAdsPostApiMediaSaveRequest = {\r\n /** Chuỗi JSON hoặc object media gồm Name (tên), Type (loại) và Settings với Url, Width, Height. Form-urlencoded field name là data. */\r\n data: ZaloAdsMediaSavePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsPostApiMediaSaveResponse = {\r\n code: number;\r\n /** ID media vừa được lưu. */\r\n data: number;\r\n};\r\n\r\n/** Tải ảnh lên kho media của tài khoản quảng cáo (`POST /api/member/upload-image`). Đây là mutation tool thuộc lane zalo-ads-media; dùng khi cần tạo asset ảnh trước bước cấu hình quảng cáo. Đã xác minh thực tế trên Zalo Ads sử dụng trường multipart `File` (chữ hoa). */\r\nexport type ZaloAdsPostApiMemberUploadImageRequest = {\r\n /** Tệp ảnh cần tải lên (URL HTTP/HTTPS, đường dẫn file local trong Node.js, hoặc Blob/Uint8Array). */\r\n File?: FileInput;\r\n /** Alias tương thích ngược cho `File` (service tự ánh xạ sang `File`). */\r\n file?: FileInput;\r\n};\r\n\r\nexport type ZaloAdsPostApiMemberUploadImageResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** URL ảnh do Zalo Ads trả về. */\r\n data: string;\r\n msg?: string;\r\n};\r\n\r\n/** Xóa hoặc gỡ một quảng cáo đã chọn khỏi Zalo Ads. Đây là mutation tool thuộc lane zalo-ads-ad; chỉ dùng khi đã xác nhận đúng quảng cáo cần xóa. */\r\nexport type ZaloAdsPostZaapiDeleteadRequest = {\r\n adId?: number | string;\r\n};\r\n\r\nexport type ZaloAdsPostZaapiDeleteadResponse = {\r\n code: number;\r\n msg: string;\r\n data?: number | boolean;\r\n};\r\n\r\n/** Đổi tên hiển thị của một chiến dịch Zalo Ads đã tồn tại. Đây là mutation tool thuộc lane quản lý chiến dịch; dùng khi chỉ cần thay tên mà không thay đổi ngân sách, lịch chạy hoặc quảng cáo bên trong. Kết quả chỉ xác nhận thao tác thành công hoặc trả lỗi từ Zalo Ads. */\r\nexport type ZaloAdsRenameCampaignRequest = {\r\n /** ID chiến dịch cần đổi tên (server nhận tham số campid). */\r\n campid?: number;\r\n /** Alias thân thiện cho campid */\r\n campaignId?: number;\r\n /** Tên hiển thị mới của chiến dịch (server nhận tham số newname). */\r\n newname?: string;\r\n /** Alias thân thiện cho newname */\r\n campaignName?: string;\r\n name?: string;\r\n};\r\n\r\nexport type ZaloAdsRenameCampaignResponse = {\r\n /** Thông điệp kết quả từ Zalo Ads. */\r\n msg: string;\r\n /** Mã kết quả; 0 biểu thị đổi tên thành công. */\r\n code: number;\r\n};\r\n\r\n/** Cập nhật cấu hình quảng cáo E-commerce / Commerce hiện có trên Zalo Ads (Type = 19 hoặc 23). */\r\nexport type ZaloAdsUpdateEcommerceAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo E-commerce / Commerce (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateEcommerceAdResponse = {\r\n msg: string;\r\n code: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Cập nhật quảng cáo biểu mẫu (Form) đang có trên Zalo Ads (Type = 18). */\r\nexport type ZaloAdsUpdateFormAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo biểu mẫu (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateFormAdResponse = {\r\n msg: string;\r\n code: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Cấu hình đầy đủ của quảng cáo Tin nhắn. Giữ lại các trường hệ thống lấy từ getAdById khi cập nhật. */\r\nexport class ZaloAdsMessageAdUpdateDataDto {\r\n AdId!: number;\r\n CampaignId!: number;\r\n MemberId!: number;\r\n /** Phiên bản lạc quan lấy từ bản quảng cáo hiện tại. */\r\n RowVersion!: number;\r\n AdName!: string;\r\n /** 20 (hoặc 19) là quảng cáo Tin nhắn. */\r\n Type!: number;\r\n Settings!: ZaloAdsAdSettingsDto;\r\n Status!: number;\r\n StartDate!: number;\r\n EndDate!: number;\r\n /** ID kịch bản, lấy từ createFlow hoặc listFlowsByOfficialAccount. */\r\n ZaloFlowId!: number;\r\n ZaloPageId?: number;\r\n ZaloFormId?: string;\r\n UseConversion?: ZaloAdsUseConversionValue | number;\r\n ConversionId?: number;\r\n Report?: Record<string, number>;\r\n}\r\n\r\n/** Cập nhật quảng cáo Tin nhắn. Service tự JSON.stringify data rồi gửi form-urlencoded. */\r\nexport class ZaloAdsUpdateMessageAdRequest {\r\n /** Payload quảng cáo đầy đủ (object hoặc chuỗi JSON); service tự tuần tự hóa thành field form data. */\r\n data!: ZaloAdsMessageAdUpdateDataDto | ZaloAdsAdUpdatePayloadDto | string;\r\n /** Tham số UI phụ trợ; capture Zalo Ads có giá trị literal \"undefined\". */\r\n est?: string;\r\n /** 0 là quảng cáo thông thường, 1 là boost ad. */\r\n isBoostAd?: 0 | 1 | string;\r\n /** Trạng thái thao tác của giao diện; mẫu đã ghi nhận 0. */\r\n stt?: number | string;\r\n}\r\n\r\nexport class ZaloAdsUpdateMessageAdResponse {\r\n msg!: string;\r\n code!: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n}\r\n\r\n/** Tải ảnh và thiết lập vùng crop để tạo asset dùng cho quảng cáo Zalo Ads (`POST /zaapi/UploadCrop`). Đây là mutation tool thuộc lane zalo-ads-media; dùng trước khi đưa URL asset kết quả vào quảng cáo Display. Cần có URL ảnh nguồn và đầy đủ x, y, width, height, scale; dùng toàn bộ 0 cùng scale 1 khi không crop. */\r\nexport type ZaloAdsUpdateNewAdsRequest = {\r\n /** URL ảnh nguồn hoặc tệp ảnh cần tải lên và crop. */\r\n File: FileInput;\r\n /** Tọa độ crop ngang; 0 khi không crop. */\r\n x: number;\r\n /** Tọa độ crop dọc; 0 khi không crop. */\r\n y: number;\r\n /** Chiều rộng crop; 0 khi không crop. */\r\n width: number;\r\n /** Chiều cao crop; 0 khi không crop. */\r\n height: number;\r\n /** Tỷ lệ crop/zoom; payload quan sát dùng 1. */\r\n scale: number;\r\n};\r\n\r\nexport type ZaloAdsUpdateNewAdsResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: string;\r\n};\r\n\r\n/** Cập nhật quảng cáo Zalo Official Account hiện có (Type = 2 hoặc 10). */\r\nexport type ZaloAdsUpdateOfficialAccountAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo Official Account (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateOfficialAccountAdResponse = {\r\n msg: string;\r\n code: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Cập nhật quảng cáo Bài viết hiện có trên Zalo Ads (Type = 3 hoặc 12). */\r\nexport type ZaloAdsUpdatePostAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo Bài viết (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdatePostAdResponse = {\r\n msg: string;\r\n code: number;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Website trên Zalo Ads (campaignType = 1, Type = 9). */\r\nexport type ZaloAdsCreateWebsiteCampaignRequest = {\r\n /** Cấu hình chiến dịch Website (object hoặc chuỗi JSON): { name, campaignType: 1, pageId, productId: -1, targetUrl, adtype: -1, budgetType: 0, budgetlimit, limitType: 0, campaignObjective: 0, campaignId: 0, adId: 0 }. */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateWebsiteCampaignResponse = {\r\n code: number;\r\n msg: string;\r\n data?: {\r\n adId: number;\r\n campaignId: number;\r\n };\r\n};\r\n\r\n/** Cập nhật quảng cáo Website trên Zalo Ads (Type = 9). */\r\nexport type ZaloAdsUpdateWebsiteAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo Website (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateWebsiteAdResponse = {\r\n code: number;\r\n msg: string;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Display trên Zalo Ads (campaignType = 1, Type = 2). */\r\nexport type ZaloAdsCreateDisplayCampaignRequest = {\r\n /** Cấu hình chiến dịch Display (object hoặc chuỗi JSON): { name, campaignType: 1, pageId: -1, productId: -1, targetUrl, adtype: 2, budgetType: 1, budgetlimit, limitType: 1, campaignObjective: 0, campaignId: 0, adId: 0 }. */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateDisplayCampaignResponse = {\r\n code: number;\r\n msg: string;\r\n data?: {\r\n adId: number;\r\n campaignId: number;\r\n };\r\n};\r\n\r\n/** Cập nhật quảng cáo Display trên Zalo Ads (Type = 2). */\r\nexport type ZaloAdsUpdateDisplayAdRequest = {\r\n est?: string;\r\n stt?: number | string;\r\n /** Payload cập nhật quảng cáo Display (object hoặc chuỗi JSON). */\r\n data: ZaloAdsAdUpdatePayloadDto | string;\r\n isBoostAd?: number | string;\r\n};\r\n\r\nexport type ZaloAdsUpdateDisplayAdResponse = {\r\n code: number;\r\n msg: string;\r\n data?: ZaloAdsAdMutationResultDto;\r\n};\r\n\r\n/** Tạo chiến dịch quảng cáo Video trên Zalo Ads (campaignType = 3, Type = 11). */\r\nexport type ZaloAdsCreateVideoCampaignRequest = {\r\n /** Cấu hình chiến dịch Video (object hoặc chuỗi JSON): { name, campaignType: 3, pageId: -1, productId: -1, targetUrl, adtype: -1, budgetType: 1, budgetlimit, limitType: 1, campaignObjective: 0, campaignId: 0, adId: 0 }. */\r\n data: ZaloAdsCampaignCreatePayloadDto | string;\r\n};\r\n\r\nexport type ZaloAdsCreateVideoCampaignResponse = {\r\n code: number;\r\n msg: string;\r\n data?: {\r\n adId: number;\r\n campaignId: number;\r\n };\r\n};\r\n\r\n/** Xóa vĩnh viễn chiến dịch quảng cáo trên Zalo Ads (status = -2). */\r\nexport type ZaloAdsDeleteCampaignRequest = {\r\n /** ID chiến dịch cần xóa. */\r\n campaignId: number;\r\n /** Mã trạng thái xóa chiến dịch (mặc định là -2). */\r\n status?: -2;\r\n};\r\n\r\nexport type ZaloAdsDeleteCampaignResponse = {\r\n /** Mã kết quả; 0 là xóa thành công. */\r\n code: number;\r\n /** Thông báo kết quả: \"Xóa chiến dịch thành công.\" */\r\n msg: string;\r\n};\r\n\r\nexport interface ZaloAdsAutomatedRuleActionDto {\r\n /** Mã loại hành động thực thi khi thỏa mãn điều kiện (ví dụ: 5). */\r\n type: number;\r\n /** Mã trường mục tiêu mà hành động tác động (ví dụ: 1). */\r\n field: number;\r\n /** Giới hạn trần hoặc sàn của hành động điều chỉnh (ví dụ: 1000000). */\r\n limit: number;\r\n /** Mảng giá trị tham số của hành động (ví dụ: [5] tương ứng mức thay đổi 5%). */\r\n values: Array<number>;\r\n}\r\n\r\nexport interface ZaloAdsAutomatedRuleConditionDto {\r\n /** Mã loại điều kiện đánh giá (ví dụ: 1). */\r\n type: number;\r\n /** Mã chỉ số đo lường dùng làm điều kiện (ví dụ: 11). */\r\n field: number;\r\n /** Giá trị ngưỡng so sánh của điều kiện (ví dụ: [1000]). */\r\n values: Array<number>;\r\n /** Mã toán tử so sánh của điều kiện (ví dụ: 1). */\r\n operator: number;\r\n /** Mã khoảng thời gian lấy dữ liệu đối chiếu điều kiện (ví dụ: 2). */\r\n timeRange: number;\r\n}\r\n\r\nexport interface ZaloAdsAutomatedRuleScheduleDto {\r\n type?: number;\r\n frequency?: number;\r\n hours?: Array<number>;\r\n daysOfWeek?: Array<number>;\r\n}\r\n\r\n/** Tìm kiếm và lấy danh sách quy tắc tự động (Automated Rules) trên Zalo Ads. */\r\nexport type ZaloAdsListAutomatedRulesRequest = {\r\n /** Từ khóa lọc theo tên quy tắc tự động (truyền \"\" để lấy toàn bộ). */\r\n ruleName?: string;\r\n};\r\n\r\nexport type ZaloAdsListAutomatedRulesResponse = {\r\n code: number;\r\n data: Array<{\r\n automatedRule: {\r\n automatedRuleId: number;\r\n rowVersion: number;\r\n memberId: number;\r\n createdBy: number;\r\n ruleName: string;\r\n action: ZaloAdsAutomatedRuleActionDto;\r\n conditions: Array<ZaloAdsAutomatedRuleConditionDto>;\r\n schedule: ZaloAdsAutomatedRuleScheduleDto;\r\n status: number;\r\n createdTime: number;\r\n appliedTo: number;\r\n };\r\n campaignIds?: number[];\r\n adIds?: number[];\r\n }>;\r\n};\r\n\r\n/** Tạo mới một quy tắc tự động (Automated Rule) trên Zalo Ads với phạm vi áp dụng, hành động thực thi, bộ điều kiện kích hoạt và tần suất kiểm tra. Đây là mutation tool thuộc lane zalo-ads-automation. */\r\nexport type ZaloAdsCreateAutomatedRuleRequest = {\r\n /** Phạm vi áp dụng quy tắc tự động (ví dụ: 1). */\r\n scope?: number;\r\n /** Tên quy tắc tự động cần tạo. */\r\n ruleName: string;\r\n /** Cấu hình hành động tự động thực thi khi các điều kiện được thỏa mãn. */\r\n action: ZaloAdsAutomatedRuleActionDto;\r\n /** Danh sách các điều kiện kích hoạt quy tắc tự động. */\r\n conditions: Array<ZaloAdsAutomatedRuleConditionDto>;\r\n /** Tần suất hệ thống chạy kiểm tra quy tắc (ví dụ: 12). */\r\n frequency?: number;\r\n /** Danh sách ID chiến dịch hoặc quảng cáo cụ thể áp dụng quy tắc; truyền mảng rỗng [] nếu áp dụng theo toàn bộ scope. */\r\n appliedIds?: Array<number>;\r\n /** Trường tương thích ngược với cấu trúc cũ. */\r\n appliedTo?: number;\r\n schedule?: ZaloAdsAutomatedRuleScheduleDto;\r\n campaignIds?: number[];\r\n adIds?: number[];\r\n};\r\n\r\nexport type ZaloAdsCreateAutomatedRuleResponse = {\r\n /** Mã kết quả phản hồi từ Zalo Ads (0 là tạo quy tắc thành công). */\r\n code: number;\r\n /** Thông điệp kết quả xử lý (ví dụ: 'Quy tắc của bạn đã được tạo thành công.'). */\r\n msg?: string;\r\n /** ID quy tắc tự động vừa tạo hoặc cờ kết quả trả về từ hệ thống (ví dụ: 1). */\r\n data?: number;\r\n};\r\n\r\nexport interface ZaloAdsAutomatedRuleAppliedItemDto {\r\n appliedId: number;\r\n mode: number; // 0: Unapply, 1: Apply\r\n}\r\n\r\n/** Cập nhật quy tắc tự động (Automated Rule) trên Zalo Ads (`POST /api/ad/automatedrules/update`). */\r\nexport type ZaloAdsUpdateAutomatedRuleRequest = {\r\n automatedRuleId: number;\r\n scope?: number; // 1: Quảng cáo (Ads)\r\n ruleName: string;\r\n action: ZaloAdsAutomatedRuleActionDto;\r\n conditions: Array<ZaloAdsAutomatedRuleConditionDto>;\r\n frequency?: number;\r\n appliedItems?: Array<ZaloAdsAutomatedRuleAppliedItemDto>;\r\n appliedIds?: number[];\r\n rowVersion?: number;\r\n appliedTo?: number;\r\n schedule?: ZaloAdsAutomatedRuleScheduleDto;\r\n campaignIds?: number[];\r\n adIds?: number[];\r\n};\r\n\r\nexport type ZaloAdsUpdateAutomatedRuleResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: number | boolean;\r\n};\r\n\r\n/** Tra cứu chi tiết một quy tắc tự động (Automated Rule) theo ID (`GET /api/automatedrules/{automatedRuleId}`). */\r\nexport type ZaloAdsGetAutomatedRuleDetailRequest = {\r\n automatedRuleId: number;\r\n};\r\n\r\nexport type ZaloAdsGetAutomatedRuleDetailResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: {\r\n automatedRule: {\r\n automatedRuleId: number;\r\n rowVersion?: number;\r\n memberId?: number;\r\n createdBy?: number;\r\n ruleName: string;\r\n action: ZaloAdsAutomatedRuleActionDto;\r\n conditions: Array<ZaloAdsAutomatedRuleConditionDto>;\r\n scope: number;\r\n appliedIds?: number[];\r\n frequency?: number;\r\n created?: number;\r\n modified?: number;\r\n };\r\n status: number;\r\n };\r\n};\r\n\r\n/** Thay đổi trạng thái bật hoặc tắt (active/inactive) của một quy tắc tự động (Automated Rule) trên Zalo Ads theo ID quy tắc (`POST /api/automatedrules/change-status`). Dùng khi đã có `automatedRuleId` và cần tạm dừng (`status = 0`) hoặc kích hoạt lại (`status = 1`) quy tắc tự động. */\r\nexport type ZaloAdsChangeAutomatedRuleStatusRequest = {\r\n /** ID định danh duy nhất của quy tắc tự động cần thay đổi trạng thái (lấy từ `listAutomatedRules`). */\r\n automatedRuleId?: number;\r\n /** Danh sách ID quy tắc tự động (tương thích ngược). */\r\n automatedRuleIds?: number[];\r\n /** Trạng thái mới của quy tắc tự động: 0 = Tạm dừng / Tắt, 1 = Bật / Hoạt động. */\r\n status: 0 | 1 | 2 | number;\r\n};\r\n\r\nexport type ZaloAdsChangeAutomatedRuleStatusResponse = {\r\n /** Mã kết quả phản hồi từ Zalo Ads (0 là thành công). */\r\n code: number;\r\n /** Thông điệp kết quả thay đổi trạng thái quy tắc tự động (ví dụ: 'Thay đổi trạng thái thành công.'). */\r\n msg?: string;\r\n data?: number | boolean;\r\n};\r\n\r\n/** Tra cứu lịch sử thực thi (executeHistory) và lịch sử chỉnh sửa (editHistory) của một quy tắc tự động (Automated Rule) trên Zalo Ads theo ID quy tắc (`GET /api/automatedrules/history/{automatedRuleId}`). */\r\nexport type ZaloAdsGetAutomatedRuleHistoryRequest = {\r\n /** ID định danh duy nhất của quy tắc tự động cần xem lịch sử (lấy từ `listAutomatedRules`). */\r\n automatedRuleId: number;\r\n};\r\n\r\nexport type ZaloAdsGetAutomatedRuleHistoryResponse = {\r\n /** Mã kết quả phản hồi từ Zalo Ads (0 là thành công). */\r\n code: number;\r\n /** Thông điệp trạng thái phản hồi từ Zalo Ads (nếu có). */\r\n msg?: string;\r\n /** Dữ liệu lịch sử thực thi và lịch sử chỉnh sửa của quy tắc tự động. */\r\n data: {\r\n /** Danh sách lịch sử các lần tạo hoặc chỉnh sửa cấu hình/trạng thái quy tắc tự động. */\r\n editHistory: Array<{\r\n /** Tên thành viên / người dùng thực hiện chỉnh sửa quy tắc. */\r\n member: string;\r\n /** Danh sách các dòng mô tả nội dung thay đổi trong lần chỉnh sửa. */\r\n content: Array<string>;\r\n /** Thời điểm thực hiện chỉnh sửa (Unix timestamp tính bằng giây). */\r\n created: number;\r\n }>;\r\n /** Danh sách lịch sử các lần hệ thống tự động kích hoạt và thực thi quy tắc. */\r\n executeHistory: Array<{\r\n /** Danh sách các dòng mô tả kết quả thực thi tự động. */\r\n content?: Array<string>;\r\n /** Thời điểm hệ thống thực thi quy tắc (Unix timestamp tính bằng giây). */\r\n created?: number;\r\n }>;\r\n };\r\n};\r\n\r\n/** Xóa quy tắc tự động trên Zalo Ads. */\r\nexport type ZaloAdsDeleteAutomatedRuleRequest = {\r\n automatedRuleIds: number[];\r\n};\r\n\r\nexport type ZaloAdsDeleteAutomatedRuleResponse = {\r\n code: number;\r\n msg?: string;\r\n data?: number | boolean;\r\n};\r\n\r\n/** Tải tệp danh sách số điện thoại để tạo hoặc bổ sung nguồn audience tùy chỉnh trong Zalo Ads. Đây là mutation tool thuộc lane zalo-ads-audience; chỉ dùng khi đã có quyền xử lý dữ liệu cá nhân, tệp hợp lệ và xác nhận phạm vi upload. Không đưa số điện thoại hoặc URL tệp có dữ liệu cá nhân vào mô tả, example hay log. */\r\nexport type ZaloAdsUploadCustomAudiencePhoneListRequest = {\r\n /** Tệp danh sách số điện thoại tải lên. Capture đã quan sát MIME text/plain. */\r\n File: FileInput;\r\n /** Cờ truyền trong FormData của Zalo Ads. Capture đã quan sát giá trị \"1\"; chỉ dùng giá trị do luồng nghiệp vụ Zalo Ads yêu cầu. */\r\n isHash: \"0\" | \"1\";\r\n};\r\n\r\nexport type ZaloAdsUploadCustomAudiencePhoneListResponse = {\r\n /** Mã kết quả; 0 biểu thị thành công trong phản hồi đã quan sát. */\r\n code: number;\r\n /** Thông tin tệp đã được Zalo Ads tiếp nhận. */\r\n data: {\r\n /** ID Zalo liên quan đến kết quả upload. */\r\n zaloId: number;\r\n /** URL tệp do Zalo Ads trả về. Có thể chứa dữ liệu cá nhân, chỉ dùng trong phạm vi được ủy quyền. */\r\n fileUrl: string;\r\n /** Số dòng được báo trong kết quả upload. */\r\n lineNumber: number;\r\n };\r\n};\r\n\r\n/** Tải video lên kho media của tài khoản quảng cáo. Đây là mutation tool thuộc lane zalo-ads-media; dùng khi cần tạo asset video trước bước cấu hình quảng cáo. */\r\nexport type ZaloAdsUploadVideoRequest = {\r\n /** Tệp video tải lên. Capture đã quan sát field File (chữ hoa) với MIME video/mp4. */\r\n File?: FileInput;\r\n /** Alias tương thích chữ thường cho File. */\r\n file?: FileInput;\r\n};\r\n\r\nexport type ZaloAdsUploadVideoResponse = {\r\n code: number;\r\n /** URL video do Zalo Ads trả về. */\r\n data: string;\r\n msg?: string;\r\n};\r\n\r\n/** Tạo mới hoặc cập nhật cấu hình báo cáo tùy chỉnh với tên, cờ mặc định và danh sách chỉ số. Đây là mutation tool thuộc lane zalo-ads-reporting; dùng khi đã xác định bộ cột báo cáo cần lưu. */\r\nexport type ZaloAdsUpsertCustomReportRequest = {\r\n /** ID báo cáo; dùng 0 để tạo mới theo capture. */\r\n id: number;\r\n /** Tên báo cáo tùy chỉnh. */\r\n name: string;\r\n /** Các mã cột/chỉ số cần hiển thị trong báo cáo. */\r\n settings: Array<number>;\r\n /** Đặt làm báo cáo mặc định. */\r\n isDefault: boolean;\r\n};\r\n\r\nexport type ZaloAdsUpsertCustomReportResponse = {\r\n code: number;\r\n /** ID báo cáo vừa tạo hoặc cập nhật. */\r\n data: number;\r\n};\r\n\r\n/** Khởi tạo mới một chiến dịch Quảng cáo Commerce (`campaignType = 22`) trên Zalo Ads để quảng bá sản phẩm và chốt đơn trực tiếp qua trang đích bán hàng (Instant Page / Mini Page). Alias chuẩn theo tool `zalo_ads_create_commerce_campaign` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsCreateCommerceCampaignRequest = ZaloAdsCreateEcommerceCampaignRequest;\r\nexport type ZaloAdsCreateCommerceCampaignResponse = ZaloAdsCreateEcommerceCampaignResponse;\r\n\r\n/** Thiết lập và lưu cấu hình chi tiết cho mẫu Quảng cáo Commerce (`Type = 23`, gắn `MiniPageId`) trên Zalo Ads. Alias chuẩn theo tool `zalo_ads_update_commerce_ad` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsUpdateCommerceAdRequest = ZaloAdsUpdateEcommerceAdRequest;\r\nexport type ZaloAdsUpdateCommerceAdResponse = ZaloAdsUpdateEcommerceAdResponse;\r\n\r\n/** Khởi tạo mới một chiến dịch Quảng cáo Bài viết (`campaignType = 4`) trên Zalo Ads để quảng bá một bài viết đã xuất bản trên Zalo Official Account (`articleId`). Alias chuẩn theo tool `zalo_ads_create_article_campaign` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsCreateArticleCampaignRequest = ZaloAdsCreatePostCampaignRequest;\r\nexport type ZaloAdsCreateArticleCampaignResponse = ZaloAdsCreatePostCampaignResponse;\r\n\r\n/** Thiết lập và lưu cấu hình chi tiết cho mẫu Quảng cáo Bài viết (`Type = 3`, gắn `ZaloFeedId`) trên Zalo Ads. Alias chuẩn theo tool `zalo_ads_update_article_ad` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsUpdateArticleAdRequest = ZaloAdsUpdatePostAdRequest;\r\nexport type ZaloAdsUpdateArticleAdResponse = ZaloAdsUpdatePostAdResponse;\r\n\r\n/** Khởi tạo mới một chiến dịch Quảng cáo Zalo Official Account (`campaignType = 3`) trên Zalo Ads nhằm tăng lượt Quan tâm (Follow) cho trang Zalo OA. Alias chuẩn theo tool `zalo_ads_create_oa_campaign` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsCreateOaCampaignRequest = ZaloAdsCreateOfficialAccountCampaignRequest;\r\nexport type ZaloAdsCreateOaCampaignResponse = ZaloAdsCreateOfficialAccountCampaignResponse;\r\n\r\n/** Thiết lập và lưu cấu hình chi tiết cho mẫu Quảng cáo Zalo Official Account (`Type = 2`, `Action = 6`) trên Zalo Ads. Alias chuẩn theo tool `zalo_ads_update_oa_ad` trong Project Schema Zalo ADS. */\r\nexport type ZaloAdsUpdateOaAdRequest = ZaloAdsUpdateOfficialAccountAdRequest;\r\nexport type ZaloAdsUpdateOaAdResponse = ZaloAdsUpdateOfficialAccountAdResponse;\r\n\r\n/** Tạo mới 'Nhóm đối tượng đã lưu' (`caType = 1` - `DEFAULT`) trên Zalo Ads (`POST /api/ad/audience`). */\r\nexport type ZaloAdsCreateSavedAudienceRequest = {\r\n /** Tên nhóm đối tượng đã lưu (từ 2 đến 255 ký tự). */\r\n name: string;\r\n /** Mã loại nhóm đối tượng (cố định `1` = DEFAULT cho Nhóm đối tượng đã lưu). */\r\n caType?: 1;\r\n /** Chuỗi JSON (`JSON.stringify`) hoặc Object cấu hình nhắm chọn (`NewAgeRanges`, `Gender`, `Os`, `Location`, `AdvanceTargeting`, `IncludedAudiences`, `ExcludedAudiences`). */\r\n targeting: string | Record<string, unknown>;\r\n};\r\n\r\nexport type ZaloAdsCreateSavedAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Lấy danh sách tài khoản Zalo Official Account (OA) có dữ liệu chuyển đổi (Lead Signal) của nhà quảng cáo (`GET /api/ad/audience/leadSignal/oas`). */\r\nexport type ZaloAdsLeadSignalOaItem = {\r\n /** ID số của Official Account. */\r\n id: number;\r\n /** ID mã hóa chuỗi của Official Account. */\r\n noisedId?: string;\r\n /** Tên hiển thị của Official Account. */\r\n name: string;\r\n /** URL ảnh đại diện của Official Account. */\r\n avatarUrl?: string;\r\n};\r\n\r\nexport type ZaloAdsListLeadSignalOasResponse = {\r\n code: number;\r\n msg: string;\r\n data: Array<ZaloAdsLeadSignalOaItem>;\r\n};\r\n\r\nexport interface ZaloAdsConversionNameItemDto {\r\n /** Mã định danh duy nhất của sự kiện chuyển đổi (Conversion ID). */\r\n id: number;\r\n /** Tên sự kiện chuyển đổi (Conversion Name, duy nhất trong phạm vi tài khoản quảng cáo). */\r\n name: string;\r\n}\r\n\r\n/** Lấy danh sách rút gọn gồm ID và tên của toàn bộ các sự kiện chuyển đổi (Conversion) đã tạo trên tài khoản quảng cáo Zalo Ads (`GET /api/conversion/names`). */\r\nexport type ZaloAdsListConversionNamesRequest = Record<string, never>;\r\n\r\nexport type ZaloAdsListConversionNamesResponse = {\r\n /** Mã kết quả phản hồi từ Zalo Ads (`0` = Thành công). */\r\n code: number;\r\n /** Thông điệp kết quả phản hồi (ví dụ: `'success'`). */\r\n msg?: string;\r\n /** Mảng danh sách rút gọn `{ id, name }` các sự kiện chuyển đổi hiện có. */\r\n data: Array<ZaloAdsConversionNameItemDto>;\r\n};\r\n\r\n// ============================================================================\r\n// DEDICATED AUDIENCE TARGETING & CREATION TYPES (caType = 3, 6, 10, 11, 12, 13, 14, 15, 16)\r\n// ============================================================================\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng SĐT (`caType = 3`). */\r\nexport interface ZaloAdsPhoneAudienceTargetingDto {\r\n /** Tên file .txt đã tải lên (ví dụ: 'example.txt'). */\r\n Name: string;\r\n /** Đường dẫn URL công khai của file .txt sau khi upload. */\r\n Path: string;\r\n /** Tổng số lượng SĐT hợp lệ trong tệp. */\r\n Total: number;\r\n /** Mã định danh tệp SĐT do Zalo cấp. */\r\n ZaloId: number;\r\n /** Cờ đánh dấu SĐT đã được người dùng tự mã hóa SHA256 (bắt đầu bằng 84) trước khi tải lên. */\r\n IsHashedByUser?: boolean;\r\n /** Mặc định là 0. */\r\n OriginAudience?: number;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ danh sách Số điện thoại (`caType = 3` - `PHONE_LIST`). */\r\nexport type ZaloAdsCreatePhoneAudienceRequest = {\r\n name: string;\r\n caType?: 3;\r\n targeting: string | ZaloAdsPhoneAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreatePhoneAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng tương tự (`caType = 6`). */\r\nexport interface ZaloAdsLookalikeAudienceTargetingDto {\r\n /** ID của nhóm đối tượng SĐT gốc (`caType = 3`). Bắt buộc nhóm gốc phải có từ 1.000 đến 10.000 SĐT! */\r\n OriginAudience: number;\r\n /** Quy mô nhóm đối tượng mở rộng: 1.000.000, 1.500.000 hoặc 2.000.000. */\r\n Total: 1000000 | 1500000 | 2000000 | number;\r\n /** Tên nhóm đối tượng SĐT gốc. */\r\n Name: string;\r\n /** Đường dẫn file nhóm gốc (chuỗi rỗng hoặc URL). */\r\n Path?: string;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng tương tự Lookalike (`caType = 6` - `LOOKALIKE`). */\r\nexport type ZaloAdsCreateLookalikeAudienceRequest = {\r\n name: string;\r\n caType?: 6;\r\n targeting: string | ZaloAdsLookalikeAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateLookalikeAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng sự kiện Form (`caType = 12`). */\r\nexport interface ZaloAdsFormEventAudienceTargetingDto {\r\n /** 1: Đã xem Form nhưng chưa submit, 2: Đã xem Form và submit, 3: Đã xem Form, 4: Mở chat OA từ Form. */\r\n EventType: 1 | 2 | 3 | 4 | number;\r\n /** ID mã hóa chuỗi (noisedId) của tài khoản OA. */\r\n OaId: string;\r\n /** Khoảng thời gian lưu vết người dùng (1 đến 90 ngày; gợi ý: 7, 14, 30, 60, 90). */\r\n NumDays: number;\r\n /** Danh sách ID biểu mẫu Zalo Form. */\r\n FormIds: string[];\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Zalo Form (`caType = 12` - `FORM_EVENT_AUDIENCE`). */\r\nexport type ZaloAdsCreateFormEventAudienceRequest = {\r\n name: string;\r\n caType?: 12;\r\n targeting: string | ZaloAdsFormEventAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateFormEventAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng sự kiện Tin nhắn OA (`caType = 11`). */\r\nexport interface ZaloAdsMessageOaEventAudienceTargetingDto {\r\n /** 1: Liên hệ sau khi xem quảng cáo tin nhắn. */\r\n EventId: 1 | number;\r\n /** ID mã hóa chuỗi (noisedId) của tài khoản OA xác thực. */\r\n OaId: string;\r\n /** Khoảng thời gian lưu vết người dùng (1 đến 90 ngày). */\r\n NumDays: number;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn OA (`caType = 11` - `MESSAGE_AUDIENCE`). */\r\nexport type ZaloAdsCreateMessageOaEventAudienceRequest = {\r\n name: string;\r\n caType?: 11;\r\n targeting: string | ZaloAdsMessageOaEventAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateMessageOaEventAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng sự kiện Tin nhắn cá nhân (`caType = 14`). */\r\nexport interface ZaloAdsMessagePersonalEventAudienceTargetingDto {\r\n /** 1: Đã liên hệ, 2: Đã xem nội dung nhưng không liên hệ, 3: Dành thời gian xem ảnh và video ở carousel nhưng không liên hệ. */\r\n EventId?: 1 | 2 | 3 | number;\r\n /** Bí danh tương thích ngược cho EventId. */\r\n EventType?: 1 | 2 | 3 | number;\r\n /** Khoảng thời gian lưu vết người dùng (1 đến 90 ngày). */\r\n NumDays: number;\r\n /** Danh sách publicId hoặc ID số của các Mini Page template Tin nhắn. */\r\n PageIds: string[];\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn cá nhân (`caType = 14` - `MESSAGE_PERSONAL_EVENT_AUDIENCE`). */\r\nexport type ZaloAdsCreateMessagePersonalEventAudienceRequest = {\r\n name: string;\r\n caType?: 14;\r\n targeting: string | ZaloAdsMessagePersonalEventAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateMessagePersonalEventAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng Trung tâm Lead - Zalo Form (`caType = 10`). */\r\nexport interface ZaloAdsFormLeadAudienceTargetingDto {\r\n Name: string;\r\n FormAudienceId: string | number;\r\n Total: number;\r\n IsCommerce?: false;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Zalo Form (`caType = 10` - `FORM_AUDIENCE`). */\r\nexport type ZaloAdsCreateFormLeadAudienceRequest = {\r\n name: string;\r\n caType?: 10;\r\n targeting: string | ZaloAdsFormLeadAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateFormLeadAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng Trung tâm Lead - Commerce Form (`caType = 15`). */\r\nexport interface ZaloAdsCommerceFormAudienceTargetingDto {\r\n Name: string;\r\n FormAudienceId: string | number;\r\n Total: number;\r\n IsCommerce: true;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Commerce Form (`caType = 15` - `COMMERCE_FORM_AUDIENCE`). */\r\nexport type ZaloAdsCreateCommerceFormAudienceRequest = {\r\n name: string;\r\n caType?: 15;\r\n targeting: string | ZaloAdsCommerceFormAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateCommerceFormAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng Trung tâm Lead - Kịch bản Tin nhắn OA (`caType = 13`). */\r\nexport interface ZaloAdsMessageOaLeadAudienceTargetingDto {\r\n Name: string;\r\n MessageOAAudienceId: string | number;\r\n Total: number;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Kịch bản Tin nhắn OA (`caType = 13` - `MESSAGE_OA_AUDIENCE`). */\r\nexport type ZaloAdsCreateMessageOaLeadAudienceRequest = {\r\n name: string;\r\n caType?: 13;\r\n targeting: string | ZaloAdsMessageOaLeadAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateMessageOaLeadAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Cấu hình targeting cho Nhóm đối tượng Dữ liệu chuyển đổi Lead Signal (`caType = 16`). */\r\nexport interface ZaloAdsLeadSignalAudienceTargetingDto {\r\n /** ID số của Official Account có dữ liệu chuyển đổi. */\r\n OaId: number;\r\n /** Tên nhãn sự kiện chuyển đổi. */\r\n Label: string;\r\n /** Mức điều chỉnh độ rộng đối tượng từ 1 đến 20 (mặc định: 5). */\r\n SegmentCount: number;\r\n /** Ước tính số người tiếp cận (Math.round(A30 / 20 * SegmentCount)). */\r\n Total: number;\r\n}\r\n\r\n/** Tạo mới Nhóm đối tượng từ Dữ liệu chuyển đổi Lead Signal (`caType = 16` - `LEAD_SIGNAL_AUDIENCE`). */\r\nexport type ZaloAdsCreateLeadSignalAudienceRequest = {\r\n name: string;\r\n caType?: 16;\r\n targeting: string | ZaloAdsLeadSignalAudienceTargetingDto;\r\n};\r\nexport type ZaloAdsCreateLeadSignalAudienceResponse = ZaloAdsCreateCustomAudienceResponse;\r\n\r\n/** Lấy số liệu báo cáo tổng quan Dashboard (GET https://ads.zalo.me/reportapi/report/overview). */\r\nexport type ZaloAdsGetReportOverviewRequest = {\r\n /** Chuỗi JSON mã hóa URL, ví dụ: '{\"StartDate\":1768755600,\"EndDate\":1768928399}' */\r\n data: string;\r\n};\r\n\r\nexport type ZaloAdsGetReportOverviewResponse = {\r\n code: number;\r\n data: Record<string, Record<string, number>>;\r\n extend?: {\r\n totalUniqueUser?: number;\r\n };\r\n};\r\n\r\n/** Lấy báo cáo nhân khẩu học của chiến dịch hoặc quảng cáo (GET https://ads.zalo.me/api/demographics/report). */\r\nexport type ZaloAdsGetDemographicsReportRequest = {\r\n campaignId: number;\r\n adId: number;\r\n startDate: number;\r\n endDate: number;\r\n agencyId?: number;\r\n from?: number;\r\n to?: number;\r\n};\r\n\r\nexport type ZaloAdsGetDemographicsReportResponse = {\r\n cAgeGender?: Record<string, number>;\r\n iAgeGender?: Record<string, number>;\r\n location?: Record<string, unknown>;\r\n};\r\n\r\n/** Xóa cấu hình báo cáo tùy chỉnh theo ID (POST https://ads.zalo.me/reportapi/custom-report/delete/{id}). */\r\nexport type ZaloAdsDeleteCustomReportRequest = {\r\n id: number | string;\r\n};\r\n\r\nexport type ZaloAdsDeleteCustomReportResponse = {\r\n code?: number;\r\n msg?: string;\r\n data?: unknown;\r\n};\r\n\r\n/** Lấy danh sách các bộ lọc báo cáo đã lưu (GET https://ads.zalo.me/reportapi/api/filter/list). */\r\nexport type ZaloAdsListReportFiltersRequest = {\r\n /** 0: all/chung, 1: campaign, 2: ad */\r\n model: number | string;\r\n};\r\n\r\nexport type ZaloAdsListReportFiltersResponse = Array<{\r\n id: number;\r\n name: string;\r\n content: string;\r\n model: number;\r\n}>;\r\n\r\n\r\n\r\n/** Xuất và tải báo cáo hiệu quả quảng cáo dạng file Excel (.xlsx) qua endpoint thu thập và xuất báo cáo (POST https://ads.zalo.me/api/collect). */\r\nexport type ZaloAdsDownloadReportRequest = {\r\n /** Hành động / chủ đề tải báo cáo; mặc định là \"cd.download.report\". */\r\n t?: \"cd.download.report\" | string;\r\n /** Danh sách ID các mẫu quảng cáo cần xuất báo cáo (ví dụ: [19770157]). */\r\n adIds: number[];\r\n /** Mã trạng thái lọc quảng cáo khi xuất báo cáo (ví dụ: 2 = Đang chạy). */\r\n status?: number;\r\n /** Bộ lọc thời gian: 0 = Toàn thời gian / Tùy chỉnh. */\r\n dateFilter?: number;\r\n /** Loại chỉ số dữ liệu báo cáo (100001: Lượt nhấn / Chi phí / Hiển thị). */\r\n reportKind?: number;\r\n /** Unix timestamp thời điểm gửi lệnh xuất báo cáo (giây). */\r\n et?: number;\r\n};\r\n\r\nexport type ZaloAdsDownloadReportResponse = Blob;\r\n","/**\r\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Chiến dịch & Quảng cáo Zalo Ads:\r\n * 1. Khởi tạo 8 loại chiến dịch (Website, Form, Message, OA, Video, Commerce, Article, Display)\r\n * 2. Thiết lập & cập nhật chi tiết mẫu quảng cáo (Ad Types: 5, 18, 30, 2, 11, 28, 3, 21)\r\n * 3. Đổi tên, thay đổi trạng thái, xóa chiến dịch và xóa quảng cáo\r\n *\r\n * Tích hợp toàn bộ quy chuẩn giao diện (UI reverse engineering), giới hạn độ dài ký tự,\r\n * quy chuẩn media, mã ID ngầm và bẫy kỹ thuật đúc kết từ live test trên máy chủ Zalo Ads.\r\n */\r\n\r\nimport {\r\n ZALO_REGION_PROVINCE_CODES,\r\n ZALO_NEW_REGION_PROVINCE_CODES,\r\n ZALO_PROVINCE_MERGE_MAPPING,\r\n} from \"./audiences.validator\";\r\nimport {\r\n ZaloAdsActionType,\r\n ZaloAdsAgeRangeId,\r\n ZaloAdsOsId,\r\n ZaloAdsDeliveryType,\r\n ZaloAdsUseConversion,\r\n type ZaloAdsCampaignCreatePayloadDto,\r\n type ZaloAdsAdUpdatePayloadDto,\r\n type ZaloAdsUpdateNewAdsRequest,\r\n type ZaloAdsCreateCommerceCampaignPayloadDto,\r\n type ZaloAdsCreateDisplayCampaignPayloadDto,\r\n type ZaloAdsCreateWebsiteCampaignPayloadDto,\r\n type ZaloAdsCreateFormCampaignPayloadDto,\r\n type ZaloAdsCreateMessageCampaignPayloadDto,\r\n type ZaloAdsCreateOfficialAccountCampaignPayloadDto,\r\n type ZaloAdsCreateArticleCampaignPayloadDto,\r\n type ZaloAdsCreateVideoCampaignPayloadDto,\r\n} from \"../dtos/ads.dto\";\r\n\r\nexport interface CampaignValidationResult<T = unknown> {\r\n isValid: boolean;\r\n errors: string[];\r\n warnings: string[];\r\n data?: T;\r\n}\r\n\r\nexport interface ValidateCampaignOptions {\r\n strictMode?: boolean;\r\n}\r\n\r\nexport interface ValidateAdOptions {\r\n strictMode?: boolean;\r\n}\r\n\r\n/** Danh sách mã CampaignType hợp lệ trên Zalo Ads */\r\nexport const VALID_CAMPAIGN_TYPES = {\r\n WEBSITE: 6,\r\n FORM: 17,\r\n MESSAGE: 18,\r\n OA: 3,\r\n VIDEO: 14,\r\n COMMERCE: 22,\r\n ARTICLE: 4,\r\n DISPLAY: 20,\r\n} as const;\r\n\r\n/** Danh sách mã AdType hợp lệ thực tế do máy chủ Zalo Ads xử lý */\r\nexport const VALID_AD_TYPES = {\r\n WEBSITE: 5,\r\n FORM: 18,\r\n MESSAGE: 30,\r\n OA: 2,\r\n VIDEO: 11,\r\n COMMERCE: 28, // Server trả về 28 (không phải 23)\r\n ARTICLE: 3,\r\n DISPLAY: 21, // Masthead Mobile (Format 1) & Masthead Desktop (Format 2)\r\n DISPLAY_HALFPAGE: 26, // Halfpage Mobile (Format 13) & Halfpage PC (Format 14)\r\n DISPLAY_MEDIUM_RECTANGLE: 23, // Medium Rectangle 300x250 (Format 6)\r\n} as const;\r\n\r\n/** Danh mục mã AdFormat chính thức của các định dạng Quảng cáo Display */\r\nexport const ZALO_DISPLAY_AD_FORMAT = {\r\n MASTHEAD_MOBILE: 1, // Kích thước 640x360, Os: [0, 1]\r\n MASTHEAD_DESKTOP: 2, // Kích thước 970x250, Os: [3]\r\n MEDIUM_RECTANGLE: 6, // Kích thước 300x250, Os: [0, 1]\r\n HALFPAGE_MOBILE: 13, // Kích thước 300x600, Os: [0, 1]\r\n HALFPAGE_PC: 14, // Kích thước 300x600, Os: [3]\r\n} as const;\r\n\r\n/** Danh sách CTA hợp lệ cho từng loại Ad */\r\nexport const ALLOWED_CTAS_PER_AD_TYPE: Record<number, number[]> = {\r\n // Website (Type 5): 9 CTAs\r\n [VALID_AD_TYPES.WEBSITE]: [\r\n ZaloAdsActionType.DAT_NGAY,\r\n ZaloAdsActionType.MUA_NGAY,\r\n ZaloAdsActionType.THU_NGAY,\r\n ZaloAdsActionType.TAI_NGAY,\r\n ZaloAdsActionType.XEM_THEM,\r\n ZaloAdsActionType.NGHE_NGAY,\r\n ZaloAdsActionType.CHOI_NGAY,\r\n ZaloAdsActionType.DANG_KY,\r\n ZaloAdsActionType.GOI_DIEN,\r\n ],\r\n // Video (Type 11): 8 CTAs\r\n [VALID_AD_TYPES.VIDEO]: [\r\n ZaloAdsActionType.DAT_NGAY,\r\n ZaloAdsActionType.MUA_NGAY,\r\n ZaloAdsActionType.THU_NGAY,\r\n ZaloAdsActionType.TAI_NGAY,\r\n ZaloAdsActionType.XEM_THEM,\r\n ZaloAdsActionType.NGHE_NGAY,\r\n ZaloAdsActionType.CHOI_NGAY,\r\n ZaloAdsActionType.DANG_KY,\r\n ],\r\n // Article (Type 3): 7 CTAs\r\n [VALID_AD_TYPES.ARTICLE]: [\r\n ZaloAdsActionType.DAT_NGAY,\r\n ZaloAdsActionType.MUA_NGAY,\r\n ZaloAdsActionType.THU_NGAY,\r\n ZaloAdsActionType.TAI_NGAY,\r\n ZaloAdsActionType.XEM_THEM,\r\n ZaloAdsActionType.CHOI_NGAY,\r\n ZaloAdsActionType.DANG_KY,\r\n ],\r\n // Form (Type 18): 5 CTAs\r\n [VALID_AD_TYPES.FORM]: [\r\n ZaloAdsActionType.DAT_NGAY,\r\n ZaloAdsActionType.MUA_NGAY,\r\n ZaloAdsActionType.THU_NGAY,\r\n ZaloAdsActionType.XEM_THEM,\r\n ZaloAdsActionType.DANG_KY,\r\n ],\r\n // Commerce (Type 28): 3 CTAs\r\n [VALID_AD_TYPES.COMMERCE]: [\r\n ZaloAdsActionType.DAT_NGAY,\r\n ZaloAdsActionType.MUA_NGAY,\r\n ZaloAdsActionType.XEM_THEM,\r\n ],\r\n // OA (Type 2): Cố định Quan tâm OA (6)\r\n [VALID_AD_TYPES.OA]: [ZaloAdsActionType.QUAN_TAM_OA],\r\n // Display (Type 21) & Display Halfpage (Type 26): Hỗ trợ các hành động cơ bản\r\n [VALID_AD_TYPES.DISPLAY]: [\r\n ZaloAdsActionType.DAT_NGAY,\r\n ZaloAdsActionType.MUA_NGAY,\r\n ZaloAdsActionType.THU_NGAY,\r\n ZaloAdsActionType.TAI_NGAY,\r\n ZaloAdsActionType.XEM_THEM,\r\n ZaloAdsActionType.NGHE_NGAY,\r\n ZaloAdsActionType.CHOI_NGAY,\r\n ZaloAdsActionType.DANG_KY,\r\n ZaloAdsActionType.GOI_DIEN,\r\n ],\r\n [VALID_AD_TYPES.DISPLAY_HALFPAGE]: [\r\n ZaloAdsActionType.DAT_NGAY,\r\n ZaloAdsActionType.MUA_NGAY,\r\n ZaloAdsActionType.THU_NGAY,\r\n ZaloAdsActionType.TAI_NGAY,\r\n ZaloAdsActionType.XEM_THEM,\r\n ZaloAdsActionType.NGHE_NGAY,\r\n ZaloAdsActionType.CHOI_NGAY,\r\n ZaloAdsActionType.DANG_KY,\r\n ZaloAdsActionType.GOI_DIEN,\r\n ],\r\n [VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE]: [\r\n ZaloAdsActionType.DAT_NGAY,\r\n ZaloAdsActionType.MUA_NGAY,\r\n ZaloAdsActionType.THU_NGAY,\r\n ZaloAdsActionType.TAI_NGAY,\r\n ZaloAdsActionType.XEM_THEM,\r\n ZaloAdsActionType.NGHE_NGAY,\r\n ZaloAdsActionType.CHOI_NGAY,\r\n ZaloAdsActionType.DANG_KY,\r\n ZaloAdsActionType.GOI_DIEN,\r\n ],\r\n};\r\n\r\n/**\r\n * Kiểm tra tính hợp lệ payload tạo mới Chiến dịch Zalo Ads (POST /zaapi/addNewCamp).\r\n */\r\nexport function validateCreateCampaignPayload(\r\n payload: Partial<ZaloAdsCampaignCreatePayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 1. Tên chiến dịch\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"name là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"name không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n // 2. Loại chiến dịch (campaignType)\r\n const validTypes = Object.values(VALID_CAMPAIGN_TYPES);\r\n if (payload.campaignType === undefined || payload.campaignType === null) {\r\n errors.push(\"campaignType là bắt buộc.\");\r\n } else if (!validTypes.includes(payload.campaignType as any)) {\r\n errors.push(\r\n `campaignType: ${payload.campaignType} không hợp lệ. Các loại hỗ trợ: 6 (Website), 17 (Form), 18 (Message), 3 (OA), 14 (Video), 22 (Commerce), 4 (Article), 20 (Display).`\r\n );\r\n }\r\n\r\n // 3. Official Account ID (pageId)\r\n // Các loại bắt buộc OA (pageId > 0): Form (17), Message (18), OA (3), Commerce (22), Article (4)\r\n // Các loại KHÔNG bắt buộc OA: Website (6), Video (14), Display (20)\r\n const OA_REQUIRED_CAMPAIGN_TYPES = [\r\n VALID_CAMPAIGN_TYPES.FORM,\r\n VALID_CAMPAIGN_TYPES.MESSAGE,\r\n VALID_CAMPAIGN_TYPES.OA,\r\n VALID_CAMPAIGN_TYPES.COMMERCE,\r\n VALID_CAMPAIGN_TYPES.ARTICLE,\r\n ];\r\n if (payload.campaignType !== undefined && OA_REQUIRED_CAMPAIGN_TYPES.includes(payload.campaignType as any)) {\r\n if (!payload.pageId || payload.pageId <= 0) {\r\n errors.push(\"pageId của Official Account là bắt buộc đối với loại chiến dịch này (phải > 0, chọn từ Danh sách tài khoản OA).\");\r\n }\r\n } else if (payload.campaignType === VALID_CAMPAIGN_TYPES.DISPLAY) {\r\n if (payload.pageId !== -1 && payload.pageId !== 0 && !payload.pageId) {\r\n warnings.push(\"Quảng cáo Display thường sử dụng pageId = -1.\");\r\n }\r\n }\r\n\r\n // 4. Ràng buộc theo từng loại chiến dịch\r\n switch (payload.campaignType) {\r\n case VALID_CAMPAIGN_TYPES.WEBSITE:\r\n if (!payload.targetUrl || typeof payload.targetUrl !== \"string\" || !payload.targetUrl.trim()) {\r\n errors.push(\"targetUrl là bắt buộc đối với Quảng cáo Website.\");\r\n } else if (!/^https?:\\/\\/.+/i.test(payload.targetUrl)) {\r\n errors.push(\"targetUrl phải là một đường link hợp lệ bắt đầu bằng http:// hoặc https://.\");\r\n }\r\n break;\r\n\r\n case VALID_CAMPAIGN_TYPES.ARTICLE:\r\n if (!payload.articleId || payload.articleId <= 0) {\r\n errors.push(\"articleId là bắt buộc đối với Quảng cáo Bài Viết (phải > 0, lấy từ getOwnedArticles).\");\r\n }\r\n break;\r\n\r\n case VALID_CAMPAIGN_TYPES.COMMERCE:\r\n if (payload.productId === undefined || payload.productId === null) {\r\n warnings.push(\"Quảng cáo Commerce nên chỉ định productId (hoặc -1/0 khi dùng Instant Page sản phẩm).\");\r\n }\r\n break;\r\n\r\n case VALID_CAMPAIGN_TYPES.FORM:\r\n case VALID_CAMPAIGN_TYPES.MESSAGE:\r\n // Form & Message có thể gán formId / flowId ở bước updateAd\r\n break;\r\n }\r\n\r\n // 5. Ngân sách & phương thức chi tiêu\r\n if (payload.budgetType !== undefined && payload.budgetlimit !== undefined) {\r\n if (payload.budgetType === 2) {\r\n // Toàn lịch chạy\r\n if (payload.budgetlimit > 0 && payload.budgetlimit < 600000) {\r\n errors.push(\"Ngân sách cho Toàn lịch chạy tối thiểu là 600,000 VNĐ.\");\r\n }\r\n } else if (payload.budgetType === 1) {\r\n // Mỗi ngày\r\n if (payload.budgetlimit > 0 && payload.budgetlimit < 50) {\r\n warnings.push(\"Số lượng tương tác mỗi ngày tối thiểu được khuyến nghị từ 50 lượt.\");\r\n }\r\n }\r\n }\r\n\r\n // 6. Kiểm tra cơ chế Multi-Ad\r\n if (payload.campaignId && payload.campaignId > 0) {\r\n if (payload.adId !== 0) {\r\n warnings.push(\"Khi thêm Ad mới vào chiến dịch hiện có (Multi-Ad), adId nên để bằng 0.\");\r\n }\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Kiểm tra tính hợp lệ payload Cập nhật Mẫu Quảng cáo (POST /zaapi/UpdateAd).\r\n */\r\nexport function validateUpdateAdPayload(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // 1. Định danh bắt buộc\r\n if (!payload.AdId || payload.AdId <= 0) {\r\n errors.push(\"AdId là bắt buộc (phải > 0).\");\r\n }\r\n if (!payload.CampaignId || payload.CampaignId <= 0) {\r\n errors.push(\"CampaignId là bắt buộc (phải > 0).\");\r\n }\r\n\r\n // 2. Tên quảng cáo\r\n if (!payload.AdName || !payload.AdName.trim()) {\r\n errors.push(\"AdName là bắt buộc và không được để trống.\");\r\n } else if (payload.AdName.length > 255) {\r\n errors.push(`AdName quá dài (${payload.AdName.length}/255 ký tự).`);\r\n }\r\n\r\n // 3. Kiểm tra thông tin nội dung quảng cáo (Settings.AdInfo)\r\n const adInfo = payload.Settings?.AdInfo;\r\n if (!adInfo) {\r\n errors.push(\"Settings.AdInfo là bắt buộc.\");\r\n } else {\r\n // Xác định xem quảng cáo có thuộc định dạng Display Banner (Type 21 Masthead, Type 26 Halfpage Mobile, Type 23 Medium Rectangle...)\r\n const rawTypeNum = Number(payload.Type);\r\n const isDisplayAd =\r\n rawTypeNum === 21 ||\r\n rawTypeNum === 23 ||\r\n rawTypeNum === 26 ||\r\n adInfo.AdFormat === 1 ||\r\n adInfo.AdFormat === 2 ||\r\n adInfo.AdFormat === 6 ||\r\n adInfo.AdFormat === 13 ||\r\n adInfo.AdFormat === 14;\r\n\r\n // Caption (Chú thích)\r\n // Đối với Quảng cáo Display dạng banner đồ họa (Masthead Type 21, Halfpage Type 26, AdFormat 13...),\r\n // thông điệp hiển thị hoàn toàn trên graphic banner nên Caption/Title được phép để chuỗi rỗng.\r\n if (!adInfo.Caption || !adInfo.Caption.trim()) {\r\n if (!isDisplayAd) {\r\n errors.push(\"Settings.AdInfo.Caption là bắt buộc.\");\r\n }\r\n } else {\r\n const captionLen = adInfo.Caption.trim().length;\r\n if (!isDisplayAd && captionLen < 35) {\r\n errors.push(`Settings.AdInfo.Caption quá ngắn (${captionLen}/35 ký tự tối thiểu).`);\r\n } else if (captionLen > 90) {\r\n errors.push(`Settings.AdInfo.Caption quá dài (${captionLen}/90 ký tự tối đa).`);\r\n }\r\n }\r\n\r\n // LongCaption (Chú thích mở rộng - không bắt buộc, nhưng nếu có phải từ 90 đến 2,000 ký tự)\r\n const longCaption = adInfo.LongCaption ?? adInfo.MoreInfo;\r\n if (longCaption !== undefined && longCaption !== null && longCaption.trim().length > 0) {\r\n const longCaptionLen = longCaption.trim().length;\r\n if (longCaptionLen < 90) {\r\n errors.push(\r\n `Settings.AdInfo.LongCaption (Chú thích mở rộng) quá ngắn (${longCaptionLen}/90 ký tự tối thiểu). Theo quy chuẩn Zalo Ads, trường này không bắt buộc, nhưng nếu nhập thì bắt buộc phải từ 90 đến 2,000 ký tự.`\r\n );\r\n } else if (longCaptionLen > 2000) {\r\n errors.push(\r\n `Settings.AdInfo.LongCaption (Chú thích mở rộng) quá dài (${longCaptionLen}/2000 ký tự tối đa).`\r\n );\r\n }\r\n\r\n // Kiểm tra đồng bộ mã bố cục mở rộng XTemplates (49: LONG_CAPTION)\r\n if (adInfo.XTemplates && Array.isArray(adInfo.XTemplates) && !adInfo.XTemplates.includes(49)) {\r\n warnings.push(\r\n \"Khi có Chú thích mở rộng (LongCaption), bạn nên thêm mã 49 (LONG_CAPTION) vào Settings.AdInfo.XTemplates để kích hoạt giao diện hiển thị bài viết dài trên Zalo Feed.\"\r\n );\r\n }\r\n }\r\n\r\n // TargetUrl: Bắt buộc đối với Quảng cáo Display\r\n if (isDisplayAd) {\r\n const targetUrl =\r\n typeof adInfo.TargetUrl === \"object\"\r\n ? (adInfo.TargetUrl as any)?.Url\r\n : adInfo.TargetUrl;\r\n if (!targetUrl || typeof targetUrl !== \"string\" || !targetUrl.trim()) {\r\n errors.push(\"Settings.AdInfo.TargetUrl là bắt buộc đối với Quảng cáo Display.\");\r\n } else if (!/^https?:\\/\\//i.test(targetUrl.trim())) {\r\n errors.push(\"Settings.AdInfo.TargetUrl phải là một đường dẫn hợp lệ (bắt đầu bằng http:// hoặc https://).\");\r\n }\r\n }\r\n\r\n // Kiểm tra Nút CTA (Action)\r\n if (adInfo.Action !== undefined && payload.Type) {\r\n const allowedCtas = ALLOWED_CTAS_PER_AD_TYPE[payload.Type];\r\n if (allowedCtas && !allowedCtas.includes(adInfo.Action)) {\r\n warnings.push(\r\n `Mã hành động Action: ${adInfo.Action} có thể không nằm trong danh mục nút CTA hỗ trợ cho Ad Type ${payload.Type}.`\r\n );\r\n }\r\n }\r\n }\r\n\r\n // 4. Kiểm tra Giá thầu & Ngân sách (Settings.Price)\r\n const price = payload.Settings?.Price;\r\n if (!price) {\r\n errors.push(\"Settings.Price là bắt buộc.\");\r\n } else {\r\n // Quy tắc sống còn đảo ngược Price.Type\r\n if (payload.Type === VALID_AD_TYPES.WEBSITE) {\r\n if (price.Type !== 1) {\r\n errors.push(\r\n \"Đối với Quảng cáo Website (Type 5), Price.Type bắt buộc phải bằng 1 (CPC). Nếu truyền 2 sẽ bị máy chủ lỗi.\"\r\n );\r\n }\r\n if (price.LimitType === 1) {\r\n errors.push(\r\n \"Quảng cáo Website không hỗ trợ LimitType: 1 (tổng ngân sách). Bắt buộc phải dùng LimitType: 0 (ngân sách ngày).\"\r\n );\r\n }\r\n } else if (payload.Type === VALID_AD_TYPES.VIDEO) {\r\n // Quảng cáo Video (Type 11): Chạy trên nền tảng Video Platform, bắt buộc dùng CPM (Type 1) hoặc CPV (Type 7)\r\n if (price.Type !== 1 && price.Type !== 7) {\r\n errors.push(\r\n \"Đối với Quảng cáo Video (Type 11) trên Video Platform, Price.Type bắt buộc là 1 (CPM - Lượt hiển thị) hoặc 7 (CPV - Lượt xem). Nếu truyền 2 (CPC), form chỉnh sửa của Zalo Ads sẽ không hiển thị được giá và số lượng.\"\r\n );\r\n }\r\n if (price.Type === 1 && (price.Limit ?? 0) < 50) {\r\n errors.push(\r\n \"Đối với Quảng cáo Video CPM, số lượng hiển thị tối thiểu (Price.Limit) là 50 (tương ứng 50,000 lượt hiển thị).\"\r\n );\r\n }\r\n } else if (\r\n payload.Type === VALID_AD_TYPES.COMMERCE ||\r\n payload.Type === VALID_AD_TYPES.ARTICLE ||\r\n payload.Type === VALID_AD_TYPES.FORM\r\n ) {\r\n if (price.Type !== 2) {\r\n errors.push(\r\n `Đối với Ad Type ${payload.Type}, Price.Type bắt buộc phải bằng 2 (CPC).`\r\n );\r\n }\r\n } else if (payload.Type === VALID_AD_TYPES.OA) {\r\n // Quảng cáo Zalo Official Account (Type 2): Hỗ trợ Price.Type = 2 (CPC - Lượt nhấn) hoặc Price.Type = 5 (CPA - Lượt quan tâm Beta)\r\n if (price.Type !== 2 && price.Type !== 5) {\r\n errors.push(\r\n \"Đối với Quảng cáo OA (Type 2), Price.Type chỉ hỗ trợ 2 (Lượt nhấn - CPC) hoặc 5 (Lượt quan tâm - CPA Beta).\"\r\n );\r\n }\r\n if (price.Type === 2) {\r\n // CPC: Đặt giá thủ công theo số lượng tương tác\r\n if (price.SpendingMethod !== 0 && price.SpendingMethod !== undefined) {\r\n errors.push(\r\n \"Khi tính tiền theo Lượt nhấn (Price.Type = 2 / CPC), SpendingMethod bắt buộc phải bằng 0 (Đặt giá thầu thủ công theo số lượng tương tác).\"\r\n );\r\n }\r\n if (price.Bid !== undefined && price.Bid < 650) {\r\n errors.push(\r\n `Giá đặt mỗi lượt nhấn (Price.Bid) tối thiểu là 650 VNĐ (sàn hệ thống Zalo Ads). Hiện tại đang truyền: ${price.Bid}đ.`\r\n );\r\n }\r\n if (price.Limit !== undefined && price.Limit < 50) {\r\n errors.push(\r\n `Số lượng lượt nhấn (Price.Limit) tối thiểu là 50 lượt/ngày (minCTA = 50). Hiện tại đang truyền: ${price.Limit}.`\r\n );\r\n } else if (price.Limit !== undefined && price.Limit > 5000) {\r\n warnings.push(\r\n `⚠️ CẢNH BÁO BẪY NGÂN SÁCH ZALO ADS: Khi Price.Type = 2 (CPC), trường Price.Limit mang ý nghĩa là SỐ LƯỢNG LƯỢT NHẤN (Clicks count), KHÔNG PHẢI SỐ TIỀN VNĐ. Bạn đang truyền Limit = ${price.Limit} lượt nhấn, có thể khiến Tổng chi phí dự kiến tăng vọt lên hàng trăm triệu VNĐ.`\r\n );\r\n }\r\n } else if (price.Type === 5) {\r\n // CPA (Lượt quan tâm OA): Hỗ trợ 2 cách đặt giá:\r\n // 1. Tổng ngân sách quảng cáo (SpendingMethod = 1 / TOTALBUDGET): Tự động tối ưu chi phí\r\n // 2. Tự đặt giá (SpendingMethod = 0 / QUANTITY): Đặt giá thầu thủ công cho từng lượt quan tâm\r\n if (price.SpendingMethod === 1) {\r\n // Cách 1: Tổng ngân sách quảng cáo\r\n if (price.Bid !== undefined && price.Bid !== 0) {\r\n errors.push(\r\n \"Khi chọn 'Tổng ngân sách quảng cáo' cho Lượt quan tâm (SpendingMethod = 1), trường Bid bắt buộc phải bằng 0 (hệ thống tự động đấu thầu).\"\r\n );\r\n }\r\n if (price.Limit !== undefined && price.Limit < 500000) {\r\n errors.push(\r\n `Ngân sách tối thiểu cho Lượt quan tâm theo Tổng ngân sách là 500,000 VNĐ / ngày (Price.Limit >= 500000). Hiện tại đang truyền: ${price.Limit}đ.`\r\n );\r\n }\r\n } else if (price.SpendingMethod === 0) {\r\n // Cách 2: Tự đặt giá (Manual Bid cho Lượt quan tâm)\r\n if (price.Bid !== undefined && price.Bid < 10000) {\r\n errors.push(\r\n `Giá đặt mỗi Lượt quan tâm (Price.Bid) tối thiểu là 10,000 VNĐ / lượt quan tâm (sàn hệ thống cho OA Follow). Hiện tại đang truyền: ${price.Bid}đ.`\r\n );\r\n }\r\n if (price.Limit !== undefined && price.Limit < 100) {\r\n errors.push(\r\n `Số lượng Lượt quan tâm (Price.Limit) tối thiểu là 100 lượt (minCTA = 100). Hiện tại đang truyền: ${price.Limit}.`\r\n );\r\n } else if (price.Limit !== undefined && price.Limit > 5000) {\r\n warnings.push(\r\n `⚠️ CẢNH BÁO BẪY NGÂN SÁCH ZALO ADS: Khi chọn 'Tự đặt giá' cho Lượt quan tâm (SpendingMethod = 0), trường Price.Limit là SỐ LƯỢNG LƯỢT QUAN TÂM (tối thiểu 100 lượt), KHÔNG PHẢI SỐ TIỀN VNĐ.`\r\n );\r\n }\r\n } else if (price.SpendingMethod !== undefined) {\r\n errors.push(\r\n \"Cách đặt giá SpendingMethod cho Lượt quan tâm chỉ chấp nhận 1 (Tổng ngân sách quảng cáo) hoặc 0 (Tự đặt giá).\"\r\n );\r\n }\r\n }\r\n } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {\r\n // Quảng cáo Tin Nhắn (Type 30): Hỗ trợ Price.Type = 2 (CPC - Click vào tin nhắn) hoặc Price.Type = 5 (CPA - Lượt liên hệ)\r\n if (price.Type !== 2 && price.Type !== 5) {\r\n errors.push(\r\n \"Đối với Quảng cáo Tin nhắn (Type 30), Price.Type chỉ hỗ trợ 2 (Lượt nhấn - CPC) hoặc 5 (Lượt liên hệ - CPA).\"\r\n );\r\n }\r\n if (price.Type === 5) {\r\n if (price.SpendingMethod !== 1) {\r\n errors.push(\r\n \"Khi tính tiền theo Lượt liên hệ (Price.Type = 5 / CPA), SpendingMethod bắt buộc phải bằng 1 (Tối ưu tự động theo ngân sách).\"\r\n );\r\n }\r\n if (price.Bid !== undefined && price.Bid !== 0) {\r\n errors.push(\r\n \"Khi tính tiền theo Lượt liên hệ (Price.Type = 5 / CPA), trường Bid bắt buộc phải bằng 0 (Zalo Ads tự động tối ưu giá thầu, nếu truyền > 0 máy chủ sẽ báo lỗi code 13: Giá đặt không hợp lệ).\"\r\n );\r\n }\r\n }\r\n if (price.Limit !== undefined && price.Limit > 0 && price.Limit < 600000) {\r\n errors.push(\r\n \"Ngân sách tối thiểu cho Quảng cáo Tin nhắn là 600,000 VNĐ (Price.Limit >= 600000). Nếu đặt dưới 600k máy chủ sẽ từ chối.\"\r\n );\r\n }\r\n } else if (\r\n Number(payload.Type) === 21 ||\r\n Number(payload.Type) === 23 ||\r\n Number(payload.Type) === 26 ||\r\n payload.Type === VALID_AD_TYPES.DISPLAY ||\r\n payload.Type === VALID_AD_TYPES.DISPLAY_HALFPAGE ||\r\n payload.Type === VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE\r\n ) {\r\n // Quảng cáo Display:\r\n // - Type 21: Masthead Mobile (Format 1) & Masthead Desktop (Format 2) & Welcome Mobile\r\n // - Type 23: Medium Rectangle 300x250 (Format 6)\r\n // - Type 26: Halfpage Mobile (Format 13)\r\n const adFormat = payload.Settings?.AdInfo?.AdFormat;\r\n const typeNum = Number(payload.Type);\r\n const isHalfpage = typeNum === 26 || adFormat === 13 || adFormat === 14 || (payload.AdName || \"\").toLowerCase().includes(\"halfpage\");\r\n const isMediumRectangle =\r\n typeNum === 23 ||\r\n adFormat === 6 ||\r\n (payload.AdName || \"\").toLowerCase().includes(\"medium rectangle\") ||\r\n (payload.AdName || \"\").toLowerCase().includes(\"300x250\");\r\n const adNameLower = (payload.AdName || \"\").toLowerCase();\r\n const isWelcome = adNameLower.includes(\"welcome\");\r\n const isMasthead =\r\n (adNameLower.includes(\"masthead\") || typeNum === 21 || adFormat === 1 || adFormat === 2) &&\r\n !isWelcome &&\r\n !isMediumRectangle;\r\n\r\n if (price.Type !== 1 && price.Type !== 2) {\r\n errors.push(\r\n \"Đối với Quảng cáo Display, Price.Type chỉ chấp nhận 1 (CPM - Lượt hiển thị) hoặc 2 (CPC - Lượt nhấn).\"\r\n );\r\n }\r\n\r\n // Halfpage Mobile và Masthead chỉ hỗ trợ CPM (Type = 1)\r\n if ((isHalfpage || isMasthead) && price.Type === 2) {\r\n errors.push(\r\n `Quảng cáo ${isHalfpage ? \"Halfpage (Type 26 / AdFormat 13, 14)\" : \"Masthead (Type 21)\"} chỉ hỗ trợ tính tiền theo lượt hiển thị CPM (Price.Type = 1), không hỗ trợ CPC.`\r\n );\r\n }\r\n\r\n // Kiểm tra giá sàn (Bid floor) theo từng định dạng Display:\r\n if (price.Type === 1) {\r\n // CPM (đơn vị: VNĐ / 1,000 lượt hiển thị)\r\n if (price.Bid !== undefined) {\r\n if (isWelcome && price.Bid < 30000) {\r\n errors.push(\r\n `Giá đặt mỗi 1,000 lượt hiển thị (Price.Bid) cho Quảng cáo Welcome Mobile tối thiểu là 30,000 VNĐ. Hiện tại đang truyền: ${price.Bid}đ.`\r\n );\r\n } else if (isHalfpage && price.Bid < 16000) {\r\n errors.push(\r\n `Giá đặt mỗi 1,000 lượt hiển thị (Price.Bid) cho Quảng cáo Halfpage tối thiểu là 16,000 VNĐ. Hiện tại đang truyền: ${price.Bid}đ.`\r\n );\r\n } else if (isMasthead && price.Bid < 13000) {\r\n errors.push(\r\n `Giá đặt mỗi 1,000 lượt hiển thị (Price.Bid) cho Quảng cáo Masthead tối thiểu là 13,000 VNĐ. Hiện tại đang truyền: ${price.Bid}đ.`\r\n );\r\n } else if (isMediumRectangle && price.Bid < 8000) {\r\n errors.push(\r\n `Giá đặt mỗi 1,000 lượt hiển thị (Price.Bid) cho Quảng cáo Medium Rectangle CPM tối thiểu là 8,000 VNĐ. Hiện tại đang truyền: ${price.Bid}đ.`\r\n );\r\n } else if (price.Bid < 8000) {\r\n errors.push(\r\n `Giá đặt mỗi 1,000 lượt hiển thị (Price.Bid) cho Quảng cáo Display CPM tối thiểu là 8,000 VNĐ (sàn hệ thống). Hiện tại đang truyền: ${price.Bid}đ.`\r\n );\r\n }\r\n }\r\n\r\n // Số lượng lượt hiển thị tối thiểu (Price.Limit): 50 (tương đương 50,000 lượt hiển thị)\r\n if (price.Limit !== undefined && price.Limit > 0 && price.Limit < 50) {\r\n errors.push(\r\n \"Số lượng lượt hiển thị tối thiểu (Price.Limit) cho Quảng cáo Display CPM là 50 (tương ứng 50,000 lượt hiển thị).\"\r\n );\r\n }\r\n } else if (price.Type === 2) {\r\n // CPC (đơn vị: VNĐ / lượt nhấn, áp dụng cho Medium Rectangle 300x250)\r\n if (price.Bid !== undefined && price.Bid < 1800) {\r\n errors.push(\r\n `Giá đặt mỗi lượt nhấn (Price.Bid) cho Quảng cáo Display CPC tối thiểu là 1,800 VNĐ. Hiện tại đang truyền: ${price.Bid}đ.`\r\n );\r\n }\r\n if (price.Limit !== undefined && price.Limit > 0 && price.Limit < 50) {\r\n errors.push(\r\n \"Số lượng lượt nhấn tối thiểu (Price.Limit) cho Quảng cáo Display CPC là 50 lượt nhấn.\"\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Kiểm tra DeliveryType trong Settings\r\n if (payload.Settings && (payload.Settings as any).DeliveryType !== undefined) {\r\n const deliveryType = (payload.Settings as any).DeliveryType;\r\n if (deliveryType !== 0 && deliveryType !== 1) {\r\n errors.push(\"Cài đặt phân phối Settings.DeliveryType chỉ chấp nhận 0 (Tiêu chuẩn - Standard) hoặc 1 (Tăng tốc - SpeedUp).\");\r\n }\r\n if ((price.LimitType === 2 || price.LimitType === 0) && deliveryType === 1) {\r\n warnings.push(\"Phân phối Tăng tốc (DeliveryType = 1) chỉ có hiệu lực khi đặt Ngân sách toàn lịch chạy (Price.LimitType = 1).\");\r\n }\r\n }\r\n\r\n // Số lượng đặt tối thiểu cho tương tác\r\n if (price.SpendingMethod === 0 && price.Limit !== undefined && price.Limit > 0 && price.Limit < 50) {\r\n warnings.push(\"Số lượng lượt tương tác đặt mỗi ngày tối thiểu là 50 lượt.\");\r\n }\r\n }\r\n\r\n // 5. Kiểm tra nhắm chọn đối tượng (Settings.Targeting)\r\n const targeting = payload.Settings?.Targeting;\r\n if (targeting) {\n // Gender: 0 (Tất cả), 1 (Nam), 2 (Nữ)\n if (targeting.Gender !== undefined && targeting.Gender !== null) {\n if (![0, 1, 2].includes(Number(targeting.Gender))) {\n errors.push(`Mã giới tính 'Gender' (${targeting.Gender}) không hợp lệ. Hợp lệ: 0 (Tất cả), 1 (Nam), 2 (Nữ).`);\n }\n }\n\n // Custom Audience / Saved Audience\n if (targeting.CustomAudienceId !== undefined && targeting.CustomAudienceId !== null) {\n if (typeof targeting.CustomAudienceId !== \"number\" || targeting.CustomAudienceId < 0) {\n errors.push(\"CustomAudienceId phải là số nguyên không âm (>= 0).\");\n }\n }\n if (targeting.ExcludedAudienceId !== undefined && targeting.ExcludedAudienceId !== null) {\n if (typeof targeting.ExcludedAudienceId !== \"number\" || targeting.ExcludedAudienceId < 0) {\n errors.push(\"ExcludedAudienceId phải là số nguyên không âm (>= 0).\");\n }\n }\n\r\n // Age ranges: Hỗ trợ cả NewAgeRanges (dạng mảng chuỗi ['18_24', '25_34', ...]) lẫn AgeRanges (mảng số legacy)\r\n const newAges = targeting.NewAgeRanges;\r\n const oldAges = targeting.AgeRanges;\r\n if (newAges && newAges.length > 0) {\r\n const validNewAgeKeys = [\"13_17\", \"18_24\", \"25_34\", \"35_44\", \"45_54\", \"55_64\", \"65_plus\", \"10283\", \"10284\", \"10285\", \"10286\", \"10287\", \"10288\"];\r\n const invalid = newAges.filter(a => !validNewAgeKeys.includes(String(a)));\r\n if (invalid.length > 0) {\r\n warnings.push(`Mã NewAgeRanges không phổ biến: ${invalid.join(\", \")}.`);\r\n }\r\n } else if (oldAges && oldAges.length > 0) {\r\n const validAges = Object.values(ZaloAdsAgeRangeId);\r\n const invalidAges = oldAges.filter(a => !validAges.includes(a as any));\r\n if (invalidAges.length > 0) {\r\n errors.push(`Mã khoảng tuổi không hợp lệ: ${invalidAges.join(\", \")}. Hợp lệ: ${validAges.join(\", \")}.`);\r\n }\r\n }\r\n\r\n // OS types: Hỗ trợ cả Os (mảng [0, 1, 3]) lẫn OsTypes\r\n const osList = targeting.Os || targeting.OsTypes;\r\n if (osList && osList.length > 0) {\r\n const validOs = [0, 1, 2, 3];\r\n const invalidOs = osList.filter(os => !validOs.includes(Number(os)));\r\n if (invalidOs.length > 0) {\r\n errors.push(`Mã hệ điều hành không hợp lệ: ${invalidOs.join(\", \")}. Hợp lệ: 0 (Android), 1 (iOS), 3 (PC).`);\r\n }\r\n }\r\n\r\n // Delivery Type (Cách phân phối: 0 = Tiêu chuẩn, 1 = Tăng tốc)\r\n const deliveryType = (payload.Settings as any)?.DeliveryType;\r\n if (\r\n deliveryType !== undefined &&\r\n deliveryType !== ZaloAdsDeliveryType.STANDARD &&\r\n deliveryType !== ZaloAdsDeliveryType.SPEED_UP\r\n ) {\r\n warnings.push(\r\n \"DeliveryType không hợp lệ. Giá trị chuẩn: 0 (Tiêu chuẩn / Standard) hoặc 1 (Tăng tốc / SpeedUp).\"\r\n );\r\n }\r\n\r\n // Location targeting validation (2026 Admin format)\r\n const location = targeting.Location;\r\n if (location) {\r\n const container = location.WardTargeting || location.DistrictTargeting;\r\n if (container && Array.isArray(container.Includes)) {\r\n const validRegions: number[] = [1, 2, 3];\r\n for (const item of container.Includes) {\r\n if (!validRegions.includes(Number(item.Id))) {\r\n warnings.push(\r\n `Mã vùng miền (Id: ${item.Id}) không hợp lệ. Các mã vùng chuẩn: 1 (Miền Bắc), 2 (Miền Trung), 3 (Miền Nam).`\r\n );\r\n }\r\n if (item.Provinces && !Array.isArray(item.Provinces)) {\r\n warnings.push(`Trường 'Provinces' trong vùng miền Id=${item.Id} phải là một mảng tỉnh/thành.`);\r\n } else if (Array.isArray(item.Provinces)) {\r\n for (const prov of item.Provinces) {\r\n if (!prov.Id || typeof prov.Id !== \"string\") {\r\n warnings.push(\r\n `Mã tỉnh 'Id' (${JSON.stringify(prov)}) trong vùng miền ${item.Id} phải là chuỗi hợp lệ (ví dụ: 'VN44', 'VN20').`\r\n );\r\n } else {\r\n const mergeInfo = ZALO_PROVINCE_MERGE_MAPPING[prov.Id];\r\n if (mergeInfo) {\r\n errors.push(\r\n `Mã tỉnh '${prov.Id}' (${mergeInfo.name}) đã được Zalo Ads gộp/sáp nhập vào cụm mã '${mergeInfo.newCode}'. ` +\r\n `Vui lòng sử dụng mã cụm '${mergeInfo.newCode}' trong WardTargeting, nếu không giao diện Zalo Ads Web sẽ báo lỗi đỏ 'Invalid wards params'.`\r\n );\r\n } else {\r\n const validNewRegionProvs = ZALO_NEW_REGION_PROVINCE_CODES[Number(item.Id)] || [];\r\n if (!validNewRegionProvs.includes(prov.Id)) {\r\n const actualRegion = Object.keys(ZALO_NEW_REGION_PROVINCE_CODES).find(r => ZALO_NEW_REGION_PROVINCE_CODES[Number(r)].includes(prov.Id));\r\n errors.push(\r\n `Mã tỉnh '${prov.Id}' không nằm trong 34 Cụm Tỉnh/Thành mới của Vùng ${item.Id} trên Zalo Ads (sẽ gây lỗi 'Invalid wards params' trên UI). ` +\r\n (actualRegion ? `Mã này thuộc Vùng ${actualRegion}. ` : \"\")\r\n );\r\n }\r\n }\r\n }\r\n if (prov.Districts && !Array.isArray(prov.Districts)) {\r\n warnings.push(`Trường 'Districts' của tỉnh ${prov.Id} phải là một mảng (hoặc [] khi chọn cả tỉnh).`);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // 6. Kiểm tra cấu hình tối ưu chuyển đổi (UseConversion & ConversionId)\r\n if (payload.UseConversion !== undefined) {\r\n const validUseConversions: number[] = Object.values(ZaloAdsUseConversion);\r\n if (!validUseConversions.includes(payload.UseConversion as number)) {\r\n warnings.push(\r\n `UseConversion (${payload.UseConversion}) không nằm trong danh mục chuẩn: 0 (NOT_USE), 1 (USE), 2 (LADI_PAGE), 3 (MINI_APP), -1 (USE_OFF), -2 (LADI_PAGE_OFF), -3 (MINI_APP_OFF).`\r\n );\r\n }\r\n if (payload.UseConversion === ZaloAdsUseConversion.USE && (!payload.ConversionId || payload.ConversionId <= 0)) {\r\n warnings.push(\r\n \"Khi chọn UseConversion = 1 (Pixel của tôi), nên cấu hình ConversionId hợp lệ từ danh sách GET /api/conversion/all để thuật toán máy học Zalo Ads tối ưu tỷ lệ chuyển đổi.\"\r\n );\r\n }\r\n }\r\n\r\n // 7. Ràng buộc theo từng loại Ad đặc thù\r\n if (payload.Type === VALID_AD_TYPES.FORM) {\r\n if (!payload.ZaloFormId || !payload.ZaloFormId.trim()) {\r\n errors.push(\"ZaloFormId là bắt buộc đối với Quảng cáo Form (Ad Type 18).\");\r\n }\r\n } else if (payload.Type === VALID_AD_TYPES.MESSAGE) {\r\n if (!payload.Settings?.Image?.LogoUrl) {\r\n errors.push(\"Settings.Image.LogoUrl là bắt buộc đối với Quảng cáo Tin Nhắn (Ad Type 30).\");\r\n }\r\n if (!payload.MiniPageId || payload.MiniPageId <= 0) {\r\n errors.push(\r\n \"MiniPageId là bắt buộc đối với Quảng cáo Tin Nhắn (Ad Type 30, Template 4 - Kịch bản giới thiệu thương hiệu / Tin nhắn). Nếu thiếu hoặc = 0, máy chủ Zalo Ads sẽ từ chối với lỗi: 'Mini Page không hợp lệ.'.\"\r\n );\r\n }\r\n if (!payload.ZaloFlowId) {\r\n warnings.push(\"Quảng cáo Tin Nhắn nên gắn ZaloFlowId để tự động kích hoạt kịch bản chatbot tương tác khi người dùng mở tin nhắn.\");\r\n }\r\n if ((payload.Settings?.Image as any)?.ExtraImgs && (payload.Settings?.Image as any)?.ExtraImgs.length > 0) {\r\n errors.push(\r\n \"Quảng cáo Tin Nhắn định dạng ảnh đơn (Landscape Cover) không được truyền mảng 'ExtraImgs'. Nếu truyền thừa sẽ bị máy chủ báo lỗi 'Dữ liệu không hợp lệ'.\"\r\n );\r\n }\r\n } else if (payload.Type === VALID_AD_TYPES.COMMERCE) {\r\n if (!payload.MiniPageId || payload.MiniPageId <= 0) {\r\n errors.push(\"MiniPageId là bắt buộc đối với Quảng cáo Commerce (Ad Type 28, Template 1/2/3).\");\r\n }\r\n } else if (payload.Type === VALID_AD_TYPES.VIDEO) {\r\n if (!payload.ZaloVideoId && !payload.Settings?.Image?.VideoUrl) {\r\n errors.push(\"ZaloVideoId hoặc Settings.Image.VideoUrl là bắt buộc đối với Quảng cáo Video (Ad Type 11).\");\r\n }\r\n if (payload.Settings?.Image?.VideoUrl && !payload.Settings.Image.VideoUrl.includes(\"zascdn.me\")) {\r\n warnings.push(\"VideoUrl nên là đường dẫn CDN chính thức của Zalo Ads (*.zascdn.me).\");\r\n }\r\n } else if (payload.Type === VALID_AD_TYPES.ARTICLE) {\r\n if (!payload.ZaloFeedId && !(payload as any).articleId) {\r\n errors.push(\"ZaloFeedId hoặc articleId là bắt buộc đối với Quảng cáo Bài Viết (Ad Type 3).\");\r\n }\r\n } else if (\r\n Number(payload.Type) === 21 ||\r\n Number(payload.Type) === 23 ||\r\n Number(payload.Type) === 26 ||\r\n payload.Type === VALID_AD_TYPES.DISPLAY ||\r\n payload.Type === VALID_AD_TYPES.DISPLAY_HALFPAGE ||\r\n payload.Type === VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE\r\n ) {\r\n const img = payload.Settings?.Image;\r\n const hasImage =\r\n img?.LandscapeCoverUrl ||\r\n img?.BaseLandscapeCoverUrl ||\r\n img?.PortraitCoverUrl ||\r\n img?.SquareCoverUrl;\r\n if (!hasImage) {\r\n errors.push(\r\n \"Quảng cáo Display bắt buộc phải có ít nhất một banner hình ảnh (Settings.Image.LandscapeCoverUrl hoặc BaseLandscapeCoverUrl).\"\r\n );\r\n }\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Kiểm tra tính hợp lệ của tham số đổi tên chiến dịch (POST /api/campaign/change-name).\r\n */\r\nexport function validateRenameCampaignParams(params: {\r\n campid?: number;\r\n campaignId?: number;\r\n newname?: string;\r\n newName?: string;\r\n name?: string;\r\n}): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n const id = params.campid || params.campaignId;\r\n const name = params.newname || params.newName || params.name;\r\n\r\n if (!id || id <= 0) {\r\n errors.push(\"ID chiến dịch (campid/campaignId) là bắt buộc và phải > 0.\");\r\n }\r\n if (!name || !name.trim()) {\r\n errors.push(\"Tên mới của chiến dịch (newname/name) là bắt buộc và không được để trống.\");\r\n } else if (name.length > 255) {\r\n errors.push(`Tên chiến dịch quá dài (${name.length}/255 ký tự).`);\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Kiểm tra tính hợp lệ của trạng thái thay đổi chiến dịch (POST /api/campaign/change-status).\r\n */\r\nexport function validateChangeCampaignStatusParams(params: {\r\n campaignId: number;\r\n status: number;\r\n isDraft?: boolean;\r\n}): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!params.campaignId || params.campaignId <= 0) {\r\n errors.push(\"campaignId là bắt buộc và phải > 0.\");\r\n }\r\n\r\n // Các trạng thái hỗ trợ: 1 = Tiếp tục / Bật, 0 = Tắt, 2 = Tạm dừng, -2 = Xóa\r\n if (![0, 1, 2, -2].includes(params.status)) {\r\n errors.push(`status: ${params.status} không hợp lệ. Các trạng thái hợp lệ: 1 (Bật), 0 (Tắt), 2 (Tạm dừng), -2 (Xóa).`);\r\n }\r\n\r\n // Bẫy HTTP 500 khi tạm dừng chiến dịch nháp chưa có Ad duyệt\r\n if (params.status === 2 && params.isDraft) {\r\n warnings.push(\r\n \"Chiến dịch nháp chưa có quảng cáo hoạt động khi gọi status: 2 (Tạm dừng) sẽ bị máy chủ ném lỗi HTTP 500 Internal Server Error. Để dọn dẹp hãy dùng status: -2 (Xóa).\"\r\n );\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Kiểm tra tính hợp lệ của tham số nhân bản quảng cáo (POST /zaapi/DuplicateAd).\r\n */\r\nexport function validateDuplicateAdParams(params: {\r\n adid?: number;\r\n adId?: number;\r\n}): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n const id = params.adid || params.adId;\r\n if (!id || id <= 0) {\r\n errors.push(\"ID mẫu quảng cáo gốc cần nhân bản (adid/adId) là bắt buộc và phải > 0.\");\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Kiểm tra tính hợp lệ của tham số cắt/tải ảnh quảng cáo (POST /api/ads/upload-crop / updateNewAds).\r\n */\r\nexport function validateCropCoordinates(\r\n input: unknown\r\n): CampaignValidationResult<ZaloAdsUpdateNewAdsRequest> {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!input || typeof input !== \"object\") {\r\n return {\r\n isValid: false,\r\n errors: [\"Dữ liệu yêu cầu cắt/tải ảnh quảng cáo phải là một đối tượng.\"],\r\n warnings,\r\n };\r\n }\r\n\r\n const raw = input as Record<string, unknown>;\r\n const file = raw.File ?? raw.file;\r\n\r\n if (!file) {\r\n errors.push(\"Trường tệp ảnh ('File') là bắt buộc.\");\r\n } else if (typeof file === \"string\" && !/^(https?:\\/\\/|data:image\\/)/i.test(file.trim())) {\r\n errors.push(\"Đường dẫn tệp ảnh ('File') phải là URL HTTP/HTTPS hoặc data URL hợp lệ.\");\r\n }\r\n\r\n const x = raw.x !== undefined ? Number(raw.x) : 0;\r\n const y = raw.y !== undefined ? Number(raw.y) : 0;\r\n const width = raw.width !== undefined ? Number(raw.width) : 0;\r\n const height = raw.height !== undefined ? Number(raw.height) : 0;\r\n const scale = raw.scale !== undefined ? Number(raw.scale) : 1;\r\n\r\n if (isNaN(x) || x < 0) {\r\n errors.push(`Tọa độ x không hợp lệ: '${raw.x}'. Phải là số không âm (>= 0).`);\r\n }\r\n if (isNaN(y) || y < 0) {\r\n errors.push(`Tọa độ y không hợp lệ: '${raw.y}'. Phải là số không âm (>= 0).`);\r\n }\r\n if (isNaN(width) || width < 0) {\r\n errors.push(`Chiều rộng khung cắt ('width') không hợp lệ: '${raw.width}'. Phải là số không âm.`);\r\n }\r\n if (isNaN(height) || height < 0) {\r\n errors.push(`Chiều cao khung cắt ('height') không hợp lệ: '${raw.height}'. Phải là số không âm.`);\r\n }\r\n if (isNaN(scale) || scale <= 0) {\r\n errors.push(`Tỷ lệ co dãn ('scale') không hợp lệ: '${raw.scale}'. Phải là số dương (> 0).`);\r\n }\r\n\r\n if ((width > 0 && height === 0) || (height > 0 && width === 0)) {\r\n errors.push(\"Khi đã chỉ định cắt ảnh, cả 'width' và 'height' đều phải lớn hơn 0.\");\r\n }\r\n\r\n if (width > 0 && height > 0) {\r\n const ratio = width / height;\r\n const isLandscape = Math.abs(ratio - 1.92) < 0.2 || Math.abs(ratio - 1.91) < 0.2 || Math.abs(ratio - 1.78) < 0.2;\r\n const isSquare = Math.abs(ratio - 1.0) < 0.05;\r\n const isVertical = Math.abs(ratio - 0.5625) < 0.1;\r\n if (!isLandscape && !isSquare && !isVertical) {\r\n warnings.push(`Tỷ lệ khung cắt (${width}x${height} ~ ${ratio.toFixed(2)}:1) khác các tỷ lệ chuẩn của Zalo Ads (16:9 / 1.92:1 ngang, 1:1 vuông hoặc 9:16 dọc). Hãy kiểm tra hiển thị thực tế.`);\r\n }\r\n }\r\n\r\n const cleanData: ZaloAdsUpdateNewAdsRequest = {\r\n File: file as any,\r\n x,\r\n y,\r\n width,\r\n height,\r\n scale,\r\n };\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n warnings,\r\n data: errors.length === 0 ? cleanData : undefined,\r\n };\r\n}\r\n\r\n\r\n/**\r\n * 1. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Commerce (Shop)\r\n * Bắt buộc: \"Tên chiến dịch\" (name) và tài khoản OA chọn từ \"Danh sách tài khoản OA\" (pageId > 0).\r\n */\r\nexport function validateCreateCommerceCampaign(\r\n payload: Partial<ZaloAdsCreateCommerceCampaignPayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n if (!payload.pageId || payload.pageId <= 0) {\r\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Commerce (chọn từ Danh sách tài khoản OA, phải > 0).\");\r\n }\r\n\r\n if (payload.productId === undefined || payload.productId === null || payload.productId <= 0) {\r\n warnings.push(\"Quảng cáo Commerce nên chỉ định productId (hoặc -1/0 khi dùng Instant Page sản phẩm).\");\r\n }\r\n\r\n return { isValid: errors.length === 0, errors, warnings };\r\n}\r\n\r\n/**\r\n * 2. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Display\r\n * Bắt buộc: \"Tên chiến dịch\" (name).\r\n */\r\nexport function validateCreateDisplayCampaign(\r\n payload: Partial<ZaloAdsCreateDisplayCampaignPayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n if (payload.targetUrl && !/^https?:\\/\\/.+/i.test(payload.targetUrl)) {\r\n errors.push(\"targetUrl phải là một đường link hợp lệ bắt đầu bằng http:// hoặc https://.\");\r\n }\r\n\r\n return { isValid: errors.length === 0, errors, warnings };\r\n}\r\n\r\n/**\r\n * 3. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Website\r\n * Bắt buộc: \"Tên chiến dịch\" (name), \"Liên kết website\" (targetUrl).\r\n * Tùy chọn: Tài khoản OA (\"Danh sách tài khoản OA\" - không bắt buộc).\r\n */\r\nexport function validateCreateWebsiteCampaign(\r\n payload: Partial<ZaloAdsCreateWebsiteCampaignPayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n if (!payload.targetUrl || typeof payload.targetUrl !== \"string\" || !payload.targetUrl.trim()) {\r\n errors.push(\"Liên kết website ('targetUrl') là bắt buộc đối với Quảng cáo Website.\");\r\n } else if (!/^https?:\\/\\/.+/i.test(payload.targetUrl)) {\r\n errors.push(\"Liên kết website ('targetUrl') phải là đường link hợp lệ bắt đầu bằng http:// hoặc https://.\");\r\n }\r\n\r\n return { isValid: errors.length === 0, errors, warnings };\r\n}\r\n\r\n/**\r\n * 4. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Form (Biểu mẫu)\r\n * Bắt buộc: \"Tên chiến dịch\" (name), tài khoản OA trong \"Danh sách tài khoản OA\" (pageId > 0).\r\n */\r\nexport function validateCreateFormCampaign(\r\n payload: Partial<ZaloAdsCreateFormCampaignPayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n if (!payload.pageId || payload.pageId <= 0) {\r\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Form (chọn từ Danh sách tài khoản OA, phải > 0).\");\r\n }\r\n\r\n return { isValid: errors.length === 0, errors, warnings };\r\n}\r\n\r\n/**\r\n * 5. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Tin nhắn\r\n * Bắt buộc: \"Tên chiến dịch\" (name), tài khoản OA trong \"Danh sách tài khoản OA\" (pageId > 0).\r\n */\r\nexport function validateCreateMessageCampaign(\r\n payload: Partial<ZaloAdsCreateMessageCampaignPayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n if (!payload.pageId || payload.pageId <= 0) {\r\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Tin nhắn (chọn từ Danh sách tài khoản OA, phải > 0).\");\r\n }\r\n\r\n return { isValid: errors.length === 0, errors, warnings };\r\n}\r\n\r\n/**\r\n * 6. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Zalo Official Account\r\n * Bắt buộc: \"Tên chiến dịch\" (name), tài khoản OA trong \"Danh sách tài khoản OA\" (pageId > 0).\r\n */\r\nexport function validateCreateOfficialAccountCampaign(\r\n payload: Partial<ZaloAdsCreateOfficialAccountCampaignPayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n if (!payload.pageId || payload.pageId <= 0) {\r\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Zalo Official Account (chọn từ Danh sách tài khoản OA, phải > 0).\");\r\n }\r\n\r\n return { isValid: errors.length === 0, errors, warnings };\r\n}\r\n\r\n/**\r\n * 7. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Bài viết\r\n * Bắt buộc: \"Tên chiến dịch\" (name), tài khoản OA trong \"Danh sách tài khoản OA\" (pageId > 0), bài viết trong \"Danh sách bài viết của OA đó\" (articleId > 0).\r\n */\r\nexport function validateCreateArticleCampaign(\r\n payload: Partial<ZaloAdsCreateArticleCampaignPayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n if (!payload.pageId || payload.pageId <= 0) {\r\n errors.push(\"Tài khoản OA ('pageId') là bắt buộc đối với Quảng cáo Bài viết (chọn từ Danh sách tài khoản OA, phải > 0).\");\r\n }\r\n\r\n if (!payload.articleId || payload.articleId <= 0) {\r\n errors.push(\"Bài viết ('articleId') là bắt buộc đối với Quảng cáo Bài viết (chọn từ Danh sách bài viết của OA đó, lấy qua getOwnedArticles).\");\r\n }\r\n\r\n return { isValid: errors.length === 0, errors, warnings };\r\n}\r\n\r\n/**\r\n * 8. Kiểm tra tính hợp lệ khi tạo mới Quảng cáo Video\r\n * Bắt buộc: \"Tên chiến dịch\" (name), \"Liên kết Website\" (targetUrl).\r\n * Tùy chọn: Tài khoản OA trong \"Danh sách tài khoản OA\" (không bắt buộc).\r\n */\r\nexport function validateCreateVideoCampaign(\r\n payload: Partial<ZaloAdsCreateVideoCampaignPayloadDto>,\r\n options: ValidateCampaignOptions = {}\r\n): CampaignValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!payload.name || typeof payload.name !== \"string\" || !payload.name.trim()) {\r\n errors.push(\"Tên chiến dịch ('name') là bắt buộc và không được để trống.\");\r\n } else if (payload.name.length > 255) {\r\n errors.push(\"Tên chiến dịch ('name') không được vượt quá 255 ký tự.\");\r\n }\r\n\r\n if (!payload.targetUrl || typeof payload.targetUrl !== \"string\" || !payload.targetUrl.trim()) {\r\n errors.push(\"Liên kết Website ('targetUrl') là bắt buộc đối với Quảng cáo Video.\");\r\n } else if (!/^https?:\\/\\/.+/i.test(payload.targetUrl)) {\r\n errors.push(\"Liên kết Website ('targetUrl') phải là đường link hợp lệ bắt đầu bằng http:// hoặc https://.\");\r\n }\r\n\r\n return { isValid: errors.length === 0, errors, warnings };\r\n}\r\n\r\n// -------------------------------------------------------------\r\n// BỘ HÀM KIỂM TRA TỪNG LOẠI MẪU QUẢNG CÁO CẬP NHẬT (Update Ad)\r\n// -------------------------------------------------------------\r\n\r\nexport function validateUpdateWebsiteAd(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.WEBSITE }, options);\r\n}\r\n\r\nexport function validateUpdateDisplayAd(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n const adFormat = payload.Settings?.AdInfo?.AdFormat;\r\n const rawType = Number(payload.Type);\r\n const isHalfpage = rawType === 26 || adFormat === 13 || adFormat === 14;\r\n const isMediumRectangle = rawType === 23 || adFormat === 6;\r\n\r\n let effectiveType: number;\r\n if (isHalfpage) {\r\n effectiveType = VALID_AD_TYPES.DISPLAY_HALFPAGE; // 26\r\n } else if (isMediumRectangle) {\r\n effectiveType = VALID_AD_TYPES.DISPLAY_MEDIUM_RECTANGLE; // 23\r\n } else {\r\n effectiveType = payload.Type ?? VALID_AD_TYPES.DISPLAY; // 21\r\n }\r\n\r\n return validateUpdateAdPayload({ ...payload, Type: effectiveType }, options);\r\n}\r\n\r\nexport function validateUpdateVideoAd(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.VIDEO }, options);\r\n}\r\n\r\nexport function validateUpdateCommerceAd(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.COMMERCE }, options);\r\n}\r\n\r\nexport function validateUpdateFormAd(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.FORM }, options);\r\n}\r\n\r\nexport function validateUpdateMessageAd(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.MESSAGE }, options);\r\n}\r\n\r\nexport function validateUpdateOfficialAccountAd(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.OA }, options);\r\n}\r\n\r\nexport function validateUpdateArticleAd(\r\n payload: Partial<ZaloAdsAdUpdatePayloadDto>,\r\n options: ValidateAdOptions = {}\r\n): CampaignValidationResult {\r\n return validateUpdateAdPayload({ ...payload, Type: VALID_AD_TYPES.ARTICLE }, options);\r\n}\r\n\r\n\r\nexport const ZaloCampaignsValidator = {\r\n // Generic\r\n createCampaign: validateCreateCampaignPayload,\r\n updateAd: validateUpdateAdPayload,\r\n renameCampaign: validateRenameCampaignParams,\r\n changeStatus: validateChangeCampaignStatusParams,\r\n duplicateAd: validateDuplicateAdParams,\r\n validateCropCoordinates,\r\n validateUploadCropAdImage: validateCropCoordinates,\r\n\r\n // Specific Create Campaign\r\n createCommerceCampaign: validateCreateCommerceCampaign,\r\n createDisplayCampaign: validateCreateDisplayCampaign,\r\n createWebsiteCampaign: validateCreateWebsiteCampaign,\r\n createFormCampaign: validateCreateFormCampaign,\r\n createMessageCampaign: validateCreateMessageCampaign,\r\n createOfficialAccountCampaign: validateCreateOfficialAccountCampaign,\r\n createArticleCampaign: validateCreateArticleCampaign,\r\n createVideoCampaign: validateCreateVideoCampaign,\r\n\r\n // Specific Update Ad\r\n updateWebsiteAd: validateUpdateWebsiteAd,\r\n updateDisplayAd: validateUpdateDisplayAd,\r\n updateVideoAd: validateUpdateVideoAd,\r\n updateCommerceAd: validateUpdateCommerceAd,\r\n updateFormAd: validateUpdateFormAd,\r\n updateMessageAd: validateUpdateMessageAd,\r\n updateOfficialAccountAd: validateUpdateOfficialAccountAd,\r\n updateArticleAd: validateUpdateArticleAd,\r\n};\r\n\r\n","/**\r\n * Dịch vụ Quản lý Chiến dịch & Quảng cáo Zalo Ads (Tạo chiến dịch, đổi trạng thái, cập nhật quảng cáo các định dạng).\r\n */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/ads.dto\";\r\nimport { ZaloCampaignsValidator } from \"../validators/campaigns.validator\";\r\n\r\n\r\nconst OP_ZaloAdsUpdateVideoAd: OperationDefinition = {\r\n operationId: \"ZaloAds_updateVideoAd\",\r\n method: \"POST\",\r\n endpoint: \"/zaapi/UpdateAd\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"data\", \"est\", \"isBoostAd\", \"stt\"]\r\n};\r\n\r\nconst OP_ZaloAdsChangeCampaignStatus: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_changeCampaignStatus\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/campaign/change-status\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"status\",\r\n \"campaignId\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateEcommerceCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createEcommerceCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateForm: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createForm\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/form/create\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateFormCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createFormCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateMessageCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createMessageCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateOfficialAccountCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createOfficialAccountCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreatePostCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createPostCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsGetAdById: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getAdById\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getAdFromAdId\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"adId\",\r\n \"v\",\r\n \"newWard\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetAdChangeLog: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getAdChangeLog\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/ad/log/{adId}\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"adId\"\r\n ],\r\n \"queryFields\": [\r\n \"type\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetApiPlaceGetalldistricts: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getApiPlaceGetalldistricts\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/place/getAllDistricts\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetApiSpellCheckV2: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getApiSpellCheckV2\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/spell-check/v2\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"text\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiCheckcamphasmanyads: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiCheckcamphasmanyads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/checkCampHasManyAds\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"campaignId\",\r\n \"campId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiGetadsfromcampaignid: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiGetadsfromcampaignid\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getAdsFromCampaignId\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"campaignId\",\r\n \"campId\",\r\n \"dataType\",\r\n \"v\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiGetallpages: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiGetallpages\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getAllPages\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiGetownedarticles: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiGetownedarticles\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getOwnedArticles\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"pageId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiGetownedpages: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiGetownedpages\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/getOwnedPages\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsListFormsByOfficialAccount: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listFormsByOfficialAccount\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/form/getByOaId\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"isAll\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsListMiniPagesByTemplate: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listMiniPagesByTemplate\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/mini-pages\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"templateIds\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsPostZaapiDeletead: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_postZaapiDeletead\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/deleteAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"adId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"adId\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsRenameCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_renameCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/campaign/change-name\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"campid\",\r\n \"newname\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateEcommerceAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateEcommerceAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateFormAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateFormAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateMessageAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateMessageAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateNewAds: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_UpdateNewAds\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UploadCrop\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [\r\n \"File\"\r\n ],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"File\",\r\n \"x\",\r\n \"y\",\r\n \"width\",\r\n \"height\",\r\n \"scale\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateOfficialAccountAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateOfficialAccountAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdatePostAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updatePostAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateWebsiteCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createWebsiteCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateWebsiteAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateWebsiteAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateDisplayCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createDisplayCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsUpdateDisplayAd: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_updateDisplayAd\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/UpdateAd\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"est\",\r\n \"stt\",\r\n \"data\",\r\n \"isBoostAd\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsCreateVideoCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createVideoCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/zaapi/addNewCamp\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"data\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsDeleteCampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_deleteCampaign\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/campaign/change-status\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"campaignId\",\r\n \"status\"\r\n ]\r\n};\r\n\r\nconst OP_ZaloAdsDuplicateAd: OperationDefinition = {\r\n operationId: \"zalo_ads_duplicate_ad\",\r\n method: \"POST\",\r\n endpoint: \"/zaapi/DuplicateAd\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"adid\"]\r\n};\r\n\r\nconst OP_ZaloAdsCreateSpellCheckV3Job: OperationDefinition = {\r\n operationId: \"zalo_ads_create_spell_check_v3_job\",\r\n method: \"POST\",\r\n endpoint: \"/api/spell-check/v3\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"title\", \"caption\"]\r\n};\r\n\r\nconst OP_ZaloAdsGetSpellCheckV3Job: OperationDefinition = {\r\n operationId: \"zalo_ads_get_spell_check_v3_job\",\r\n method: \"GET\",\r\n endpoint: \"/api/spell-check/v3/{jobId}\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [\"jobId\"],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: []\r\n};\r\n\r\nexport class ZaloCampaignsService {\r\n public readonly validator = ZaloCampaignsValidator;\r\n public static readonly validator = ZaloCampaignsValidator;\r\n\r\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\r\n\r\n public updateVideoAd(request: Dto.ZaloAdsUpdateVideoAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateVideoAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateVideoAdResponse>(OP_ZaloAdsUpdateVideoAd, this.client.toTransportInput(OP_ZaloAdsUpdateVideoAd, request as unknown as Record<string, unknown>), options);\r\n }\r\n\r\n public changeCampaignStatus(request: Dto.ZaloAdsChangeCampaignStatusRequest, options?: RequestOptions): Promise<Dto.ZaloAdsChangeCampaignStatusResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsChangeCampaignStatusResponse>(OP_ZaloAdsChangeCampaignStatus, this.client.toTransportInput(OP_ZaloAdsChangeCampaignStatus, request as Record<string, unknown>), options);\r\n }\r\n\r\n public deleteCampaign(request: Dto.ZaloAdsDeleteCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCampaignResponse> {\r\n const payload = { campaignId: request.campaignId, status: request.status ?? -2 };\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsDeleteCampaignResponse>(OP_ZaloAdsDeleteCampaign, this.client.toTransportInput(OP_ZaloAdsDeleteCampaign, payload as Record<string, unknown>), options);\r\n }\r\n\r\n public createWebsiteCampaign(request: Dto.ZaloAdsCreateWebsiteCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateWebsiteCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateWebsiteCampaignResponse>(OP_ZaloAdsCreateWebsiteCampaign, this.client.toTransportInput(OP_ZaloAdsCreateWebsiteCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public updateWebsiteAd(request: Dto.ZaloAdsUpdateWebsiteAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateWebsiteAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateWebsiteAdResponse>(OP_ZaloAdsUpdateWebsiteAd, this.client.toTransportInput(OP_ZaloAdsUpdateWebsiteAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createDisplayCampaign(request: Dto.ZaloAdsCreateDisplayCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateDisplayCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateDisplayCampaignResponse>(OP_ZaloAdsCreateDisplayCampaign, this.client.toTransportInput(OP_ZaloAdsCreateDisplayCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public updateDisplayAd(request: Dto.ZaloAdsUpdateDisplayAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateDisplayAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateDisplayAdResponse>(OP_ZaloAdsUpdateDisplayAd, this.client.toTransportInput(OP_ZaloAdsUpdateDisplayAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createVideoCampaign(request: Dto.ZaloAdsCreateVideoCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateVideoCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateVideoCampaignResponse>(OP_ZaloAdsCreateVideoCampaign, this.client.toTransportInput(OP_ZaloAdsCreateVideoCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createEcommerceCampaign(request: Dto.ZaloAdsCreateEcommerceCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateEcommerceCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateEcommerceCampaignResponse>(OP_ZaloAdsCreateEcommerceCampaign, this.client.toTransportInput(OP_ZaloAdsCreateEcommerceCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_create_commerce_campaign` trong Project Schema Zalo ADS (`campaignType = 22`). */\r\n public createCommerceCampaign(request: Dto.ZaloAdsCreateCommerceCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCommerceCampaignResponse> {\r\n return this.createEcommerceCampaign(request, options);\r\n }\r\n\r\n public createForm(request: Dto.ZaloAdsCreateFormRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateFormResponse>(OP_ZaloAdsCreateForm, this.client.toTransportInput(OP_ZaloAdsCreateForm, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createFormCampaign(request: Dto.ZaloAdsCreateFormCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateFormCampaignResponse>(OP_ZaloAdsCreateFormCampaign, this.client.toTransportInput(OP_ZaloAdsCreateFormCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createMessageCampaign(request: Dto.ZaloAdsCreateMessageCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateMessageCampaignResponse>(OP_ZaloAdsCreateMessageCampaign, this.client.toTransportInput(OP_ZaloAdsCreateMessageCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public createOfficialAccountCampaign(request: Dto.ZaloAdsCreateOfficialAccountCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateOfficialAccountCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreateOfficialAccountCampaignResponse>(OP_ZaloAdsCreateOfficialAccountCampaign, this.client.toTransportInput(OP_ZaloAdsCreateOfficialAccountCampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_create_oa_campaign` trong Project Schema Zalo ADS (`campaignType = 3`). */\r\n public createOaCampaign(request: Dto.ZaloAdsCreateOaCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateOaCampaignResponse> {\r\n return this.createOfficialAccountCampaign(request, options);\r\n }\r\n\r\n public createPostCampaign(request: Dto.ZaloAdsCreatePostCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreatePostCampaignResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsCreatePostCampaignResponse>(OP_ZaloAdsCreatePostCampaign, this.client.toTransportInput(OP_ZaloAdsCreatePostCampaign, request as unknown as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_create_article_campaign` trong Project Schema Zalo ADS (`campaignType = 4`). */\r\n public createArticleCampaign(request: Dto.ZaloAdsCreateArticleCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateArticleCampaignResponse> {\r\n return this.createPostCampaign(request, options);\r\n }\r\n\r\n public getAdById(request: Dto.ZaloAdsGetAdByIdRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetAdByIdResponse> {\r\n const normalized = {\r\n adId: request.adId,\r\n v: request.v ?? 2,\r\n newWard: request.newWard ?? true\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetAdByIdResponse>(OP_ZaloAdsGetAdById, this.client.toTransportInput(OP_ZaloAdsGetAdById, normalized as Record<string, unknown>), options);\r\n }\r\n\r\n public getAdChangeLog(request: Dto.ZaloAdsGetAdChangeLogRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAdChangeLogResponse> {\r\n const normalized = {\r\n adId: request.adId,\r\n type: (request as any).type ?? 1\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetAdChangeLogResponse>(OP_ZaloAdsGetAdChangeLog, this.client.toTransportInput(OP_ZaloAdsGetAdChangeLog, normalized), options);\r\n }\r\n\r\n public getApiPlaceGetalldistricts(request: Dto.ZaloAdsGetApiPlaceGetalldistrictsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiPlaceGetalldistrictsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiPlaceGetalldistrictsResponse>(OP_ZaloAdsGetApiPlaceGetalldistricts, this.client.toTransportInput(OP_ZaloAdsGetApiPlaceGetalldistricts, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getApiSpellCheckV2(request: Dto.ZaloAdsGetApiSpellCheckV2Request, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiSpellCheckV2Response> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiSpellCheckV2Response>(OP_ZaloAdsGetApiSpellCheckV2, this.client.toTransportInput(OP_ZaloAdsGetApiSpellCheckV2, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getZaapiCheckcamphasmanyads(request: Dto.ZaloAdsGetZaapiCheckcamphasmanyadsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiCheckcamphasmanyadsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiCheckcamphasmanyadsResponse>(OP_ZaloAdsGetZaapiCheckcamphasmanyads, this.client.toTransportInput(OP_ZaloAdsGetZaapiCheckcamphasmanyads, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getZaapiGetadsfromcampaignid(request: Dto.ZaloAdsGetZaapiGetadsfromcampaignidRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetadsfromcampaignidResponse> {\r\n const normalized = {\r\n campaignId: request.campaignId ?? request.campId,\r\n dataType: request.dataType ?? 1,\r\n v: request.v ?? 2,\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiGetadsfromcampaignidResponse>(OP_ZaloAdsGetZaapiGetadsfromcampaignid, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetadsfromcampaignid, normalized as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias lấy danh sách quảng cáo của chiến dịch kèm metadata extend và extra.appliedRuleInfo */\r\n public getAdsFromCampaignId(request: Dto.ZaloAdsGetZaapiGetadsfromcampaignidRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetadsfromcampaignidResponse> {\r\n return this.getZaapiGetadsfromcampaignid(request, options);\r\n }\r\n\r\n public getZaapiGetallpages(request: Dto.ZaloAdsGetZaapiGetallpagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetallpagesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiGetallpagesResponse>(OP_ZaloAdsGetZaapiGetallpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetallpages, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getAllPages(request: Dto.ZaloAdsGetZaapiGetallpagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetallpagesResponse> {\r\n return this.getZaapiGetallpages(request, options);\r\n }\r\n\r\n public getZaapiGetownedarticles(request: Dto.ZaloAdsGetZaapiGetownedarticlesRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetownedarticlesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiGetownedarticlesResponse>(OP_ZaloAdsGetZaapiGetownedarticles, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedarticles, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getOwnedArticles(request: Dto.ZaloAdsGetZaapiGetownedarticlesRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetownedarticlesResponse> {\r\n return this.getZaapiGetownedarticles(request, options);\r\n }\r\n\r\n public getZaapiGetownedpages(request: Dto.ZaloAdsGetZaapiGetownedpagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetownedpagesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiGetownedpagesResponse>(OP_ZaloAdsGetZaapiGetownedpages, this.client.toTransportInput(OP_ZaloAdsGetZaapiGetownedpages, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getOwnedPages(request: Dto.ZaloAdsGetZaapiGetownedpagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiGetownedpagesResponse> {\r\n return this.getZaapiGetownedpages(request, options);\r\n }\r\n\r\n public listFormsByOfficialAccount(request: Dto.ZaloAdsListFormsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListFormsByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListFormsByOfficialAccountResponse>(OP_ZaloAdsListFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n\r\n public listMiniPagesByTemplate(request: Dto.ZaloAdsListMiniPagesByTemplateRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListMiniPagesByTemplateResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListMiniPagesByTemplateResponse>(OP_ZaloAdsListMiniPagesByTemplate, this.client.toTransportInput(OP_ZaloAdsListMiniPagesByTemplate, request as Record<string, unknown>), options);\r\n }\r\n\r\n public postZaapiDeletead(request: Dto.ZaloAdsPostZaapiDeleteadRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsPostZaapiDeleteadResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsPostZaapiDeleteadResponse>(OP_ZaloAdsPostZaapiDeletead, this.client.toTransportInput(OP_ZaloAdsPostZaapiDeletead, request as Record<string, unknown>), options);\r\n }\r\n\r\n public renameCampaign(request: Dto.ZaloAdsRenameCampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsRenameCampaignResponse> {\r\n const normalized = {\r\n campid: (request as any).campid ?? (request as any).campaignId,\r\n newname: (request as any).newname ?? (request as any).campaignName ?? (request as any).name\r\n };\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsRenameCampaignResponse>(OP_ZaloAdsRenameCampaign, this.client.toTransportInput(OP_ZaloAdsRenameCampaign, normalized), options);\r\n }\r\n\r\n public updateEcommerceAd(request: Dto.ZaloAdsUpdateEcommerceAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateEcommerceAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateEcommerceAdResponse>(OP_ZaloAdsUpdateEcommerceAd, this.client.toTransportInput(OP_ZaloAdsUpdateEcommerceAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_update_commerce_ad` trong Project Schema Zalo ADS (`Type = 23`, gắn `MiniPageId`). */\r\n public updateCommerceAd(request: Dto.ZaloAdsUpdateCommerceAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateCommerceAdResponse> {\r\n return this.updateEcommerceAd(request, options);\r\n }\r\n\r\n public updateFormAd(request: Dto.ZaloAdsUpdateFormAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateFormAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateFormAdResponse>(OP_ZaloAdsUpdateFormAd, this.client.toTransportInput(OP_ZaloAdsUpdateFormAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n public updateMessageAd(request: Dto.ZaloAdsUpdateMessageAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateMessageAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateMessageAdResponse>(OP_ZaloAdsUpdateMessageAd, this.client.toTransportInput(OP_ZaloAdsUpdateMessageAd, request as unknown as Record<string, unknown>), options);\r\n }\r\n\r\n public updateNewAds(request: Dto.ZaloAdsUpdateNewAdsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateNewAdsResponse> {\r\n return this.client.requestMultipart<Dto.ZaloAdsUpdateNewAdsResponse>(OP_ZaloAdsUpdateNewAds, this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request as Record<string, unknown>), options);\r\n }\r\n\r\n public updateOfficialAccountAd(request: Dto.ZaloAdsUpdateOfficialAccountAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateOfficialAccountAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdateOfficialAccountAdResponse>(OP_ZaloAdsUpdateOfficialAccountAd, this.client.toTransportInput(OP_ZaloAdsUpdateOfficialAccountAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_update_oa_ad` trong Project Schema Zalo ADS (`Type = 2`, `Action = 6`). */\r\n public updateOaAd(request: Dto.ZaloAdsUpdateOaAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateOaAdResponse> {\r\n return this.updateOfficialAccountAd(request, options);\r\n }\r\n\r\n public updatePostAd(request: Dto.ZaloAdsUpdatePostAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdatePostAdResponse> {\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsUpdatePostAdResponse>(OP_ZaloAdsUpdatePostAd, this.client.toTransportInput(OP_ZaloAdsUpdatePostAd, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Alias theo tên tool chuẩn `zalo_ads_update_article_ad` trong Project Schema Zalo ADS (`Type = 3`, gắn `ZaloFeedId`). */\r\n public updateArticleAd(request: Dto.ZaloAdsUpdateArticleAdRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateArticleAdResponse> {\r\n return this.updatePostAd(request, options);\r\n }\r\n\r\n /** Xóa quảng cáo */\r\n public deleteAd(...args: Parameters<this[\"postZaapiDeletead\"]>): ReturnType<this[\"postZaapiDeletead\"]> {\r\n return (this.postZaapiDeletead as any)(...args);\r\n }\r\n\r\n /** Danh sách quận/huyện để nhắm mục tiêu */\r\n public getAllDistricts(...args: Parameters<this[\"getApiPlaceGetalldistricts\"]>): ReturnType<this[\"getApiPlaceGetalldistricts\"]> {\r\n return (this.getApiPlaceGetalldistricts as any)(...args);\r\n }\r\n\r\n /** Kiểm tra chính tả văn bản quảng cáo */\r\n public getSpellCheckV2(...args: Parameters<this[\"getApiSpellCheckV2\"]>): ReturnType<this[\"getApiSpellCheckV2\"]> {\r\n return (this.getApiSpellCheckV2 as any)(...args);\r\n }\r\n\r\n /**\r\n * Khởi tạo tác vụ kiểm tra chính tả và vi phạm quy chuẩn quảng cáo AI V3 (POST /api/spell-check/v3).\r\n */\r\n public createSpellCheckV3Job(\r\n request: Dto.ZaloAdsCreateSpellCheckV3JobRequest,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloAdsCreateSpellCheckV3JobResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsCreateSpellCheckV3JobResponse>(\r\n OP_ZaloAdsCreateSpellCheckV3Job,\r\n this.client.toTransportInput(OP_ZaloAdsCreateSpellCheckV3Job, request as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n\r\n /**\r\n * Lấy kết quả kiểm tra chính tả AI V3 theo jobId (GET /api/spell-check/v3/{jobId}).\r\n */\r\n public getSpellCheckV3Job(\r\n request: Dto.ZaloAdsGetSpellCheckV3JobRequest,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloAdsGetSpellCheckV3JobResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetSpellCheckV3JobResponse>(\r\n OP_ZaloAdsGetSpellCheckV3Job,\r\n this.client.toTransportInput(OP_ZaloAdsGetSpellCheckV3Job, request as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n\r\n /**\r\n * Helper kiểm tra chính tả AI V3 trọn gói: Gửi kiểm tra và tự động polling cho đến khi hoàn thành (hoặc timeout).\r\n * @param request Tiêu đề (title) và chú thích (caption) cần kiểm tra.\r\n * @param pollIntervalMs Chu kỳ polling kiểm tra trạng thái (mặc định: 600ms).\r\n * @param timeoutMs Thời gian chờ tối đa (mặc định: 15.000ms = 15 giây).\r\n */\r\n public async checkSpellV3AndWait(\r\n request: Dto.ZaloAdsCreateSpellCheckV3JobRequest,\r\n pollIntervalMs: number = 600,\r\n timeoutMs: number = 15000,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloAdsGetSpellCheckV3JobResponse> {\r\n const jobRes = await this.createSpellCheckV3Job(request, options);\r\n const jobId = jobRes?.data?.jobId;\r\n if (!jobId) {\r\n throw new Error(`[SpellCheckV3] Không nhận được jobId từ Zalo Ads (code: ${jobRes?.code})`);\r\n }\r\n\r\n const startTime = Date.now();\r\n while (Date.now() - startTime < timeoutMs) {\r\n await new Promise(r => setTimeout(r, pollIntervalMs));\r\n const res = await this.getSpellCheckV3Job({ jobId }, options);\r\n if (res?.data?.status === \"COMPLETED\") {\r\n return res;\r\n }\r\n }\r\n throw new Error(`[SpellCheckV3] Quá thời gian chờ (${timeoutMs}ms) cho tác vụ kiểm tra chính tả jobId: ${jobId}`);\r\n }\r\n\r\n\r\n /**\r\n * Nhân bản (sao chép / duplicate) một mẫu quảng cáo đã tồn tại trên Zalo Ads (POST /zaapi/DuplicateAd).\r\n * Giúp tạo nhanh một bản sao Ad mới trong cùng chiến dịch để thực hiện A/B testing.\r\n */\r\n public duplicateAd(\r\n request: Dto.ZaloAdsDuplicateAdRequest,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloAdsDuplicateAdResponse> {\r\n const payload = {\r\n adid: request.adid ?? request.adId\r\n };\r\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsDuplicateAdResponse>(\r\n OP_ZaloAdsDuplicateAd,\r\n this.client.toTransportInput(OP_ZaloAdsDuplicateAd, payload as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n\r\n}\r\n","/**\n * Dịch vụ Quản lý Tài khoản & Thanh toán Zalo Ads (whoami, transactions, BA accessors, agency).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\n\n\nconst OP_ZaloAdsGetApiWhoami: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiWhoami\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/whoami\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiPaymentTransactionHistory: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiPaymentTransactionHistory\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/payment/transaction-history\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"to\",\n \"from\",\n \"memberId\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiBaAccountAllaccessors: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiBaAccountAllaccessors\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ba/account/allAccessors\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"isShowAll\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiBaAccountAllgrantedmembers: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiBaAccountAllgrantedmembers\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ba/account/allGrantedMembers\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsListAgencyCustomersWithBudget: OperationDefinition = {\n \"operationId\": \"ZaloAds_listAgencyCustomersWithBudget\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ba/agency/customersWithBudget\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"limit\",\n \"offset\",\n \"joinDateAsc\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiBaAgencyEmployees: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiBaAgencyEmployees\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ba/agency/employees\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiNotifiesHeader: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiNotifiesHeader\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/notifies/header\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiLpNews: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiLpNews\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/lp-news\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nexport class ZaloAccountService {\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public getApiWhoami(request: Dto.ZaloAdsGetApiWhoamiRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiWhoamiResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiWhoamiResponse>(OP_ZaloAdsGetApiWhoami, this.client.toTransportInput(OP_ZaloAdsGetApiWhoami, request as Record<string, unknown>), options);\n }\n\n public getApiPaymentTransactionHistory(request: Dto.ZaloAdsGetApiPaymentTransactionHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiPaymentTransactionHistoryResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiPaymentTransactionHistoryResponse>(OP_ZaloAdsGetApiPaymentTransactionHistory, this.client.toTransportInput(OP_ZaloAdsGetApiPaymentTransactionHistory, request as Record<string, unknown>), options);\n }\n\n public getApiBaAccountAllaccessors(request: Dto.ZaloAdsGetApiBaAccountAllaccessorsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAccountAllaccessorsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiBaAccountAllaccessorsResponse>(OP_ZaloAdsGetApiBaAccountAllaccessors, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllaccessors, request as Record<string, unknown>), options);\n }\n\n public getApiBaAccountAllgrantedmembers(request: Dto.ZaloAdsGetApiBaAccountAllgrantedmembersRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAccountAllgrantedmembersResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiBaAccountAllgrantedmembersResponse>(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, this.client.toTransportInput(OP_ZaloAdsGetApiBaAccountAllgrantedmembers, request as Record<string, unknown>), options);\n }\n\n public listAgencyCustomersWithBudget(request: Dto.ZaloAdsListAgencyCustomersWithBudgetRequest = { limit: 15, offset: 0, joinDateAsc: true }, options?: RequestOptions): Promise<Dto.ZaloAdsListAgencyCustomersWithBudgetResponse> {\n const normalized: Record<string, unknown> = {\n limit: 15,\n offset: 0,\n joinDateAsc: true,\n ...request,\n };\n return this.client.requestWithoutBody<Dto.ZaloAdsListAgencyCustomersWithBudgetResponse>(OP_ZaloAdsListAgencyCustomersWithBudget, this.client.toTransportInput(OP_ZaloAdsListAgencyCustomersWithBudget, normalized), options);\n }\n\n public getApiBaAgencyEmployees(request: Dto.ZaloAdsGetApiBaAgencyEmployeesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAgencyEmployeesResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiBaAgencyEmployeesResponse>(OP_ZaloAdsGetApiBaAgencyEmployees, this.client.toTransportInput(OP_ZaloAdsGetApiBaAgencyEmployees, request as Record<string, unknown>), options);\n }\n\n public getApiNotifiesHeader(request: Dto.ZaloAdsGetApiNotifiesHeaderRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiNotifiesHeaderResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiNotifiesHeaderResponse>(OP_ZaloAdsGetApiNotifiesHeader, this.client.toTransportInput(OP_ZaloAdsGetApiNotifiesHeader, request as Record<string, unknown>), options);\n }\n\n public getApiLpNews(request: Dto.ZaloAdsGetApiLpNewsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiLpNewsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiLpNewsResponse>(OP_ZaloAdsGetApiLpNews, this.client.toTransportInput(OP_ZaloAdsGetApiLpNews, request as Record<string, unknown>), options);\n }\n\n /** Lấy thông tin tài khoản đang đăng nhập */\n public getWhoami(...args: Parameters<this[\"getApiWhoami\"]>): ReturnType<this[\"getApiWhoami\"]> {\n return (this.getApiWhoami as any)(...args);\n }\n\n /** Lịch sử giao dịch thanh toán */\n public getPaymentTransactionHistory(...args: Parameters<this[\"getApiPaymentTransactionHistory\"]>): ReturnType<this[\"getApiPaymentTransactionHistory\"]> {\n return (this.getApiPaymentTransactionHistory as any)(...args);\n }\n\n /** Danh sách accessor tài khoản BA */\n public getBaAccountAllAccessors(...args: Parameters<this[\"getApiBaAccountAllaccessors\"]>): ReturnType<this[\"getApiBaAccountAllaccessors\"]> {\n return (this.getApiBaAccountAllaccessors as any)(...args);\n }\n\n /** Danh sách thành viên được cấp quyền BA */\n public getBaAccountAllGrantedMembers(...args: Parameters<this[\"getApiBaAccountAllgrantedmembers\"]>): ReturnType<this[\"getApiBaAccountAllgrantedmembers\"]> {\n return (this.getApiBaAccountAllgrantedmembers as any)(...args);\n }\n\n /** Danh sách nhân viên trực thuộc Agency */\n public getBaAgencyEmployees(...args: Parameters<this[\"getApiBaAgencyEmployees\"]>): ReturnType<this[\"getApiBaAgencyEmployees\"]> {\n return (this.getApiBaAgencyEmployees as any)(...args);\n }\n\n /** Thông báo trên thanh tiêu đề */\n public getNotifiesHeader(...args: Parameters<this[\"getApiNotifiesHeader\"]>): ReturnType<this[\"getApiNotifiesHeader\"]> {\n return (this.getApiNotifiesHeader as any)(...args);\n }\n\n /** Tin tức landing page / bảng tin */\n public getLpNews(...args: Parameters<this[\"getApiLpNews\"]>): ReturnType<this[\"getApiLpNews\"]> {\n return (this.getApiLpNews as any)(...args);\n }\n}\n","/**\n * Dịch vụ Quản lý Đối tượng Tùy chỉnh & Ước tính Tiếp cận (Custom Audiences, Phone List, Lookalike, Event Audiences).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\nimport { ZaloAudiencesValidator } from \"../validators/audiences.validator\";\n\n\nconst OP_ZaloAdsCreateCustomAudience: OperationDefinition = {\n \"operationId\": \"ZaloAds_createCustomAudience\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/ad/audience\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"name\",\n \"caType\",\n \"targeting\"\n ]\n};\n\nconst OP_ZaloAdsDeleteCustomAudience: OperationDefinition = {\n \"operationId\": \"ZaloAds_deleteCustomAudience\",\n \"method\": \"DELETE\",\n \"endpoint\": \"/api/ad/audience/{customAudienceId}\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [\n \"customAudienceId\"\n ],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiAdGetlistadadvancetargeting: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiAdGetlistadadvancetargeting\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/ad/getListAdAdvanceTargeting\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetApiCustomAudienceAll: OperationDefinition = {\n \"operationId\": \"ZaloAds_getApiCustomAudienceAll\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/custom-audience/all\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"newWard\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsPostApiAdEstimateaudience: OperationDefinition = {\n \"operationId\": \"ZaloAds_postApiAdEstimateaudience\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/ad/estimateAudience\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"gender\",\n \"number\",\n \"ageRanges\",\n \"locations\",\n \"platforms\",\n \"priceType\",\n \"provinces\",\n \"wardsTargeting\",\n \"districtsTargeting\"\n ]\n};\n\nconst OP_ZaloAdsUploadCustomAudiencePhoneList: OperationDefinition = {\n \"operationId\": \"ZaloAds_uploadCustomAudiencePhoneList\",\n \"method\": \"POST\",\n \"endpoint\": \"/zaapi/uploadPhoneList\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [\n \"File\"\n ],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"File\",\n \"isHash\"\n ]\n};\n\nexport class ZaloAudiencesService {\n public static readonly validator = ZaloAudiencesValidator;\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public postApiAdEstimateaudience(request: Dto.ZaloAdsPostApiAdEstimateaudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiAdEstimateaudienceResponse> {\n return this.client.requestJson<Dto.ZaloAdsPostApiAdEstimateaudienceResponse>(OP_ZaloAdsPostApiAdEstimateaudience, this.client.toTransportInput(OP_ZaloAdsPostApiAdEstimateaudience, request as Record<string, unknown>), options);\n }\n\n public getApiAdGetlistadadvancetargeting(request: Dto.ZaloAdsGetApiAdGetlistadadvancetargetingRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiAdGetlistadadvancetargetingResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiAdGetlistadadvancetargetingResponse>(OP_ZaloAdsGetApiAdGetlistadadvancetargeting, this.client.toTransportInput(OP_ZaloAdsGetApiAdGetlistadadvancetargeting, request as Record<string, unknown>), options);\n }\n\n public getApiCustomAudienceAll(request: Dto.ZaloAdsGetApiCustomAudienceAllRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiCustomAudienceAllResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiCustomAudienceAllResponse>(OP_ZaloAdsGetApiCustomAudienceAll, this.client.toTransportInput(OP_ZaloAdsGetApiCustomAudienceAll, request as Record<string, unknown>), options);\n }\n\n public createCustomAudience(request: Dto.ZaloAdsCreateCustomAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCustomAudienceResponse> {\n return this.client.requestJson<Dto.ZaloAdsCreateCustomAudienceResponse>(OP_ZaloAdsCreateCustomAudience, this.client.toTransportInput(OP_ZaloAdsCreateCustomAudience, request as Record<string, unknown>), options);\n }\n\n public deleteCustomAudience(request: Dto.ZaloAdsDeleteCustomAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCustomAudienceResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsDeleteCustomAudienceResponse>(OP_ZaloAdsDeleteCustomAudience, this.client.toTransportInput(OP_ZaloAdsDeleteCustomAudience, request as Record<string, unknown>), options);\n }\n\n public uploadCustomAudiencePhoneList(request: Dto.ZaloAdsUploadCustomAudiencePhoneListRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUploadCustomAudiencePhoneListResponse> {\n return this.client.requestMultipart<Dto.ZaloAdsUploadCustomAudiencePhoneListResponse>(OP_ZaloAdsUploadCustomAudiencePhoneList, this.client.toTransportInput(OP_ZaloAdsUploadCustomAudiencePhoneList, request as Record<string, unknown>), options);\n }\n\n /** Tạo mới 'Nhóm đối tượng đã lưu' (`caType = 1` - `DEFAULT`) trên Zalo Ads (`POST /api/ad/audience`). */\n public createSavedAudience(request: Dto.ZaloAdsCreateSavedAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateSavedAudienceResponse> {\n const targetingStr =\n typeof request.targeting === \"string\"\n ? request.targeting\n : JSON.stringify(request.targeting);\n return this.createCustomAudience(\n {\n name: request.name,\n caType: 1,\n targeting: targetingStr,\n },\n options\n );\n }\n\n /** Tạo mới Nhóm đối tượng từ danh sách Số điện thoại (`caType = 3` - `PHONE_LIST`). */\n public createPhoneAudience(request: Dto.ZaloAdsCreatePhoneAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreatePhoneAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 3, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng tương tự Lookalike (`caType = 6` - `LOOKALIKE`). */\n public createLookalikeAudience(request: Dto.ZaloAdsCreateLookalikeAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateLookalikeAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 6, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Zalo Form (`caType = 12` - `FORM_EVENT_AUDIENCE`). */\n public createFormEventAudience(request: Dto.ZaloAdsCreateFormEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormEventAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 12, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn OA (`caType = 11` - `MESSAGE_AUDIENCE`). */\n public createMessageOaEventAudience(request: Dto.ZaloAdsCreateMessageOaEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageOaEventAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 11, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn cá nhân (`caType = 14` - `MESSAGE_PERSONAL_EVENT_AUDIENCE`). */\n public createMessagePersonalEventAudience(request: Dto.ZaloAdsCreateMessagePersonalEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessagePersonalEventAudienceResponse> {\n let targetingObj: any;\n if (typeof request.targeting === \"string\") {\n try {\n targetingObj = JSON.parse(request.targeting);\n } catch {\n targetingObj = null;\n }\n } else if (request.targeting && typeof request.targeting === \"object\") {\n targetingObj = { ...request.targeting };\n }\n if (targetingObj && typeof targetingObj === \"object\") {\n if (targetingObj.EventId === undefined && targetingObj.EventType !== undefined) {\n targetingObj.EventId = targetingObj.EventType;\n }\n }\n const targetingStr = targetingObj ? JSON.stringify(targetingObj) : (typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting));\n return this.createCustomAudience({ name: request.name, caType: 14, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Zalo Form (`caType = 10` - `FORM_AUDIENCE`). */\n public createFormLeadAudience(request: Dto.ZaloAdsCreateFormLeadAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormLeadAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 10, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Commerce Form (`caType = 15` - `COMMERCE_FORM_AUDIENCE`). */\n public createCommerceFormAudience(request: Dto.ZaloAdsCreateCommerceFormAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCommerceFormAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 15, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Kịch bản Tin nhắn OA (`caType = 13` - `MESSAGE_OA_AUDIENCE`). */\n public createMessageOaLeadAudience(request: Dto.ZaloAdsCreateMessageOaLeadAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageOaLeadAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 13, targeting: targetingStr }, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Dữ liệu chuyển đổi Lead Signal (`caType = 16` - `LEAD_SIGNAL_AUDIENCE`). */\n public createLeadSignalAudience(request: Dto.ZaloAdsCreateLeadSignalAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateLeadSignalAudienceResponse> {\n const targetingStr = typeof request.targeting === \"string\" ? request.targeting : JSON.stringify(request.targeting);\n return this.createCustomAudience({ name: request.name, caType: 16, targeting: targetingStr }, options);\n }\n\n /** Ước tính quy mô đối tượng tiếp cận */\n public estimateAudience(...args: Parameters<this[\"postApiAdEstimateaudience\"]>): ReturnType<this[\"postApiAdEstimateaudience\"]> {\n return (this.postApiAdEstimateaudience as any)(...args);\n }\n\n /** Danh sách toàn bộ nhóm đối tượng tùy chỉnh */\n public listCustomAudiences(...args: Parameters<this[\"getApiCustomAudienceAll\"]>): ReturnType<this[\"getApiCustomAudienceAll\"]> {\n return (this.getApiCustomAudienceAll as any)(...args);\n }\n\n /** Danh sách cấu hình nhắm mục tiêu nâng cao */\n public getListAdAdvanceTargeting(...args: Parameters<this[\"getApiAdGetlistadadvancetargeting\"]>): ReturnType<this[\"getApiAdGetlistadadvancetargeting\"]> {\n return (this.getApiAdGetlistadadvancetargeting as any)(...args);\n }\n}\n","/**\r\n * Dịch vụ Báo cáo & Thống kê Hiệu quả Zalo Ads (Campaigns, Ads, Demographics, Overview, Custom Reports).\r\n */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/ads.dto\";\r\n\r\n\r\nconst OP_ZaloAdsGetReportapiV2Ads: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportapiV2Ads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/v2/ads\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"to\",\r\n \"from\",\r\n \"filter\",\r\n \"endDate\",\r\n \"refresh\",\r\n \"breakdown\",\r\n \"startDate\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetReportapiV2Campaigns: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportapiV2Campaigns\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/v2/campaigns/{campaignId}\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"campaignId\"\r\n ],\r\n \"queryFields\": [\r\n \"startDate\",\r\n \"endDate\",\r\n \"refresh\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetReportapiV2UniqueUser: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportapiV2UniqueUser\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/v2/unique-user\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"start\",\r\n \"end\",\r\n \"campaignId\",\r\n \"adId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetReportapiV3Campaigns: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportapiV3Campaigns\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/v3/campaigns\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"filter\",\r\n \"endDate\",\r\n \"refresh\",\r\n \"agencyId\",\r\n \"createdBy\",\r\n \"startDate\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetReportOverview: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getReportOverview\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/report/overview\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"data\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetDemographicsReport: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getDemographicsReport\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/demographics/report\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"campaignId\",\r\n \"adId\",\r\n \"startDate\",\r\n \"endDate\",\r\n \"agencyId\",\r\n \"from\",\r\n \"to\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsDeleteCustomReport: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_deleteCustomReport\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/reportapi/custom-report/delete/{id}\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"id\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsListReportFilters: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listReportFilters\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/api/filter/list\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"model\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsGetZaapiCampaignReportcampaign: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getZaapiCampaignReportcampaign\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/zaapi/Campaign/reportCampaign\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"campaignId\",\r\n \"campId\",\r\n \"from\",\r\n \"to\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsListCustomReports: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listCustomReports\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/reportapi/custom-report/list\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloAdsUpsertCustomReport: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_upsertCustomReport\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/reportapi/custom-report/update\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"id\",\r\n \"name\",\r\n \"settings\",\r\n \"isDefault\"\r\n ]\r\n};\r\n\r\n\r\nconst OP_ZaloAdsDownloadReport: OperationDefinition = {\r\n operationId: \"zalo_ads_download_report\",\r\n method: \"POST\",\r\n endpoint: \"/api/collect\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\r\n \"t\",\r\n \"adIds\",\r\n \"status\",\r\n \"dateFilter\",\r\n \"reportKind\",\r\n \"et\"\r\n ]\r\n};\r\n\r\nexport class ZaloReportsService {\r\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\r\n\r\n public getReportapiV2Ads(request: Dto.ZaloAdsGetReportapiV2AdsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2AdsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportapiV2AdsResponse>(OP_ZaloAdsGetReportapiV2Ads, this.client.toTransportInput(OP_ZaloAdsGetReportapiV2Ads, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getReportapiV2Campaigns(request: Dto.ZaloAdsGetReportapiV2CampaignsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2CampaignsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportapiV2CampaignsResponse>(OP_ZaloAdsGetReportapiV2Campaigns, this.client.toTransportInput(OP_ZaloAdsGetReportapiV2Campaigns, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getReportapiV2UniqueUser(request: Dto.ZaloAdsGetReportapiV2UniqueUserRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2UniqueUserResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportapiV2UniqueUserResponse>(OP_ZaloAdsGetReportapiV2UniqueUser, this.client.toTransportInput(OP_ZaloAdsGetReportapiV2UniqueUser, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getReportapiV3Campaigns(request: Dto.ZaloAdsGetReportapiV3CampaignsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV3CampaignsResponse> {\r\n const normalized: Record<string, unknown> = {\r\n filter: \"[]\",\r\n ...request,\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportapiV3CampaignsResponse>(OP_ZaloAdsGetReportapiV3Campaigns, this.client.toTransportInput(OP_ZaloAdsGetReportapiV3Campaigns, normalized), options);\r\n }\r\n\r\n public getReportOverview(request: Dto.ZaloAdsGetReportOverviewRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportOverviewResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetReportOverviewResponse>(OP_ZaloAdsGetReportOverview, this.client.toTransportInput(OP_ZaloAdsGetReportOverview, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getDemographicsReport(request: Dto.ZaloAdsGetDemographicsReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetDemographicsReportResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetDemographicsReportResponse>(OP_ZaloAdsGetDemographicsReport, this.client.toTransportInput(OP_ZaloAdsGetDemographicsReport, request as Record<string, unknown>), options);\r\n }\r\n\r\n public getZaapiCampaignReportcampaign(request: Dto.ZaloAdsGetZaapiCampaignReportcampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiCampaignReportcampaignResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetZaapiCampaignReportcampaignResponse>(OP_ZaloAdsGetZaapiCampaignReportcampaign, this.client.toTransportInput(OP_ZaloAdsGetZaapiCampaignReportcampaign, request as Record<string, unknown>), options);\r\n }\r\n\r\n public listCustomReports(request: Dto.ZaloAdsListCustomReportsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListCustomReportsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListCustomReportsResponse>(OP_ZaloAdsListCustomReports, this.client.toTransportInput(OP_ZaloAdsListCustomReports, request as Record<string, unknown>), options);\r\n }\r\n\r\n public upsertCustomReport(request: Dto.ZaloAdsUpsertCustomReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpsertCustomReportResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsUpsertCustomReportResponse>(OP_ZaloAdsUpsertCustomReport, this.client.toTransportInput(OP_ZaloAdsUpsertCustomReport, request as Record<string, unknown>), options);\r\n }\r\n\r\n public deleteCustomReport(request: Dto.ZaloAdsDeleteCustomReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCustomReportResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsDeleteCustomReportResponse>(OP_ZaloAdsDeleteCustomReport, this.client.toTransportInput(OP_ZaloAdsDeleteCustomReport, request as Record<string, unknown>), options);\r\n }\r\n\r\n public listReportFilters(request: Dto.ZaloAdsListReportFiltersRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListReportFiltersResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListReportFiltersResponse>(OP_ZaloAdsListReportFilters, this.client.toTransportInput(OP_ZaloAdsListReportFilters, request as Record<string, unknown>), options);\r\n }\r\n\r\n /** Báo cáo hiệu quả chiến dịch (API V3 - Khuyên dùng) */\r\n public getCampaignReportV3(...args: Parameters<this[\"getReportapiV3Campaigns\"]>): ReturnType<this[\"getReportapiV3Campaigns\"]> {\r\n return (this.getReportapiV3Campaigns as any)(...args);\r\n }\r\n\r\n /** Báo cáo hiệu quả chiến dịch (API V2) */\r\n public getCampaignReportV2(...args: Parameters<this[\"getReportapiV2Campaigns\"]>): ReturnType<this[\"getReportapiV2Campaigns\"]> {\r\n return (this.getReportapiV2Campaigns as any)(...args);\r\n }\r\n\r\n /** Báo cáo hiệu quả quảng cáo (API V2) */\r\n public getAdsReportV2(...args: Parameters<this[\"getReportapiV2Ads\"]>): ReturnType<this[\"getReportapiV2Ads\"]> {\r\n return (this.getReportapiV2Ads as any)(...args);\r\n }\r\n\r\n /** Báo cáo người dùng tiếp cận duy nhất (Unique Reach) */\r\n public getUniqueUserReport(...args: Parameters<this[\"getReportapiV2UniqueUser\"]>): ReturnType<this[\"getReportapiV2UniqueUser\"]> {\r\n return (this.getReportapiV2UniqueUser as any)(...args);\r\n }\r\n\r\n /** Báo cáo chiến dịch theo ngày/tháng (Legacy ZAAPI) */\r\n public getCampaignReportLegacy(...args: Parameters<this[\"getZaapiCampaignReportcampaign\"]>): ReturnType<this[\"getZaapiCampaignReportcampaign\"]> {\r\n return (this.getZaapiCampaignReportcampaign as any)(...args);\r\n }\r\n\r\n /** Xuất và tải trực tiếp tệp tin Excel (.xlsx / Blob) báo cáo hiệu quả quảng cáo (POST /api/collect) */\r\n public downloadReport(request: Dto.ZaloAdsDownloadReportRequest, options?: RequestOptions): Promise<Blob> {\r\n const payload = {\r\n t: request.t ?? \"cd.download.report\",\r\n status: request.status ?? 2,\r\n dateFilter: request.dateFilter ?? 0,\r\n reportKind: request.reportKind ?? 100001,\r\n et: request.et ?? Math.floor(Date.now() / 1000),\r\n adIds: request.adIds\r\n };\r\n return this.client.requestJson<Blob>(OP_ZaloAdsDownloadReport, this.client.toTransportInput(OP_ZaloAdsDownloadReport, payload as Record<string, unknown>), options);\r\n }\r\n\r\n}\r\n","/**\n * Dịch vụ Quản lý Chuyển đổi & Zalo Pixel (Conversions, Standard Events, Lead Signals, Pixel Labels).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\n\n\nconst OP_ZaloAdsCreateConversion: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_createConversion\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/conversion/add\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"name\",\r\n \"landingPage\",\r\n \"urlType\",\r\n \"labelId\",\r\n \"buttonIds\",\r\n \"elements\",\r\n \"keywords\"\r\n ]\r\n};\n\nconst OP_ZaloAdsDeleteConversion: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_deleteConversion\",\r\n \"method\": \"DELETE\",\r\n \"endpoint\": \"/api/conversion/delete/{conversionId}\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"conversionId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\n\nconst OP_ZaloAdsGetApiConversionAll: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getApiConversionAll\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/conversion/all\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\n\nconst OP_ZaloAdsGetApiConversionStandardEvents: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_getApiConversionStandardEvents\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/conversion/standard-events\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\n\nconst OP_ZaloAdsListPersonalPixelLabels: OperationDefinition = {\r\n \"operationId\": \"ZaloAds_listPersonalPixelLabels\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/conversion/support-personal-pixel-labels\",\r\n \"baseUrl\": \"https://ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\n\nexport class ZaloConversionsService {\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public createConversion(request: Dto.ZaloAdsCreateConversionRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateConversionResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsCreateConversionResponse>(OP_ZaloAdsCreateConversion, this.client.toTransportInput(OP_ZaloAdsCreateConversion, request as Record<string, unknown>), options);\r\n }\r\n\n public deleteConversion(request: Dto.ZaloAdsDeleteConversionRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteConversionResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsDeleteConversionResponse>(OP_ZaloAdsDeleteConversion, this.client.toTransportInput(OP_ZaloAdsDeleteConversion, request as Record<string, unknown>), options);\r\n }\r\n\n public getApiConversionAll(request: Dto.ZaloAdsGetApiConversionAllRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiConversionAllResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiConversionAllResponse>(OP_ZaloAdsGetApiConversionAll, this.client.toTransportInput(OP_ZaloAdsGetApiConversionAll, request as Record<string, unknown>), options);\r\n }\r\n\n public getApiConversionStandardEvents(request: Dto.ZaloAdsGetApiConversionStandardEventsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiConversionStandardEventsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiConversionStandardEventsResponse>(OP_ZaloAdsGetApiConversionStandardEvents, this.client.toTransportInput(OP_ZaloAdsGetApiConversionStandardEvents, request as Record<string, unknown>), options);\r\n }\r\n\n public listPersonalPixelLabels(request: Dto.ZaloAdsListPersonalPixelLabelsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListPersonalPixelLabelsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListPersonalPixelLabelsResponse>(OP_ZaloAdsListPersonalPixelLabels, this.client.toTransportInput(OP_ZaloAdsListPersonalPixelLabels, request as Record<string, unknown>), options);\r\n }\r\n\n /** Lấy danh sách tài khoản Zalo Official Account (OA) có dữ liệu chuyển đổi (Lead Signal) (`GET /api/ad/audience/leadSignal/oas`). */\r\n public listLeadSignalOas(options?: RequestOptions): Promise<Dto.ZaloAdsListLeadSignalOasResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListLeadSignalOasResponse>(\r\n {\r\n operationId: \"ZaloAds_listLeadSignalOas\",\r\n method: \"GET\",\r\n endpoint: \"/api/ad/audience/leadSignal/oas\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [],\r\n },\r\n undefined,\r\n options\r\n );\r\n }\r\n\n /** Lấy danh sách rút gọn gồm ID và tên của toàn bộ các sự kiện chuyển đổi (Conversion) đã tạo trên tài khoản quảng cáo Zalo Ads (`GET /api/conversion/names`). */\r\n public listConversionNames(request: Dto.ZaloAdsListConversionNamesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListConversionNamesResponse> {\r\n const op: OperationDefinition = {\r\n operationId: \"ZaloAds_listConversionNames\",\r\n method: \"GET\",\r\n endpoint: \"/api/conversion/names\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [],\r\n };\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListConversionNamesResponse>(\r\n op,\r\n this.client.toTransportInput(op, request as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n\n /** Alias cho `listConversionNames` (`GET /api/conversion/names`). */\r\n public getApiConversionNames(request: Dto.ZaloAdsListConversionNamesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListConversionNamesResponse> {\r\n return this.listConversionNames(request, options);\r\n }\r\n\n /** Danh sách toàn bộ sự kiện chuyển đổi */\n public listConversions(...args: Parameters<this[\"getApiConversionAll\"]>): ReturnType<this[\"getApiConversionAll\"]> {\n return (this.getApiConversionAll as any)(...args);\n }\n\n /** Danh sách sự kiện chuyển đổi tiêu chuẩn */\n public getConversionStandardEvents(...args: Parameters<this[\"getApiConversionStandardEvents\"]>): ReturnType<this[\"getApiConversionStandardEvents\"]> {\n return (this.getApiConversionStandardEvents as any)(...args);\n }\n}\n","/**\n * Dịch vụ Quản lý Quy tắc Tự động Zalo Ads (Automated Rules CRUD, Status, History).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\n\nconst OP_ZaloAdsListAutomatedRules: OperationDefinition = {\n \"operationId\": \"ZaloAds_listAutomatedRules\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/automatedrules/list\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"ruleName\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsGetAutomatedRuleDetail: OperationDefinition = {\n \"operationId\": \"ZaloAds_getAutomatedRuleDetail\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/automatedrules/{automatedRuleId}\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [\n \"automatedRuleId\"\n ],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsCreateAutomatedRule: OperationDefinition = {\n \"operationId\": \"ZaloAds_createAutomatedRule\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/automatedrules/create\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"scope\",\n \"appliedTo\",\n \"ruleName\",\n \"action\",\n \"conditions\",\n \"frequency\",\n \"appliedIds\",\n \"schedule\",\n \"campaignIds\",\n \"adIds\"\n ]\n};\n\nconst OP_ZaloAdsUpdateAutomatedRule: OperationDefinition = {\n \"operationId\": \"ZaloAds_updateAutomatedRule\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/ad/automatedrules/update\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"automatedRuleId\",\n \"scope\",\n \"ruleName\",\n \"action\",\n \"conditions\",\n \"frequency\",\n \"appliedItems\",\n \"appliedIds\",\n \"rowVersion\",\n \"appliedTo\",\n \"schedule\",\n \"campaignIds\",\n \"adIds\"\n ]\n};\n\nconst OP_ZaloAdsChangeAutomatedRuleStatus: OperationDefinition = {\n \"operationId\": \"ZaloAds_changeAutomatedRuleStatus\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/automatedrules/change-status\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"automatedRuleId\",\n \"automatedRuleIds\",\n \"status\"\n ]\n};\n\nconst OP_ZaloAdsGetAutomatedRuleHistory: OperationDefinition = {\n \"operationId\": \"ZaloAds_getAutomatedRuleHistory\",\n \"method\": \"GET\",\n \"endpoint\": \"/api/automatedrules/history/{automatedRuleId}\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [\n \"automatedRuleId\"\n ],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloAdsDeleteAutomatedRule: OperationDefinition = {\n \"operationId\": \"ZaloAds_deleteAutomatedRule\",\n \"method\": \"POST\",\n \"endpoint\": \"/api/automatedrules/delete\",\n \"baseUrl\": \"https://ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"automatedRuleIds\"\n ]\n};\n\nexport class ZaloAutomatedRulesService {\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public listAutomatedRules(request: Dto.ZaloAdsListAutomatedRulesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListAutomatedRulesResponse> {\n const queryInput = { query_param: { ruleName: request.ruleName ?? \"\" } };\n return this.client.requestWithoutBody<Dto.ZaloAdsListAutomatedRulesResponse>(OP_ZaloAdsListAutomatedRules, queryInput, options);\n }\n\n public getAutomatedRuleDetail(request: Dto.ZaloAdsGetAutomatedRuleDetailRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAutomatedRuleDetailResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetAutomatedRuleDetailResponse>(OP_ZaloAdsGetAutomatedRuleDetail, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleDetail, request as Record<string, unknown>), options);\n }\n\n public createAutomatedRule(request: Dto.ZaloAdsCreateAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateAutomatedRuleResponse> {\n return this.client.requestJson<Dto.ZaloAdsCreateAutomatedRuleResponse>(OP_ZaloAdsCreateAutomatedRule, this.client.toTransportInput(OP_ZaloAdsCreateAutomatedRule, request as Record<string, unknown>), options);\n }\n\n public updateAutomatedRule(request: Dto.ZaloAdsUpdateAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateAutomatedRuleResponse> {\n return this.client.requestJson<Dto.ZaloAdsUpdateAutomatedRuleResponse>(OP_ZaloAdsUpdateAutomatedRule, this.client.toTransportInput(OP_ZaloAdsUpdateAutomatedRule, request as Record<string, unknown>), options);\n }\n\n public changeAutomatedRuleStatus(request: Dto.ZaloAdsChangeAutomatedRuleStatusRequest, options?: RequestOptions): Promise<Dto.ZaloAdsChangeAutomatedRuleStatusResponse> {\n return this.client.requestJson<Dto.ZaloAdsChangeAutomatedRuleStatusResponse>(OP_ZaloAdsChangeAutomatedRuleStatus, this.client.toTransportInput(OP_ZaloAdsChangeAutomatedRuleStatus, request as Record<string, unknown>), options);\n }\n\n public getAutomatedRuleHistory(request: Dto.ZaloAdsGetAutomatedRuleHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAutomatedRuleHistoryResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetAutomatedRuleHistoryResponse>(OP_ZaloAdsGetAutomatedRuleHistory, this.client.toTransportInput(OP_ZaloAdsGetAutomatedRuleHistory, request as Record<string, unknown>), options);\n }\n\n public deleteAutomatedRule(request: Dto.ZaloAdsDeleteAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteAutomatedRuleResponse> {\n return this.client.requestJson<Dto.ZaloAdsDeleteAutomatedRuleResponse>(OP_ZaloAdsDeleteAutomatedRule, this.client.toTransportInput(OP_ZaloAdsDeleteAutomatedRule, request as Record<string, unknown>), options);\n }\n}\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Zalo Message Flows:\n * 1. listFlowsByOfficialAccount (GET /api/flow/getByOaId)\n * 2. createFlow (POST /api/flow/create)\n * 3. updateFlow (POST /api/flow/update)\n *\n * Được thiết kế theo dạng hàm thuần (pure functions) độc lập, xuất ra ngoài để backend\n * (NestJS/Express/Fastify), middleware hoặc AI Agent sử dụng xác thực dữ liệu trước khi gọi Zalo Ads.\n */\nimport type * as Dto from \"../dtos/ads.dto\";\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\n\n/** Giới hạn số nguyên 32-bit có dấu của Play Framework (Java Integer.MAX_VALUE). */\nconst MAX_INT_32 = 2147483647;\n\nfunction is32BitPositiveInteger(val: unknown): boolean {\n if (typeof val === \"number\") {\n return Number.isInteger(val) && val > 0 && val <= MAX_INT_32;\n }\n if (typeof val === \"string\" && val.trim() !== \"\") {\n const num = Number(val);\n return Number.isInteger(num) && num > 0 && num <= MAX_INT_32;\n }\n return false;\n}\n\nfunction isPositiveInteger(val: unknown): boolean {\n if (typeof val === \"number\") return Number.isInteger(val) && val > 0;\n if (typeof val === \"string\" && val.trim() !== \"\") {\n const num = Number(val);\n return Number.isInteger(num) && num > 0;\n }\n return false;\n}\n\nfunction isNonNegativeInteger(val: unknown): boolean {\n if (typeof val === \"number\") return Number.isInteger(val) && val >= 0;\n if (typeof val === \"string\" && val.trim() !== \"\") {\n const num = Number(val);\n return Number.isInteger(num) && num >= 0;\n }\n return false;\n}\n\nfunction toPositiveInteger(val: unknown): number {\n return typeof val === \"number\" ? Math.floor(val) : parseInt(String(val), 10);\n}\n\n// ============================================================================\n// Helper validate cấu trúc nút bấm (ZaloAdsFlowButtonDto)\n// ============================================================================\nfunction validateFlowButtons(buttons: unknown, errors: string[], prefix: string): Dto.ZaloAdsFlowButtonDto[] {\n if (!Array.isArray(buttons)) {\n errors.push(`${prefix}: Trường 'buttons' phải là một mảng.`);\n return [];\n }\n\n const cleanButtons: Dto.ZaloAdsFlowButtonDto[] = [];\n\n buttons.forEach((btn, idx) => {\n const btnPrefix = `${prefix}.buttons[${idx}]`;\n if (!btn || typeof btn !== \"object\") {\n errors.push(`${btnPrefix}: Nút bấm phải là một đối tượng.`);\n return;\n }\n const b = btn as Record<string, unknown>;\n\n // 1. Nhãn nút\n if (typeof b.text !== \"string\" || b.text.trim() === \"\") {\n errors.push(`${btnPrefix}: Nhãn nút 'text' là bắt buộc và không được để trống.`);\n }\n\n // 2. Loại nút: 3 (nhánh), 10 (website), 12 (hotline)\n const btnType = Number(b.type);\n if (![3, 10, 12].includes(btnType)) {\n errors.push(`${btnPrefix}: Loại nút 'type' phải là 3 (nhánh hội thoại), 10 (mở website), hoặc 12 (gọi hotline).`);\n }\n\n const cleanBtn: Dto.ZaloAdsFlowButtonDto = {\n type: btnType,\n text: String(b.text ?? \"\").trim(),\n editable: b.editable !== false\n };\n\n // Chi tiết theo loại nút\n if (btnType === 10) {\n if (typeof b.url !== \"string\" || b.url.trim() === \"\") {\n errors.push(`${btnPrefix}: Nút loại 10 (mở website) bắt buộc phải có trường 'url' hợp lệ.`);\n } else {\n cleanBtn.url = b.url.trim();\n }\n } else if (btnType === 12) {\n if (typeof b.phone !== \"string\" || b.phone.trim() === \"\") {\n errors.push(`${btnPrefix}: Nút loại 12 (gọi hotline) bắt buộc phải có trường 'phone' hợp lệ.`);\n } else {\n cleanBtn.phone = b.phone.trim();\n }\n } else if (btnType === 3) {\n if (!Array.isArray(b.messages) || b.messages.length === 0) {\n errors.push(`${btnPrefix}: Nút loại 3 (nhánh hội thoại) bắt buộc phải có mảng 'messages' chứa ít nhất 1 tin nhắn con phản hồi.`);\n } else {\n const cleanChildMsgs: Dto.ZaloAdsFlowChildMessageDto[] = [];\n b.messages.forEach((child, cIdx) => {\n const childPrefix = `${btnPrefix}.messages[${cIdx}]`;\n if (!child || typeof child !== \"object\") {\n errors.push(`${childPrefix}: Tin nhắn con phải là một đối tượng.`);\n return;\n }\n const c = child as Record<string, unknown>;\n if (typeof c.text !== \"string\" || c.text.trim() === \"\") {\n errors.push(`${childPrefix}: Nội dung tin nhắn con 'text' không được để trống.`);\n } else if (c.text.length > 1961) {\n errors.push(`${childPrefix}: Nội dung tin nhắn con vượt quá 1961 ký tự (hiện có ${c.text.length} ký tự).`);\n }\n cleanChildMsgs.push({\n type: 8,\n text: String(c.text ?? \"\").trim()\n });\n });\n cleanBtn.messages = cleanChildMsgs;\n }\n }\n\n cleanButtons.push(cleanBtn);\n });\n\n return cleanButtons;\n}\n\n// ============================================================================\n// Helper validate tin nhắn kịch bản (ZaloAdsFlowMessageDto)\n// ============================================================================\nfunction validateFlowMessages(messages: unknown, errors: string[]): Dto.ZaloAdsFlowMessageDto[] {\n if (!Array.isArray(messages)) {\n errors.push(\"Trường 'messages' phải là một mảng chứa tin nhắn kịch bản.\");\n return [];\n }\n\n if (messages.length !== 1) {\n errors.push(`Zalo Ads chỉ cho phép kịch bản chứa DUY NHẤT 1 tin nhắn chào mừng cấp cao (hiện có ${messages.length} tin nhắn). Các nhánh hội thoại tiếp theo phải cấu hình bên trong nút bấm loại 3 (type=3).`);\n return [];\n }\n\n const msg = messages[0];\n if (!msg || typeof msg !== \"object\") {\n errors.push(\"Tin nhắn kịch bản phải là một đối tượng.\");\n return [];\n }\n const m = msg as Record<string, unknown>;\n\n const msgType = Number(m.type);\n if (![1, 2].includes(msgType)) {\n errors.push(\"Loại tin nhắn 'type' phải là 1 (văn bản) hoặc 2 (kèm hình ảnh).\");\n }\n\n if (typeof m.text !== \"string\" || m.text.trim() === \"\") {\n errors.push(\"Nội dung tin nhắn 'text' là bắt buộc và không được để trống.\");\n } else if (m.text.length > 1961) {\n errors.push(`Nội dung tin nhắn vượt quá 1961 ký tự (hiện có ${m.text.length} ký tự).`);\n }\n\n const cleanMsg: Dto.ZaloAdsFlowMessageDto = {\n type: msgType,\n text: String(m.text ?? \"\").trim()\n };\n\n if (msgType === 2) {\n if (typeof m.url !== \"string\" || m.url.trim() === \"\") {\n errors.push(\"Tin nhắn loại 2 (kèm ảnh) bắt buộc phải có trường 'url' chứa đường dẫn hình ảnh.\");\n } else {\n cleanMsg.url = m.url.trim();\n }\n }\n\n if (m.buttons !== undefined && m.buttons !== null) {\n cleanMsg.buttons = validateFlowButtons(m.buttons, errors, \"messages[0]\");\n }\n\n return [cleanMsg];\n}\n\n// ============================================================================\n// 1. listFlowsByOfficialAccount (GET /api/flow/getByOaId)\n// ============================================================================\nexport function validateListFlowsByOfficialAccountRequest(input: unknown): ValidationResult<Dto.ZaloAdsListFlowsByOfficialAccountRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy danh sách kịch bản phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n // oaId: 32-bit positive integer (internal pageId)\n if (!is32BitPositiveInteger(obj.oaId)) {\n errors.push(\"Trường 'oaId' là bắt buộc và phải là mã pageId nội bộ kiểu số nguyên 32-bit (<= 2,147,483,647). Không truyền chuỗi noisedId công khai (18 chữ số) vì backend Play Framework sẽ từ chối.\");\n }\n\n // limit: positive integer\n if (!isPositiveInteger(obj.limit)) {\n errors.push(\"Trường 'limit' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n // offset: non-negative integer (optional)\n if (obj.offset !== undefined && obj.offset !== null && !isNonNegativeInteger(obj.offset)) {\n errors.push(\"Trường 'offset' nếu có phải là số nguyên không âm (>= 0).\");\n }\n\n // flowId: positive integer (optional)\n if (obj.flowId !== undefined && obj.flowId !== null && !isPositiveInteger(obj.flowId)) {\n errors.push(\"Trường 'flowId' nếu có phải là số nguyên dương (> 0).\");\n }\n\n const cleanData: Dto.ZaloAdsListFlowsByOfficialAccountRequest = {\n oaId: toPositiveInteger(obj.oaId),\n limit: toPositiveInteger(obj.limit)\n };\n if (obj.offset !== undefined && obj.offset !== null) cleanData.offset = toPositiveInteger(obj.offset);\n if (obj.flowId !== undefined && obj.flowId !== null) cleanData.flowId = toPositiveInteger(obj.flowId);\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined\n };\n}\n\n// ============================================================================\n// 2. createFlow (POST /api/flow/create)\n// ============================================================================\nexport function validateCreateFlowRequest(input: unknown): ValidationResult<Dto.ZaloAdsCreateFlowRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu tạo kịch bản phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n // oaId: 32-bit integer\n if (!is32BitPositiveInteger(obj.oaId)) {\n errors.push(\"Trường 'oaId' là bắt buộc và phải là mã pageId nội bộ kiểu số nguyên 32-bit (<= 2,147,483,647).\");\n }\n\n // name: string, 1 <= length <= 50\n if (typeof obj.name !== \"string\" || obj.name.trim() === \"\") {\n errors.push(\"Trường 'name' (tên kịch bản) là bắt buộc và không được để trống.\");\n } else if (obj.name.trim().length > 50) {\n errors.push(`Tên kịch bản không được vượt quá 50 ký tự (hiện có ${obj.name.trim().length} ký tự).`);\n }\n\n // messages: exactly 1 message\n const cleanMessages = validateFlowMessages(obj.messages, errors);\n\n const cleanData: Dto.ZaloAdsCreateFlowRequest = {\n oaId: toPositiveInteger(obj.oaId),\n id: null,\n name: String(obj.name ?? \"\").trim(),\n messages: cleanMessages\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined\n };\n}\n\n// ============================================================================\n// 3. updateFlow (POST /api/flow/update)\n// ============================================================================\nexport function validateUpdateFlowRequest(input: unknown): ValidationResult<Dto.ZaloAdsUpdateFlowRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu cập nhật kịch bản phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n // id: positive integer\n if (!isPositiveInteger(obj.id)) {\n errors.push(\"Trường 'id' (ID Flow cần cập nhật) là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n // oaId: 32-bit integer\n if (!is32BitPositiveInteger(obj.oaId)) {\n errors.push(\"Trường 'oaId' là bắt buộc và phải là mã pageId nội bộ kiểu số nguyên 32-bit (<= 2,147,483,647).\");\n }\n\n // name: string, 1 <= length <= 50\n if (typeof obj.name !== \"string\" || obj.name.trim() === \"\") {\n errors.push(\"Trường 'name' (tên kịch bản) là bắt buộc và không được để trống.\");\n } else if (obj.name.trim().length > 50) {\n errors.push(`Tên kịch bản không được vượt quá 50 ký tự (hiện có ${obj.name.trim().length} ký tự).`);\n }\n\n // messages: exactly 1 message\n const cleanMessages = validateFlowMessages(obj.messages, errors);\n\n const cleanData: Dto.ZaloAdsUpdateFlowRequest = {\n id: toPositiveInteger(obj.id),\n oaId: toPositiveInteger(obj.oaId),\n name: String(obj.name ?? \"\").trim(),\n messages: cleanMessages\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined\n };\n}\n\n/**\n * Đối tượng gom nhóm các hàm kiểm tra tính hợp lệ dữ liệu cho Message Flows APIs.\n */\nexport const ZaloFlowsValidator = {\n listFlowsByOfficialAccount: validateListFlowsByOfficialAccountRequest,\n createFlow: validateCreateFlowRequest,\n updateFlow: validateUpdateFlowRequest\n} as const;\n\n","/**\n * Dịch vụ Quản lý Kịch bản Tin nhắn OA (Message Flows get/create/update).\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\nimport { ZaloFlowsValidator } from \"../validators/flows.validator\";\n\n\nconst OP_ZaloAdsListFlowsByOfficialAccount: OperationDefinition = {\r\n operationId: \"ZaloAds_listFlowsByOfficialAccount\",\r\n method: \"GET\",\r\n endpoint: \"/api/flow/getByOaId\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [\"oaId\", \"limit\", \"offset\", \"flowId\"],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: []\r\n};\n\nconst OP_ZaloAdsCreateFlow: OperationDefinition = {\r\n operationId: \"ZaloAds_createFlow\",\r\n method: \"POST\",\r\n endpoint: \"/api/flow/create\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"oaId\", \"id\", \"name\", \"messages\"]\r\n};\n\nconst OP_ZaloAdsUpdateFlow: OperationDefinition = {\r\n operationId: \"ZaloAds_updateFlow\",\r\n method: \"POST\",\r\n endpoint: \"/api/flow/update\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"oaId\", \"id\", \"name\", \"messages\"]\r\n};\n\nexport class ZaloFlowsService {\n /**\n * Bộ công cụ kiểm tra tính hợp lệ dữ liệu (Standalone Validators) cho Message Flows APIs.\n * Dùng để validate dữ liệu đầu vào trước khi lưu DB hoặc gọi Zalo Ads.\n */\n public static readonly validator = ZaloFlowsValidator;\n public readonly validator = ZaloFlowsValidator;\n\n public constructor(protected readonly client: ZaloSdkHttpClient) {}\n\n public listFlowsByOfficialAccount(request: Dto.ZaloAdsListFlowsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListFlowsByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloAdsListFlowsByOfficialAccountResponse>(OP_ZaloAdsListFlowsByOfficialAccount, this.client.toTransportInput(OP_ZaloAdsListFlowsByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n\n public createFlow(request: Dto.ZaloAdsCreateFlowRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFlowResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsCreateFlowResponse>(OP_ZaloAdsCreateFlow, this.client.toTransportInput(OP_ZaloAdsCreateFlow, request as unknown as Record<string, unknown>), options);\r\n }\r\n\n public updateFlow(request: Dto.ZaloAdsUpdateFlowRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateFlowResponse> {\r\n return this.client.requestJson<Dto.ZaloAdsUpdateFlowResponse>(OP_ZaloAdsUpdateFlow, this.client.toTransportInput(OP_ZaloAdsUpdateFlow, request as unknown as Record<string, unknown>), options);\r\n }\r\n\n}\n","/**\n * Zalo Ads Media & Assets Service (`https://ads.zalo.me`).\n * Quản lý kho hình ảnh, video, upload CDN, lưu thư viện Media, cắt ảnh (crop)\n * và cung cấp các tiện ích upload+save trọn gói cùng bộ validation độc lập cho backend.\n */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions, FileInput } from \"../types\";\nimport { ZaloSdkError } from \"../types\";\nimport type * as Dto from \"../dtos/media.dto\";\n\nconst OP_ZaloAdsGetApiMediaItems: OperationDefinition = {\n operationId: \"ZaloAds_getApiMediaItems\",\n method: \"GET\",\n endpoint: \"/api/media/items\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [],\n pathFields: [],\n queryFields: [\"endDate\", \"startDate\"],\n headerFields: [],\n cookieFields: [],\n bodyFields: [],\n};\n\nconst OP_ZaloAdsGetApiMemberFiles: OperationDefinition = {\n operationId: \"ZaloAds_getApiMemberFiles\",\n method: \"GET\",\n endpoint: \"/api/member/files\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [],\n};\n\nconst OP_ZaloAdsGetApiFilegroups: OperationDefinition = {\n operationId: \"ZaloAds_getApiFilegroups\",\n method: \"GET\",\n endpoint: \"/api/filegroups\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [],\n};\n\nconst OP_ZaloAdsPostApiMediaSave: OperationDefinition = {\n operationId: \"ZaloAds_postApiMediaSave\",\n method: \"POST\",\n endpoint: \"/api/media/save\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [\"data\"],\n};\n\nconst OP_ZaloAdsPostApiMemberUploadImage: OperationDefinition = {\n operationId: \"ZaloAds_postApiMemberUploadImage\",\n method: \"POST\",\n endpoint: \"/api/member/upload-image\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [\"File\"],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [\"File\"],\n};\n\nconst OP_ZaloAdsUploadVideo: OperationDefinition = {\n operationId: \"ZaloAds_uploadVideo\",\n method: \"POST\",\n endpoint: \"/api/member/upload-video\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [\"File\"],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [\"File\"],\n};\n\nconst OP_ZaloAdsUpdateNewAds: OperationDefinition = {\n operationId: \"ZaloAds_UpdateNewAds\",\n method: \"POST\",\n endpoint: \"/zaapi/UploadCrop\",\n baseUrl: \"https://ads.zalo.me\",\n binaryFields: [\"File\"],\n pathFields: [],\n queryFields: [],\n headerFields: [],\n cookieFields: [],\n bodyFields: [\"File\", \"x\", \"y\", \"width\", \"height\", \"scale\"],\n};\n\n/**\n * Helper trích xuất kích thước từ header binary JPEG (SOF marker)\n */\nfunction extractJpegDimensions(buffer: Uint8Array): { width: number; height: number } | null {\n let i = 2;\n while (i < buffer.length - 8) {\n if (buffer[i] !== 0xff) {\n i++;\n continue;\n }\n const marker = buffer[i + 1];\n if (marker === 0xc0 || marker === 0xc1 || marker === 0xc2) {\n const height = (buffer[i + 5] << 8) | buffer[i + 6];\n const width = (buffer[i + 7] << 8) | buffer[i + 8];\n return { width, height };\n }\n const len = (buffer[i + 2] << 8) | buffer[i + 3];\n i += 2 + len;\n }\n return null;\n}\n\n/**\n * Helper trích xuất kích thước từ chunk IHDR của PNG\n */\nfunction extractPngDimensions(buffer: Uint8Array): { width: number; height: number } | null {\n if (\n buffer.length >= 24 &&\n buffer[0] === 0x89 &&\n buffer[1] === 0x50 &&\n buffer[2] === 0x4e &&\n buffer[3] === 0x47\n ) {\n const width = (buffer[16] << 24) | (buffer[17] << 16) | (buffer[18] << 8) | buffer[19];\n const height = (buffer[20] << 24) | (buffer[21] << 16) | (buffer[22] << 8) | buffer[23];\n return { width, height };\n }\n return null;\n}\n\n/**\n * Kiểm tra đối tượng có phải là Uint8Array hoặc Node.js Buffer hay không (Type Guard an toàn không phụ thuộc @types/node)\n */\nfunction isUint8Array(val: unknown): val is Uint8Array {\n if (val instanceof Uint8Array) {\n return true;\n }\n if (\n typeof val === \"object\" &&\n val !== null &&\n typeof (val as { constructor?: { isBuffer?: (o: unknown) => boolean } }).constructor?.isBuffer === \"function\"\n ) {\n return (val as { constructor: { isBuffer: (o: unknown) => boolean } }).constructor.isBuffer(val);\n }\n return false;\n}\n\n/**\n * Trích xuất tên tệp từ đường dẫn, URL hoặc FileInput\n */\nfunction resolveFileName(input: unknown, defaultPrefix = \"media\"): string {\n if (typeof input === \"string\") {\n const clean = input.split(/[?#]/)[0];\n const match = clean.match(/[^/\\\\]+$/);\n if (match && match[0]) return match[0];\n }\n if (input && typeof input === \"object\") {\n const record = input as Record<string, unknown>;\n if (typeof record.name === \"string\" && record.name) return record.name;\n if (typeof record.originalname === \"string\" && record.originalname) return record.originalname;\n if (typeof record.fileName === \"string\" && record.fileName) return record.fileName;\n }\n return `${defaultPrefix}_${Date.now()}.jpg`;\n}\n\nexport class ZaloMediaService {\n public constructor(private readonly client: ZaloSdkHttpClient) {}\n\n // ==========================================================================\n // 1. RAW API METHODS (Chuẩn theo OpenAPI spec media-and-assets, không validate)\n // ==========================================================================\n\n /**\n * Lấy danh sách ảnh, video trong thư viện Zalo Ads theo khoảng thời gian (`GET /api/media/items`).\n */\n public getApiMediaItems(\n request: Dto.ZaloAdsGetApiMediaItemsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiMediaItemsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiMediaItemsResponse>(\n OP_ZaloAdsGetApiMediaItems,\n this.client.toTransportInput(OP_ZaloAdsGetApiMediaItems, request as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `getApiMediaItems`.\n */\n public listMediaItems(\n request: Dto.ZaloAdsGetApiMediaItemsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiMediaItemsResponse> {\n return this.getApiMediaItems(request, options);\n }\n\n /**\n * Lấy các tệp do thành viên hiện tại quản lý trong tài khoản quảng cáo (`GET /api/member/files`).\n */\n public getApiMemberFiles(\n request: Dto.ZaloAdsGetApiMemberFilesRequest = {},\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiMemberFilesResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiMemberFilesResponse>(\n OP_ZaloAdsGetApiMemberFiles,\n this.client.toTransportInput(OP_ZaloAdsGetApiMemberFiles, request as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `getApiMemberFiles`.\n */\n public listMemberFiles(\n request: Dto.ZaloAdsGetApiMemberFilesRequest = {},\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiMemberFilesResponse> {\n return this.getApiMemberFiles(request, options);\n }\n\n /**\n * Lấy danh sách nhóm tệp trong kho media (`GET /api/filegroups`).\n */\n public getApiFilegroups(\n request: Dto.ZaloAdsGetApiFilegroupsRequest = {},\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiFilegroupsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloAdsGetApiFilegroupsResponse>(\n OP_ZaloAdsGetApiFilegroups,\n this.client.toTransportInput(OP_ZaloAdsGetApiFilegroups, request as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `getApiFilegroups`.\n */\n public listFilegroups(\n request: Dto.ZaloAdsGetApiFilegroupsRequest = {},\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsGetApiFilegroupsResponse> {\n return this.getApiFilegroups(request, options);\n }\n\n /**\n * Lưu tài nguyên media vào thư viện Zalo Ads sau khi đã có URL ảnh/video và metadata (`POST /api/media/save`).\n * Phản hồi trả về `{ code: 0, data: <MediaId> }`.\n */\n public postApiMediaSave(\n request: Dto.ZaloAdsPostApiMediaSaveRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsPostApiMediaSaveResponse> {\n const normalized = {\n ...request,\n data: typeof request.data === \"string\" ? request.data : JSON.stringify(request.data),\n };\n return this.client.requestFormUrlEncoded<Dto.ZaloAdsPostApiMediaSaveResponse>(\n OP_ZaloAdsPostApiMediaSave,\n this.client.toTransportInput(OP_ZaloAdsPostApiMediaSave, normalized as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `postApiMediaSave`.\n */\n public saveMedia(\n request: Dto.ZaloAdsPostApiMediaSaveRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsPostApiMediaSaveResponse> {\n return this.postApiMediaSave(request, options);\n }\n\n /**\n * Tải ảnh lên kho media của tài khoản quảng cáo (`POST /api/member/upload-image`).\n * Sử dụng multipart/form-data với trường `File` (chữ hoa). Trả về URL CDN Adtima.\n */\n public postApiMemberUploadImage(\n request: Dto.ZaloAdsPostApiMemberUploadImageRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsPostApiMemberUploadImageResponse> {\n const file = request.File ?? request.file;\n if (typeof file === \"string\" && !/^(https?:|data:)/i.test(file)) {\n throw new ZaloSdkError(\n \"Đường dẫn tệp cục bộ trên ổ cứng không được hỗ trợ. Vui lòng truyền Buffer/Uint8Array (ví dụ: req.file.buffer từ Multer), Web Blob/File hoặc URL ảnh công khai (http/https).\",\n 400,\n \"postApiMemberUploadImage\",\n null\n );\n }\n const normalized = {\n File: file,\n };\n return this.client.requestMultipart<Dto.ZaloAdsPostApiMemberUploadImageResponse>(\n OP_ZaloAdsPostApiMemberUploadImage,\n this.client.toTransportInput(OP_ZaloAdsPostApiMemberUploadImage, normalized),\n options\n );\n }\n\n /**\n * Alias cho `postApiMemberUploadImage`.\n */\n public uploadImage(\n request: Dto.ZaloAdsPostApiMemberUploadImageRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsPostApiMemberUploadImageResponse> {\n return this.postApiMemberUploadImage(request, options);\n }\n\n /**\n * Tải video lên kho media của tài khoản quảng cáo (`POST /api/member/upload-video`).\n * Định dạng chuẩn .MP4 (H.264), tối đa 150MB. Trả về URL video trên Adtima CDN.\n */\n public uploadVideo(\n request: Dto.ZaloAdsUploadVideoRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsUploadVideoResponse> {\n const file = request.File ?? request.file;\n if (typeof file === \"string\" && !/^(https?:|data:)/i.test(file)) {\n throw new ZaloSdkError(\n \"Đường dẫn tệp cục bộ trên ổ cứng không được hỗ trợ. Vui lòng truyền Buffer/Uint8Array (ví dụ: req.file.buffer), Web Blob/File hoặc URL video công khai (http/https).\",\n 400,\n \"uploadVideo\",\n null\n );\n }\n const normalized = {\n File: file,\n };\n return this.client.requestMultipart<Dto.ZaloAdsUploadVideoResponse>(\n OP_ZaloAdsUploadVideo,\n this.client.toTransportInput(OP_ZaloAdsUploadVideo, normalized),\n options\n );\n }\n\n /**\n * Tải ảnh và thiết lập vùng crop tạo asset dùng cho quảng cáo Zalo Ads (`POST /zaapi/UploadCrop`).\n */\n public updateNewAds(\n request: Dto.ZaloAdsUpdateNewAdsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsUpdateNewAdsResponse> {\n return this.client.requestMultipart<Dto.ZaloAdsUpdateNewAdsResponse>(\n OP_ZaloAdsUpdateNewAds,\n this.client.toTransportInput(OP_ZaloAdsUpdateNewAds, request as Record<string, unknown>),\n options\n );\n }\n\n /**\n * Alias cho `updateNewAds` (`POST /zaapi/UploadCrop`).\n */\n public uploadCrop(\n request: Dto.ZaloAdsUpdateNewAdsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloAdsUpdateNewAdsResponse> {\n return this.updateNewAds(request, options);\n }\n\n // ==========================================================================\n // 2. CONVENIENCE CUSTOM METHODS: UPLOAD + SAVE TRỌN GÓI\n // ==========================================================================\n\n /**\n * Method tiện ích trọn gói: Tự động tải ảnh lên CDN (`/api/member/upload-image`)\n * VÀ lưu vào Thư viện Zalo Ads (`/api/media/save`) trong cùng 1 lời gọi duy nhất.\n * \n * Trả về MediaId, URL CDN và kích thước để gắn ngay vào Creative/Quảng cáo.\n */\n public async uploadAndSaveImage(\n request: Dto.ZaloUploadAndSaveImageRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloUploadAndSaveImageResult> {\n if (!request.file) {\n throw new ZaloSdkError(\n \"ZaloMediaService: `file` là tham số bắt buộc trong uploadAndSaveImage.\",\n 400,\n \"uploadAndSaveImage\",\n null\n );\n }\n\n // Không hỗ trợ đường dẫn tệp cục bộ trên ổ cứng\n if (typeof request.file === \"string\" && !/^(https?:|data:)/i.test(request.file)) {\n throw new ZaloSdkError(\n \"Đường dẫn tệp cục bộ trên ổ cứng không được hỗ trợ. Vui lòng truyền Buffer/Uint8Array (ví dụ: req.file.buffer từ Multer), Web Blob/File hoặc URL ảnh công khai (http/https).\",\n 400,\n \"uploadAndSaveImage\",\n null\n );\n }\n\n // 1. Tự động nhận diện tên file nếu chưa truyền\n const fileName = request.fileName || resolveFileName(request.file, \"image\");\n\n // 2. Tự động đọc kích thước (Width, Height) từ binary Buffer/Uint8Array nếu chưa truyền\n let width = request.width;\n let height = request.height;\n\n if ((!width || !height) && isUint8Array(request.file)) {\n const dims = extractJpegDimensions(request.file) || extractPngDimensions(request.file);\n if (dims) {\n width = width || dims.width;\n height = height || dims.height;\n }\n }\n\n // Fallback kích thước chuẩn nếu không trích xuất được\n const resolvedWidth = width && width > 0 ? width : 1200;\n const resolvedHeight = height && height > 0 ? height : 710;\n\n // 3. BƯỚC 1: Tải ảnh lên CDN\n const uploadRes = await this.postApiMemberUploadImage({ File: request.file }, options);\n if (!uploadRes || uploadRes.code !== 0 || !uploadRes.data) {\n throw new ZaloSdkError(\n uploadRes?.msg || \"Tải ảnh lên Zalo Ads thất bại ở bước upload CDN.\",\n uploadRes?.code || 500,\n \"uploadAndSaveImage_upload\",\n uploadRes\n );\n }\n const cdnUrl = uploadRes.data;\n\n // 4. BƯỚC 2: Lưu vào Thư viện Media\n const mediaType = request.type !== undefined ? request.type : 1; // 1 = Ảnh\n const savePayload: Dto.ZaloAdsMediaSavePayloadDto = {\n Name: fileName,\n Type: mediaType,\n Settings: {\n Url: cdnUrl,\n Width: resolvedWidth,\n Height: resolvedHeight,\n ...(request.thumbUrl ? { ThumbUrl: request.thumbUrl } : {}),\n },\n };\n\n const saveRes = await this.postApiMediaSave({ data: savePayload }, options);\n if (!saveRes || saveRes.code !== 0 || typeof saveRes.data !== \"number\") {\n throw new ZaloSdkError(\n \"Lưu ảnh vào Thư viện Media Zalo Ads thất bại ở bước save.\",\n saveRes?.code || 500,\n \"uploadAndSaveImage_save\",\n saveRes\n );\n }\n\n return {\n code: 0,\n mediaId: saveRes.data,\n cdnUrl,\n name: fileName,\n width: resolvedWidth,\n height: resolvedHeight,\n type: mediaType,\n rawUploadResponse: uploadRes,\n rawSaveResponse: saveRes,\n };\n }\n\n /**\n * Method tiện ích trọn gói cho Video: Tự động tải video lên CDN (`/api/member/upload-video`)\n * VÀ lưu vào Thư viện Zalo Ads (`/api/media/save`) để cấp MediaId.\n */\n public async uploadAndSaveVideo(\n request: Dto.ZaloUploadAndSaveVideoRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloUploadAndSaveVideoResult> {\n if (!request.file) {\n throw new ZaloSdkError(\n \"ZaloMediaService: `file` là tham số bắt buộc trong uploadAndSaveVideo.\",\n 400,\n \"uploadAndSaveVideo\",\n null\n );\n }\n\n if (typeof request.file === \"string\" && !/^(https?:|data:)/i.test(request.file)) {\n throw new ZaloSdkError(\n \"Đường dẫn tệp cục bộ trên ổ cứng không được hỗ trợ. Vui lòng truyền Buffer/Uint8Array, Web Blob/File hoặc URL video công khai (http/https).\",\n 400,\n \"uploadAndSaveVideo\",\n null\n );\n }\n\n const fileName = request.fileName || resolveFileName(request.file, \"video\");\n const width = request.width || 1920;\n const height = request.height || 1080;\n const duration = request.duration || 30;\n\n // 1. BƯỚC 1: Tải video lên CDN\n const uploadRes = await this.uploadVideo({ File: request.file }, options);\n if (!uploadRes || uploadRes.code !== 0 || !uploadRes.data) {\n throw new ZaloSdkError(\n uploadRes?.msg || \"Tải video lên Zalo Ads thất bại ở bước upload CDN.\",\n uploadRes?.code || 500,\n \"uploadAndSaveVideo_upload\",\n uploadRes\n );\n }\n const cdnUrl = uploadRes.data;\n\n // 2. BƯỚC 2: Lưu vào Thư viện Media (Type = 2: Video)\n const savePayload: Dto.ZaloAdsMediaSavePayloadDto = {\n Name: fileName,\n Type: 2, // 2 = Video\n Settings: {\n Url: cdnUrl,\n Width: width,\n Height: height,\n Duration: duration,\n ...(request.thumbUrl ? { ThumbUrl: request.thumbUrl } : {}),\n },\n };\n\n const saveRes = await this.postApiMediaSave({ data: savePayload }, options);\n if (!saveRes || saveRes.code !== 0 || typeof saveRes.data !== \"number\") {\n throw new ZaloSdkError(\n \"Lưu video vào Thư viện Media Zalo Ads thất bại ở bước save.\",\n saveRes?.code || 500,\n \"uploadAndSaveVideo_save\",\n saveRes\n );\n }\n\n return {\n code: 0,\n mediaId: saveRes.data,\n cdnUrl,\n name: fileName,\n width,\n height,\n duration,\n type: 2,\n rawUploadResponse: uploadRes,\n rawSaveResponse: saveRes,\n };\n }\n\n // ==========================================================================\n // 3. STANDALONE VALIDATION METHODS (Cho Backend sử dụng độc lập, không chặn API)\n // ==========================================================================\n\n /**\n * Kiểm tra tính hợp lệ của tệp Ảnh theo quy chuẩn Zalo Ads:\n * - \"No file chosen\": Bắt buộc phải có tệp.\n * - Dung lượng: Tối đa 2MB (2 * 1024 * 1024 bytes).\n * - Kích thước: Tối thiểu 150x150 pixels.\n * - Định dạng: Hỗ trợ .JPG, .JPEG, .PNG.\n * \n * Trả về `{ isValid: boolean, status: 'VALID' | 'INVALID', errors: string[], metadata: {...} }`.\n */\n public validateImage(input: Dto.ValidateImageInput): Dto.MediaValidationResult {\n const errors: string[] = [];\n\n // 1. Phân tích sự tồn tại của file & dung lượng\n let sizeBytes = input.sizeBytes;\n let fileName = input.fileName;\n let format = input.format;\n let width = input.width;\n let height = input.height;\n\n const file = input.file;\n const hasFile = Boolean(\n file !== null &&\n file !== undefined &&\n (typeof file !== \"string\" || file.trim() !== \"\")\n );\n\n if (!hasFile && sizeBytes === undefined) {\n errors.push(\"No file chosen\");\n return {\n isValid: false,\n status: \"INVALID\",\n errors,\n metadata: { fileDetected: false },\n };\n }\n\n // Trích xuất metadata từ file object (multer/buffer) nếu có\n if (file && typeof file === \"object\") {\n const rec = file as Record<string, unknown>;\n if (typeof rec.size === \"number\" && sizeBytes === undefined) {\n sizeBytes = rec.size;\n }\n if (typeof rec.originalname === \"string\" && !fileName) {\n fileName = rec.originalname;\n }\n if (typeof rec.mimetype === \"string\" && !format) {\n format = rec.mimetype;\n }\n if (isUint8Array(rec.buffer)) {\n if (sizeBytes === undefined) sizeBytes = rec.buffer.byteLength;\n const dims = extractJpegDimensions(rec.buffer) || extractPngDimensions(rec.buffer);\n if (dims) {\n width = width || dims.width;\n height = height || dims.height;\n }\n } else if (isUint8Array(file)) {\n if (sizeBytes === undefined) sizeBytes = file.byteLength;\n const dims = extractJpegDimensions(file) || extractPngDimensions(file);\n if (dims) {\n width = width || dims.width;\n height = height || dims.height;\n }\n }\n } else if (typeof file === \"string\" && !fileName) {\n fileName = resolveFileName(file);\n }\n\n // Kiểm tra dung lượng = 0\n if (sizeBytes !== undefined && sizeBytes <= 0) {\n errors.push(\"No file chosen\");\n }\n\n // 2. Kiểm tra dung lượng tối đa 2MB\n const MAX_IMAGE_BYTES = 2 * 1024 * 1024; // 2,097,152 bytes\n if (sizeBytes !== undefined && sizeBytes > MAX_IMAGE_BYTES) {\n const sizeMB = (sizeBytes / (1024 * 1024)).toFixed(2);\n errors.push(`Dung lượng ảnh vượt quá giới hạn tối đa 2MB (dung lượng hiện tại: ${sizeMB}MB).`);\n }\n\n // 3. Kiểm tra kích thước tối thiểu 150x150\n if (width !== undefined && height !== undefined) {\n if (width < 150 || height < 150) {\n errors.push(`Kích thước ảnh tối thiểu 150x150 (kích thước hiện tại: ${width}x${height} pixels).`);\n }\n }\n\n // 4. Kiểm tra định dạng ảnh (.JPG, .JPEG, .PNG)\n const nameToCheck = (fileName || format || \"\").toLowerCase();\n if (nameToCheck) {\n const isAllowedFormat =\n nameToCheck.endsWith(\".jpg\") ||\n nameToCheck.endsWith(\".jpeg\") ||\n nameToCheck.endsWith(\".png\") ||\n nameToCheck.includes(\"image/jpeg\") ||\n nameToCheck.includes(\"image/jpg\") ||\n nameToCheck.includes(\"image/png\");\n\n if (!isAllowedFormat) {\n errors.push(\"Định dạng ảnh không hợp lệ, yêu cầu định dạng .JPG, .JPEG hoặc .PNG.\");\n }\n }\n\n const isValid = errors.length === 0;\n return {\n isValid,\n status: isValid ? \"VALID\" : \"INVALID\",\n errors,\n metadata: {\n fileDetected: true,\n sizeBytes,\n width,\n height,\n format: format || (fileName ? fileName.split(\".\").pop() : undefined),\n },\n };\n }\n\n /**\n * Kiểm tra tính hợp lệ của tệp Video theo quy chuẩn Zalo Ads:\n * - \"No file chosen\": Bắt buộc phải có tệp.\n * - Định dạng: .MP4 H.264.\n * - Dung lượng: Tối đa 150MB (150 * 1024 * 1024 bytes).\n * - Thời lượng: Tối đa 60 giây.\n * - Tỉ lệ khung hình: 16:9, 9:16 hoặc 1:1.\n * \n * Trả về `{ isValid: boolean, status: 'VALID' | 'INVALID', errors: string[], metadata: {...} }`.\n */\n public validateVideo(input: Dto.ValidateVideoInput): Dto.MediaValidationResult {\n const errors: string[] = [];\n\n let sizeBytes = input.sizeBytes;\n let fileName = input.fileName;\n let format = input.format;\n const durationSeconds = input.durationSeconds;\n const width = input.width;\n const height = input.height;\n\n const file = input.file;\n const hasFile = Boolean(\n file !== null &&\n file !== undefined &&\n (typeof file !== \"string\" || file.trim() !== \"\")\n );\n\n if (!hasFile && sizeBytes === undefined) {\n errors.push(\"No file chosen\");\n return {\n isValid: false,\n status: \"INVALID\",\n errors,\n metadata: { fileDetected: false },\n };\n }\n\n if (file && typeof file === \"object\") {\n const rec = file as Record<string, unknown>;\n if (typeof rec.size === \"number\" && sizeBytes === undefined) {\n sizeBytes = rec.size;\n }\n if (typeof rec.originalname === \"string\" && !fileName) {\n fileName = rec.originalname;\n }\n if (typeof rec.mimetype === \"string\" && !format) {\n format = rec.mimetype;\n }\n if (isUint8Array(rec.buffer)) {\n if (sizeBytes === undefined) sizeBytes = rec.buffer.byteLength;\n } else if (isUint8Array(file)) {\n if (sizeBytes === undefined) sizeBytes = file.byteLength;\n }\n } else if (typeof file === \"string\" && !fileName) {\n fileName = resolveFileName(file);\n }\n\n // Kiểm tra dung lượng = 0\n if (sizeBytes !== undefined && sizeBytes <= 0) {\n errors.push(\"No file chosen\");\n }\n\n // 1. Định dạng: .MP4 H.264\n const nameToCheck = (fileName || format || \"\").toLowerCase();\n if (nameToCheck) {\n const isMp4 =\n nameToCheck.endsWith(\".mp4\") ||\n nameToCheck.includes(\"video/mp4\") ||\n nameToCheck.includes(\"h264\");\n\n if (!isMp4) {\n errors.push(\"Định dạng video không hợp lệ, yêu cầu định dạng .MP4 (H.264).\");\n }\n }\n\n // 2. Dung lượng: Tối đa 150MB\n const MAX_VIDEO_BYTES = 150 * 1024 * 1024; // 157,286,400 bytes\n if (sizeBytes !== undefined && sizeBytes > MAX_VIDEO_BYTES) {\n const sizeMB = (sizeBytes / (1024 * 1024)).toFixed(2);\n errors.push(`Dung lượng video vượt quá giới hạn tối đa 150MB (dung lượng hiện tại: ${sizeMB}MB).`);\n }\n\n // 3. Thời lượng tối đa 60 giây\n if (durationSeconds !== undefined && durationSeconds > 60) {\n errors.push(`Thời lượng video vượt quá giới hạn tối đa 60 giây (thời lượng hiện tại: ${durationSeconds} giây).`);\n }\n\n // 4. Tỉ lệ khung hình: 16:9, 9:16 hoặc 1:1\n let ratioLabel: string | undefined;\n if (width !== undefined && height !== undefined && width > 0 && height > 0) {\n const ratio = width / height;\n const is16_9 = Math.abs(ratio - 16 / 9) <= 0.06; // ~1.78\n const is9_16 = Math.abs(ratio - 9 / 16) <= 0.04; // ~0.56\n const is1_1 = Math.abs(ratio - 1.0) <= 0.05; // ~1.00\n\n if (is16_9) ratioLabel = \"16:9\";\n else if (is9_16) ratioLabel = \"9:16\";\n else if (is1_1) ratioLabel = \"1:1\";\n else {\n ratioLabel = `${width}:${height} (~${ratio.toFixed(2)})`;\n errors.push(`Tỉ lệ khung hình video phải là 16:9, 9:16 hoặc 1:1 (tỉ lệ hiện tại: ${width}x${height} - ${ratioLabel}).`);\n }\n }\n\n const isValid = errors.length === 0;\n return {\n isValid,\n status: isValid ? \"VALID\" : \"INVALID\",\n errors,\n metadata: {\n fileDetected: true,\n sizeBytes,\n width,\n height,\n durationSeconds,\n format: format || (fileName ? fileName.split(\".\").pop() : undefined),\n aspectRatio: ratioLabel,\n },\n };\n }\n}\n","/**\n * Zalo Ads API facade service.\n * Kế thừa toàn bộ API Chiến dịch & Quảng cáo từ `ZaloCampaignsService`,\n * đồng thời tích hợp và điều phối các module chuyên biệt:\n * - `account`: Quản lý tài khoản, phân quyền BA, thanh toán (`ZaloAccountService`)\n * - `audiences`: Nhóm đối tượng tùy chỉnh, Lookalike, Event/Lead Audiences (`ZaloAudiencesService`)\n * - `reports`: Báo cáo chiến dịch, quảng cáo, nhân khẩu học, báo cáo tùy chỉnh (`ZaloReportsService`)\n * - `conversions`: Sự kiện chuyển đổi, Zalo Pixel (`ZaloConversionsService`)\n * - `automatedRules`: Quy tắc tự động (`ZaloAutomatedRulesService`)\n * - `flows`: Kịch bản tin nhắn OA (`ZaloFlowsService`)\n * - `media`: Thư viện tài nguyên & tải lên ảnh/video (`ZaloMediaService`)\n */\nimport { ZaloSdkHttpClient } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/ads.dto\";\nimport type {\n ZaloUploadAndSaveImageRequest,\n ZaloUploadAndSaveImageResult,\n ZaloUploadAndSaveVideoRequest,\n ZaloUploadAndSaveVideoResult,\n MediaValidationResult,\n ValidateImageInput,\n ValidateVideoInput,\n} from \"../dtos/media.dto\";\n\nimport { ZaloCampaignsService } from \"./campaigns.service\";\nimport { ZaloAccountService } from \"./account.service\";\nimport { ZaloAudiencesService } from \"./audiences.service\";\nimport { ZaloReportsService } from \"./reports.service\";\nimport { ZaloConversionsService } from \"./conversions.service\";\nimport { ZaloAutomatedRulesService } from \"./automated-rules.service\";\nimport { ZaloFlowsService } from \"./flows.service\";\nimport { ZaloMediaService } from \"./media.service\";\n\nexport class ZaloAdsService extends ZaloCampaignsService {\n public readonly account: ZaloAccountService;\n public readonly audiences: ZaloAudiencesService;\n public readonly targeting: ZaloAudiencesService;\n public readonly reports: ZaloReportsService;\n public readonly conversions: ZaloConversionsService;\n public readonly pixel: ZaloConversionsService;\n public readonly automatedRules: ZaloAutomatedRulesService;\n public readonly rules: ZaloAutomatedRulesService;\n public readonly flows: ZaloFlowsService;\n public readonly media: ZaloMediaService;\n public readonly campaigns: ZaloCampaignsService;\n\n public constructor(client: ZaloSdkHttpClient) {\n super(client);\n this.account = new ZaloAccountService(client);\n this.audiences = new ZaloAudiencesService(client);\n this.targeting = this.audiences;\n this.reports = new ZaloReportsService(client);\n this.conversions = new ZaloConversionsService(client);\n this.pixel = this.conversions;\n this.automatedRules = new ZaloAutomatedRulesService(client);\n this.rules = this.automatedRules;\n this.flows = new ZaloFlowsService(client);\n this.media = new ZaloMediaService(client);\n this.campaigns = this;\n }\n\n // =========================================================================\n // Delegations -> this.account\n // =========================================================================\n\n public getApiWhoami(request: Dto.ZaloAdsGetApiWhoamiRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiWhoamiResponse> {\n return (this.account.getApiWhoami as any)(request, options);\n }\n\n public getApiPaymentTransactionHistory(request: Dto.ZaloAdsGetApiPaymentTransactionHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiPaymentTransactionHistoryResponse> {\n return (this.account.getApiPaymentTransactionHistory as any)(request, options);\n }\n\n public getApiBaAccountAllaccessors(request: Dto.ZaloAdsGetApiBaAccountAllaccessorsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAccountAllaccessorsResponse> {\n return (this.account.getApiBaAccountAllaccessors as any)(request, options);\n }\n\n public getApiBaAccountAllgrantedmembers(request: Dto.ZaloAdsGetApiBaAccountAllgrantedmembersRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAccountAllgrantedmembersResponse> {\n return (this.account.getApiBaAccountAllgrantedmembers as any)(request, options);\n }\n\n public listAgencyCustomersWithBudget(request: Dto.ZaloAdsListAgencyCustomersWithBudgetRequest = { limit: 15, offset: 0, joinDateAsc: true }, options?: RequestOptions): Promise<Dto.ZaloAdsListAgencyCustomersWithBudgetResponse> {\n return (this.account.listAgencyCustomersWithBudget as any)(request, options);\n }\n\n public getApiBaAgencyEmployees(request: Dto.ZaloAdsGetApiBaAgencyEmployeesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiBaAgencyEmployeesResponse> {\n return (this.account.getApiBaAgencyEmployees as any)(request, options);\n }\n\n public getBaAgencyEmployees(...args: Parameters<this[\"getApiBaAgencyEmployees\"]>): ReturnType<this[\"getApiBaAgencyEmployees\"]> {\n return (this.account.getBaAgencyEmployees as any)(...args);\n }\n\n public getApiNotifiesHeader(request: Dto.ZaloAdsGetApiNotifiesHeaderRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiNotifiesHeaderResponse> {\n return (this.account.getApiNotifiesHeader as any)(request, options);\n }\n\n public getApiLpNews(request: Dto.ZaloAdsGetApiLpNewsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiLpNewsResponse> {\n return (this.account.getApiLpNews as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.audiences\n // =========================================================================\n\n public postApiAdEstimateaudience(request: Dto.ZaloAdsPostApiAdEstimateaudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiAdEstimateaudienceResponse> {\n return (this.audiences.postApiAdEstimateaudience as any)(request, options);\n }\n\n public getApiAdGetlistadadvancetargeting(request: Dto.ZaloAdsGetApiAdGetlistadadvancetargetingRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiAdGetlistadadvancetargetingResponse> {\n return (this.audiences.getApiAdGetlistadadvancetargeting as any)(request, options);\n }\n\n public getApiCustomAudienceAll(request: Dto.ZaloAdsGetApiCustomAudienceAllRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiCustomAudienceAllResponse> {\n return (this.audiences.getApiCustomAudienceAll as any)(request, options);\n }\n\n public createCustomAudience(request: Dto.ZaloAdsCreateCustomAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCustomAudienceResponse> {\n return (this.audiences.createCustomAudience as any)(request, options);\n }\n\n public deleteCustomAudience(request: Dto.ZaloAdsDeleteCustomAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCustomAudienceResponse> {\n return (this.audiences.deleteCustomAudience as any)(request, options);\n }\n\n public uploadCustomAudiencePhoneList(request: Dto.ZaloAdsUploadCustomAudiencePhoneListRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUploadCustomAudiencePhoneListResponse> {\n return (this.audiences.uploadCustomAudiencePhoneList as any)(request, options);\n }\n\n /** Tạo mới 'Nhóm đối tượng đã lưu' (`caType = 1` - `DEFAULT`) trên Zalo Ads (`POST /api/ad/audience`). */\r\n public createSavedAudience(request: Dto.ZaloAdsCreateSavedAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateSavedAudienceResponse> {\n return (this.audiences.createSavedAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ danh sách Số điện thoại (`caType = 3` - `PHONE_LIST`). */\r\n public createPhoneAudience(request: Dto.ZaloAdsCreatePhoneAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreatePhoneAudienceResponse> {\n return (this.audiences.createPhoneAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng tương tự Lookalike (`caType = 6` - `LOOKALIKE`). */\r\n public createLookalikeAudience(request: Dto.ZaloAdsCreateLookalikeAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateLookalikeAudienceResponse> {\n return (this.audiences.createLookalikeAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Zalo Form (`caType = 12` - `FORM_EVENT_AUDIENCE`). */\r\n public createFormEventAudience(request: Dto.ZaloAdsCreateFormEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormEventAudienceResponse> {\n return (this.audiences.createFormEventAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn OA (`caType = 11` - `MESSAGE_AUDIENCE`). */\r\n public createMessageOaEventAudience(request: Dto.ZaloAdsCreateMessageOaEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageOaEventAudienceResponse> {\n return (this.audiences.createMessageOaEventAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng phát sinh sự kiện trên Kịch bản Tin nhắn cá nhân (`caType = 14` - `MESSAGE_PERSONAL_EVENT_AUDIENCE`). */\r\n public createMessagePersonalEventAudience(request: Dto.ZaloAdsCreateMessagePersonalEventAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessagePersonalEventAudienceResponse> {\n return (this.audiences.createMessagePersonalEventAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Zalo Form (`caType = 10` - `FORM_AUDIENCE`). */\r\n public createFormLeadAudience(request: Dto.ZaloAdsCreateFormLeadAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFormLeadAudienceResponse> {\n return (this.audiences.createFormLeadAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Commerce Form (`caType = 15` - `COMMERCE_FORM_AUDIENCE`). */\r\n public createCommerceFormAudience(request: Dto.ZaloAdsCreateCommerceFormAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateCommerceFormAudienceResponse> {\n return (this.audiences.createCommerceFormAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Trung tâm Lead - Kịch bản Tin nhắn OA (`caType = 13` - `MESSAGE_OA_AUDIENCE`). */\r\n public createMessageOaLeadAudience(request: Dto.ZaloAdsCreateMessageOaLeadAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateMessageOaLeadAudienceResponse> {\n return (this.audiences.createMessageOaLeadAudience as any)(request, options);\n }\n\n /** Tạo mới Nhóm đối tượng từ Dữ liệu chuyển đổi Lead Signal (`caType = 16` - `LEAD_SIGNAL_AUDIENCE`). */\r\n public createLeadSignalAudience(request: Dto.ZaloAdsCreateLeadSignalAudienceRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateLeadSignalAudienceResponse> {\n return (this.audiences.createLeadSignalAudience as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.reports\n // =========================================================================\n\n public getReportapiV2Ads(request: Dto.ZaloAdsGetReportapiV2AdsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2AdsResponse> {\n return (this.reports.getReportapiV2Ads as any)(request, options);\n }\n\n public getReportapiV2Campaigns(request: Dto.ZaloAdsGetReportapiV2CampaignsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2CampaignsResponse> {\n return (this.reports.getReportapiV2Campaigns as any)(request, options);\n }\n\n public getReportapiV2UniqueUser(request: Dto.ZaloAdsGetReportapiV2UniqueUserRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV2UniqueUserResponse> {\n return (this.reports.getReportapiV2UniqueUser as any)(request, options);\n }\n\n public getReportapiV3Campaigns(request: Dto.ZaloAdsGetReportapiV3CampaignsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportapiV3CampaignsResponse> {\n return (this.reports.getReportapiV3Campaigns as any)(request, options);\n }\n\n public getReportOverview(request: Dto.ZaloAdsGetReportOverviewRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetReportOverviewResponse> {\n return (this.reports.getReportOverview as any)(request, options);\n }\n\n public getDemographicsReport(request: Dto.ZaloAdsGetDemographicsReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetDemographicsReportResponse> {\n return (this.reports.getDemographicsReport as any)(request, options);\n }\n\n public getZaapiCampaignReportcampaign(request: Dto.ZaloAdsGetZaapiCampaignReportcampaignRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetZaapiCampaignReportcampaignResponse> {\n return (this.reports.getZaapiCampaignReportcampaign as any)(request, options);\n }\n\n public listCustomReports(request: Dto.ZaloAdsListCustomReportsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListCustomReportsResponse> {\n return (this.reports.listCustomReports as any)(request, options);\n }\n\n public upsertCustomReport(request: Dto.ZaloAdsUpsertCustomReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpsertCustomReportResponse> {\n return (this.reports.upsertCustomReport as any)(request, options);\n }\n\n public deleteCustomReport(request: Dto.ZaloAdsDeleteCustomReportRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteCustomReportResponse> {\n return (this.reports.deleteCustomReport as any)(request, options);\n }\n\n public listReportFilters(request: Dto.ZaloAdsListReportFiltersRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListReportFiltersResponse> {\n return (this.reports.listReportFilters as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.conversions\n // =========================================================================\n\n public createConversion(request: Dto.ZaloAdsCreateConversionRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateConversionResponse> {\n return (this.conversions.createConversion as any)(request, options);\n }\n\n public deleteConversion(request: Dto.ZaloAdsDeleteConversionRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteConversionResponse> {\n return (this.conversions.deleteConversion as any)(request, options);\n }\n\n public getApiConversionAll(request: Dto.ZaloAdsGetApiConversionAllRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiConversionAllResponse> {\n return (this.conversions.getApiConversionAll as any)(request, options);\n }\n\n public getApiConversionStandardEvents(request: Dto.ZaloAdsGetApiConversionStandardEventsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiConversionStandardEventsResponse> {\n return (this.conversions.getApiConversionStandardEvents as any)(request, options);\n }\n\n public listPersonalPixelLabels(request: Dto.ZaloAdsListPersonalPixelLabelsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListPersonalPixelLabelsResponse> {\n return (this.conversions.listPersonalPixelLabels as any)(request, options);\n }\n\n /** Lấy danh sách tài khoản Zalo Official Account (OA) có dữ liệu chuyển đổi (Lead Signal) (`GET /api/ad/audience/leadSignal/oas`). */\r\n public listLeadSignalOas(options?: RequestOptions): Promise<Dto.ZaloAdsListLeadSignalOasResponse> {\n return (this.conversions.listLeadSignalOas as any)(options);\n }\n\n /** Lấy danh sách rút gọn gồm ID và tên của toàn bộ các sự kiện chuyển đổi (Conversion) đã tạo trên tài khoản quảng cáo Zalo Ads (`GET /api/conversion/names`). */\r\n public listConversionNames(request: Dto.ZaloAdsListConversionNamesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListConversionNamesResponse> {\n return (this.conversions.listConversionNames as any)(request, options);\n }\n\n /** Alias cho `listConversionNames` (`GET /api/conversion/names`). */\r\n public getApiConversionNames(request: Dto.ZaloAdsListConversionNamesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListConversionNamesResponse> {\n return (this.conversions.getApiConversionNames as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.automatedRules\r\n // =========================================================================\r\n\r\n public listAutomatedRules(request: Dto.ZaloAdsListAutomatedRulesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsListAutomatedRulesResponse> {\r\n return (this.automatedRules.listAutomatedRules as any)(request, options);\r\n }\r\n\r\n public getAutomatedRuleDetail(request: Dto.ZaloAdsGetAutomatedRuleDetailRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAutomatedRuleDetailResponse> {\r\n return (this.automatedRules.getAutomatedRuleDetail as any)(request, options);\r\n }\r\n\r\n public createAutomatedRule(request: Dto.ZaloAdsCreateAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateAutomatedRuleResponse> {\n return (this.automatedRules.createAutomatedRule as any)(request, options);\n }\n\n public updateAutomatedRule(request: Dto.ZaloAdsUpdateAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateAutomatedRuleResponse> {\n return (this.automatedRules.updateAutomatedRule as any)(request, options);\n }\n\n public changeAutomatedRuleStatus(request: Dto.ZaloAdsChangeAutomatedRuleStatusRequest, options?: RequestOptions): Promise<Dto.ZaloAdsChangeAutomatedRuleStatusResponse> {\n return (this.automatedRules.changeAutomatedRuleStatus as any)(request, options);\n }\n\n public getAutomatedRuleHistory(request: Dto.ZaloAdsGetAutomatedRuleHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetAutomatedRuleHistoryResponse> {\n return (this.automatedRules.getAutomatedRuleHistory as any)(request, options);\n }\n\n public deleteAutomatedRule(request: Dto.ZaloAdsDeleteAutomatedRuleRequest, options?: RequestOptions): Promise<Dto.ZaloAdsDeleteAutomatedRuleResponse> {\n return (this.automatedRules.deleteAutomatedRule as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.flows\n // =========================================================================\n\n public listFlowsByOfficialAccount(request: Dto.ZaloAdsListFlowsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloAdsListFlowsByOfficialAccountResponse> {\n return (this.flows.listFlowsByOfficialAccount as any)(request, options);\n }\n\n public createFlow(request: Dto.ZaloAdsCreateFlowRequest, options?: RequestOptions): Promise<Dto.ZaloAdsCreateFlowResponse> {\n return (this.flows.createFlow as any)(request, options);\n }\n\n public updateFlow(request: Dto.ZaloAdsUpdateFlowRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUpdateFlowResponse> {\n return (this.flows.updateFlow as any)(request, options);\n }\n\n // =========================================================================\n // Delegations -> this.media\n // =========================================================================\n\n public getApiFilegroups(request: Dto.ZaloAdsGetApiFilegroupsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiFilegroupsResponse> {\n return (this.media.getApiFilegroups as any)(request, options);\n }\n\n public getApiMediaItems(request: Dto.ZaloAdsGetApiMediaItemsRequest, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiMediaItemsResponse> {\n return (this.media.getApiMediaItems as any)(request, options);\n }\n\n public getApiMemberFiles(request: Dto.ZaloAdsGetApiMemberFilesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloAdsGetApiMemberFilesResponse> {\n return (this.media.getApiMemberFiles as any)(request, options);\n }\n\n public postApiMediaSave(request: Dto.ZaloAdsPostApiMediaSaveRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiMediaSaveResponse> {\n return (this.media.postApiMediaSave as any)(request, options);\n }\n\n public postApiMemberUploadImage(request: Dto.ZaloAdsPostApiMemberUploadImageRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiMemberUploadImageResponse> {\n return (this.media.postApiMemberUploadImage as any)(request, options);\n }\n\n /** Alias tiện lợi cho `postApiMemberUploadImage` (`POST /api/member/upload-image`). */\r\n public uploadImage(request: Dto.ZaloAdsPostApiMemberUploadImageRequest, options?: RequestOptions): Promise<Dto.ZaloAdsPostApiMemberUploadImageResponse> {\n return (this.media.uploadImage as any)(request, options);\n }\n\n public uploadVideo(request: Dto.ZaloAdsUploadVideoRequest, options?: RequestOptions): Promise<Dto.ZaloAdsUploadVideoResponse> {\n return (this.media.uploadVideo as any)(request, options);\n }\n\n /**\r\n * Kiểm tra tính hợp lệ của tệp Ảnh theo quy chuẩn Zalo Ads (độc lập cho backend).\r\n * Tiêu chí: Có file, Dung lượng tối đa 2MB, Kích thước tối thiểu 150x150, Định dạng JPG/PNG.\r\n */\r\n public validateImage(input: ValidateImageInput): MediaValidationResult {\n return (this.media.validateImage as any)(input);\n }\n\n /**\r\n * Kiểm tra tính hợp lệ của tệp Video theo quy chuẩn Zalo Ads (độc lập cho backend).\r\n * Tiêu chí: Có file, Định dạng .MP4 H.264, Dung lượng tối đa 150MB, Thời lượng tối đa 60s, Tỉ lệ 16:9, 9:16 hoặc 1:1.\r\n */\r\n public validateVideo(input: ValidateVideoInput): MediaValidationResult {\n return (this.media.validateVideo as any)(input);\n }\n}\n","/** Zalo Chat Widget API service. Each API explicitly selects its own request transport. */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/chat-widget.dto\";\r\n\r\nconst OP_ZaloChatWidgetGetChatWidgetLoginConfig: OperationDefinition = {\r\n \"operationId\": \"ZaloChatWidget_getChatWidgetLoginConfig\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/login-tab\",\r\n \"baseUrl\": \"https://widget.chat.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nexport class ZaloChatWidgetService {\r\n public constructor(private readonly client: ZaloSdkHttpClient) {}\r\n public getChatWidgetLoginConfig(request: Dto.ZaloChatWidgetGetChatWidgetLoginConfigRequest, options?: RequestOptions): Promise<Dto.ZaloChatWidgetGetChatWidgetLoginConfigResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloChatWidgetGetChatWidgetLoginConfigResponse>(OP_ZaloChatWidgetGetChatWidgetLoginConfig, this.client.toTransportInput(OP_ZaloChatWidgetGetChatWidgetLoginConfig, request as Record<string, unknown>), options);\r\n }\r\n /** Alias theo tên tool chuẩn `zalo_chat_widget_get_login_config` trong Project Schema Zalo ADS. */\r\n public getLoginConfig(request: Dto.ZaloChatWidgetGetLoginConfigRequest, options?: RequestOptions): Promise<Dto.ZaloChatWidgetGetLoginConfigResponse> {\r\n return this.getChatWidgetLoginConfig(request, options);\r\n }\r\n}\r\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Zalo Forms & Leads:\n * 1. createForm (POST https://ads.zalo.me/api/form/create)\n * 2. listFormsByOfficialAccount (GET https://ads.zalo.me/api/form/getByOaId)\n * 3. listFormLeads (GET https://form.ads.zalo.me/client/manage/api/manageForm/getFormLeads)\n * 4. listConversationLeads (GET https://form.ads.zalo.me/client/manage/api/manageConversation/getConversationLeads)\n * 5. leadNotification (POST enable/disable/updateInterval)\n *\n * Tích hợp toàn bộ giới hạn độ dài ký tự và quy tắc nghiệp vụ trích xuất từ DOM Angular thực tế.\n */\n\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\nexport interface ZaloFormQuestionAnswerInput {\n type: number; // 7 = Họ tên, 13 = SĐT chuẩn, 2 = SĐT phụ\n placeHolder?: string;\n value?: string | null;\n priority?: number;\n}\n\nexport interface ZaloFormQuestionInput {\n title: string;\n type?: number; // 1 = Chuẩn\n isRequired?: boolean;\n editDisabled?: boolean;\n priority?: number;\n answers: ZaloFormQuestionAnswerInput[];\n}\n\nexport interface ZaloFormSectionInput {\n type: number; // 0 = tổng quan; 1 = chi tiết; 2 = bảng giá; 3 = ưu điểm; 4 = ưu đãi\n title?: string;\n disable?: boolean;\n expand?: boolean;\n content?: {\n title?: string;\n description?: string;\n table?: Array<{ key: string; value: string }>;\n images?: Array<{ url: string; title?: string; caption?: string }>;\n videos?: unknown[];\n };\n}\n\nexport interface ZaloCreateFormCleanPayload {\n oaId: string;\n title: string;\n formName: string;\n description?: string;\n coverPhoto: string;\n submitTitle: string;\n thanks: string;\n gotoActionType: number;\n gotoText: string;\n website?: string;\n reviewSubmit: boolean;\n questions: ZaloFormQuestionInput[];\n sections?: ZaloFormSectionInput[];\n useCustomConsent?: boolean;\n consentName?: string;\n consentUrl?: string;\n [key: string]: unknown;\n}\n\nexport interface ZaloCreateFormRequestInput {\n data?: string | ZaloCreateFormCleanPayload;\n [key: string]: unknown;\n}\n\nfunction isValidUrl(val: unknown): boolean {\n if (typeof val !== \"string\" || val.trim() === \"\") return false;\n try {\n const url = new URL(val);\n return url.protocol === \"http:\" || url.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\n/**\n * Kiểm tra tính hợp lệ dữ liệu khi tạo mới Zalo Form (POST /api/form/create)\n */\nexport function validateCreateFormRequest(input: unknown): ValidationResult<ZaloCreateFormCleanPayload> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu tạo Form phải là một object.\"],\n data: undefined\n };\n }\n\n // Hỗ trợ cả { data: JSON.stringify(...) } lẫn payload trực tiếp\n let raw: Record<string, unknown> = input as Record<string, unknown>;\n if (typeof (input as any).data === \"string\") {\n try {\n raw = JSON.parse((input as any).data);\n } catch {\n errors.push(\"Trường 'data' không phải là chuỗi JSON hợp lệ.\");\n return { isValid: false, errors, data: undefined };\n }\n } else if (typeof (input as any).data === \"object\" && (input as any).data !== null) {\n raw = (input as any).data;\n }\n\n // 1. Kiểm tra oaId (Bắt buộc là chuỗi số pageId nội bộ)\n const oaIdRaw = raw.oaId;\n let cleanOaId = \"\";\n if (typeof oaIdRaw === \"string\" && /^[0-9]+$/.test(oaIdRaw.trim())) {\n cleanOaId = oaIdRaw.trim();\n } else if (typeof oaIdRaw === \"number\" && Number.isInteger(oaIdRaw) && oaIdRaw > 0) {\n cleanOaId = String(oaIdRaw);\n } else {\n errors.push(\"Trường 'oaId' bắt buộc phải là chuỗi số nguyên dương đại diện cho pageId nội bộ của OA (ví dụ: '429753475').\");\n }\n\n // 2. Kiểm tra title (2 - 40 ký tự)\n const title = typeof raw.title === \"string\" ? raw.title.trim() : \"\";\n if (!title) {\n errors.push(\"Trường 'title' (tiêu đề form) là bắt buộc.\");\n } else if (title.length < 2 || title.length > 40) {\n errors.push(`Trường 'title' phải có độ dài từ 2 đến 40 ký tự (hiện tại: ${title.length} ký tự).`);\n }\n\n // 3. Kiểm tra formName (2 - 100 ký tự)\n const formName = typeof raw.formName === \"string\" ? raw.formName.trim() : \"\";\n if (!formName) {\n errors.push(\"Trường 'formName' (tên quản trị form) là bắt buộc.\");\n } else if (formName.length < 2 || formName.length > 100) {\n errors.push(`Trường 'formName' phải có độ dài từ 2 đến 100 ký tự (hiện tại: ${formName.length} ký tự).`);\n }\n\n // 4. Kiểm tra description (tối đa 600 ký tự)\n let cleanDescription: string | undefined = undefined;\n if (raw.description !== undefined && raw.description !== null) {\n const desc = String(raw.description).trim();\n if (desc.length > 600) {\n errors.push(`Trường 'description' không được vượt quá 600 ký tự (hiện tại: ${desc.length} ký tự).`);\n } else {\n cleanDescription = desc;\n }\n }\n\n // 5. Kiểm tra coverPhoto (URL hợp lệ)\n const coverPhoto = typeof raw.coverPhoto === \"string\" ? raw.coverPhoto.trim() : \"\";\n if (!coverPhoto) {\n errors.push(\"Trường 'coverPhoto' (ảnh bìa form) là bắt buộc.\");\n } else if (!isValidUrl(coverPhoto)) {\n errors.push(`Trường 'coverPhoto' phải là URL hợp lệ (http:// hoặc https://).`);\n }\n\n // 6. Kiểm tra submitTitle (tối đa 90 ký tự) & thanks (tối đa 255 ký tự)\n const submitTitle = typeof raw.submitTitle === \"string\" && raw.submitTitle.trim() !== \"\"\n ? raw.submitTitle.trim()\n : \"Gửi thông tin thành công\";\n if (submitTitle.length > 90) {\n errors.push(`Trường 'submitTitle' không được vượt quá 90 ký tự (hiện tại: ${submitTitle.length} ký tự).`);\n }\n\n const thanks = typeof raw.thanks === \"string\" && raw.thanks.trim() !== \"\"\n ? raw.thanks.trim()\n : \"Cảm ơn bạn đã gửi thông tin. Chúng tôi sẽ liên hệ trong thời gian sớm nhất.\";\n if (thanks.length > 255) {\n errors.push(`Trường 'thanks' không được vượt quá 255 ký tự (hiện tại: ${thanks.length} ký tự).`);\n }\n\n // 7. Kiểm tra gotoActionType (0 hoặc 1) & website\n const gotoActionType = raw.gotoActionType === 0 ? 0 : 1;\n const gotoText = typeof raw.gotoText === \"string\" && raw.gotoText.trim() !== \"\"\n ? raw.gotoText.trim()\n : (gotoActionType === 1 ? \"Xem trang Web\" : \"Đóng lại\");\n\n let cleanWebsite: string | undefined = undefined;\n if (gotoActionType === 1) {\n if (!raw.website || !isValidUrl(raw.website)) {\n errors.push(\"Khi 'gotoActionType' = 1 (mở website), trường 'website' là bắt buộc và phải là URL hợp lệ.\");\n } else {\n cleanWebsite = String(raw.website).trim();\n }\n }\n\n // 8. Kiểm tra consent (Điều khoản & chính sách)\n const useCustomConsent = Boolean(raw.useCustomConsent);\n let cleanConsentName: string | undefined = undefined;\n let cleanConsentUrl: string | undefined = undefined;\n if (useCustomConsent) {\n const cName = typeof raw.consentName === \"string\" ? raw.consentName.trim() : \"\";\n if (!cName) {\n errors.push(\"Khi 'useCustomConsent' = true, trường 'consentName' (tiêu đề điều khoản) là bắt buộc.\");\n } else if (cName.length > 255) {\n errors.push(`Trường 'consentName' không được vượt quá 255 ký tự (hiện tại: ${cName.length} ký tự).`);\n } else {\n cleanConsentName = cName;\n }\n\n if (!raw.consentUrl || !isValidUrl(raw.consentUrl)) {\n errors.push(\"Khi 'useCustomConsent' = true, trường 'consentUrl' phải là URL hợp lệ chứa chính sách bảo mật.\");\n } else {\n cleanConsentUrl = String(raw.consentUrl).trim();\n }\n }\n\n // 9. Kiểm tra câu hỏi (questions) & Quy tắc SĐT\n if (!Array.isArray(raw.questions) || raw.questions.length === 0) {\n errors.push(\"Biểu mẫu bắt buộc phải có ít nhất 1 câu hỏi trong mảng 'questions'.\");\n }\n\n const cleanQuestions: ZaloFormQuestionInput[] = [];\n let hasPhonePrimary = false;\n let hasPhoneSecondary = false;\n\n if (Array.isArray(raw.questions)) {\n raw.questions.forEach((q: any, idx: number) => {\n const qPrefix = `Câu hỏi [${idx}]`;\n if (!q || typeof q !== \"object\") {\n errors.push(`${qPrefix} phải là một object.`);\n return;\n }\n\n const qTitle = typeof q.title === \"string\" ? q.title.trim() : \"\";\n if (qTitle.length < 2 || qTitle.length > 180) {\n errors.push(`${qPrefix}: Tiêu đề 'title' phải có độ dài từ 2 đến 180 ký tự.`);\n }\n\n if (!Array.isArray(q.answers) || q.answers.length === 0) {\n errors.push(`${qPrefix}: Phải có ít nhất 1 đáp án trong mảng 'answers'.`);\n return;\n }\n\n const cleanAnswers: ZaloFormQuestionAnswerInput[] = [];\n q.answers.forEach((ans: any, aIdx: number) => {\n const aType = Number(ans?.type);\n if (![2, 7, 13].includes(aType)) {\n errors.push(`${qPrefix} đáp án [${aIdx}]: 'type' phải là 7 (Họ tên), 13 (SĐT chuẩn), hoặc 2 (SĐT phụ).`);\n }\n if (aType === 13) hasPhonePrimary = true;\n if (aType === 2) hasPhoneSecondary = true;\n\n cleanAnswers.push({\n type: aType,\n placeHolder: ans?.placeHolder ? String(ans.placeHolder).trim() : undefined,\n value: ans?.value ? String(ans.value).trim() : null,\n priority: typeof ans?.priority === \"number\" ? ans.priority : 500\n });\n });\n\n cleanQuestions.push({\n title: qTitle,\n type: typeof q.type === \"number\" ? q.type : 1,\n isRequired: q.isRequired !== undefined ? Boolean(q.isRequired) : true,\n editDisabled: Boolean(q.editDisabled),\n priority: typeof q.priority === \"number\" ? q.priority : (idx + 1) * 100,\n answers: cleanAnswers\n });\n });\n }\n\n // Áp dụng quy tắc ngầm: Nếu có SĐT phụ (type 2), SĐT chuẩn (type 13) PHẢI khóa cứng editDisabled = true\n if (hasPhoneSecondary) {\n cleanQuestions.forEach(q => {\n if (q.answers.some(a => a.type === 13)) {\n q.editDisabled = true;\n }\n });\n }\n\n // 10. Kiểm tra sections\n const cleanSections: ZaloFormSectionInput[] = [];\n if (Array.isArray(raw.sections)) {\n raw.sections.forEach((sec: any, sIdx: number) => {\n const sPrefix = `Section [${sIdx}]`;\n const sType = Number(sec?.type);\n if (isNaN(sType) || sType < 0 || sType > 4) {\n errors.push(`${sPrefix}: 'type' phải là số từ 0 đến 4 (0=tổng quan, 1=chi tiết, 2=bảng giá, 3=ưu điểm, 4=ưu đãi).`);\n }\n\n const sTitle = typeof sec?.title === \"string\" ? sec.title.trim() : \"\";\n if (sTitle.length > 60) {\n errors.push(`${sPrefix}: 'title' không được vượt quá 60 ký tự.`);\n }\n\n cleanSections.push({\n type: sType,\n title: sTitle,\n disable: Boolean(sec?.disable),\n expand: Boolean(sec?.expand),\n content: sec?.content ? sec.content : {}\n });\n });\n }\n\n const cleanData: ZaloCreateFormCleanPayload = {\n oaId: cleanOaId,\n title,\n formName,\n description: cleanDescription,\n coverPhoto,\n submitTitle,\n thanks,\n gotoActionType,\n gotoText,\n website: cleanWebsite,\n reviewSubmit: raw.reviewSubmit !== undefined ? Boolean(raw.reviewSubmit) : true,\n questions: cleanQuestions,\n sections: cleanSections.length > 0 ? cleanSections : undefined,\n useCustomConsent,\n consentName: cleanConsentName,\n consentUrl: cleanConsentUrl\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ dữ liệu lấy danh sách Form theo OA (GET /api/form/getByOaId)\n */\nexport function validateListFormsByOfficialAccountRequest(input: unknown): ValidationResult<{ oaId: string; isAll?: boolean }> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n let cleanOaId = \"\";\n if (typeof raw.oaId === \"string\" && /^[0-9]+$/.test(raw.oaId.trim())) {\n cleanOaId = raw.oaId.trim();\n } else if (typeof raw.oaId === \"number\" && Number.isInteger(raw.oaId) && raw.oaId > 0) {\n cleanOaId = String(raw.oaId);\n } else {\n errors.push(\"Trường 'oaId' bắt buộc phải là chuỗi số nguyên dương đại diện cho pageId của OA.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { oaId: cleanOaId, isAll: raw.isAll !== undefined ? Boolean(raw.isAll) : true } : undefined\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ dữ liệu tra cứu Form Leads (GET /client/manage/api/manageForm/getFormLeads)\n */\nexport function validateListFormLeadsRequest(input: unknown): ValidationResult<{\n oaId: string;\n type: number;\n limit: number;\n offset: number;\n status: string;\n fromTime: number;\n toTime: number;\n formIds?: string;\n keyword?: string;\n reason?: string;\n labelIds?: string;\n isCommerce?: boolean;\n}> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Input phải là một object.\"], data: undefined };\n }\n\n const raw = input as Record<string, unknown>;\n\n // oaId trong Lead Center bắt buộc là mã chữ (alphanumeric ID từ session)\n const oaId = typeof raw.oaId === \"string\" ? raw.oaId.trim() : \"\";\n if (!oaId) {\n errors.push(\"Trường 'oaId' là bắt buộc (mã chữ từ getAuthSession, ví dụ 'J4UB9MRE497YDQKKK').\");\n } else if (/^[0-9]+$/.test(oaId)) {\n errors.push(\"Trường 'oaId' trên Lead Center phải là mã chữ alphanumeric từ getAuthSession, không dùng chuỗi số pageId (sẽ bị lỗi 403 Forbidden).\");\n }\n\n const type = Number(raw.type);\n if (![1, 5].includes(type)) {\n errors.push(\"Trường 'type' phải là 1 (ZALOFORM) hoặc 5 (COMMERCE).\");\n }\n\n const limit = typeof raw.limit === \"number\" && raw.limit > 0 ? Math.floor(raw.limit) : 20;\n const offset = typeof raw.offset === \"number\" && raw.offset >= 0 ? Math.floor(raw.offset) : 0;\n\n const status = typeof raw.status === \"string\" && raw.status.trim() !== \"\"\n ? raw.status.trim()\n : \"2,6,1,0,7,4,5,3\";\n\n const now = Math.floor(Date.now() / 1000);\n const fromTime = typeof raw.fromTime === \"number\" && raw.fromTime >= 0\n ? (raw.fromTime >= 10000000000 ? Math.floor(raw.fromTime / 1000) : Math.floor(raw.fromTime))\n : now - 90 * 86400;\n const toTime = typeof raw.toTime === \"number\" && raw.toTime >= 0\n ? (raw.toTime >= 10000000000 ? Math.floor(raw.toTime / 1000) : Math.floor(raw.toTime))\n : now;\n\n if (toTime < fromTime) {\n errors.push(\"Mốc thời gian kết thúc 'toTime' phải lớn hơn hoặc bằng 'fromTime'.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n oaId,\n type,\n limit,\n offset,\n status,\n fromTime,\n toTime,\n formIds: raw.formIds ? String(raw.formIds).trim() : undefined,\n keyword: raw.keyword ? String(raw.keyword).trim() : undefined,\n reason: raw.reason ? String(raw.reason).trim() : undefined,\n labelIds: raw.labelIds ? String(raw.labelIds).trim() : undefined,\n isCommerce: raw.isCommerce !== undefined ? Boolean(raw.isCommerce) : false\n } : undefined\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của yêu cầu bật/tắt nhận thông báo khách hàng tiềm năng (POST /client/manage/api/manageForm/enable, disable).\n */\nexport function validateToggleLeadNotificationRequest(\n input: unknown\n): ValidationResult<{ formId: string }> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu bật/tắt thông báo lead phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const formId = typeof raw.formId === \"string\" ? raw.formId.trim() : (raw.formId ? String(raw.formId).trim() : \"\");\n\n if (!formId) {\n errors.push(\"Mã biểu mẫu ('formId') là bắt buộc và không được để trống.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { formId } : undefined,\n };\n}\n\n/**\n * Kiểm tra tính hợp lệ của yêu cầu cập nhật chu kỳ thông báo khách hàng tiềm năng (POST /client/manage/api/manageForm/updateInterval).\n */\nexport function validateUpdateLeadNotificationIntervalRequest(\n input: unknown\n): ValidationResult<{ oaId: string; formId: string; interval: number }> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu cập nhật chu kỳ thông báo lead phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const oaId = typeof raw.oaId === \"string\" ? raw.oaId.trim() : (raw.oaId ? String(raw.oaId).trim() : \"\");\n const formId = typeof raw.formId === \"string\" ? raw.formId.trim() : (raw.formId ? String(raw.formId).trim() : \"\");\n\n if (!oaId) {\n errors.push(\"Mã Official Account ('oaId') là bắt buộc và không được để trống.\");\n }\n if (!formId) {\n errors.push(\"Mã biểu mẫu ('formId') là bắt buộc và không được để trống.\");\n }\n\n const interval = Number(raw.interval);\n if (isNaN(interval) || ![0, 1, 6].includes(interval)) {\n errors.push(`Chu kỳ thông báo lead ('interval') '${raw.interval}' không hợp lệ. Phải là số nguyên thuộc [0, 1, 6] (0: Ngay lập tức khi có lead / INSTANT, 1 hoặc 6: Tổng hợp theo ngày / DAILY).`);\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { oaId, formId, interval } : undefined,\n };\n}\n\n/**\n * Gom nhóm toàn bộ Validators cho Form & Lead APIs.\n */\nexport const ZaloFormsValidator = {\n createForm: validateCreateFormRequest,\n listFormsByOfficialAccount: validateListFormsByOfficialAccountRequest,\n listFormLeads: validateListFormLeadsRequest,\n enableLeadNotification: validateToggleLeadNotificationRequest,\n disableLeadNotification: validateToggleLeadNotificationRequest,\n updateLeadNotificationInterval: validateUpdateLeadNotificationIntervalRequest,\n validateLeadNotificationInterval: validateUpdateLeadNotificationIntervalRequest,\n} as const;\n","/** Zalo Forms API service. Each API explicitly selects its own request transport. */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/forms.dto\";\r\nimport type * as AdsDto from \"../dtos/ads.dto\";\r\nimport { ZaloFormsValidator, type ZaloCreateFormCleanPayload } from \"../validators/forms.validator\";\r\n\r\nconst OP_ZaloAdsCreateForm: OperationDefinition = {\r\n operationId: \"zalo_ads_create_form\",\r\n method: \"POST\",\r\n endpoint: \"/api/form/create\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: [\"data\"]\r\n};\r\n\r\nconst OP_ZaloAdsListFormsByOfficialAccount: OperationDefinition = {\r\n operationId: \"zalo_ads_list_forms_by_official_account\",\r\n method: \"GET\",\r\n endpoint: \"/api/form/getByOaId\",\r\n baseUrl: \"https://ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [\"oaId\", \"isAll\"],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: []\r\n};\r\n\r\nconst OP_ZaloFormsDisableFormLeadNotification: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_disableFormLeadNotification\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/client/manage/api/notifyLead/disable\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"formId\"\r\n ]\r\n};\r\nconst OP_ZaloFormsEnableFormLeadNotification: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_enableFormLeadNotification\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/client/manage/api/notifyLead/enable\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"formId\"\r\n ]\r\n};\r\nconst OP_ZaloFormsExportFormLeadReport: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_exportFormLeadReport\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getReport\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"formId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListAudienceExclusionTargeting: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listAudienceExclusionTargeting\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getListAudiExcldTargeting\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListConversationLeads: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listConversationLeads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageConversation/getConversationLeads\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"limit\",\r\n \"offset\",\r\n \"status\",\r\n \"toTime\",\r\n \"keyword\",\r\n \"fromTime\",\r\n \"labelIds\",\r\n \"sceneIds\",\r\n \"reason\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListFormLeads: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listFormLeads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getFormLeads\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"type\",\r\n \"limit\",\r\n \"offset\",\r\n \"status\",\r\n \"toTime\",\r\n \"formIds\",\r\n \"keyword\",\r\n \"fromTime\",\r\n \"labelIds\",\r\n \"isCommerce\",\r\n \"reason\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListManagedFormsByOfficialAccount: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listManagedFormsByOfficialAccount\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getByOaId\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"toTime\",\r\n \"fromTime\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListSimpleFormsByOfficialAccount: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listSimpleFormsByOfficialAccount\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageForm/getSimpleFormsByOaId\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\",\r\n \"type\",\r\n \"toTime\",\r\n \"fromTime\",\r\n \"isCommerce\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsListScenariosByOfficialAccount: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_listScenariosByOfficialAccount\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/manageConversation/getScenariosByOaId\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloFormsUpdateFormLeadNotificationInterval: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_updateFormLeadNotificationInterval\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/client/manage/api/notifyLead/updateInterval\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"oaId\",\r\n \"formId\",\r\n \"interval\"\r\n ]\r\n};\r\nconst OP_ZaloFormsGetAuthSession: OperationDefinition = {\r\n \"operationId\": \"ZaloForms_getAuthSession\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/client/manage/api/auth/session\",\r\n \"baseUrl\": \"https://form.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nconst OP_ZaloFormsTrackManageFormEvent: OperationDefinition = {\r\n operationId: \"zalo_forms_track_manage_form_event\",\r\n method: \"GET\",\r\n endpoint: \"/client/manage/api/manageForm/tracking\",\r\n baseUrl: \"https://form.ads.zalo.me\",\r\n binaryFields: [],\r\n pathFields: [],\r\n queryFields: [\"eventId\", \"oaId\", \"formId\"],\r\n headerFields: [],\r\n cookieFields: [],\r\n bodyFields: []\r\n};\r\n\r\nexport class ZaloFormsService {\r\n public readonly validator = ZaloFormsValidator;\r\n public static readonly validator = ZaloFormsValidator;\r\n\r\n public constructor(private readonly client: ZaloSdkHttpClient) {}\r\n\r\n /**\r\n * Tạo biểu mẫu mới gắn với Official Account (POST https://ads.zalo.me/api/form/create).\r\n * Hỗ trợ truyền thẳng Typed Payload (tự động validate qua ZaloFormsValidator và mã hóa urlencoded)\r\n * hoặc object dạng `{ data: JSON.stringify(...) }`.\r\n */\r\n public async createForm(\r\n request: AdsDto.ZaloAdsCreateFormRequest | ZaloCreateFormCleanPayload | Record<string, unknown>,\r\n options?: RequestOptions\r\n ): Promise<AdsDto.ZaloAdsCreateFormResponse> {\r\n let payloadStr: string;\r\n if (typeof (request as any).data === \"string\") {\r\n payloadStr = (request as any).data;\r\n } else {\r\n const val = ZaloFormsValidator.createForm(request);\r\n if (!val.isValid || !val.data) {\r\n throw new Error(`[ZaloFormsValidator] Dữ liệu tạo form không hợp lệ:\\n - ${val.errors.join(\"\\n - \")}`);\r\n }\r\n payloadStr = JSON.stringify(val.data);\r\n }\r\n return this.client.requestFormUrlEncoded<AdsDto.ZaloAdsCreateFormResponse>(\r\n OP_ZaloAdsCreateForm,\r\n this.client.toTransportInput(OP_ZaloAdsCreateForm, { data: payloadStr }),\r\n options\r\n );\r\n }\r\n\r\n /**\r\n * Lấy danh sách biểu mẫu Zalo Ads theo Official Account (GET https://ads.zalo.me/api/form/getByOaId).\r\n */\r\n public listFormsByOfficialAccount(\r\n request: AdsDto.ZaloAdsListFormsByOfficialAccountRequest,\r\n options?: RequestOptions\r\n ): Promise<AdsDto.ZaloAdsListFormsByOfficialAccountResponse> {\r\n const val = ZaloFormsValidator.listFormsByOfficialAccount(request);\r\n const cleanInput = val.isValid && val.data ? val.data : request;\r\n return this.client.requestWithoutBody<AdsDto.ZaloAdsListFormsByOfficialAccountResponse>(\r\n OP_ZaloAdsListFormsByOfficialAccount,\r\n this.client.toTransportInput(OP_ZaloAdsListFormsByOfficialAccount, cleanInput as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n public getAuthSession(options?: RequestOptions): Promise<Dto.ZaloFormsGetAuthSessionResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsGetAuthSessionResponse>(OP_ZaloFormsGetAuthSession, undefined, options);\r\n }\r\n public disableFormLeadNotification(request: Dto.ZaloFormsDisableFormLeadNotificationRequest, options?: RequestOptions): Promise<Dto.ZaloFormsDisableFormLeadNotificationResponse> {\r\n return this.client.requestJson<Dto.ZaloFormsDisableFormLeadNotificationResponse>(OP_ZaloFormsDisableFormLeadNotification, this.client.toTransportInput(OP_ZaloFormsDisableFormLeadNotification, request as Record<string, unknown>), options);\r\n }\r\n public enableFormLeadNotification(request: Dto.ZaloFormsEnableFormLeadNotificationRequest, options?: RequestOptions): Promise<Dto.ZaloFormsEnableFormLeadNotificationResponse> {\r\n return this.client.requestJson<Dto.ZaloFormsEnableFormLeadNotificationResponse>(OP_ZaloFormsEnableFormLeadNotification, this.client.toTransportInput(OP_ZaloFormsEnableFormLeadNotification, request as Record<string, unknown>), options);\r\n }\r\n public exportFormLeadReport(request: Dto.ZaloFormsExportFormLeadReportRequest, options?: RequestOptions): Promise<Dto.ZaloFormsExportFormLeadReportResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsExportFormLeadReportResponse>(OP_ZaloFormsExportFormLeadReport, this.client.toTransportInput(OP_ZaloFormsExportFormLeadReport, request as Record<string, unknown>), options);\r\n }\r\n public listAudienceExclusionTargeting(request: Dto.ZaloFormsListAudienceExclusionTargetingRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListAudienceExclusionTargetingResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListAudienceExclusionTargetingResponse>(OP_ZaloFormsListAudienceExclusionTargeting, this.client.toTransportInput(OP_ZaloFormsListAudienceExclusionTargeting, request as Record<string, unknown>), options);\r\n }\r\n public listConversationLeads(request: Dto.ZaloFormsListConversationLeadsRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListConversationLeadsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListConversationLeadsResponse>(OP_ZaloFormsListConversationLeads, this.client.toTransportInput(OP_ZaloFormsListConversationLeads, request as Record<string, unknown>), options);\r\n }\r\n public listFormLeads(request: Dto.ZaloFormsListFormLeadsRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListFormLeadsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListFormLeadsResponse>(OP_ZaloFormsListFormLeads, this.client.toTransportInput(OP_ZaloFormsListFormLeads, request as Record<string, unknown>), options);\r\n }\r\n public listManagedFormsByOfficialAccount(request: Dto.ZaloFormsListManagedFormsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListManagedFormsByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListManagedFormsByOfficialAccountResponse>(OP_ZaloFormsListManagedFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloFormsListManagedFormsByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n public listSimpleFormsByOfficialAccount(request: Dto.ZaloFormsListSimpleFormsByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListSimpleFormsByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListSimpleFormsByOfficialAccountResponse>(OP_ZaloFormsListSimpleFormsByOfficialAccount, this.client.toTransportInput(OP_ZaloFormsListSimpleFormsByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n public listScenariosByOfficialAccount(request: Dto.ZaloFormsListScenariosByOfficialAccountRequest, options?: RequestOptions): Promise<Dto.ZaloFormsListScenariosByOfficialAccountResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsListScenariosByOfficialAccountResponse>(OP_ZaloFormsListScenariosByOfficialAccount, this.client.toTransportInput(OP_ZaloFormsListScenariosByOfficialAccount, request as Record<string, unknown>), options);\r\n }\r\n public updateFormLeadNotificationInterval(request: Dto.ZaloFormsUpdateFormLeadNotificationIntervalRequest, options?: RequestOptions): Promise<Dto.ZaloFormsUpdateFormLeadNotificationIntervalResponse> {\r\n return this.client.requestJson<Dto.ZaloFormsUpdateFormLeadNotificationIntervalResponse>(OP_ZaloFormsUpdateFormLeadNotificationInterval, this.client.toTransportInput(OP_ZaloFormsUpdateFormLeadNotificationInterval, request as Record<string, unknown>), options);\r\n }\r\n\r\n /**\r\n * Ghi nhận sự kiện tương tác trên Lead Center (GET /client/manage/api/manageForm/tracking).\r\n */\r\n public trackManageFormEvent(\r\n request: Dto.ZaloFormsTrackManageFormEventRequest,\r\n options?: RequestOptions\r\n ): Promise<Dto.ZaloFormsTrackManageFormEventResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloFormsTrackManageFormEventResponse>(\r\n OP_ZaloFormsTrackManageFormEvent,\r\n this.client.toTransportInput(OP_ZaloFormsTrackManageFormEvent, request as Record<string, unknown>),\r\n options\r\n );\r\n }\r\n}\r\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho 13 API Zalo Instant Pages.\n * Được thiết kế để xuất ra ngoài cho backend (NestJS/Express/Fastify), middleware hoặc AI Agent\n * sử dụng để xác thực dữ liệu đầu vào trước khi lưu trữ hoặc gọi API Zalo Ads.\n *\n * Lưu ý: Các hàm validate này là độc lập (pure functions), KHÔNG bị nhúng cứng bên trong\n * các hàm gọi HTTP của ZaloInstantPagesService, giúp giữ cho Service gọn gàng và unopinionated.\n */\nimport type * as Dto from \"../dtos/instant-pages.dto\";\n\n/** Kết quả xác thực dữ liệu đầu vào của API. */\nexport interface ValidationResult<T = unknown> {\n /** True nếu dữ liệu hợp lệ và thỏa mãn quy chuẩn; False nếu có ít nhất 1 lỗi. */\n isValid: boolean;\n /** Danh sách các thông báo lỗi chi tiết. Rỗng nếu isValid = true. */\n errors: string[];\n /** Dữ liệu sau khi làm sạch và ép kiểu chuẩn (nếu hợp lệ). */\n data?: T;\n}\n\n/** Helper kiểm tra giá trị có phải là số nguyên dương > 0. */\nfunction isPositiveInteger(val: unknown): boolean {\n if (typeof val === \"number\") return Number.isInteger(val) && val > 0;\n if (typeof val === \"string\" && val.trim() !== \"\") {\n const num = Number(val);\n return Number.isInteger(num) && num > 0;\n }\n return false;\n}\n\n/** Helper ép kiểu về số nguyên dương. */\nfunction toPositiveInteger(val: unknown): number {\n return typeof val === \"number\" ? Math.floor(val) : parseInt(String(val), 10);\n}\n\n// ============================================================================\n// 1. createInstantPage\n// ============================================================================\nexport function validateCreateInstantPageRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesCreateInstantPageRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu tạo Instant Page phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n const validTemplates = [1, 3, 4, 5];\n if (!isPositiveInteger(obj.templateId) || !validTemplates.includes(Number(obj.templateId))) {\n errors.push(`Trường 'templateId' là bắt buộc và phải thuộc danh mục mẫu hợp lệ: ${validTemplates.join(\", \")} (1: Sản phẩm form nhúng, 3: Sản phẩm popup, 4: Kịch bản tin nhắn, 5: Mua sắm).`);\n }\n\n if (obj.oaId !== undefined && obj.oaId !== null) {\n const oaIdStr = String(obj.oaId).trim();\n if (!oaIdStr) {\n errors.push(\"Trường 'oaId' nếu cung cấp không được để trống.\");\n } else if (oaIdStr.length < 10) {\n errors.push(\"Trường 'oaId' trên domain page.ads.zalo.me bắt buộc phải là chuỗi định danh 64-bit của Official Account (lấy từ GET /api/official-accounts), không dùng ID số nguyên ngắn.\");\n }\n }\n\n const data: Dto.ZaloInstantPagesCreateInstantPageRequest = {\n templateId: toPositiveInteger(obj.templateId) as any,\n oaId: obj.oaId ? String(obj.oaId).trim() : undefined,\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? data : undefined,\n };\n}\n\n// ============================================================================\n// 2. cloneInstantPage\n// ============================================================================\nexport function validateCloneInstantPageRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesCloneInstantPageRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu sao chép Instant Page phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : undefined,\n };\n}\n\n// ============================================================================\n// 2. getInstantPageDetail\n// ============================================================================\nexport function validateGetInstantPageDetailRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesGetInstantPageDetailRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy chi tiết Instant Page phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : undefined,\n };\n}\n\n// ============================================================================\n// 3. getInstantPageSharedUser\n// ============================================================================\nexport function validateGetInstantPageSharedUserRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesGetInstantPageSharedUserRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy thông tin người dùng chia sẻ phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n if (!isPositiveInteger(obj.userId)) {\n errors.push(\"Trường 'userId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n instantPageId: toPositiveInteger(obj.instantPageId),\n userId: toPositiveInteger(obj.userId),\n } : undefined,\n };\n}\n\n// ============================================================================\n// 4. listInstantPageEditHistory\n// ============================================================================\nexport function validateListInstantPageEditHistoryRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageEditHistoryRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy lịch sử chỉnh sửa phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n let limit: number | undefined = undefined;\n if (obj.limit !== undefined && obj.limit !== null) {\n if (!isPositiveInteger(obj.limit)) {\n errors.push(\"Trường 'limit' nếu có phải là số nguyên >= 1.\");\n } else {\n limit = toPositiveInteger(obj.limit);\n }\n }\n\n let offset: number | undefined = undefined;\n if (obj.offset !== undefined && obj.offset !== null) {\n const num = Number(obj.offset);\n if (!Number.isInteger(num) || num < 0) {\n errors.push(\"Trường 'offset' nếu có phải là số nguyên >= 0.\");\n } else {\n offset = num;\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? {\n instantPageId: toPositiveInteger(obj.instantPageId),\n ...(limit !== undefined ? { limit } : {}),\n ...(offset !== undefined ? { offset } : {}),\n } : undefined,\n };\n}\n\n// ============================================================================\n// 5. listInstantPageFormRecords\n// ============================================================================\nexport function validateListInstantPageFormRecordsRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageFormRecordsRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu tải bản ghi form phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : undefined,\n };\n}\n\n// ============================================================================\n// 6. listInstantPageShares\n// ============================================================================\nexport function validateListInstantPageSharesRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageSharesRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy danh sách người được chia sẻ phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { instantPageId: toPositiveInteger(obj.instantPageId) } : undefined,\n };\n}\n\n// ============================================================================\n// 7. listInstantPageUsers\n// ============================================================================\nexport function validateListInstantPageUsersRequest(input?: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageUsersRequest> {\n if (input !== undefined && input !== null && typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy danh sách người dùng phải là một đối tượng hoặc để trống.\"] };\n }\n return { isValid: true, errors: [], data: {} };\n}\n\n// ============================================================================\n// 8. listMiniPageTemplates\n// ============================================================================\nexport function validateListMiniPageTemplatesRequest(input?: unknown): ValidationResult<Dto.ZaloInstantPagesListMiniPageTemplatesRequest> {\n if (input !== undefined && input !== null && typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy mẫu giao diện phải là một đối tượng hoặc để trống.\"] };\n }\n return { isValid: true, errors: [], data: {} };\n}\n\n// ============================================================================\n// 9. searchInstantPages\n// ============================================================================\nexport function validateSearchInstantPagesRequest(input?: unknown): ValidationResult<Dto.ZaloInstantPagesSearchInstantPagesRequest> {\n const errors: string[] = [];\n if (input === undefined || input === null) {\n return { isValid: true, errors: [], data: {} };\n }\n if (typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu tìm kiếm Instant Page phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n const data: Dto.ZaloInstantPagesSearchInstantPagesRequest = {};\n\n if (obj.id !== undefined && obj.id !== null && obj.id !== \"\") {\n if (!isPositiveInteger(obj.id)) {\n errors.push(\"Bộ lọc 'id' nếu có phải là số nguyên dương (> 0).\");\n } else {\n data.id = toPositiveInteger(obj.id);\n }\n }\n\n if (obj.name !== undefined && obj.name !== null) {\n if (typeof obj.name !== \"string\") {\n errors.push(\"Bộ lọc 'name' nếu có phải là chuỗi ký tự.\");\n } else {\n data.name = obj.name;\n }\n }\n\n if (obj.group !== undefined && obj.group !== null && obj.group !== \"\") {\n const grp = Number(obj.group);\n if (grp !== 1 && grp !== 2) {\n errors.push(\"Bộ lọc 'group' chỉ nhận giá trị 1 (Trang sản phẩm) hoặc 2 (Kịch bản tin nhắn).\");\n } else {\n data.group = grp as 1 | 2;\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? data : undefined,\n };\n}\n\n// ============================================================================\n// 10. updateInstantPage\n// ============================================================================\n\n/**\n * Làm sạch key của dictionary data (khử dấu ngoặc kép thừa do parse lỗi hoặc serialize nhầm, ví dụ: '\"1\"' -> '1').\n */\nexport function sanitizeCanvasKeys(data: Record<string, unknown>): Record<string, unknown> {\n const cleanData: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n const cleanKey = key.replace(/^[\"']+|[\"']+$/g, \"\").trim();\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n const valObj = value as Record<string, unknown>;\n const sanitizedSub: Record<string, unknown> = { ...valObj };\n if (sanitizedSub.images && typeof sanitizedSub.images === \"object\" && !Array.isArray(sanitizedSub.images)) {\n sanitizedSub.images = sanitizeCanvasKeys(sanitizedSub.images as Record<string, unknown>);\n }\n if (sanitizedSub.videos && typeof sanitizedSub.videos === \"object\" && !Array.isArray(sanitizedSub.videos)) {\n sanitizedSub.videos = sanitizeCanvasKeys(sanitizedSub.videos as Record<string, unknown>);\n }\n cleanData[cleanKey] = sanitizedSub;\n } else {\n cleanData[cleanKey] = value;\n }\n }\n return cleanData;\n}\n\n/**\n * Kiểm tra tính hợp lệ toàn vẹn của một Canvas Instant Page (renderList, data matching, block rules).\n */\nexport function validateInstantPageCanvas(\n input: unknown,\n isPublishing: boolean = false\n): ValidationResult<Dto.InstantPageCanvas> {\n const errors: string[] = [];\n if (!input) {\n return { isValid: false, errors: [\"Canvas Instant Page không được để trống.\"] };\n }\n\n let canvasObj: Record<string, unknown>;\n if (typeof input === \"string\") {\n if (input.trim() === \"\") {\n return { isValid: false, errors: [\"Chuỗi Canvas JSON không được rỗng.\"] };\n }\n try {\n canvasObj = JSON.parse(input);\n } catch (e) {\n return { isValid: false, errors: [`Canvas JSON không hợp lệ: ${(e as Error).message}`] };\n }\n } else if (typeof input === \"object\" && input !== null) {\n canvasObj = input as Record<string, unknown>;\n } else {\n return { isValid: false, errors: [\"Canvas phải là đối tượng (Object) hoặc chuỗi JSON hợp lệ.\"] };\n }\n\n // 1. Kiểm tra renderList\n if (!canvasObj.renderList || !Array.isArray(canvasObj.renderList)) {\n errors.push(\"Canvas bắt buộc phải có mảng 'renderList' định nghĩa thứ tự hiển thị các khối giao diện (ví dụ: ['0', '1', '2']). Không được dùng { blocks: [] }.\");\n } else if (canvasObj.renderList.length === 0) {\n errors.push(\"Mảng 'renderList' không được rỗng, phải chứa ít nhất 1 ID khối giao diện.\");\n }\n\n // 2. Kiểm tra data\n if (!canvasObj.data || typeof canvasObj.data !== \"object\" || Array.isArray(canvasObj.data)) {\n errors.push(\"Canvas bắt buộc phải có đối tượng 'data' chứa cấu hình chi tiết của từng khối giao diện.\");\n }\n\n if (errors.length > 0) {\n return { isValid: false, errors };\n }\n\n // 3. Khử escape key và kiểm tra toàn vẹn 1-1\n const renderList = (canvasObj.renderList as unknown[]).map((id) =>\n String(id).replace(/^[\"']+|[\"']+$/g, \"\").trim()\n );\n const rawData = canvasObj.data as Record<string, unknown>;\n const cleanData = sanitizeCanvasKeys(rawData);\n\n for (const blockId of renderList) {\n if (!(blockId in cleanData)) {\n errors.push(`Khối ID '${blockId}' có trong 'renderList' nhưng không tồn tại trong từ điển 'data'.`);\n } else {\n const block = cleanData[blockId] as Record<string, unknown>;\n if (!block || typeof block !== \"object\") {\n errors.push(`Khối dữ liệu data['${blockId}'] phải là một đối tượng.`);\n } else if (block.type === undefined || typeof block.type !== \"number\") {\n errors.push(`Khối data['${blockId}'] bắt buộc phải có trường 'type' là mã số nguyên (Block Type).`);\n }\n }\n }\n\n // 4. Kiểm tra điều kiện xuất bản (Pre-publish guard khi isPublishing = true)\n if (isPublishing) {\n for (const blockId of renderList) {\n const block = cleanData[blockId] as Record<string, unknown>;\n if (!block) continue;\n\n // Type 28: SHOP_INFO\n if (block.type === 28) {\n const name = typeof block.name === \"string\" ? block.name.trim() : \"\";\n if (name.length < 2 || name.length > 30) {\n errors.push(`Khối Thông tin Mini Shop (ID: '${blockId}'): Tên Mini Shop ('name') phải từ 2 đến 30 ký tự.`);\n }\n const img = block.image as Record<string, unknown> | undefined;\n if (!img || typeof img.url !== \"string\" || !img.url.startsWith(\"http\")) {\n errors.push(`Khối Thông tin Mini Shop (ID: '${blockId}'): Bắt buộc phải có ảnh logo với URL hợp lệ ('image.url').`);\n }\n }\n\n // Type 29: SHOP_DESCRIPTION\n if (block.type === 29) {\n const len = typeof block.length === \"number\" ? block.length : 0;\n const html = typeof block.outputHtml === \"string\" ? block.outputHtml.trim() : \"\";\n if (len === 0 && html === \"\") {\n errors.push(`Khối Mô tả (ID: '${blockId}'): Không được để trống nội dung mô tả.`);\n }\n }\n\n // Type 1: CAROUSEL\n if (block.type === 1) {\n const indexes = Array.isArray(block.indexes) ? block.indexes : [];\n const images =\n block.images && typeof block.images === \"object\"\n ? (block.images as Record<string, Record<string, unknown>>)\n : {};\n for (const idx of indexes) {\n const img = images[String(idx)];\n if (img && typeof img.url === \"string\" && img.url.trim() === \"\") {\n errors.push(`Khối Carousel (ID: '${blockId}'): Ảnh tại chỉ mục '${idx}' không được để URL rỗng.`);\n }\n }\n }\n\n // Type 21: DEFAULT_MESSAGE\n if (block.type === 21) {\n const msg = typeof block.content === \"string\" ? block.content.trim() : \"\";\n if (msg.length === 0 || msg.length > 40) {\n errors.push(`Khối Tin nhắn mặc định (ID: '${blockId}'): Nội dung tin nhắn phải từ 1 đến 40 ký tự.`);\n }\n }\n }\n }\n\n const resultCanvas: Dto.InstantPageCanvas = {\n version: (typeof canvasObj.version === \"number\" || typeof canvasObj.version === \"string\") ? canvasObj.version : \"1\",\n renderList,\n data: cleanData as Record<string, Dto.InstantPageBlock>,\n ...(canvasObj.freezedTop !== undefined ? { freezedTop: Number(canvasObj.freezedTop) } : {}),\n ...(canvasObj.freezedBottom !== undefined ? { freezedBottom: Number(canvasObj.freezedBottom) } : {}),\n ...(canvasObj.pageTitle !== undefined ? { pageTitle: String(canvasObj.pageTitle) } : {}),\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? resultCanvas : undefined,\n };\n}\n\n// ============================================================================\n// 10. updateInstantPage\n// ============================================================================\nexport function validateUpdateInstantPageRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesUpdateInstantPageRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu cập nhật Instant Page phải là một đối tượng (object).\"] };\n }\n const obj = input as Record<string, unknown>;\n\n // ID validation\n const instantPageId = obj.instantPageId ?? obj.id;\n if (!isPositiveInteger(instantPageId)) {\n errors.push(\"Trường 'instantPageId' (hoặc 'id') là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n const numericId = toPositiveInteger(instantPageId);\n const data: Dto.ZaloInstantPagesUpdateInstantPageRequest = {\n instantPageId: numericId,\n id: numericId,\n };\n\n // Name validation\n if (obj.name !== undefined && obj.name !== null) {\n if (typeof obj.name !== \"string\") {\n errors.push(\"Trường 'name' phải là chuỗi ký tự.\");\n } else {\n data.name = obj.name;\n }\n }\n\n // oaId validation\n if (obj.oaId !== undefined && obj.oaId !== null) {\n if (typeof obj.oaId !== \"string\") {\n errors.push(\"Trường 'oaId' phải là chuỗi ký tự (hoặc chuỗi rỗng \\\"\\\").\");\n } else {\n data.oaId = obj.oaId;\n }\n }\n\n // Active validation: BẮT BUỘC số nguyên 0 hoặc 1, KHÔNG nhận boolean\n if (obj.active !== undefined && obj.active !== null) {\n if (typeof obj.active === \"boolean\") {\n errors.push(\"Trường 'active' bắt buộc là số nguyên 0 (Tắt) hoặc 1 (Bật), không được truyền kiểu boolean (true/false) vì Zalo Ads API sẽ trả về lỗi HTTP 400.\");\n } else if (obj.active !== 0 && obj.active !== 1) {\n errors.push(\"Trường 'active' chỉ nhận giá trị số nguyên 0 (Tắt) hoặc 1 (Bật).\");\n } else {\n data.active = obj.active as Dto.ZaloInstantPageActive;\n }\n }\n\n // Status validation: 0, 1, 2, 3\n let isPublishing = false;\n if (obj.status !== undefined && obj.status !== null) {\n const st = Number(obj.status);\n if (![0, 1, 2, 3].includes(st)) {\n errors.push(\"Trường 'status' phải là một trong các mã: 0 (Bản sao mới tạo chưa lưu), 1 (Đang hoạt động / Đã xuất bản), 3 (Đã kết thúc / Lưu trữ).\");\n } else {\n data.status = st as Dto.ZaloInstantPageStatus;\n if (st === 1) isPublishing = true;\n }\n }\n\n // Draft validation & Canvas Integrity\n let validatedDraftCanvas: Dto.InstantPageCanvas | undefined;\n if (obj.draft !== undefined && obj.draft !== null) {\n const canvasRes = validateInstantPageCanvas(obj.draft, isPublishing);\n if (!canvasRes.isValid) {\n errors.push(...canvasRes.errors.map(err => `[draft] ${err}`));\n } else {\n validatedDraftCanvas = canvasRes.data;\n data.draft = JSON.stringify(canvasRes.data);\n }\n }\n\n // Content validation & Canvas Integrity\n let validatedContentCanvas: Dto.InstantPageCanvas | undefined;\n if (obj.content !== undefined && obj.content !== null) {\n const canvasRes = validateInstantPageCanvas(obj.content, isPublishing);\n if (!canvasRes.isValid) {\n errors.push(...canvasRes.errors.map(err => `[content] ${err}`));\n } else {\n validatedContentCanvas = canvasRes.data;\n data.content = JSON.stringify(canvasRes.data);\n }\n }\n\n // Tự động đồng bộ nội dung khi Xuất bản Live (status === 1)\n if (isPublishing) {\n if (data.draft && !data.content) {\n data.content = data.draft;\n } else if (data.content && !data.draft) {\n data.draft = data.content;\n } else if (!data.draft && !data.content) {\n // Khi status = 1 mà không gửi draft lẫn content, cảnh báo cần có nội dung\n // (Trừ khi người dùng chỉ đổi tên hoặc bật active)\n }\n }\n\n // Kiểm tra ít nhất 1 trường cần cập nhật\n const hasUpdateField = data.name !== undefined || data.oaId !== undefined || data.active !== undefined || data.status !== undefined || data.draft !== undefined || data.content !== undefined;\n if (!hasUpdateField) {\n errors.push(\"Yêu cầu cập nhật Instant Page phải có ít nhất một trường thay đổi: 'name', 'oaId', 'active', 'status', 'draft', hoặc 'content'.\");\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? data : undefined,\n };\n}\n\n// ============================================================================\n// 11. listInstantPageLeads\n// ============================================================================\nexport function validateListInstantPageLeadsRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesListInstantPageLeadsRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy thống kê leads phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n let idsString = \"\";\n if (typeof obj.ids === \"string\" && obj.ids.trim() !== \"\") {\n idsString = obj.ids.trim();\n } else if (Array.isArray(obj.ids) && obj.ids.length > 0) {\n idsString = obj.ids.join(\",\");\n } else {\n errors.push(\"Trường 'ids' là bắt buộc và phải là chuỗi các ID phân tách bằng dấu phẩy (ví dụ: '81433,76292') hoặc mảng các ID.\");\n }\n\n if (idsString) {\n const idParts = idsString.split(\",\").map(s => s.trim()).filter(Boolean);\n if (idParts.length === 0) {\n errors.push(\"Trường 'ids' không chứa bất kỳ ID hợp lệ nào.\");\n } else {\n for (const id of idParts) {\n if (!isPositiveInteger(id)) {\n errors.push(`Mã trang '${id}' trong danh sách 'ids' không phải là số nguyên dương hợp lệ.`);\n }\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? { ids: idsString } : undefined,\n };\n}\n\n// ============================================================================\n// 12. listOfficialAccounts\n// ============================================================================\nexport function validateListOfficialAccountsRequest(input?: unknown): ValidationResult<Dto.ZaloInstantPagesListOfficialAccountsRequest> {\n if (input !== undefined && input !== null && typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu yêu cầu lấy danh sách Official Accounts phải là một đối tượng hoặc để trống.\"] };\n }\n return { isValid: true, errors: [], data: {} };\n}\n\n// ============================================================================\n// 13. upsertInstantPageForm\n// ============================================================================\nexport function validateUpsertInstantPageFormRequest(input: unknown): ValidationResult<Dto.ZaloInstantPagesUpsertInstantPageFormRequest> {\n const errors: string[] = [];\n if (!input || typeof input !== \"object\") {\n return { isValid: false, errors: [\"Dữ liệu cấu hình biểu mẫu Instant Page phải là một đối tượng.\"] };\n }\n const obj = input as Record<string, unknown>;\n\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n if (!obj.oaId || typeof obj.oaId !== \"string\" || !/^\\d+$/.test(obj.oaId.trim())) {\n errors.push(\"Trường 'oaId' là bắt buộc và phải là chuỗi số định danh Zalo Official Account.\");\n }\n\n if (!obj.formName || typeof obj.formName !== \"string\" || obj.formName.trim() === \"\") {\n errors.push(\"Trường 'formName' là bắt buộc và không được để trống.\");\n }\n\n if (!Array.isArray(obj.questions) || obj.questions.length === 0) {\n errors.push(\"Trường 'questions' là bắt buộc và phải chứa ít nhất một câu hỏi (minItems: 1).\");\n } else {\n obj.questions.forEach((q, idx) => {\n if (!q || typeof q !== \"object\") {\n errors.push(`Câu hỏi số ${idx + 1} phải là một đối tượng.`);\n return;\n }\n const question = q as Record<string, unknown>;\n if (question.type !== 1 && question.type !== 2) {\n errors.push(`Câu hỏi số ${idx + 1}: Trường 'type' bắt buộc là 1 (nhập liệu) hoặc 2 (lựa chọn phương án).`);\n }\n if (!question.title || typeof question.title !== \"string\" || question.title.trim() === \"\") {\n errors.push(`Câu hỏi số ${idx + 1}: Trường 'title' không được để trống.`);\n }\n if (!Array.isArray(question.answers) || question.answers.length === 0) {\n errors.push(`Câu hỏi số ${idx + 1}: Trường 'answers' phải chứa ít nhất một phương án/ô nhập liệu.`);\n } else {\n question.answers.forEach((ans, ansIdx) => {\n if (!ans || typeof ans !== \"object\") {\n errors.push(`Câu hỏi số ${idx + 1}, phương án ${ansIdx + 1}: Phải là một đối tượng.`);\n return;\n }\n const answer = ans as Record<string, unknown>;\n if (answer.type === undefined || typeof answer.type !== \"number\") {\n errors.push(`Câu hỏi số ${idx + 1}, phương án ${ansIdx + 1}: Trường 'type' bắt buộc là số nguyên.`);\n }\n });\n }\n });\n }\n\n const useCustomConsent = typeof obj.useCustomConsent === \"boolean\" ? obj.useCustomConsent : false;\n let consentConfig = obj.consentConfig as Dto.ZaloInstantPagesUpsertInstantPageFormRequest[\"consentConfig\"] | undefined;\n\n if (useCustomConsent) {\n if (!consentConfig || typeof consentConfig !== \"object\") {\n errors.push(\"Khi 'useCustomConsent' = true, trường 'consentConfig' là bắt buộc.\");\n } else {\n if (!consentConfig.address || typeof consentConfig.address !== \"string\") errors.push(\"Cấu hình điều khoản: 'address' không được để trống.\");\n if (!consentConfig.ownerName || typeof consentConfig.ownerName !== \"string\") errors.push(\"Cấu hình điều khoản: 'ownerName' không được để trống.\");\n if (!consentConfig.ownerEmail || typeof consentConfig.ownerEmail !== \"string\") errors.push(\"Cấu hình điều khoản: 'ownerEmail' không được để trống.\");\n if (!consentConfig.ownerPhone || typeof consentConfig.ownerPhone !== \"string\") errors.push(\"Cấu hình điều khoản: 'ownerPhone' không được để trống.\");\n }\n }\n\n const data: Dto.ZaloInstantPagesUpsertInstantPageFormRequest = {\n instantPageId: toPositiveInteger(obj.instantPageId),\n oaId: String(obj.oaId).trim(),\n formName: String(obj.formName).trim(),\n questions: (obj.questions as Dto.ZaloInstantPagesUpsertInstantPageFormRequest[\"questions\"]) ?? [],\n useCustomConsent,\n consentConfig: consentConfig as Dto.ZaloInstantPagesUpsertInstantPageFormRequest[\"consentConfig\"],\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? data : undefined,\n };\n}\n\n// ============================================================================\n// 15. updateInstantPageShares\n// ============================================================================\nexport function validateUpdateInstantPageSharesRequest(\n input: unknown\n): ValidationResult<Dto.ZaloInstantPagesUpdateInstantPageSharesRequest> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu cập nhật quyền chia sẻ Instant Page phải là một đối tượng.\"],\n };\n }\n\n const obj = input as Record<string, unknown>;\n\n if (!isPositiveInteger(obj.instantPageId)) {\n errors.push(\"Trường 'instantPageId' là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n if (!Array.isArray(obj.shares) || obj.shares.length === 0) {\n errors.push(\"Trường 'shares' là bắt buộc và phải chứa ít nhất một người dùng được phân quyền (minItems: 1).\");\n } else {\n const validPermissions = [1, 2, 3, 4];\n const seenUserIds = new Set<number>();\n\n obj.shares.forEach((item, idx) => {\n if (!item || typeof item !== \"object\") {\n errors.push(`Phần tử thứ ${idx + 1} trong danh sách 'shares' phải là một đối tượng.`);\n return;\n }\n const share = item as Record<string, unknown>;\n const userId = Number(share.userId);\n if (!Number.isInteger(userId) || userId <= 0) {\n errors.push(`Phần tử thứ ${idx + 1}: Trường 'userId' phải là số nguyên dương định danh Zalo (hiện tại: ${share.userId}).`);\n } else if (seenUserIds.has(userId)) {\n errors.push(`Phần tử thứ ${idx + 1}: ID người dùng '${userId}' bị trùng lặp trong danh sách phân quyền.`);\n } else {\n seenUserIds.add(userId);\n }\n\n const permission = Number(share.permission);\n if (!validPermissions.includes(permission)) {\n errors.push(`Phần tử thứ ${idx + 1}: Quyền 'permission' không hợp lệ: ${share.permission}. Phải thuộc [1, 2, 3, 4] (1: ADMIN, 2: UPDATE_PAGE, 3: DOWNLOAD_INFO, 4: READ_ONLY).`);\n }\n });\n }\n\n const cleanData: Dto.ZaloInstantPagesUpdateInstantPageSharesRequest = {\n instantPageId: toPositiveInteger(obj.instantPageId),\n shares: (obj.shares as Dto.ZaloInstantPagesShareMemberDto[]) || [],\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n// ============================================================================\n// Master Validator Container\n// ============================================================================\nexport const ZaloInstantPagesValidator = {\n validateCreateInstantPage: validateCreateInstantPageRequest,\n validateCloneInstantPage: validateCloneInstantPageRequest,\n validateGetInstantPageDetail: validateGetInstantPageDetailRequest,\n validateGetInstantPageSharedUser: validateGetInstantPageSharedUserRequest,\n validateListInstantPageEditHistory: validateListInstantPageEditHistoryRequest,\n validateListInstantPageFormRecords: validateListInstantPageFormRecordsRequest,\n validateListInstantPageShares: validateListInstantPageSharesRequest,\n validateUpdateInstantPageShares: validateUpdateInstantPageSharesRequest,\n validateUpdateShares: validateUpdateInstantPageSharesRequest,\n validateListInstantPageUsers: validateListInstantPageUsersRequest,\n validateListMiniPageTemplates: validateListMiniPageTemplatesRequest,\n validateSearchInstantPages: validateSearchInstantPagesRequest,\n validateUpdateInstantPage: validateUpdateInstantPageRequest,\n validateListInstantPageLeads: validateListInstantPageLeadsRequest,\n validateListOfficialAccounts: validateListOfficialAccountsRequest,\n validateUpsertInstantPageForm: validateUpsertInstantPageFormRequest,\n};\n","/** Zalo Instant Pages API service. Each API explicitly selects its own request transport. */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/instant-pages.dto\";\r\nimport { ZaloInstantPagesValidator } from \"../validators/instant-pages.validator\";\r\n\r\nconst OP_ZaloInstantPagesCreateInstantPage: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_createInstantPage\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/instant-pages\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"templateId\",\r\n \"oaId\"\r\n ]\r\n};\r\nconst OP_ZaloInstantPagesCloneInstantPage: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_cloneInstantPage\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/clone\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesGetInstantPageDetail: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_getInstantPageDetail\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesGetInstantPageSharedUser: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_getInstantPageSharedUser\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/sharedUser\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [\r\n \"userId\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageEditHistory: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageEditHistory\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/edit-history\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [\r\n \"limit\",\r\n \"offset\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageFormRecords: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageFormRecords\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/form/records\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageShares: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageShares\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/shares\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesUpdateInstantPageShares: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_updateInstantPageShares\",\r\n \"method\": \"POST\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/shares\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageUsers: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageUsers\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/users\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListMiniPageTemplates: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listMiniPageTemplates\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/templates\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesSearchInstantPages: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_searchInstantPages\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"id\",\r\n \"name\",\r\n \"group\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesUpdateInstantPage: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_updateInstantPage\",\r\n \"method\": \"PUT\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"id\",\r\n \"name\",\r\n \"oaId\",\r\n \"draft\",\r\n \"active\",\r\n \"status\",\r\n \"content\"\r\n ]\r\n};\r\nconst OP_ZaloInstantPagesListInstantPageLeads: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listInstantPageLeads\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/instant-pages/leads\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"ids\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesListOfficialAccounts: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_listOfficialAccounts\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/api/official-accounts\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloInstantPagesUpsertInstantPageForm: OperationDefinition = {\r\n \"operationId\": \"ZaloInstantPages_upsertInstantPageForm\",\r\n \"method\": \"PUT\",\r\n \"endpoint\": \"/api/instant-pages/{instantPageId}/form\",\r\n \"baseUrl\": \"https://page.ads.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [\r\n \"instantPageId\"\r\n ],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": [\r\n \"oaId\",\r\n \"formName\",\r\n \"questions\",\r\n \"useCustomConsent\",\r\n \"consentConfig\"\r\n ]\r\n};\r\n\r\nexport class ZaloInstantPagesService {\r\n /**\r\n * Bộ công cụ kiểm tra tính hợp lệ dữ liệu (Standalone Validators) cho 13 API Instant Pages.\r\n * Dùng ở backend (NestJS/Express/Fastify), middleware hoặc AI Agent để verify payload trước khi gọi SDK.\r\n */\r\n public static readonly validator = ZaloInstantPagesValidator;\r\n\r\n public constructor(private readonly client: ZaloSdkHttpClient) {}\r\n public createInstantPage(request: Dto.ZaloInstantPagesCreateInstantPageRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesCreateInstantPageResponse> {\r\n return this.client.requestJson<Dto.ZaloInstantPagesCreateInstantPageResponse>(OP_ZaloInstantPagesCreateInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCreateInstantPage, request as Record<string, unknown>), options);\r\n }\r\n public cloneInstantPage(request: Dto.ZaloInstantPagesCloneInstantPageRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesCloneInstantPageResponse> {\r\n return this.client.requestJson<Dto.ZaloInstantPagesCloneInstantPageResponse>(OP_ZaloInstantPagesCloneInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesCloneInstantPage, request as Record<string, unknown>), options);\r\n }\r\n public getInstantPageDetail(request: Dto.ZaloInstantPagesGetInstantPageDetailRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesGetInstantPageDetailResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesGetInstantPageDetailResponse>(OP_ZaloInstantPagesGetInstantPageDetail, this.client.toTransportInput(OP_ZaloInstantPagesGetInstantPageDetail, request as Record<string, unknown>), options);\r\n }\r\n public getInstantPageSharedUser(request: Dto.ZaloInstantPagesGetInstantPageSharedUserRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesGetInstantPageSharedUserResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesGetInstantPageSharedUserResponse>(OP_ZaloInstantPagesGetInstantPageSharedUser, this.client.toTransportInput(OP_ZaloInstantPagesGetInstantPageSharedUser, request as Record<string, unknown>), options);\r\n }\r\n public listInstantPageEditHistory(request: Dto.ZaloInstantPagesListInstantPageEditHistoryRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageEditHistoryResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageEditHistoryResponse>(OP_ZaloInstantPagesListInstantPageEditHistory, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageEditHistory, request as Record<string, unknown>), options);\r\n }\r\n public listInstantPageFormRecords(request: Dto.ZaloInstantPagesListInstantPageFormRecordsRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageFormRecordsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageFormRecordsResponse>(OP_ZaloInstantPagesListInstantPageFormRecords, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageFormRecords, request as Record<string, unknown>), options);\r\n }\r\n public listInstantPageShares(request: Dto.ZaloInstantPagesListInstantPageSharesRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageSharesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageSharesResponse>(OP_ZaloInstantPagesListInstantPageShares, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageShares, request as Record<string, unknown>), options);\r\n }\r\n public updateInstantPageShares(request: Dto.ZaloInstantPagesUpdateInstantPageSharesRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesUpdateInstantPageSharesResponse> {\r\n const transportInput = {\r\n path_param: { instantPageId: request.instantPageId },\r\n body: request.shares\r\n };\r\n return this.client.requestJson<Dto.ZaloInstantPagesUpdateInstantPageSharesResponse>(OP_ZaloInstantPagesUpdateInstantPageShares, transportInput, options);\r\n }\r\n public listInstantPageUsers(request: Dto.ZaloInstantPagesListInstantPageUsersRequest = {}, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageUsersResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageUsersResponse>(OP_ZaloInstantPagesListInstantPageUsers, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageUsers, request as Record<string, unknown>), options);\r\n }\r\n public listMiniPageTemplates(request: Dto.ZaloInstantPagesListMiniPageTemplatesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListMiniPageTemplatesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListMiniPageTemplatesResponse>(OP_ZaloInstantPagesListMiniPageTemplates, this.client.toTransportInput(OP_ZaloInstantPagesListMiniPageTemplates, request as Record<string, unknown>), options);\r\n }\r\n public searchInstantPages(request: Dto.ZaloInstantPagesSearchInstantPagesRequest = {}, options?: RequestOptions): Promise<Dto.ZaloInstantPagesSearchInstantPagesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesSearchInstantPagesResponse>(OP_ZaloInstantPagesSearchInstantPages, this.client.toTransportInput(OP_ZaloInstantPagesSearchInstantPages, request as Record<string, unknown>), options);\r\n }\r\n public updateInstantPage(request: Dto.ZaloInstantPagesUpdateInstantPageRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesUpdateInstantPageResponse> {\r\n return this.client.requestJson<Dto.ZaloInstantPagesUpdateInstantPageResponse>(OP_ZaloInstantPagesUpdateInstantPage, this.client.toTransportInput(OP_ZaloInstantPagesUpdateInstantPage, request as Record<string, unknown>), options);\r\n }\r\n public listInstantPageLeads(request: Dto.ZaloInstantPagesListInstantPageLeadsRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListInstantPageLeadsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListInstantPageLeadsResponse>(OP_ZaloInstantPagesListInstantPageLeads, this.client.toTransportInput(OP_ZaloInstantPagesListInstantPageLeads, request as Record<string, unknown>), options);\r\n }\r\n public listOfficialAccounts(request: Dto.ZaloInstantPagesListOfficialAccountsRequest = {}, options?: RequestOptions): Promise<Dto.ZaloInstantPagesListOfficialAccountsResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloInstantPagesListOfficialAccountsResponse>(OP_ZaloInstantPagesListOfficialAccounts, this.client.toTransportInput(OP_ZaloInstantPagesListOfficialAccounts, request as Record<string, unknown>), options);\r\n }\r\n public upsertInstantPageForm(request: Dto.ZaloInstantPagesUpsertInstantPageFormRequest, options?: RequestOptions): Promise<Dto.ZaloInstantPagesUpsertInstantPageFormResponse> {\r\n return this.client.requestJson<Dto.ZaloInstantPagesUpsertInstantPageFormResponse>(OP_ZaloInstantPagesUpsertInstantPageForm, this.client.toTransportInput(OP_ZaloInstantPagesUpsertInstantPageForm, request as Record<string, unknown>), options);\r\n }\r\n}\r\n","/** Zalo Profile Ads API service (`https://profile.ads.zalo.me`). Each API explicitly selects its own request transport. */\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\nimport type { RequestOptions } from \"../types\";\nimport type * as Dto from \"../dtos/profile-ads.dto\";\n\nconst OP_ZaloProfileAdsCreateOaPage: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_createOaPage\",\n \"method\": \"POST\",\n \"endpoint\": \"/oa\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"option\",\n \"crsf-token\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"typeId\",\n \"tier\",\n \"typeName\",\n \"categoryId\",\n \"subCategoryId\",\n \"oaName\",\n \"description\",\n \"contactName\",\n \"contactPhone\",\n \"coverId\",\n \"avatarId\",\n \"province\",\n \"district\",\n \"address\",\n \"agreeTerm\"\n ]\n};\n\nconst OP_ZaloProfileAdsUploadOaAvatar: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_uploadOaAvatar\",\n \"method\": \"POST\",\n \"endpoint\": \"/ajax/avatar/upload\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [\n \"avatar-file\"\n ],\n \"pathFields\": [],\n \"queryFields\": [\n \"option\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"avatar-file\",\n \"is-new\"\n ]\n};\n\nconst OP_ZaloProfileAdsUploadOaCover: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_uploadOaCover\",\n \"method\": \"POST\",\n \"endpoint\": \"/ajax/cover/upload\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [\n \"cover-file\"\n ],\n \"pathFields\": [],\n \"queryFields\": [\n \"option\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": [\n \"cover-file\",\n \"is-new\"\n ]\n};\n\nconst OP_ZaloProfileAdsGetProvinces: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_getProvinces\",\n \"method\": \"GET\",\n \"endpoint\": \"/ajax/get-province\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nconst OP_ZaloProfileAdsGetDistricts: OperationDefinition = {\n \"operationId\": \"ZaloProfileAds_getDistricts\",\n \"method\": \"GET\",\n \"endpoint\": \"/ajax/get-district\",\n \"baseUrl\": \"https://profile.ads.zalo.me\",\n \"binaryFields\": [],\n \"pathFields\": [],\n \"queryFields\": [\n \"provinceId\"\n ],\n \"headerFields\": [],\n \"cookieFields\": [],\n \"bodyFields\": []\n};\n\nexport class ZaloProfileAdsService {\n public constructor(private readonly client: ZaloSdkHttpClient) {}\n\n public async createOaPage(\n request: Dto.ZaloProfileAdsCreateOaPageRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsCreateOaPageResponse> {\n let csrfToken = request[\"crsf-token\"];\n if (!csrfToken && this.client.authManager) {\n const session = await this.client.authManager.getSession(\"profile.ads.zalo.me\");\n csrfToken = session.cookies[\"CSRF_TOKEN\"] ?? session.xsrfToken;\n }\n const normalizedRequest: Record<string, unknown> = {\n option: \"createpage\",\n typeId: 2,\n tier: 0,\n typeName: \"store\",\n categoryId: 10003,\n agreeTerm: true,\n ...request,\n ...(csrfToken ? { \"crsf-token\": csrfToken } : {}),\n };\n return this.client.requestFormUrlEncoded<Dto.ZaloProfileAdsCreateOaPageResponse>(\n OP_ZaloProfileAdsCreateOaPage,\n this.client.toTransportInput(OP_ZaloProfileAdsCreateOaPage, normalizedRequest),\n options\n );\n }\n\n public uploadOaAvatar(\n request: Dto.ZaloProfileAdsUploadOaAvatarRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsUploadOaAvatarResponse> {\n const normalizedRequest: Record<string, unknown> = {\n option: \"update\",\n \"is-new\": \"true\",\n ...request,\n };\n return this.client.requestMultipart<Dto.ZaloProfileAdsUploadOaAvatarResponse>(\n OP_ZaloProfileAdsUploadOaAvatar,\n this.client.toTransportInput(OP_ZaloProfileAdsUploadOaAvatar, normalizedRequest),\n options\n );\n }\n\n public uploadOaCover(\n request: Dto.ZaloProfileAdsUploadOaCoverRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsUploadOaCoverResponse> {\n const normalizedRequest: Record<string, unknown> = {\n option: \"update\",\n \"is-new\": \"true\",\n ...request,\n };\n return this.client.requestMultipart<Dto.ZaloProfileAdsUploadOaCoverResponse>(\n OP_ZaloProfileAdsUploadOaCover,\n this.client.toTransportInput(OP_ZaloProfileAdsUploadOaCover, normalizedRequest),\n options\n );\n }\n\n public getProvinces(\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsGetProvincesResponse> {\n return this.client.requestWithoutBody<Dto.ZaloProfileAdsGetProvincesResponse>(\n OP_ZaloProfileAdsGetProvinces,\n {},\n options\n );\n }\n\n public getDistricts(\n request: Dto.ZaloProfileAdsGetDistrictsRequest,\n options?: RequestOptions\n ): Promise<Dto.ZaloProfileAdsGetDistrictsResponse> {\n return this.client.requestWithoutBody<Dto.ZaloProfileAdsGetDistrictsResponse>(\n OP_ZaloProfileAdsGetDistricts,\n this.client.toTransportInput(OP_ZaloProfileAdsGetDistricts, request as unknown as Record<string, unknown>),\n options\n );\n }\n}\n","/** Zalo Widget API API service. Each API explicitly selects its own request transport. */\r\nimport { ZaloSdkHttpClient, type OperationDefinition } from \"../client\";\r\nimport type { RequestOptions } from \"../types\";\r\nimport type * as Dto from \"../dtos/widget.dto\";\r\n\r\nconst OP_ZaloWidgetAPIGetOfficialAccountInfo: OperationDefinition = {\r\n \"operationId\": \"ZaloWidgetAPI_getOfficialAccountInfo\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/v1/oa\",\r\n \"baseUrl\": \"https://api.widget.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"oaid\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloWidgetAPIGetWidgetUserProfile: OperationDefinition = {\r\n \"operationId\": \"ZaloWidgetAPI_getWidgetUserProfile\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/v1/zuser\",\r\n \"baseUrl\": \"https://api.widget.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloWidgetAPIListStickerCategories: OperationDefinition = {\r\n \"operationId\": \"ZaloWidgetAPI_listStickerCategories\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/v1/stk-cate\",\r\n \"baseUrl\": \"https://api.widget.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\nconst OP_ZaloWidgetAPIListStickersByCategory: OperationDefinition = {\r\n \"operationId\": \"ZaloWidgetAPI_listStickersByCategory\",\r\n \"method\": \"GET\",\r\n \"endpoint\": \"/v1/stk-cate/stickers\",\r\n \"baseUrl\": \"https://api.widget.zalo.me\",\r\n \"binaryFields\": [],\r\n \"pathFields\": [],\r\n \"queryFields\": [\r\n \"cate_id\"\r\n ],\r\n \"headerFields\": [],\r\n \"cookieFields\": [],\r\n \"bodyFields\": []\r\n};\r\n\r\nexport class ZaloWidgetApiService {\r\n public constructor(private readonly client: ZaloSdkHttpClient) {}\r\n public getOfficialAccountInfo(request: Dto.ZaloWidgetAPIGetOfficialAccountInfoRequest, options?: RequestOptions): Promise<Dto.ZaloWidgetAPIGetOfficialAccountInfoResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloWidgetAPIGetOfficialAccountInfoResponse>(OP_ZaloWidgetAPIGetOfficialAccountInfo, this.client.toTransportInput(OP_ZaloWidgetAPIGetOfficialAccountInfo, request as Record<string, unknown>), options);\r\n }\r\n public getWidgetUserProfile(request: Dto.ZaloWidgetAPIGetWidgetUserProfileRequest, options?: RequestOptions): Promise<Dto.ZaloWidgetAPIGetWidgetUserProfileResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloWidgetAPIGetWidgetUserProfileResponse>(OP_ZaloWidgetAPIGetWidgetUserProfile, this.client.toTransportInput(OP_ZaloWidgetAPIGetWidgetUserProfile, request as Record<string, unknown>), options);\r\n }\r\n public listStickerCategories(request: Dto.ZaloWidgetAPIListStickerCategoriesRequest, options?: RequestOptions): Promise<Dto.ZaloWidgetAPIListStickerCategoriesResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloWidgetAPIListStickerCategoriesResponse>(OP_ZaloWidgetAPIListStickerCategories, this.client.toTransportInput(OP_ZaloWidgetAPIListStickerCategories, request as Record<string, unknown>), options);\r\n }\r\n public listStickersByCategory(request: Dto.ZaloWidgetAPIListStickersByCategoryRequest, options?: RequestOptions): Promise<Dto.ZaloWidgetAPIListStickersByCategoryResponse> {\r\n return this.client.requestWithoutBody<Dto.ZaloWidgetAPIListStickersByCategoryResponse>(OP_ZaloWidgetAPIListStickersByCategory, this.client.toTransportInput(OP_ZaloWidgetAPIListStickersByCategory, request as Record<string, unknown>), options);\r\n }\r\n}\r\n","import type { ZaloAuthDomain, ZaloAuthManager, ZaloDomainSession, ZaloSsoAuthOptions } from \"./auth\";\nimport { ZaloSdkHttpClient } from \"./client\";\nimport { ZaloAdsService } from \"./services/ads.service\";\nimport { ZaloCampaignsService } from \"./services/campaigns.service\";\nimport { ZaloAccountService } from \"./services/account.service\";\nimport { ZaloAudiencesService } from \"./services/audiences.service\";\nimport { ZaloReportsService } from \"./services/reports.service\";\nimport { ZaloConversionsService } from \"./services/conversions.service\";\nimport { ZaloAutomatedRulesService } from \"./services/automated-rules.service\";\nimport { ZaloFlowsService } from \"./services/flows.service\";\nimport { ZaloChatWidgetService } from \"./services/chat-widget.service\";\nimport { ZaloFormsService } from \"./services/forms.service\";\nimport { ZaloInstantPagesService } from \"./services/instant-pages.service\";\nimport { ZaloProfileAdsService } from \"./services/profile-ads.service\";\nimport { ZaloWidgetApiService } from \"./services/widget.service\";\nimport { ZaloMediaService } from \"./services/media.service\";\nimport type { ZaloAccountScope, ZaloAdsSdkOptions, ZaloSdkAuth } from \"./types\";\n\n/**\n * Entry point for the Zalo Ads ecosystem SDK (`ads.zalo.me`, `page.ads.zalo.me`, `form.ads.zalo.me`,\n * `profile.ads.zalo.me`, `api.widget.zalo.me`, `widget.chat.zalo.me`).\n *\n * Hỗ trợ 2 chế độ xác thực:\n * 1. **Tự động Silent OAuth2 PKCE SSO qua `zpsid`** (Khuyên dùng):\n * `new ZaloAdsSdk({ zpsid: \"g_kQ.330114198...\" })` — SDK tự động đổi `zpsid` lấy `PLAY_SESSION`,\n * `XSRF-TOKEN`, `zf_id` và `Authorization` token riêng cho từng domain và tự động làm mới khi gặp 401.\n * 2. **Tự truyền Header/Cookie thủ công**:\n * Qua `auth`, `authByHost`, hoặc `setAuth` / `setAuthForHost`.\n */\nexport class ZaloAdsSdk {\n private readonly client: ZaloSdkHttpClient;\n public readonly ads: ZaloAdsService;\n public readonly campaigns: ZaloCampaignsService;\n public readonly account: ZaloAccountService;\n public readonly audiences: ZaloAudiencesService;\n public readonly targeting: ZaloAudiencesService;\n public readonly reports: ZaloReportsService;\n public readonly conversions: ZaloConversionsService;\n public readonly pixel: ZaloConversionsService;\n public readonly automatedRules: ZaloAutomatedRulesService;\n public readonly rules: ZaloAutomatedRulesService;\n public readonly flows: ZaloFlowsService;\n public readonly media: ZaloMediaService;\n public readonly forms: ZaloFormsService;\n public readonly instantPages: ZaloInstantPagesService;\n public readonly profileAds: ZaloProfileAdsService;\n public readonly profile: ZaloProfileAdsService;\n public readonly widget: ZaloWidgetApiService;\n public readonly chatWidget: ZaloChatWidgetService;\n\n public constructor(options: ZaloAdsSdkOptions | string = {}) {\n const resolvedOptions: ZaloAdsSdkOptions =\n typeof options === \"string\" ? { zpsid: options } : options;\n this.client = new ZaloSdkHttpClient(resolvedOptions);\n this.ads = new ZaloAdsService(this.client);\n this.campaigns = this.ads;\n this.account = this.ads.account;\n this.audiences = this.ads.audiences;\n this.targeting = this.ads.audiences;\n this.reports = this.ads.reports;\n this.conversions = this.ads.conversions;\n this.pixel = this.ads.conversions;\n this.automatedRules = this.ads.automatedRules;\n this.rules = this.ads.automatedRules;\n this.flows = this.ads.flows;\n this.media = this.ads.media;\n this.forms = new ZaloFormsService(this.client);\n this.instantPages = new ZaloInstantPagesService(this.client);\n this.profileAds = new ZaloProfileAdsService(this.client);\n this.profile = this.profileAds;\n this.widget = new ZaloWidgetApiService(this.client);\n this.chatWidget = new ZaloChatWidgetService(this.client);\n }\n\n /**\n * Trình quản lý xác thực `ZaloAuthManager` đang gắn với SDK (nếu khởi tạo bằng `zpsid` / `ssoAuth` / `authManager`).\n */\n public get authManager(): ZaloAuthManager | undefined {\n return this.client.authManager;\n }\n\n /**\n * Phạm vi tài khoản quảng cáo cô lập (Isolated Workspace) đang gắn với instance SDK.\n */\n public get accountScope(): ZaloAccountScope | undefined {\n return this.client.accountScope;\n }\n\n /**\n * Cập nhật phạm vi tài khoản quảng cáo cô lập.\n */\n public setAccountScope(scope?: ZaloAccountScope): void {\n this.client.accountScope = scope;\n if (this.client.authManager) {\n this.client.authManager.setAccountScope(scope);\n }\n }\n\n /**\n * Cập nhật cookie `zpsid` gốc (hoặc chuỗi Cookie trình duyệt) để tự động xác thực cho toàn bộ các domain Zalo Ads.\n */\n public setZpsid(zpsidInput: string, ssoOptions?: Omit<ZaloSsoAuthOptions, \"zpsid\">): ZaloAuthManager {\n return this.client.setZpsid(zpsidInput, ssoOptions);\n }\n\n /**\n * Chủ động thực hiện OAuth2 PKCE Handshake trước cho một domain cụ thể.\n */\n public authenticateDomain(domain: ZaloAuthDomain, forceRefresh = false): Promise<ZaloDomainSession> {\n if (!this.client.authManager) {\n throw new Error(\"ZaloAdsSdk: `authManager` is not configured. Call `sdk.setZpsid(...)` or pass `zpsid` in constructor.\");\n }\n return this.client.authManager.authenticateDomain(domain, forceRefresh);\n }\n\n /**\n * Chủ động thực hiện OAuth2 PKCE Handshake đồng thời cho nhiều domain (`ads.zalo.me`, `page.ads.zalo.me`, `form.ads.zalo.me`).\n */\n public authenticateAll(domains?: ZaloAuthDomain[]): Promise<Record<string, ZaloDomainSession>> {\n if (!this.client.authManager) {\n throw new Error(\"ZaloAdsSdk: `authManager` is not configured. Call `sdk.setZpsid(...)` or pass `zpsid` in constructor.\");\n }\n return this.client.authManager.authenticateAll(domains);\n }\n\n public setAuth(auth?: ZaloSdkAuth): void { this.client.setAuth(auth); }\n public setAuthForHost(host: string, auth?: ZaloSdkAuth): void { this.client.setAuthForHost(host, auth); }\n}\n","import {\n deriveAccountKeyFromZpsid,\n parseZaloCookieInput,\n type ZaloAdsWhoamiProfile,\n type ZaloAuthDomain,\n type ZaloDomainSession,\n type ZaloFormSessionProfile,\n} from \"./auth\";\nimport type { ZaloInstantPagesOfficialAccountItem } from \"./dtos/instant-pages.dto\";\nimport { ZaloAdsSdk } from \"./sdk\";\nimport {\n MemoryZaloSessionStore,\n TieredZaloSessionStore,\n type ZaloRedisLikeClient,\n type ZaloSessionStore,\n} from \"./store\";\nimport type { ZaloAccountScope, ZaloAdsSdkOptions } from \"./types\";\n\nexport interface ZaloIntegrationCredentials {\n /**\n * Giá trị cookie `zpsid` gốc của Zalo (hoặc nguyên chuỗi Cookie trình duyệt có chứa `zpsid=...`).\n */\n zpsid: string;\n /**\n * Cookie phụ `zoaw_sek` (tùy chọn, dùng cho các API thuộc `api.widget.zalo.me` / `widget.chat.zalo.me`).\n */\n zoawSek?: string;\n /**\n * Các cookie bổ sung muốn gắn kèm.\n */\n extraCookies?: Record<string, string>;\n /**\n * Phạm vi tài khoản quảng cáo cô lập (Isolated Workspace) - chứa accountId, memberId, agencyId, accountType.\n */\n accountScope?: ZaloAccountScope;\n}\n\nexport interface ZaloAdsClientRequest extends ZaloIntegrationCredentials {\n /**\n * Định danh Integration (`integrationId`) hoặc `accountKey` của người dùng trong hệ thống Backend.\n */\n integrationId: string;\n}\n\nexport interface ZaloIntegrationVerificationResult {\n /** Định danh tài khoản / Integration ID */\n accountKey: string;\n /** Thông tin tài khoản quảng cáo trên ads.zalo.me (/api/whoami) */\n adsProfile?: ZaloAdsWhoamiProfile;\n /** Danh sách Official Accounts trên page.ads.zalo.me (/api/official-accounts) */\n officialAccounts: ZaloInstantPagesOfficialAccountItem[];\n /** Thông tin phiên & danh sách OA mã hóa trên form.ads.zalo.me (/client/manage/api/auth/session) */\n formProfile?: ZaloFormSessionProfile;\n /** Toàn bộ các phiên đã khởi tạo và lưu vào cache (RAM/Redis) */\n sessions: Record<string, ZaloDomainSession>;\n}\n\nexport interface ZaloAdsIntegrationManagerOptions {\n /**\n * Tầng lưu trữ session dùng chung cho toàn bộ các tài khoản/integrations.\n * Nếu không truyền `sessionStore` và `redis`, mặc định dùng `MemoryZaloSessionStore` (RAM LRU).\n */\n sessionStore?: ZaloSessionStore;\n /**\n * Truyền trực tiếp `RedisService` (của `redai-v201-be-app-staging`) hoặc `ioredis` client.\n * Tự động kích hoạt `TieredZaloSessionStore` (L1 RAM + L2 Redis + Distributed Lock).\n */\n redis?: ZaloRedisLikeClient;\n /**\n * Tiền tố key trên Redis (mặc định: `'zalo_ads:sso'`).\n */\n redisKeyPrefix?: string;\n /**\n * Thời gian sống tối đa của L1 RAM cache (giây) khi dùng chế độ Tiered (RAM + Redis). Mặc định: 300s (5 phút).\n */\n l1MaxTtlSeconds?: number;\n /**\n * Thời gian sống mặc định của mỗi phiên OAuth domain (mili-giây). Mặc định: 45 phút.\n */\n sessionTtlMs?: number;\n /**\n * Số lượng instance SDK / tài khoản tối đa giữ trong Pool RAM (LRU). Mặc định: 500.\n */\n maxAccountsInMemory?: number;\n /**\n * Hàm callback giải mã / đọc `zpsid` từ Database hoặc Credential Vault của Backend theo `integrationId`.\n * Khi cấu hình hàm này, chỉ cần gọi `await manager.forIntegration(integrationId)` mà không cần truyền lại `zpsid`.\n */\n resolveCredentials?: (\n integrationId: string\n ) => Promise<ZaloIntegrationCredentials | string> | ZaloIntegrationCredentials | string;\n /**\n * Hook được gọi mỗi khi một tài khoản/integration làm mới phiên của một domain.\n */\n onSessionRefreshed?: (\n integrationId: string,\n domain: ZaloAuthDomain,\n session: ZaloDomainSession\n ) => Promise<void> | void;\n fetch?: typeof fetch;\n baseUrls?: ZaloAdsSdkOptions[\"baseUrls\"];\n}\n\n/**\n * Trình quản lý Đa Tài Khoản / Đa Integration (`ZaloAdsIntegrationManager`) dành cho Backend (`redai-v201-be-app-staging`).\n *\n * Tính năng:\n * 1. Quản lý hàng trăm/nghìn `integrationId` khác nhau của nhiều người dùng mà không bị lẫn lộn session.\n * 2. Hỗ trợ lưu trữ phiên trên RAM (`MemoryZaloSessionStore` có LRU eviction) hoặc 2 tầng L1 RAM + L2 Redis (`TieredZaloSessionStore`).\n * 3. Có Distributed Lock trên Redis giúp nhiều worker/pod backend không gọi trùng OAuth handshake của cùng 1 `integrationId`.\n * 4. Tự động phát hiện khi người dùng cập nhật `zpsid` mới cho `integrationId` cũ để xóa cache cũ và handshake lại.\n */\nexport class ZaloAdsIntegrationManager {\n public readonly sessionStore: ZaloSessionStore;\n private readonly sdkPool = new Map<string, { sdk: ZaloAdsSdk; zpsid: string }>();\n private readonly maxAccountsInMemory: number;\n private readonly sessionTtlMs?: number;\n private readonly resolveCredentialsFn?: ZaloAdsIntegrationManagerOptions[\"resolveCredentials\"];\n private readonly onSessionRefreshedFn?: ZaloAdsIntegrationManagerOptions[\"onSessionRefreshed\"];\n private readonly fetchImpl?: typeof fetch;\n private readonly baseUrls?: ZaloAdsSdkOptions[\"baseUrls\"];\n\n public constructor(options: ZaloAdsIntegrationManagerOptions = {}) {\n this.maxAccountsInMemory = options.maxAccountsInMemory ?? 500;\n this.sessionTtlMs = options.sessionTtlMs;\n this.resolveCredentialsFn = options.resolveCredentials;\n this.onSessionRefreshedFn = options.onSessionRefreshed;\n this.fetchImpl = options.fetch;\n this.baseUrls = options.baseUrls;\n\n if (options.sessionStore) {\n this.sessionStore = options.sessionStore;\n } else if (options.redis) {\n this.sessionStore = new TieredZaloSessionStore(options.redis, {\n maxAccounts: this.maxAccountsInMemory,\n keyPrefix: options.redisKeyPrefix,\n l1MaxTtlSeconds: options.l1MaxTtlSeconds,\n defaultTtlSeconds: options.sessionTtlMs ? Math.floor(options.sessionTtlMs / 1000) : undefined,\n });\n } else {\n this.sessionStore = new MemoryZaloSessionStore({\n maxAccounts: this.maxAccountsInMemory,\n });\n }\n }\n\n /**\n * Lấy hoặc khởi tạo instance `ZaloAdsSdk` gắn với một `integrationId` và `zpsid` cụ thể.\n * Instance được giữ trong LRU Pool và tự động dùng chung `sessionStore` (RAM / Redis).\n */\n public getClient(request: ZaloAdsClientRequest): ZaloAdsSdk {\n const { integrationId } = request;\n const parsed = parseZaloCookieInput(request.zpsid);\n const cleanZpsid = parsed.zpsid;\n\n const existing = this.sdkPool.get(integrationId);\n if (existing) {\n // Cập nhật thứ tự LRU\n this.sdkPool.delete(integrationId);\n if (existing.zpsid !== cleanZpsid) {\n existing.sdk.setZpsid(request.zpsid);\n existing.zpsid = cleanZpsid;\n }\n if (request.accountScope) {\n existing.sdk.setAccountScope(request.accountScope);\n }\n this.sdkPool.set(integrationId, existing);\n return existing.sdk;\n }\n\n if (this.sdkPool.size >= this.maxAccountsInMemory) {\n const oldestKey = this.sdkPool.keys().next().value;\n if (oldestKey !== undefined) {\n this.sdkPool.delete(oldestKey);\n }\n }\n\n const extraCookies: Record<string, string> = {\n ...parsed.extractedCookies,\n ...(request.extraCookies ?? {}),\n ...(request.zoawSek ? { zoaw_sek: request.zoawSek } : {}),\n };\n if (request.accountScope?.memberId && String(request.accountScope.memberId) !== \"0\") {\n extraCookies.ads_user_id = String(request.accountScope.memberId);\n }\n\n const sdk = new ZaloAdsSdk({\n integrationId,\n zpsid: cleanZpsid,\n accountScope: request.accountScope,\n sessionStore: this.sessionStore,\n fetch: this.fetchImpl,\n baseUrls: this.baseUrls,\n ssoAuth: {\n integrationId,\n zpsid: cleanZpsid,\n accountScope: request.accountScope,\n extraCookies,\n sessionStore: this.sessionStore,\n sessionTtlMs: this.sessionTtlMs,\n onSessionRefreshed: this.onSessionRefreshedFn\n ? (domain, session) => this.onSessionRefreshedFn!(integrationId, domain, session)\n : undefined,\n },\n });\n\n this.sdkPool.set(integrationId, { sdk, zpsid: cleanZpsid });\n return sdk;\n }\n\n /**\n * Lấy `ZaloAdsSdk` theo `integrationId`.\n * - Nếu truyền `credentialsOverride`, dùng luôn credential đó.\n * - Nếu không truyền và đã cấu hình `resolveCredentials` (đọc từ DB/Vault của Backend), tự động gọi `resolveCredentials(integrationId)`.\n * - Nếu instance đã có sẵn trong Pool RAM, trả về instance đó.\n */\n public async forIntegration(\n integrationId: string,\n credentialsOverride?: ZaloIntegrationCredentials | string\n ): Promise<ZaloAdsSdk> {\n if (credentialsOverride) {\n const normalized: ZaloIntegrationCredentials =\n typeof credentialsOverride === \"string\"\n ? { zpsid: credentialsOverride }\n : credentialsOverride;\n return this.getClient({ integrationId, ...normalized });\n }\n\n if (this.resolveCredentialsFn) {\n const resolved = await this.resolveCredentialsFn(integrationId);\n const normalized: ZaloIntegrationCredentials =\n typeof resolved === \"string\" ? { zpsid: resolved } : resolved;\n return this.getClient({ integrationId, ...normalized });\n }\n\n const cached = this.sdkPool.get(integrationId);\n if (cached) {\n this.sdkPool.delete(integrationId);\n this.sdkPool.set(integrationId, cached);\n return cached.sdk;\n }\n\n throw new Error(\n `ZaloAdsIntegrationManager: Cannot resolve credentials for integration \"${integrationId}\". Pass credentials or configure \\`resolveCredentials\\` option.`\n );\n }\n\n /**\n * Lấy `ZaloAdsSdk` nhanh chỉ bằng `zpsid` (tự động trích xuất `accountKey` duy nhất từ `zpsid`, ví dụ `zalo_330114198_...`).\n */\n public forZpsid(zpsidOrCookie: string, extraCookies?: Record<string, string>): ZaloAdsSdk {\n const parsed = parseZaloCookieInput(zpsidOrCookie);\n const accountKey = deriveAccountKeyFromZpsid(parsed.zpsid);\n return this.getClient({\n integrationId: accountKey,\n zpsid: zpsidOrCookie,\n extraCookies,\n });\n }\n\n /**\n * Xóa sạch cache phiên (trên cả L1 RAM và L2 Redis) của một `integrationId`.\n * Dùng khi người dùng ngắt kết nối hoặc cập nhật lại thông tin xác thực của Integration.\n */\n public async invalidateIntegration(\n integrationId: string,\n domain?: ZaloAuthDomain\n ): Promise<void> {\n const existing = this.sdkPool.get(integrationId);\n if (existing?.sdk.authManager) {\n if (domain) {\n await existing.sdk.authManager.invalidateDomainAsync(domain);\n } else {\n await existing.sdk.authManager.clearSessionsAsync();\n }\n return;\n }\n await this.sessionStore.delete(integrationId, domain);\n }\n\n /**\n * Xóa hẳn `integrationId` khỏi Pool trong RAM và xóa toàn bộ phiên trên RAM/Redis.\n */\n public async removeIntegration(integrationId: string): Promise<void> {\n await this.invalidateIntegration(integrationId);\n this.sdkPool.delete(integrationId);\n }\n\n /**\n * Kiểm tra kết nối (Test Connection / Auth Connect Flow) cho một tài khoản Zalo Ads:\n * - Tự động chạy Silent OAuth2 PKCE Handshake trên `ads.zalo.me`, `page.ads.zalo.me`, `form.ads.zalo.me`.\n * - Trả về thông tin tài khoản quảng cáo (`adsProfile`), danh sách OA (`officialAccounts`), và `formProfile`.\n * - Lưu sẵn toàn bộ phiên vào RAM/Redis để các lệnh gọi API tiếp theo đạt tốc độ tức thì (0ms handshake).\n */\n public async verifyIntegration(params: {\n integrationId?: string;\n zpsid: string;\n zoawSek?: string;\n extraCookies?: Record<string, string>;\n accountScope?: ZaloAccountScope;\n }): Promise<ZaloIntegrationVerificationResult> {\n const parsed = parseZaloCookieInput(params.zpsid);\n const accountKey = params.integrationId ?? deriveAccountKeyFromZpsid(parsed.zpsid);\n const sdk = this.getClient({\n integrationId: accountKey,\n zpsid: params.zpsid,\n zoawSek: params.zoawSek,\n extraCookies: params.extraCookies,\n accountScope: params.accountScope,\n });\n\n const sessions = await sdk.authenticateAll([\n \"ads.zalo.me\",\n \"page.ads.zalo.me\",\n \"form.ads.zalo.me\",\n ]);\n\n const oasResponse = await sdk.instantPages\n .listOfficialAccounts()\n .catch(() => ({ data: [] as ZaloInstantPagesOfficialAccountItem[] }));\n\n return {\n accountKey,\n adsProfile: sessions[\"ads.zalo.me\"]?.adsProfile,\n officialAccounts: Array.isArray(oasResponse?.data) ? oasResponse.data : [],\n formProfile: sessions[\"form.ads.zalo.me\"]?.formProfile,\n sessions,\n };\n }\n\n /**\n * Số lượng instance SDK đang giữ trong Pool RAM.\n */\n public get poolSize(): number {\n return this.sdkPool.size;\n }\n}\n\nexport { ZaloAdsIntegrationManager as ZaloAdsAccountPool };\n","/** DTOs for Zalo Instant Pages. Request fields are flattened; services route them automatically. */\r\nimport type { FileInput } from \"../types\";\r\n\r\n/**\r\n * Mã trạng thái kỹ thuật & nghiệp vụ của Instant Page:\r\n * - 0: Bản sao mới tạo (Clone Draft) - vừa nhân bản từ template hoặc trang khác, chưa từng sửa và chưa xuất bản (máy chủ lọc bỏ khỏi danh sách tìm kiếm)\r\n * - 1: Đang hoạt động / Đã xuất bản (Active / Published) - trang chính thức, nội dung live nằm trong trường content, máy chủ cấp timestamp published\r\n * - 2: Mã trạng thái trung gian cũ trên giao diện\r\n * - 3: Lưu trữ / Đã kết thúc (Archived / Ended) - trang đã ngưng hoạt động hoặc kết thúc chiến dịch\r\n */\r\nexport type ZaloInstantPageStatus = 0 | 1 | 2 | 3;\r\n\r\n/**\r\n * Cờ trạng thái hoạt động của Instant Page:\r\n * - 0: Tắt (tạm khóa, không cho người dùng truy cập)\r\n * - 1: Bật (cho phép xem trang qua https://page.zalo.me/p/{publicId})\r\n * Bắt buộc kiểu số nguyên 0 | 1, không truyền boolean true/false.\r\n */\r\nexport type ZaloInstantPageActive = 0 | 1;\r\n\r\n/**\r\n * Danh mục mã định danh các loại khối giao diện (Block Types) trong Instant Page Canvas (trường draft và content):\r\n */\r\n/** Cấu trúc đối tượng hình ảnh lưu trữ trên CDN Zalo Ads (adtima-media.zascdn.me). */\nexport interface ZaloMediaImage {\n name: string;\n url: string;\n mediaId?: number;\n}\n\n/** Cấu trúc JSON Canvas chuẩn của một Instant Page trên Zalo Ads (page.ads.zalo.me). */\n/** Khối 1: Trình chiếu ảnh / Video xoay vòng (Carousel Slider) */\nexport interface InstantPageCarouselBlock {\n id?: string;\n type: 1 | ZaloInstantPageBlockType.CAROUSEL_SLIDER;\n indexes: string[];\n images: Record<string, ZaloMediaImage>;\n videos?: Record<string, { url: string; name?: string; thumbnail?: string }>;\n textEditor?: {\n delta?: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n outputHtml?: string;\n };\n [key: string]: unknown;\n}\n\n/** Khối 2: Đồng hồ đếm ngược Flash sale / Thời gian ưu đãi */\nexport interface InstantPageCountdownBlock {\n id?: string;\n type: 2 | ZaloInstantPageBlockType.COUNTDOWN;\n discountValue?: number;\n countdownType?: number;\n startDate?: number;\n loopDays?: number;\n label?: string;\n labelDelta?: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n visibility?: {\n days?: boolean;\n hours?: boolean;\n minutes?: boolean;\n seconds?: boolean;\n };\n marginTop?: number;\n marginBottom?: number;\n visible?: boolean;\n [key: string]: unknown;\n}\n\n/** Khối 4: Văn bản mô tả định dạng giàu (Rich Text / Quill Delta) */\nexport interface InstantPageRichTextBlock {\n id?: string;\n type: 4 | ZaloInstantPageBlockType.RICH_TEXT;\n delta?: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n outputHtml?: string;\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 6: Hình ảnh đơn hoặc Video minh họa sản phẩm (Hero Media) */\nexport interface InstantPageHeroMediaBlock {\n id?: string;\n type: 6 | ZaloInstantPageBlockType.HERO_IMAGE;\n mediaType?: \"image\" | \"video\";\n image?: ZaloMediaImage;\n videoSetting?: {\n autoPlay?: boolean;\n loop?: boolean;\n };\n [key: string]: unknown;\n}\n\n/** Khối 7: Form nhập Họ và tên khách hàng */\nexport interface InstantPageFormNameBlock {\n id?: string;\n type: 7 | ZaloInstantPageBlockType.FORM_NAME;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value?: string;\n placeHolder?: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 8: Nút CTA đặt hàng cố định chân trang hoặc mở form popup */\nexport interface InstantPageStickyButtonBlock {\n id?: string;\n type: 8 | ZaloInstantPageBlockType.ORDER_CTA_BUTTON;\n content2: string;\n background?: string;\n borderColor?: string;\n borderRadius?: number;\n borderSize?: number;\n showBorder?: boolean;\n formPopup?: boolean;\n fixedPosition?: boolean;\n image?: ZaloMediaImage;\n [key: string]: unknown;\n}\n\n/** Khối 9: Form nhập Số điện thoại liên hệ */\nexport interface InstantPageFormPhoneBlock {\n id?: string;\n type: 9 | ZaloInstantPageBlockType.FORM_PHONE;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value?: string;\n placeHolder?: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 10: Form nhập Địa chỉ giao hàng */\nexport interface InstantPageFormAddressBlock {\n id?: string;\n type: 10 | ZaloInstantPageBlockType.FORM_ADDRESS;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value?: string;\n placeHolder?: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 14: Chân trang thương hiệu (Địa chỉ, Hotline, Email, Website) */\nexport interface InstantPageFooterBlock {\n id?: string;\n type: 14 | ZaloInstantPageBlockType.FOOTER;\n backgroundColor?: string;\n textDelta?: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n textHtml?: string;\n detailings?: Array<{\n image?: ZaloMediaImage;\n textDelta?: { ops: Array<{ insert: string }> };\n textHtml?: string;\n }>;\n [key: string]: unknown;\n}\n\n/** Khối 16: Form chọn Số lượng mua */\nexport interface InstantPageQuantityBlock {\n id?: string;\n type: 16 | ZaloInstantPageBlockType.FORM_QUANTITY;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value?: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 18: Phân loại / Biến thể sản phẩm (Màu sắc, Size, Combo) */\nexport interface InstantPageProductVariantBlock {\n id?: string;\n type: 18 | ZaloInstantPageBlockType.PRODUCT_VARIANT;\n visible?: boolean;\n formQuestion: {\n type: number;\n title: string;\n isRequired?: boolean;\n disable?: boolean;\n answers: Array<{\n type: number;\n value: string;\n priority?: number;\n }>;\n description?: string;\n priority?: number;\n };\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 19: Tiêu đề sản phẩm & Giá bán */\nexport interface InstantPageProductTitlePriceBlock {\n id?: string;\n type: 19 | ZaloInstantPageBlockType.PRODUCT_TITLE_PRICE;\n name: string;\n price: number;\n rawPrice?: number;\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 20: Danh sách câu hỏi gợi ý nhanh (FAQ pills) */\nexport interface InstantPageQuickQuestionsBlock {\n id?: string;\n type: 20 | ZaloInstantPageBlockType.QUICK_QUESTIONS;\n list: string[];\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 21: Nút / Khung gửi tin nhắn trực tiếp đến Zalo OA */\nexport interface InstantPageDefaultMessageBlock {\n id?: string;\n type: 21 | ZaloInstantPageBlockType.MESSAGE_CTA_BUTTON;\n content: string;\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 23: Nút gọi Hotline liên hệ nhanh */\nexport interface InstantPageCallHotlineBlock {\n id?: string;\n type: 23 | ZaloInstantPageBlockType.CALL_HOTLINE_BUTTON;\n content: string;\n phone: string;\n actionType?: string;\n background?: string;\n color?: string;\n borderColor?: string;\n borderRadius?: number;\n borderSize?: number;\n showBorder?: boolean;\n fixedPosition?: boolean;\n visible?: boolean;\n image?: ZaloMediaImage;\n marginTop?: number;\n marginBottom?: number;\n [key: string]: unknown;\n}\n\n/** Khối 25: Bảng thông số kỹ thuật 2 cột (Key-Value) */\nexport interface InstantPageKeyValueTableBlock {\n id?: string;\n type: 25 | ZaloInstantPageBlockType.KEY_VALUE_TABLE;\n rows: Array<{ id: number; left: string; right: string }>;\n [key: string]: unknown;\n}\n\n/** Khối 27: Điều khoản đồng thuận thu thập dữ liệu cá nhân (NĐ 13) */\nexport interface InstantPageConsentNoticeBlock {\n id?: string;\n type: 27 | ZaloInstantPageBlockType.CONSENT_NOTICE;\n useCustomConsent?: boolean;\n [key: string]: unknown;\n}\n\n/** Khối 28: Thông tin Mini Shop TMĐT (Logo & Tên Shop) */\nexport interface InstantPageShopInfoBlock {\n id?: string;\n type: 28 | ZaloInstantPageBlockType.SHOP_INFO;\n name: string;\n image: ZaloMediaImage;\n [key: string]: unknown;\n}\n\n/** Khối 29: Mô tả giới thiệu sản phẩm TMĐT */\nexport interface InstantPageShopDescriptionBlock {\n id?: string;\n type: 29 | ZaloInstantPageBlockType.SHOP_DESCRIPTION;\n delta: { ops: Array<{ insert: string; attributes?: Record<string, unknown> }> };\n outputHtml: string;\n length: number;\n [key: string]: unknown;\n}\n\n/** Discriminated Union cho toàn bộ 19 loại Block giao diện trên Zalo Instant Page */\nexport type InstantPageBlock =\n | InstantPageCarouselBlock\n | InstantPageCountdownBlock\n | InstantPageRichTextBlock\n | InstantPageHeroMediaBlock\n | InstantPageFormNameBlock\n | InstantPageStickyButtonBlock\n | InstantPageFormPhoneBlock\n | InstantPageFormAddressBlock\n | InstantPageFooterBlock\n | InstantPageQuantityBlock\n | InstantPageProductVariantBlock\n | InstantPageProductTitlePriceBlock\n | InstantPageQuickQuestionsBlock\n | InstantPageDefaultMessageBlock\n | InstantPageCallHotlineBlock\n | InstantPageKeyValueTableBlock\n | InstantPageConsentNoticeBlock\n | InstantPageShopInfoBlock\n | InstantPageShopDescriptionBlock;\n\n/** Cấu trúc JSON Canvas chuẩn của một Instant Page trên Zalo Ads (page.ads.zalo.me). */\nexport interface InstantPageCanvas<TBlock = InstantPageBlock> {\n /** Phiên bản schema của canvas (thường là 1 hoặc '1') */\n version: string | number;\n /** Danh sách ID các khối giao diện theo thứ tự hiển thị */\n renderList: string[];\n /** Bảng tra cứu dữ liệu chi tiết của từng khối giao diện, index bằng ID khối */\n data: Record<string, TBlock>;\n /** Số khối ghim cố định ở đầu trang */\n freezedTop?: number;\n /** Số khối ghim cố định ở cuối chân trang (ví dụ: nút đặt hàng hoặc khung chat) */\n freezedBottom?: number;\n /** Tiêu đề hiển thị trên thanh header mobile */\n pageTitle?: string;\n}\n\nexport enum ZaloInstantPageBlockType {\r\n /** Slide ảnh/video banner trình chiếu sản phẩm */\r\n CAROUSEL_SLIDER = 1,\r\n /** Đồng hồ đếm ngược Flash sale / thời gian khuyến mãi */\r\n COUNTDOWN = 2,\r\n /** Văn bản mô tả giàu định dạng (HTML / Quill Delta ops) */\r\n RICH_TEXT = 4,\r\n /** Hình ảnh đơn / banner minh họa (Hero image) */\r\n HERO_IMAGE = 6,\r\n /** Form field: Ô nhập họ và tên khách hàng */\r\n FORM_NAME = 7,\r\n /** Nút CTA Đặt hàng ngay (cố định chân trang hoặc mở form popup) */\r\n ORDER_CTA_BUTTON = 8,\r\n /** Form field: Ô nhập số điện thoại */\r\n FORM_PHONE = 9,\r\n /** Form field: Ô nhập địa chỉ giao hàng */\r\n FORM_ADDRESS = 10,\r\n /** Chân trang thương hiệu (Hotline, Email, Website, Địa chỉ) */\r\n FOOTER = 14,\r\n /** Form field: Ô chọn số lượng sản phẩm mua */\r\n FORM_QUANTITY = 16,\r\n /** Phân loại / Biến thể sản phẩm (Màu sắc, Size, Combo) */\r\n PRODUCT_VARIANT = 18,\r\n /** Tiêu đề sản phẩm & Giá bán (name, rawPrice, price) */\r\n PRODUCT_TITLE_PRICE = 19,\r\n /** Câu hỏi gợi ý nhanh (FAQ quick replies) */\r\n QUICK_QUESTIONS = 20,\r\n /** Nút CTA nhắn tin trực tiếp đến Zalo Official Account */\r\n MESSAGE_CTA_BUTTON = 21,\r\n /** Tiêu đề phân đoạn (Section Heading) */\r\n SECTION_HEADING = 22,\r\n /** Nút Hotline gọi điện thoại tư vấn viên */\r\n CALL_HOTLINE_BUTTON = 23,\r\n /** Bảng thông số / Ưu đãi 2 cột (Key-Value rows) */\r\n KEY_VALUE_TABLE = 25,\r\n /** Điều khoản đồng thuận thu thập dữ liệu cá nhân theo NĐ 13 */\r\n CONSENT_NOTICE = 27,\n /** Đầu trang TMĐT: Logo & Tên Mini Shop (Template 5) */\n SHOP_INFO = 28,\n /** Đoạn giới thiệu mô tả sản phẩm TMĐT (Template 5) */\n SHOP_DESCRIPTION = 29,\r\n}\r\n\r\n/** Sao chép một Instant Page hiện có và trả về bản Instant Page mới cùng toàn bộ draft được sao chép. Đây là mutation tool thuộc lane zalo-ads-content; dùng khi cần tạo bản làm việc độc lập trước khi chỉnh sửa nội dung hoặc trạng thái. Bản sao có id và publicId mới, không ghi đè Instant Page nguồn. */\r\nexport type ZaloInstantPagesCloneInstantPageRequest = {\r\n /** ID Instant Page nguồn cần sao chép. */\r\n instantPageId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesCloneInstantPageResponse = {\r\n /** Instant Page mới được tạo từ bản sao. */\r\n data: {\r\n /** ID nội bộ mới của Instant Page bản sao; dùng để đọc, cập nhật hoặc clone tiếp. */\r\n id: number;\r\n /** Mã chế độ của Instant Page. */\r\n mode: number;\r\n /** Tên bản sao, thường có tiền tố 'Sao chép từ'. */\r\n name: string;\r\n /** ID Official Account liên kết; có thể rỗng. */\r\n oaId: string;\r\n /** Chuỗi JSON cấu hình bản nháp đã được sao chép, gồm data các block/section, renderList và các thiết lập layout. Đây chưa tự đại diện cho nội dung public đã phát hành. */\r\n draft: string;\r\n /** Cờ bật/tắt của Instant Page: 0 = Tắt, 1 = Bật. */\r\n active: ZaloInstantPageActive;\r\n /** ID form liên kết; có thể rỗng. */\r\n formId: string;\r\n /** Mã trạng thái Instant Page: 0 = Bản sao mới tạo, 1 = Bản nháp, 2 = Đã xuất bản, 3 = Lưu trữ. */\r\n status: ZaloInstantPageStatus | number;\r\n /** ID người dùng sở hữu Instant Page. */\r\n userId: number;\r\n /** Nội dung đã phát hành/được lưu ngoài draft; có thể rỗng. */\r\n content: string;\r\n /** Thời điểm tạo bản sao, Unix timestamp tính bằng giây. */\r\n created: number;\r\n /** Phiên bản dữ liệu Instant Page. */\r\n version: number;\r\n /** Thời điểm cập nhật gần nhất, Unix timestamp tính bằng giây. */\r\n modified: number;\r\n /** ID công khai mới dùng cho URL preview/phát hành. */\r\n publicId: string;\r\n /** ID người tạo bản sao. */\r\n createdBy: number;\r\n /** Thời điểm phát hành, Unix timestamp tính bằng giây; 0 khi chưa phát hành. */\r\n published: number;\r\n /** ID template nguồn của Instant Page. */\r\n templateId: number;\r\n};\r\n};\r\n\r\n/** Lấy chi tiết Instant Page theo ID, gồm cấu hình đang dùng, bản nháp, template và trạng thái phát hành. Đây là detail tool thuộc lane zalo-ads-content; dùng khi đã có Instant Page ID và cần xem hoặc so sánh content với draft trước khi chỉnh sửa. */\r\nexport type ZaloInstantPagesGetInstantPageDetailRequest = {\r\n /** ID nội bộ Instant Page cần xem chi tiết. */\r\n instantPageId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesGetInstantPageDetailResponse = {\r\n data: {\r\n /** ID nội bộ Instant Page. */\r\n id: number;\r\n /** Chế độ vận hành page. */\r\n mode: number;\r\n /** Tên Instant Page. */\r\n name: string;\r\n /** ID Official Account liên kết, khi có. */\r\n oaId: string;\r\n /** Bản nháp cấu hình Instant Page chưa được phát hành hoặc chưa áp dụng làm nội dung chính; dạng chuỗi JSON/serialized payload. Dùng để so sánh hoặc tiếp tục chỉnh sửa, không tự xem là bản public. */\r\n draft: string;\r\n /** Trạng thái kích hoạt: 0 = Tắt, 1 = Bật. */\r\n active: ZaloInstantPageActive;\r\n /** ID form liên kết, khi có. */\r\n formId: string;\r\n /** Trạng thái nghiệp vụ: 0 = Bản sao mới tạo, 1 = Bản nháp, 2 = Đã xuất bản, 3 = Lưu trữ. */\r\n status: ZaloInstantPageStatus | number;\r\n /** ID người dùng sở hữu page. */\r\n userId: number;\r\n /** Nội dung/cấu hình Instant Page đang được lưu, dạng chuỗi JSON hoặc serialized payload. */\r\n content: string;\r\n /** Thời điểm tạo, Unix timestamp theo giây. */\r\n created: number;\r\n /** Phiên bản cấu hình page. */\r\n version: number;\r\n /** Thời điểm chỉnh sửa cuối, Unix timestamp theo giây. */\r\n modified: number;\r\n /** ID công khai dùng cho preview hoặc truy cập page. */\r\n publicId: string;\r\n /** ID người tạo page. */\r\n createdBy: number;\r\n /** Thời điểm phát hành, Unix timestamp theo giây. */\r\n published: number;\r\n /** ID template dùng để khởi tạo page. */\r\n templateId: number;\r\n};\r\n};\r\n\r\n/** Lấy thông tin quyền chi tiết của một người dùng được chia sẻ trên Instant Page, gồm quyền Official Account và các cờ khả năng sử dụng tính năng. Đây là detail tool thuộc lane zalo-ads-content; dùng sau khi có userId từ danh sách chia sẻ để kiểm tra điều kiện quyền của đúng người dùng. Khác với tool danh sách shares, kết quả này trả extraFlags của một người cụ thể. */\r\nexport type ZaloInstantPagesGetInstantPageSharedUserRequest = {\r\n /** ID Instant Page có người dùng được chia sẻ quyền. */\r\n instantPageId: number;\r\n /** ID người dùng cần lấy quyền chi tiết; lấy từ data[].userId của ZaloAds_listInstantPageShares. */\r\n userId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesGetInstantPageSharedUserResponse = {\r\n data: {\r\n /** Tên hiển thị của người dùng. */\r\n name: string;\r\n extraFlags: {\r\n /** Người dùng có được phép sử dụng template quảng cáo mua sắm hay không. */\r\n canUseShoppingAdTemplate: boolean;\r\n};\r\n /** Mã quyền của người dùng trên Official Account liên kết; ý nghĩa chi tiết phụ thuộc quy ước Zalo Ads. */\r\n oaPermission: number;\r\n};\r\n};\r\n\r\n/** Lấy lịch sử chỉnh sửa của một Instant Page theo từng trang dữ liệu. Đây là detail tool thuộc lane zalo-ads-content; dùng khi đã có instantPageId và cần kiểm tra các thay đổi trước đó, với limit và offset để duyệt danh sách. */\r\nexport type ZaloInstantPagesListInstantPageEditHistoryRequest = {\r\n /** ID nội bộ Instant Page cần xem lịch sử chỉnh sửa. */\r\n instantPageId: number;\r\n /** Số bản ghi lịch sử tối đa trong một trang; giá trị quan sát được là 10. */\r\n limit?: number;\r\n /** Vị trí bắt đầu của trang lịch sử, tính từ 0. */\r\n offset?: number;\r\n};\r\n\r\nexport type ZaloInstantPagesListInstantPageEditHistoryResponse = {\r\n /** Trang dữ liệu lịch sử chỉnh sửa. */\r\n data: {\r\n /** Các bản ghi chỉnh sửa trong trang hiện tại. */\r\n items: Array<{\r\n /** Mã loại thao tác lịch sử. API quan sát trả về 1; ý nghĩa các mã khác chưa được xác minh. */\r\n action: number;\r\n /** ID Instant Page được chỉnh sửa. */\r\n pageId: number;\r\n /** ID người dùng thực hiện thao tác. */\r\n userId: number;\r\n /** Thời điểm tạo bản ghi, Unix timestamp theo giây. */\r\n created: number;\r\n /** Tên hiển thị của người dùng thực hiện thao tác. */\r\n userName: string;\r\n }>;\r\n metadata: {\r\n /** Giới hạn bản ghi của trang đã trả về. */\r\n limit: number;\r\n /** Tổng số bản ghi lịch sử. */\r\n total: number;\r\n /** Vị trí bắt đầu của trang đã trả về. */\r\n offset: number;\r\n };\r\n };\r\n};\r\n\r\n/** Lấy danh sách bản ghi gửi form của một Instant Page. Đây là detail tool thuộc lane zalo-ads-content; dùng khi cần xem dữ liệu khách hàng đã gửi từ form gắn với trang cụ thể. */\r\nexport type ZaloInstantPagesListInstantPageFormRecordsRequest = {\r\n /** ID Instant Page có form cần lấy bản ghi gửi. */\r\n instantPageId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesFormRecordItem = {\r\n id: string;\r\n pageId: number;\r\n userId?: string;\r\n userName?: string;\r\n phone?: string;\r\n created: number;\r\n answers: Array<{\r\n questionId: string;\r\n title: string;\r\n value: string;\r\n }>;\r\n};\r\n\r\nexport type ZaloInstantPagesListInstantPageFormRecordsResponse =\r\n | Blob\r\n | {\r\n data: {\r\n items: Array<ZaloInstantPagesFormRecordItem>;\r\n total: number;\r\n };\r\n };\r\n\r\n/** Lấy danh sách người dùng được chia sẻ quyền truy cập một Instant Page, gồm quyền trên trang và quyền Official Account. Đây là detail tool thuộc lane zalo-ads-content; dùng để kiểm tra quyền cộng tác trước khi chia sẻ, chỉnh sửa hoặc thu hồi quyền. Mỗi phần tử xác định người dùng bằng userId và thông tin hiển thị. */\r\nexport type ZaloInstantPagesListInstantPageSharesRequest = {\r\n /** ID Instant Page cần xem người dùng được chia sẻ quyền. */\r\n instantPageId: number;\r\n};\r\n\r\nexport type ZaloInstantPagesListInstantPageSharesResponse = {\r\n /** Danh sách người dùng được chia sẻ quyền trên Instant Page. */\r\n data: Array<{\r\n /** Tên hiển thị của người dùng. */\r\n name: string;\r\n /** Tên tệp hoặc URL ảnh đại diện của người dùng. */\r\n avatar: string;\r\n /** ID người dùng được chia sẻ quyền. */\r\n userId: number;\r\n /** Mã quyền của người dùng trên Instant Page; ý nghĩa chi tiết phụ thuộc quy ước phân quyền Zalo Ads. */\r\n permission: number;\r\n /** Mã quyền của người dùng trên Official Account liên kết; ý nghĩa chi tiết phụ thuộc quy ước Zalo Ads. */\r\n oaPermission: number;\r\n}>;\r\n};\r\n\r\n/**\r\n * Danh mục mã phân quyền người dùng được chia sẻ trên Instant Page (POST /api/instant-pages/{instantPageId}/shares):\r\n * - ADMIN (1): Quản trị viên (Toàn quyền quản trị, phân quyền thành viên, gắn quảng cáo, xuất bản trang).\r\n * - UPDATE_PAGE (2): Chỉnh sửa trang (Quyền chỉnh sửa nội dung giao diện trang).\r\n * - DOWNLOAD_INFO (3): Tải thông tin khách hàng (Quyền tải file lead/đơn hàng).\r\n * - READ_ONLY (4): Chỉ xem (Chỉ xem trước trang và báo cáo).\r\n */\r\nexport const ZaloInstantPageSharePermission = {\r\n /** Quản trị viên: Toàn quyền quản trị, chỉnh sửa, phân quyền và gắn quảng cáo. */\r\n ADMIN: 1,\r\n /** Biên tập viên: Quyền chỉnh sửa nội dung trang. */\r\n UPDATE_PAGE: 2,\r\n /** Tải dữ liệu: Quyền tải thông tin khách hàng / Leads. */\r\n DOWNLOAD_INFO: 3,\r\n /** Chỉ xem: Quyền xem trước và thống kê. */\r\n READ_ONLY: 4,\r\n} as const;\r\n\r\nexport type ZaloInstantPageSharePermissionValue = typeof ZaloInstantPageSharePermission[keyof typeof ZaloInstantPageSharePermission];\r\n\r\n/** Thông tin phân quyền cho một thành viên trên Instant Page. */\r\nexport type ZaloInstantPagesShareMemberDto = {\r\n /** ID người dùng được phân quyền (ví dụ: 2394323333639486). */\r\n userId: number;\r\n /** Mã phân quyền: 1 (ADMIN), 2 (UPDATE_PAGE), 3 (DOWNLOAD_INFO), 4 (READ_ONLY). */\r\n permission: ZaloInstantPageSharePermissionValue | number;\r\n};\r\n\r\n/** Cập nhật danh sách người dùng được phân quyền / chia sẻ trên Instant Page (`POST /api/instant-pages/{instantPageId}/shares`). */\r\nexport type ZaloInstantPagesUpdateInstantPageSharesRequest = {\r\n /** ID Instant Page cần phân quyền chia sẻ. */\r\n instantPageId: number;\r\n /** Danh sách thành viên và mã quyền tương ứng. Body HTTP là JSON Array: `[{ userId, permission }]`. */\r\n shares: Array<ZaloInstantPagesShareMemberDto>;\r\n};\r\n\r\nexport type ZaloInstantPagesUpdateInstantPageSharesResponse = {\r\n /** Danh sách thành viên được chia sẻ sau khi cập nhật. */\r\n data?: Array<{\r\n userId: number;\r\n permission: number;\r\n name?: string;\r\n avatar?: string;\r\n oaPermission?: number;\r\n }>;\r\n code?: number;\r\n msg?: string;\r\n};\r\n\r\n/** Lấy các danh sách người dùng có thể dùng trong Instant Page, gồm chủ sở hữu, người tạo và người được chia sẻ. Đây là entry tool thuộc lane zalo-ads-content; dùng để chọn hoặc đối chiếu người dùng trước khi lọc, chia sẻ hay kiểm tra quyền trên Instant Page cụ thể. Khác với tool shares của một trang, kết quả này là danh mục người dùng theo vai trò trên phạm vi Instant Page. */\r\nexport type ZaloInstantPagesListInstantPageUsersRequest = Record<string, never>;\r\n\r\nexport type ZaloInstantPagesListInstantPageUsersResponse = {\r\n data: {\r\n /** Danh sách chủ sở hữu Instant Page. */\r\n owners: Array<{\r\n /** ID người dùng. */\r\n id: number;\r\n /** Tên hiển thị người dùng; có thể là nhãn hệ thống khi chưa có người được chia sẻ. */\r\n name: string;\r\n}>;\r\n /** Danh sách người dùng được chia sẻ hoặc nhãn trạng thái chia sẻ. */\r\n shares: Array<{\r\n /** ID người dùng. */\r\n id: number;\r\n /** Tên hiển thị người dùng; có thể là nhãn hệ thống khi chưa có người được chia sẻ. */\r\n name: string;\r\n}>;\r\n /** Danh sách người tạo Instant Page. */\r\n creators: Array<{\r\n /** ID người dùng. */\r\n id: number;\r\n /** Tên hiển thị người dùng; có thể là nhãn hệ thống khi chưa có người được chia sẻ. */\r\n name: string;\r\n}>;\r\n};\r\n};\r\n\r\n/** Lấy danh sách template mini page, gồm tên, mô tả, thumbnail, preview và nội dung cấu hình. Đây là entry tool thuộc lane zalo-ads-content; dùng khi chọn template trước khi tạo hoặc cấu hình mini page. */\r\nexport type ZaloInstantPagesListMiniPageTemplatesRequest = Record<string, never>;\r\n\r\nexport type ZaloInstantPagesListMiniPageTemplatesResponse = {\r\n data: Array<{\r\n id: number;\r\n name: string;\r\n /** Nội dung cấu hình template dạng chuỗi. */\r\n content: string;\r\n preview: string;\r\n thumbnail: string;\r\n description: string;\r\n}>;\r\n};\r\n\r\n/** Lấy danh sách Instant Page mà tài khoản hiện tại có quyền truy cập, với bộ lọc tên, ID hoặc nhóm nội dung. Đây là entry tool thuộc lane zalo-ads-content; dùng để tìm instantPageId trước khi xem chi tiết, quản lý quyền, xem lịch sử hoặc cập nhật trạng thái. */\r\nexport type ZaloInstantPagesSearchInstantPagesRequest = {\r\n /** ID Instant Page cần tìm chính xác; bỏ qua để không lọc theo ID. */\r\n id?: number;\r\n /** Từ khóa tìm trong tên Instant Page; bỏ qua để không lọc tên. */\r\n name?: string;\r\n /** Nhóm nội dung: 1 là Trang sản phẩm, 2 là Kịch bản tin nhắn; bỏ qua để lấy tất cả. */\r\n group?: 1 | 2;\r\n};\r\n\r\nexport type ZaloInstantPagesSearchInstantPagesResponse = {\r\n data: Array<{\r\n /** ID nội bộ Instant Page; dùng cho các API chi tiết, cập nhật, quyền và lịch sử. */\r\n id: number;\r\n /** Tên Instant Page. */\r\n name: string;\r\n /** ID Official Account liên kết; có thể rỗng. */\r\n oaId: string;\r\n /** Tên hiển thị chủ sở hữu. */\r\n owner: string;\r\n /** Trạng thái bật/tắt: 0 = Tắt, 1 = Bật. */\r\n active: ZaloInstantPageActive;\r\n /** ID form liên kết; có thể rỗng. */\r\n formId: string;\r\n /** Tên các người dùng được chia sẻ quyền. */\r\n shares: Array<string>;\r\n /** Mã trạng thái: 0 = Bản sao mới tạo, 1 = Bản nháp, 2 = Đã xuất bản, 3 = Lưu trữ. */\r\n status: ZaloInstantPageStatus | number;\r\n /** Unix timestamp theo giây lúc tạo. */\r\n created: number;\r\n /** Tên hiển thị người tạo. */\r\n creator: string;\r\n /** ID chủ sở hữu. */\r\n ownerId: number;\r\n /** Unix timestamp theo giây lúc cập nhật. */\r\n modified: number;\r\n /** Mã công khai 12 ký tự của Instant Page (dùng trên https://page.zalo.me/p/{publicId}). */\r\n publicId: string;\r\n /** Unix timestamp theo giây lúc xuất bản (0 nếu chưa xuất bản). */\r\n published: number;\r\n /** Quyền trực tiếp trên Instant Page khi API trả về. */\r\n permission?: number;\r\n /** ID template tạo Page. */\r\n templateId: number;\r\n /** Quyền trên OA khi API trả về. */\r\n oaPermission?: number;\r\n [key: string]: unknown;\r\n}>;\r\n [key: string]: unknown;\r\n};\r\n\r\n/**\r\n * Cập nhật thông tin, cấu hình bản nháp (draft), nội dung chính thức (content) hoặc bật/tắt trạng thái (active) của Instant Page theo ID.\r\n *\r\n * Hỗ trợ 4 loại thao tác nghiệp vụ:\r\n * - **Loại 1 (Bật/Tắt nhanh)**: `{ id, active: 0 | 1 }` (0: Tắt, 1: Bật)\r\n * - **Loại 2 (Đổi tên / Đổi OA)**: `{ id, name?: string, oaId?: string }`\r\n * - **Loại 3 (Lưu bản nháp - Save Draft)**: `{ id, name?: string, status: 1, draft: string }`\r\n * - **Loại 4 (Xuất bản - Publish Live)**: `{ id, name?: string, status: 2, draft: string, content: string }`\r\n */\r\nexport type ZaloInstantPagesUpdateInstantPageRequest = {\r\n /** ID Instant Page cần cập nhật. */\r\n instantPageId: number;\r\n /** ID Instant Page trong payload; bắt buộc và phải trùng path_param.instantPageId. */\r\n id: number;\r\n /** Tên Instant Page mới; giao diện giới hạn tối đa 40 ký tự. Chỉ gửi khi cần đổi tên. */\r\n name?: string;\r\n /** ID Official Account liên kết; truyền chuỗi rỗng \"\" nếu trang chưa liên kết OA hoặc không dùng OA. */\r\n oaId?: string;\r\n /**\r\n * Chuỗi JSON bản nháp cấu hình Instant Page đang biên tập trên Canvas Editor (chưa xuất bản).\r\n * Gồm renderList (mảng ID thứ tự hiển thị), data (map ID -> block object), freezedTop, freezedBottom, version.\r\n * Danh mục block types:\r\n * 1: CAROUSEL_SLIDER | 2: COUNTDOWN | 4: RICH_TEXT | 6: HERO_IMAGE | 7: FORM_NAME |\r\n * 8: ORDER_CTA_BUTTON | 9: FORM_PHONE | 10: FORM_ADDRESS | 14: FOOTER | 16: FORM_QUANTITY |\r\n * 18: PRODUCT_VARIANT | 19: PRODUCT_TITLE_PRICE | 20: QUICK_QUESTIONS | 21: MESSAGE_CTA_BUTTON |\r\n * 22: SECTION_HEADING | 23: CALL_HOTLINE_BUTTON | 25: KEY_VALUE_TABLE | 27: CONSENT_NOTICE\r\n */\r\n draft?: string | InstantPageCanvas;\r\n /** Thao tác bật/tắt Instant Page: 0 là tắt, 1 là bật. BẮT BUỘC là số nguyên 0 | 1, không truyền kiểu boolean. */\r\n active?: ZaloInstantPageActive;\r\n /** Mã trạng thái của Instant Page: 1 = Lưu bản nháp (Draft), 2 = Xuất bản chính thức (Published). */\r\n status?: ZaloInstantPageStatus | number;\r\n /**\r\n * Chuỗi JSON cấu hình nội dung chính thức đang chạy ở Production của Instant Page (sau khi xuất bản).\r\n * Chỉ gửi khi xuất bản chính thức (status = 2). Cấu trúc tương tự draft.\r\n */\r\n content?: string | InstantPageCanvas;\r\n};\r\n\r\nexport type ZaloInstantPagesUpdateInstantPageResponse = {\r\n /** Thông điệp kết quả nếu API trả envelope có msg. */\r\n msg?: string;\r\n /** Mã kết quả nếu API trả envelope có code. */\r\n code?: number;\r\n /** Dữ liệu Instant Page hoặc kết quả cập nhật nếu API trả trong data. */\r\n data?: unknown;\r\n [key: string]: unknown;\r\n};\r\n\r\n/** Lấy thống kê tổng số lượt gửi form (totalSubmit) và thời gian gửi gần nhất (lastSubmitTime) theo danh sách các Instant Page ID (ids). */\r\nexport type ZaloInstantPagesListInstantPageLeadsRequest = {\r\n /** Danh sách ID của các trang Instant Page phân tách bằng dấu phẩy (ví dụ: \"81433,76292\"). */\r\n ids: string;\r\n};\r\n\r\nexport type ZaloInstantPagesListInstantPageLeadsResponse = {\r\n data: Array<{\r\n /** ID trang Instant Page. */\r\n id: number;\r\n /** Tổng số lượt khách hàng điền form trên trang Instant Page. */\r\n totalSubmit: number;\r\n /** Thời điểm điền form gần nhất (Unix timestamp theo giây, hoặc 0 nếu chưa có). */\r\n lastSubmitTime: number;\r\n [key: string]: unknown;\r\n }>;\r\n [key: string]: unknown;\r\n};\r\n\r\n/** Lấy danh sách Zalo Official Accounts (OA) khả dụng trên hệ thống Instant Pages (page.ads.zalo.me). */\r\nexport type ZaloInstantPagesListOfficialAccountsRequest = Record<string, never>;\r\n\r\nexport type ZaloInstantPagesOfficialAccountItem = {\r\n id: string;\r\n name: string;\r\n avatar: string;\r\n status: number;\r\n type: number;\r\n createdTime: number;\r\n config?: Record<string, unknown>;\r\n roles?: number[];\r\n [key: string]: unknown;\r\n};\r\n\r\nexport type ZaloInstantPagesListOfficialAccountsResponse = {\r\n data: ZaloInstantPagesOfficialAccountItem[];\r\n [key: string]: unknown;\r\n};\r\n\r\n/** Cấu hình hoặc cập nhật biểu mẫu thu thập thông tin và đặt hàng gắn liền với một Instant Page, bao gồm danh sách câu hỏi, lựa chọn trả lời và điều khoản bảo vệ dữ liệu cá nhân. Đây là mutation tool thuộc lane zalo-ads-content. Dùng khi đã có instantPageId cùng oaId và cần lưu cấu trúc câu hỏi biểu mẫu trước khi gắn ID câu hỏi vào block nội dung của Instant Page. */\r\nexport type ZaloInstantPagesUpsertInstantPageFormRequest = {\r\n /** ID nội bộ của Instant Page cần cấu hình biểu mẫu (lấy từ công cụ tìm kiếm, chi tiết hoặc sao chép Instant Page). */\r\n instantPageId: number;\r\n /** ID Zalo Official Account liên kết với biểu mẫu của Instant Page (chuỗi số định danh dài). */\r\n oaId: string;\r\n /** Tên biểu mẫu gắn với Instant Page (ví dụ: 'Trang sản phẩm - 14/10/2026 18:51'). */\r\n formName: string;\r\n /** Danh sách các câu hỏi và trường thông tin trong biểu mẫu của Instant Page. */\r\n questions: Array<{\r\n /** Mã định danh câu hỏi (tùy chọn khi cập nhật câu hỏi đã tồn tại). */\r\n id?: string;\r\n /** Loại câu hỏi: 1 là câu hỏi nhập liệu (số lượng, họ tên, số điện thoại, địa chỉ), 2 là câu hỏi lựa chọn phương án (phiên bản, kích thước, combo). */\r\n type: 1 | 2 | number;\r\n /** Tiêu đề câu hỏi hiển thị trên biểu mẫu. */\r\n title: string;\r\n /** Danh sách các phương án lựa chọn hoặc cấu hình ô nhập liệu của câu hỏi. */\r\n answers: Array<{\r\n /** Mã định danh phương án trả lời (tùy chọn khi cập nhật phương án đã tồn tại). */\r\n id?: string;\r\n /** Loại ô trả lời: 1 là lựa chọn cố định (option), 5 là số lượng, 7 là họ và tên, 13 là số điện thoại, 15 là địa chỉ. */\r\n type: 1 | 5 | 7 | 13 | 15 | number;\r\n /** Giá trị phương án trả lời (dùng cho câu hỏi lựa chọn type=2, để chuỗi rỗng với ô nhập liệu). */\r\n value?: string;\r\n /** Thứ tự ưu tiên của phương án trả lời (bắt đầu từ 0). */\r\n priority: number;\r\n /** Văn bản gợi ý trong ô nhập liệu (dùng cho họ tên, số điện thoại, địa chỉ). */\r\n placeHolder?: string;\r\n }>;\r\n /** Trạng thái vô hiệu hóa câu hỏi (false là đang kích hoạt). */\r\n disable: boolean;\r\n /** Thứ tự ưu tiên hiển thị của câu hỏi (bắt đầu từ 0). */\r\n priority: number;\r\n /** Bắt buộc người dùng trả lời câu hỏi này hay không. */\r\n isRequired: boolean;\r\n /** Mô tả phụ của câu hỏi (có thể để chuỗi rỗng). */\r\n description: string;\r\n }>;\r\n /** Sử dụng cấu hình điều khoản đồng ý tùy chỉnh hay mặc định (mặc định: false). */\r\n useCustomConsent?: boolean;\r\n /** Cấu hình thông tin pháp lý và phạm vi thu thập dữ liệu cá nhân của biểu mẫu (bắt buộc khi useCustomConsent = true). */\r\n consentConfig?: {\r\n /** Địa chỉ liên hệ của bên kiểm soát hoặc sở hữu dữ liệu. */\r\n address: string;\r\n /** Tên cá nhân hoặc đơn vị sở hữu dữ liệu. */\r\n ownerName: string;\r\n /** Email liên hệ của bên kiểm soát hoặc sở hữu dữ liệu. */\r\n ownerEmail: string;\r\n /** Số điện thoại liên hệ của bên sở hữu dữ liệu (ví dụ: '84977682707'). */\r\n ownerPhone: string;\r\n /** Danh sách mã loại dữ liệu cá nhân cơ bản thu thập (ví dụ: [0,1,2,3,4,5]). */\r\n regularDataTypes: Array<number>;\r\n /** Danh sách mã mục đích xử lý dữ liệu (ví dụ: [0,1,2,3]). */\r\n dataUsagePurposes: Array<number>;\r\n /** Danh sách mã loại dữ liệu cá nhân nhạy cảm thu thập (ví dụ: [0,1]). */\r\n sensitiveDataTypes: Array<number>;\r\n };\r\n};\r\n\r\nexport type ZaloInstantPagesUpsertInstantPageFormResponse = {\r\n /** Danh sách câu hỏi và phương án trả lời của biểu mẫu Instant Page sau khi đã lưu kèm mã định danh (id) do hệ thống sinh ra. */\r\n data: Array<{\r\n /** Mã định danh câu hỏi do hệ thống sinh ra (ví dụ: '6VUZYGPQ66KYVG796M'), dùng để gắn vào cấu hình block form của Instant Page. */\r\n id: string;\r\n /** Loại câu hỏi (1: nhập liệu, 2: lựa chọn). */\r\n type: number;\r\n /** Tiêu đề câu hỏi. */\r\n title: string;\r\n /** Danh sách phương án trả lời hoặc ô nhập liệu của câu hỏi. */\r\n answers: Array<{\r\n /** Mã định danh phương án trả lời do hệ thống sinh ra (ví dụ: 'ERUR9ZVA9ZAQ8RQEQ'). */\r\n id: string;\r\n /** Loại ô trả lời (1: lựa chọn, 5: số lượng, 7: họ tên, 13: số điện thoại, 15: địa chỉ). */\r\n type: number;\r\n /** Giá trị của phương án lựa chọn. */\r\n value?: string;\r\n /** Thứ tự hiển thị của phương án trả lời (bắt đầu từ 0). */\r\n priority: number;\r\n /** Văn bản gợi ý hiển thị trong ô nhập liệu. */\r\n placeHolder?: string;\r\n [key: string]: unknown;\r\n }>;\r\n /** Trạng thái vô hiệu hóa câu hỏi. */\r\n disable: boolean;\r\n /** Thứ tự hiển thị của câu hỏi trên biểu mẫu. */\r\n priority: number;\r\n /** Cờ bắt buộc trả lời câu hỏi. */\r\n isRequired: boolean;\r\n /** Mô tả phụ của câu hỏi. */\r\n description: string;\r\n [key: string]: unknown;\r\n }>;\r\n [key: string]: unknown;\r\n};\r\n\r\n/**\r\n * Khởi tạo một Instant Page mới từ Template mẫu trên domain page.ads.zalo.me.\r\n * \r\n * Bẫy kỹ thuật & nghiệp vụ:\r\n * - templateId = 4: Kịch bản giới thiệu thương hiệu / Tin nhắn (bắt buộc dùng cho Quảng cáo Tin nhắn Type 30).\r\n * - oaId: Bắt buộc là chuỗi ID 64-bit của Official Account (ví dụ: '4411301888544366414' từ GET /api/official-accounts), KHÔNG dùng ID số nguyên ngắn.\r\n * - Sau khi tạo, Instant Page ở trạng thái nháp (status: 0). Cần gọi updateInstantPage với status: 1 (truyền đồng thời cả draft và content) để xuất bản Live.\r\n */\r\nexport type ZaloInstantPagesCreateInstantPageRequest = {\r\n /** Mã mẫu giao diện: 1 (Trang bán sản phẩm form trực tiếp), 3 (Trang bán sản phẩm form popup), 4 (Kịch bản tin nhắn), 5 (Trang đệm mua sắm). */\r\n templateId: 1 | 3 | 4 | 5 | number;\r\n /** Mã định danh 64-bit của Official Account liên kết (Lấy từ GET /api/official-accounts). */\r\n oaId?: string;\r\n};\r\n\r\nexport type ZaloInstantPagesCreateInstantPageResponse = {\r\n /** Bản ghi Instant Page mới được khởi tạo từ template. */\r\n data: {\r\n /** Mã số định danh nội bộ của Instant Page mới được cấp phát. */\r\n id: number;\r\n /** Mã public dùng cho URL người dùng cuối (https://page.zalo.me/p/{publicId}). */\r\n publicId: string;\r\n /** Tên mặc định của Instant Page theo template. */\r\n name: string;\r\n /** Cờ hoạt động: 0 = Tắt, 1 = Bật. */\r\n active: ZaloInstantPageActive | number;\r\n /** Mã trạng thái: 0 = Nháp mới tạo, 1 = Đã xuất bản Live. */\r\n status: ZaloInstantPageStatus | number;\r\n /** Phiên bản cấu trúc trang. */\r\n version: number;\r\n /** Mã mẫu giao diện đã dùng để khởi tạo. */\r\n templateId: number;\r\n /** Mã định danh 64-bit của Official Account liên kết. */\r\n oaId?: string;\r\n [key: string]: unknown;\r\n };\r\n [key: string]: unknown;\r\n};\r\n","/**\n * Factory tiện ích khởi tạo cấu trúc Instant Page Canvas hợp lệ cho Zalo Ads.\n * Tự động nạp sẵn (hydrate) các giá trị mặc định chuẩn chỉnh (thương hiệu, logo, hình ảnh, văn bản Quill),\n * đảm bảo 100% trang đích khi tạo không bao giờ bị lỗi viền đỏ (data-section-error=\"true\")\n * hay lỗi crash React khi mở trên domain page.ads.zalo.me.\n */\nimport type { InstantPageCanvas, ZaloMediaImage } from \"../dtos/instant-pages.dto\";\n\nexport interface HydrateInstantPageOptions {\n /** Tên thương hiệu / Shop (từ 2 - 30 ký tự) */\n brandName?: string;\n /** URL ảnh logo thương hiệu (kích thước tối thiểu 150x150) */\n brandLogoUrl?: string;\n /** Tên sản phẩm / dịch vụ chính */\n productName?: string;\n /** Giá bán sản phẩm (VND) */\n price?: number;\n /** Giá niêm yết / giá gốc (VND) */\n rawPrice?: number;\n /** Đoạn mô tả giới thiệu chi tiết sản phẩm / dịch vụ */\n description?: string;\n /** Danh sách URL ảnh sản phẩm trình chiếu Carousel (tối thiểu 1 ảnh) */\n carouselImages?: Array<{ url: string; name?: string }>;\n /** Tin nhắn mẫu gửi tới Zalo Official Account */\n defaultMessage?: string;\n /** Số hotline liên hệ */\n hotline?: string;\n /** Địa chỉ doanh nghiệp */\n address?: string;\n}\n\nexport class InstantPageFactory {\n /**\n * Khởi tạo Canvas hoàn chỉnh từ Template ID (1, 3, 4, 5) được điền sẵn dữ liệu hợp lệ.\n */\n static createFromTemplate(\n templateId: 1 | 3 | 4 | 5 | number,\n options: HydrateInstantPageOptions = {}\n ): InstantPageCanvas {\n const brandName = options.brandName || \"RedAI Official Store\";\n const brandLogoUrl =\n options.brandLogoUrl ||\n \"https://adtima-media.zascdn.me/2023/10/58117541-e206-4f9d-b4cf-69e50f963288.svg\";\n const productName = options.productName || \"Sản phẩm / Dịch vụ Đột phá 2026\";\n const price = options.price ?? 299000;\n const rawPrice = options.rawPrice ?? 499000;\n const defaultMsg =\n options.defaultMessage ||\n \"Tôi muốn tìm hiểu thêm về sản phẩm này\";\n\n const defaultImages = [\n \"https://adtima-media.zascdn.me/2023/06/84cba4c9-be13-425a-8daa-40e695ca9805.jpg\",\n \"https://adtima-media.zascdn.me/2023/06/805587cd-4699-47e6-a9bb-3cbbb4039b40.jpg\",\n \"https://adtima-media.zascdn.me/2023/06/aca98d2c-1739-4f03-a366-43a6d6c4ef53.jpg\",\n \"https://adtima-media.zascdn.me/2023/06/8cc5692b-2899-4862-9957-d3f66e8778cd.jpg\",\n ];\n\n switch (templateId) {\n case 5: {\n // Template 5: Trang đệm mua sắm TMĐT (Shopping Ad Bridge)\n const carouselImgs =\n options.carouselImages && options.carouselImages.length > 0\n ? options.carouselImages\n : defaultImages.map((url, i) => ({ url, name: `image-${i + 1}.jpg` }));\n\n const indexes = carouselImgs.map((_, i) => String(i));\n const imagesMap: Record<string, ZaloMediaImage> = {};\n carouselImgs.forEach((img, i) => {\n imagesMap[String(i)] = {\n name: img.name || `image-${i + 1}.jpg`,\n url: img.url,\n };\n });\n\n const descText =\n options.description ||\n \"Hệ sinh thái công nghệ tự động hóa RedAI. Tích hợp đa kênh Zalo OA, Website & CRM; hỗ trợ tự động phản hồi và chốt đơn 24/7.\";\n\n return {\n version: 1,\n renderList: [\"1\", \"2\", \"3\", \"4\"],\n freezedBottom: 4,\n pageTitle: \"Chi tiết\",\n data: {\n \"1\": {\n id: \"-1\",\n type: 28,\n name: brandName,\n image: {\n name: \"logo.png\",\n url: brandLogoUrl,\n },\n },\n \"2\": {\n id: \"-1\",\n type: 29,\n delta: {\n ops: [\n { attributes: { bold: true, size: \"18px\" }, insert: `${brandName}\\n` },\n { insert: `\\n${descText}\\n` },\n ],\n },\n outputHtml: `<p><strong style=\"font-size: 18px;\">${brandName}</strong></p><p><br>${descText}</p>`,\n length: brandName.length + descText.length + 10,\n },\n \"3\": {\n id: \"-1\",\n type: 1,\n indexes,\n images: imagesMap,\n videos: {\n \"0\": { name: \"\", thumbnail: \"\", url: \"\" },\n },\n },\n \"4\": {\n id: \"-1\",\n type: 21,\n content: defaultMsg,\n marginTop: 0,\n marginBottom: 0,\n },\n },\n };\n }\n\n case 4: {\n // Template 4: Kịch bản giới thiệu thương hiệu / Tin nhắn\n return {\n version: 4,\n renderList: [\"1\", \"2\", \"3\"],\n freezedBottom: 3,\n data: {\n \"1\": {\n id: \"-1\",\n indexes: [\"0\", \"1\", \"2\"],\n images: {\n \"1\": { name: \"banner-1.jpg\", url: defaultImages[0] },\n \"2\": { name: \"banner-2.jpg\", url: defaultImages[1] },\n },\n textEditor: {\n delta: {\n ops: [\n { attributes: { bold: true }, insert: `Chào mừng bạn đến với ${brandName}` },\n { insert: \"\\n\\nBạn đang quan tâm giải pháp nào để chuyên viên hỗ trợ ngay?\\n\\n\" },\n ],\n },\n outputHtml: `<p><strong>Chào mừng bạn đến với ${brandName}</strong></p><p><br></p><p>Bạn đang quan tâm giải pháp nào để chuyên viên hỗ trợ ngay?</p>`,\n },\n type: 1,\n videos: {\n \"0\": { name: \"\", thumbnail: \"\", url: \"\" },\n },\n },\n \"2\": {\n rows: [{ id: 0, left: \"Ưu đãi trải nghiệm\", right: \"Dùng thử miễn phí\" }],\n type: 25,\n },\n \"3\": {\n list: [\n \"Tư vấn giải pháp tự động hóa\",\n \"Báo giá chi tiết gói doanh nghiệp\",\n \"Hỗ trợ kỹ thuật 24/7\",\n ],\n marginBottom: 16,\n marginTop: 0,\n type: 20,\n },\n },\n };\n }\n\n case 3:\n case 1:\n default: {\n // Template 1 & 3: Bán sản phẩm đặt hàng trực tiếp / pop-up\n return {\n version: \"1\",\n renderList: [\n \"0\", \"1\", \"2\", \"11\", \"16\", \"17\", \"18\", \"26\", \"3\", \"4\", \"5\", \"7\", \"8\", \"9\", \"12\", \"10\", \"27\"\n ],\n freezedTop: 3,\n freezedBottom: 10,\n data: {\n \"0\": {\n id: \"-1\",\n type: 1,\n indexes: [\"0\", \"1\", \"2\"],\n images: {\n \"0\": { name: \"prod-1.jpg\", url: defaultImages[0] },\n \"1\": { name: \"prod-2.jpg\", url: defaultImages[1] },\n \"2\": { name: \"prod-3.jpg\", url: defaultImages[2] },\n },\n videos: { \"5\": { name: \"\", thumbnail: \"\", url: \"\" } },\n },\n \"1\": {\n id: \"-1\",\n discountValue: 35,\n visible: true,\n countdownType: 4,\n type: 2,\n startDate: Date.now(),\n loopDays: 1,\n label: \"<p>Thời gian ưu đãi còn lại:</p>\",\n labelDelta: { ops: [{ insert: \"Thời gian ưu đãi còn lại:\\n\" }] },\n marginTop: 8,\n marginBottom: 0,\n visibility: { days: true, hours: true, minutes: true, seconds: true },\n },\n \"2\": {\n type: 19,\n name: productName,\n price,\n rawPrice,\n marginTop: 8,\n marginBottom: 8,\n },\n \"3\": {\n id: \"-1\",\n type: 18,\n visible: true,\n formQuestion: {\n type: 2,\n title: \"Phiên bản\",\n isRequired: true,\n disable: false,\n answers: [\n { type: 1, value: \"Bản Tiêu Chuẩn\", priority: 0 },\n { type: 1, value: \"Bản Cao Cấp\", priority: 1 },\n ],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"4\": {\n id: \"-1\",\n type: 18,\n visible: true,\n formQuestion: {\n type: 2,\n title: \"Gói dung lượng\",\n isRequired: true,\n disable: false,\n answers: [\n { type: 1, value: \"Gói 1 Tháng\", priority: 0 },\n { type: 1, value: \"Gói 1 Năm\", priority: 1 },\n ],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"5\": {\n id: \"-1\",\n type: 16,\n formQuestion: {\n type: 1,\n title: \"Số lượng\",\n isRequired: true,\n disable: false,\n answers: [{ type: 5, value: \"\", priority: 0 }],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"7\": {\n id: \"-1\",\n type: 7,\n formQuestion: {\n type: 1,\n title: \"Họ và tên\",\n isRequired: true,\n disable: false,\n answers: [{ type: 7, value: \"\", placeHolder: \"Nhập họ và tên của bạn\", priority: 0 }],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"8\": {\n id: \"-1\",\n type: 9,\n formQuestion: {\n type: 1,\n title: \"Số điện thoại\",\n isRequired: true,\n disable: false,\n answers: [{ type: 13, value: \"\", placeHolder: \"Nhập số điện thoại liên hệ\", priority: 0 }],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"9\": {\n id: \"-1\",\n type: 10,\n formQuestion: {\n type: 1,\n title: \"Địa chỉ\",\n isRequired: true,\n disable: false,\n answers: [{ type: 15, value: \"\", placeHolder: \"Nhập địa chỉ giao hàng hoặc nhận tư vấn\", priority: 0 }],\n description: \"\",\n priority: 0,\n },\n marginTop: 8,\n marginBottom: 8,\n },\n \"10\": {\n id: \"-1\",\n type: 8,\n background: \"#008FE5\",\n borderColor: \"#000000\",\n borderRadius: 4,\n borderSize: 1,\n showBorder: false,\n formPopup: templateId === 3,\n fixedPosition: true,\n image: {\n name: \"cart.svg\",\n url: \"https://adtima-media.zascdn.me/2023/10/58117541-e206-4f9d-b4cf-69e50f963288.svg\",\n },\n content2: \"Đặt hàng ngay\",\n },\n \"11\": {\n id: \"-1\",\n type: 4,\n delta: {\n ops: [\n { attributes: { color: \"#bf2600\", bold: true }, insert: \"ƯU ĐÃI ĐẶC BIỆT HÔM NAY\\n\" },\n { insert: `Trải nghiệm trọn bộ tính năng vượt trội của ${productName}.\\n` },\n ],\n },\n marginTop: 16,\n marginBottom: 16,\n outputHtml: `<p><strong style=\"color: rgb(191, 38, 0);\">ƯU ĐÃI ĐẶC BIỆT HÔM NAY</strong></p><p>Trải nghiệm trọn bộ tính năng vượt trội của ${productName}.</p>`,\n },\n \"12\": {\n id: \"-1\",\n type: 23,\n actionType: \"1\",\n content: \"Liên hệ Hotline\",\n borderColor: \"#008fe5\",\n borderRadius: 4,\n borderSize: 2,\n showBorder: true,\n fixedPosition: true,\n visible: true,\n phone: options.hotline || \"\",\n image: {\n name: \"phone.svg\",\n url: \"https://adtima-media.zascdn.me/2023/10/03d065a4-90b2-4deb-b684-5ff61407a47d.svg\",\n },\n color: \"#008fe5\",\n background: \"#ffffff\",\n marginTop: 16,\n marginBottom: 16,\n },\n \"16\": {\n id: \"-1\",\n type: 6,\n mediaType: \"image\",\n image: { url: defaultImages[0], name: \"hero-1.png\" },\n videoSetting: { autoPlay: true, loop: true },\n },\n \"17\": {\n id: \"-1\",\n type: 6,\n mediaType: \"image\",\n image: { url: defaultImages[1], name: \"hero-2.png\" },\n videoSetting: { autoPlay: true, loop: true },\n },\n \"18\": {\n id: \"-1\",\n type: 6,\n mediaType: \"image\",\n image: { url: defaultImages[2], name: \"hero-3.png\" },\n videoSetting: { autoPlay: true, loop: true },\n },\n \"26\": {\n id: \"-1\",\n type: 14,\n backgroundColor: \"#f2f3f3\",\n textDelta: { ops: [{ attributes: { size: \"18px\", bold: true }, insert: `${brandName}\\n` }] },\n textHtml: `<p><strong style=\"font-size: 18px;\">${brandName}</strong></p>`,\n detailings: [\n {\n image: {\n url: \"https://adtima-media.zascdn.me/2023/10/cba64b4d-0bd5-4504-8b6d-5f2d2562854a.png\",\n name: \"home.png\",\n },\n textDelta: { ops: [{ insert: `Địa chỉ: ${options.address || \"Hà Nội / TP.HCM\"}\\n` }] },\n textHtml: `<p>Địa chỉ: ${options.address || \"Hà Nội / TP.HCM\"}</p>`,\n },\n {\n image: {\n url: \"https://adtima-media.zascdn.me/2023/10/d538811f-9232-4ef0-a130-ea2b1dda05d2.png\",\n name: \"phone.png\",\n },\n textDelta: { ops: [{ insert: `Hotline: ${options.hotline || \"1900 xxxx\"}\\n` }] },\n textHtml: `<p>Hotline: ${options.hotline || \"1900 xxxx\"}</p>`,\n },\n ],\n },\n \"27\": {\n id: \"-1\",\n type: 27,\n useCustomConsent: false,\n },\n },\n };\n }\n }\n }\n}\n","/**\n * Bộ kiểm tra tính hợp lệ và chuẩn hóa tham số Quy tắc tự động (Automated Rules Validator) cho Zalo Ads.\n * Reverse-engineered và kiểm chứng trực tiếp từ Zalo Ads Web Frontend (chunk 183) & Backend API.\n */\n\nexport enum AutomatedRuleScopeEnum {\n Ads = 1, // Quảng cáo (Phạm vi duy nhất hiện được hỗ trợ)\n}\n\nexport enum AutomatedRuleActionTypeEnum {\n Resume = 1, // Tiếp tục chạy quảng cáo (Bật)\n Pause = 2, // Tạm dừng quảng cáo (Tắt)\n IncreaseByAmount = 3, // Tăng giá đấu thầu theo số tiền cố định (VNĐ)\n DecreaseByAmount = 4, // Giảm giá đấu thầu theo số tiền cố định (VNĐ)\n IncreaseByPercentage = 5, // Tăng giá đấu thầu theo %\n DecreaseByPercentage = 6, // Giảm giá đấu thầu theo %\n}\n\nexport enum AutomatedRuleFrequencyEnum {\n OneHour = 1, // Mỗi tiếng / lần sau lần thực thi trước (1 giờ)\n HalfDay = 12, // 12 giờ / lần sau lần thực thi trước (12 giờ)\n OneDay = 24, // Mỗi ngày / lần sau lần thực thi trước (24 giờ)\n OneWeek = 168, // Mỗi tuần / lần sau lần thực thi trước (168 giờ = 7 ngày)\n}\n\nexport enum AutomatedRuleConditionFieldEnum {\n Status = 1, // Trạng thái quảng cáo (Đang chạy / Tạm dừng)\n Impression = 11, // Lượt hiển thị (tối thiểu 500)\n Click = 16, // Lượt nhấn (tối thiểu 10)\n CTR = 9999, // CTR (%)\n Cost = 100001, // Đã chi tiêu (VNĐ - tối thiểu 49.999đ)\n}\n\nexport enum AutomatedRuleOperatorEnum {\n GreaterThan = 1, // Lớn hơn (>)\n LessThan = 2, // Nhỏ hơn (<)\n Between = 3, // Trong khoảng\n NotBetween = 4, // Không trong khoảng\n Include = 5, // Bao gồm\n Exclude = 6, // Không bao gồm\n}\n\nexport enum AutomatedRuleTimeRangeEnum {\n AllTime = 1, // Từ lúc bắt đầu tới hiện tại (Lifetime)\n AllTimeExcludeToday = 2, // Từ lúc bắt đầu tới hết hôm qua\n Today = 3, // Trong ngày hôm nay\n Yesterday = 4, // Trong ngày hôm qua\n Previous2Day = 1002, // 2 ngày trước tới hiện tại\n Previous3Day = 1003, // 3 ngày trước tới hiện tại\n Previous4Day = 1004, // 4 ngày trước tới hiện tại\n Previous5Day = 1005, // 5 ngày trước tới hiện tại\n Previous6Day = 1006, // 6 ngày trước tới hiện tại\n Previous7Day = 1007, // 7 ngày trước tới hiện tại\n Previous14Day = 1014, // 14 ngày trước tới hiện tại\n Previous21Day = 1021, // 21 ngày trước tới hiện tại\n Previous30Day = 1030, // 30 ngày trước tới hiện tại\n}\n\nexport interface AutomatedRuleValidationResult<T = any> {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n sanitizedData?: T;\n}\n\nexport class ZaloAutomatedRulesValidator {\n /**\n * Kiểm tra và chuẩn hóa payload tạo mới quy tắc tự động (`POST /api/automatedrules/create`)\n */\n public static validateCreateRule(payload: any): AutomatedRuleValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload || typeof payload !== 'object') {\n return { isValid: false, errors: ['Payload quy tắc tự động phải là một object.'], warnings };\n }\n\n // 1. Tên quy tắc (ruleName)\n const ruleName = String(payload.ruleName || '').trim();\n if (!ruleName) {\n errors.push('Tên quy tắc (ruleName) không được để trống.');\n } else if (ruleName.length > 100) {\n errors.push(`Tên quy tắc không được vượt quá 100 ký tự (hiện có ${ruleName.length} ký tự).`);\n }\n\n // 2. Phạm vi (scope)\n const scope = payload.scope !== undefined ? Number(payload.scope) : 1;\n if (scope !== 1) {\n errors.push('Zalo Ads hiện chỉ hỗ trợ scope: 1 (Áp dụng cho Quảng cáo).');\n }\n\n // 3. Hành động (action)\n if (!payload.action || typeof payload.action !== 'object') {\n errors.push('Thiếu cấu hình hành động (action).');\n } else {\n const act = payload.action;\n const actType = Number(act.type);\n if (![3, 4, 5, 6].includes(actType)) {\n if ([1, 2].includes(actType)) {\n errors.push(`Hành động ${actType === 1 ? 'Tiếp tục' : 'Tạm dừng'} quảng cáo (type: ${actType}) hiện chưa được backend Zalo Ads kích hoạt trong scope này.`);\n } else {\n errors.push(`Loại hành động không hợp lệ: ${act.type}. Chỉ hỗ trợ 3 (Tăng giá đ), 4 (Giảm giá đ), 5 (Tăng giá %), 6 (Giảm giá %).`);\n }\n }\n\n // Kiểm tra values\n if (!Array.isArray(act.values) || act.values.length === 0 || Number(act.values[0]) <= 0) {\n errors.push('Giá trị thay đổi giá thầu (action.values) phải là mảng chứa số dương > 0.');\n } else {\n const val = Number(act.values[0]);\n if ([5, 6].includes(actType) && (val < 1 || val > 100)) {\n errors.push(`Thay đổi theo % (type: ${actType}) yêu cầu giá trị trong khoảng từ 1% đến 100% (hiện là ${val}%).`);\n }\n }\n\n // Kiểm tra hạn mức (limit)\n if (act.limit !== undefined && Number(act.limit) <= 0) {\n errors.push('Hạn mức giá thầu (action.limit) nếu có phải là số tiền dương > 0 VNĐ.');\n }\n }\n\n // 4. Tần suất hành động (frequency)\n const frequency = payload.frequency !== undefined ? Number(payload.frequency) : 12;\n const actType = payload.action ? Number(payload.action.type) : 0;\n if ([3, 4, 5, 6].includes(actType)) {\n if (![1, 12, 24, 168].includes(frequency)) {\n errors.push(`Tần suất hành động cho điều chỉnh giá thầu phải thuộc [1 (1 giờ), 12 (12 giờ), 24 (1 ngày), 168 (1 tuần)]. Giá trị ${frequency} sẽ bị từ chối với lỗi \"Tần suất hành động không hợp lệ.\"`);\n }\n }\n\n // 5. Điều kiện chỉ số (conditions)\n if (!Array.isArray(payload.conditions) || payload.conditions.length === 0) {\n errors.push('Quy tắc tự động phải có ít nhất 1 điều kiện chỉ số (conditions).');\n } else {\n payload.conditions.forEach((c: any, idx: number) => {\n const f = Number(c.field);\n if (![1, 11, 16, 9999, 100001].includes(f)) {\n errors.push(`Điều kiện [${idx + 1}]: Chỉ số không hợp lệ (field: ${c.field}). Hỗ trợ: 1 (Status), 11 (Impression), 16 (Click), 9999 (CTR), 100001 (Cost).`);\n }\n const op = Number(c.operator);\n if (![1, 2, 3, 4, 5, 6].includes(op)) {\n errors.push(`Điều kiện [${idx + 1}]: Phép toán không hợp lệ (operator: ${c.operator}). Hỗ trợ 1 (>), 2 (<), 3 (between), 4 (not between), 5 (include), 6 (exclude).`);\n }\n if (!Array.isArray(c.values) || c.values.length === 0) {\n errors.push(`Điều kiện [${idx + 1}]: values phải là mảng giá trị ngưỡng.`);\n }\n if (f !== 1 && !c.timeRange) {\n warnings.push(`Điều kiện [${idx + 1}]: Thiếu timeRange, hệ thống sẽ mặc định là 1 (Lifetime).`);\n }\n });\n }\n\n const sanitizedData = {\n ruleName,\n scope: 1,\n action: {\n type: Number(payload.action?.type),\n field: 1,\n values: payload.action?.values?.map(Number) || [10],\n limit: payload.action?.limit !== undefined ? Number(payload.action.limit) : 1000000,\n },\n conditions: (payload.conditions || []).map((c: any) => ({\n field: Number(c.field),\n operator: Number(c.operator),\n values: c.values.map(Number),\n timeRange: c.timeRange !== undefined ? Number(c.timeRange) : 1,\n })),\n frequency,\n appliedIds: Array.isArray(payload.appliedIds) ? payload.appliedIds.map(Number) : [],\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n sanitizedData: errors.length === 0 ? sanitizedData : undefined,\n };\n }\n\n /**\n * Kiểm tra và chuẩn hóa payload cập nhật quy tắc tự động (`POST /api/ad/automatedrules/update`)\n */\n public static validateUpdateRule(payload: any): AutomatedRuleValidationResult {\n const base = this.validateCreateRule(payload);\n const errors = [...base.errors];\n const warnings = [...base.warnings];\n\n if (!payload.automatedRuleId || Number(payload.automatedRuleId) <= 0) {\n errors.unshift('ID quy tắc tự động (automatedRuleId) là bắt buộc khi cập nhật.');\n }\n\n const appliedItems = Array.isArray(payload.appliedItems)\n ? payload.appliedItems.map((item: any) => ({\n appliedId: Number(item.appliedId),\n mode: Number(item.mode) === -1 ? -1 : 1, // -1: Unapply, 1: Apply\n }))\n : [];\n\n const sanitizedData = base.sanitizedData\n ? {\n automatedRuleId: Number(payload.automatedRuleId),\n ...base.sanitizedData,\n appliedItems,\n }\n : undefined;\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n sanitizedData,\n };\n }\n}\n","/**\n * Bộ kiểm tra tính hợp lệ và chuẩn hóa tham số Sự kiện chuyển đổi & Zalo Pixel (Conversions Validator) cho Zalo Ads.\n * Reverse-engineered và kiểm chứng trực tiếp từ Zalo Ads Web Frontend (chunk 602, chunk 804) & Backend API.\n */\n\nexport enum ConversionLabelEnum {\n AddToCart = 2, // Thêm vào giỏ hàng\n CompleteRegistration = 4, // Hoàn tất đăng ký\n Contact = 5, // Liên hệ\n InitiateCheckout = 9, // Bắt đầu thanh toán\n Lead = 10, // Trở thành khách hàng tiềm năng\n Purchase = 11, // Hoàn tất mua hàng\n Other = 19, // Khác\n}\n\nexport enum ConversionUrlTypeEnum {\n Exact = 0, // URL chính xác\n Contains = 1, // URL chứa từ khóa / đường dẫn tương đối\n}\n\nexport interface ConversionValidationResult<T = any> {\n isValid: boolean;\n errors: string[];\n warnings: string[];\n sanitizedData?: T;\n}\n\nexport class ZaloConversionsValidator {\n /**\n * Danh mục 7 nhãn chuẩn được Zalo Ads hỗ trợ chính thức\n */\n public static readonly SUPPORTED_LABELS: Record<number, string> = {\n [ConversionLabelEnum.Lead]: 'Trở thành khách hàng tiềm năng',\n [ConversionLabelEnum.Purchase]: 'Hoàn tất mua hàng',\n [ConversionLabelEnum.Contact]: 'Liên hệ',\n [ConversionLabelEnum.CompleteRegistration]: 'Hoàn tất đăng ký',\n [ConversionLabelEnum.InitiateCheckout]: 'Bắt đầu thanh toán',\n [ConversionLabelEnum.AddToCart]: 'Thêm vào giỏ hàng',\n [ConversionLabelEnum.Other]: 'Khác',\n };\n\n /**\n * Kiểm tra và chuẩn hóa payload tạo mới Conversion (`POST /api/conversion/add`)\n */\n public static validateCreateConversion(payload: any): ConversionValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!payload || typeof payload !== 'object') {\n return { isValid: false, errors: ['Payload conversion phải là một object.'], warnings };\n }\n\n // 1. Tên conversion (name)\n const name = String(payload.name || '').trim();\n if (!name) {\n errors.push('Tên conversion (name) không được để trống.');\n } else if (name.length > 180) {\n errors.push(`Tên conversion không được vượt quá 180 ký tự (hiện có ${name.length} ký tự).`);\n }\n\n // 2. Trang đích (landingPage)\n const landingPage = String(payload.landingPage || '').trim();\n if (!landingPage) {\n errors.push('Trang đích (landingPage) không được để trống.');\n } else {\n const urlPattern = /^https?:\\/\\/.+/i;\n if (!urlPattern.test(landingPage)) {\n errors.push('Trang đích (landingPage) phải là một URL hợp lệ bắt đầu bằng http:// hoặc https:// (ví dụ: https://redai.vn).');\n }\n }\n\n // 3. Loại URL (urlType)\n const urlType = payload.urlType !== undefined ? Number(payload.urlType) : 1;\n if (![0, 1].includes(urlType)) {\n errors.push(`Loại URL không hợp lệ: ${payload.urlType}. Chỉ hỗ trợ 0 (Exact URL) hoặc 1 (Contains keywords).`);\n }\n\n // 4. Nhãn sự kiện (labelId)\n const labelId = payload.labelId !== undefined ? Number(payload.labelId) : 10;\n if (!Object.keys(this.SUPPORTED_LABELS).map(Number).includes(labelId)) {\n errors.push(`Nhãn conversion không hợp lệ (labelId: ${payload.labelId}). Zalo Ads chỉ hỗ trợ: 10 (Lead), 11 (Purchase), 5 (Contact), 4 (Registration), 9 (Checkout), 2 (AddToCart), 19 (Other).`);\n }\n\n // 5. Cơ chế kích hoạt sự kiện (Tối thiểu 1 trong: keywords, buttonIds, elements)\n const buttonIds: string[] = Array.isArray(payload.buttonIds) ? payload.buttonIds.map(String).map((s: string) => s.trim()).filter((s: string) => Boolean(s)) : [];\n const elements: any[] = Array.isArray(payload.elements) ? payload.elements : [];\n const keywords: string[] = Array.isArray(payload.keywords) ? payload.keywords.map(String).map((s: string) => s.trim()).filter((s: string) => Boolean(s)) : [];\n\n if (buttonIds.length === 0 && elements.length === 0 && keywords.length === 0) {\n errors.push('Conversion bắt buộc phải có ít nhất 1 cơ chế nhận diện sự kiện: URL chứa từ khóa (keywords), ID nút bấm (buttonIds), hoặc phần tử giao diện (elements).');\n }\n\n // Sanitize elements\n const sanitizedElements = elements.map(el => {\n if (typeof el === 'object' && Array.isArray(el.class)) {\n return { class: el.class.map(String).map((s: string) => s.trim()).filter((s: string) => Boolean(s)) };\n }\n return el;\n });\n\n const sanitizedData = {\n name,\n landingPage,\n urlType,\n labelId,\n buttonIds,\n elements: sanitizedElements,\n keywords,\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n warnings,\n sanitizedData: errors.length === 0 ? sanitizedData : undefined,\n };\n }\n}\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Zalo Profile Ads (https://profile.ads.zalo.me):\n * 1. createOaPage (POST /ajax/create-page)\n * 2. uploadOaAvatar (POST /ajax/upload-avatar)\n * 3. uploadOaCover (POST /ajax/upload-cover)\n *\n * Tích hợp toàn bộ quy chuẩn, danh mục 22 SubCategories, 34 Provinces, định dạng CCCD/SĐT,\n * và chính sách xét duyệt Official Account cửa hàng/doanh nghiệp.\n */\n\nimport type {\n ZaloProfileAdsCreateOaPageRequest,\n ZaloProfileAdsProvinceId,\n ZaloProfileAdsSubCategoryId,\n} from \"../dtos/profile-ads.dto\";\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\n/**\n * Danh mục 22 mã SubCategory chuẩn trên Zalo Ads Profile\n */\nexport const ZALO_PROFILE_ADS_SUB_CATEGORIES: Record<number, string> = {\n 10043: \"Bất động sản\",\n 10018: \"Công nghệ & Thiết bị\",\n 10097: \"Dịch vụ tiện ích\",\n 10020: \"Du lịch & Lưu trú\",\n 10021: \"Giáo dục & Đào tạo\",\n 10024: \"Mua sắm & Bán lẻ\",\n 10019: \"Mỹ phẩm & Làm đẹp\",\n 10014: \"Nhà hàng & Quán\",\n 10094: \"Ô tô & Xe máy\",\n 10098: \"Sản xuất & Chế tạo\",\n 10044: \"Tài chính & Ngân hàng\",\n 10099: \"Thiết kế & Thi công\",\n 10017: \"Thời trang & May mặc\",\n 10023: \"Thực phẩm & Đồ uống\",\n 10016: \"Truyền thông & Giải trí\",\n 10092: \"Truyền thông nội bộ\",\n 10101: \"Tuyển dụng & Việc làm\",\n 10100: \"Tư vấn & Quản lý\",\n 10095: \"Vận tải\",\n 10093: \"Viễn thông\",\n 10022: \"Y tế & Dược phẩm\",\n 10025: \"Dịch vụ khác\",\n};\n\n/**\n * Danh mục 34 Tỉnh/Thành phố chuẩn trên Zalo Ads Profile (GET /ajax/get-province)\n */\nexport const ZALO_PROFILE_ADS_PROVINCES: Record<number, string> = {\n 1: \"Thành phố Hà Nội\",\n 4: \"Tỉnh Cao Bằng\",\n 8: \"Tỉnh Tuyên Quang\",\n 11: \"Tỉnh Điện Biên\",\n 12: \"Tỉnh Lai Châu\",\n 14: \"Tỉnh Sơn La\",\n 15: \"Tỉnh Lào Cai\",\n 19: \"Tỉnh Thái Nguyên\",\n 20: \"Tỉnh Lạng Sơn\",\n 22: \"Tỉnh Quảng Ninh\",\n 24: \"Tỉnh Bắc Ninh\",\n 25: \"Tỉnh Phú Thọ\",\n 31: \"Thành phố Hải Phòng\",\n 33: \"Tỉnh Hưng Yên\",\n 37: \"Tỉnh Ninh Bình\",\n 38: \"Tỉnh Thanh Hóa\",\n 40: \"Tỉnh Nghệ An\",\n 42: \"Tỉnh Hà Tĩnh\",\n 44: \"Tỉnh Quảng Trị\",\n 46: \"Thành phố Huế\",\n 48: \"Thành phố Đà Nẵng\",\n 51: \"Tỉnh Quảng Ngãi\",\n 52: \"Tỉnh Gia Lai\",\n 56: \"Tỉnh Khánh Hòa\",\n 66: \"Tỉnh Đắk Lắk\",\n 68: \"Tỉnh Lâm Đồng\",\n 75: \"Tỉnh Đồng Nai\",\n 79: \"Thành phố Hồ Chí Minh\",\n 80: \"Tỉnh Tây Ninh\",\n 82: \"Tỉnh Đồng Tháp\",\n 86: \"Tỉnh Vĩnh Long\",\n 91: \"Tỉnh An Giang\",\n 92: \"Thành phố Cần Thơ\",\n 96: \"Tỉnh Cà Mau\",\n};\n\n/**\n * Biểu thức Regex kiểm tra số điện thoại di động Việt Nam (10 số, đầu 03, 05, 07, 08, 09 hoặc 843, 845,...)\n */\nexport const VIETNAM_PHONE_REGEX = /^(84|0)(3[2-9]|5[2689]|7[06-9]|8[1-9]|9[0-9])[0-9]{7}$/;\n\n/**\n * Helper kiểm tra URL hợp lệ\n */\nfunction isValidUrl(val: string): boolean {\n return /^(https?:\\/\\/|data:image\\/)/i.test(val);\n}\n\n// ============================================================================\n// 1. validateCreateOaPageRequest\n// ============================================================================\nexport function validateCreateOaPageRequest(input: unknown): ValidationResult<ZaloProfileAdsCreateOaPageRequest> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu khởi tạo Zalo Official Account phải là một đối tượng (object).\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n\n // 1. oaName: Tên hiển thị của trang OA (2 - 40 ký tự)\n const oaName = typeof raw.oaName === \"string\" ? raw.oaName.trim() : \"\";\n if (!oaName) {\n errors.push(\"Tên trang Official Account ('oaName') là bắt buộc và không được để trống.\");\n } else if (oaName.length < 2 || oaName.length > 40) {\n errors.push(`Tên trang Official Account phải từ 2 đến 40 ký tự (hiện tại: ${oaName.length} ký tự).`);\n } else {\n // Không dùng chữ in hoa toàn bộ (trừ viết tắt thương hiệu ngắn <= 5 ký tự)\n if (oaName.length > 5 && oaName === oaName.toUpperCase() && /[A-Z]/.test(oaName)) {\n errors.push(\"Tên trang Official Account không được viết in hoa toàn bộ các từ. Vui lòng viết theo ngữ pháp tiếng Việt chuẩn.\");\n }\n // Cấm các từ ngữ chung chung hoặc từ khóa nhạy cảm\n const forbiddenKeywords = [\"số 1\", \"nhất việt nam\", \"cam kết 100%\", \"trị dứt điểm\"];\n for (const kw of forbiddenKeywords) {\n if (oaName.toLowerCase().includes(kw)) {\n errors.push(`Tên trang Official Account chứa từ ngữ cam kết/phô trương không hợp lệ: '${kw}'.`);\n }\n }\n }\n\n // 2. description: Mô tả hoạt động (20 - 500 ký tự)\n const description = typeof raw.description === \"string\" ? raw.description.trim() : \"\";\n if (!description) {\n errors.push(\"Thông tin mô tả hoạt động ('description') là bắt buộc.\");\n } else if (description.length < 20 || description.length > 500) {\n errors.push(`Thông tin mô tả hoạt động phải từ 20 đến 500 ký tự (hiện tại: ${description.length} ký tự).`);\n }\n\n // 3. contactName: Tên người liên hệ (tối thiểu 2 từ)\n const contactName = typeof raw.contactName === \"string\" ? raw.contactName.trim() : \"\";\n if (!contactName) {\n errors.push(\"Họ và tên người liên hệ ('contactName') là bắt buộc.\");\n } else if (contactName.split(/\\s+/).length < 2) {\n errors.push(\"Họ và tên người liên hệ phải có ít nhất 2 từ (họ và tên).\");\n }\n\n // 4. contactPhone: Số điện thoại liên hệ (10 chữ số chuẩn VN)\n const contactPhone = typeof raw.contactPhone === \"string\" ? raw.contactPhone.trim() : String(raw.contactPhone || \"\").trim();\n if (!contactPhone) {\n errors.push(\"Số điện thoại liên hệ ('contactPhone') là bắt buộc.\");\n } else {\n const cleanPhone = contactPhone.replace(/\\s+/g, \"\");\n if (!VIETNAM_PHONE_REGEX.test(cleanPhone)) {\n errors.push(`Số điện thoại liên hệ '${contactPhone}' không hợp lệ. Phải là số di động Việt Nam 10 chữ số (ví dụ: 0901234567 hoặc 84901234567).`);\n }\n }\n\n // 5. subCategoryId: 1 trong 22 mã chuẩn\n const subCatId = Number(raw.subCategoryId);\n if (!subCatId || !ZALO_PROFILE_ADS_SUB_CATEGORIES[subCatId]) {\n errors.push(\n `Mã danh mục hoạt động ('subCategoryId') '${raw.subCategoryId}' không hợp lệ. Phải thuộc 22 mã danh mục chuẩn trên Zalo Ads Profile (ví dụ: 10018: Công nghệ & Thiết bị, 10043: Bất động sản, 10024: Mua sắm & Bán lẻ).`\n );\n }\n\n // 6. province: 1 trong 34 mã tỉnh thành chuẩn\n const provinceId = Number(raw.province);\n if (!provinceId || !ZALO_PROFILE_ADS_PROVINCES[provinceId]) {\n errors.push(\n `Mã Tỉnh/Thành phố ('province') '${raw.province}' không hợp lệ. Phải thuộc 34 mã hành chính chuẩn trên Zalo Ads Profile (ví dụ: 1: Hà Nội, 79: TP.HCM, 48: Đà Nẵng).`\n );\n }\n\n // 7. district: Phường/Xã (số nguyên dương > 0)\n const district = Number(raw.district);\n if (!district || !Number.isInteger(district) || district <= 0) {\n errors.push(\"Mã Phường/Xã ('district') là bắt buộc và phải là số nguyên dương (> 0).\");\n }\n\n // 8. address: Địa chỉ chi tiết (tối thiểu 5 ký tự)\n const address = typeof raw.address === \"string\" ? raw.address.trim() : \"\";\n if (!address || address.length < 5) {\n errors.push(\"Địa chỉ hoạt động chi tiết ('address') phải có độ dài tối thiểu 5 ký tự.\");\n }\n\n // 9. avatarId & coverId: Chuỗi fileId không rỗng\n const avatarId = typeof raw.avatarId === \"string\" ? raw.avatarId.trim() : \"\";\n if (!avatarId) {\n errors.push(\"Mã định danh ảnh đại diện ('avatarId') là bắt buộc. Hãy tải ảnh qua API uploadOaAvatar trước.\");\n }\n\n const coverId = typeof raw.coverId === \"string\" ? raw.coverId.trim() : \"\";\n if (!coverId) {\n errors.push(\"Mã định danh ảnh bìa ('coverId') là bắt buộc. Hãy tải ảnh qua API uploadOaCover trước.\");\n }\n\n const cleanData: ZaloProfileAdsCreateOaPageRequest = {\n option: \"createpage\",\n typeId: raw.typeId !== undefined ? Number(raw.typeId) : 2,\n typeName: typeof raw.typeName === \"string\" ? raw.typeName : \"store\",\n tier: raw.tier !== undefined ? Number(raw.tier) : 0,\n categoryId: raw.categoryId !== undefined ? Number(raw.categoryId) : 10003,\n subCategoryId: subCatId as ZaloProfileAdsSubCategoryId,\n oaName,\n description,\n contactName,\n contactPhone,\n avatarId,\n coverId,\n province: provinceId as ZaloProfileAdsProvinceId,\n district,\n address,\n agreeTerm: raw.agreeTerm !== undefined ? Boolean(raw.agreeTerm) : true,\n ...(typeof raw[\"crsf-token\"] === \"string\" ? { \"crsf-token\": raw[\"crsf-token\"] } : {}),\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n// ============================================================================\n// 2. validateUploadMediaRequest (Avatar & Cover)\n// ============================================================================\nexport interface ValidateUploadMediaOptions {\n mediaType: \"avatar\" | \"cover\";\n maxSizeBytes?: number;\n minWidth?: number;\n minHeight?: number;\n}\n\nexport function validateUploadMediaRequest(\n input: unknown,\n options: ValidateUploadMediaOptions\n): ValidationResult<{ file: unknown; isNew?: string; option?: string }> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu yêu cầu tải ảnh lên phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n const fileField = options.mediaType === \"avatar\" ? (raw[\"avatar-file\"] ?? raw.file ?? raw.File) : (raw[\"cover-file\"] ?? raw.file ?? raw.File);\n\n if (!fileField) {\n errors.push(`Trường tệp ảnh ('${options.mediaType === \"avatar\" ? \"avatar-file\" : \"cover-file\"}') là bắt buộc.`);\n return { isValid: false, errors };\n }\n\n // Kiểm tra nếu là URL chuỗi\n if (typeof fileField === \"string\") {\n const trimmed = fileField.trim();\n if (!trimmed) {\n errors.push(\"Đường dẫn tệp ảnh không được để trống.\");\n } else if (!isValidUrl(trimmed)) {\n errors.push(`Đường dẫn tệp '${trimmed}' không hợp lệ. Phải là URL HTTP/HTTPS công khai hoặc data URL.`);\n }\n }\n\n // Kiểm tra kích thước và giới hạn dung lượng\n const maxBytes = options.maxSizeBytes || 15 * 1024 * 1024; // Mặc định 15MB\n if (typeof raw.sizeBytes === \"number\" && raw.sizeBytes > maxBytes) {\n const sizeMb = (raw.sizeBytes / (1024 * 1024)).toFixed(2);\n errors.push(`Dung lượng ảnh vượt quá giới hạn tối đa 15MB (dung lượng: ${sizeMb}MB).`);\n }\n\n const minW = options.minWidth || (options.mediaType === \"avatar\" ? 150 : 320);\n const minH = options.minHeight || (options.mediaType === \"avatar\" ? 150 : 180);\n\n if (typeof raw.width === \"number\" && raw.width < minW) {\n errors.push(`Chiều rộng ảnh tối thiểu ${minW}px (hiện tại: ${raw.width}px).`);\n }\n if (typeof raw.height === \"number\" && raw.height < minH) {\n errors.push(`Chiều cao ảnh tối thiểu ${minH}px (hiện tại: ${raw.height}px).`);\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0\n ? {\n file: fileField,\n isNew: typeof raw[\"is-new\"] === \"string\" ? raw[\"is-new\"] : \"true\",\n option: typeof raw.option === \"string\" ? raw.option : \"update\",\n }\n : undefined,\n };\n}\n\n/**\n * ZaloProfileAdsValidator: Gom nhóm các hàm xác thực cho Zalo Profile Ads\n */\nexport const ZaloProfileAdsValidator = {\n validateCreateOaPage: validateCreateOaPageRequest,\n validateUploadMedia: validateUploadMediaRequest,\n validateUploadAvatar: (input: unknown) =>\n validateUploadMediaRequest(input, { mediaType: \"avatar\", minWidth: 150, minHeight: 150 }),\n validateUploadCover: (input: unknown) =>\n validateUploadMediaRequest(input, { mediaType: \"cover\", minWidth: 320, minHeight: 180 }),\n};\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Báo cáo (Reports) trên Zalo Ads:\n * 1. upsertCustomReport (POST /api/report/upsertCustomReport)\n * 2. validateDateRangeReport: Xác thực khoảng thời gian truy vấn báo cáo (v2/v3 campaigns, ads, unique-user, demographics)\n *\n * Tích hợp quy chuẩn giới hạn thời gian tối đa 90 ngày của Zalo Ads Report Engine,\n * định dạng Unix timestamp giây/mili-giây và danh mục các cột chỉ số báo cáo.\n */\n\nimport type { ZaloAdsUpsertCustomReportRequest } from \"../dtos/ads.dto\";\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\n/**\n * 90 ngày tính bằng giây (90 * 24 * 3600)\n */\nexport const MAX_REPORT_RANGE_SECONDS = 90 * 86400;\n\n/**\n * 90 ngày tính bằng mili-giây\n */\nexport const MAX_REPORT_RANGE_MS = MAX_REPORT_RANGE_SECONDS * 1000;\n\n// ============================================================================\n// 1. validateUpsertCustomReportRequest\n// ============================================================================\nexport function validateUpsertCustomReportRequest(\n input: unknown\n): ValidationResult<ZaloAdsUpsertCustomReportRequest> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu cấu hình báo cáo tùy chỉnh phải là một đối tượng.\"],\n };\n }\n\n const raw = input as Record<string, unknown>;\n\n // 1. id: 0 khi tạo mới, số nguyên dương khi cập nhật\n let id = 0;\n if (raw.id !== undefined && raw.id !== null) {\n const parsedId = Number(raw.id);\n if (!Number.isInteger(parsedId) || parsedId < 0) {\n errors.push(\"Trường 'id' phải là số nguyên không âm (0 khi tạo mới, > 0 khi cập nhật).\");\n } else {\n id = parsedId;\n }\n }\n\n // 2. name: Tên báo cáo tùy chỉnh (1 - 100 ký tự)\n const name = typeof raw.name === \"string\" ? raw.name.trim() : \"\";\n if (!name) {\n errors.push(\"Tên báo cáo tùy chỉnh ('name') là bắt buộc và không được để trống.\");\n } else if (name.length > 100) {\n errors.push(`Tên báo cáo tùy chỉnh không được vượt quá 100 ký tự (hiện tại: ${name.length} ký tự).`);\n }\n\n // 3. settings: Danh sách mã cột/chỉ số (Array<number>, minItems: 1)\n const settings: number[] = [];\n if (!Array.isArray(raw.settings) || raw.settings.length === 0) {\n errors.push(\"Danh sách chỉ số cột ('settings') là bắt buộc và phải có ít nhất 1 chỉ số.\");\n } else {\n for (const item of raw.settings) {\n const colId = Number(item);\n if (!Number.isInteger(colId) || colId <= 0) {\n errors.push(`Mã chỉ số cột '${item}' không hợp lệ. Phải là số nguyên dương.`);\n } else {\n if (!settings.includes(colId)) {\n settings.push(colId);\n }\n }\n }\n }\n\n // 4. isDefault: Cờ báo cáo mặc định\n const isDefault = Boolean(raw.isDefault);\n\n const cleanData: ZaloAdsUpsertCustomReportRequest = {\n id,\n name,\n settings,\n isDefault,\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n// ============================================================================\n// 2. validateDateRangeReportRequest\n// ============================================================================\nexport interface DateRangeReportQuery {\n startDate?: number;\n endDate?: number;\n from?: number;\n to?: number;\n campaignId?: number;\n [key: string]: unknown;\n}\n\nexport interface CleanDateRangeReport {\n startDate: number;\n endDate: number;\n isMilliseconds: boolean;\n campaignId?: number;\n}\n\nexport function validateDateRangeReportRequest(\n input: unknown\n): ValidationResult<CleanDateRangeReport> {\n const errors: string[] = [];\n\n if (!input || typeof input !== \"object\") {\n return {\n isValid: false,\n errors: [\"Tham số truy vấn khoảng thời gian báo cáo phải là một đối tượng.\"],\n };\n }\n\n const raw = input as DateRangeReportQuery;\n\n // Lấy start/end (hỗ trợ cả cặp startDate/endDate và from/to)\n const rawStart = raw.startDate ?? raw.from;\n const rawEnd = raw.endDate ?? raw.to;\n\n if (rawStart === undefined || rawStart === null) {\n errors.push(\"Mốc thời gian bắt đầu ('startDate' hoặc 'from') là bắt buộc.\");\n }\n if (rawEnd === undefined || rawEnd === null) {\n errors.push(\"Mốc thời gian kết thúc ('endDate' hoặc 'to') là bắt buộc.\");\n }\n\n if (errors.length > 0) {\n return { isValid: false, errors };\n }\n\n const startNum = Number(rawStart);\n const endNum = Number(rawEnd);\n\n if (isNaN(startNum) || startNum <= 0) {\n errors.push(`Mốc thời gian bắt đầu '${rawStart}' không hợp lệ. Phải là Unix timestamp dương.`);\n }\n if (isNaN(endNum) || endNum <= 0) {\n errors.push(`Mốc thời gian kết thúc '${rawEnd}' không hợp lệ. Phải là Unix timestamp dương.`);\n }\n\n if (errors.length > 0) {\n return { isValid: false, errors };\n }\n\n // Nhận diện đang dùng giây hay mili-giây\n // Nếu > 10,000,000,000 (10 chữ số) => mili-giây (năm 2286 ở dạng giây)\n const isMs = startNum > 10000000000 || endNum > 10000000000;\n const maxRange = isMs ? MAX_REPORT_RANGE_MS : MAX_REPORT_RANGE_SECONDS;\n\n if (endNum < startNum) {\n errors.push(\"Mốc thời gian kết thúc phải lớn hơn hoặc bằng mốc thời gian bắt đầu.\");\n } else {\n const diff = endNum - startNum;\n if (diff > maxRange) {\n const days = isMs ? Math.round(diff / (86400 * 1000)) : Math.round(diff / 86400);\n errors.push(`Khoảng thời gian truy vấn báo cáo không được vượt quá 90 ngày theo chính sách Zalo Ads (khoảng thời gian hiện tại: ${days} ngày).`);\n }\n }\n\n let campaignId: number | undefined;\n if (raw.campaignId !== undefined && raw.campaignId !== null) {\n const parsedCampId = Number(raw.campaignId);\n if (!Number.isInteger(parsedCampId) || parsedCampId <= 0) {\n errors.push(\"Mã chiến dịch ('campaignId') phải là số nguyên dương (> 0).\");\n } else {\n campaignId = parsedCampId;\n }\n }\n\n const cleanData: CleanDateRangeReport = {\n startDate: startNum,\n endDate: endNum,\n isMilliseconds: isMs,\n ...(campaignId !== undefined ? { campaignId } : {}),\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n/**\n * ZaloReportsValidator: Gom nhóm các hàm xác thực cho Zalo Ads Reporting\n */\nexport const ZaloReportsValidator = {\n validateUpsertCustomReport: validateUpsertCustomReportRequest,\n validateDateRangeReport: validateDateRangeReportRequest,\n};\n","/**\n * Bộ kiểm tra tính hợp lệ dữ liệu (Request Validators) cho các API Thư viện Media trên Zalo Ads:\n * 1. saveMedia (POST /api/media/save)\n *\n * Kiểm tra cấu trúc metadata lưu trữ Media (Name, Type: 1-Ảnh / 2-Video, Settings: Url, Width, Height, Duration, ThumbUrl).\n */\n\nimport type { ZaloAdsMediaSavePayloadDto } from \"../dtos/ads.dto\";\nimport type { ValidationResult } from \"./instant-pages.validator\";\n\n/**\n * Helper kiểm tra URL hợp lệ\n */\nfunction isValidUrl(val: unknown): boolean {\n if (typeof val !== \"string\") return false;\n return /^https?:\\/\\/.+/i.test(val.trim());\n}\n\n// ============================================================================\n// 1. validateSaveMediaRequest\n// ============================================================================\nexport function validateSaveMediaRequest(\n input: unknown\n): ValidationResult<ZaloAdsMediaSavePayloadDto> {\n const errors: string[] = [];\n\n if (!input) {\n return {\n isValid: false,\n errors: [\"Dữ liệu lưu Media ('saveMedia') không được để trống.\"],\n };\n }\n\n // Hỗ trợ trường hợp input là JSON string hoặc bọc trong { data: ... }\n let targetObj: unknown = input;\n if (typeof input === \"string\") {\n try {\n targetObj = JSON.parse(input);\n } catch {\n return {\n isValid: false,\n errors: [\"Chuỗi JSON dữ liệu Media ('data') không đúng định dạng.\"],\n };\n }\n }\n\n if (!targetObj || typeof targetObj !== \"object\") {\n return {\n isValid: false,\n errors: [\"Dữ liệu Media phải là một đối tượng.\"],\n };\n }\n\n const rawObj = targetObj as Record<string, unknown>;\n // Nếu có wrapper 'data' bên ngoài\n let raw = rawObj;\n if (rawObj.data && typeof rawObj.data === \"object\") {\n raw = rawObj.data as Record<string, unknown>;\n } else if (typeof rawObj.data === \"string\") {\n try {\n raw = JSON.parse(rawObj.data);\n } catch {\n return {\n isValid: false,\n errors: [\"Chuỗi JSON trong trường 'data' không đúng định dạng.\"],\n };\n }\n }\n\n // 1. Name: Tên media (1 - 255 ký tự)\n const name = typeof raw.Name === \"string\" ? raw.Name.trim() : (typeof raw.name === \"string\" ? raw.name.trim() : \"\");\n if (!name) {\n errors.push(\"Tên tệp media ('Name') là bắt buộc và không được để trống.\");\n } else if (name.length > 255) {\n errors.push(`Tên tệp media không được vượt quá 255 ký tự (hiện tại: ${name.length} ký tự).`);\n }\n\n // 2. Type: 1 (Ảnh) hoặc 2 (Video)\n const typeVal = raw.Type !== undefined ? Number(raw.Type) : (raw.type !== undefined ? Number(raw.type) : NaN);\n if (typeVal !== 1 && typeVal !== 2) {\n errors.push(`Loại media ('Type') không hợp lệ: '${raw.Type ?? raw.type}'. Chỉ hỗ trợ 1 (Ảnh) hoặc 2 (Video).`);\n }\n\n // 3. Settings: Cấu hình chi tiết\n const rawSettings = (raw.Settings ?? raw.settings) as Record<string, unknown> | undefined;\n if (!rawSettings || typeof rawSettings !== \"object\") {\n errors.push(\"Cấu hình tệp media ('Settings') là bắt buộc.\");\n return { isValid: false, errors };\n }\n\n // Settings.Url: Bắt buộc là URL CDN hợp lệ\n const url = typeof rawSettings.Url === \"string\" ? rawSettings.Url.trim() : (typeof rawSettings.url === \"string\" ? rawSettings.url.trim() : \"\");\n if (!url) {\n errors.push(\"Đường dẫn tệp media ('Settings.Url') là bắt buộc.\");\n } else if (!isValidUrl(url)) {\n errors.push(`Đường dẫn tệp media ('Settings.Url') không hợp lệ: '${url}'. Phải là URL HTTP hoặc HTTPS bắt đầu bằng http:// hoặc https://.`);\n }\n\n // Settings.Width & Settings.Height: Số nguyên dương\n const width = Number(rawSettings.Width ?? rawSettings.width);\n if (!Number.isInteger(width) || width <= 0) {\n errors.push(`Chiều rộng tệp media ('Settings.Width') phải là số nguyên dương (> 0). Hiện tại: ${rawSettings.Width ?? rawSettings.width}`);\n }\n\n const height = Number(rawSettings.Height ?? rawSettings.height);\n if (!Number.isInteger(height) || height <= 0) {\n errors.push(`Chiều cao tệp media ('Settings.Height') phải là số nguyên dương (> 0). Hiện tại: ${rawSettings.Height ?? rawSettings.height}`);\n }\n\n // Nếu là Video (Type = 2): Kiểm tra thời lượng Duration & ThumbUrl\n let duration: number | undefined;\n let thumbUrl: string | undefined;\n\n if (typeVal === 2) {\n const dur = Number(rawSettings.Duration ?? rawSettings.duration);\n if (!isNaN(dur) && dur > 0) {\n if (dur > 600) {\n errors.push(`Thời lượng video ('Settings.Duration') không được vượt quá 600 giây (hiện tại: ${dur}s).`);\n } else {\n duration = dur;\n }\n } else {\n errors.push(\"Với loại media Video (Type = 2), thời lượng video ('Settings.Duration') là bắt buộc và phải là số dương (> 0).\");\n }\n\n const thumb = typeof rawSettings.ThumbUrl === \"string\" ? rawSettings.ThumbUrl.trim() : (typeof rawSettings.thumbUrl === \"string\" ? rawSettings.thumbUrl.trim() : \"\");\n if (thumb) {\n if (!isValidUrl(thumb)) {\n errors.push(`Ảnh thu nhỏ của video ('Settings.ThumbUrl') không hợp lệ: '${thumb}'. Phải là URL HTTP/HTTPS.`);\n } else {\n thumbUrl = thumb;\n }\n }\n }\n\n const cleanData: ZaloAdsMediaSavePayloadDto = {\n Name: name,\n Type: typeVal,\n Settings: {\n Url: url,\n Width: width,\n Height: height,\n ...(duration !== undefined ? { Duration: duration } : {}),\n ...(thumbUrl !== undefined ? { ThumbUrl: thumbUrl } : {}),\n },\n };\n\n return {\n isValid: errors.length === 0,\n errors,\n data: errors.length === 0 ? cleanData : undefined,\n };\n}\n\n/**\n * ZaloMediaValidator: Gom nhóm các hàm xác thực cho Thư viện Media\n */\nexport const ZaloMediaValidator = {\n validateSaveMedia: validateSaveMediaRequest,\n};\n"],"mappings":"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","names":["bytes","OP_ZaloAdsUpdateNewAds","OP_ZaloAdsCreateForm","OP_ZaloAdsListFormsByOfficialAccount","isPositiveInteger","toPositiveInteger","ZaloInstantPageBlockType","AutomatedRuleScopeEnum","AutomatedRuleActionTypeEnum","AutomatedRuleFrequencyEnum","AutomatedRuleConditionFieldEnum","AutomatedRuleOperatorEnum","AutomatedRuleTimeRangeEnum","actType","ConversionLabelEnum","ConversionUrlTypeEnum","isValidUrl","isValidUrl"]}