Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

World Names #269

Merged
merged 6 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 38 additions & 21 deletions backend/routes/indexer/worlds.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,33 @@ import (

func processCanvasCreatedEvent(event IndexerEvent) {
canvasIdHex := event.Event.Keys[1]
host := event.Event.Data[0][2:] // Remove 0x prefix
nameHex := event.Event.Data[1][2:] // Remove 0x prefix
widthHex := event.Event.Data[2]
heightHex := event.Event.Data[3]
timeBetweenPixelsHex := event.Event.Data[4]
colorPaletteLenHex := event.Event.Data[5]
host := event.Event.Data[0][2:] // Remove 0x prefix
nameHex := event.Event.Data[1][2:] // Remove 0x prefix
uniqueNameHex := event.Event.Data[2][2:] // Remove 0x prefix
widthHex := event.Event.Data[3]
heightHex := event.Event.Data[4]
timeBetweenPixelsHex := event.Event.Data[5]
colorPaletteLenHex := event.Event.Data[6]

colorPaletteLen, err := strconv.ParseInt(colorPaletteLenHex, 0, 64)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse colorPaletteLenHex", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse colorPaletteLenHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}
// Skip colors since they are processed in another event

startTimeHex := event.Event.Data[6+colorPaletteLen]
endTimeHex := event.Event.Data[7+colorPaletteLen]
startTimeHex := event.Event.Data[7+colorPaletteLen]
endTimeHex := event.Event.Data[8+colorPaletteLen]

canvasId, err := strconv.ParseInt(canvasIdHex, 0, 64)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse canvasIdHex", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse canvasIdHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}

decodedName, err := hex.DecodeString(nameHex)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to decode nameHex", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to decode nameHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}
trimmedName := []byte{}
Expand All @@ -55,40 +56,56 @@ func processCanvasCreatedEvent(event IndexerEvent) {
}
name := string(trimmedName)

decodedUniqueName, err := hex.DecodeString(uniqueNameHex)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to decode uniqueNameHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}
trimmedUniqueName := []byte{}
trimming = true
for _, b := range decodedUniqueName {
if b == 0 && trimming {
continue
}
trimming = false
trimmedUniqueName = append(trimmedUniqueName, b)
}
uniqueName := string(trimmedUniqueName)

width, err := strconv.ParseInt(widthHex, 0, 64)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse widthHex", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse widthHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}

height, err := strconv.ParseInt(heightHex, 0, 64)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse heightHex", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse heightHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}

timeBetweenPixels, err := strconv.ParseInt(timeBetweenPixelsHex, 0, 64)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse timeBetweenPixelsHex", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse timeBetweenPixelsHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}

startTime, err := strconv.ParseInt(startTimeHex, 0, 64)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse startTimeHex", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse startTimeHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}

endTime, err := strconv.ParseInt(endTimeHex, 0, 64)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse endTimeHex", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to parse endTimeHex", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}

// Insert into Worlds
_, err = core.ArtPeaceBackend.Databases.Postgres.Exec(context.Background(), "INSERT INTO Worlds (world_id, host, name, width, height, time_between_pixels, start_time, end_time) VALUES ($1, $2, $3, $4, $5, $6, TO_TIMESTAMP($7), TO_TIMESTAMP($8))", canvasId, host, name, width, height, timeBetweenPixels, startTime, endTime)
_, err = core.ArtPeaceBackend.Databases.Postgres.Exec(context.Background(), "INSERT INTO Worlds (world_id, host, name, unique_name, width, height, time_between_pixels, start_time, end_time) VALUES ($1, $2, $3, $4, $5, $6, $7, TO_TIMESTAMP($8), TO_TIMESTAMP($9))", canvasId, host, name, uniqueName, width, height, timeBetweenPixels, startTime, endTime)
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to insert into Worlds", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to insert into Worlds", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}

