From dbb2522295a679354e2b986d3ea4a06b2ee10f88 Mon Sep 17 00:00:00 2001 From: MobilettoSoft Date: Mon, 30 Dec 2024 12:08:23 +0100 Subject: [PATCH] PUN: fix api (#17900) --- tariff/pun.go | 125 +++++++++++++++++++++----------------------------- 1 file changed, 52 insertions(+), 73 deletions(-) diff --git a/tariff/pun.go b/tariff/pun.go index f9fc1428b..58cb84486 100644 --- a/tariff/pun.go +++ b/tariff/pun.go @@ -1,11 +1,12 @@ package tariff import ( + "archive/zip" + "bytes" "encoding/xml" "fmt" - "io" + "net/http" "net/http/cookiejar" - "net/url" "slices" "strconv" "strings" @@ -16,7 +17,6 @@ import ( "github.com/evcc-io/evcc/api" "github.com/evcc-io/evcc/util" "github.com/evcc-io/evcc/util/request" - "golang.org/x/net/html" ) type Pun struct { @@ -76,20 +76,18 @@ func (t *Pun) run(done chan error) { var once sync.Once for tick := time.Tick(time.Hour); ; <-tick { - var today api.Rates - if err := backoff.Retry(func() error { - var err error - - today, err = t.getData(time.Now()) - - return err - }, bo()); err != nil { + // get today data + today, err := backoff.RetryWithData(func() (api.Rates, error) { + res, err := t.getData(time.Now()) + return res, backoffPermanentError(err) + }, bo()) + if err != nil { once.Do(func() { done <- err }) - t.log.ERROR.Println(err) continue } + // get tomorrow data res, err := backoff.RetryWithData(func() (api.Rates, error) { res, err := t.getData(time.Now().AddDate(0, 0, 1)) return res, backoffPermanentError(err) @@ -123,48 +121,54 @@ func (t *Pun) Type() api.TariffType { } func (t *Pun) getData(day time.Time) (api.Rates, error) { - // Cookie Jar zur Speicherung von Cookies zwischen den Requests client := request.NewClient(t.log) client.Jar, _ = cookiejar.New(nil) - // Erster Request - uri := "https://storico.mercatoelettrico.org/It/WebServerDataStore/MGP_Prezzi/" + day.Format("20060102") + "MGPPrezzi.xml" - resp, err := client.Get(uri) + // Request the ZIP file + uri := "https://gme.mercatoelettrico.org/DesktopModules/GmeDownload/API/ExcelDownload/downloadzipfile?DataInizio=" + day.Format("20060102") + "&DataFine=" + day.Format("20060102") + "&Date=" + day.Format("20060102") + "&Mercato=MGP&Settore=Prezzi&FiltroDate=InizioFine" + req, _ := http.NewRequest("GET", uri, nil) + req.Header = http.Header{ + "Referer": {"https://gme.mercatoelettrico.org/en-us/Home/Results/Electricity/MGP/Download?valore=Prezzi"}, + "moduleid": {"12103"}, + "sec-ch-ua-mobile": {"?0"}, + "sec-ch-ua-platform": {"Windows"}, + "sec-fetch-dest": {"empty"}, + "sec-fetch-mode": {"cors"}, + "sec-fetch-site": {"same-origin"}, + "sec-gpc": {"1"}, + "tabid": {"1749"}, + "userid": {"-1"}, + } + + resp, err := client.Do(req) + if err != nil || resp.StatusCode == http.StatusNotFound { + return nil, err + } + + body, err := request.ReadBody(resp) if err != nil { return nil, err } - defer resp.Body.Close() - formData, err := parseFormFields(resp.Body) - if err != nil { - return nil, fmt.Errorf("form fields: %w", err) - } - - redirectURL := resp.Request.URL.String() - - // Hinzufügen der spezifizierten Parameter - formData.Set("ctl00$ContentPlaceHolder1$CBAccetto1", "on") - formData.Set("ctl00$ContentPlaceHolder1$CBAccetto2", "on") - formData.Set("ctl00$ContentPlaceHolder1$Button1", "Accetto") - - // Formular senden - resp, err = client.PostForm(redirectURL, formData) - if err != nil { - fmt.Println("Error submitting form:", err) - return nil, err - } - defer resp.Body.Close() - - // Erneuter Request auf die ursprüngliche URL - resp, err = client.Get(uri) + zipReader, err := zip.NewReader(bytes.NewReader(body), int64(len(body))) if err != nil { return nil, err } - defer resp.Body.Close() - // Verarbeitung der erhaltenen Daten + if len(zipReader.File) != 1 { + return nil, fmt.Errorf("unexpected number of files in the ZIP archive") + } + + zipFile := zipReader.File[0] + f, err := zipFile.Open() + if err != nil { + return nil, err + } + defer f.Close() + + // Process the received data var dataSet NewDataSet - if err := xml.NewDecoder(resp.Body).Decode(&dataSet); err != nil { + if err := xml.NewDecoder(f).Decode(&dataSet); err != nil { return nil, err } @@ -181,6 +185,12 @@ func (t *Pun) getData(day time.Time) (api.Rates, error) { return nil, fmt.Errorf("parse hour: %w", err) } + // Adjust hour to handle edge case where p.Ora is "00" + if hour == 0 { + hour = 24 + date = date.AddDate(0, 0, -1) + } + location, err := time.LoadLocation("Europe/Rome") if err != nil { return nil, fmt.Errorf("load location: %w", err) @@ -203,34 +213,3 @@ func (t *Pun) getData(day time.Time) (api.Rates, error) { data.Sort() return data, nil } - -func parseFormFields(body io.Reader) (url.Values, error) { - data := url.Values{} - doc, err := html.Parse(body) - if err != nil { - return data, err - } - var f func(*html.Node) - f = func(n *html.Node) { - if n.Type == html.ElementNode && n.Data == "input" { - var inputType, inputName, inputValue string - for _, a := range n.Attr { - if a.Key == "type" { - inputType = a.Val - } else if a.Key == "name" { - inputName = a.Val - } else if a.Key == "value" { - inputValue = a.Val - } - } - if inputType == "hidden" && inputName != "" { - data.Set(inputName, inputValue) - } - } - for c := n.FirstChild; c != nil; c = c.NextSibling { - f(c) - } - } - f(doc) - return data, nil -}