Skip to content

Commit

Permalink
misc: 独立wbiSign代码,修改缓存判断
Browse files Browse the repository at this point in the history
  • Loading branch information
yichengchen committed Dec 1, 2024
1 parent f4a851d commit aef4d8e
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 129 deletions.
4 changes: 4 additions & 0 deletions BilibiliLive.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
492AD7112C001C7B007221C8 /* BVideoPlayPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492AD7102C001C7B007221C8 /* BVideoPlayPlugin.swift */; };
492AD7132C001CA7007221C8 /* String+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 492AD7122C001CA7007221C8 /* String+Error.swift */; };
493307FD2BF230DB003622ED /* LivePlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493307FC2BF230DB003622ED /* LivePlayerViewModel.swift */; };
4933B8912CFC1B070056B04D /* WebRequest+WbiSign.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4933B8902CFC1B070056B04D /* WebRequest+WbiSign.swift */; };
49389D6228AFEA2900B9DAFD /* VideoDanmuProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49389D6128AFEA2900B9DAFD /* VideoDanmuProvider.swift */; };
49389D8928B0A1B700B9DAFD /* UIViewController+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49389D8828B0A1B700B9DAFD /* UIViewController+Ext.swift */; };
49389D8C28B0A84500B9DAFD /* PersonalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49389D8B28B0A84500B9DAFD /* PersonalViewController.swift */; };
Expand Down Expand Up @@ -179,6 +180,7 @@
492AD7102C001C7B007221C8 /* BVideoPlayPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BVideoPlayPlugin.swift; sourceTree = "<group>"; };
492AD7122C001CA7007221C8 /* String+Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Error.swift"; sourceTree = "<group>"; };
493307FC2BF230DB003622ED /* LivePlayerViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LivePlayerViewModel.swift; sourceTree = "<group>"; };
4933B8902CFC1B070056B04D /* WebRequest+WbiSign.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebRequest+WbiSign.swift"; sourceTree = "<group>"; };
49389D6128AFEA2900B9DAFD /* VideoDanmuProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDanmuProvider.swift; sourceTree = "<group>"; };
49389D8828B0A1B700B9DAFD /* UIViewController+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Ext.swift"; sourceTree = "<group>"; };
49389D8B28B0A84500B9DAFD /* PersonalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonalViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -632,6 +634,7 @@
0A41EE1A2A63102B0066444C /* dm.pb.swift */,
0A41EE1B2A63102B0066444C /* dmView.pb.swift */,
49D39F27263AD40000F14497 /* WebRequest.swift */,
4933B8902CFC1B070056B04D /* WebRequest+WbiSign.swift */,
F9D382B326359EF90070508F /* ApiRequest.swift */,
F927ED8F2610A5E900EAB8E3 /* CookieManager.swift */,
4921389F2CD5CA6000891D56 /* SponsorBlockRequest.swift */,
Expand Down Expand Up @@ -975,6 +978,7 @@
49A441CD293F6DFD0007606C /* FollowUpsViewController.swift in Sources */,
AEA6AB1928FFF3DD007CE72E /* Settings.swift in Sources */,
498CF2962B63AABE0009793E /* block_splitter.c in Sources */,
4933B8912CFC1B070056B04D /* WebRequest+WbiSign.swift in Sources */,
494741C6290177BB005D6885 /* UpSpaceViewController.swift in Sources */,
496E5A552C01CDBB0062951B /* DebugPlugin.swift in Sources */,
49DA01A0296C466C00EEAE15 /* AVInfoPanelCollectionViewThumbnailCell+Hook.swift in Sources */,
Expand Down
141 changes: 141 additions & 0 deletions BilibiliLive/Request/WebRequest+WbiSign.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//
// WebRequest+WbiSign.swift
// BilibiliLive
//
// Created by yicheng on 1/12/2024.
//

import Alamofire
import CommonCrypto
import SwiftyJSON

