random-api-go/services/csv_service.go

166 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package services
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"random-api-go/config"
"random-api-go/models"
"random-api-go/utils"
"strings"
"sync"
)
var (
CSVPathsCache map[string]map[string]string
csvCache = make(map[string]*models.URLSelector)
Mu sync.RWMutex
)
// InitializeCSVService 初始化CSV服务
func InitializeCSVService() error {
return LoadCSVPaths()
}
func LoadCSVPaths() error {
var data []byte
var err error
// 获取环境变量中的基础URL
baseURL := os.Getenv(config.EnvBaseURL)
if baseURL != "" {
// 构建完整的URL
var fullURL string
if strings.HasPrefix(baseURL, "http://") || strings.HasPrefix(baseURL, "https://") {
fullURL = utils.JoinURLPath(baseURL, "url.json")
} else {
fullURL = "https://" + utils.JoinURLPath(baseURL, "url.json")
}
log.Printf("Attempting to read url.json from: %s", fullURL)
// 创建HTTP客户端
client := &http.Client{
Timeout: config.RequestTimeout,
}
resp, err := client.Get(fullURL)
if err != nil {
return fmt.Errorf("failed to fetch url.json: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to fetch url.json, status code: %d", resp.StatusCode)
}
data, err = io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read url.json response: %w", err)
}
} else {
// 从本地文件读取
jsonPath := filepath.Join("public", "url.json")
log.Printf("Attempting to read local file: %s", jsonPath)
data, err = os.ReadFile(jsonPath)
if err != nil {
return fmt.Errorf("failed to read local url.json: %w", err)
}
}
var result map[string]map[string]string
if err := json.Unmarshal(data, &result); err != nil {
return fmt.Errorf("failed to unmarshal url.json: %w", err)
}
Mu.Lock()
CSVPathsCache = result
Mu.Unlock()
log.Println("CSV paths loaded from url.json")
return nil
}
func GetCSVContent(path string) (*models.URLSelector, error) {
Mu.RLock()
selector, exists := csvCache[path]
Mu.RUnlock()
if exists {
return selector, nil
}
var fileContent []byte
var err error
// 获取环境变量中的基础URL
baseURL := os.Getenv(config.EnvBaseURL)
if baseURL != "" {
// 如果设置了基础URL构建完整的URL
var fullURL string
if strings.HasPrefix(baseURL, "http://") || strings.HasPrefix(baseURL, "https://") {
// 如果baseURL已经包含协议,直接使用
fullURL = utils.JoinURLPath(baseURL, path)
} else {
// 如果没有协议,添加https://
fullURL = "https://" + utils.JoinURLPath(baseURL, path)
}
log.Printf("尝试从URL获取: %s", fullURL)
// 创建HTTP客户端
client := &http.Client{
Timeout: config.RequestTimeout,
}
resp, err := client.Get(fullURL)
if err != nil {
return nil, fmt.Errorf("HTTP请求失败: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP请求返回非200状态码: %d", resp.StatusCode)
}
fileContent, err = io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应内容失败: %w", err)
}
} else {
// 如果没有设置基础URL从本地文件读取
fullPath := filepath.Join("public", path)
log.Printf("尝试读取本地文件: %s", fullPath)
fileContent, err = os.ReadFile(fullPath)
if err != nil {
return nil, fmt.Errorf("读取CSV内容时出错: %w", err)
}
}
lines := strings.Split(string(fileContent), "\n")
uniqueURLs := make(map[string]bool)
var fileArray []string
for _, line := range lines {
trimmed := strings.TrimSpace(line)
if trimmed != "" && !strings.HasPrefix(trimmed, "#") && !uniqueURLs[trimmed] {
fileArray = append(fileArray, trimmed)
uniqueURLs[trimmed] = true
}
}
selector = models.NewURLSelector(fileArray)
Mu.Lock()
csvCache[path] = selector
Mu.Unlock()
return selector, nil
}