Files
steipete--codexbar/Sources/CodexBarCore/Providers/MiniMax/MiniMaxCookieHeader.swift
T
2026-07-13 12:22:33 +08:00

119 lines
4.6 KiB
Swift

import Foundation
public struct MiniMaxCookieOverride: Sendable {
public let cookieHeader: String
public let authorizationToken: String?
public let groupID: String?
public init(cookieHeader: String, authorizationToken: String?, groupID: String?) {
self.cookieHeader = cookieHeader
self.authorizationToken = authorizationToken
self.groupID = groupID
}
}
public enum MiniMaxCookieHeader {
private static let headerPatterns: [String] = [
#"(?i)-H\s*'Cookie:\s*([^']+)'"#,
#"(?i)-H\s*\"Cookie:\s*([^\"]+)\""#,
#"(?i)\bcookie:\s*'([^']+)'"#,
#"(?i)\bcookie:\s*\"([^\"]+)\""#,
#"(?i)\bcookie:\s*([^\r\n]+)"#,
#"(?i)(?:--cookie|-b)\s*'([^']+)'"#,
#"(?i)(?:--cookie|-b)\s*\"([^\"]+)\""#,
#"(?i)(?:--cookie|-b)\s*([^\s]+)"#,
]
private static let authorizationPattern = #"(?i)\bauthorization:\s*bearer\s+([A-Za-z0-9._\-+=/]+)"#
private static let groupIDPatterns = [
#"(?i)\bx-group-id:\s*([0-9]{4,})"#,
#"(?i)\bminimax_group_id_v2=([0-9]{4,})"#,
#"(?i)\bgroup[_]?id=([0-9]{4,})"#,
]
public static func override(from raw: String?) -> MiniMaxCookieOverride? {
guard let raw = raw?.trimmingCharacters(in: .whitespacesAndNewlines),
!raw.isEmpty
else {
return nil
}
guard let cookie = self.normalized(from: raw) else { return nil }
let authorizationToken = self.extractFirst(pattern: self.authorizationPattern, text: raw)
let groupID = self.extractFirst(patterns: self.groupIDPatterns, text: raw)
return MiniMaxCookieOverride(
cookieHeader: cookie,
authorizationToken: authorizationToken,
groupID: groupID)
}
public static func normalized(from raw: String?) -> String? {
guard var value = raw?.trimmingCharacters(in: .whitespacesAndNewlines), !value.isEmpty else {
return nil
}
if let extracted = self.extractHeader(from: value) {
value = extracted
}
value = self.stripCookiePrefix(value)
value = self.stripWrappingQuotes(value)
value = value.trimmingCharacters(in: .whitespacesAndNewlines)
return value.isEmpty ? nil : value
}
private static func extractHeader(from raw: String) -> String? {
for pattern in self.headerPatterns {
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { continue }
let range = NSRange(raw.startIndex..<raw.endIndex, in: raw)
guard let match = regex.firstMatch(in: raw, options: [], range: range),
match.numberOfRanges >= 2,
let captureRange = Range(match.range(at: 1), in: raw)
else {
continue
}
let captured = String(raw[captureRange]).trimmingCharacters(in: .whitespacesAndNewlines)
if !captured.isEmpty { return captured }
}
return nil
}
private static func stripCookiePrefix(_ raw: String) -> String {
let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)
guard trimmed.lowercased().hasPrefix("cookie:") else { return trimmed }
let idx = trimmed.index(trimmed.startIndex, offsetBy: "cookie:".count)
return String(trimmed[idx...]).trimmingCharacters(in: .whitespacesAndNewlines)
}
private static func stripWrappingQuotes(_ raw: String) -> String {
guard raw.count >= 2 else { return raw }
if (raw.hasPrefix("\"") && raw.hasSuffix("\"")) ||
(raw.hasPrefix("'") && raw.hasSuffix("'"))
{
return String(raw.dropFirst().dropLast())
}
return raw
}
private static func extractFirst(pattern: String, text: String) -> String? {
guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else { return nil }
let range = NSRange(text.startIndex..<text.endIndex, in: text)
guard let match = regex.firstMatch(in: text, options: [], range: range),
match.numberOfRanges >= 2,
let captureRange = Range(match.range(at: 1), in: text)
else {
return nil
}
let value = text[captureRange].trimmingCharacters(in: .whitespacesAndNewlines)
return value.isEmpty ? nil : String(value)
}
private static func extractFirst(patterns: [String], text: String) -> String? {
for pattern in patterns {
if let value = self.extractFirst(pattern: pattern, text: text) {
return value
}
}
return nil
}
}