discordBots/cmd/dealsbot/humblebundle.go

138 lines
2.9 KiB
Go
Raw Normal View History

2023-03-04 11:54:08 +00:00
package main
import (
"encoding/json"
"fmt"
"golang.org/x/net/html"
"net/http"
"regexp"
)
type HumbleBundleStruct struct {
url string
baseUrl string
idPrefix string
deals DealsMap
}
func newHumbleBundleApi() HumbleBundleStruct {
return HumbleBundleStruct{
url: "https://www.humblebundle.com/",
baseUrl: "https://www.humblebundle.com/store/",
idPrefix: "humblebundle-",
deals: make(map[string]Deal),
}
}
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
}
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
}