Expand All @@ -103,11 +120,11 @@ func processCanvasCreatedEvent(event IndexerEvent) {
canvas := make([]byte, totalByteSize)
err := core.ArtPeaceBackend.Databases.Redis.Set(context.Background(), canvasRedisKey, canvas, 0).Err()
if err != nil {
PrintIndexerError("processCanvasCreatedEvent", "Failed to set canvas in redis", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Failed to set canvas in redis", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
return
}
} else {
PrintIndexerError("processCanvasCreatedEvent", "Canvas already exists in redis", canvasIdHex, host, nameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
PrintIndexerError("processCanvasCreatedEvent", "Canvas already exists in redis", canvasIdHex, host, nameHex, uniqueNameHex, widthHex, heightHex, timeBetweenPixelsHex, colorPaletteLenHex, err)
}

// Create base directories if they don't exist
Expand All @@ -127,7 +144,7 @@ func processCanvasCreatedEvent(event IndexerEvent) {
}

generatedWorldImage := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
baseColorHex := event.Event.Data[6]
baseColorHex := event.Event.Data[7]
baseColor := baseColorHex[len(baseColorHex)-6:] // Remove prefix
baseColorR, err := strconv.ParseInt(baseColor[0:2], 16, 64)
if err != nil {
Expand Down
63 changes: 58 additions & 5 deletions backend/routes/worlds.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package routes

import (
"context"
"fmt"
"net/http"
"os"
"os/exec"
Expand All @@ -17,6 +16,7 @@ import (
// TODO: check-worlds-name-unique?
func InitWorldsRoutes() {
http.HandleFunc("/get-world-canvas", getWorldCanvas)
http.HandleFunc("/get-world-id", getWorldId)
http.HandleFunc("/get-world", getWorld)
http.HandleFunc("/get-worlds", getWorlds)
http.HandleFunc("/get-new-worlds", getNewWorlds)
Expand All @@ -29,6 +29,7 @@ func InitWorldsRoutes() {
http.HandleFunc("/get-worlds-colors", getWorldsColors)
http.HandleFunc("/get-worlds-pixel-count", getWorldsPixelCount)
http.HandleFunc("/get-worlds-pixel-info", getWorldsPixelInfo)
http.HandleFunc("/check-world-name", checkWorldName)
if !core.ArtPeaceBackend.BackendConfig.Production {
http.HandleFunc("/create-canvas-devnet", createCanvasDevnet)
http.HandleFunc("/favorite-world-devnet", favoriteWorldDevnet)
Expand Down Expand Up @@ -66,6 +67,7 @@ type WorldData struct {
WorldId int `json:"worldId"`
Host string `json:"host"`
Name string `json:"name"`
UniqueName string `json:"uniqueName"`
Width int `json:"width"`
Height int `json:"height"`
TimeBetweenPixels int `json:"timeBetweenPixels"`
Expand All @@ -75,6 +77,20 @@ type WorldData struct {
Favorited bool `json:"favorited"`
}

func getWorldId(w http.ResponseWriter, r *http.Request) {
worldName := r.URL.Query().Get("worldName")
if worldName == "" {
routeutils.WriteErrorJson(w, http.StatusBadRequest, "Missing worldName")
return
}
worldId, err := core.PostgresQueryOne[int]("SELECT world_id FROM worlds WHERE unique_name = $1", worldName)
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to retrieve World")
return
}
routeutils.WriteDataJson(w, strconv.Itoa(*worldId))
}

func getWorld(w http.ResponseWriter, r *http.Request) {
worldId := r.URL.Query().Get("worldId")
if worldId == "" {
Expand Down Expand Up @@ -173,7 +189,6 @@ func getNewWorlds(w http.ResponseWriter, r *http.Request) {
LIMIT $2 OFFSET $3`
worlds, err := core.PostgresQueryJson[WorldData](query, address, pageLength, offset)
if err != nil {
fmt.Println(err)
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to retrieve Worlds")
return
}
Expand Down Expand Up @@ -459,9 +474,21 @@ func createCanvasDevnet(w http.ResponseWriter, r *http.Request) {

host := (*jsonBody)["host"]
name := (*jsonBody)["name"]
uniqueName := (*jsonBody)["unique_name"]

if host == "" || name == "" || uniqueName == "" {
routeutils.WriteErrorJson(w, http.StatusBadRequest, "Missing host or name or uniqueName")
return
}

if host == "" || name == "" {
routeutils.WriteErrorJson(w, http.StatusBadRequest, "Missing host or name")
// Check if world name already exists
exists, err := core.PostgresQueryOne[bool]("SELECT EXISTS(SELECT 1 FROM worlds WHERE unique_name = $1)", uniqueName)
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "World unique name check failed")
return
}
if *exists {
routeutils.WriteErrorJson(w, http.StatusBadRequest, "World name already exists")
return
}

Expand Down Expand Up @@ -512,7 +539,7 @@ func createCanvasDevnet(w http.ResponseWriter, r *http.Request) {
shellCmd := core.ArtPeaceBackend.BackendConfig.Scripts.CreateCanvasDevnet
contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS")

cmd := exec.Command(shellCmd, contract, "create_canvas", host, name, strconv.Itoa(width), strconv.Itoa(height), strconv.Itoa(timer), strconv.Itoa(len(palette)), paletteInput, strconv.Itoa(startTime), strconv.Itoa(endTime))
cmd := exec.Command(shellCmd, contract, "create_canvas", host, name, uniqueName, strconv.Itoa(width), strconv.Itoa(height), strconv.Itoa(timer), strconv.Itoa(len(palette)), paletteInput, strconv.Itoa(startTime), strconv.Itoa(endTime))
_, err = cmd.Output()
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to create canvas")
Expand Down Expand Up @@ -637,3 +664,29 @@ func placeWorldPixelDevnet(w http.ResponseWriter, r *http.Request) {

routeutils.WriteResultJson(w, "Pixel placed world")
}

func checkWorldName(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("uniqueName")
if name == "" {
routeutils.WriteErrorJson(w, http.StatusBadRequest, "Missing uniqueName parameter")
return
}

// Use the helper function
exists, err := doesWorldNameExist(name)
if err != nil {
routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to check world name")
return
}

routeutils.WriteDataJson(w, strconv.FormatBool(exists))
}

// Add a helper function to check if a world name exists
func doesWorldNameExist(name string) (bool, error) {
exists, err := core.PostgresQueryOne[bool]("SELECT EXISTS(SELECT 1 FROM worlds WHERE unique_name = $1)", name)
if err != nil {
return false, err
}
return *exists, nil
}
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ services:
- REACT_APP_ROUND_NUMBER=2
volumes:
- ./frontend/package.json:/app/package.json
- ./frontend/package-lock.json:/app/package-lock.json
- ./frontend/pnpm-lock.yaml:/app/pnpm-lock.yaml
- ./frontend/public/:/app/public
- ./frontend/src:/app/src
- configs:/app/src/configs
Expand Down
Loading
Loading