Skip to content

Commit dcf93bb

Browse files
committed
Merge branch 'develop'
2 parents f1e8e4a + c4b8b5c commit dcf93bb

File tree

4 files changed

+108
-7
lines changed

4 files changed

+108
-7
lines changed

IINA+.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@
11001100
"@executable_path/../Frameworks",
11011101
);
11021102
MACOSX_DEPLOYMENT_TARGET = 11.5;
1103-
MARKETING_VERSION = 0.8.8;
1103+
MARKETING_VERSION = 0.8.9;
11041104
PRODUCT_BUNDLE_IDENTIFIER = "com.xjbeta.iina-plus";
11051105
PRODUCT_NAME = "$(TARGET_NAME)";
11061106
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1127,7 +1127,7 @@
11271127
"@executable_path/../Frameworks",
11281128
);
11291129
MACOSX_DEPLOYMENT_TARGET = 11.5;
1130-
MARKETING_VERSION = 0.8.8;
1130+
MARKETING_VERSION = 0.8.9;
11311131
PRODUCT_BUNDLE_IDENTIFIER = "com.xjbeta.iina-plus";
11321132
PRODUCT_NAME = "$(TARGET_NAME)";
11331133
PROVISIONING_PROFILE_SPECIFIER = "";

IINA+/Utils/Danmaku/DanmakuBiliLive.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ extension Danmaku {
106106
}
107107

108108
func bililiveToken(_ rid: String) async throws -> String {
109-
let url = "https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=\(rid)&type=0"
109+
110+
let param = try await Processes.shared.videoDecoder.bilibili.wbiSign("id=\(rid)&type=0&web_location=444.8")
111+
let url = "https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?\(param)"
112+
110113
let data = try await AF.request(url).serializingData().value
111114
let json = try JSONParser.JSONObjectWithData(data)
112115

IINA+/Utils/VideoDecoder/BilbiliShare.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import Foundation
1010
import Alamofire
1111
import Marshal
12+
import CommonCrypto
13+
import CryptoSwift
1214

1315
actor BilibiliShare {
1416

@@ -84,6 +86,62 @@ actor BilibiliShare {
8486

8587
return yougetJson
8688
}
89+
90+
91+
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/f1001353f83e12e018ae6bc42fa73654986eb544/docs/misc/sign/wbi.md#swift
92+
93+
func biliWbiSign(param: String, wbiImg: String, wbiSub: String) -> String {
94+
func getMixinKey(orig: String) -> String {
95+
String(mixinKeyEncTab.map { orig[orig.index(orig.startIndex, offsetBy: $0)] }.prefix(32))
96+
}
97+
98+
func encWbi(params: [String: Any], imgKey: String, subKey: String) -> [String: Any] {
99+
var params = params
100+
let mixinKey = getMixinKey(orig: imgKey + subKey)
101+
let currTime = Int(Date().timeIntervalSince1970)
102+
params["wts"] = currTime
103+
104+
let query = params.sorted {
105+
$0.key < $1.key
106+
}.map { (key, value) -> String in
107+
let stringValue: String
108+
109+
if let doubleValue = value as? Double, doubleValue.truncatingRemainder(dividingBy: 1) == 0 {
110+
stringValue = String(Int(doubleValue))
111+
} else {
112+
stringValue = String(describing: value)
113+
}
114+
115+
let filteredValue = stringValue.filter { !"!'()*".contains($0) }
116+
117+
return "\(key)=\(filteredValue)"
118+
}.joined(separator: "&")
119+
120+
let wbiSign = (query + mixinKey).md5()
121+
params["w_rid"] = wbiSign
122+
123+
return params
124+
}
125+
126+
let mixinKeyEncTab = [
127+
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
128+
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
129+
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
130+
36, 20, 34, 44, 52
131+
]
132+
133+
let spdParam = param.components(separatedBy: "&")
134+
var spdDicParam = [String: String]()
135+
for pair in spdParam {
136+
let components = pair.components(separatedBy: "=")
137+
if components.count == 2 {
138+
spdDicParam[components[0]] = components[1]
139+
}
140+
}
141+
142+
let signedParams = encWbi(params: spdDicParam, imgKey: wbiImg, subKey: wbiSub)
143+
return signedParams.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
144+
}
87145
}
88146

89147
struct BilibiliPlayInfo: Unmarshaling {

IINA+/Utils/VideoDecoder/Bilibili.swift

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ actor Bilibili: SupportSiteProtocol {
1515
let biliShare = BilibiliShare()
1616
let bangumi = Bangumi()
1717

18+
private var wbiKeys: (img: String, sub: String)?
19+
private var wbiRefreshDate: Date?
20+
1821
func liveInfo(_ url: String) async throws -> any LiveInfo {
1922
let isBangumi = SupportSites(url: url) == .bangumi
2023

@@ -191,12 +194,25 @@ actor Bilibili: SupportSiteProtocol {
191194
let data = try await AF.request("https://api.bilibili.com/x/web-interface/nav").serializingData().value
192195
let json: JSONObject = try JSONParser.JSONObjectWithData(data)
193196
let isLogin: Bool = try json.value(for: "data.isLogin")
197+
194198
NotificationCenter.default.post(name: .biliStatusChanged, object: nil, userInfo: ["isLogin": isLogin])
195199
var name = ""
196-
if isLogin {
197-
name = try json.value(for: "data.uname")
198-
}
199-
200+
201+
guard isLogin else {
202+
return (isLogin, name)
203+
}
204+
205+
name = try json.value(for: "data.uname")
206+
guard let s1: String = try? json.value(for: "data.wbi_img.img_url"),
207+
let s2: String = try? json.value(for: "data.wbi_img.sub_url"),
208+
let img = URL(string: s1)?.deletingPathExtension().lastPathComponent,
209+
let sub = URL(string: s2)?.deletingPathExtension().lastPathComponent else {
210+
Log("Bilibili wbi keys not found")
211+
return (false, name)
212+
}
213+
214+
wbiKeys = (img, sub)
215+
200216
return (isLogin, name)
201217
}
202218

@@ -215,6 +231,30 @@ actor Bilibili: SupportSiteProtocol {
215231
return try json.value(for: "data.mid")
216232
}
217233

234+
func wbiSign(_ param: String) async throws -> String {
235+
let now = Date()
236+
var needsRefresh = true
237+
238+
if let lastRefresh = wbiRefreshDate {
239+
var calendar = Calendar.current
240+
calendar.timeZone = TimeZone(identifier: "Asia/Shanghai")!
241+
if calendar.isDate(lastRefresh, inSameDayAs: now) {
242+
needsRefresh = false
243+
}
244+
}
245+
246+
if needsRefresh || wbiKeys == nil {
247+
let _ = try await isLogin()
248+
self.wbiRefreshDate = now
249+
}
250+
251+
guard let wbiKeys else {
252+
return ""
253+
}
254+
255+
return await biliShare.biliWbiSign(param: param, wbiImg: wbiKeys.img, wbiSub: wbiKeys.sub)
256+
}
257+
218258
func dynamicList(_ uid: Int,
219259
_ action: BilibiliDynamicAction = .init😅,
220260
_ dynamicID: Int = -1) async throws -> [BilibiliCard] {

0 commit comments

Comments
 (0)