From 9c70b5cfd8bef584759f6f0e1724544b2be1bcdc Mon Sep 17 00:00:00 2001 From: xjbeta Date: Fri, 31 May 2024 14:38:22 +0800 Subject: [PATCH 1/7] fix jsplayer window origin --- .../JSPlayer/JSPlayerViewController.swift | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/IINA+/Views/JSPlayer/JSPlayerViewController.swift b/IINA+/Views/JSPlayer/JSPlayerViewController.swift index 12055628..05f0b522 100644 --- a/IINA+/Views/JSPlayer/JSPlayerViewController.swift +++ b/IINA+/Views/JSPlayer/JSPlayerViewController.swift @@ -755,12 +755,22 @@ extension JSPlayerViewController: WKScriptMessageHandler { var newFrame = NSRect(origin: .zero, size: size) if !windowSizeInited, - var frame = NSScreen.main?.frame { - let newH = frame.width / size.width * size.height - frame.origin.y = frame.height - newH - frame.size.height = newH - - newFrame = frame + let frame = NSScreen.main?.visibleFrame ?? NSScreen.main?.frame { + + let aspectRatio = size.width / size.height + + if aspectRatio >= frame.width / frame.height { + let w = frame.width + let h = w / aspectRatio + newFrame.size = .init(width: w, height: h) + } else { + let h = frame.height + let w = h * aspectRatio + newFrame.size = .init(width: w, height: h) + } + + newFrame.origin.x = (frame.width - newFrame.width) / 2 + newFrame.origin.y = frame.height - newFrame.height } else { var f = window.frame f.size.height = f.width / size.width * size.height From a356167114182356d196973b1aaa1eff27bfe4b9 Mon Sep 17 00:00:00 2001 From: xjbeta Date: Sat, 1 Jun 2024 15:18:41 +0800 Subject: [PATCH 2/7] update huyaurl --- IINA+/Utils/VideoDecoder/Huya.swift | 14 +++--- IINA+/Utils/VideoDecoder/HuyaUrl.swift | 64 +++++++++++++++++--------- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/IINA+/Utils/VideoDecoder/Huya.swift b/IINA+/Utils/VideoDecoder/Huya.swift index cf96f701..b4dabc94 100644 --- a/IINA+/Utils/VideoDecoder/Huya.swift +++ b/IINA+/Utils/VideoDecoder/Huya.swift @@ -22,8 +22,6 @@ class Huya: NSObject, SupportSiteProtocol { return Session(configuration: configuration) }() - private let huyaUid = Int.random(in: Int(1e12).. Promise { getHuyaInfo(url).map { $0 @@ -91,7 +89,7 @@ class Huya: NSObject, SupportSiteProtocol { let info = try HuyaStream(object: $0) var yougetJson = YouGetJSON(rawUrl: url) - return info.write(to: yougetJson, uid: self.huyaUid) + return info.write(to: yougetJson) } } @@ -187,14 +185,14 @@ struct HuyaStream: Unmarshaling { vMultiStreamInfo = try object.value(for: "vMultiStreamInfo") } - func write(to yougetJson: YouGetJSON, uid: Int) -> YouGetJSON { + func write(to yougetJson: YouGetJSON) -> YouGetJSON { var yougetJson = yougetJson if let infoData = data.first { yougetJson.title = infoData.liveInfo.title let urls = infoData.streamInfoList.map { - $0.url(uid) + $0.url() } vMultiStreamInfo.enumerated().forEach { @@ -295,16 +293,18 @@ struct HuyaStream: Unmarshaling { var sFlvUrl: String var sFlvUrlSuffix: String var sFlvAntiCode: String + var lPresenterUid: Int init(object: MarshaledObject) throws { sStreamName = try object.value(for: "sStreamName") sFlvUrl = try object.value(for: "sFlvUrl") sFlvUrlSuffix = try object.value(for: "sFlvUrlSuffix") sFlvAntiCode = try object.value(for: "sFlvAntiCode") + lPresenterUid = try object.value(for: "lPresenterUid") } - func url(_ uid: Int) -> String { - HuyaUrl.format(uid, sStreamName: sStreamName, sFlvUrl: sFlvUrl, sFlvUrlSuffix: sFlvUrlSuffix, sFlvAntiCode: sFlvAntiCode) + func url() -> String { + HuyaUrl.format(lPresenterUid, sStreamName: sStreamName, sFlvUrl: sFlvUrl, sFlvUrlSuffix: sFlvUrlSuffix, sFlvAntiCode: sFlvAntiCode) } } } diff --git a/IINA+/Utils/VideoDecoder/HuyaUrl.swift b/IINA+/Utils/VideoDecoder/HuyaUrl.swift index c71ba7cf..cfa83a14 100644 --- a/IINA+/Utils/VideoDecoder/HuyaUrl.swift +++ b/IINA+/Utils/VideoDecoder/HuyaUrl.swift @@ -21,39 +21,56 @@ class HuyaUrl: NSObject { let seqid = uid + now() let sid = now() + var parameters = [String: String]() + + sFlvAntiCode.split(separator: "&").map { + $0.split(separator: "=", maxSplits: 1).map(String.init) + }.filter { + $0.count == 2 + }.forEach { + parameters[$0[0]] = $0[1] + } guard let convertUid = rotUid(uid), let wsSecret = wsSecret(sFlvAntiCode, convertUid: convertUid, seqid: seqid, streamName: sStreamName) else { return "" } - let newAntiCode: String = { - var s = sFlvAntiCode.split(separator: "&") - .filter { - !$0.contains("fm=") && - !$0.contains("wsSecret=") - } - s.append("wsSecret=\(wsSecret)") - return s.joined(separator: "&") - }() + parameters["u"] = "\(convertUid)" + parameters["wsSecret"] = wsSecret + +// parameters["fm"] = nil + parameters["seqid"] = "\(seqid)" + parameters["sdk_sid"] = "\(sid)" + parameters["sv"] = "2405220949" + parameters["sdkPcdn"] = "1_1" + parameters["t"] = "100" + parameters["a_block"] = "0" + parameters["ver"] = "1" + parameters["ratio"] = "0" + parameters["dMod"] = "mseh-32" - return sFlvUrl.replacingOccurrences(of: "http://", with: "https://") + let example = "https://qvodlive-va.huya.com/src/1394575534-1394575534-5989656310331736064-2789274524-10057-A-0-1.flv?wsSecret=b9636212d1ad30223c157f5ac678d7c5&wsTime=665aaef2&seqid=7784383132214&ctype=huya_live&ver=1&txyp=o%3An4%3B&fs=bgct&sphdcdn=al_7-tx_3-js_3-ws_7-bd_2-hw_2&sphdDC=huya&sphd=264_*-265_*&exsphd=264_500,264_2000,264_4000,264_6000,264_8000,&ratio=500&&https=1&dMod=mseh-32&sdkPcdn=1_1&u=6065176706463&t=100&sv=2405220949&sdk_sid=1717219065187&a_block=0" + + var url = sFlvUrl.replacingOccurrences(of: "http://", with: "https://") + "/" + sStreamName + "." + sFlvUrlSuffix + "?" - + newAntiCode - + "&ver=1" - + "&seqid=\(seqid)" - + "&ratio=0" - + "&dMod=mseh-32" - + "&sdkPcdn=1_1" - + "&u=\(convertUid)" - + "&t=100" - + "&sv=2401310322" - + "&sdk_sid=\(sid)" - + "&https=1" -// + "&codec=av1" + + let pars = URLComponents(string: example)!.queryItems!.compactMap { + let key = $0.name + if let value = parameters[key] { + return key + "=" + value + } else { + Log("Huya parameters missing key, \($0.description)") + return nil + } + } + + url += pars.joined(separator: "&") + + return url } private static func turnStr(_ e: Int, _ t: Int, _ i: Int) -> String { @@ -101,7 +118,8 @@ class HuyaUrl: NSObject { let ctype = d["ctype"] else { return nil } let s = "\(seqid)|\(ctype)|100".md5() - + +// let o = this[Mt].replace(Xt, r).replace($t, this[Kt]).replace(Zt, s).replace(te, this[Bt]); u = u.replacingOccurrences(of: "$0", with: "\(convertUid)") u = u.replacingOccurrences(of: "$1", with: streamName) u = u.replacingOccurrences(of: "$2", with: s) From b05aa428b2e3f230291d82bef2f86f2fd98be4bb Mon Sep 17 00:00:00 2001 From: xjbeta Date: Sat, 1 Jun 2024 15:19:03 +0800 Subject: [PATCH 3/7] string https func --- IINA+/Utils/Danmaku/DanmakuBiliLive.swift | 4 ++-- IINA+/Utils/Extensions/StringExtension.swift | 4 ++++ IINA+/Utils/VideoDecoder/Bilibili.swift | 6 +++--- IINA+/Utils/VideoDecoder/CC163.swift | 6 +++--- IINA+/Utils/VideoDecoder/DouYin.swift | 4 ++-- IINA+/Utils/VideoDecoder/Huya.swift | 10 ++++++---- IINA+/Utils/VideoDecoder/HuyaUrl.swift | 2 +- IINA+/Utils/VideoDecoder/QQLive.swift | 2 +- 8 files changed, 22 insertions(+), 16 deletions(-) diff --git a/IINA+/Utils/Danmaku/DanmakuBiliLive.swift b/IINA+/Utils/Danmaku/DanmakuBiliLive.swift index 22720000..137f227e 100644 --- a/IINA+/Utils/Danmaku/DanmakuBiliLive.swift +++ b/IINA+/Utils/Danmaku/DanmakuBiliLive.swift @@ -65,7 +65,7 @@ extension Danmaku { init(object: MarshaledObject) throws { emoji = try object.value(for: "emoji") let u: String = try object.value(for: "url") - url = u.replacingOccurrences(of: "http://", with: "https://") + url = u.https() width = try object.value(for: "width") height = try object.value(for: "height") // identity = try object.value(for: "identity") @@ -360,7 +360,7 @@ extension Danmaku { return emoticon.comment() } - let url = url.replacingOccurrences(of: "http://", with: "https://") + let url = url.https() var emoticon = BiliLiveEmoticon(unique, url: url) emoticon.width = width diff --git a/IINA+/Utils/Extensions/StringExtension.swift b/IINA+/Utils/Extensions/StringExtension.swift index 9f9131d6..35b3681e 100644 --- a/IINA+/Utils/Extensions/StringExtension.swift +++ b/IINA+/Utils/Extensions/StringExtension.swift @@ -142,6 +142,10 @@ extension String { } return s } + + func https() -> String { + self.replacingOccurrences(of: "http://", with: "https://") + } } diff --git a/IINA+/Utils/VideoDecoder/Bilibili.swift b/IINA+/Utils/VideoDecoder/Bilibili.swift index 5e8f8625..eb837367 100644 --- a/IINA+/Utils/VideoDecoder/Bilibili.swift +++ b/IINA+/Utils/VideoDecoder/Bilibili.swift @@ -44,7 +44,7 @@ class Bilibili: NSObject, SupportSiteProtocol { var info = BilibiliInfo() info.title = try initialStateJson.value(for: "videoData.title") info.cover = try initialStateJson.value(for: "videoData.pic") - info.cover = info.cover.replacingOccurrences(of: "http://", with: "https://") + info.cover = info.cover.https() info.name = try initialStateJson.value(for: "videoData.owner.name") info.isLiving = true return info @@ -474,7 +474,7 @@ class BilibiliCard: NSObject, Unmarshaling { aid = try json.value(for: "aid") title = try json.value(for: "title") let picUrl: String = try json.value(for: "pic") - self.picUrl = picUrl.replacingOccurrences(of: "http://", with: "https://") + self.picUrl = picUrl.https() duration = try json.value(for: "duration") name = try json.value(for: "owner.name") views = try json.value(for: "stat.view") @@ -503,7 +503,7 @@ struct BilibiliPvideo: Unmarshaling { init(object: MarshaledObject) throws { let imageStrs: [String] = try object.value(for: "data.image") // images = imageStrs.compactMap { str -> NSImage? in -// if let url = URL(string: str.replacingOccurrences(of: "http://", with: "https://")) { +// if let url = URL(string: str.https()) { // return NSImage(contentsOf: url) // } else { // return nil diff --git a/IINA+/Utils/VideoDecoder/CC163.swift b/IINA+/Utils/VideoDecoder/CC163.swift index 07f03a5e..fba9b9c7 100644 --- a/IINA+/Utils/VideoDecoder/CC163.swift +++ b/IINA+/Utils/VideoDecoder/CC163.swift @@ -175,7 +175,7 @@ struct CC163Info: Unmarshaling, LiveInfo { title = try object.value(for: "props.pageProps.roomInfoInitData.live.title") name = try object.value(for: "props.pageProps.roomInfoInitData.micfirst.nickname") avatar = try object.value(for: "props.pageProps.roomInfoInitData.micfirst.purl") - avatar = avatar.replacingOccurrences(of: "http://", with: "https://") + avatar = avatar.https() cover = avatar let living: Bool? = try? object.value(for: "props.pageProps.roomInfoInitData.is_show_live_rcm") @@ -248,9 +248,9 @@ struct CC163ChannelInfo: Unmarshaling, LiveInfo { if isLiving { title = try object.value(for: "title") cover = try object.value(for: "cover") - cover = cover.replacingOccurrences(of: "http://", with: "https://") + cover = cover.https() avatar = (try? object.value(for: "purl")) ?? "" - avatar = avatar.replacingOccurrences(of: "http://", with: "https://") + avatar = avatar.https() } else { title = (try? object.value(for: "title")) ?? name cover = "" diff --git a/IINA+/Utils/VideoDecoder/DouYin.swift b/IINA+/Utils/VideoDecoder/DouYin.swift index 9866bfee..5167c28f 100644 --- a/IINA+/Utils/VideoDecoder/DouYin.swift +++ b/IINA+/Utils/VideoDecoder/DouYin.swift @@ -474,7 +474,7 @@ struct DouYinInfo: Unmarshaling, LiveInfo { urls.map { - ($0.key, $0.value.replacingOccurrences(of: "http://", with: "https://")) + ($0.key, $0.value.https()) }.sorted { v0, v1 in v0.0 < v1.0 }.enumerated().forEach { @@ -526,7 +526,7 @@ struct DouYinEnterData: Unmarshaling { urls.map { - ($0.key, $0.value.replacingOccurrences(of: "http://", with: "https://")) + ($0.key, $0.value.https()) }.sorted { v0, v1 in v0.0 < v1.0 }.enumerated().forEach { diff --git a/IINA+/Utils/VideoDecoder/Huya.swift b/IINA+/Utils/VideoDecoder/Huya.swift index b4dabc94..9777aa87 100644 --- a/IINA+/Utils/VideoDecoder/Huya.swift +++ b/IINA+/Utils/VideoDecoder/Huya.swift @@ -153,10 +153,10 @@ struct HuyaInfo: Unmarshaling, LiveInfo { title = try object.value(for: "introduction") name = try object.value(for: "nick") avatar = try object.value(for: "avatar") - avatar = avatar.replacingOccurrences(of: "http://", with: "https://") + avatar = avatar.https() isLiving = "\(try object.any(for: "isOn"))" == "1" cover = try object.value(for: "screenshot") - cover = cover.replacingOccurrences(of: "http://", with: "https://") + cover = cover.https() rid = try object.value(for: "profileRoom") @@ -270,8 +270,10 @@ struct HuyaStream: Unmarshaling { name = try object.value(for: "nick") avatar = try object.value(for: "avatar180") + avatar = avatar.https() rid = try object.value(for: "profileRoom") cover = try object.value(for: "screenshot") + cover = cover.https() if let uid: Int = try? object.value(for: "uid") { self.uid = uid @@ -359,8 +361,8 @@ struct HuyaInfoM: Unmarshaling, LiveInfo { init(object: MarshaledObject) throws { name = try object.value(for: "roomInfo.tProfileInfo.sNick") - let ava: String = try object.value(for: "roomInfo.tProfileInfo.sAvatar180") - avatar = ava.replacingOccurrences(of: "http://", with: "https://") + avatar = try object.value(for: "roomInfo.tProfileInfo.sAvatar180") + avatar = avatar.https() let state: Int = try object.value(for: "roomInfo.eLiveStatus") isLiving = state == 2 diff --git a/IINA+/Utils/VideoDecoder/HuyaUrl.swift b/IINA+/Utils/VideoDecoder/HuyaUrl.swift index cfa83a14..6bcb77b0 100644 --- a/IINA+/Utils/VideoDecoder/HuyaUrl.swift +++ b/IINA+/Utils/VideoDecoder/HuyaUrl.swift @@ -51,7 +51,7 @@ class HuyaUrl: NSObject { let example = "https://qvodlive-va.huya.com/src/1394575534-1394575534-5989656310331736064-2789274524-10057-A-0-1.flv?wsSecret=b9636212d1ad30223c157f5ac678d7c5&wsTime=665aaef2&seqid=7784383132214&ctype=huya_live&ver=1&txyp=o%3An4%3B&fs=bgct&sphdcdn=al_7-tx_3-js_3-ws_7-bd_2-hw_2&sphdDC=huya&sphd=264_*-265_*&exsphd=264_500,264_2000,264_4000,264_6000,264_8000,&ratio=500&&https=1&dMod=mseh-32&sdkPcdn=1_1&u=6065176706463&t=100&sv=2405220949&sdk_sid=1717219065187&a_block=0" - var url = sFlvUrl.replacingOccurrences(of: "http://", with: "https://") + var url = sFlvUrl.https() + "/" + sStreamName + "." diff --git a/IINA+/Utils/VideoDecoder/QQLive.swift b/IINA+/Utils/VideoDecoder/QQLive.swift index 559bb2a6..bc3bcd6f 100644 --- a/IINA+/Utils/VideoDecoder/QQLive.swift +++ b/IINA+/Utils/VideoDecoder/QQLive.swift @@ -30,7 +30,7 @@ class QQLive: NSObject, SupportSiteProtocol { mInfo(url).map { var re = YouGetJSON(rawUrl: url) re.title = $0.title - re.streams["Default"] = .init(url: $0.url.replacingOccurrences(of: "http://", with: "https://")) + re.streams["Default"] = .init(url: $0.url.https()) return re } } From af380afcff5f358de9e6f349b9601844e447b529 Mon Sep 17 00:00:00 2001 From: xjbeta Date: Sun, 2 Jun 2024 13:33:58 +0800 Subject: [PATCH 4/7] fix huya --- IINA+/Utils/VideoDecoder/Huya.swift | 15 ++++++++------- IINA+/Utils/VideoDecoder/HuyaUrl.swift | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/IINA+/Utils/VideoDecoder/Huya.swift b/IINA+/Utils/VideoDecoder/Huya.swift index 9777aa87..9cd2a938 100644 --- a/IINA+/Utils/VideoDecoder/Huya.swift +++ b/IINA+/Utils/VideoDecoder/Huya.swift @@ -22,6 +22,9 @@ class Huya: NSObject, SupportSiteProtocol { return Session(configuration: configuration) }() + // T.a.uid + private let huyaUid = (Int(Date().timeIntervalSince1970 * 1000) % Int(1e10) * Int(1e3) + Int.random(in: Int(1e2).. Promise { getHuyaInfo(url).map { $0 @@ -89,7 +92,7 @@ class Huya: NSObject, SupportSiteProtocol { let info = try HuyaStream(object: $0) var yougetJson = YouGetJSON(rawUrl: url) - return info.write(to: yougetJson) + return info.write(to: yougetJson, uid: self.huyaUid) } } @@ -185,14 +188,14 @@ struct HuyaStream: Unmarshaling { vMultiStreamInfo = try object.value(for: "vMultiStreamInfo") } - func write(to yougetJson: YouGetJSON) -> YouGetJSON { + func write(to yougetJson: YouGetJSON, uid: Int) -> YouGetJSON { var yougetJson = yougetJson if let infoData = data.first { yougetJson.title = infoData.liveInfo.title let urls = infoData.streamInfoList.map { - $0.url() + $0.url(uid) } vMultiStreamInfo.enumerated().forEach { @@ -295,18 +298,16 @@ struct HuyaStream: Unmarshaling { var sFlvUrl: String var sFlvUrlSuffix: String var sFlvAntiCode: String - var lPresenterUid: Int init(object: MarshaledObject) throws { sStreamName = try object.value(for: "sStreamName") sFlvUrl = try object.value(for: "sFlvUrl") sFlvUrlSuffix = try object.value(for: "sFlvUrlSuffix") sFlvAntiCode = try object.value(for: "sFlvAntiCode") - lPresenterUid = try object.value(for: "lPresenterUid") } - func url() -> String { - HuyaUrl.format(lPresenterUid, sStreamName: sStreamName, sFlvUrl: sFlvUrl, sFlvUrlSuffix: sFlvUrlSuffix, sFlvAntiCode: sFlvAntiCode) + func url(_ uid: Int) -> String { + HuyaUrl.format(uid, sStreamName: sStreamName, sFlvUrl: sFlvUrl, sFlvUrlSuffix: sFlvUrlSuffix, sFlvAntiCode: sFlvAntiCode) } } } diff --git a/IINA+/Utils/VideoDecoder/HuyaUrl.swift b/IINA+/Utils/VideoDecoder/HuyaUrl.swift index 6bcb77b0..f72d8126 100644 --- a/IINA+/Utils/VideoDecoder/HuyaUrl.swift +++ b/IINA+/Utils/VideoDecoder/HuyaUrl.swift @@ -14,13 +14,13 @@ class HuyaUrl: NSObject { sFlvUrl: String, sFlvUrlSuffix: String, sFlvAntiCode: String) -> String { - + func now() -> Int { Int(Date().timeIntervalSince1970 * 1000) } - - let seqid = uid + now() + let sid = now() + var parameters = [String: String]() sFlvAntiCode.split(separator: "&").map { @@ -31,6 +31,9 @@ class HuyaUrl: NSObject { parameters[$0[0]] = $0[1] } + // (seqid - uid) > sid + let seqid = uid + now() + guard let convertUid = rotUid(uid), let wsSecret = wsSecret(sFlvAntiCode, convertUid: convertUid, seqid: seqid, streamName: sStreamName) else { return "" } @@ -49,7 +52,7 @@ class HuyaUrl: NSObject { parameters["ratio"] = "0" parameters["dMod"] = "mseh-32" - let example = "https://qvodlive-va.huya.com/src/1394575534-1394575534-5989656310331736064-2789274524-10057-A-0-1.flv?wsSecret=b9636212d1ad30223c157f5ac678d7c5&wsTime=665aaef2&seqid=7784383132214&ctype=huya_live&ver=1&txyp=o%3An4%3B&fs=bgct&sphdcdn=al_7-tx_3-js_3-ws_7-bd_2-hw_2&sphdDC=huya&sphd=264_*-265_*&exsphd=264_500,264_2000,264_4000,264_6000,264_8000,&ratio=500&&https=1&dMod=mseh-32&sdkPcdn=1_1&u=6065176706463&t=100&sv=2405220949&sdk_sid=1717219065187&a_block=0" + let example = "https://hw.flv.huya.com/src/1394575534-1394575534-5989656310331736064-2789274524-10057-A-0-1.flv?wsSecret=4b1ac7c8b5b3792b756f419bd6db09f8&wsTime=665aeff5&seqid=1750435781966&ctype=huya_webh5&ver=1&txyp=o%3An4%3B&fs=bgct&sphdcdn=al_7-tx_3-js_3-ws_7-bd_2-hw_2&sphdDC=huya&sphd=264_*-265_*&exsphd=264_500,264_2000,264_4000,264_6000,264_8000,&ratio=2000&dMod=mseh-32&sdkPcdn=1_1&u=33818100666&t=100&sv=2405220949&sdk_sid=1717235700093&a_block=0" var url = sFlvUrl.https() + "/" @@ -111,9 +114,7 @@ class HuyaUrl: NSObject { return r } - guard let fm = d["fm"]?.removingPercentEncoding, - let fmData = Data(base64Encoded: fm), - var u = String(data: fmData, encoding: .utf8), + guard var u = d["fm"]?.removingPercentEncoding?.base64Decode(), let l = d["wsTime"], let ctype = d["ctype"] else { return nil } From d27320658f9dab4152e572e3901535e5df8860de Mon Sep 17 00:00:00 2001 From: xjbeta Date: Sun, 2 Jun 2024 13:35:01 +0800 Subject: [PATCH 5/7] SPM --- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IINA+.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/IINA+.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 993da811..693cec9a 100644 --- a/IINA+.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/IINA+.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -60,8 +60,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/SDWebImage/SDWebImage", "state" : { - "revision" : "5642d1ffe3dbe628592443bd14154e31929727b4", - "version" : "5.19.2" + "revision" : "b8523c1642f3c142b06dd98443ea7c48343a4dfd", + "version" : "5.19.3" } }, { From 6546a561bf3f1ca61c98ddfea4c6397fecd0a32b Mon Sep 17 00:00:00 2001 From: xjbeta Date: Sun, 2 Jun 2024 13:35:07 +0800 Subject: [PATCH 6/7] Bump Version to 0.7.29. --- IINA+.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IINA+.xcodeproj/project.pbxproj b/IINA+.xcodeproj/project.pbxproj index 39010d8d..976c44d0 100644 --- a/IINA+.xcodeproj/project.pbxproj +++ b/IINA+.xcodeproj/project.pbxproj @@ -1041,7 +1041,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 0.7.28; + MARKETING_VERSION = 0.7.29; PRODUCT_BUNDLE_IDENTIFIER = "com.xjbeta.iina-plus"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1068,7 +1068,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 0.7.28; + MARKETING_VERSION = 0.7.29; PRODUCT_BUNDLE_IDENTIFIER = "com.xjbeta.iina-plus"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; From 000354ef10dd44df9cfcf6e377872bab2a98e163 Mon Sep 17 00:00:00 2001 From: xjbeta Date: Wed, 5 Jun 2024 19:01:04 +0800 Subject: [PATCH 7/7] huya mp api --- IINA+/Utils/VideoDecoder/Huya.swift | 104 ++++++++++++++++++++++--- IINA+/Utils/VideoDecoder/HuyaUrl.swift | 85 ++++++++++---------- 2 files changed, 135 insertions(+), 54 deletions(-) diff --git a/IINA+/Utils/VideoDecoder/Huya.swift b/IINA+/Utils/VideoDecoder/Huya.swift index 9cd2a938..26f04dce 100644 --- a/IINA+/Utils/VideoDecoder/Huya.swift +++ b/IINA+/Utils/VideoDecoder/Huya.swift @@ -26,20 +26,15 @@ class Huya: NSObject, SupportSiteProtocol { private let huyaUid = (Int(Date().timeIntervalSince1970 * 1000) % Int(1e10) * Int(1e3) + Int.random(in: Int(1e2).. Promise { - getHuyaInfo(url).map { + getHuyaInfoMP(url).map { $0 } } func decodeUrl(_ url: String) -> Promise { - getHuyaVideos(url) - /* - getHuyaInfoM(url).map { - var yougetJson = YouGetJSON(rawUrl: url) - yougetJson.title = $0.title - return $0.write(to: yougetJson, uid: self.huyaUid) - } - */ + getHuyaInfoMP(url).map { + $0.videos(url, uid: self.huyaUid) + } } // MARK: - Huya @@ -138,6 +133,19 @@ class Huya: NSObject, SupportSiteProtocol { return info } } + + func getHuyaInfoMP(_ url: String) -> Promise { + let ucs = url.pathComponents + guard ucs.count >= 3 else { + return .init(error: VideoGetError.invalidLink) + } + let rid = ucs[2] + + return pSession.request("https://mp.huya.com/cache.php?m=Live&do=profileRoom&roomid=\(rid)").responseData().map { + let jsonObj: JSONObject = try JSONParser.JSONObjectWithData($0.data) + return try HuyaInfoMP(object: jsonObj) + } + } } /* @@ -433,6 +441,84 @@ struct HuyaInfoM: Unmarshaling, LiveInfo { } } +struct HuyaInfoMP: Unmarshaling, LiveInfo { + + var title: String + var name: String + var avatar: String + var cover: String + var isLiving: Bool + var site: SupportSites = .huya + + var streamInfos: [HuyaInfoM.StreamInfo] + var bitRateInfos: [HuyaInfoM.BitRateInfo] + + init(object: any Marshal.MarshaledObject) throws { + let name1: String = try object.value(for: "data.liveData.roomName") + let name2: String = try object.value(for: "data.liveData.introduction") + + title = name1 == "" ? name2 : name1 + + name = try object.value(for: "data.liveData.nick") + avatar = try object.value(for: "data.liveData.avatar180") + avatar = avatar.https() + cover = try object.value(for: "data.liveData.screenshot") + cover = cover.https() + + let liveStatus: String = try object.value(for: "data.liveStatus") + isLiving = liveStatus == "ON" + + streamInfos = try object.value(for: "data.stream.baseSteamInfoList") + + let bitRateInfoString: String = try object.value(for: "data.liveData.bitRateInfo") + guard let data = bitRateInfoString.data(using: .utf8) else { + throw VideoGetError.notFountData + } + let jsonObj: [JSONObject] = try JSONParser.JSONArrayWithData(data) + bitRateInfos = try jsonObj.map(HuyaInfoM.BitRateInfo.init) + } + + + func videos(_ url: String, uid: Int) -> YouGetJSON { + var yougetJson = YouGetJSON(rawUrl: url) + yougetJson.title = title + + let urls = streamInfos +// .sorted { i1, i2 -> Bool in +// i1.sCdnType == defaultCDN +// } + .sorted { i1, i2 -> Bool in + !i1.sFlvUrl.contains("txdirect.flv.huya.com") + }.compactMap { + HuyaUrl.format( + uid, + sStreamName: $0.sStreamName, + sFlvUrl: $0.sFlvUrl, + sFlvUrlSuffix: $0.sFlvUrlSuffix, + sFlvAntiCode: $0.sFlvAntiCode) + } + + guard urls.count > 0 else { + return yougetJson + } + + bitRateInfos.map { + ($0.sDisplayName, $0.iBitRate) + }.forEach { (name, rate) in + var us = urls.map { + $0.replacingOccurrences(of: "&ratio=0", with: "&ratio=\(rate)") + } + var s = Stream(url: us.removeFirst()) + s.src = us + s.quality = rate == 0 ? 9999999 : rate + + yougetJson.streams[name] = s + } + + return yougetJson + } +} + struct HuyaVideoSelector: VideoSelector { var id: String diff --git a/IINA+/Utils/VideoDecoder/HuyaUrl.swift b/IINA+/Utils/VideoDecoder/HuyaUrl.swift index f72d8126..8e60de6f 100644 --- a/IINA+/Utils/VideoDecoder/HuyaUrl.swift +++ b/IINA+/Utils/VideoDecoder/HuyaUrl.swift @@ -21,36 +21,27 @@ class HuyaUrl: NSObject { let sid = now() - var parameters = [String: String]() + var antiCodes = antiCodeDic(sFlvAntiCode) - sFlvAntiCode.split(separator: "&").map { - $0.split(separator: "=", maxSplits: 1).map(String.init) - }.filter { - $0.count == 2 - }.forEach { - parameters[$0[0]] = $0[1] - } - - // (seqid - uid) > sid let seqid = uid + now() guard let convertUid = rotUid(uid), - let wsSecret = wsSecret(sFlvAntiCode, convertUid: convertUid, seqid: seqid, streamName: sStreamName) else { return "" } + let wsSecret = wsSecret(antiCodes, convertUid: convertUid, seqid: seqid, streamName: sStreamName) else { return "" } - parameters["u"] = "\(convertUid)" - parameters["wsSecret"] = wsSecret + antiCodes["u"] = "\(convertUid)" + antiCodes["wsSecret"] = wsSecret -// parameters["fm"] = nil - parameters["seqid"] = "\(seqid)" - parameters["sdk_sid"] = "\(sid)" - parameters["sv"] = "2405220949" +// antiCodes["fm"] = nil + antiCodes["seqid"] = "\(seqid)" + antiCodes["sdk_sid"] = "\(sid)" + antiCodes["sv"] = "2405220949" - parameters["sdkPcdn"] = "1_1" - parameters["t"] = "100" - parameters["a_block"] = "0" - parameters["ver"] = "1" - parameters["ratio"] = "0" - parameters["dMod"] = "mseh-32" + antiCodes["sdkPcdn"] = "1_1" +// parameters["t"] = "100" + antiCodes["a_block"] = "0" + antiCodes["ver"] = "1" + antiCodes["ratio"] = "0" + antiCodes["dMod"] = "mseh-32" let example = "https://hw.flv.huya.com/src/1394575534-1394575534-5989656310331736064-2789274524-10057-A-0-1.flv?wsSecret=4b1ac7c8b5b3792b756f419bd6db09f8&wsTime=665aeff5&seqid=1750435781966&ctype=huya_webh5&ver=1&txyp=o%3An4%3B&fs=bgct&sphdcdn=al_7-tx_3-js_3-ws_7-bd_2-hw_2&sphdDC=huya&sphd=264_*-265_*&exsphd=264_500,264_2000,264_4000,264_6000,264_8000,&ratio=2000&dMod=mseh-32&sdkPcdn=1_1&u=33818100666&t=100&sv=2405220949&sdk_sid=1717235700093&a_block=0" @@ -63,7 +54,7 @@ class HuyaUrl: NSObject { let pars = URLComponents(string: example)!.queryItems!.compactMap { let key = $0.name - if let value = parameters[key] { + if let value = antiCodes[key] { return key + "=" + value } else { Log("Huya parameters missing key, \($0.description)") @@ -101,31 +92,35 @@ class HuyaUrl: NSObject { return Int(a + n, radix: 2) } - private static func wsSecret(_ antiCode: String, - convertUid: Int, - seqid: Int, - streamName: String) -> String? { - - let d = antiCode.components(separatedBy: "&").reduce([String: String]()) { (re, str) -> [String: String] in - var r = re - let kv = str.components(separatedBy: "=") - guard kv.count == 2 else { return r } - r[kv[0]] = kv[1] - return r - } - - guard var u = d["fm"]?.removingPercentEncoding?.base64Decode(), - let l = d["wsTime"], - let ctype = d["ctype"] else { return nil } - - let s = "\(seqid)|\(ctype)|100".md5() - -// let o = this[Mt].replace(Xt, r).replace($t, this[Kt]).replace(Zt, s).replace(te, this[Bt]); + private static func wsSecret(_ antiCodes: [String: String], + convertUid: Int, + seqid: Int, + streamName: String) -> String? { + guard var u = antiCodes["fm"]?.removingPercentEncoding?.base64Decode(), + let l = antiCodes["wsTime"], + let ctype = antiCodes["ctype"] else { return nil } + let t = antiCodes["t"] ?? "100" + let s = "\(seqid)|\(ctype)|\(t)".md5() + + // let o = this[Mt].replace(Xt, r).replace($t, this[Kt]).replace(Zt, s).replace(te, this[Bt]); u = u.replacingOccurrences(of: "$0", with: "\(convertUid)") u = u.replacingOccurrences(of: "$1", with: streamName) u = u.replacingOccurrences(of: "$2", with: s) u = u.replacingOccurrences(of: "$3", with: l) - + return u.md5() } + + private static func antiCodeDic(_ antiCode: String) -> [String: String] { + var dic = [String: String]() + + antiCode.split(separator: "&").map { + $0.split(separator: "=", maxSplits: 1).map(String.init) + }.filter { + $0.count == 2 + }.forEach { + dic[$0[0]] = $0[1] + } + return dic + } }