@@ -167,7 +167,12 @@ export default {
167167 let pagesSum = UD ;
168168 let workersSum = UD ;
169169 let total = 24 * 1099511627776 ;
170-
170+ if ( env . CF_EMAIL && env . CF_APIKEY ) {
171+ const usage = await getUsage ( env . CF_ID , env . CF_EMAIL , env . CF_APIKEY , env . CF_ALL ) ;
172+ pagesSum = usage [ 1 ] ;
173+ workersSum = usage [ 2 ] ;
174+ total = env . CF_ALL ? Number ( env . CF_ALL ) : ( 1024 * 100 ) ; // 100K
175+ }
171176 if ( userAgent && ( userAgent . includes ( 'mozilla' ) || userAgent . includes ( 'subconverter' ) ) ) {
172177 return new Response ( 特洛伊Config , {
173178 status : 200 ,
@@ -3614,4 +3619,192 @@ async function bestIP(request, env, txt = 'ADD.txt') {
36143619 'Content-Type' : 'text/html; charset=UTF-8' ,
36153620 } ,
36163621 } ) ;
3622+ }
3623+
3624+ /**
3625+ * 获取 Cloudflare 账户今日使用量统计
3626+ * @param {string } accountId - 账户ID(可选,如果没有会自动获取)
3627+ * @param {string } email - Cloudflare 账户邮箱
3628+ * @param {string } apikey - Cloudflare API 密钥
3629+ * @param {number } all - 总限额,默认10万次
3630+ * @returns {Array } [总限额, Pages请求数, Workers请求数, 总请求数]
3631+ */
3632+ async function getUsage ( accountId , email , apikey , all = 100000 ) {
3633+ /**
3634+ * 获取 Cloudflare 账户ID
3635+ * @param {string } email - 账户邮箱
3636+ * @param {string } apikey - API密钥
3637+ * @param {number } accountIndex - 取第几个账户,默认第0个
3638+ * @returns {string } 账户ID
3639+ */
3640+ async function getAccountId ( email , apikey ) {
3641+ console . log ( '正在获取账户信息...' ) ;
3642+
3643+ const response = await fetch ( "https://api.cloudflare.com/client/v4/accounts" , {
3644+ method : "GET" ,
3645+ headers : {
3646+ "Content-Type" : "application/json" ,
3647+ "X-AUTH-EMAIL" : email ,
3648+ "X-AUTH-KEY" : apikey ,
3649+ }
3650+ } ) ;
3651+
3652+ if ( ! response . ok ) {
3653+ const errorText = await response . text ( ) ;
3654+ console . error ( `获取账户信息失败: ${ response . status } ${ response . statusText } ` , errorText ) ;
3655+ throw new Error ( `Cloudflare API 请求失败: ${ response . status } ${ response . statusText } - ${ errorText } ` ) ;
3656+ }
3657+
3658+ const res = await response . json ( ) ;
3659+ //console.log(res);
3660+
3661+ let accountIndex = 0 ; // 默认取第一个账户
3662+ let foundMatch = false ; // 标记是否找到匹配的账户
3663+
3664+ // 如果有多个账户,智能匹配包含邮箱前缀的账户
3665+ if ( res ?. result && res . result . length > 1 ) {
3666+ console . log ( `发现 ${ res . result . length } 个账户,正在智能匹配...` ) ;
3667+
3668+ // 提取邮箱前缀并转为小写
3669+ const emailPrefix = email . toLowerCase ( ) ;
3670+ console . log ( `邮箱: ${ emailPrefix } ` ) ;
3671+
3672+ // 遍历所有账户,寻找名称开头包含邮箱前缀的账户
3673+ for ( let i = 0 ; i < res . result . length ; i ++ ) {
3674+ const accountName = res . result [ i ] ?. name ?. toLowerCase ( ) || '' ;
3675+ console . log ( `检查账户 ${ i } : ${ res . result [ i ] ?. name } ` ) ;
3676+
3677+ // 检查账户名称开头是否包含邮箱前缀
3678+ if ( accountName . startsWith ( emailPrefix ) ) {
3679+ accountIndex = i ;
3680+ foundMatch = true ;
3681+ console . log ( `✅ 找到匹配账户,使用第 ${ i } 个账户` ) ;
3682+ break ;
3683+ }
3684+ }
3685+
3686+ // 如果遍历完还没找到匹配的,使用默认值0
3687+ if ( ! foundMatch ) {
3688+ console . log ( '❌ 未找到匹配的账户,使用默认第 0 个账户' ) ;
3689+ }
3690+ } else if ( res ?. result && res . result . length === 1 ) {
3691+ console . log ( '只有一个账户,使用第 0 个账户' ) ;
3692+ foundMatch = true ;
3693+ }
3694+
3695+ const name = res ?. result ?. [ accountIndex ] ?. name ;
3696+ const id = res ?. result ?. [ accountIndex ] ?. id ;
3697+
3698+ console . log ( `最终选择账户 ${ accountIndex } - 名称: ${ name } , ID: ${ id } ` ) ;
3699+
3700+ if ( ! id ) {
3701+ throw new Error ( "找不到有效的账户ID,请检查API权限" ) ;
3702+ }
3703+
3704+ return id ;
3705+ }
3706+
3707+ try {
3708+ // 如果没有提供账户ID,就自动获取
3709+ if ( ! accountId ) {
3710+ console . log ( '未提供账户ID,正在自动获取...' ) ;
3711+ accountId = await getAccountId ( email , apikey ) ;
3712+ }
3713+
3714+ // 设置查询时间范围:今天0点到现在
3715+ const now = new Date ( ) ;
3716+ const endDate = now . toISOString ( ) ; // 结束时间:现在
3717+
3718+ // 设置开始时间为今天凌晨0点
3719+ now . setUTCHours ( 0 , 0 , 0 , 0 ) ;
3720+ const startDate = now . toISOString ( ) ; // 开始时间:今天0点
3721+
3722+ console . log ( `查询时间范围: ${ startDate } 到 ${ endDate } ` ) ;
3723+
3724+ // 向 Cloudflare GraphQL API 发送请求,获取今日使用量
3725+ const response = await fetch ( "https://api.cloudflare.com/client/v4/graphql" , {
3726+ method : "POST" ,
3727+ headers : {
3728+ "Content-Type" : "application/json" ,
3729+ "X-AUTH-EMAIL" : email ,
3730+ "X-AUTH-KEY" : apikey ,
3731+ } ,
3732+ body : JSON . stringify ( {
3733+ // GraphQL 查询语句:获取 Pages 和 Workers 的请求数统计
3734+ query : `query getBillingMetrics($accountId: String!, $filter: AccountWorkersInvocationsAdaptiveFilter_InputObject) {
3735+ viewer {
3736+ accounts(filter: {accountTag: $accountId}) {
3737+ pagesFunctionsInvocationsAdaptiveGroups(limit: 1000, filter: $filter) {
3738+ sum {
3739+ requests
3740+ }
3741+ }
3742+ workersInvocationsAdaptive(limit: 10000, filter: $filter) {
3743+ sum {
3744+ requests
3745+ }
3746+ }
3747+ }
3748+ }
3749+ }` ,
3750+ variables : {
3751+ accountId : accountId ,
3752+ filter : {
3753+ datetime_geq : startDate , // 大于等于开始时间
3754+ datetime_leq : endDate // 小于等于结束时间
3755+ } ,
3756+ } ,
3757+ } ) ,
3758+ } ) ;
3759+
3760+ // 检查API请求是否成功
3761+ if ( ! response . ok ) {
3762+ const errorText = await response . text ( ) ;
3763+ console . error ( `GraphQL查询失败: ${ response . status } ${ response . statusText } ` , errorText ) ;
3764+ console . log ( '返回默认值:全部为0' ) ;
3765+ return [ all , 0 , 0 , 0 ] ;
3766+ }
3767+
3768+ const res = await response . json ( ) ;
3769+
3770+ // 检查GraphQL响应是否有错误
3771+ if ( res . errors && res . errors . length > 0 ) {
3772+ console . error ( 'GraphQL查询错误:' , res . errors [ 0 ] . message ) ;
3773+ console . log ( '返回默认值:全部为0' ) ;
3774+ return [ all , 0 , 0 , 0 ] ;
3775+ }
3776+
3777+ // 从响应中提取账户数据
3778+ const accounts = res ?. data ?. viewer ?. accounts ?. [ 0 ] ;
3779+
3780+ if ( ! accounts ) {
3781+ console . warn ( '未找到账户数据' ) ;
3782+ return [ all , 0 , 0 , 0 ] ;
3783+ }
3784+
3785+ // 计算 Pages 请求数(Cloudflare Pages 的请求统计)
3786+ const pagesArray = accounts ?. pagesFunctionsInvocationsAdaptiveGroups || [ ] ;
3787+ const pages = pagesArray . reduce ( ( total , item ) => {
3788+ return total + ( item ?. sum ?. requests || 0 ) ;
3789+ } , 0 ) ;
3790+
3791+ // 计算 Workers 请求数(Cloudflare Workers 的请求统计)
3792+ const workersArray = accounts ?. workersInvocationsAdaptive || [ ] ;
3793+ const workers = workersArray . reduce ( ( total , item ) => {
3794+ return total + ( item ?. sum ?. requests || 0 ) ;
3795+ } , 0 ) ;
3796+
3797+ // 计算总请求数
3798+ const total = pages + workers ;
3799+
3800+ console . log ( `统计结果 - Pages: ${ pages } , Workers: ${ workers } , 总计: ${ total } ` ) ;
3801+
3802+ // 返回格式:[总限额, Pages请求数, Workers请求数, 总请求数]
3803+ return [ all , pages || 0 , workers || 0 , total || 0 ] ;
3804+
3805+ } catch ( error ) {
3806+ console . error ( '获取使用量时发生错误:' , error . message ) ;
3807+ // 发生错误时返回默认值
3808+ return [ all , 0 , 0 , 0 ] ;
3809+ }
36173810}
0 commit comments