From 231ebad4785345ea5175a3b8f7071625135e103e Mon Sep 17 00:00:00 2001
From: man90 <man90@tuta.io>
Date: Tue, 26 May 2026 19:23:56 +0200
Subject: [PATCH] Implement regional guild name standards

---
 handlers/getGuild.go                          | 12 ++++-----
 handlers/getGuildSearch.go                    | 12 ++++-----
 handlers/getStatus.go                         |  2 +-
 validators/ValidateGuildNameQueryParam.go     | 14 +++++++---
 .../ValidateGuildNameQueryParam_test.go       | 27 ++++++++++---------
 5 files changed, 38 insertions(+), 29 deletions(-)

diff --git a/handlers/getGuild.go b/handlers/getGuild.go
index a969d0a..bbcaedb 100644
--- a/handlers/getGuild.go
+++ b/handlers/getGuild.go
@@ -12,18 +12,18 @@ import (
 )
 
 func getGuild(w http.ResponseWriter, r *http.Request) {
-	name, nameOk, nameValidationMessage := validators.ValidateGuildNameQueryParam(r.URL.Query()["guildName"])
-	if !nameOk {
-		giveBadRequestResponse(w, nameValidationMessage)
-		return
-	}
-
 	region, regionOk, regionValidationMessage := validators.ValidateRegionQueryParam(r.URL.Query()["region"])
 	if !regionOk {
 		giveBadRequestResponse(w, regionValidationMessage)
 		return
 	}
 
+	name, nameOk, nameValidationMessage := validators.ValidateGuildNameQueryParam(r.URL.Query()["guildName"], region)
+	if !nameOk {
+		giveBadRequestResponse(w, nameValidationMessage)
+		return
+	}
+
 	bypassCache := validators.ValidateBypassCacheQueryParam(r.URL.Query()["bypassCache"])
 	if !bypassCache || !utils.CheckAdminToken(r) {
 		if data, status, date, expires, ok := cache.GuildProfiles.GetRecord([]string{region, name}); !bypassCache && ok {
diff --git a/handlers/getGuildSearch.go b/handlers/getGuildSearch.go
index 935a3e3..e0f6d76 100644
--- a/handlers/getGuildSearch.go
+++ b/handlers/getGuildSearch.go
@@ -12,18 +12,18 @@ import (
 )
 
 func getGuildSearch(w http.ResponseWriter, r *http.Request) {
-	name, nameOk, nameValidationMessage := validators.ValidateGuildNameQueryParam(r.URL.Query()["query"])
-	if !nameOk {
-		giveBadRequestResponse(w, nameValidationMessage)
-		return
-	}
-
 	region, regionOk, regionValidationMessage := validators.ValidateRegionQueryParam(r.URL.Query()["region"])
 	if !regionOk {
 		giveBadRequestResponse(w, regionValidationMessage)
 		return
 	}
 
+	name, nameOk, nameValidationMessage := validators.ValidateGuildNameQueryParam(r.URL.Query()["query"], region)
+	if !nameOk {
+		giveBadRequestResponse(w, nameValidationMessage)
+		return
+	}
+
 	bypassCache := validators.ValidateBypassCacheQueryParam(r.URL.Query()["bypassCache"])
 	if !bypassCache || !utils.CheckAdminToken(r) {
 		if data, status, date, expires, ok := cache.GuildSearch.GetRecord([]string{region, name}); !bypassCache && ok {
diff --git a/handlers/getStatus.go b/handlers/getStatus.go
index fd5280c..bfc4d43 100644
--- a/handlers/getStatus.go
+++ b/handlers/getStatus.go
@@ -12,7 +12,7 @@ import (
 )
 
 var initTime = time.Now()
-var version = "1.19.1"
+var version = "1.19.2"
 
 func getStatus(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(map[string]interface{}{
diff --git a/validators/ValidateGuildNameQueryParam.go b/validators/ValidateGuildNameQueryParam.go
index ef892e2..8aeacf8 100644
--- a/validators/ValidateGuildNameQueryParam.go
+++ b/validators/ValidateGuildNameQueryParam.go
@@ -9,15 +9,21 @@ import (
 // The naming policies in BDO are fucked up
 // This function only checks the length and allowed symbols
 // I also assumed that the allowed symbols are the same as for adventurer names
-func ValidateGuildNameQueryParam(query []string) (guildName string, ok bool, errorMessage string) {
+func ValidateGuildNameQueryParam(query []string, region string) (guildName string, ok bool, errorMessage string) {
 	if 1 > len(query) {
 		return "", false, "Guild name is missing from request"
 	}
 
 	guildName = strings.ToLower(query[0])
 
-	if len(guildName) < 3 {
-		return guildName, false, "Guild name can't be shorter than 3 symbols"
+	minLength := map[string]int{
+		"EU": 3,
+		"KR": 3,
+		"NA": 3,
+		"SA": 2,
+	}[region]
+	if len(guildName) < minLength {
+		return guildName, false, fmt.Sprintf("Guild name in %v region can't be shorter than %v symbols", region, minLength)
 	}
 
 	if len(guildName) > 16 {
@@ -43,7 +49,7 @@ func ValidateGuildNameQueryParam(query []string) (guildName string, ok bool, err
 		}
 
 		// Korean characters
-		if unicode.Is(unicode.Hangul, r) {
+		if region == "KR" && unicode.Is(unicode.Hangul, r) {
 			return false
 		}
 
diff --git a/validators/ValidateGuildNameQueryParam_test.go b/validators/ValidateGuildNameQueryParam_test.go
index bc5faf7..fccfd22 100644
--- a/validators/ValidateGuildNameQueryParam_test.go
+++ b/validators/ValidateGuildNameQueryParam_test.go
@@ -8,23 +8,26 @@ func TestValidateGuildNameQueryParam(t *testing.T) {
 		expectedOk      bool
 		expectedMessage string
 		input           []string
+		region          string
 	}{
-		{input: []string{"1NumberGuild"}, expectedName: "1numberguild", expectedOk: true, expectedMessage: ""}, // Contains a number
-		{input: []string{"Adventure_Guild"}, expectedName: "adventure_guild", expectedOk: true, expectedMessage: ""},
-		{input: []string{"FirstGuild", "SecondGuild"}, expectedName: "firstguild", expectedOk: true, expectedMessage: ""},
-		{input: []string{"MyGuild"}, expectedName: "myguild", expectedOk: true, expectedMessage: ""},
-		{input: []string{"고대신"}, expectedName: "고대신", expectedOk: true, expectedMessage: ""}, // Guild name with Korean characters
+		{input: []string{"1NumberGuild"}, region: "EU", expectedName: "1numberguild", expectedOk: true, expectedMessage: ""}, // Contains a number
+		{input: []string{"Adventure_Guild"}, region: "NA", expectedName: "adventure_guild", expectedOk: true, expectedMessage: ""},
+		{input: []string{"FirstGuild", "SecondGuild"}, region: "EU", expectedName: "firstguild", expectedOk: true, expectedMessage: ""},
+		{input: []string{"MyGuild"}, region: "NA", expectedName: "myguild", expectedOk: true, expectedMessage: ""},
+		{input: []string{"고대신"}, region: "KR", expectedName: "고대신", expectedOk: true, expectedMessage: ""}, // Guild name with Korean characters
+		{input: []string{"IX"}, region: "SA", expectedName: "ix", expectedOk: true, expectedMessage: ""},   // Guild names on SA can be 2 symbols long
 
-		{input: []string{""}, expectedName: "", expectedOk: false, expectedMessage: "Guild name can't be shorter than 3 symbols"},
-		{input: []string{"With Spaces"}, expectedName: "with spaces", expectedOk: false, expectedMessage: "Guild name contains a forbidden symbol at position 5: ' '"},
-		{input: []string{"Some$"}, expectedName: "some$", expectedOk: false, expectedMessage: "Guild name contains a forbidden symbol at position 5: '$'"},
-		{input: []string{"x"}, expectedName: "x", expectedOk: false, expectedMessage: "Guild name can't be shorter than 3 symbols"},
-		{input: []string{}, expectedName: "", expectedOk: false, expectedMessage: "Guild name is missing from request"},
-		{input: []string{"GuildNameThatIsWayTooLong"}, expectedName: "guildnamethatiswaytoolong", expectedOk: false, expectedMessage: "Guild name can't be longer than 16 symbols"},
+		{input: []string{""}, region: "EU", expectedName: "", expectedOk: false, expectedMessage: "Guild name in EU region can't be shorter than 3 symbols"},
+		{input: []string{"X"}, region: "SA", expectedName: "x", expectedOk: false, expectedMessage: "Guild name in SA region can't be shorter than 2 symbols"}, // Guild names on SA can be 2 symbols long
+		{input: []string{"With Spaces"}, region: "NA", expectedName: "with spaces", expectedOk: false, expectedMessage: "Guild name contains a forbidden symbol at position 5: ' '"},
+		{input: []string{"Some$"}, region: "SA", expectedName: "some$", expectedOk: false, expectedMessage: "Guild name contains a forbidden symbol at position 5: '$'"},
+		{input: []string{"x"}, region: "KR", expectedName: "x", expectedOk: false, expectedMessage: "Guild name in KR region can't be shorter than 3 symbols"},
+		{input: []string{}, region: "EU", expectedName: "", expectedOk: false, expectedMessage: "Guild name is missing from request"},
+		{input: []string{"GuildNameThatIsWayTooLong"}, region: "NA", expectedName: "guildnamethatiswaytoolong", expectedOk: false, expectedMessage: "Guild name can't be longer than 16 symbols"},
 	}
 
 	for _, test := range tests {
-		name, ok, message := ValidateGuildNameQueryParam(test.input)
+		name, ok, message := ValidateGuildNameQueryParam(test.input, test.region)
 		if name != test.expectedName || ok != test.expectedOk || message != test.expectedMessage {
 			t.Errorf("Input: %v, Expected: %v %v %v, Got: %v %v %v", test.input, test.expectedName, test.expectedOk, test.expectedMessage, name, ok, message)
 		}
