diff --git a/api/ban.go b/api/ban.go index b34266c..4a4661a 100644 --- a/api/ban.go +++ b/api/ban.go @@ -8,6 +8,9 @@ import ( "time" "wwfc/database" "wwfc/gpcm" + "wwfc/logging" + + "github.com/logrusorgru/aurora/v3" ) func HandleBan(w http.ResponseWriter, r *http.Request) { @@ -17,36 +20,46 @@ func HandleBan(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { success, err, statusCode = handleBanImpl(r) + } else if r.Method == http.MethodOptions { + statusCode = http.StatusNoContent + w.Header().Set("Access-Control-Allow-Methods", "POST") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") } else { err = "Incorrect request. POST only." - statusCode = http.StatusBadRequest + statusCode = http.StatusMethodNotAllowed + w.Header().Set("Allow", "POST") } - w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") var jsonData []byte - if success { - jsonData, _ = json.Marshal(map[string]string{"success": "true"}) - } else { - jsonData, _ = json.Marshal(map[string]string{"error": err}) + + if statusCode != http.StatusNoContent { + w.Header().Set("Content-Type", "application/json") + + if success { + jsonData, _ = json.Marshal(map[string]string{"success": "true"}) + } else { + jsonData, _ = json.Marshal(map[string]string{"error": err}) + } } w.Header().Set("Content-Length", strconv.Itoa(len(jsonData))) + w.WriteHeader(statusCode) w.Write(jsonData) } type BanRequestSpec struct { - Secret string - Pid uint32 - Days uint64 - Hours uint64 - Minutes uint64 - Tos bool - Reason string - ReasonHidden string - Moderator string + Secret string `json:"secret"` + ProfileID uint32 `json:"pid"` + Days uint64 `json:"days"` + Hours uint64 `json:"hours"` + Minutes uint64 `json:"minutes"` + Tos bool `json:"tos"` + Reason string `json:"reason"` + ReasonHidden string `json:"reason_hidden"` + Moderator string `json:"moderator"` } func handleBanImpl(r *http.Request) (bool, string, int) { @@ -67,8 +80,8 @@ func handleBanImpl(r *http.Request) (bool, string, int) { return false, "Invalid API secret in request", http.StatusUnauthorized } - if req.Pid == 0 { - return false, "pid missing or 0 in request", http.StatusBadRequest + if req.ProfileID == 0 { + return false, "Profile ID missing or 0 in request", http.StatusBadRequest } if req.Reason == "" { @@ -87,11 +100,13 @@ func handleBanImpl(r *http.Request) (bool, string, int) { length := time.Duration(minutes) * time.Minute - if !database.BanUser(pool, ctx, req.Pid, req.Tos, length, req.Reason, req.ReasonHidden, moderator) { + logging.Notice("API:"+moderator, "Ban profile:", aurora.Cyan(req.ProfileID), "TOS:", aurora.Cyan(req.Tos), "Length:", aurora.Cyan(length), "Reason:", aurora.BrightCyan(req.Reason), "Reason (Hidden):", aurora.BrightCyan(req.ReasonHidden)) + + if !database.BanUser(pool, ctx, req.ProfileID, req.Tos, length, req.Reason, req.ReasonHidden, moderator) { return false, "Failed to ban user", http.StatusInternalServerError } - gpcm.KickPlayerCustomMessage(req.Pid, req.Reason, gpcm.WWFCMsgProfileRestrictedCustom) + gpcm.KickPlayerCustomMessage(req.ProfileID, req.Reason, gpcm.WWFCMsgProfileRestrictedCustom) return true, "", http.StatusOK } diff --git a/api/kick.go b/api/kick.go index 43228cd..6e43be6 100644 --- a/api/kick.go +++ b/api/kick.go @@ -15,30 +15,40 @@ func HandleKick(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { success, err, statusCode = handleKickImpl(r) + } else if r.Method == http.MethodOptions { + statusCode = http.StatusNoContent + w.Header().Set("Access-Control-Allow-Methods", "POST") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") } else { err = "Incorrect request. POST only." - statusCode = http.StatusBadRequest + statusCode = http.StatusMethodNotAllowed + w.Header().Set("Allow", "POST") } - w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") var jsonData []byte - if success { - jsonData, _ = json.Marshal(map[string]string{"success": "true"}) - } else { - jsonData, _ = json.Marshal(map[string]string{"error": err}) + + if statusCode != http.StatusNoContent { + w.Header().Set("Content-Type", "application/json") + + if success { + jsonData, _ = json.Marshal(map[string]string{"success": "true"}) + } else { + jsonData, _ = json.Marshal(map[string]string{"error": err}) + } } w.Header().Set("Content-Length", strconv.Itoa(len(jsonData))) + w.WriteHeader(statusCode) w.Write(jsonData) } type KickRequestSpec struct { - Secret string - Reason string - Pid uint32 + Secret string `json:"secret"` + Reason string `json:"reason"` + ProfileID uint32 `json:"pid"` } func handleKickImpl(r *http.Request) (bool, string, int) { @@ -59,15 +69,15 @@ func handleKickImpl(r *http.Request) (bool, string, int) { return false, "Invalid API secret in request", http.StatusUnauthorized } - if req.Pid == 0 { - return false, "pid missing or 0 in request", http.StatusBadRequest + if req.ProfileID == 0 { + return false, "Profile ID missing or 0 in request", http.StatusBadRequest } if req.Reason == "" { return false, "Missing kick reason in request", http.StatusBadRequest } - gpcm.KickPlayerCustomMessage(req.Pid, req.Reason, gpcm.WWFCMsgKickedCustom) + gpcm.KickPlayerCustomMessage(req.ProfileID, req.Reason, gpcm.WWFCMsgKickedCustom) return true, "", http.StatusOK } diff --git a/api/unban.go b/api/unban.go index 72081d6..33eb180 100644 --- a/api/unban.go +++ b/api/unban.go @@ -15,29 +15,39 @@ func HandleUnban(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { success, err, statusCode = handleUnbanImpl(r) + } else if r.Method == http.MethodOptions { + statusCode = http.StatusNoContent + w.Header().Set("Access-Control-Allow-Methods", "POST") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") } else { err = "Incorrect request. POST only." - statusCode = http.StatusBadRequest + statusCode = http.StatusMethodNotAllowed + w.Header().Set("Allow", "POST") } - w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") var jsonData []byte - if success { - jsonData, _ = json.Marshal(map[string]string{"success": "true"}) - } else { - jsonData, _ = json.Marshal(map[string]string{"error": err}) + + if statusCode != http.StatusNoContent { + w.Header().Set("Content-Type", "application/json") + + if success { + jsonData, _ = json.Marshal(map[string]string{"success": "true"}) + } else { + jsonData, _ = json.Marshal(map[string]string{"error": err}) + } } w.Header().Set("Content-Length", strconv.Itoa(len(jsonData))) + w.WriteHeader(statusCode) w.Write(jsonData) } type UnbanRequestSpec struct { - Secret string - Pid uint32 + Secret string `json:"secret"` + ProfileID uint32 `json:"pid"` } func handleUnbanImpl(r *http.Request) (bool, string, int) { @@ -58,11 +68,11 @@ func handleUnbanImpl(r *http.Request) (bool, string, int) { return false, "Invalid API secret in request", http.StatusUnauthorized } - if req.Pid == 0 { + if req.ProfileID == 0 { return false, "pid missing or 0 in request", http.StatusBadRequest } - if !database.UnbanUser(pool, ctx, req.Pid) { + if !database.UnbanUser(pool, ctx, req.ProfileID) { return false, "Failed to unban user", http.StatusInternalServerError } diff --git a/gpcm/error.go b/gpcm/error.go index 3a05ec9..b0479de 100644 --- a/gpcm/error.go +++ b/gpcm/error.go @@ -252,10 +252,21 @@ var ( ErrorCode: 22002, MessageRMC: map[byte]string{ LangEnglish: "" + - "You have been banned from WiiLink WFC\n" + + "You are banned from public matches.\n" + + "Reason: %s" + "Error Code: %[1]d\n" + - "Support Info: NG%08[2]x\n" + - "Reason: %s", + "Support Info: NG%08[2]x\n", + }, + } + + WWFCMsgProfileRestrictedNowCustom = WWFCErrorMessage{ + ErrorCode: 22002, + MessageRMC: map[byte]string{ + LangEnglish: "" + + "You have been banned from public matches.\n" + + "Reason: %s" + + "Error Code: %[1]d\n" + + "Support Info: NG%08[2]x\n", }, } @@ -297,10 +308,10 @@ var ( ErrorCode: 22002, MessageRMC: map[byte]string{ LangEnglish: "" + - "You have been kicked from WiiLink WFC\n" + + "You have been kicked from WiiLink WFC.\n" + + "Reason: %s" + "Error Code: %[1]d\n" + - "Support Info: NG%08[2]x\n" + - "Reason: %s", + "Support Info: NG%08[2]x\n", }, } @@ -382,7 +393,7 @@ var ( "Your game is dropping too many frames.\n" + "Please remove any modifications that may\n" + "be causing frame rate problems to avoid\n" + - "being banned from WiiLink Wi-Fi Connection.\n" + + "being banned from WiiLink WFC.\n" + "\n" + "Error Code: %[1]d", }, @@ -423,17 +434,45 @@ func (err GPError) GetMessageTranslate(gameName string, region byte, lang byte, if err.Fatal && err.WWFCMessage.ErrorCode != 0 { switch gameName { case "mariokartwii": - errMsg := err.WWFCMessage.MessageRMC[lang] - if errMsg == "" { - errMsg = err.WWFCMessage.MessageRMC[LangEnglish] + reason := err.Reason + wwfcMessage := err.WWFCMessage + + if reason == "" { + reason = "None provided." + + engMsg := err.WWFCMessage.MessageRMC[LangEnglish] + + if engMsg == WWFCMsgKickedCustom.MessageRMC[LangEnglish] { + wwfcMessage = WWFCMsgKickedModerator + } else if engMsg == WWFCMsgProfileRestrictedCustom.MessageRMC[LangEnglish] { + wwfcMessage = WWFCMsgProfileRestricted + } else if engMsg == WWFCMsgProfileRestrictedNowCustom.MessageRMC[LangEnglish] { + wwfcMessage = WWFCMsgProfileRestrictedNow + } } - errMsg = fmt.Sprintf(errMsg, err.WWFCMessage.ErrorCode, ngid, err.Reason) - errMsgUTF16 := utf16.Encode([]rune(errMsg)) - errMsgByteArray := common.UTF16ToByteArray(errMsgUTF16) + errMsg := wwfcMessage.MessageRMC[lang] + if errMsg == "" && lang != LangEnglish { + if lang == LangSpanishEU { + errMsg = wwfcMessage.MessageRMC[LangSpanish] + } else if lang == LangFrenchEU { + errMsg = wwfcMessage.MessageRMC[LangFrench] + } + + if errMsg == "" { + errMsg = wwfcMessage.MessageRMC[LangEnglish] + } + } + + if errMsg != "" { + errMsg = fmt.Sprintf(errMsg, wwfcMessage.ErrorCode, ngid, reason) + errMsgUTF16 := utf16.Encode([]rune(errMsg)) + errMsgByteArray := common.UTF16ToByteArray(errMsgUTF16) + command.OtherValues["wwfc_errmsg"] = common.Base64DwcEncoding.EncodeToString(errMsgByteArray) + } + + command.OtherValues["wwfc_err"] = strconv.Itoa(wwfcMessage.ErrorCode) - command.OtherValues["wwfc_err"] = strconv.Itoa(err.WWFCMessage.ErrorCode) - command.OtherValues["wwfc_errmsg"] = common.Base64DwcEncoding.EncodeToString(errMsgByteArray) } } diff --git a/gpcm/main.go b/gpcm/main.go index 1d7c68e..a3bb388 100644 --- a/gpcm/main.go +++ b/gpcm/main.go @@ -261,7 +261,7 @@ func HandlePacket(index uint64, data []byte) { data := []byte{} logged := false for c := 0; c < len(session.WriteBuffer); c++ { - if session.WriteBuffer[c] > 0xff || session.WriteBuffer[c] == 0x00 { + if session.WriteBuffer[c] == 0x00 { if !logged { logging.Warn(session.ModuleName, "Non-char or null byte in response packet:", session.WriteBuffer) logged = true