github.com/diadata-org/diadata@v1.4.593/internal/pkg/ratescrapers/updateESTER.go (about)

     1  package ratescrapers
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/xml"
     6  	"fmt"
     7  	"os"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	models "github.com/diadata-org/diadata/pkg/model"
    13  	utils "github.com/diadata-org/diadata/pkg/utils"
    14  	log "github.com/sirupsen/logrus"
    15  )
    16  
    17  type (
    18  
    19  	// Define the fields associated with the rss document.
    20  	RssESTER struct {
    21  		Header  Header  `xml:"header"`
    22  		RssBody RssBody `xml:"body"`
    23  	}
    24  	Header struct {
    25  		ReleaseTitle string `xml:"releaseTitle"`
    26  		ReleaseTime  string `xml:"releaseDateTime"`
    27  	}
    28  	RssBody struct {
    29  		Content Content `xml:"content"`
    30  	}
    31  	Content struct {
    32  		EstrData EstrData `xml:"EURO-SHORT-TERM-RATE_MID_PUBLICATION_MESSAGE"`
    33  	}
    34  	EstrData struct {
    35  		Results Results `xml:"CALCULATION_RESULTS"`
    36  	}
    37  
    38  	Results struct {
    39  		RefDate string `xml:"REF_DATE"`
    40  		Rate    string `xml:"RATE"`
    41  	}
    42  )
    43  
    44  func getRSS() (pubDate string, link string, err error) {
    45  	// Scrapes the actual rss feed address for the ESTER index
    46  
    47  	// First define the structure for decoding the xml
    48  	type (
    49  		// Define the fields associated with the rss document.
    50  		Item struct {
    51  			Title string `xml:"title"`
    52  			Link  string `xml:"link"`
    53  		}
    54  		Channel struct {
    55  			Title   string `xml:"title"`
    56  			Link    string `xml:"link"`
    57  			PubDate string `xml:"pubDate"`
    58  			Item    []Item `xml:"item"`
    59  		}
    60  		RssMain struct {
    61  			Channel Channel `xml:"channel"`
    62  		}
    63  	)
    64  
    65  	XMLdata, _, err := utils.GetRequest("http://mid.ecb.europa.eu/rss/mid.xml")
    66  	if err != nil {
    67  		return "", "", err
    68  	}
    69  
    70  	// Decode the body
    71  	rss := new(RssMain)
    72  	buffer := bytes.NewBuffer(XMLdata)
    73  	decoded := xml.NewDecoder(buffer)
    74  	err = decoded.Decode(rss)
    75  
    76  	if err != nil {
    77  		fmt.Println(err)
    78  		os.Exit(1)
    79  	}
    80  
    81  	// Determine the item containing the link to the ESTER feed
    82  	for _, item := range rss.Channel.Item {
    83  		if strings.Contains(item.Title, "EURO-SHORT-TERM-RATE") {
    84  			pubDate = rss.Channel.PubDate
    85  			link = item.Link
    86  			return
    87  		}
    88  	}
    89  	return "", "", err
    90  }
    91  
    92  // UpdateESTER makes a GET request from an rss feed and sends updated value through
    93  // Channel s.chanInterestRate
    94  func (s *RateScraper) UpdateESTER() error {
    95  	log.Printf("ESTERScraper update")
    96  
    97  	// Get link to ESTER publication feed and publication time
    98  	pubTime, address, err := getRSS()
    99  
   100  	if err != nil {
   101  		fmt.Println(err)
   102  		os.Exit(1)
   103  	}
   104  	if address == "" {
   105  		log.Info("ESTER is not published right now. Please wait.")
   106  		return nil
   107  	}
   108  
   109  	// Get response from ESTER feed
   110  	XMLdata, _, err := utils.GetRequest(address)
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	// Decode the body
   116  	rss := new(RssESTER)
   117  	buffer := bytes.NewBuffer(XMLdata)
   118  	decoded := xml.NewDecoder(buffer)
   119  	err = decoded.Decode(rss)
   120  
   121  	if err != nil {
   122  		fmt.Println(err)
   123  		os.Exit(1)
   124  	}
   125  
   126  	// Collect entries of InterestRate struct -----------------------------------
   127  
   128  	// Convert interest rate from string to float64
   129  	rate, err := strconv.ParseFloat(rss.RssBody.Content.EstrData.Results.Rate, 64)
   130  	if err != nil {
   131  		fmt.Println(err)
   132  	}
   133  
   134  	// Convert publication time and effective date from string to Time type in UTC
   135  	loc, _ := time.LoadLocation("CET") // Time is given as CET time
   136  	publicationTime, err := time.ParseInLocation("2006/01/02 15:04:05", pubTime, loc)
   137  	if err != nil {
   138  		fmt.Println(err)
   139  	} else {
   140  		publicationTime = publicationTime.UTC()
   141  	}
   142  	effDate, err := time.Parse("2006-01-02", rss.RssBody.Content.EstrData.Results.RefDate)
   143  	if err != nil {
   144  		fmt.Println(err)
   145  	}
   146  
   147  	t := &models.InterestRate{
   148  		Symbol:          "ESTER",
   149  		Value:           rate,
   150  		PublicationTime: publicationTime,
   151  		EffectiveDate:   effDate,
   152  		Source:          "ECB",
   153  	}
   154  
   155  	// Send new data through channel chanInterestRate
   156  	log.Printf("writing interestRate %#v in %v\n", t, s.chanInterestRate)
   157  	s.chanInterestRate <- t
   158  
   159  	log.Info("Update complete")
   160  
   161  	return err
   162  }