Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Napolitain committed May 15, 2024
1 parent 8f12054 commit 83e0c76
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 15 deletions.
22 changes: 18 additions & 4 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ func getFromCache(ctx context.Context, game string) (*memcache.Item, error) {
// saveToCachePlayer function is used to saveToCache data on Memcached server. It is used to saveToCache data for a specific player for a specific game.
// The whole entry is a iCalendar string, ready to be sent to the user as a response directly.
// Super fast, very useful for reducing the load if the same player is queried multiple times (for example a superstar player).
func saveToCachePlayer(ctx context.Context, data string, game string, player string) error {
func saveToCachePlayer(ctx context.Context, data string, queries string) error {
item := &memcache.Item{
Key: game + "/" + player,
Key: queries,
Value: []byte(data),

This comment has been minimized.

Copy link
@Napolitain

Napolitain May 15, 2024

Author Owner

reasoning: no need to cache the decoded hexadecimal, but directly the querystring

Expiration: time.Hour * 1,
}
Expand All @@ -40,6 +40,20 @@ func saveToCachePlayer(ctx context.Context, data string, game string, player str

// getFromCachePlayer function is used to retrieve data from Memcached server. It returns iCalendar string ready to be sent to the user as a response directly.
// Super fast, very useful for reducing the load if the same player is queried multiple times (for example a superstar player).
func getFromCachePlayer(ctx context.Context, game string, player string) (*memcache.Item, error) {
return memcache.Get(ctx, game+"/"+player)
func getFromCachePlayer(ctx context.Context, queries string) (*memcache.Item, error) {
return memcache.Get(ctx, queries)
}

// getGamesFromCache function is used to retrieve the enabled games from cache
func getGamesFromCache(ctx context.Context) (*memcache.Item, error) {
return memcache.Get(ctx, "!games")
}

// saveGamesToCache function is used to save the enabled games to cache
func saveGamesToCache(ctx context.Context, data string) error {
item := &memcache.Item{
Key: "!games",
Value: []byte(data),
}
return memcache.Set(ctx, item)
}
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
module github.com/Napolitain/liquipedia_calendar

go 1.22
go 1.22.0

require google.golang.org/appengine v1.6.8

require (
cloud.google.com/go/logging v1.9.0
github.com/PuerkitoBio/goquery v1.9.2
github.com/arran4/golang-ical v0.2.8
k8s.io/apimachinery v0.30.0
)

require (
Expand All @@ -17,7 +18,7 @@ require (
cloud.google.com/go/longrunning v0.5.2 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
Expand Down
9 changes: 6 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
Expand Down Expand Up @@ -76,8 +76,9 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
Expand Down Expand Up @@ -192,3 +193,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
50 changes: 45 additions & 5 deletions liquipedia-calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import (
"context"
"fmt"
"github.com/PuerkitoBio/goquery"
"k8s.io/apimachinery/pkg/util/sets"
_ "k8s.io/apimachinery/pkg/util/sets"
"log"
"net/http"
"os"
"strings"
)

var logger *log.Logger = log.New(os.Stdout, "", 0)
Expand Down Expand Up @@ -42,6 +45,13 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
return
}

// Get from cache the queries calendar if cached. (Superstar player case).
calendar, err := getFromCachePlayer(r.Context(), r.URL.Query().Get("query"))
if err == nil {
sendCalendar(w, err, string(calendar.Value))
return
}

// Get query string's name from querystring.
querystring := r.URL.Query().Get("query")
if querystring == "" {
Expand All @@ -58,10 +68,9 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
return
}

// Get from cache the game+player calendar if cached. (Superstar player case).
calendar, err := getFromCachePlayer(r.Context(), queries.data[0].game, queries.data[0].players[0])
if err == nil {
sendCalendar(w, err, string(calendar.Value))
// If the game inside query is not valid, return bad request.
if !isValidGame(r.Context(), queries.data[0].game) {
http.Error(w, "Bad request", http.StatusBadRequest)
return

This comment has been minimized.

Copy link
@Napolitain

Napolitain May 15, 2024

Author Owner

check first whether the game is valid from Liquipedia list of wikis

}

Expand Down Expand Up @@ -92,10 +101,41 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
serializedCalendar := cal.Serialize()

// If it is for a single player, save to cache the game+player calendar (superstar player case).
err = saveToCachePlayer(r.Context(), serializedCalendar, queries.data[0].game, queries.data[0].players[0])
err = saveToCachePlayer(r.Context(), serializedCalendar, r.URL.Query().Get("query"))
sendCalendar(w, err, serializedCalendar)
}

// TODO: do the function, test and move to other file.
func isValidGame(ctx context.Context, game string) bool {
// List of games supported by Liquipedia API : important to avoid not only errors, but attacks.
// Retrieve from the cache first.
item, err := getGamesFromCache(ctx)
// Cache result
if err == nil {
// Convert string to sets.String
gamesMap := sets.NewString()
// Deserialize string1,string2 to []string then to Map
gamesMap.Insert(strings.Split(string(item.Value), ",")...)
// Check if the game is in the map, return true if it is.
return gamesMap.Has(game)
}
// Cache miss, log the issue, but continue.
logger.Println(err)
// Otherwise, from the DB.
// Otherwise, from the API.
gamesMap, err := fetchGames()
if err != nil {
logger.Println(err)
return false
}
// Save to cache
// Serialize Map to []string, then to string1,string2
gamesList := gamesMap.List()
games := strings.Join(gamesList, ",")
err = saveGamesToCache(ctx, games)
return gamesMap.Has(game)
}

// sendCalendar function is used to send the calendar to the user.
// It sends the calendar in iCalendar format.
func sendCalendar(w http.ResponseWriter, err error, serializedCalendar string) {
Expand Down
Loading

0 comments on commit 83e0c76

Please sign in to comment.