180 lines
5.2 KiB
Swift
180 lines
5.2 KiB
Swift
import Foundation
|
|
|
|
public enum ClaudePlan: String, CaseIterable, Sendable {
|
|
case max
|
|
case pro
|
|
case team
|
|
case enterprise
|
|
case ultra
|
|
|
|
public var brandedLoginMethod: String {
|
|
switch self {
|
|
case .max:
|
|
"Claude Max"
|
|
case .pro:
|
|
"Claude Pro"
|
|
case .team:
|
|
"Claude Team"
|
|
case .enterprise:
|
|
"Claude Enterprise"
|
|
case .ultra:
|
|
"Claude Ultra"
|
|
}
|
|
}
|
|
|
|
/// Branded label including the Max usage multiplier when the rate-limit tier carries one.
|
|
public func brandedLoginMethod(rateLimitTier: String?) -> String {
|
|
guard self == .max, let multiplier = Self.maxUsageMultiplier(rateLimitTier: rateLimitTier) else {
|
|
return self.brandedLoginMethod
|
|
}
|
|
return "\(self.brandedLoginMethod) \(multiplier)"
|
|
}
|
|
|
|
public var compactLoginMethod: String {
|
|
switch self {
|
|
case .max:
|
|
"Max"
|
|
case .pro:
|
|
"Pro"
|
|
case .team:
|
|
"Team"
|
|
case .enterprise:
|
|
"Enterprise"
|
|
case .ultra:
|
|
"Ultra"
|
|
}
|
|
}
|
|
|
|
public var countsAsSubscription: Bool {
|
|
switch self {
|
|
case .max, .pro, .team, .ultra:
|
|
true
|
|
case .enterprise:
|
|
false
|
|
}
|
|
}
|
|
|
|
public static func fromOAuthRateLimitTier(_ rateLimitTier: String?) -> Self? {
|
|
self.fromRateLimitTier(rateLimitTier)
|
|
}
|
|
|
|
public static func fromOAuthCredentials(subscriptionType: String?, rateLimitTier: String?) -> Self? {
|
|
self.fromCompatibilityLoginMethod(subscriptionType)
|
|
?? self.fromOAuthRateLimitTier(rateLimitTier)
|
|
}
|
|
|
|
public static func fromWebAccount(rateLimitTier: String?, billingType: String?) -> Self? {
|
|
if let plan = self.fromRateLimitTier(rateLimitTier) {
|
|
return plan
|
|
}
|
|
|
|
let tier = Self.normalized(rateLimitTier)
|
|
let billing = Self.normalized(billingType)
|
|
if billing.contains("stripe"), tier.contains("claude") {
|
|
return .pro
|
|
}
|
|
return nil
|
|
}
|
|
|
|
public static func fromCompatibilityLoginMethod(_ loginMethod: String?) -> Self? {
|
|
let words = Self.normalizedWords(loginMethod)
|
|
if words.isEmpty {
|
|
return nil
|
|
}
|
|
if words.contains("max") {
|
|
return .max
|
|
}
|
|
if words.contains("pro") {
|
|
return .pro
|
|
}
|
|
if words.contains("team") {
|
|
return .team
|
|
}
|
|
if words.contains("enterprise") {
|
|
return .enterprise
|
|
}
|
|
if words.contains("ultra") {
|
|
return .ultra
|
|
}
|
|
return nil
|
|
}
|
|
|
|
public static func oauthLoginMethod(rateLimitTier: String?) -> String? {
|
|
self.fromOAuthRateLimitTier(rateLimitTier)?.brandedLoginMethod(rateLimitTier: rateLimitTier)
|
|
}
|
|
|
|
public static func oauthLoginMethod(subscriptionType: String?, rateLimitTier: String?) -> String? {
|
|
self.fromOAuthCredentials(
|
|
subscriptionType: subscriptionType,
|
|
rateLimitTier: rateLimitTier)?.brandedLoginMethod(rateLimitTier: rateLimitTier)
|
|
}
|
|
|
|
public static func webLoginMethod(rateLimitTier: String?, billingType: String?) -> String? {
|
|
self.fromWebAccount(
|
|
rateLimitTier: rateLimitTier,
|
|
billingType: billingType)?.brandedLoginMethod(rateLimitTier: rateLimitTier)
|
|
}
|
|
|
|
public static func cliCompatibilityLoginMethod(_ loginMethod: String?) -> String? {
|
|
guard let loginMethod = loginMethod?.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
!loginMethod.isEmpty
|
|
else {
|
|
return nil
|
|
}
|
|
|
|
if let plan = self.fromCompatibilityLoginMethod(loginMethod) {
|
|
return plan.compactLoginMethod
|
|
}
|
|
|
|
return loginMethod
|
|
}
|
|
|
|
public static func isSubscriptionLoginMethod(_ loginMethod: String?) -> Bool {
|
|
self.fromCompatibilityLoginMethod(loginMethod)?.countsAsSubscription ?? false
|
|
}
|
|
|
|
private static func fromRateLimitTier(_ rateLimitTier: String?) -> Self? {
|
|
let tier = Self.normalized(rateLimitTier)
|
|
if tier.contains("max") {
|
|
return .max
|
|
}
|
|
if tier.contains("pro") {
|
|
return .pro
|
|
}
|
|
if tier.contains("team") {
|
|
return .team
|
|
}
|
|
if tier.contains("enterprise") {
|
|
return .enterprise
|
|
}
|
|
return nil
|
|
}
|
|
|
|
private static func maxUsageMultiplier(rateLimitTier: String?) -> String? {
|
|
let words = Self.normalizedWords(rateLimitTier)
|
|
guard let maxIndex = words.firstIndex(of: Self.max.rawValue),
|
|
words.indices.contains(maxIndex + 1)
|
|
else {
|
|
return nil
|
|
}
|
|
|
|
let multiplier = words[maxIndex + 1]
|
|
guard multiplier.last == "x", Int(multiplier.dropLast()) != nil else {
|
|
return nil
|
|
}
|
|
return multiplier
|
|
}
|
|
|
|
private static func normalized(_ text: String?) -> String {
|
|
text?
|
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
.lowercased() ?? ""
|
|
}
|
|
|
|
private static func normalizedWords(_ text: String?) -> [String] {
|
|
self.normalized(text)
|
|
.split(whereSeparator: { !$0.isLetter && !$0.isNumber })
|
|
.map(String.init)
|
|
}
|
|
}
|