extension WebRequest {
static func addWbiSign(method: HTTPMethod = .get,
url: URLConvertible,
parameters: Parameters = [:],
onComplete: @escaping (String?) -> Void)
{
do {
let urlObj = try url.asURL()
if urlObj.absoluteString.contains("/wbi/") == true, method == .get {
var request = URLRequest(url: urlObj)
request.method = .get
request = try URLEncoding.queryString.encode(request, with: parameters)
if let query = request.url?.query(percentEncoded: true) {
biliWbiSign(param: query) { res in
if let res {
let urlString = urlObj.absoluteString + "?" + res
onComplete(urlString)
return
} else {
onComplete(nil)
}
}
return
}
}
onComplete(nil)
} catch {
onComplete(nil)
}
}

// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/misc/sign/wbi.md#Swift
private static func biliWbiSign(param: String, completion: @escaping (String?) -> Void) {
func getMixinKey(orig: String) -> String {
return String(mixinKeyEncTab.map { orig[orig.index(orig.startIndex, offsetBy: $0)] }.prefix(32))
}

func encWbi(params: [String: Any], imgKey: String, subKey: String) -> [String: Any] {
var params = params
let mixinKey = getMixinKey(orig: imgKey + subKey)
let currTime = round(Date().timeIntervalSince1970)
params["wts"] = currTime
params = params.sorted { $0.key < $1.key }.reduce(into: [:]) { $0[$1.key] = $1.value }
params = params.mapValues { String(describing: $0).filter { !"!'()*".contains($0) } }
let query = params.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
let wbiSign = calculateMD5(string: query + mixinKey)
params["w_rid"] = wbiSign
return params
}

func getWbiKeys(completion: @escaping (Result<(imgKey: String, subKey: String), Error>) -> Void) {
class Cache {
var imgKey: String?
var subKey: String?
var lastUpdate: Date?

static let shared = Cache()
}

if let imgKey = Cache.shared.imgKey,
let subKey = Cache.shared.subKey,
let lastUpdate = Cache.shared.lastUpdate,
Date().timeIntervalSince(lastUpdate) < 60 * 60 * 12,
Calendar.current.isDate(Date(), inSameDayAs: lastUpdate)
{
completion(.success((imgKey, subKey)))
return
}

let headers: HTTPHeaders = [
"User-Agent": Keys.userAgent,
"Referer": Keys.referer,
]

AF.request("https://api.bilibili.com/x/web-interface/nav", headers: headers).responseData { response in
switch response.result {
case let .success(value):
let json = JSON(value)
let imgURL = json["data"]["wbi_img"]["img_url"].string ?? ""
let subURL = json["data"]["wbi_img"]["sub_url"].string ?? ""
let imgKey = imgURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
let subKey = subURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
Cache.shared.imgKey = imgKey
Cache.shared.subKey = subKey
Cache.shared.lastUpdate = Date()
completion(.success((imgKey, subKey)))
case let .failure(error):
completion(.failure(error))
}
}
}

func calculateMD5(string: String) -> String {
let data = Data(string.utf8)
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
_ = data.withUnsafeBytes {
CC_MD5($0.baseAddress, CC_LONG(data.count), &digest)
}
return digest.map { String(format: "%02hhx", $0) }.joined()
}

let mixinKeyEncTab = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52,
]

getWbiKeys { result in
switch result {
case let .success(keys):
let spdParam = param.components(separatedBy: "&")
var spdDicParam = [String: String]()
spdParam.forEach { pair in
let components = pair.components(separatedBy: "=")
if components.count == 2 {
spdDicParam[components[0]] = components[1]
}
}

let signedParams = encWbi(params: spdDicParam, imgKey: keys.imgKey, subKey: keys.subKey)
let query = signedParams.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
completion(query)
case let .failure(error):
print("Error getting keys: \(error)")
completion(nil)
}
}
}
}
129 changes: 0 additions & 129 deletions BilibiliLive/Request/WebRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
//

import Alamofire
import CommonCrypto
import Foundation
import SwiftProtobuf
import SwiftyJSON
Expand Down Expand Up @@ -113,36 +112,6 @@ enum WebRequest {
}
}

