discordBots/cmd/dealsbot/humblebundle.go
2023-03-06 19:02:40 +01:00

147 lines
3.3 KiB
Go

package main
import (
"encoding/json"
"fmt"
"golang.org/x/net/html"
"net/http"
"regexp"
)
type HumbleBundleStruct struct {
url string
baseUrl string
idPrefix string
headers map[string]string
deals DealsMap
}
func newHumbleBundleApi() HumbleBundleStruct {
humbleBundle := HumbleBundleStruct{
url: "https://www.humblebundle.com/",
baseUrl: "https://www.humblebundle.com/store/",
idPrefix: "humblebundle-",
headers: make(map[string]string),
deals: make(map[string]Deal),
}
humbleBundle.headers["Accept-Language"] = "en"
humbleBundle.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0"
return humbleBundle
}
type humblebundleJsonBody struct {
Mosaic []struct {
Products []struct {
ProductUrl string `json:"product_url,omitempty"`
Highlights []string `json:"highlights,omitempty"`
TileName string `json:"tile_name,omitempty"`
ProductTitle *string `json:"product_title,omitempty"`
Type string `json:"type"`
Category string `json:"category,omitempty"`
EndDateDatetime string `json:"end_date|datetime,omitempty"`
OperatingSystems []string `json:"operating_systems,omitempty"`
Platforms []string `json:"platforms,omitempty"`
} `json:"products"`
} `json:"mosaic"`
}
func (e HumbleBundleStruct) load() error {
client := &http.Client{}
// might have to add a cookie at a later time but currently works without
// "Cookie", "gog_lc=GB_GBP_en-US" or "Accept-Language", "en"
reqStore, err := http.NewRequest("GET", e.url, nil)
if err != nil {
return err
}
for key, value := range e.headers {
reqStore.Header.Set(key, value)
}
resStore, err := client.Do(reqStore)
if err != nil {
return err
}
bodyStore := html.NewTokenizer(resStore.Body)
var data humblebundleJsonBody
err = func() error {
for {
tt := bodyStore.Next()
switch {
case tt == html.ErrorToken:
// file end or error
return nil
case tt == html.StartTagToken:
t := bodyStore.Token()
if t.Data != "script" {
continue
}
for _, a := range t.Attr {
if !(a.Key == "id" && a.Val == "webpack-json-data") {
continue
}
if tt = bodyStore.Next(); tt != html.TextToken {
continue
}
err = json.Unmarshal([]byte(bodyStore.Token().Data), &data)
if err != nil {
return err
}
}
}
}
}()
if err != nil {
return err
}
regexAppid, err := regexp.Compile(`/store/([-\w]+)`)
if err != nil {
return err
}
for _, products := range data.Mosaic {
for _, product := range products.Products {
if !contains(product.Highlights, "FREE WHILE SUPPLIES LAST") {
continue
}
appID := regexAppid.FindStringSubmatch(product.ProductUrl)
if len(appID) < 1 {
continue
}
id := fmt.Sprintf("%v%v", e.idPrefix, appID[1])
title := product.TileName
url := fmt.Sprintf("%v%v", e.baseUrl, appID[1])
e.deals[id] = Deal{
Id: id,
Title: title,
Url: url,
}
}
}
return nil
}
func contains(s []string, str string) bool {
for _, v := range s {
if v == str {
return true
}
}
return false
}
func (e HumbleBundleStruct) get() []Deal {
var deals []Deal
for _, deal := range e.deals {
deals = append(deals, deal)
}
return deals
}