package api import ( "encoding/json" "errors" "fmt" "io" "log/slog" "net/http" "regexp" "strings" ) type UbisoftStruct struct { url string idPrefix string headers map[string]string deals DealsMap logger *slog.Logger } func NewUbsioftApi(logger *slog.Logger) UbisoftStruct { ubisoft := UbisoftStruct{ url: "https://free.ubisoft.com/configuration.js", idPrefix: "ubisoft-", headers: make(map[string]string), deals: make(map[string]Deal), logger: logger, } ubisoft.headers["referer"] = "https://free.ubisoft.com/" ubisoft.headers["origin"] = "https://free.ubisoft.com" ubisoft.headers["ubi-localecode"] = "en-US" ubisoft.headers["Accept-Language"] = "en" ubisoft.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0" return ubisoft } type ubisoftApiBody struct { News []struct { Type string `json:"type"` Title string `json:"title"` Links []struct { Param string `json:"param"` } `json:"links"` } `json:"news"` } func (e UbisoftStruct) Load() error { appId, prodUrl, err := func() (string, string, error) { client := &http.Client{} req, err := http.NewRequest("GET", e.url, nil) if err != nil { return "", "", err } for key, value := range e.headers { req.Header.Set(key, value) } res, err := client.Do(req) if err != nil { return "", "", err } body, err := io.ReadAll(res.Body) regexAppId, err := regexp.Compile(`appId:\s*'(.+)'`) if err != nil { return "", "", err } regexProd, err := regexp.Compile(`prod:\s*'(.+)'`) if err != nil { return "", "", err } appId := regexAppId.FindSubmatch(body) prodUrl := regexProd.FindSubmatch(body) if len(appId) < 1 || len(prodUrl) < 1 { return "", "", errors.New("appid or prod url not found") } return string(appId[1]), string(prodUrl[1]), nil }() if err != nil { return err } client := &http.Client{} req, err := http.NewRequest("GET", prodUrl, nil) if err != nil { return err } for key, value := range e.headers { req.Header.Set(key, value) } req.Header.Set("ubi-appid", appId) res, err := client.Do(req) if err != nil { return err } body, err := io.ReadAll(res.Body) var data ubisoftApiBody err = json.Unmarshal(body, &data) if err != nil { return err } for _, news := range data.News { if news.Type != "freegame" { continue } title := strings.TrimSpace(news.Title) if len(news.Links) != 1 { return errors.New(fmt.Sprintf("lenght of links for %v is more or less then 1", news.Title)) } regexName, err := regexp.Compile(`https://register.ubisoft.com/([^/]*)/?`) idFromUrl := regexName.FindStringSubmatch(news.Links[0].Param) if err != nil { return err } if len(idFromUrl) < 1 { return errors.New("could not parse url") } id := fmt.Sprintf("%v%v", e.idPrefix, idFromUrl[1]) url := news.Links[0].Param e.deals[id] = Deal{ Id: id, Title: title, Url: url, } } return nil } func (e UbisoftStruct) Get() []Deal { var deals []Deal for _, deal := range e.deals { deals = append(deals, deal) } return deals }