From 991d733e7c1f25b22f64826c60750928b50d1e6c Mon Sep 17 00:00:00 2001 From: yxxyun Date: Fri, 21 Feb 2025 16:57:16 +0800 Subject: [PATCH 1/2] update quarkuc extractor --- lib/eval/model/m_bridge.dart | 33 ++-- .../anime_extractors/quarkuc_extractor.dart | 186 +++++++++--------- lib/services/http/m_client.dart | 10 +- pubspec.lock | 66 +++---- 4 files changed, 155 insertions(+), 140 deletions(-) diff --git a/lib/eval/model/m_bridge.dart b/lib/eval/model/m_bridge.dart index a66914b7..af41fa3c 100644 --- a/lib/eval/model/m_bridge.dart +++ b/lib/eval/model/m_bridge.dart @@ -350,31 +350,38 @@ class MBridge { .videosFromUrl(url, newHeaders, prefix: prefix, suffix: suffix); } - static Future>> quarkFilesExtractor( - List url, String cookie) async { - QuarkUcExtractor quark = QuarkUcExtractor(); - await quark.initCloudDrive(cookie, CloudDriveType.quark); - return await quark.videoFilesFromUrl(url); + static final Map _extractorCache = {}; + + static QuarkUcExtractor _getExtractor(String cookie, CloudDriveType type) { + if (!_extractorCache.containsKey(type)) { + QuarkUcExtractor extractor = QuarkUcExtractor(); + extractor.initCloudDrive(cookie, type); + _extractorCache[type] = extractor; + } + return _extractorCache[type]!; } - static Future>> ucFilesExtractor( + static Future>> quarkFilesExtractor( List url, String cookie) async { - QuarkUcExtractor uc = QuarkUcExtractor(); - await uc.initCloudDrive(cookie, CloudDriveType.uc); - return await uc.videoFilesFromUrl(url); + var quark = _getExtractor(cookie, CloudDriveType.quark); + return await quark.videoFilesFromUrl(url); } static Future> quarkVideosExtractor( String url, String cookie) async { - QuarkUcExtractor quark = QuarkUcExtractor(); - await quark.initCloudDrive(cookie, CloudDriveType.quark); + var quark = _getExtractor(cookie, CloudDriveType.quark); return await quark.videosFromUrl(url); } + static Future>> ucFilesExtractor( + List url, String cookie) async { + var uc = _getExtractor(cookie, CloudDriveType.uc); + return await uc.videoFilesFromUrl(url); + } + static Future> ucVideosExtractor( String url, String cookie) async { - QuarkUcExtractor uc = QuarkUcExtractor(); - await uc.initCloudDrive(cookie, CloudDriveType.uc); + var uc = _getExtractor(cookie, CloudDriveType.uc); return await uc.videosFromUrl(url); } diff --git a/lib/services/anime_extractors/quarkuc_extractor.dart b/lib/services/anime_extractors/quarkuc_extractor.dart index 732fb436..9dd807c7 100644 --- a/lib/services/anime_extractors/quarkuc_extractor.dart +++ b/lib/services/anime_extractors/quarkuc_extractor.dart @@ -4,6 +4,7 @@ import 'dart:math'; import 'package:http_interceptor/http_interceptor.dart'; import 'package:mangayomi/models/video.dart'; import 'package:mangayomi/services/http/m_client.dart'; +import 'package:mangayomi/services/torrent_server.dart'; enum CloudDriveType { quark, @@ -12,48 +13,62 @@ enum CloudDriveType { class QuarkUcExtractor { late CloudDriveType cloudDriveType; - String apiUrl = ""; //"https://drive-pc.quark.cn/1/clouddrive/"; - String cookie = ""; + String apiUrl = ""; + // String cookie = ""; + String refererUrl = ""; + String ua = ""; + String host = ""; Map shareTokenCache = {}; - String pr = ""; //"pr=ucpro&fr=pc"; + String pr = ""; final List subtitleExts = ['.srt', '.ass', '.scc', '.stl', '.ttml']; Map saveFileIdCaches = {}; String? saveDirId; final String saveDirName = 'TV'; + String _lastCookie = ""; Future initCloudDrive( String cookie, CloudDriveType cloudDriveType) async { - this.cookie = cookie; this.cloudDriveType = cloudDriveType; if (cloudDriveType == CloudDriveType.quark) { apiUrl = "https://drive-pc.quark.cn/1/clouddrive/"; pr = "pr=ucpro&fr=pc"; + ua = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch"; + refererUrl = "https://pan.quark.cn/"; + host = "https://quark.cn"; + _lastCookie = "https://quarkcookie.last"; } else { apiUrl = "https://pc-api.uc.cn/1/clouddrive/"; pr = "pr=UCBrowser&fr=pc"; + ua = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) uc-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch"; + refererUrl = "https://drive.uc.cn/"; + host = "https://uc.cn"; + _lastCookie = "https://uccookie.last"; + } + if (cookie.isNotEmpty && getLastCookie() != cookie) { + MClient.setCookie(host, ua, null, cookie: cookie); + MClient.setCookie(_lastCookie, ua, null, cookie: cookie); } } + String getLastCookie() { + var cookie = MClient.getCookiesPref(_lastCookie); + return cookie.isNotEmpty ? cookie.values.first : ""; + } + + String getCurrentCookie() { + var cookie = MClient.getCookiesPref(host); + return cookie.isNotEmpty ? cookie.values.first : ""; + } + Map getHeaders() { - if (cloudDriveType == CloudDriveType.quark) { - return { - 'User-Agent': - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) quark-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch', - 'Referer': 'https://pan.quark.cn/', - "Content-Type": "application/json", - "Cookie": cookie, - "Host": "drive-pc.quark.cn" - }; - } else { - return { - 'User-Agent': - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) uc-cloud-drive/2.5.20 Chrome/100.0.4896.160 Electron/18.3.5.4-b478491100 Safari/537.36 Channel/pckk_other_ch', - 'Referer': 'https://drive.uc.cn/', - "Content-Type": "application/json", - "Cookie": cookie, - "Host": "pc-api.uc.cn" - }; - } + return { + 'User-Agent': ua, + 'Referer': refererUrl, + "Content-Type": "application/json", + "Cookie": getCurrentCookie(), + }; } Future> api( @@ -67,18 +82,42 @@ class QuarkUcExtractor { } else { resp = await client.get(Uri.parse(apiUrl + url), headers: getHeaders()); } + // if (resp.headers['set-cookie'] != null) { + // print('headers: ${resp.headers}'); + // final puus = resp.headers['set-cookie']! + // .split(';;;') + // .join() + // .split(';') + // .firstWhere((element) => element.startsWith('__puus='), + // orElse: () => ''); + // if (puus.isNotEmpty) { + // final newPuus = puus.split('=')[1]; + // var cookie = getCurrentCookie(); + // if (cookie != null && cookie.contains('__puus=')) { + // cookie = + // cookie.replaceFirst(RegExp(r'__puus=[^;]+'), '__puus=$newPuus'); + // } + // MClient.setCookie(host, ua, cookie: cookie); + // } + // } + // 处理 set-cookie if (resp.headers['set-cookie'] != null) { - final puus = resp.headers['set-cookie']! - .split(';;;') - .join() - .split(';') - .firstWhere((element) => element.startsWith('__puus='), - orElse: () => ''); - if (puus.isNotEmpty) { - final newPuus = puus.split('=')[1]; + final cookies = resp.headers['set-cookie']!.split(';;;'); + for (var cookie in cookies) { if (cookie.contains('__puus=')) { - cookie = - cookie.replaceFirst(RegExp(r'__puus=[^;]+'), '__puus=$newPuus'); + final newPuus = cookie.split(';')[0]; // 获取新的 __puus + var currentCookie = getCurrentCookie(); + if (currentCookie.isNotEmpty) { + // 更新 __puus + if (currentCookie.contains('__puus=')) { + currentCookie = + currentCookie.replaceFirst(RegExp(r'__puus=[^;]+'), newPuus); + } else { + currentCookie = '$currentCookie; $newPuus'; + } + MClient.setCookie(host, ua, null, cookie: currentCookie); + } + break; } } } @@ -102,10 +141,6 @@ class QuarkUcExtractor { return null; } - List getPlayFormtList() { - return ["4k", "2k", "super", "high", "normal", "low", "原画"]; - } - Future getShareToken(Map shareData) async { if (!shareTokenCache.containsKey(shareData['shareId'])) { shareTokenCache.remove(shareData['shareId']); @@ -305,8 +340,8 @@ class QuarkUcExtractor { return null; } - Future getLiveTranscoding(String shareId, String stoken, - String fileId, String fileToken, String quality) async { + Future>?> getLiveTranscoding( + String shareId, String stoken, String fileId, String fileToken) async { if (!saveFileIdCaches.containsKey(fileId)) { final saveFileId = await save(shareId, stoken, fileId, fileToken, true); if (saveFileId == null) return null; @@ -322,13 +357,14 @@ class QuarkUcExtractor { 'post'); if (transcoding['data'] != null && transcoding['data']['video_list'] != null) { + List> qualityOptions = []; for (final video in transcoding['data']['video_list']) { - if (video['resolution'] == quality) { - return video['video_info']['url']; - } + qualityOptions.add({ + 'url': video['video_info']['url'], + 'quality': video['resolution'] + }); } - // 如果没有找到匹配的质量,返回null - return null; + return qualityOptions; } return null; } @@ -362,12 +398,6 @@ class QuarkUcExtractor { await getFilesByShareUrl(i + 1, shareUrl, videoItems, subItems); } - // if (videoItems.isNotEmpty) { - // print('获取播放链接成功,分享链接为:${shareUrlList.join("\t")}'); - // } else { - // print('获取播放链接失败,检查分享链接为:${shareUrlList.join("\t")}'); - // } - return await getVodFile(videoItems, subItems, typeName); } @@ -399,45 +429,23 @@ class QuarkUcExtractor { String type = parts[0]; List subtitleParts = parts.length > 5 ? parts[5].split('+') : []; // 获取可用的质量列表 - List qualities = getPlayFormtList(); + //List qualities = getPlayFormtList(); List