Initial sanitized code sync
This commit is contained in:
134
pkg/provider/card/file.go
Normal file
134
pkg/provider/card/file.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package card
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FileProvider loads cards from a local TXT file (one card per line).
|
||||
// Supported formats:
|
||||
// 卡号|月|年|CVC
|
||||
// 卡号|月|年|CVC|姓名|国家|货币
|
||||
// 卡号|月|年|CVC|姓名|国家|货币|地址|城市|州|邮编
|
||||
// 卡号,月,年,CVC
|
||||
// 卡号,月,年,CVC,姓名,国家,货币,地址,城市,州,邮编
|
||||
type FileProvider struct {
|
||||
pool *CardPool
|
||||
}
|
||||
|
||||
// NewFileProvider creates a FileProvider by reading cards from a text file.
|
||||
func NewFileProvider(filePath string, defaultCountry, defaultCurrency string, poolCfg PoolConfig) (*FileProvider, error) {
|
||||
cards, err := parseCardFile(filePath, defaultCountry, defaultCurrency)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(cards) == 0 {
|
||||
return nil, fmt.Errorf("no valid cards found in %s", filePath)
|
||||
}
|
||||
|
||||
pool := NewCardPool(poolCfg)
|
||||
pool.AddCards(cards)
|
||||
|
||||
return &FileProvider{pool: pool}, nil
|
||||
}
|
||||
|
||||
// GetCard returns the next available card from the pool.
|
||||
func (p *FileProvider) GetCard(ctx context.Context) (*CardInfo, error) {
|
||||
return p.pool.GetCard()
|
||||
}
|
||||
|
||||
// ReportResult reports the usage outcome.
|
||||
func (p *FileProvider) ReportResult(ctx context.Context, card *CardInfo, success bool) error {
|
||||
p.pool.ReportResult(card, success)
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseCardFile reads and parses a card file.
|
||||
func parseCardFile(filePath, defaultCountry, defaultCurrency string) ([]*CardInfo, error) {
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open card file: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var cards []*CardInfo
|
||||
scanner := bufio.NewScanner(f)
|
||||
lineNum := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
lineNum++
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
|
||||
// Skip empty lines and comments
|
||||
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, "//") {
|
||||
continue
|
||||
}
|
||||
|
||||
card, err := parseLine(line, defaultCountry, defaultCurrency)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("line %d: %w", lineNum, err)
|
||||
}
|
||||
cards = append(cards, card)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("read card file: %w", err)
|
||||
}
|
||||
|
||||
return cards, nil
|
||||
}
|
||||
|
||||
// parseLine parses a single card line. Supports | and , delimiters.
|
||||
func parseLine(line, defaultCountry, defaultCurrency string) (*CardInfo, error) {
|
||||
var parts []string
|
||||
if strings.Contains(line, "|") {
|
||||
parts = strings.Split(line, "|")
|
||||
} else {
|
||||
parts = strings.Split(line, ",")
|
||||
}
|
||||
|
||||
// Trim all parts
|
||||
for i := range parts {
|
||||
parts[i] = strings.TrimSpace(parts[i])
|
||||
}
|
||||
|
||||
if len(parts) < 4 {
|
||||
return nil, fmt.Errorf("expected at least 4 fields (number|month|year|cvc), got %d", len(parts))
|
||||
}
|
||||
|
||||
card := &CardInfo{
|
||||
Number: parts[0],
|
||||
ExpMonth: parts[1],
|
||||
ExpYear: parts[2],
|
||||
CVC: parts[3],
|
||||
Country: defaultCountry,
|
||||
Currency: defaultCurrency,
|
||||
}
|
||||
|
||||
if len(parts) >= 5 && parts[4] != "" {
|
||||
card.Name = parts[4]
|
||||
}
|
||||
if len(parts) >= 6 && parts[5] != "" {
|
||||
card.Country = parts[5]
|
||||
}
|
||||
if len(parts) >= 7 && parts[6] != "" {
|
||||
card.Currency = parts[6]
|
||||
}
|
||||
if len(parts) >= 8 && parts[7] != "" {
|
||||
card.Address = parts[7]
|
||||
}
|
||||
if len(parts) >= 9 && parts[8] != "" {
|
||||
card.City = parts[8]
|
||||
}
|
||||
if len(parts) >= 10 && parts[9] != "" {
|
||||
card.State = parts[9]
|
||||
}
|
||||
if len(parts) >= 11 && parts[10] != "" {
|
||||
card.PostalCode = parts[10]
|
||||
}
|
||||
|
||||
return card, nil
|
||||
}
|
||||
Reference in New Issue
Block a user