Files
torrent-indexer/api/b3/prices/[ticker].go

144 lines
3.7 KiB
Go

package quotation
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
log "github.com/sirupsen/logrus"
)
type RawResponse struct {
BizSts struct {
Cd string `json:"cd"`
} `json:"BizSts"`
Msg struct {
DtTm string `json:"dtTm"`
} `json:"Msg"`
Trad []struct {
Scty struct {
SctyQtn struct {
OpngPric float64 `json:"opngPric"`
MinPric float64 `json:"minPric"`
MaxPric float64 `json:"maxPric"`
AvrgPric float64 `json:"avrgPric"`
CurPrc float64 `json:"curPrc"`
PrcFlcn float64 `json:"prcFlcn"`
} `json:"SctyQtn"`
Mkt struct {
Nm string `json:"nm"`
} `json:"mkt"`
Symb string `json:"symb"`
Desc string `json:"desc"`
IndxCmpnInd bool `json:"indxCmpnInd"`
} `json:"scty"`
TTLQty int `json:"ttlQty"`
} `json:"Trad"`
}
type Response struct {
Symbol string `json:"symbol"`
Name string `json:"name"`
Market string `json:"market"`
OpeningPrice float64 `json:"openingPrice"`
MinPrice float64 `json:"minPrice"`
MaxPrice float64 `json:"maxPrice"`
AveragePrice float64 `json:"averagePrice"`
CurrentPrice float64 `json:"currentPrice"`
PriceVariation float64 `json:"priceVariation"`
IndexComponentIndicator bool `json:"indexComponentIndicator"`
}
type RawErrorResponse struct {
BizSts struct {
Cd string `json:"cd"`
Desc string `json:"desc"`
} `json:"BizSts"`
Msg struct {
DtTm string `json:"dtTm"`
} `json:"Msg"`
}
type Error struct {
Message string `json:"message"`
}
func HandlerListCompanies(w http.ResponseWriter, r *http.Request) {
ticker := strings.Split(r.URL.Path, "/")[4]
log.Info("Getting quotation info for ticker: " + ticker)
if ticker == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Ticker is required"))
return
}
client := http.Client{}
res, err := client.Get(fmt.Sprintf("https://cotacao.b3.com.br/mds/api/v1/instrumentQuotation/%s", ticker))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
defer res.Body.Close()
w.Header().Set("Content-Type", "application/json")
// add 1min cache header
w.Header().Set("Cache-Control", "max-age=60, public")
out, err := ioutil.ReadAll(res.Body)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
var raw RawResponse
err = json.Unmarshal(out, &raw)
if err != nil || raw.BizSts.Cd != "OK" {
var errorResponse RawErrorResponse
err = json.Unmarshal(out, &errorResponse)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
// 404
w.WriteHeader(http.StatusNotFound)
formatedError := Error{Message: errorResponse.BizSts.Desc}
err := json.NewEncoder(w).Encode(formatedError)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
return
}
var response []Response
for _, trad := range raw.Trad {
response = append(response, Response{
Symbol: trad.Scty.Symb,
Name: trad.Scty.Desc,
Market: trad.Scty.Mkt.Nm,
OpeningPrice: trad.Scty.SctyQtn.OpngPric,
MinPrice: trad.Scty.SctyQtn.MinPric,
MaxPrice: trad.Scty.SctyQtn.MaxPric,
AveragePrice: trad.Scty.SctyQtn.AvrgPric,
CurrentPrice: trad.Scty.SctyQtn.CurPrc,
PriceVariation: trad.Scty.SctyQtn.PrcFlcn,
IndexComponentIndicator: trad.Scty.IndxCmpnInd,
})
}
err = json.NewEncoder(w).Encode(response[0])
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
return
}