private static func addWbiSign(method: HTTPMethod = .get,
url: URLConvertible,
parameters: Parameters = [:],
onComplete: @escaping (String?) -> Void)
{
do {
let urlObj = try url.asURL()
if urlObj.absoluteString.contains("/wbi/") == true, method == .get {
var request = URLRequest(url: urlObj)
request.method = .get
request = try URLEncoding.queryString.encode(request, with: parameters)
if let query = request.url?.query(percentEncoded: true) {
biliWbiSign(param: query) { res in
if let res {
let urlString = urlObj.absoluteString + "?" + res
onComplete(urlString)
return
} else {
onComplete(nil)
}
}
return
}
}
onComplete(nil)
} catch {
onComplete(nil)
}
}

static func requestJSON(method: HTTPMethod = .get,
url: URLConvertible,
parameters: Parameters = [:],
Expand Down Expand Up @@ -550,104 +519,6 @@ extension WebRequest {
}
}

// MARK: - Wbi

extension WebRequest {
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/misc/sign/wbi.md#Swift
static func biliWbiSign(param: String, completion: @escaping (String?) -> Void) {
func getMixinKey(orig: String) -> String {
return String(mixinKeyEncTab.map { orig[orig.index(orig.startIndex, offsetBy: $0)] }.prefix(32))
}

func encWbi(params: [String: Any], imgKey: String, subKey: String) -> [String: Any] {
var params = params
let mixinKey = getMixinKey(orig: imgKey + subKey)
let currTime = round(Date().timeIntervalSince1970)
params["wts"] = currTime
params = params.sorted { $0.key < $1.key }.reduce(into: [:]) { $0[$1.key] = $1.value }
params = params.mapValues { String(describing: $0).filter { !"!'()*".contains($0) } }
let query = params.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
let wbiSign = calculateMD5(string: query + mixinKey)
params["w_rid"] = wbiSign
return params
}

func getWbiKeys(completion: @escaping (Result<(imgKey: String, subKey: String), Error>) -> Void) {
class Cache {
var imgKey: String?
var subKey: String?
var lastUpdate: Date?

static let shared = Cache()
}

if let imgKey = Cache.shared.imgKey, let subKey = Cache.shared.subKey, let lastUpdate = Cache.shared.lastUpdate, Date().timeIntervalSince(lastUpdate) < 60 * 60 * 12 {
completion(.success((imgKey, subKey)))
return
}

let headers: HTTPHeaders = [
"User-Agent": Keys.userAgent,
"Referer": Keys.referer,
]

AF.request("https://api.bilibili.com/x/web-interface/nav", headers: headers).responseData { response in
switch response.result {
case let .success(value):
let json = JSON(value)
let imgURL = json["data"]["wbi_img"]["img_url"].string ?? ""
let subURL = json["data"]["wbi_img"]["sub_url"].string ?? ""
let imgKey = imgURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
let subKey = subURL.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? ""
Cache.shared.imgKey = imgKey
Cache.shared.subKey = subKey
Cache.shared.lastUpdate = Date()
completion(.success((imgKey, subKey)))
case let .failure(error):
completion(.failure(error))
}
}
}

func calculateMD5(string: String) -> String {
let data = Data(string.utf8)
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
_ = data.withUnsafeBytes {
CC_MD5($0.baseAddress, CC_LONG(data.count), &digest)
}
return digest.map { String(format: "%02hhx", $0) }.joined()
}

let mixinKeyEncTab = [
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
36, 20, 34, 44, 52,
]

getWbiKeys { result in
switch result {
case let .success(keys):
let spdParam = param.components(separatedBy: "&")
var spdDicParam = [String: String]()
spdParam.forEach { pair in
let components = pair.components(separatedBy: "=")
if components.count == 2 {
spdDicParam[components[0]] = components[1]
}
}

let signedParams = encWbi(params: spdDicParam, imgKey: keys.imgKey, subKey: keys.subKey)
let query = signedParams.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
completion(query)
case let .failure(error):
print("Error getting keys: \(error)")
completion(nil)
}
}
}
}

struct HistoryData: DisplayData, Codable {
struct HistoryPage: Codable, Hashable {
let cid: Int
Expand Down

0 comments on commit aef4d8e

Please sign in to comment.