1+
12class QRCodeHandler {
23 // 状态常量
34 static STATUS_NEW = "NEW" ; // 待扫描
@@ -10,6 +11,7 @@ class QRCodeHandler {
1011 static PLATFORM_QUARK = "quark" ; // 夸克
1112 static PLATFORM_ALI = "ali" ; // 阿里云盘
1213 static PLATFORM_UC = "uc" ; // UC
14+ static PLATFORM_UC_TOKEN = "uc_token" ; // uc_token
1315 static PLATFORM_BILI = "bili" ; // 哔哩哔哩
1416
1517 // 通用请求头
@@ -24,8 +26,22 @@ class QRCodeHandler {
2426 [ QRCodeHandler . PLATFORM_QUARK ] : null ,
2527 [ QRCodeHandler . PLATFORM_ALI ] : null ,
2628 [ QRCodeHandler . PLATFORM_UC ] : null ,
29+ [ QRCodeHandler . PLATFORM_UC_TOKEN ] : null ,
2730 [ QRCodeHandler . PLATFORM_BILI ] : null
2831 } ;
32+ this . Addition = {
33+ DeviceID : '07b48aaba8a739356ab8107b5e230ad4' ,
34+ RefreshToken : '' ,
35+ AccessToken : ''
36+ }
37+ this . conf = {
38+ api : "https://open-api-drive.uc.cn" ,
39+ clientID : "5acf882d27b74502b7040b0c65519aa7" ,
40+ signKey : "l3srvtd7p42l0d0x1u8d7yc8ye9kki4d" ,
41+ appVer : "1.6.8" ,
42+ channel : "UCTVOFFICIALWEB" ,
43+ codeApi : "http://api.extscreen.com/ucdrive" ,
44+ } ;
2945 }
3046
3147 static generateUUID ( ) {
@@ -107,6 +123,8 @@ class QRCodeHandler {
107123 return await this . _startAliScan ( ) ;
108124 case QRCodeHandler . PLATFORM_UC :
109125 return await this . _startUCScan ( ) ;
126+ case QRCodeHandler . PLATFORM_UC_TOKEN :
127+ return await this . _startUC_TOKENScan ( ) ;
110128 case QRCodeHandler . PLATFORM_BILI :
111129 return await this . _startBiliScan ( ) ;
112130 default :
@@ -122,6 +140,8 @@ class QRCodeHandler {
122140 return await this . _checkAliStatus ( ) ;
123141 case QRCodeHandler . PLATFORM_UC :
124142 return await this . _checkUCStatus ( ) ;
143+ case QRCodeHandler . PLATFORM_UC_TOKEN :
144+ return await this . _checkUC_TOKENStatus ( ) ;
125145 case QRCodeHandler . PLATFORM_BILI :
126146 return await this . _checkBiliStatus ( ) ;
127147 default :
@@ -380,14 +400,12 @@ class QRCodeHandler {
380400 } ) ;
381401 const resData = res . data ;
382402 const token = resData . data . data . members . token ;
383-
384403 const qrUrl = `https://su.uc.cn/1_n0ZCv?token=${ token } &client_id=381&uc_param_str=&uc_biz_str=S%3Acustom%7CC%3Atitlebar_fix` ;
385404
386405 this . platformStates [ QRCodeHandler . PLATFORM_UC ] = {
387406 token : token ,
388407 request_id : requestId
389408 } ;
390-
391409 const qrCode = await this . _generateQRCode ( qrUrl ) ;
392410 return {
393411 qrcode : qrCode ,
@@ -404,8 +422,8 @@ class QRCodeHandler {
404422 if ( ! state ) {
405423 return { status : QRCodeHandler . STATUS_EXPIRED } ;
406424 }
407-
408425 try {
426+
409427 const res = await axios ( {
410428 url : "/http" ,
411429 method : "POST" ,
@@ -426,9 +444,12 @@ class QRCodeHandler {
426444 }
427445 }
428446 } ) ;
447+ // this.code = await this.getCode(this.token)
448+ // let access_token = await this.refreshToken(this.code);
449+ // console.log(access_token)
429450 const resData = res . data ;
430-
431451 if ( resData . data . status === 2000000 ) { // 扫码成功
452+
432453 const serviceTicket = resData . data . data . members . service_ticket ;
433454 const cookieRes = await axios ( {
434455 url : "/http" ,
@@ -482,6 +503,178 @@ class QRCodeHandler {
482503 }
483504 }
484505
506+ generateDeviceID ( timestamp ) {
507+ return CryptoJS . MD5 ( timestamp ) . toString ( ) . slice ( 0 , 16 ) ; // 取前16位
508+ }
509+
510+ generateReqId ( deviceID , timestamp ) {
511+ return CryptoJS . MD5 ( deviceID + timestamp ) . toString ( ) . slice ( 0 , 16 ) ;
512+ }
513+
514+ generateXPanToken ( method , pathname , timestamp , key ) {
515+ const data = method + '&' + pathname + '&' + timestamp + '&' + key ;
516+ return CryptoJS . SHA256 ( data ) . toString ( ) ;
517+ }
518+
519+ //uc_token
520+ async _startUC_TOKENScan ( ) {
521+ try {
522+ const pathname = '/oauth/authorize'
523+ const timestamp = Math . floor ( Date . now ( ) / 1000 ) . toString ( ) + '000' ; // 13位时间戳需调整
524+ const deviceID = this . Addition . DeviceID || this . generateDeviceID ( timestamp ) ;
525+ const reqId = this . generateReqId ( deviceID , timestamp ) ;
526+ const token = this . generateXPanToken ( 'GET' , pathname , timestamp , this . conf . signKey ) ;
527+ const headers = {
528+ Accept : 'application/json, text/plain, */*' ,
529+ 'User-Agent' : 'Mozilla/5.0 (Linux; U; Android 13; zh-cn; M2004J7AC Build/UKQ1.231108.001) AppleWebKit/533.1 (KHTML, like Gecko) Mobile Safari/533.1' ,
530+ 'x-pan-tm' : timestamp ,
531+ 'x-pan-token' : token ,
532+ 'x-pan-client-id' : this . conf . clientID ,
533+ ...( this . Addition . AccessToken ? { 'Authorization' : `Bearer ${ this . Addition . AccessToken } ` } : { } )
534+ } ;
535+ const res = await axios ( {
536+ url : "/http" ,
537+ method : "POST" ,
538+ data : {
539+ url : `${ this . conf . api } ${ pathname } ` ,
540+ headers : headers ,
541+ params : {
542+ req_id : reqId ,
543+ access_token : this . Addition . AccessToken ,
544+ app_ver : this . conf . appVer ,
545+ device_id : deviceID ,
546+ device_brand : 'Xiaomi' ,
547+ platform : 'tv' ,
548+ device_name : 'M2004J7AC' ,
549+ device_model : 'M2004J7AC' ,
550+ build_device : 'M2004J7AC' ,
551+ build_product : 'M2004J7AC' ,
552+ device_gpu : 'Adreno (TM) 550' ,
553+ activity_rect : '{}' ,
554+ channel : this . conf . channel ,
555+ auth_type : 'code' ,
556+ client_id : this . conf . clientID ,
557+ scope : 'netdisk' ,
558+ qrcode : '1' ,
559+ qr_width : '460' ,
560+ qr_height : '460' ,
561+ } ,
562+ }
563+ } ) ;
564+ const resData = res . data ;
565+ this . query_token = resData . data . query_token ;
566+ const qrCode = resData . data . qr_data ;
567+ this . platformStates [ QRCodeHandler . PLATFORM_UC_TOKEN ] = {
568+ query_token : this . query_token ,
569+ request_id : reqId
570+ } ;
571+ return {
572+ qrcode : 'data:image/png;base64,' + qrCode ,
573+ status : QRCodeHandler . STATUS_NEW
574+ } ;
575+ } catch ( e ) {
576+ this . platformStates [ QRCodeHandler . PLATFORM_UC_TOKEN ] = null ;
577+ throw e ;
578+ }
579+ }
580+
581+ async _checkUC_TOKENStatus ( ) {
582+ const state = this . platformStates [ QRCodeHandler . PLATFORM_UC_TOKEN ] ;
583+ if ( ! state ) {
584+ return { status : QRCodeHandler . STATUS_EXPIRED } ;
585+ }
586+ const pathname = '/oauth/code' ;
587+ const timestamp = Math . floor ( Date . now ( ) / 1000 ) . toString ( ) + '000' ; // 13位时间戳需调整
588+ const deviceID = this . Addition . DeviceID || this . generateDeviceID ( timestamp ) ;
589+ const reqId = this . generateReqId ( deviceID , timestamp ) ;
590+ const x_pan_token = this . generateXPanToken ( "GET" , pathname , timestamp , this . conf . signKey ) ;
591+ const headers = {
592+ Accept : 'application/json, text/plain, */*' ,
593+ 'User-Agent' : 'Mozilla/5.0 (Linux; U; Android 13; zh-cn; M2004J7AC Build/UKQ1.231108.001) AppleWebKit/533.1 (KHTML, like Gecko) Mobile Safari/533.1' ,
594+ 'x-pan-tm' : timestamp ,
595+ 'x-pan-token' : x_pan_token ,
596+ 'x-pan-client-id' : this . conf . clientID ,
597+ ...( this . Addition . AccessToken ? { 'Authorization' : `Bearer ${ this . Addition . AccessToken } ` } : { } )
598+ } ;
599+ try {
600+ const res = await axios ( {
601+ url : "/http" ,
602+ method : "POST" ,
603+ data : {
604+ url : `${ this . conf . api } ${ pathname } ` ,
605+ headers : headers ,
606+ params : {
607+ req_id : reqId ,
608+ access_token : this . Addition . AccessToken ,
609+ app_ver : this . conf . appVer ,
610+ device_id : deviceID ,
611+ device_brand : 'Xiaomi' ,
612+ platform : 'tv' ,
613+ device_name : 'M2004J7AC' ,
614+ device_model : 'M2004J7AC' ,
615+ build_device : 'M2004J7AC' ,
616+ build_product : 'M2004J7AC' ,
617+ device_gpu : 'Adreno (TM) 550' ,
618+ activity_rect : '{}' ,
619+ channel : this . conf . channel ,
620+ client_id : this . conf . clientID ,
621+ scope : 'netdisk' ,
622+ query_token : this . query_token
623+ }
624+ }
625+ } ) . catch ( err => err . response ) ;
626+ const resData = res . data ;
627+ if ( resData . status === 200 ) { // 扫码成功
628+ const pathname = '/token' ;
629+ const timestamp = Math . floor ( Date . now ( ) / 1000 ) . toString ( ) + '000' ;
630+ const reqId = this . generateReqId ( this . Addition . DeviceID , timestamp ) ;
631+ const data = JSON . stringify ( {
632+ req_id : reqId ,
633+ app_ver : this . conf . appVer ,
634+ device_id : this . Addition . DeviceID ,
635+ device_brand : 'Xiaomi' ,
636+ platform : 'tv' ,
637+ device_name : 'M2004J7AC' ,
638+ device_model : 'M2004J7AC' ,
639+ build_device : 'M2004J7AC' ,
640+ build_product : 'M2004J7AC' ,
641+ device_gpu : 'Adreno (TM) 550' ,
642+ activity_rect : '{}' ,
643+ channel : this . conf . channel ,
644+ code :resData . data . code
645+ } ) ;
646+ const response = await axios ( {
647+ url : '/http' ,
648+ method : "POST" ,
649+ data :{
650+ url :`${ this . conf . codeApi } ${ pathname } ` ,
651+ method : "POST" ,
652+ headers : {
653+ 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36' ,
654+ 'Accept' : 'application/json, text/plain, */*' ,
655+ 'Content-Type' : 'application/json' ,
656+ } ,
657+ data :data
658+ }
659+ } ) ;
660+ const resp = response . data ;
661+ if ( resp . status === 200 ) {
662+ this . platformStates [ QRCodeHandler . PLATFORM_UC_TOKEN ] = null ;
663+ return {
664+ status : QRCodeHandler . STATUS_CONFIRMED ,
665+ cookie : resp . data . data . access_token
666+ } ;
667+ }
668+
669+ } else if ( resData . status === 400 ) {
670+ return { status : QRCodeHandler . STATUS_NEW } ;
671+ }
672+ } catch ( e ) {
673+ this . platformStates [ QRCodeHandler . PLATFORM_UC_TOKEN ] = null ;
674+ throw new Error ( e . message ) ;
675+ }
676+ }
677+
485678 // 哔哩哔哩平台相关方法
486679 async _startBiliScan ( ) {
487680 try {
0 commit comments