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 }