本文目录 正在整理章节
本文信息核对时间:2026 年 7 月 23 日。文中的腾讯云链接为推广入口,活动资格、库存、配置和最终价格以登录后的活动页面及订单为准。
2026 年 7 月 23 日更新:脚本已升级为按目标场次绑定商品参数,并在开抢前 60 秒和 5 秒重新校时;确认售罄后改用“库存探测 + 定期真实下单复核”,同时增加错误分类、接口耗时和多标签运行保护。
最近腾讯云上线了“AI 焕新·智启新局”活动,其中比较受开发者关注的是 4 核 4G 服务器新客 38 元/年起。
对于准备搭建个人博客、测试环境、小型 API 服务或者 Docker 学习环境的用户,这个档位有一定吸引力。不过,活动商品通常受到账号资格、场次和库存限制,并不是所有账号都能以相同价格购买。
腾讯云活动入口:
建议进入页面后登录自己的腾讯云账号,直接查看当前账号显示的商品、价格和活动资格。
一、脚本当前识别的目标配置
我根据活动页面当前返回的商品数据,编写了一个浏览器 Console 辅助脚本。脚本识别的目标档位如下:
| 项目 | 目标配置 |
|---|---|
| 产品类型 | 腾讯云轻量应用服务器 Lighthouse |
| 活动价格 | 38 元/年 |
| CPU | 4 核 |
| 内存 | 4GB |
| 公网带宽 | 3Mbps |
| 月流量 | 300GB |
| 当前检查地域 | 广州、上海、北京 |
| 当前关注场次 | 10:00、15:00 |
这些参数是脚本当前版本使用的匹配条件。腾讯云可能调整商品、场次、地域和活动规则,付款前必须重新核对订单页面。
二、4 核 4G 3M 适合哪些场景?
4 核 4GB 的计算和内存配置适合以下轻量场景:
- 部署个人博客和内容网站
- 运行 Django、Flask、FastAPI 或 Node.js 项目
- 搭建开发、测试和演示环境
- 运行少量 Docker 容器
- 部署访问量不高的 API 服务
- 学习 Linux、Nginx、数据库和服务器运维
- 执行定时任务和个人自动化脚本
需要注意的是,3Mbps 公网带宽的理论传输速度约为 384KB/s,实际速度还会受到网络质量和协议开销影响。因此,它不适合大文件下载、视频分发、图床外链和高并发业务。
300GB 月流量对于普通博客和开发测试通常较宽裕,但仍应根据真实访问量设置监控,避免异常请求消耗流量。
三、为什么写这个 Console 辅助脚本?
限时商品常见的问题并不是找不到购买入口,而是需要在指定场次及时操作,同时不同地域的库存状态可能不同。
手动参与时可能遇到:
- 本地时间与腾讯云服务器时间存在误差
- 没有及时进入活动场次
- 当前选择的地域暂时没有库存
- 切换地域后已经错过下单时间
- 不清楚订单是否已经创建
- 页面展示活动商品,但账号并不符合资格
这个脚本在腾讯云活动页的浏览器 Console 中运行,复用已登录页面加载的请求模块,主要用于倒计时、地域检查和订单状态提示。
它不会增加商品库存,也不能绕过账号资格、实名认证、验证码或腾讯云风控,更不能保证创建订单成功。
四、脚本能够做什么?
当前版本包含以下功能:
- 自动识别 38 元、4 核 4G 3M、300GB 月流量的目标商品
- 将商品参数严格绑定到目标场次,避免误用其他场次或过期参数
- 使用腾讯云接口校准倒计时,并在开抢前 60 秒和 5 秒分别重新校时
- 自动选择下一场 10:00 或 15:00 的活动
- 默认按广州、上海、北京的顺序检查地域,并支持手动调整优先地域
- 确认三地售罄后,先短时间直接复核,再切换为库存探测,并定期保留真实下单兜底
- 区分售罄、未开始、限流、登录失效、风控和未知返回,网络异常时自动熔断退避
- 显示倒计时、运行状态、请求轮次和接口耗时,并阻止多个标签页重复运行
- 创建订单成功后显示腾讯云支付页面入口,支持随时停止后续请求
脚本只尝试创建 待支付订单,不会自动付款。订单创建后,仍需在腾讯云支付页面人工核对价格、配置、地域和购买时长。
五、脚本使用方法
使用前请先阅读完整源码,不要在浏览器 Console 中执行来源不明的代码。
- 通过上面的活动入口打开腾讯云活动页面。
- 登录腾讯云账号,查看自己的活动资格和目标商品。
- 使用桌面版 Chrome、Edge 等 Chromium 浏览器。
- 打开浏览器开发者工具的 Console。
- 复制下方完整 JavaScript,检查后粘贴到 Console 并按回车。
- 脚本会显示悬浮面板,并自动选择下一场活动。
- 如有需要,在面板中调整广州、上海或北京的优先顺序。
- 创建订单成功后,打开腾讯云支付页面并人工核对订单。
开发者工具快捷键:
- Windows/Linux:通常为
F12或Ctrl + Shift + J - macOS:通常为
Command + Option + J
常用命令:
| 命令 | 作用 |
|---|---|
TC38.status() | 查看状态、目标场次、地域顺序和服务器时差 |
TC38.dryRun() | 检查各地域的活动状态,不创建订单 |
TC38.cancel() | 停止倒计时和后续请求 |
TC38.start() | 重新选择下一场并开始监控 |
TC38.setPreferredRegion("上海") | 将上海调整为第一优先地域 |
脚本还提供 TC38.fireNow() 命令。它会立即开始发送真实的创建订单请求,不等待目标场次,因此不建议在不了解其行为时使用。
六、完整 Console 脚本
点击展开完整 JavaScript 源码
/*
* 腾讯云 38 元轻量服务器 Console 脚本。
*
* 运行位置:已登录的活动页
* https://curl.qcloud.com/REmjDl1z
*
* 粘贴完整脚本后会自动选择下一场并等待下单。
* 脚本直接复用活动页官方请求模块,不需要再执行初始化命令。
* TC38.fireNow() 会立即尝试创建待支付订单。
*/
(() => {
"use strict";
// 重复粘贴新版时先停止上一版,避免留下两个等待任务。
try {
window.TC38?.cancel?.();
} catch {}
document.querySelector("#tc38-monitor-panel")?.remove();
document.querySelector("#tc38-payment-link")?.remove();
const CFG = {
expectedPriceFen: 3800,
expectedSpec: "4核4G3M",
sessionMatchToleranceMs: 5 * 60_000,
noStockObservationMs: 20_000,
directSubmitWindowMs: 2_000,
stockPollPeriodMs: 600,
directSentinelIntervalMs: 3_000,
retryRoundStages: [
// periodMs 是一整轮三个地域从开始到下一轮开始的目标周期,
// 已包含网络请求耗时,不是每轮结束后固定追加的等待。
{ untilMs: 2_000, periodMs: 180 },
{ untilMs: 8_000, periodMs: 600 },
{ untilMs: 20_000, periodMs: 1_500 },
],
finalClockSyncLeadMs: 60_000,
lastClockSyncLeadMs: 5_000,
panelNormalRefreshMs: 1000,
panelFastRefreshMs: 200,
panelFastRefreshLeadMs: 10_000,
networkRetryDelaysMs: [500, 2000],
networkProbeDelaysMs: [15_000, 30_000, 60_000],
maxUnknownResponses: 6,
regionPriority: [
{ id: 1, name: "广州" },
{ id: 4, name: "上海" },
{ id: 8, name: "北京" },
],
};
let dianshiApi = null;
let runGeneration = 0;
let scheduledFor = null;
let monitorTimer = null;
let monitorState = "idle";
let monitorTargetMs = null;
let monitorClockOffsetMs = 0;
let monitorSession = null;
let monitorMessage = "";
let preferredRegionId = CFG.regionPriority[0].id;
let orderRound = 0;
let orderRequestCount = 0;
let noStockRetryCount = 0;
let noStockDetected = false;
let noStockDetectedAt = null;
let networkErrorStreak = 0;
let networkProbeAttempt = 0;
let networkPauseUntil = null;
let lastOrderResponses = [];
let stockCheckCount = 0;
let lastStockSnapshot = null;
let lastStockStateKey = "";
let orderLatencySamples = [];
let stockLatencySamples = [];
const instanceId = typeof window.crypto?.randomUUID === "function"
? window.crypto.randomUUID()
: `${Date.now()}_${Math.random().toString(16).slice(2)}`;
const runLeaseKey = "tc38-console-active-run";
let runLeaseDepth = 0;
let runLeaseTimer = null;
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function readRunLease() {
try {
return JSON.parse(localStorage.getItem(runLeaseKey) || "null");
} catch {
return null;
}
}
function writeRunLease() {
localStorage.setItem(runLeaseKey, JSON.stringify({
owner: instanceId,
expiresAt: Date.now() + 30_000,
}));
}
function acquireRunLease() {
if (runLeaseDepth > 0) {
runLeaseDepth++;
writeRunLease();
return;
}
const current = readRunLease();
if (
current?.owner
&& current.owner !== instanceId
&& Number(current.expiresAt) > Date.now()
) {
throw new Error("另一个腾讯云活动页标签正在运行 TC38,请先在那个标签停止监控");
}
writeRunLease();
if (readRunLease()?.owner !== instanceId) {
throw new Error("另一个标签正在启动 TC38,本标签已停止以避免重复下单");
}
runLeaseDepth = 1;
runLeaseTimer = setInterval(() => {
const lease = readRunLease();
if (lease?.owner && lease.owner !== instanceId) {
clearInterval(runLeaseTimer);
runLeaseTimer = null;
runLeaseDepth = 0;
runGeneration++;
monitorState = "stopped";
monitorMessage = "检测到其他标签接管运行,当前标签已停止";
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
return;
}
try {
writeRunLease();
} catch {}
}, 5_000);
}
function releaseRunLease(force = false) {
if (force) runLeaseDepth = 1;
if (runLeaseDepth > 0) runLeaseDepth--;
if (runLeaseDepth > 0) return;
if (runLeaseTimer !== null) {
clearInterval(runLeaseTimer);
runLeaseTimer = null;
}
try {
if (readRunLease()?.owner === instanceId) {
localStorage.removeItem(runLeaseKey);
}
} catch {}
}
function coerceEpochMs(value) {
if (typeof value === "string" && /^\d+$/.test(value.trim())) {
value = Number(value);
}
if (typeof value === "number" && Number.isFinite(value)) {
return value < 10_000_000_000 ? value * 1000 : value;
}
if (typeof value === "string") {
const normalized = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(?::\d{2})?$/.test(
value.trim(),
)
? `${value.trim().replace(" ", "T")}+08:00`
: value;
const parsed = Date.parse(normalized);
if (Number.isFinite(parsed)) return parsed;
}
return null;
}
function readTarget(targetSessionMs = null) {
const node = document.querySelector("#__NEXT_DATA__");
if (!node?.textContent) {
throw new Error("找不到 __NEXT_DATA__,请确认在活动页运行");
}
const root = JSON.parse(node.textContent);
const activity = root?.props?.pageProps?.activityData;
const flash = activity?.twoDaySeckillState?.flashResult || {};
const candidates = Object.values(flash)
.flatMap((sessions) => (Array.isArray(sessions) ? sessions : []))
.flatMap((session) => {
const sessionStartMs = coerceEpochMs(
session?.startTime
?? session?.start_time
?? session?.startAt
?? session?.start_at
?? session?.saleTime
?? session?.sale_time,
);
return (Array.isArray(session?.sales) ? session.sales : []).map(
(sale) => ({
sale,
sessionStartMs: sessionStartMs ?? coerceEpochMs(
sale?.startTime
?? sale?.start_time
?? sale?.startAt
?? sale?.start_at
?? sale?.saleTime
?? sale?.sale_time,
),
}),
);
});
const matches = candidates.filter(({ sale: item }) => {
const sku = item?.seckill_act_extra?.skuList || [];
return item?.priceData?.real_cost === CFG.expectedPriceFen
&& sku.includes(CFG.expectedSpec)
&& sku.includes("300GB 月流量")
&& String(item?.product_name || "").includes("lighthouse");
});
if (!matches.length) {
throw new Error("未找到 38 元 4核4G3M / 300GB 商品,拒绝继续");
}
let eligible = matches;
if (Number.isFinite(targetSessionMs)) {
const timed = matches.filter(({ sessionStartMs }) => (
Number.isFinite(sessionStartMs)
));
if (timed.length) {
eligible = timed.filter(({ sessionStartMs }) => (
Math.abs(sessionStartMs - targetSessionMs) <= CFG.sessionMatchToleranceMs
));
if (!eligible.length) {
throw new Error(
`活动页中没有 ${chinaTimeText(targetSessionMs)} 场的目标商品,请刷新活动页后重新粘贴脚本`,
);
}
}
} else {
eligible = [...matches].sort((left, right) => {
const leftTime = left.sessionStartMs ?? Number.POSITIVE_INFINITY;
const rightTime = right.sessionStartMs ?? Number.POSITIVE_INFINITY;
const now = Date.now();
const leftScore = leftTime >= now ? leftTime - now : 1e15 + now - leftTime;
const rightScore = rightTime >= now ? rightTime - now : 1e15 + now - rightTime;
return leftScore - rightScore;
});
}
const goodsActIds = new Set(eligible.map(({ sale: item }) => Number(
item.goodsId || item.act_id || item?.$goods?.big_goods_id,
)).filter(Number.isSafeInteger));
if (goodsActIds.size > 1) {
throw new Error("同一场次匹配到多个不同商品 ID,拒绝盲目下单");
}
const { sale, sessionStartMs } = eligible[0];
const goodsParam = structuredClone(
sale.defaultOrderParam || sale.defaultGoodsParam || {},
);
const activityId = Number(
sale.activityId || sale?.$goods?.activity_id || activity?.activityId,
);
const goodsActId = Number(
sale.goodsId || sale.act_id || sale?.$goods?.big_goods_id,
);
if (!Number.isSafeInteger(activityId) || !Number.isSafeInteger(goodsActId)) {
throw new Error("活动 ID 解析失败");
}
return {
activityId,
goodsActId,
outerType: sale.productType || sale.product_name || sale?.$goods?.product_name,
goodsType: goodsParam.type,
goodsParam,
title: sale.goods_name,
priceFen: sale.priceData.real_cost,
sessionStartMs,
};
}
let target = readTarget();
function refreshTarget(targetSessionMs = null) {
const refreshed = readTarget(targetSessionMs);
const changed = refreshed.activityId !== target.activityId
|| refreshed.goodsActId !== target.goodsActId
|| refreshed.goodsType !== target.goodsType;
target = refreshed;
if (changed) {
console.log("[TC38] 活动商品参数已更新", {
activityId: target.activityId,
goodsActId: target.goodsActId,
goodsType: target.goodsType,
});
}
return changed;
}
function chinaTimeText(timestamp) {
return new Date(timestamp + 8 * 3_600_000)
.toISOString()
.replace("T", " ")
.slice(0, 19);
}
function remainingText(milliseconds) {
// 与活动页一样显示“完整剩余秒数”,避免向上取整多出 1 秒。
const totalSeconds = Math.max(0, Math.floor(milliseconds / 1000));
const days = Math.floor(totalSeconds / 86_400);
const hours = Math.floor((totalSeconds % 86_400) / 3_600);
const minutes = Math.floor((totalSeconds % 3_600) / 60);
const seconds = totalSeconds % 60;
const clock = [hours, minutes, seconds]
.map((value) => String(value).padStart(2, "0"))
.join(":");
return days ? `${days}天 ${clock}` : clock;
}
function noStockElapsedMs(now = Date.now()) {
return noStockDetectedAt === null ? 0 : Math.max(0, now - noStockDetectedAt);
}
function retryRoundPeriodMs(elapsed = noStockElapsedMs()) {
const stage = CFG.retryRoundStages.find((item) => elapsed < item.untilMs);
return stage?.periodMs ?? CFG.retryRoundStages.at(-1).periodMs;
}
function regionsInPriorityOrder() {
const preferred = CFG.regionPriority.find(
(region) => region.id === preferredRegionId,
);
if (!preferred) return [...CFG.regionPriority];
return [
preferred,
...CFG.regionPriority.filter((region) => region.id !== preferredRegionId),
];
}
function setPreferredRegion(regionValue) {
const normalized = String(regionValue).trim();
const region = CFG.regionPriority.find(
(item) => String(item.id) === normalized || item.name === normalized,
);
if (!region) {
throw new Error(`不支持的地域:${regionValue}`);
}
preferredRegionId = region.id;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
const order = regionsInPriorityOrder().map((item) => item.name);
console.log(`[TC38] 优先地域已设为 ${region.name}`, order.join(" → "));
return order;
}
function clearMonitorTimer() {
if (monitorTimer !== null) {
clearTimeout(monitorTimer);
monitorTimer = null;
}
}
function monitorRefreshDelay() {
if (monitorTargetMs === null) return CFG.panelNormalRefreshMs;
const left = monitorTargetMs - (Date.now() + monitorClockOffsetMs);
return left <= CFG.panelFastRefreshLeadMs
? CFG.panelFastRefreshMs
: CFG.panelNormalRefreshMs;
}
function scheduleMonitorRefresh() {
clearMonitorTimer();
const tick = () => {
if (monitorState !== "monitoring") {
monitorTimer = null;
return;
}
renderMonitorPanel();
monitorTimer = setTimeout(tick, monitorRefreshDelay());
};
monitorTimer = setTimeout(tick, monitorRefreshDelay());
}
function ensureMonitorPanel() {
let panel = document.querySelector("#tc38-monitor-panel");
if (panel) return panel;
panel = document.createElement("div");
panel.id = "tc38-monitor-panel";
Object.assign(panel.style, {
position: "fixed",
zIndex: "2147483647",
top: "20px",
right: "20px",
width: "340px",
padding: "16px",
border: "1px solid #2f6feb",
borderRadius: "10px",
background: "#101828",
boxShadow: "0 8px 28px rgba(0, 0, 0, 0.3)",
color: "#f8fafc",
font: "14px/1.5 -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif",
});
panel.innerHTML = `
<div style="display:flex;align-items:center;justify-content:space-between;gap:12px">
<strong data-role="title" style="font-size:16px"></strong>
<span data-role="state" style="color:#6ee7b7"></span>
</div>
<div data-role="countdown" style="margin:12px 0 8px;font:700 30px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;color:#7dd3fc"></div>
<div data-role="target" style="color:#cbd5e1"></div>
<div data-role="offset" style="color:#94a3b8"></div>
<label style="display:flex;align-items:center;gap:8px;margin-top:8px;color:#cbd5e1">
<span>优先地域:</span>
<select data-role="preferred-region" style="flex:1;padding:5px 8px;border:1px solid #64748b;border-radius:5px;background:#1e293b;color:#f8fafc;cursor:pointer">
${CFG.regionPriority.map((region) => `<option value="${region.id}">${region.name}</option>`).join("")}
</select>
</label>
<div data-role="regions" style="margin-top:6px;color:#94a3b8"></div>
<div data-role="attempts" style="margin-top:4px;color:#94a3b8"></div>
<div data-role="stock-retries" style="margin-top:4px;color:#94a3b8"></div>
<div data-role="latency" style="margin-top:4px;color:#94a3b8"></div>
<div data-role="message" style="min-height:21px;margin-top:8px;color:#fbbf24"></div>
<div style="margin-top:12px;display:flex;gap:8px">
<button data-role="stop" type="button" style="padding:8px 13px;border:0;border-radius:6px;background:#ef4444;color:white;cursor:pointer">停止监控</button>
</div>
`;
panel.querySelector('[data-role="stop"]').addEventListener("click", cancel);
panel.querySelector('[data-role="preferred-region"]').addEventListener(
"change",
(event) => setPreferredRegion(event.currentTarget.value),
);
document.body.append(panel);
return panel;
}
function renderMonitorPanel() {
const panel = ensureMonitorPanel();
const stateLabels = {
monitoring: "持续监控中",
submitting: "循环抢购中",
paused: "网络恢复中",
stopped: "已停止",
failed: "下单失败",
success: "订单已创建",
};
const left = monitorTargetMs === null
? null
: monitorTargetMs - (Date.now() + monitorClockOffsetMs);
const stopButton = panel.querySelector('[data-role="stop"]');
const preferredSelect = panel.querySelector('[data-role="preferred-region"]');
const isStoppable = ["monitoring", "submitting", "paused"].includes(
monitorState,
);
panel.querySelector('[data-role="title"]').textContent = "腾讯云 38 元抢购";
panel.querySelector('[data-role="state"]').textContent =
stateLabels[monitorState] || monitorState;
panel.querySelector('[data-role="countdown"]').textContent = left === null
? "--:--:--"
: remainingText(left);
panel.querySelector('[data-role="target"]').textContent = monitorTargetMs === null
? `场次:${monitorSession || "-"}`
: `场次:${monitorSession}(${chinaTimeText(monitorTargetMs)})`;
panel.querySelector('[data-role="offset"]').textContent =
`服务器时差:${monitorClockOffsetMs >= 0 ? "+" : ""}${monitorClockOffsetMs} ms`;
preferredSelect.value = String(preferredRegionId);
panel.querySelector('[data-role="regions"]').textContent = `地域顺序:${regionsInPriorityOrder()
.map((region) => region.name)
.join(" → ")}`;
panel.querySelector('[data-role="attempts"]').textContent = orderRequestCount
? `抢购进度:第 ${orderRound} 轮,累计 ${orderRequestCount} 次请求`
: "抢购进度:等待开抢";
panel.querySelector('[data-role="stock-retries"]').textContent = noStockDetected
? `无库存观察:${Math.floor(Math.min(
CFG.noStockObservationMs,
noStockElapsedMs(),
) / 1000)}/${CFG.noStockObservationMs / 1000} 秒,库存探测 ${stockCheckCount} 次`
: "无库存复查:尚未触发";
const orderLatency = latencySummary(orderLatencySamples);
const stockLatency = latencySummary(stockLatencySamples);
panel.querySelector('[data-role="latency"]').textContent = [
orderLatency
? `下单 ${orderLatency.latestMs}ms(中位 ${orderLatency.medianMs}ms)`
: null,
stockLatency
? `库存 ${stockLatency.latestMs}ms(中位 ${stockLatency.medianMs}ms)`
: null,
].filter(Boolean).join(";") || "接口耗时:等待采样";
panel.querySelector('[data-role="message"]').textContent = monitorMessage;
stopButton.disabled = !isStoppable;
stopButton.textContent = monitorState === "monitoring"
? "停止监控"
: monitorState === "submitting"
? "停止抢购"
: monitorState === "paused"
? "停止恢复"
: "监控已停止";
Object.assign(stopButton.style, {
opacity: isStoppable ? "1" : "0.55",
cursor: isStoppable ? "pointer" : "not-allowed",
});
}
function beginMonitor(session, targetMs, offset) {
clearMonitorTimer();
monitorState = "monitoring";
monitorTargetMs = targetMs;
monitorClockOffsetMs = offset;
monitorSession = session;
orderRound = 0;
orderRequestCount = 0;
noStockRetryCount = 0;
noStockDetected = false;
noStockDetectedAt = null;
networkErrorStreak = 0;
networkProbeAttempt = 0;
networkPauseUntil = null;
stockCheckCount = 0;
lastStockSnapshot = null;
lastStockStateKey = "";
orderLatencySamples = [];
stockLatencySamples = [];
monitorMessage = "保持登录且电脑不休眠;临近开抢请让本页保持前台";
renderMonitorPanel();
// 平时降低刷新频率,最后 10 秒再提高到 200ms。
scheduleMonitorRefresh();
console.log(
`[TC38] 持续监控中,距离 ${session} 还有 ${remainingText(
targetMs - (Date.now() + offset),
)};点击右上角“停止监控”或执行 TC38.cancel() 可停止。`,
);
}
function finishMonitor(state, message, removePanel = false) {
clearMonitorTimer();
monitorState = state;
monitorMessage = message;
if (removePanel) {
document.querySelector("#tc38-monitor-panel")?.remove();
return;
}
renderMonitorPanel();
}
function resolveDianshiApi() {
const chunkQueue = window.webpackChunk_tencent_qcact_ssr;
if (!Array.isArray(chunkQueue)) {
throw new Error("腾讯云页面请求模块尚未加载,请刷新活动页后重试");
}
let webpackRequire;
const chunkId = `tc38_${Date.now()}_${Math.random().toString(16).slice(2)}`;
chunkQueue.push([
[chunkId],
{},
(runtimeRequire) => {
webpackRequire = runtimeRequire;
},
]);
if (typeof webpackRequire !== "function") {
throw new Error("无法连接腾讯云页面请求模块");
}
const candidateIds = ["58357"];
for (const [moduleId, factory] of Object.entries(webpackRequire.m || {})) {
if (moduleId === "58357") continue;
const source = Function.prototype.toString.call(factory);
if (source.includes("check-available") && source.includes("do-goods")) {
candidateIds.push(moduleId);
}
}
for (const moduleId of candidateIds) {
try {
const module = webpackRequire(moduleId);
const api = module?.api?.dianshi;
if (
typeof api?.checkAvailable?.request === "function"
&& typeof api?.doGoods?.request === "function"
&& typeof api?.getNow?.request === "function"
) {
return api;
}
} catch {}
}
throw new Error("当前活动页版本中未找到腾讯云官方下单模块");
}
function normalizeApiError(error) {
if (error?.response?.data && typeof error.response.data === "object") {
return error.response.data;
}
if (error && typeof error === "object") {
return {
code: error.code ?? "API_ERROR",
message: error.message || error.msg || JSON.stringify(error).slice(0, 300),
};
}
return { code: "API_ERROR", message: String(error) };
}
async function callOfficialApi(request) {
try {
return { code: 0, data: await request() };
} catch (error) {
return normalizeApiError(error);
}
}
function isNetworkFailure(payload, text) {
const code = String(payload?.code || "").toUpperCase();
const message = `${payload?.message || payload?.msg || ""} ${text}`.toLowerCase();
return ["ERR_NETWORK", "NETWORK_ERROR", "ECONNABORTED"].includes(code)
|| /network error|failed to fetch|cors|load failed|net::err_failed/.test(message);
}
async function waitForNetworkDelay(delayMs, generation, message) {
networkPauseUntil = Date.now() + delayMs;
while (generation === runGeneration) {
const left = networkPauseUntil - Date.now();
if (left <= 0) break;
const waitText = left >= 1000
? `${Math.ceil(left / 1000)} 秒`
: `${Math.ceil(left)}ms`;
monitorMessage = `${message},${waitText} 后继续`;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
await sleep(Math.min(1000, left));
}
networkPauseUntil = null;
return generation === runGeneration;
}
async function probeNetwork() {
const nowData = await dianshiApi.getNow.request();
let server = Number(nowData?.nowTime ?? nowData);
if (server > 0 && server < 10_000_000_000) server *= 1000;
if (!Number.isFinite(server) || server <= 0) {
throw new Error("网络探测未返回有效服务器时间");
}
return server;
}
async function recoverNetwork(generation) {
for (let index = 0; index < CFG.networkProbeDelaysMs.length; index++) {
networkProbeAttempt = index + 1;
monitorState = "paused";
const active = await waitForNetworkDelay(
CFG.networkProbeDelaysMs[index],
generation,
`网络异常,暂停请求;等待第 ${networkProbeAttempt}/3 次恢复探测`,
);
if (!active) return { state: "cancelled" };
monitorMessage = `正在执行第 ${networkProbeAttempt}/3 次网络恢复探测`;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
try {
await probeNetwork();
networkErrorStreak = 0;
networkProbeAttempt = 0;
networkPauseUntil = null;
monitorState = "submitting";
monitorMessage = "网络已恢复,正在从优先地域重新开始";
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
console.log("[TC38] 网络恢复探测成功,恢复下单轮询");
return { state: "recovered" };
} catch (error) {
console.warn(
`[TC38] 第 ${networkProbeAttempt}/3 次网络恢复探测失败`,
error,
);
}
}
networkPauseUntil = null;
monitorState = "submitting";
monitorMessage = "三次网络恢复探测均失败,结束当前场次";
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
return { state: "network-failed" };
}
async function handleTransportFailure(generation) {
noStockDetected = false;
noStockRetryCount = 0;
noStockDetectedAt = null;
networkErrorStreak++;
if (networkErrorStreak <= CFG.networkRetryDelaysMs.length) {
const delay = CFG.networkRetryDelaysMs[networkErrorStreak - 1];
const active = await waitForNetworkDelay(
delay,
generation,
`连续 ${networkErrorStreak}/3 次网络异常`,
);
return active ? { state: "retry" } : { state: "cancelled" };
}
console.warn("[TC38] 连续 3 次网络异常,暂停下单并启动恢复探测");
const recovery = await recoverNetwork(generation);
return recovery.state === "recovered"
? { state: "retry" }
: recovery;
}
function importCopiedFetch() {
try {
dianshiApi = resolveDianshiApi();
console.log("已连接腾讯云页面的官方请求模块,正在自动选择下一场");
start().catch((error) => {
console.error("自动抢购任务启动失败", error);
});
return true;
} catch (error) {
console.error("初始化失败", error);
throw error;
}
}
function assertApiReady() {
if (!dianshiApi) {
throw new Error("请先执行 TC38.importCopiedFetch()");
}
}
function stockState(payload, regionId) {
const text = JSON.stringify(payload).toLowerCase();
if (isManualResponse(payload, text)) return "manual";
if (isRateLimitedResponse(payload, text)) return "rate-limited";
if (isSoldOutResponse(payload, text)) return "sold-out";
if (isNotStartedResponse(payload, text)) return "not-started";
if (responseCodes(payload).some((code) => ![0, "0"].includes(code))) {
return "unavailable";
}
const queue = [payload?.data?.data, payload?.data, payload]
.filter((item) => item && typeof item === "object");
const visited = new Set();
while (queue.length) {
const record = queue.shift();
if (!record || visited.has(record)) continue;
visited.add(record);
if (Array.isArray(record)) {
queue.push(...record);
continue;
}
const quota = record?.quota?.[String(regionId)]?.[target.goodsType];
if (quota && "available" in quota) {
return Number(quota.available) > 0 ? "available" : "unavailable";
}
for (const key of [
"user_available",
"userAvailable",
"available",
"canBuy",
"enable",
]) {
if (!(key in record)) continue;
const value = record[key];
if (typeof value === "string") {
if (["1", "true", "yes"].includes(value.toLowerCase())) {
return "available";
}
if (["0", "false", "no", ""].includes(value.toLowerCase())) {
return "unavailable";
}
}
return Number(value) > 0 || value === true
? "available"
: "unavailable";
}
for (const value of Object.values(record)) {
if (value && typeof value === "object" && visited.size < 100) {
queue.push(value);
}
}
}
return "unknown";
}
function rememberLatency(samples, latencyMs) {
samples.push(latencyMs);
if (samples.length > 50) samples.shift();
}
function latencySummary(samples) {
if (!samples.length) return null;
const sorted = [...samples].sort((left, right) => left - right);
return {
latestMs: samples.at(-1),
medianMs: sorted[Math.floor(sorted.length / 2)],
maxMs: sorted.at(-1),
count: samples.length,
};
}
async function checkAllRegionStock(generation = runGeneration) {
const regions = regionsInPriorityOrder();
const startedAt = performance.now();
const payload = await callOfficialApi(
() => dianshiApi.checkAvailable.request({
activityId: target.activityId,
goods: [{
act_id: target.goodsActId,
region_id: regions.map((region) => region.id),
}],
isPreview: false,
}),
);
const latencyMs = Math.round(performance.now() - startedAt);
rememberLatency(stockLatencySamples, latencyMs);
stockCheckCount++;
const text = JSON.stringify(payload);
const results = regions.map((region) => ({
...region,
state: stockState(payload, region.id),
}));
lastStockSnapshot = {
time: chinaTimeText(Date.now() + monitorClockOffsetMs),
latencyMs,
code: responseCode(payload),
message: responseMessage(payload),
results,
payload,
};
const stockStateKey = results
.map((region) => `${region.id}:${region.state}`)
.join("|");
if (
stockStateKey !== lastStockStateKey
|| stockCheckCount === 1
|| stockCheckCount % 5 === 0
) {
console.log("库存探测", {
count: stockCheckCount,
latencyMs,
regions: results.map((region) => `${region.name}:${region.state}`).join(","),
});
}
lastStockStateKey = stockStateKey;
if (generation !== runGeneration) return { state: "cancelled" };
return {
state: "checked",
payload,
text,
results,
availableRegions: results.filter((region) => region.state === "available"),
};
}
async function dryRun() {
assertApiReady();
const results = [];
for (const region of regionsInPriorityOrder()) {
const payload = await callOfficialApi(
() => dianshiApi.checkAvailable.request({
activityId: target.activityId,
goods: [{ act_id: target.goodsActId, region_id: [region.id] }],
isPreview: false,
}),
);
results.push({
region: region.name,
code: payload?.code,
state: stockState(payload, region.id),
message: payload?.message || payload?.msg || "",
});
}
console.table(results);
return results;
}
function buildOrder(region) {
const goodsParam = structuredClone(target.goodsParam);
Object.assign(goodsParam, {
area: 1,
goodsNum: 1,
regionId: region.id,
type: target.goodsType,
});
const body = {
activity_id: target.activityId,
goods: [{
act_id: target.goodsActId,
type: target.outerType,
goods_param: goodsParam,
page_from: "act_buy",
}],
preview: 0,
agent_channel: {
fromChannel: "",
fromSales: "",
isAgentClient: false,
fromUrl: location.href,
},
};
return body;
}
function responseCodes(payload) {
const values = [
payload?.code,
payload?.data?.code,
payload?.data?.data?.code,
payload?.data?.detail?.code,
payload?.data?.detail?.errCode,
payload?.data?.detail?.status,
payload?.data?.data?.detail?.code,
payload?.data?.data?.detail?.errCode,
payload?.data?.data?.detail?.status,
];
return values.filter((value) => value !== undefined && value !== null);
}
function responseCode(payload) {
const codes = responseCodes(payload);
return codes.find((value) => ![0, "0"].includes(value)) ?? codes[0];
}
function responseMessage(payload) {
const candidates = [payload, payload?.data, payload?.data?.data];
for (const candidate of candidates) {
const message = candidate?.message || candidate?.msg;
if (message) return String(message);
}
return "";
}
function orderResultData(payload) {
const candidates = [payload?.data, payload?.data?.data, payload];
return candidates.find((data) => data && typeof data === "object" && (
"deal_names" in data
|| "big_deal_no" in data
|| "seqId" in data
|| Object.values(data).some(
(value) => typeof value === "string" && value.includes("order/check"),
)
));
}
function hasResponseCode(payload, expectedCodes) {
const expected = new Set(expectedCodes.map(Number));
return responseCodes(payload).some((code) => expected.has(Number(code)));
}
function isSoldOutResponse(payload, lowerText) {
return /sold.?out|抢光|售罄/.test(lowerText)
|| hasResponseCode(payload, [20001, 10002, 1100151, 1000703]);
}
function isNotStartedResponse(payload, lowerText) {
return /not.?started|not_start|未开始|尚未开始/.test(lowerText)
|| hasResponseCode(payload, [10001, 1101001]);
}
function isManualResponse(payload, lowerText) {
return /captcha|验证码|人机验证|风险验证|need.?login|not.?login|unauthoriz|登录态|登陆态|请.{0,8}登录|csrf|鉴权失败|认证失败|校验失败|token.{0,20}(invalid|expired|失效|过期)/.test(
lowerText,
);
}
function isRateLimitedResponse(payload, lowerText) {
return /too many|rate.?limit|频率过快|访问频率|限制访问|请求受限|access denied|forbidden|edgeone/.test(
lowerText,
) || hasResponseCode(payload, [403, 408, 429, 567, 1100110]);
}
function isAmbiguousSuccessResponse(payload) {
const codes = responseCodes(payload);
return codes.length > 0 && codes.every((code) => [0, "0"].includes(code));
}
function orderState(payload, text) {
const lower = text.toLowerCase();
if (orderResultData(payload)) {
return "pending-payment";
}
if (isSoldOutResponse(payload, lower)) return "sold-out";
if (isNotStartedResponse(payload, lower)) return "not-started";
if (isManualResponse(payload, lower)) return "manual";
if (isRateLimitedResponse(payload, lower)) return "rate-limited";
if (isAmbiguousSuccessResponse(payload)) return "ambiguous-success";
return "unknown";
}
function paymentUrlFromPayload(payload) {
const fallback = "https://buy.cloud.tencent.com/order/check";
const data = orderResultData(payload) || payload?.data;
if (!data || typeof data !== "object") return fallback;
const candidates = [
data.url,
data.redirectUrl,
data.redirect_url,
data.orderUrl,
data.order_url,
];
for (const candidate of candidates) {
if (typeof candidate !== "string" || !candidate) continue;
try {
const url = new URL(candidate, fallback);
if (
url.hostname === "buy.cloud.tencent.com"
&& url.pathname.startsWith("/order/")
) {
return url.href;
}
} catch {}
}
const url = new URL(fallback);
const bigDealId = Array.isArray(data.big_deal_no)
? data.big_deal_no.join("|")
: data.big_deal_no;
const dealName = Array.isArray(data.deal_names)
? data.deal_names.join("|")
: data.deal_names;
if (bigDealId) url.searchParams.set("bigDealId", bigDealId);
if (!bigDealId && dealName) url.searchParams.set("dealName", dealName);
url.searchParams.set("s_url", location.href);
url.searchParams.set("serviceFrom", "activity");
return url.href;
}
function showPaymentLink(
paymentUrl,
regionName,
titleText = `订单已创建(${regionName})`,
) {
clearMonitorTimer();
document.querySelector("#tc38-monitor-panel")?.remove();
document.querySelector("#tc38-payment-link")?.remove();
const panel = document.createElement("div");
panel.id = "tc38-payment-link";
Object.assign(panel.style, {
position: "fixed",
zIndex: "2147483647",
top: "20px",
right: "20px",
width: "320px",
padding: "18px",
border: "1px solid #57a564",
borderRadius: "10px",
background: "#f2fff4",
boxShadow: "0 8px 28px rgba(0, 0, 0, 0.22)",
color: "#183b20",
font: "14px/1.5 -apple-system, BlinkMacSystemFont, Segoe UI, sans-serif",
});
const title = document.createElement("strong");
title.textContent = titleText;
title.style.display = "block";
title.style.marginBottom = "12px";
const link = document.createElement("a");
link.href = paymentUrl;
link.target = "_blank";
link.rel = "noopener noreferrer";
link.textContent = "打开订单支付页";
Object.assign(link.style, {
display: "inline-block",
padding: "9px 16px",
borderRadius: "6px",
background: "#006eff",
color: "#fff",
fontWeight: "600",
textDecoration: "none",
});
const close = document.createElement("button");
close.type = "button";
close.textContent = "关闭";
close.addEventListener("click", () => panel.remove());
Object.assign(close.style, {
marginLeft: "10px",
padding: "8px 12px",
border: "1px solid #aab4c3",
borderRadius: "6px",
background: "#fff",
cursor: "pointer",
});
panel.append(title, link, close);
document.body.append(panel);
}
async function fire(generation = runGeneration) {
assertApiReady();
orderRound = 0;
orderRequestCount = 0;
noStockRetryCount = 0;
noStockDetected = false;
noStockDetectedAt = null;
networkErrorStreak = 0;
networkProbeAttempt = 0;
networkPauseUntil = null;
lastOrderResponses = [];
stockCheckCount = 0;
lastStockSnapshot = null;
lastStockStateKey = "";
orderLatencySamples = [];
stockLatencySamples = [];
const submissionStartedAt = Date.now();
let lastDirectSweepAt = 0;
let unknownOrderStreak = 0;
orderLoop:
while (generation === runGeneration) {
if (
noStockDetected
&& noStockElapsedMs() >= CFG.noStockObservationMs
) {
monitorMessage = `所有地域持续无库存,已观察 ${CFG.noStockObservationMs / 1000} 秒,结束当前场次`;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
console.warn(`[TC38] 所有地域持续无库存,已观察 ${CFG.noStockObservationMs / 1000} 秒,结束当前场次`);
return {
state: "sold-out",
noStockRetryCount,
requestCount: orderRequestCount,
};
}
const roundStartedAt = Date.now();
const allRegions = regionsInPriorityOrder();
let regionsForRound = allRegions;
const stockMode = noStockDetected
&& noStockElapsedMs() >= CFG.directSubmitWindowMs;
const directSentinelDue = Date.now() - lastDirectSweepAt
>= CFG.directSentinelIntervalMs;
if (stockMode && !directSentinelDue) {
monitorMessage = `无库存观察中:正在执行第 ${stockCheckCount + 1} 次库存探测`;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
const stockStartedAt = Date.now();
const stock = await checkAllRegionStock(generation);
if (stock.state === "cancelled") return stock;
const states = stock.results.map((region) => region.state);
if (states.includes("manual")) {
monitorMessage = "库存接口要求登录、认证或风控处理,已停止本场请求";
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
console.error("[TC38] 库存探测需要人工处理", lastStockSnapshot);
return { state: "manual" };
}
const transportFailure = isNetworkFailure(stock.payload, stock.text)
|| states.includes("rate-limited");
if (transportFailure) {
const handling = await handleTransportFailure(generation);
if (handling.state === "retry") continue orderLoop;
return handling;
}
networkErrorStreak = 0;
networkProbeAttempt = 0;
networkPauseUntil = null;
if (states.includes("not-started")) {
noStockDetected = false;
noStockRetryCount = 0;
noStockDetectedAt = null;
monitorMessage = "库存接口显示尚未开始,恢复直接提交确认";
continue;
}
if (stock.availableRegions.length) {
regionsForRound = stock.availableRegions;
monitorMessage = `库存接口显示 ${regionsForRound.map((region) => region.name).join("、")} 可用,立即提交`;
} else {
noStockRetryCount++;
monitorMessage = `库存探测未发现可用地域,已观察 ${(noStockElapsedMs() / 1000).toFixed(1)}/${CFG.noStockObservationMs / 1000} 秒`;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
const delayMs = Math.max(
0,
CFG.stockPollPeriodMs - (Date.now() - stockStartedAt),
);
if (delayMs > 0) await sleep(delayMs);
continue;
}
}
orderRound++;
let allRegionsSoldOut = true;
let restartOuterLoop = false;
for (const region of regionsForRound) {
if (generation !== runGeneration) return { state: "cancelled" };
orderRequestCount++;
monitorMessage = `第 ${orderRound} 轮:正在尝试 ${region.name}(累计 ${orderRequestCount} 次)`;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
const order = buildOrder(region);
const requestStartedAt = performance.now();
const payload = await callOfficialApi(
() => dianshiApi.doGoods.request({
activityId: order.activity_id,
goods: order.goods,
isPreview: false,
agentChannel: order.agent_channel,
business: order.business,
}),
);
const latencyMs = Math.round(performance.now() - requestStartedAt);
rememberLatency(orderLatencySamples, latencyMs);
const text = JSON.stringify(payload);
const state = orderState(payload, text);
const code = responseCode(payload);
const message = responseMessage(payload);
lastOrderResponses.push({
time: chinaTimeText(Date.now() + monitorClockOffsetMs),
region: region.name,
regionId: region.id,
round: orderRound,
requestCount: orderRequestCount,
code,
state,
message,
latencyMs,
payload,
});
if (lastOrderResponses.length > 12) lastOrderResponses.shift();
if (
state !== "sold-out"
|| orderRequestCount <= CFG.regionPriority.length
|| orderRequestCount % 10 === 0
) {
console.log("下单返回", {
region: region.name,
round: orderRound,
requestCount: orderRequestCount,
code,
state,
message,
latencyMs,
});
}
if (state === "pending-payment") {
const paymentUrl = paymentUrlFromPayload(payload);
showPaymentLink(paymentUrl, region.name);
console.log("订单已创建,点击下面的 URL 打开支付页:");
console.log(paymentUrl);
return { state, region: region.name, paymentUrl };
}
if (state === "ambiguous-success") {
const paymentUrl = "https://buy.cloud.tencent.com/order/check";
showPaymentLink(
paymentUrl,
region.name,
`接口返回成功,请核对订单(${region.name})`,
);
console.warn(
"[TC38] 接口返回 code=0 但没有订单标记,已停止继续提交,请打开订单页核对",
payload,
);
return {
state: "manual-review",
region: region.name,
paymentUrl,
};
}
if (state === "manual") {
monitorMessage = `腾讯云要求登录、认证或风控处理,已停止继续提交(${message || code})`;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
console.error("[TC38] 需要人工处理,已停止本场请求", {
region: region.name,
code,
message,
});
return { state: "manual", region: region.name, code, message };
}
if (generation !== runGeneration) return { state: "cancelled" };
const transportFailure =
isNetworkFailure(payload, text) || state === "rate-limited";
if (transportFailure) {
allRegionsSoldOut = false;
const handling = await handleTransportFailure(generation);
if (handling.state !== "retry") return handling;
restartOuterLoop = true;
break;
}
networkErrorStreak = 0;
networkProbeAttempt = 0;
networkPauseUntil = null;
if (state === "sold-out") {
unknownOrderStreak = 0;
if (noStockDetected) noStockRetryCount++;
} else if (state === "not-started") {
unknownOrderStreak = 0;
noStockDetected = false;
noStockRetryCount = 0;
noStockDetectedAt = null;
}
if (state !== "sold-out") {
allRegionsSoldOut = false;
}
if (state === "unknown") {
unknownOrderStreak++;
console.warn("本次返回无法分类,将有限次复核", {
region: region.name,
state,
code,
message,
unknownOrderStreak,
});
if (unknownOrderStreak >= CFG.maxUnknownResponses) {
monitorMessage = `连续 ${unknownOrderStreak} 次返回无法分类,已停止以避免异常请求`;
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
console.error("[TC38] 连续收到未知响应,已停止本场请求;请执行 TC38.diagnostics() 查看详情");
return { state: "unclassified", code, message };
}
}
}
if (restartOuterLoop) continue orderLoop;
if (generation !== runGeneration) return { state: "cancelled" };
lastDirectSweepAt = Date.now();
const checkedAllRegions = regionsForRound.length === allRegions.length
&& allRegions.every((region) => (
regionsForRound.some((checked) => checked.id === region.id)
));
if (allRegionsSoldOut && checkedAllRegions && !noStockDetected) {
noStockDetected = true;
noStockRetryCount = 0;
noStockDetectedAt = Date.now();
monitorMessage = `检测到所有地域无库存,继续观察 ${CFG.noStockObservationMs / 1000} 秒`;
} else if (noStockDetected) {
monitorMessage = `所有地域仍无库存,已观察 ${(noStockElapsedMs() / 1000).toFixed(1)}/${CFG.noStockObservationMs / 1000} 秒`;
} else {
monitorMessage = `第 ${orderRound} 轮未创建订单,继续下一轮`;
}
if (noStockDetected && noStockElapsedMs() >= CFG.noStockObservationMs) {
continue;
}
if (stockMode) {
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
continue;
}
const pacingElapsedMs = noStockDetected
? noStockElapsedMs()
: Date.now() - submissionStartedAt;
const targetRoundPeriodMs = retryRoundPeriodMs(pacingElapsedMs);
const roundElapsedMs = Date.now() - roundStartedAt;
const delayMs = Math.max(0, targetRoundPeriodMs - roundElapsedMs);
if (delayMs > 0) {
monitorMessage += `;${delayMs}ms 后继续`;
}
if (document.querySelector("#tc38-monitor-panel")) renderMonitorPanel();
if (delayMs > 0) await sleep(delayMs);
}
return { state: "cancelled" };
}
async function fireNow() {
acquireRunLease();
try {
return await fireNowInternal();
} finally {
releaseRunLease();
}
}
async function fireNowInternal() {
assertApiReady();
refreshTarget();
const generation = ++runGeneration;
scheduledFor = null;
clearMonitorTimer();
monitorState = "submitting";
monitorTargetMs = null;
monitorSession = "立即下单";
monitorMessage = "正在立即循环尝试创建订单";
renderMonitorPanel();
const result = await fire(generation);
if (result.state === "pending-payment") {
finishMonitor("success", "订单已创建,请尽快支付", true);
} else if (result.state === "manual-review") {
monitorState = "stopped";
} else if (result.state === "manual") {
finishMonitor("failed", "腾讯云要求重新登录、认证或完成风控验证");
} else if (result.state !== "cancelled") {
finishMonitor("failed", "抢购已停止,具体原因请查看 Console");
}
return result;
}
async function serverOffset() {
assertApiReady();
const offsets = [];
for (let index = 0; index < 3; index++) {
const before = Date.now();
const nowData = await dianshiApi.getNow.request();
const after = Date.now();
let server = Number(nowData?.nowTime ?? nowData);
if (server > 0 && server < 10_000_000_000) server *= 1000;
if (Number.isFinite(server)) {
offsets.push(server - Math.round((before + after) / 2));
}
if (index < 2) await sleep(80);
}
if (!offsets.length) throw new Error("服务器时间同步失败");
offsets.sort((left, right) => left - right);
return offsets[Math.floor(offsets.length / 2)];
}
function nextSessionChina(serverNowMs) {
const china = new Date(serverNowMs + 8 * 3_600_000);
const ten = Date.UTC(
china.getUTCFullYear(),
china.getUTCMonth(),
china.getUTCDate(),
10 - 8,
0,
0,
0,
);
const fifteen = Date.UTC(
china.getUTCFullYear(),
china.getUTCMonth(),
china.getUTCDate(),
15 - 8,
0,
0,
0,
);
if (serverNowMs <= ten) {
return { targetMs: ten, label: "今天 10:00" };
}
if (serverNowMs <= fifteen) {
return { targetMs: fifteen, label: "今天 15:00" };
}
return {
targetMs: ten + 24 * 3_600_000,
label: "明天 10:00",
};
}
async function start(forcedSession = null) {
acquireRunLease();
try {
return await startInternal(forcedSession);
} finally {
releaseRunLease();
}
}
async function startInternal(forcedSession = null) {
assertApiReady();
const generation = ++runGeneration;
let offset = forcedSession?.offset;
if (!Number.isFinite(offset)) {
offset = await serverOffset();
}
if (generation !== runGeneration) return { state: "cancelled" };
const nowServer = Date.now() + offset;
const session = forcedSession
? {
targetMs: Number(forcedSession.targetMs),
label: String(forcedSession.label),
}
: nextSessionChina(nowServer);
const { targetMs } = session;
if (!Number.isFinite(targetMs)) {
throw new Error("目标场次时间无效");
}
refreshTarget(targetMs);
const waitMs = targetMs - nowServer;
let finalClockSyncPending = waitMs > CFG.finalClockSyncLeadMs;
let lastClockSyncPending = waitMs > CFG.lastClockSyncLeadMs;
scheduledFor = session.label;
beginMonitor(session.label, targetMs, offset);
console.log(
`[TC38] 已选择 ${session.label},距离开抢 ${remainingText(waitMs)},服务器时差 ${offset >= 0 ? "+" : ""}${offset}ms`,
);
while (true) {
if (generation !== runGeneration) return { state: "cancelled" };
const left = targetMs - (Date.now() + offset);
if (finalClockSyncPending && left <= CFG.finalClockSyncLeadMs) {
finalClockSyncPending = false;
try {
const refreshedOffset = await serverOffset();
if (generation !== runGeneration) return { state: "cancelled" };
offset = refreshedOffset;
monitorClockOffsetMs = refreshedOffset;
try {
refreshTarget(targetMs);
} catch (error) {
console.warn("[TC38] 临场商品参数刷新失败,继续使用已解析参数", error);
}
monitorMessage = "开抢前 60 秒已重新同步腾讯云服务器时间";
renderMonitorPanel();
console.log("[TC38] 临场服务器时间同步完成", {
clockOffsetMs: refreshedOffset,
});
continue;
} catch (error) {
monitorMessage = "临场校时失败,继续使用上次服务器时差";
renderMonitorPanel();
console.warn("[TC38] 临场服务器时间同步失败", error);
}
}
if (lastClockSyncPending && left <= CFG.lastClockSyncLeadMs) {
lastClockSyncPending = false;
try {
const refreshedOffset = await serverOffset();
if (generation !== runGeneration) return { state: "cancelled" };
offset = refreshedOffset;
monitorClockOffsetMs = refreshedOffset;
try {
refreshTarget(targetMs);
} catch (error) {
console.warn("[TC38] 最后校时商品参数刷新失败,继续使用本场参数", error);
}
monitorMessage = "开抢前 5 秒已完成最后校时和接口预热";
renderMonitorPanel();
console.log("[TC38] 最后服务器时间同步完成", {
clockOffsetMs: refreshedOffset,
});
continue;
} catch (error) {
monitorMessage = "最后校时失败,继续使用上次服务器时差";
renderMonitorPanel();
console.warn("[TC38] 最后服务器时间同步失败", error);
}
}
if (left <= 20) break;
await sleep(Math.min(200, Math.max(1, left - 10)));
}
while (Date.now() + offset < targetMs) {}
if (generation !== runGeneration) return { state: "cancelled" };
try {
refreshTarget(targetMs);
} catch (error) {
console.warn("[TC38] 开抢前刷新商品参数失败,继续使用本场已解析参数", error);
}
clearMonitorTimer();
monitorState = "submitting";
monitorMessage = "已到开抢时间,正在发送创建订单请求";
renderMonitorPanel();
const result = await fire(generation);
scheduledFor = null;
if (result.state === "pending-payment") {
finishMonitor("success", "订单已创建,请尽快支付", true);
} else if (result.state === "manual-review") {
monitorState = "stopped";
} else if (result.state === "manual") {
finishMonitor("failed", "腾讯云要求重新登录、认证或完成风控验证");
} else if (["sold-out", "network-failed"].includes(result.state)) {
const finishedHour =
new Date(targetMs + 8 * 3_600_000).getUTCHours();
const nextSessionText = finishedHour === 10
? "今天 15:00"
: "明天 10:00";
const nextTargetMs = targetMs + (finishedHour === 10 ? 5 : 19) * 3_600_000;
const finishReason = result.state === "sold-out"
? "已无库存"
: "网络恢复失败";
monitorState = "monitoring";
monitorMessage =
`${finishedHour}:00 场${finishReason},正在自动切换到 ${nextSessionText}`;
renderMonitorPanel();
console.log(
`[TC38] ${finishedHour}:00 场${finishReason},自动继续监控 ${nextSessionText}`,
);
try {
return await startInternal({
targetMs: nextTargetMs,
label: nextSessionText,
offset,
});
} catch (error) {
if (/活动页中没有.+场的目标商品/.test(String(error?.message || error))) {
finishMonitor(
"stopped",
"活动页预载场次已用完,请刷新页面并重新粘贴脚本",
);
console.warn("[TC38] 活动页数据已过期,未继续跨日运行", error);
return { state: "refresh-required" };
}
throw error;
}
} else if (result.state !== "cancelled") {
finishMonitor("failed", "未创建订单,具体原因请查看 Console");
}
return result;
}
function cancel() {
if (
!["monitoring", "submitting", "paused"].includes(monitorState)
&& !scheduledFor
) {
console.log("[TC38] 当前没有正在等待的监控任务");
return false;
}
const activeOrderFlow = ["submitting", "paused"].includes(monitorState);
runGeneration++;
scheduledFor = null;
clearMonitorTimer();
monitorState = "stopped";
monitorTargetMs = null;
networkPauseUntil = null;
releaseRunLease(true);
monitorMessage = activeOrderFlow
? "已停止网络恢复及后续重试;已发出的当前请求无法撤回"
: "已停止,不会在开抢时间发送下单请求";
renderMonitorPanel();
console.log("[TC38] 已停止监控及后续重试");
return true;
}
function status() {
const remaining = monitorTargetMs === null || monitorState !== "monitoring"
? null
: remainingText(
monitorTargetMs - (Date.now() + monitorClockOffsetMs),
);
const info = {
activityId: target.activityId,
goodsActId: target.goodsActId,
priceYuan: target.priceFen / 100,
goodsType: target.goodsType,
officialApiReady: Boolean(dianshiApi),
scheduledFor,
monitorState,
remaining,
orderRound,
orderRequestCount,
noStockDetected,
noStockRetryCount,
noStockObservedMs: noStockElapsedMs(),
stockCheckCount,
networkErrorStreak,
networkProbeAttempt,
networkPauseUntil,
currentRoundPeriodMs: retryRoundPeriodMs(),
noStockObservationMs: CFG.noStockObservationMs,
orderLatency: latencySummary(orderLatencySamples),
stockLatency: latencySummary(stockLatencySamples),
stopCommand: "TC38.cancel()",
regions: regionsInPriorityOrder()
.map((region) => `${region.name}(${region.id})`)
.join(" → "),
};
return info;
}
function diagnostics() {
const summary = lastOrderResponses.map(({ payload, ...item }) => item);
console.table(summary);
console.log("[TC38] 最近下单接口原始返回", lastOrderResponses);
if (lastStockSnapshot) {
const { payload, ...stockSummary } = lastStockSnapshot;
console.log("[TC38] 最近库存探测", stockSummary, payload);
}
const result = {
orders: lastOrderResponses.slice(),
stock: lastStockSnapshot,
latency: {
order: latencySummary(orderLatencySamples),
stock: latencySummary(stockLatencySamples),
},
};
return result;
}
window.TC38 = {
importCopiedFetch,
dryRun,
start,
fireNow,
setPreferredRegion,
cancel,
status,
diagnostics,
};
window.addEventListener("pagehide", () => releaseRunLease(true), {
once: true,
});
console.log("TC38 已加载,正在自动初始化并启动");
queueMicrotask(() => {
try {
importCopiedFetch();
} catch {}
});
})();
七、使用脚本前需要注意什么?
这个脚本不是腾讯云官方工具,也没有得到腾讯云官方背书。
使用前需要注意:
- 必须遵守腾讯云活动规则、服务条款和适用法律。
- 如果活动规则不允许自动化请求,请不要运行脚本。
- 循环请求可能触发访问频率限制、验证码或账号风控。
- 出现限流、验证或异常提示时,应立即执行
TC38.cancel()。 - 腾讯云活动页或内部接口更新后,脚本可能失效。
- 浏览器休眠、后台节流和网络波动会影响执行时间。
- 脚本不能绕过账号资格、实名认证、库存或风控限制。
- 不要将账号密码、Cookie 或其他敏感信息交给陌生人。
脚本的定位是个人技术实验和操作辅助,不是“保证抢到”的工具。当天不再参与时,应主动停止脚本,不建议无人值守连续运行。
八、创建订单后先检查这些信息
即使脚本已经创建待支付订单,也不要直接付款,建议逐项检查:
- 是否为自己的腾讯云账号
- 最终价格是否符合预期
- 购买时长是否为 1 年
- CPU、内存、带宽和月流量是否正确
- 地域是否适合自己的用户群体
- 是否限制新客或产品首购资格
- 活动商品是否支持退款
- 第二年正常续费价格是多少
首年活动价通常不等于后续续费价格。如果只是用于学习或短期项目,应在到期前做好数据备份和迁移准备。
九、常见问题
所有腾讯云账号都能买到 38 元服务器吗?
不一定。活动可能限制新用户、产品首购用户、实名认证主体或购买数量,以登录后的活动页面提示为准。
脚本会自动付款吗?
不会。脚本最多只创建待支付订单,付款仍然需要人工完成。
使用脚本一定能够抢到吗?
不能保证。结果仍然取决于库存、账号资格、活动规则、网络环境和腾讯云风控。
为什么脚本检查多个地域?
同一个商品在不同地域可能有不同的库存状态。脚本会按设定顺序检查广州、上海和北京,但服务器地域最终应根据访问用户的位置选择。
没有成功需要一直运行吗?
不建议无人值守连续运行。当天不再参与时,应执行 TC38.cancel()。准备参与下一场前,重新打开活动页、确认登录状态并加载最新版脚本。
十、总结
腾讯云此次活动中的 4 核 4G 服务器新客 38 元/年起,对个人开发者、博客站长和轻量项目有一定吸引力。
购买前不能只看 CPU 和内存,还要关注 3Mbps 公网带宽、300GB 月流量、可选地域、活动资格、退款规则和后续续费价格。
Console 脚本可以减少倒计时、切换地域和检查状态的重复操作,但它不能绕过活动规则,也不能保证创建订单成功。使用脚本前应阅读源码,出现限流或验证提示时及时停止。
如果还在比较不同厂商和配置,也可以继续查看本站整理的云服务器相关文章。
准备购买前,可以先打开活动页,查看自己的账号是否显示目标商品和价格: