//go:build llm_script package main import ( "fmt" "regexp" "strings" ) const defaultMinimaxTokenPlanURL = "https://platform.minimax.io/docs/guides/pricing-token-plan" type minimaxPlanSpec struct { billingCycle string priceUnit string blockPattern string modelScope []string tiers []string planCodes []string planNames []string quotaUnit string } func parseMinimaxTokenPlans(raw string) ([]subscriptionImportRecord, error) { publishedAt, known := publishedAtFromText(raw) normalized := normalizeMinimaxTokenPlanText(raw) specs := []minimaxPlanSpec{ { billingCycle: "monthly", priceUnit: "USD/month", blockPattern: `Monthly.*?Starter\s+Plus\s+Max\s+Price\s+\$([\d,]+)\s*/month\s+\$([\d,]+)\s*/month\s+\$([\d,]+)\s*/month\s+M2\.7\s+([\d,]+)\s+requests/5hrs\s+([\d,]+)\s+requests/5hrs\s+([\d,]+)\s+requests/5hrs`, modelScope: []string{"MiniMax-M2.7"}, tiers: []string{"Starter", "Plus", "Max"}, planCodes: []string{"minimax-token-plan-starter", "minimax-token-plan-plus", "minimax-token-plan-max"}, planNames: []string{"MiniMax Token Plan Starter", "MiniMax Token Plan Plus", "MiniMax Token Plan Max"}, quotaUnit: "requests/5hrs", }, { billingCycle: "monthly", priceUnit: "USD/month", blockPattern: `Monthly.*?Highspeed Plans\s+Plus-Highspeed\s+Max-Highspeed\s+Ultra-Highspeed\s+Price\s+\$([\d,]+)\s*/month\s+\$([\d,]+)\s*/month\s+\$([\d,]+)\s*/month\s+M2\.7-highspeed\s+([\d,]+)\s+requests/5hrs\s+([\d,]+)\s+requests/5hrs\s+([\d,]+)\s+requests/5hrs`, modelScope: []string{"MiniMax-M2.7-Highspeed"}, tiers: []string{"Plus-Highspeed", "Max-Highspeed", "Ultra-Highspeed"}, planCodes: []string{"minimax-token-plan-plus-highspeed", "minimax-token-plan-max-highspeed", "minimax-token-plan-ultra-highspeed"}, planNames: []string{"MiniMax Token Plan Plus-Highspeed", "MiniMax Token Plan Max-Highspeed", "MiniMax Token Plan Ultra-Highspeed"}, quotaUnit: "requests/5hrs", }, { billingCycle: "yearly", priceUnit: "USD/year", blockPattern: `Yearly.*?Starter\s+Plus\s+Max\s+Price\s+\$([\d,]+)\s*/year\s+\$([\d,]+)\s*/year\s+\$([\d,]+)\s*/year\s+M2\.7\s+([\d,]+)\s+requests/5hrs\s+([\d,]+)\s+requests/5hrs\s+([\d,]+)\s+requests/5hrs`, modelScope: []string{"MiniMax-M2.7"}, tiers: []string{"Starter-Yearly", "Plus-Yearly", "Max-Yearly"}, planCodes: []string{"minimax-token-plan-starter-yearly", "minimax-token-plan-plus-yearly", "minimax-token-plan-max-yearly"}, planNames: []string{"MiniMax Token Plan Starter Yearly", "MiniMax Token Plan Plus Yearly", "MiniMax Token Plan Max Yearly"}, quotaUnit: "requests/5hrs", }, { billingCycle: "yearly", priceUnit: "USD/year", blockPattern: `Yearly.*?Highspeed Plans\s+Plus-Highspeed\s+Max-Highspeed\s+Ultra-Highspeed\s+Price\s+\$([\d,]+)\s*/year\s+\$([\d,]+)\s*/year\s+\$([\d,]+)\s*/year\s+M2\.7-highspeed\s+([\d,]+)\s+requests/5hrs\s+([\d,]+)\s+requests/5hrs\s+([\d,]+)\s+requests/5hrs`, modelScope: []string{"MiniMax-M2.7-Highspeed"}, tiers: []string{"Plus-Highspeed-Yearly", "Max-Highspeed-Yearly", "Ultra-Highspeed-Yearly"}, planCodes: []string{"minimax-token-plan-plus-highspeed-yearly", "minimax-token-plan-max-highspeed-yearly", "minimax-token-plan-ultra-highspeed-yearly"}, planNames: []string{"MiniMax Token Plan Plus-Highspeed Yearly", "MiniMax Token Plan Max-Highspeed Yearly", "MiniMax Token Plan Ultra-Highspeed Yearly"}, quotaUnit: "requests/5hrs", }, } var records []subscriptionImportRecord for _, spec := range specs { parsed, err := parseMinimaxPlanBlock(normalized, spec, publishedAt) if err != nil { return nil, err } records = append(records, parsed...) } standardNotes := extractMinimaxNotes(normalized, []string{ "Speech 2.8", "image-01", "Hailuo-2.3-Fast", "Hailuo-2.3", "Music-2.6", }) for i := range records { records[i].PublishedAtKnown = known if strings.Contains(records[i].PlanCode, "highspeed") { records[i].Notes = joinNonEmptyNotes(records[i].Notes, "高速版覆盖 MiniMax-M2.7-Highspeed。") continue } records[i].Notes = joinNonEmptyNotes(records[i].Notes, standardNotes) } return records, nil } func parseMinimaxPlanBlock(raw string, spec minimaxPlanSpec, publishedAt string) ([]subscriptionImportRecord, error) { match := regexp.MustCompile(spec.blockPattern).FindStringSubmatch(raw) if len(match) != 7 { return nil, fmt.Errorf("unexpected minimax %s block", spec.billingCycle) } records := make([]subscriptionImportRecord, 0, 3) for i := range spec.tiers { records = append(records, subscriptionImportRecord{ ProviderName: "MiniMax", ProviderNameCn: "MiniMax", ProviderCountry: "CN", ProviderWebsite: "https://platform.minimax.io", OperatorName: "MiniMax", OperatorNameCn: "MiniMax", OperatorCountry: "CN", OperatorWebsite: "https://platform.minimax.io/docs/guides/pricing-overview", OperatorType: "official", PlanFamily: "token_plan", PlanCode: spec.planCodes[i], PlanName: spec.planNames[i], Tier: spec.tiers[i], BillingCycle: spec.billingCycle, Currency: "USD", ListPrice: mustParseSubscriptionPrice(match[i+1]), PriceUnit: spec.priceUnit, QuotaValue: mustParseSubscriptionInt64(match[i+4]), QuotaUnit: spec.quotaUnit, PlanScope: "Token Plan", ModelScope: append([]string(nil), spec.modelScope...), SourceURL: defaultMinimaxTokenPlanURL, PublishedAt: publishedAt, EffectiveDate: effectiveDateFromPublishedAt(publishedAt), PublishedAtKnown: true, }) } return records, nil } func normalizeMinimaxTokenPlanText(raw string) string { replacer := strings.NewReplacer( "High-Speed", "Highspeed", "High Speed", "Highspeed", "Max-High-Speed", "Max-Highspeed", "Ultra-High-Speed", "Ultra-Highspeed", "Plus `Cost-Effective`", "Plus", "Max `Extra Large`", "Max", "Starter `Save $20`", "Starter", "Plus `Save $40`", "Plus", "Max `Save $100`", "Max", "Plus-Highspeed `Save $80`", "Plus-Highspeed", "Max-Highspeed `Save $160`", "Max-Highspeed", "Ultra-Highspeed `Save $300`", "Ultra-Highspeed", "Subscribe Now Standard Plans:", "", "Subscribe Now", "", "Standard Plans:", "", "Highspeed Plans:", "Highspeed Plans", ) normalized := replacer.Replace(raw) normalized = strings.ReplaceAll(normalized, "\r\n", "\n") normalized = strings.ReplaceAll(normalized, "\r", "\n") normalized = strings.ReplaceAll(normalized, "|", " ") normalized = strings.ReplaceAll(normalized, "---", " ") normalized = regexp.MustCompile(`\s+`).ReplaceAllString(normalized, " ") return strings.TrimSpace(normalized) } func extractMinimaxNotes(raw string, markers []string) string { var hits []string for _, marker := range markers { if strings.Contains(raw, marker) { hits = append(hits, marker) } } if len(hits) == 0 { return "" } return "附带配额包含 " + strings.Join(hits, " / ") + "。" } func joinNonEmptyNotes(parts ...string) string { filtered := make([]string, 0, len(parts)) for _, part := range parts { part = strings.TrimSpace(part) if part == "" { continue } filtered = append(filtered, part) } return strings.Join(filtered, " ") }