// src/utils.js function getBeijingDateStr(timeMs) { const beijingOffset = 8 * 60 * 60 * 1e3; const date = new Date(timeMs + beijingOffset); return date.toISOString().split("T")[0]; } function getSelfDestructTime(expireDate, hasPaid) { if (!expireDate || expireDate === "-1" || expireDate === "trial") return null; const t = Date.parse(expireDate.includes("T") ? expireDate : expireDate + "T00:00:00+08:00"); if (isNaN(t)) return null; return t + (hasPaid ? 365 : 180) * 864e5; } async function md5Hex(text) { const msgUint8 = new TextEncoder().encode(text); const hashBuffer = await crypto.subtle.digest("MD5", msgUint8); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); return hashHex; } function vipJson(obj, status = 200) { return new Response(JSON.stringify(obj), { status, headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Cache-Control": "no-store" } }); } // src/config.js var regPriceCNY = "1.00"; var priceCNY = "9.90"; var priceYearCNY = "99.00"; var APP_LATEST_VERSION_CODE = 576; var APP_LATEST_VERSION_NAME = "26.09.17"; var APK_URL_TV = "https://videovideo.2000168.xyz/\u7B80\u5355\u5F71\u89C6\u7535\u89C6\u7248-v576.apk"; var APK_URL_MOBILE = "https://videovideo.2000168.xyz/\u7B80\u5355\u5F71\u89C6\u79FB\u52A8\u7248-v576.apk"; var APP_CHANGELOG = "\u4F18\u5316\u65E5\u5E38bug"; var PROMO_IMAGE_URL = ""; var POSTER_URLS = [ "https://mdb.yuncongz.com/static/upload/raw/0005d5b734104313ba6c020636682002.jpg", // 海报1 → 首屏海报墙(竖版 600×900px) "https://mdb.yuncongz.com/static/upload/raw/7d0dd1a5ad904bfa8cf9016a55016ade.jpg", // 海报2 "https://mdb.yuncongz.com/static/upload/raw/3e4253d8066d4eb1bbfb1515b7c9d50e.jpg", // 海报3 "https://mdb.yuncongz.com/static/upload/raw/38dd2e7e96434268b7e005aa4a468370.jpg", // 海报4 "https://mdb.yuncongz.com/static/upload/raw/baa5a5c38a9340358b1ac6ba8f35ddda.jpg", // 海报5 "https://mdb.yuncongz.com/static/upload/raw/2729709f4f46490c94f181baa0403207.jpg", // 海报6 "https://mdb.yuncongz.com/static/upload/raw/5aa3209bedf243ce871303502c2fe36f.jpg", // 海报7 "https://mdb.yuncongz.com/static/upload/raw/9c6bb4c6c95a48f3b590f002b714df63.jpg" // 海报8 ]; var VIDEO_SRC_URL = "https://videovideo.2000168.xyz/tutorial.mp4"; var VIDEO_POSTER_URL = "https://videovideo.2000168.xyz/tutorial-poster.jpg"; var FAVICON_URL = "https://go.2000168.xyz/favicon.ico"; var SHARE_IMAGE_URL = "https://videovideo.2000168.xyz/og-cover.jpg"; // src/pay.js async function generateSign(params, key) { const sortedKeys = Object.keys(params).sort(); const tempArray = []; for (const k of sortedKeys) { const v = params[k]; if (k !== "sign" && k !== "sign_type" && v !== null && v !== void 0 && v !== "") { tempArray.push(`${k}=${v}`); } } const rawString = tempArray.join("&") + key; return await md5Hex(rawString); } function getPayUrlFailReason(env) { if (env.PAY_PAUSED === "true" || env.PAY_PAUSED === true) return "pay_paused"; if (!env.MOTION_PID || !env.MOTION_KEY) return "missing_config"; return null; } async function getDynamicPayQrCode(token, isTrial, origin, env, clientIP, isYear = false) { if (env.PAY_PAUSED === "true" || env.PAY_PAUSED === true) { console.warn("pay_url_fail reason=pay_paused"); return null; } const motionPid = env.MOTION_PID; const motionKey = env.MOTION_KEY; const motionGateway = env.MOTION_GATEWAY || "https://motionpay.net/submit.php"; if (!motionPid || !motionKey) { console.warn("pay_url_fail reason=missing_config pid=" + (motionPid ? 1 : 0) + " key=" + (motionKey ? 1 : 0)); return null; } let finalPrice = isTrial ? regPriceCNY : priceCNY; let finalName = isTrial ? "VIP-Trial" : "VIP-Monthly"; let finalDays = "30"; if (!isTrial && isYear) { finalPrice = priceYearCNY; finalName = "VIP-Yearly"; finalDays = "365"; } const cacheKey = `pay_url_cache_${token}_${isYear ? "year" : "month"}_${finalPrice}`; const cachedUrl = await env.USER_DB.get(cacheKey); if (cachedUrl) return cachedUrl; const shortId = Date.now().toString(36) + Math.random().toString(36).substr(2, 4); const orderMapKey = `ord_${shortId}`; await env.USER_DB.put(orderMapKey, JSON.stringify({ t: token, d: finalDays }), { expirationTtl: 604800 }); const dynamicOrderId = `V${shortId}`; const payParams = { pid: motionPid, type: "wxpay", out_trade_no: dynamicOrderId, notify_url: `https://vip.8000168.xyz/api/pay-callback`, return_url: `${origin}/pay/success?token=${token}`, name: finalName, money: finalPrice, clientip: clientIP || "127.0.0.1", device: "pc", rawurl: "1" }; const sign = await generateSign(payParams, motionKey); payParams.sign = sign; payParams.sign_type = "MD5"; let mapiGateway = motionGateway.trim(); if (mapiGateway.includes("submit.php")) { mapiGateway = mapiGateway.replace("submit.php", "mapi.php"); } else if (!mapiGateway.includes("mapi.php")) { mapiGateway = mapiGateway.endsWith("/") ? mapiGateway + "mapi.php" : mapiGateway + "/mapi.php"; } try { const queryStr = new URLSearchParams(payParams).toString(); const finalApiUrl = `${mapiGateway}?${queryStr}`; const response = await fetch(finalApiUrl, { method: "GET", headers: { "Accept": "application/json" } }); const res = await response.json(); if (res && (res.code === 1 || res.code === "1")) { const payQr = res.qrcode || res.payurl || res.url; if (payQr) { await env.USER_DB.put(cacheKey, payQr, { expirationTtl: 300 }); return payQr; } } else { console.warn("\u26A0\uFE0F [\u6613\u652F\u4ED8\u63A5\u53E3\u62A5\u9519\u660E\u7EC6]\uFF1A", JSON.stringify(res)); } } catch (e) { console.error("pay_url_fail reason=gateway_error exception:", e); } console.warn("pay_url_fail reason=gateway_error gateway=" + mapiGateway); return null; } // src/user-db.js async function getUserByDeviceId(env, deviceId) { let row; try { row = await env.DB.prepare("SELECT * FROM users WHERE device_id = ?").bind(deviceId).first(); } catch (e) { console.warn("D1 query failed:", e.message); } if (!row) { const raw = await env.USER_DB.get(deviceId); if (!raw) return null; try { row = JSON.parse(raw); } catch (_) { return null; } } if (!row) return null; const sdTime = getSelfDestructTime(row.expire_date, !!row.has_paid); if (sdTime && sdTime < Date.now()) return null; return { invite_code: row.invite_code, invite_count: row.invite_count, invite_paid_count: row.invite_paid_count, invite_earned_days: row.invite_earned_days, referred_by: row.referred_by, expire_date: row.expire_date, is_blocked: !!row.is_blocked, has_paid: !!row.has_paid, disable_referral: !!row.disable_referral }; } async function getUserByInviteCode(env, inviteCode) { const row = await env.DB.prepare("SELECT * FROM users WHERE invite_code = ?").bind(inviteCode).first(); if (!row) return null; const sdTime = getSelfDestructTime(row.expire_date, !!row.has_paid); if (sdTime && sdTime < Date.now()) return null; return { device_id: row.device_id, invite_code: row.invite_code, invite_count: row.invite_count, invite_paid_count: row.invite_paid_count, invite_earned_days: row.invite_earned_days, referred_by: row.referred_by, expire_date: row.expire_date, is_blocked: !!row.is_blocked, has_paid: !!row.has_paid, disable_referral: !!row.disable_referral }; } async function upsertUser(env, deviceId, data) { await env.DB.prepare( "INSERT OR REPLACE INTO users (device_id, invite_code, invite_count, invite_paid_count, invite_earned_days, referred_by, expire_date, is_blocked, has_paid, disable_referral) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ).bind( deviceId, data.invite_code || "", data.invite_count || 0, data.invite_paid_count || 0, data.invite_earned_days || 0, data.referred_by || "", data.expire_date || "trial", data.is_blocked ? 1 : 0, data.has_paid ? 1 : 0, data.disable_referral ? 1 : 0 ).run(); } // src/referral.js function applyReferralReward(referrerData, now) { const todayStr = getBeijingDateStr(now); if (!referrerData.invite_count_today_date || referrerData.invite_count_today_date !== todayStr) { referrerData.invite_count_today_date = todayStr; referrerData.invite_count_today = 0; } referrerData.invite_paid_count = (referrerData.invite_paid_count || 0) + 1; if (referrerData.invite_count_today >= 2) { referrerData.invite_count = (referrerData.invite_count || 0) + 1; return { ok: false, limit: true }; } referrerData.invite_count_today += 1; let refExpire = referrerData.expire_date; let refBaseTime = now; if (refExpire && refExpire !== -1 && refExpire !== "-1" && refExpire !== "trial") { const refExpireTime = Date.parse(refExpire.includes("T") ? refExpire : `${refExpire}T00:00:00+08:00`); const finalRefExpireTime = refExpireTime ? refExpireTime + 24 * 60 * 60 * 1e3 - 1e3 : NaN; if (!isNaN(finalRefExpireTime) && finalRefExpireTime > now) { refBaseTime = finalRefExpireTime; } } if (refExpire !== -1 && refExpire !== "-1") { const refFinalExpireMs = refBaseTime + 30 * 24 * 60 * 60 * 1e3; referrerData.expire_date = getBeijingDateStr(refFinalExpireMs); } referrerData.invite_count = (referrerData.invite_count || 0) + 1; referrerData.invite_earned_days = (referrerData.invite_earned_days || 0) + 30; return { ok: true }; } function applyInviteeReward(userData, now) { const exp = userData.expire_date; if (exp === -1 || exp === "-1") return; const newExpireMs = now + 30 * 24 * 60 * 60 * 1e3; if (exp && exp !== "trial") { const t = Date.parse(String(exp).includes("T") ? String(exp) : `${String(exp)}T00:00:00+08:00`); const endMs = t ? t + 24 * 60 * 60 * 1e3 - 1e3 : NaN; if (!isNaN(endMs) && endMs > newExpireMs) return; } userData.expire_date = getBeijingDateStr(newExpireMs); } // src/pages/bottom-nav.js function getBottomNavHtml(activeTab, token) { const tokenParam = token ? "?token=" + token : ""; return `