1
+
1
2
class QRCodeHandler {
2
3
// 状态常量
3
4
static STATUS_NEW = "NEW" ; // 待扫描
@@ -10,6 +11,7 @@ class QRCodeHandler {
10
11
static PLATFORM_QUARK = "quark" ; // 夸克
11
12
static PLATFORM_ALI = "ali" ; // 阿里云盘
12
13
static PLATFORM_UC = "uc" ; // UC
14
+ static PLATFORM_UC_TOKEN = "uc_token" ; // uc_token
13
15
static PLATFORM_BILI = "bili" ; // 哔哩哔哩
14
16
15
17
// 通用请求头
@@ -24,8 +26,22 @@ class QRCodeHandler {
24
26
[ QRCodeHandler . PLATFORM_QUARK ] : null ,
25
27
[ QRCodeHandler . PLATFORM_ALI ] : null ,
26
28
[ QRCodeHandler . PLATFORM_UC ] : null ,
29
+ [ QRCodeHandler . PLATFORM_UC_TOKEN ] : null ,
27
30
[ QRCodeHandler . PLATFORM_BILI ] : null
28
31
} ;
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
+ } ;
29
45
}
30
46
31
47
static generateUUID ( ) {
@@ -107,6 +123,8 @@ class QRCodeHandler {
107
123
return await this . _startAliScan ( ) ;
108
124
case QRCodeHandler . PLATFORM_UC :
109
125
return await this . _startUCScan ( ) ;
126
+ case QRCodeHandler . PLATFORM_UC_TOKEN :
127
+ return await this . _startUC_TOKENScan ( ) ;
110
128
case QRCodeHandler . PLATFORM_BILI :
111
129
return await this . _startBiliScan ( ) ;
112
130
default :
@@ -122,6 +140,8 @@ class QRCodeHandler {
122
140
return await this . _checkAliStatus ( ) ;
123
141
case QRCodeHandler . PLATFORM_UC :
124
142
return await this . _checkUCStatus ( ) ;
143
+ case QRCodeHandler . PLATFORM_UC_TOKEN :
144
+ return await this . _checkUC_TOKENStatus ( ) ;
125
145
case QRCodeHandler . PLATFORM_BILI :
126
146
return await this . _checkBiliStatus ( ) ;
127
147
default :
@@ -380,14 +400,12 @@ class QRCodeHandler {
380
400
} ) ;
381
401
const resData = res . data ;
382
402
const token = resData . data . data . members . token ;
383
-
384
403
const qrUrl = `https://su.uc.cn/1_n0ZCv?token=${ token } &client_id=381&uc_param_str=&uc_biz_str=S%3Acustom%7CC%3Atitlebar_fix` ;
385
404
386
405
this . platformStates [ QRCodeHandler . PLATFORM_UC ] = {
387
406
token : token ,
388
407
request_id : requestId
389
408
} ;
390
-
391
409
const qrCode = await this . _generateQRCode ( qrUrl ) ;
392
410
return {
393
411
qrcode : qrCode ,
@@ -404,8 +422,8 @@ class QRCodeHandler {
404
422
if ( ! state ) {
405
423
return { status : QRCodeHandler . STATUS_EXPIRED } ;
406
424
}
407
-
408
425
try {
426
+
409
427
const res = await axios ( {
410
428
url : "/http" ,
411
429
method : "POST" ,
@@ -426,9 +444,12 @@ class QRCodeHandler {
426
444
}
427
445
}
428
446
} ) ;
447
+ // this.code = await this.getCode(this.token)
448
+ // let access_token = await this.refreshToken(this.code);
449
+ // console.log(access_token)
429
450
const resData = res . data ;
430
-
431
451
if ( resData . data . status === 2000000 ) { // 扫码成功
452
+
432
453
const serviceTicket = resData . data . data . members . service_ticket ;
433
454
const cookieRes = await axios ( {
434
455
url : "/http" ,
@@ -482,6 +503,178 @@ class QRCodeHandler {
482
503
}
483
504
}
484
505
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
+
485
678
// 哔哩哔哩平台相关方法
486
679
async _startBiliScan ( ) {
487
680
try {
0 commit comments