add dcloud-renew

This commit is contained in:
luk
2026-07-30 22:09:46 +08:00
parent 0eb30b6361
commit e3ffcbc06c
6 changed files with 203 additions and 0 deletions

110
dcloud-renew/renew.mjs Normal file
View File

@@ -0,0 +1,110 @@
import 'dotenv/config'
import { chromium } from 'playwright'
const email = process.env.UNICLOUD_EMAIL
const password = process.env.UNICLOUD_PASSWORD
if (!email || !password) {
throw new Error('Missing UNICLOUD_EMAIL or UNICLOUD_PASSWORD')
}
async function waitForLoginFrame (page, timeoutMs = 30000) {
const start = Date.now()
while (Date.now() - start < timeoutMs) {
const f = page.frames().find(fr => fr.url().includes('account.dcloud.net.cn'))
if (f) return f
await page.waitForTimeout(500)
}
throw new Error('Timed out waiting for account.dcloud.net.cn login iframe')
}
async function waitForUrl (page, predicate, timeoutMs = 30000) {
const start = Date.now()
while (Date.now() - start < timeoutMs) {
if (predicate(page.url())) return page.url()
await page.waitForTimeout(500)
}
throw new Error(`Timed out waiting for URL condition. Current: ${page.url()}`)
}
;(async () => {
const browser = await chromium.launch({
channel: 'msedge',
headless: false,
slowMo: 200
})
const context = await browser.newContext()
const page = await context.newPage()
page.setDefaultTimeout(30000)
await page.goto('https://unicloud.dcloud.net.cn/', {
waitUntil: 'domcontentloaded',
timeout: 60000
})
console.log('Page loaded, waiting for login iframe...')
// 1. Login via the account.dcloud.net.cn iframe.
const loginFrame = await waitForLoginFrame(page)
await loginFrame.waitForSelector('input.uni-input-input', { timeout: 20000 })
await page.waitForTimeout(1500)
const inputs = loginFrame.locator('input.uni-input-input')
if ((await inputs.count()) < 2) {
throw new Error('Expected 2 inputs in login iframe')
}
await inputs.nth(0).click({ clickCount: 3 })
await inputs.nth(0).fill(email)
await inputs.nth(1).click({ clickCount: 3 })
await inputs.nth(1).fill(password)
await loginFrame.getByText('登录', { exact: true }).click()
await waitForUrl(page, u => u.includes('unicloud.dcloud.net.cn') && !u.includes('/login/login'))
await page.waitForTimeout(5000)
console.log('Login successful. URL:', page.url())
// 2. Click "续费" — opens a NEW TAB that first goes through SSO
// (uni-trade.dcloud.net.cn/pages/login/login?oauthToken=...) then lands
// on the create-order page.
const renewBtn = page.getByText('续费', { exact: true }).first()
await renewBtn.waitFor({ timeout: 30000 })
const newPagePromise = new Promise(resolve => context.once('page', resolve))
await renewBtn.click()
const orderPage = await newPagePromise
// Wait for the OAuth redirect to settle on create-order.
await waitForUrl(
orderPage,
u => u.includes('uni-trade.dcloud.net.cn') && u.includes('create-order'),
45000
)
await orderPage.waitForTimeout(3000)
console.log('Order page ready:', orderPage.url())
// 3. Click "立即购买" — same tab navigates to /order-payment.
const buyBtn = orderPage.getByText('立即购买', { exact: true }).first()
await buyBtn.waitFor({ timeout: 30000 })
await buyBtn.click()
await waitForUrl(
orderPage,
u => u.includes('order-payment'),
30000
)
await orderPage.waitForTimeout(3000)
console.log('Payment page ready:', orderPage.url())
// 4. Click "确认开通" to finalize.
const confirmBtn = orderPage.getByText('确认开通', { exact: true }).first()
await confirmBtn.waitFor({ timeout: 30000 })
await confirmBtn.click()
console.log('Clicked 确认开通. Renewal submitted.')
// Wait briefly for the confirmation redirect to complete, then exit.
await orderPage.waitForTimeout(5000)
await browser.close()
process.exit(0)
})()