文章详情

返回首页

CF上部署webhostmost帐号保活

分享文章 作者: Ws01 创建时间: 2025-11-24 更新时间: 2025-12-28 📝 字数: 8,673 字 👁️ 阅读: 52 次
一、CF上变量设置

帐号和密码

ACCOUNTS_JSON

[
  { "username": "帐号1", "password": "帐号1的密码" },
  { "username": "帐号2", "password": "帐号2的密码" }
]
或
[
  { "username": "帐号1", "password": "帐号1的密码", "type": "webhostmost" },
  { "username": "帐号2", "password": "帐号2的密码", "type": "webhostmost" }
]

电报
TELEGRAM_JSON
{
  "telegramBotToken": "XXXX274559:XXXXNhe663WD3z_PxTaUvSAYlKFBJ5QXXXX",
  "telegramBotUserId": "XXXX504211"
}
二、CF上触发时间

三、CF上代码开始:

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

addEventListener('scheduled', event => {
  event.waitUntil(handleScheduled(event.scheduledTime))
})

async function handleRequest(request) {
  return new Response('Worker is running')
}

async function handleScheduled(scheduledTime) {
  const accounts = JSON.parse(ACCOUNTS_JSON)
  const results = await loginAccounts(accounts)
  await sendSummary(results)
}

async function loginAccounts(accounts) {
  const results = []
  for (const account of accounts) {
    const result = await loginAccount(account)
    results.push({ ...account, ...result })
    await delay(Math.floor(Math.random() * 8000) + 1000)
  }
  return results
}

function generateRandomUserAgent() {
  const browsers = ['Chrome', 'Firefox', 'Safari', 'Edge', 'Opera'];
  const browser = browsers[Math.floor(Math.random() * browsers.length)];
  const version = Math.floor(Math.random() * 100) + 1;
  const os = ['Windows NT 10.0', 'Macintosh', 'X11'];
  const selectedOS = os[Math.floor(Math.random() * os.length)];
  const osVersion = selectedOS === 'X11' ? 'Linux x86_64' : selectedOS === 'Macintosh' ? 'Intel Mac OS X 10_15_7' : 'Win64; x64';

  return `Mozilla/5.0 (${selectedOS}; ${osVersion}) AppleWebKit/537.36 (KHTML, like Gecko) ${browser}/${version}.0.0.0 Safari/537.36`;
}

