mirror of
https://github.com/netscrawler/changeAPI.git
synced 2025-05-06 07:19:54 +00:00
178 lines
3.9 KiB
Go
178 lines
3.9 KiB
Go
package rateExtract
|
|
|
|
import (
|
|
"compress/gzip"
|
|
"converter/internal/domain/models"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"golang.org/x/text/encoding/charmap"
|
|
)
|
|
|
|
type resultType struct {
|
|
XMLName xml.Name `xml:"ValCurs"`
|
|
Valute []struct {
|
|
NumCode string `xml:"NumCode"`
|
|
CharCode string `xml:"CharCode"`
|
|
Nominal string `xml:"Nominal"`
|
|
Name string `xml:"Name"`
|
|
Value string `xml:"Value"`
|
|
} `xml:"Valute"`
|
|
}
|
|
|
|
type cacheKeyType struct {
|
|
CurrencyId string
|
|
Date string
|
|
}
|
|
|
|
type cacheResultType struct {
|
|
Rate float64
|
|
}
|
|
|
|
var urlTemplate string = "https://www.cbr.ru/scripts/XML_daily.asp?date_req=%s"
|
|
|
|
var cache map[cacheKeyType]*cacheResultType
|
|
|
|
func GetExchangeRate(currencyId string) (models.VunitRate, error) {
|
|
date := time.Now()
|
|
if cache == nil {
|
|
cache = map[cacheKeyType]*cacheResultType{}
|
|
}
|
|
|
|
reqDate := fmt.Sprintf("%02d/%02d/%d", date.Day(), date.Month(), date.Year())
|
|
|
|
cacheKey := cacheKeyType{CurrencyId: currencyId, Date: reqDate}
|
|
|
|
cacheResult, exists := cache[cacheKey]
|
|
|
|
if !exists {
|
|
|
|
url := fmt.Sprintf(urlTemplate, reqDate)
|
|
|
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
|
if err != nil {
|
|
return models.VunitRate{}, err
|
|
}
|
|
|
|
req.Header.Add("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
|
|
req.Header.Add("accept-encoding", "gzip, deflate, br")
|
|
req.Header.Add("accept-language", "en-US,en;q=0.9,ru;q=0.8")
|
|
req.Header.Add("cache-control", "max-age=0")
|
|
req.Header.Add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36")
|
|
|
|
client := &http.Client{}
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return models.VunitRate{Currency: currencyId, Rate: 0}, err
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
var reader io.ReadCloser
|
|
|
|
switch resp.Header.Get("Content-Encoding") {
|
|
case "gzip":
|
|
reader, err = gzip.NewReader(resp.Body)
|
|
if err != nil {
|
|
return models.VunitRate{Currency: currencyId, Rate: 0}, err
|
|
}
|
|
defer reader.Close()
|
|
default:
|
|
reader = resp.Body
|
|
}
|
|
|
|
xml := xml.NewDecoder(reader)
|
|
|
|
xml.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
|
|
switch charset {
|
|
case "windows-1251":
|
|
return charmap.Windows1251.NewDecoder().Reader(input), nil
|
|
default:
|
|
return nil, fmt.Errorf("unknown charset: %s", charset)
|
|
}
|
|
}
|
|
|
|
result := &resultType{}
|
|
|
|
err = xml.Decode(result)
|
|
if err != nil {
|
|
return models.VunitRate{Currency: currencyId, Rate: 0}, err
|
|
}
|
|
|
|
for _, resultRow := range result.Valute {
|
|
|
|
if resultRow.CharCode != currencyId {
|
|
continue
|
|
}
|
|
|
|
resultRow.Value = strings.Replace(resultRow.Value, ",", ".", 1)
|
|
|
|
rate, err := strconv.ParseFloat(resultRow.Value, 64)
|
|
if err != nil {
|
|
return models.VunitRate{Currency: currencyId, Rate: 0}, err
|
|
}
|
|
|
|
nominal, err := strconv.ParseInt(resultRow.Nominal, 10, 64)
|
|
if err != nil {
|
|
return models.VunitRate{Currency: currencyId, Rate: 0}, err
|
|
}
|
|
|
|
cacheResult = &cacheResultType{Rate: rate / float64(nominal)}
|
|
|
|
cache[cacheKey] = cacheResult
|
|
|
|
}
|
|
|
|
}
|
|
return models.VunitRate{Currency: currencyId, Rate: float32(cacheResult.Rate)}, nil
|
|
|
|
}
|
|
|
|
//func Convert(from string, to string, value float64, date time.Time) (float64, error) {
|
|
//
|
|
// if from == to {
|
|
// return value, nil
|
|
// }
|
|
//
|
|
// if value == 0 {
|
|
// return 0, nil
|
|
// }
|
|
//
|
|
// result := value
|
|
//
|
|
// if from != CurrencyRUB {
|
|
//
|
|
// exchangeRate, err := GetExchangeRate(from, date)
|
|
// if err != nil {
|
|
// return 0, err
|
|
// }
|
|
//
|
|
// result = result * exchangeRate
|
|
//
|
|
// }
|
|
//
|
|
// if to != CurrencyRUB {
|
|
//
|
|
// exchangeRate, err := GetExchangeRate(to, date)
|
|
// if err != nil {
|
|
// return 0, err
|
|
// }
|
|
//
|
|
// result = result / exchangeRate
|
|
//
|
|
// }
|
|
//
|
|
// return (math.Floor(result*100) / 100), nil
|
|
//
|
|
//}
|
|
//
|
|
//func main() {
|
|
// fmt.Println(GetExchangeRate(CurrencyUSD, time.Now()))
|
|
//}
|