























直接贴代码了,懒得搞个文件上传了,ai vibe 的,使用的话,可以让 ai 帮你看看怎么用
比如 SHAREDCHAT_USERNAME=(你的 qq 邮箱) SHAREDCHAT_PASSWORD=(你的密码)
xxx.sh 就可以了
需要 node ,npm 环境,本质就是给你打开一个浏览器,其他的都会自动处理的,已经领取过的也会提示已领取,自用了几天了,没什么太大问题
#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${SHAREDCHAT_BASE_URL:-https://new.sharedchat.cc}"
USERNAME="${SHAREDCHAT_USERNAME}"
PASSWORD="${SHAREDCHAT_PASSWORD}"
REASON="${SHAREDCHAT_REASON:-用于开发个人项目,学习code的使用 $(date +%s)}"
HEADLESS="${HEADLESS:-1}"
PLAYWRIGHT_VERSION="${PLAYWRIGHT_VERSION:-1.60.0}"
WORK_DIR="${SHAREDCHAT_WORK_DIR:-${TMPDIR:-/tmp}/sharedchat-codex-claim}"
if [[ -z "$PASSWORD" ]]; then
printf "SharedChat password: " >&2
IFS= read -rs PASSWORD
printf "\n" >&2
fi
if [[ -z "$PASSWORD" ]]; then
echo "Password is required. Set SHAREDCHAT_PASSWORD or enter it at the prompt." >&2
exit 2
fi
if ! command -v node >/dev/null 2>&1; then
echo "node is required." >&2
exit 2
fi
if ! command -v npm >/dev/null 2>&1; then
echo "npm is required to install playwright-core." >&2
exit 2
fi
if [[ -z "${CHROME_PATH:-}" ]]; then
for candidate in \
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
"/Applications/Chromium.app/Contents/MacOS/Chromium" \
"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"; do
if [[ -x "$candidate" ]]; then
CHROME_PATH="$candidate"
break
fi
done
fi
if [[ -z "${CHROME_PATH:-}" || ! -x "$CHROME_PATH" ]]; then
echo "Chrome was not found. Set CHROME_PATH to your Chrome executable." >&2
exit 2
fi
mkdir -p "$WORK_DIR"
cd "$WORK_DIR"
if [[ ! -d node_modules/playwright-core ]]; then
npm init -y >/dev/null
npm install "playwright-core@$PLAYWRIGHT_VERSION" >/dev/null
fi
export BASE_URL USERNAME PASSWORD REASON HEADLESS CHROME_PATH
node <<'NODE'
const { chromium } = require('playwright-core');
const baseUrl = process.env.BASE_URL;
const username = process.env.USERNAME;
const password = process.env.PASSWORD;
const reason = process.env.REASON;
const chromePath = process.env.CHROME_PATH;
const headless = process.env.HEADLESS === '1';
function pickCodexQuota(payload) {
return payload?.data?.codex || null;
}
async function readJsonResponse(response) {
try {
return JSON.parse(await response.text());
} catch {
return null;
}
}
(async () => {
const browser = await chromium.launch({
executablePath: chromePath,
headless,
args: [
'--disable-blink-features=AutomationControlled',
'--no-first-run',
'--no-default-browser-check',
],
});
const context = await browser.newContext({
locale: 'zh-CN',
timezoneId: 'Asia/Shanghai',
viewport: { width: 1280, height: 900 },
});
await context.addInitScript(() => {
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
});
const page = await context.newPage();
try {
await page.goto(`${baseUrl}/list/#/login`, { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('networkidle', { timeout: 30000 }).catch(() => {});
const inputs = page.locator('input');
await inputs.nth(0).fill(username);
await inputs.nth(1).fill(password);
await page.locator('button.submit-btn').first().click();
await page.waitForResponse(
(response) => response.url().includes('/frontend-api/getme') && response.status() === 200,
{ timeout: 30000 }
);
await page.goto(`${baseUrl}/list/#/vibe-code/dashboard`, { waitUntil: 'domcontentloaded' });
const quotaResponse = await page.waitForResponse(
(response) =>
response.url().includes('/frontend-api/vibe-code/quota') && response.status() === 200,
{ timeout: 30000 }
);
const quotaPayload = await readJsonResponse(quotaResponse);
const codex = pickCodexQuota(quotaPayload);
const sub = codex?.subscriptions || null;
if (sub?.isActive) {
console.log(
JSON.stringify(
{
ok: true,
status: 'already_active',
message: 'Codex subscription is already active.',
expireTime: sub.expireTime,
remainingAmount: sub.remainingAmount,
},
null,
2
)
);
return;
}
const claimButton = page
.getByRole('button', { name: /领取\s*Codex\s*权益|Claim\s*Codex\s*Access/i })
.first();
await claimButton.waitFor({ state: 'visible', timeout: 30000 });
await claimButton.click();
const textarea = page.locator('textarea').last();
await textarea.waitFor({ state: 'visible', timeout: 10000 });
await textarea.fill(reason);
const claimResponsePromise = page.waitForResponse(
(response) => response.url().includes('/frontend-api/vibe-code/codex/claim'),
{ timeout: 60000 }
);
await page.getByRole('button', { name: /^领取$|^Claim$/i }).click();
const claimResponse = await claimResponsePromise;
const claimPayload = await readJsonResponse(claimResponse);
const data = claimPayload?.data || {};
if (!data.claimed) {
console.log(
JSON.stringify(
{
ok: false,
status: 'claim_failed',
message: data.message || claimPayload?.msg || 'Claim failed.',
response: claimPayload,
},
null,
2
)
);
process.exitCode = 1;
return;
}
console.log(
JSON.stringify(
{
ok: true,
status: 'claimed',
message: data.message || 'Claim succeeded.',
subscriptionId: data.subscriptionId,
expireTime: data.expireTime,
},
null,
2
)
);
} finally {
await browser.close();
}
})().catch((error) => {
console.error(JSON.stringify({ ok: false, status: 'error', message: String(error) }, null, 2));
process.exit(1);
});
NODE
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。