async function loginAccount(account) {
  const { username, password, panelnum, type } = account
  const url = 'https://client.webhostmost.com/login'

  const userAgent = generateRandomUserAgent();

  try {
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'User-Agent': userAgent,
      },
    })

    const pageContent = await response.text()
    
    // 尝试多种可能的 CSRF token 格式(WHMCS 系统可能使用不同的 token 名称)
    let token = null
    const tokenPatterns = [
      /name="token" value="([^"]*)"/,
      /name="csrf_token" value="([^"]*)"/,
      /name="securitytoken" value="([^"]*)"/,
      /name="token" value='([^']*)'/,
      /name="csrf_token" value='([^']*)'/,
      /name="securitytoken" value='([^']*)'/,
      /<input[^>]*name="token"[^>]*value="([^"]*)"/,
      /<input[^>]*name="csrf_token"[^>]*value="([^"]*)"/,
      /<input[^>]*name="securitytoken"[^>]*value="([^"]*)"/,
    ]
    
    for (const pattern of tokenPatterns) {
      const match = pageContent.match(pattern)
      if (match && match[1]) {
        token = match[1]
        break
      }
    }

    const initialCookies = response.headers.get('set-cookie') || ''

    // WHMCS 系统通常使用 username 和 password 字段
    const formData = new URLSearchParams({
      'username': username,
      'password': password,
    })
    
    // 如果找到 token,添加到表单数据中
    if (token) {
      formData.append('token', token)
    }

    const loginResponse = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Referer': url,
        'User-Agent': userAgent,
        'Cookie': initialCookies,
      },
      body: formData.toString(),
      redirect: 'manual'
    })

    console.log(`Login response status: ${loginResponse.status}`)
    console.log(`Login response headers: ${JSON.stringify(Object.fromEntries(loginResponse.headers))}`)

    const loginResponseBody = await loginResponse.text()
    console.log(`Login response body: ${loginResponseBody.substring(0, 200)}...`)

    // 检查登录是否成功(WHMCS 通常重定向到客户端区域首页)
    const location = loginResponse.headers.get('location') || ''
    if (loginResponse.status === 302 && (location.includes('clientarea') || location.includes('index.php') || location === '/' || location.includes('dashboard'))) {
      const loginCookies = loginResponse.headers.get('set-cookie') || ''
      const allCookies = combineCookies(initialCookies, loginCookies)

      // 访问客户端区域验证登录状态
      const dashboardUrl = location.startsWith('http') ? location : `https://client.webhostmost.com${location.startsWith('/') ? location : '/' + location}`
      const dashboardResponse = await fetch(dashboardUrl, {
        headers: {
          'Cookie': allCookies,
          'User-Agent': userAgent,
        },
        redirect: 'manual'
      })
      const dashboardContent = await dashboardResponse.text()
      console.log(`Dashboard content: ${dashboardContent.substring(0, 200)}...`)

      // 检查是否包含登出链接或客户端区域标识
      if (dashboardContent.includes('logout') || dashboardContent.includes('Logout') || 
          dashboardContent.includes('clientarea') || dashboardContent.includes('Client Area') ||
          dashboardContent.includes('Welcome') || dashboardContent.includes('Dashboard')) {
        const nowUtc = formatToISO(new Date())
        const nowBeijing = formatToISO(new Date(Date.now() + 8 * 60 * 60 * 1000))
        const message = `账号 ${username} (${type || 'webhostmost'}) 于北京时间 ${nowBeijing}(UTC时间 ${nowUtc})登录成功!`
        console.log(message)
        await sendTelegramMessage(message)
        return { success: true, message }
      } else {
        const message = `账号 ${username} (${type || 'webhostmost'}) 登录后未找到客户端区域标识,可能登录失败。`
        console.error(message)
        await sendTelegramMessage(message)
        return { success: false, message }
      }
    } else if (loginResponseBody.includes('Invalid') || loginResponseBody.includes('incorrect') || 
               loginResponseBody.includes('error') || loginResponseBody.includes('Error') ||
               loginResponseBody.includes('Invalid Login') || loginResponseBody.includes('Login Failed')) {
      const message = `账号 ${username} (${type || 'webhostmost'}) 登录失败:用户名或密码错误。`
      console.error(message)
      await sendTelegramMessage(message)
      return { success: false, message }
    } else {
      const message = `账号 ${username} (${type || 'webhostmost'}) 登录失败,未知原因。请检查账号和密码是否正确。`
      console.error(message)
      await sendTelegramMessage(message)
      return { success: false, message }
    }
  } catch (error) {
    const message = `账号 ${username} (${type || 'webhostmost'}) 登录时出现错误: ${error.message}`
    console.error(message)
    await sendTelegramMessage(message)
    return { success: false, message }
  }
}

function combineCookies(cookies1, cookies2) {
  const cookieMap = new Map()
  
  const parseCookies = (cookieString) => {
    cookieString.split(',').forEach(cookie => {
      const [fullCookie] = cookie.trim().split(';')
      const [name, value] = fullCookie.split('=')
      if (name && value) {
        cookieMap.set(name.trim(), value.trim())
      }
    })
  }

  parseCookies(cookies1)
  parseCookies(cookies2)

  return Array.from(cookieMap.entries()).map(([name, value]) => `${name}=${value}`).join('; ')
}

async function sendSummary(results) {
  const successfulLogins = results.filter(r => r.success)
  const failedLogins = results.filter(r => !r.success)

  let summaryMessage = '登录结果统计:\n'
  summaryMessage += `成功登录的账号:${successfulLogins.length}\n`
  summaryMessage += `登录失败的账号:${failedLogins.length}\n`

  if (failedLogins.length > 0) {
    summaryMessage += '\n登录失败的账号列表:\n'
    failedLogins.forEach(({ username, type, message }) => {
      summaryMessage += `- ${username} (${type}): ${message}\n`
    })
  }

  console.log(summaryMessage)
  await sendTelegramMessage(summaryMessage)
}

async function sendTelegramMessage(message) {
  const telegramConfig = JSON.parse(TELEGRAM_JSON)
  const { telegramBotToken, telegramBotUserId } = telegramConfig
  const url = `https://api.telegram.org/bot${telegramBotToken}/sendMessage`
  
  try {
    await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        chat_id: telegramBotUserId,
        text: message
      })
    })
  } catch (error) {
    console.error('Error sending Telegram message:', error)
  }
}

function formatToISO(date) {
  return date.toISOString().replace('T', ' ').replace('Z', '').replace(/\.\d{3}Z/, '')
}

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

留言

暂无留言

0 / 100