mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-03-21 17:44:58 -05:00
commit
e5a6aedb34
139
api/ban.go
139
api/ban.go
|
|
@ -2,8 +2,8 @@ package api
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
"wwfc/database"
|
||||
|
|
@ -11,116 +11,87 @@ import (
|
|||
)
|
||||
|
||||
func HandleBan(w http.ResponseWriter, r *http.Request) {
|
||||
errorString := handleBanImpl(w, r)
|
||||
if errorString != "" {
|
||||
jsonData, _ := json.Marshal(map[string]string{"error": errorString})
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.Write(jsonData)
|
||||
var success bool
|
||||
var err string
|
||||
var statusCode int
|
||||
|
||||
if r.Method == http.MethodPost {
|
||||
success, err, statusCode = handleBanImpl(r)
|
||||
} else {
|
||||
jsonData, _ := json.Marshal(map[string]string{"success": "true"})
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.Write(jsonData)
|
||||
err = "Incorrect request. POST only."
|
||||
statusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
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})
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(jsonData)
|
||||
}
|
||||
|
||||
func handleBanImpl(w http.ResponseWriter, r *http.Request) string {
|
||||
type BanRequestSpec struct {
|
||||
Secret string
|
||||
Pid uint32
|
||||
Days uint64
|
||||
Hours uint64
|
||||
Minutes uint64
|
||||
Tos bool
|
||||
Reason string
|
||||
ReasonHidden string
|
||||
Moderator string
|
||||
}
|
||||
|
||||
func handleBanImpl(r *http.Request) (bool, string, int) {
|
||||
// TODO: Actual authentication rather than a fixed secret
|
||||
// TODO: Use POST instead of GET
|
||||
|
||||
u, err := url.Parse(r.URL.String())
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return "Bad request"
|
||||
return false, "Unable to read request body", http.StatusBadRequest
|
||||
}
|
||||
|
||||
query, err := url.ParseQuery(u.RawQuery)
|
||||
var req BanRequestSpec
|
||||
err = json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
return "Bad request"
|
||||
return false, err.Error(), http.StatusBadRequest
|
||||
}
|
||||
|
||||
if apiSecret == "" || query.Get("secret") != apiSecret {
|
||||
return "Invalid API secret"
|
||||
if apiSecret == "" || req.Secret != apiSecret {
|
||||
return false, "Invalid API secret in request", http.StatusUnauthorized
|
||||
}
|
||||
|
||||
pidStr := query.Get("pid")
|
||||
if pidStr == "" {
|
||||
return "Missing pid in request"
|
||||
if req.Pid == 0 {
|
||||
return false, "pid missing or 0 in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
pid, err := strconv.ParseUint(pidStr, 10, 32)
|
||||
if err != nil {
|
||||
return "Invalid pid"
|
||||
if req.Reason == "" {
|
||||
return false, "Missing ban reason in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
tosStr := query.Get("tos")
|
||||
if tosStr == "" {
|
||||
return "Missing tos in request"
|
||||
}
|
||||
|
||||
tos, err := strconv.ParseBool(tosStr)
|
||||
if err != nil {
|
||||
return "Invalid tos"
|
||||
}
|
||||
|
||||
minutes := uint64(0)
|
||||
if query.Get("minutes") != "" {
|
||||
minutesStr := query.Get("minutes")
|
||||
minutes, err = strconv.ParseUint(minutesStr, 10, 32)
|
||||
if err != nil {
|
||||
return "Invalid minutes"
|
||||
}
|
||||
}
|
||||
|
||||
hours := uint64(0)
|
||||
if query.Get("hours") != "" {
|
||||
hoursStr := query.Get("hours")
|
||||
hours, err = strconv.ParseUint(hoursStr, 10, 32)
|
||||
if err != nil {
|
||||
return "Invalid hours"
|
||||
}
|
||||
}
|
||||
|
||||
days := uint64(0)
|
||||
if query.Get("days") != "" {
|
||||
daysStr := query.Get("days")
|
||||
days, err = strconv.ParseUint(daysStr, 10, 32)
|
||||
if err != nil {
|
||||
return "Invalid days"
|
||||
}
|
||||
}
|
||||
|
||||
reason := query.Get("reason")
|
||||
if "reason" == "" {
|
||||
return "Missing ban reason"
|
||||
}
|
||||
|
||||
// reason_hidden is optional
|
||||
reasonHidden := query.Get("reason_hidden")
|
||||
|
||||
moderator := query.Get("moderator")
|
||||
if "moderator" == "" {
|
||||
moderator := req.Moderator
|
||||
if moderator == "" {
|
||||
moderator = "admin"
|
||||
}
|
||||
|
||||
minutes = days*24*60 + hours*60 + minutes
|
||||
minutes := req.Days*24*60 + req.Hours*60 + req.Minutes
|
||||
if minutes == 0 {
|
||||
return "Missing ban length"
|
||||
return false, "Ban length missing or 0", http.StatusBadRequest
|
||||
}
|
||||
|
||||
length := time.Duration(minutes) * time.Minute
|
||||
|
||||
if !database.BanUser(pool, ctx, uint32(pid), tos, length, reason, reasonHidden, moderator) {
|
||||
return "Failed to ban user"
|
||||
if !database.BanUser(pool, ctx, req.Pid, req.Tos, length, req.Reason, req.ReasonHidden, moderator) {
|
||||
return false, "Failed to ban user", http.StatusInternalServerError
|
||||
}
|
||||
|
||||
if tos {
|
||||
gpcm.KickPlayer(uint32(pid), "banned")
|
||||
} else {
|
||||
gpcm.KickPlayer(uint32(pid), "restricted")
|
||||
}
|
||||
gpcm.KickPlayerCustomMessage(req.Pid, req.Reason, gpcm.WWFCMsgProfileRestrictedCustom)
|
||||
|
||||
return ""
|
||||
return true, "", http.StatusOK
|
||||
}
|
||||
|
|
|
|||
73
api/kick.go
73
api/kick.go
|
|
@ -2,57 +2,72 @@ package api
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"wwfc/gpcm"
|
||||
)
|
||||
|
||||
func HandleKick(w http.ResponseWriter, r *http.Request) {
|
||||
errorString := handleKickImpl(w, r)
|
||||
if errorString != "" {
|
||||
jsonData, _ := json.Marshal(map[string]string{"error": errorString})
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.Write(jsonData)
|
||||
var success bool
|
||||
var err string
|
||||
var statusCode int
|
||||
|
||||
if r.Method == http.MethodPost {
|
||||
success, err, statusCode = handleKickImpl(r)
|
||||
} else {
|
||||
jsonData, _ := json.Marshal(map[string]string{"success": "true"})
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.Write(jsonData)
|
||||
err = "Incorrect request. POST only."
|
||||
statusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
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})
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(jsonData)
|
||||
}
|
||||
|
||||
func handleKickImpl(w http.ResponseWriter, r *http.Request) string {
|
||||
type KickRequestSpec struct {
|
||||
Secret string
|
||||
Reason string
|
||||
Pid uint32
|
||||
}
|
||||
|
||||
func handleKickImpl(r *http.Request) (bool, string, int) {
|
||||
// TODO: Actual authentication rather than a fixed secret
|
||||
// TODO: Use POST instead of GET
|
||||
|
||||
u, err := url.Parse(r.URL.String())
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return "Bad request"
|
||||
return false, "Unable to read request body", http.StatusBadRequest
|
||||
}
|
||||
|
||||
query, err := url.ParseQuery(u.RawQuery)
|
||||
var req KickRequestSpec
|
||||
err = json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
return "Bad request"
|
||||
return false, err.Error(), http.StatusBadRequest
|
||||
}
|
||||
|
||||
if apiSecret == "" || query.Get("secret") != apiSecret {
|
||||
return "Invalid API secret"
|
||||
if apiSecret == "" || req.Secret != apiSecret {
|
||||
return false, "Invalid API secret in request", http.StatusUnauthorized
|
||||
}
|
||||
|
||||
pidStr := query.Get("pid")
|
||||
if pidStr == "" {
|
||||
return "Missing pid in request"
|
||||
if req.Pid == 0 {
|
||||
return false, "pid missing or 0 in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
pid, err := strconv.ParseUint(pidStr, 10, 32)
|
||||
if err != nil {
|
||||
return "Invalid pid"
|
||||
if req.Reason == "" {
|
||||
return false, "Missing kick reason in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
gpcm.KickPlayer(uint32(pid), "moderator_kick")
|
||||
return ""
|
||||
gpcm.KickPlayerCustomMessage(req.Pid, req.Reason, gpcm.WWFCMsgKickedCustom)
|
||||
|
||||
return true, "", http.StatusOK
|
||||
}
|
||||
|
|
|
|||
70
api/unban.go
70
api/unban.go
|
|
@ -2,57 +2,69 @@ package api
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"wwfc/database"
|
||||
)
|
||||
|
||||
func HandleUnban(w http.ResponseWriter, r *http.Request) {
|
||||
errorString := handleUnbanImpl(w, r)
|
||||
if errorString != "" {
|
||||
jsonData, _ := json.Marshal(map[string]string{"error": errorString})
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.Write(jsonData)
|
||||
var success bool
|
||||
var err string
|
||||
var statusCode int
|
||||
|
||||
if r.Method == http.MethodPost {
|
||||
success, err, statusCode = handleUnbanImpl(r)
|
||||
} else {
|
||||
jsonData, _ := json.Marshal(map[string]string{"success": "true"})
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.Write(jsonData)
|
||||
err = "Incorrect request. POST only."
|
||||
statusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
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})
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(jsonData)
|
||||
}
|
||||
|
||||
func handleUnbanImpl(w http.ResponseWriter, r *http.Request) string {
|
||||
type UnbanRequestSpec struct {
|
||||
Secret string
|
||||
Pid uint32
|
||||
}
|
||||
|
||||
func handleUnbanImpl(r *http.Request) (bool, string, int) {
|
||||
// TODO: Actual authentication rather than a fixed secret
|
||||
// TODO: Use POST instead of GET
|
||||
|
||||
u, err := url.Parse(r.URL.String())
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return "Bad request"
|
||||
return false, "Unable to read request body", http.StatusBadRequest
|
||||
}
|
||||
|
||||
query, err := url.ParseQuery(u.RawQuery)
|
||||
var req UnbanRequestSpec
|
||||
err = json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
return "Bad request"
|
||||
return false, err.Error(), http.StatusBadRequest
|
||||
}
|
||||
|
||||
if apiSecret == "" || query.Get("secret") != apiSecret {
|
||||
return "Invalid API secret"
|
||||
if apiSecret == "" || req.Secret != apiSecret {
|
||||
return false, "Invalid API secret in request", http.StatusUnauthorized
|
||||
}
|
||||
|
||||
pidStr := query.Get("pid")
|
||||
if pidStr == "" {
|
||||
return "Missing pid in request"
|
||||
if req.Pid == 0 {
|
||||
return false, "pid missing or 0 in request", http.StatusBadRequest
|
||||
}
|
||||
|
||||
pid, err := strconv.ParseUint(pidStr, 10, 32)
|
||||
if err != nil {
|
||||
return "Invalid pid"
|
||||
if !database.UnbanUser(pool, ctx, req.Pid) {
|
||||
return false, "Failed to unban user", http.StatusInternalServerError
|
||||
}
|
||||
|
||||
database.UnbanUser(pool, ctx, uint32(pid))
|
||||
return ""
|
||||
return true, "", http.StatusOK
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const (
|
|||
ON ng_device_id && array[dt.device_id]
|
||||
) SELECT array_agg(DISTINCT device_id) FROM device_tree
|
||||
)
|
||||
SELECT has_ban, ban_tos, ng_device_id
|
||||
SELECT has_ban, ban_tos, ng_device_id, ban_reason
|
||||
FROM users
|
||||
WHERE has_ban = true
|
||||
AND (profile_id = $2
|
||||
|
|
@ -170,8 +170,11 @@ func LoginUserToGPCM(pool *pgxpool.Pool, ctx context.Context, userId uint64, gsb
|
|||
var banExists bool
|
||||
var banTOS bool
|
||||
var bannedDeviceIdList []uint32
|
||||
var banReason string
|
||||
|
||||
timeNow := time.Now()
|
||||
err = pool.QueryRow(ctx, SearchUserBan, user.NgDeviceId, user.ProfileId, ipAddress, *lastIPAddress, timeNow).Scan(&banExists, &banTOS, &bannedDeviceIdList)
|
||||
err = pool.QueryRow(ctx, SearchUserBan, user.NgDeviceId, user.ProfileId, ipAddress, *lastIPAddress, timeNow).Scan(&banExists, &banTOS, &bannedDeviceIdList, &banReason)
|
||||
|
||||
if err != nil {
|
||||
if err != pgx.ErrNoRows {
|
||||
return User{}, err
|
||||
|
|
@ -202,12 +205,13 @@ func LoginUserToGPCM(pool *pgxpool.Pool, ctx context.Context, userId uint64, gsb
|
|||
|
||||
if banTOS {
|
||||
logging.Warn("DATABASE", "Profile", aurora.Cyan(user.ProfileId), "is banned")
|
||||
return User{RestrictedDeviceId: bannedDeviceId}, ErrProfileBannedTOS
|
||||
return User{RestrictedDeviceId: bannedDeviceId, BanReason: banReason}, ErrProfileBannedTOS
|
||||
}
|
||||
|
||||
logging.Warn("DATABASE", "Profile", aurora.Cyan(user.ProfileId), "is restricted")
|
||||
user.Restricted = true
|
||||
user.RestrictedDeviceId = bannedDeviceId
|
||||
user.BanReason = banReason
|
||||
}
|
||||
|
||||
return user, nil
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ const (
|
|||
UpdateUserTable = `UPDATE users SET firstname = CASE WHEN $3 THEN $2 ELSE firstname END, lastname = CASE WHEN $5 THEN $4 ELSE lastname END, open_host = CASE WHEN $7 THEN $6 ELSE open_host END WHERE profile_id = $1`
|
||||
UpdateUserProfileID = `UPDATE users SET profile_id = $3 WHERE user_id = $1 AND gsbrcd = $2`
|
||||
UpdateUserNGDeviceID = `UPDATE users SET ng_device_id = $2 WHERE profile_id = $1`
|
||||
GetUser = `SELECT user_id, gsbrcd, email, unique_nick, firstname, lastname, open_host FROM users WHERE profile_id = $1`
|
||||
GetUser = `SELECT user_id, gsbrcd, email, unique_nick, firstname, lastname, open_host, last_ip_address, last_ingamesn FROM users WHERE profile_id = $1`
|
||||
ClearProfileQuery = `DELETE FROM users WHERE profile_id = $1 RETURNING user_id, gsbrcd, email, unique_nick, firstname, lastname, open_host, last_ip_address, last_ingamesn`
|
||||
DoesUserExist = `SELECT EXISTS(SELECT 1 FROM users WHERE user_id = $1 AND gsbrcd = $2)`
|
||||
IsProfileIDInUse = `SELECT EXISTS(SELECT 1 FROM users WHERE profile_id = $1)`
|
||||
DeleteUserSession = `DELETE FROM sessions WHERE profile_id = $1`
|
||||
|
|
@ -39,7 +40,10 @@ type User struct {
|
|||
LastName string
|
||||
Restricted bool
|
||||
RestrictedDeviceId uint32
|
||||
BanReason string
|
||||
OpenHost bool
|
||||
LastInGameSn string
|
||||
LastIPAddress string
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -128,7 +132,20 @@ func (user *User) UpdateProfile(pool *pgxpool.Pool, ctx context.Context, data ma
|
|||
func GetProfile(pool *pgxpool.Pool, ctx context.Context, profileId uint32) (User, bool) {
|
||||
user := User{}
|
||||
row := pool.QueryRow(ctx, GetUser, profileId)
|
||||
err := row.Scan(&user.UserId, &user.GsbrCode, &user.Email, &user.UniqueNick, &user.FirstName, &user.LastName, &user.OpenHost)
|
||||
err := row.Scan(&user.UserId, &user.GsbrCode, &user.Email, &user.UniqueNick, &user.FirstName, &user.LastName, &user.OpenHost, &user.LastIPAddress, &user.LastInGameSn)
|
||||
if err != nil {
|
||||
return User{}, false
|
||||
}
|
||||
|
||||
user.ProfileId = profileId
|
||||
return user, true
|
||||
}
|
||||
|
||||
func ClearProfile(pool *pgxpool.Pool, ctx context.Context, profileId uint32) (User, bool) {
|
||||
user := User{}
|
||||
row := pool.QueryRow(ctx, ClearProfileQuery, profileId)
|
||||
err := row.Scan(&user.UserId, &user.GsbrCode, &user.Email, &user.UniqueNick, &user.FirstName, &user.LastName, &user.OpenHost, &user.LastIPAddress, &user.LastInGameSn)
|
||||
|
||||
if err != nil {
|
||||
return User{}, false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ type GPError struct {
|
|||
ErrorString string
|
||||
Fatal bool
|
||||
WWFCMessage WWFCErrorMessage
|
||||
Reason string
|
||||
}
|
||||
|
||||
func MakeGPError(errorCode int, errorString string, fatal bool) GPError {
|
||||
|
|
@ -247,6 +248,17 @@ var (
|
|||
},
|
||||
}
|
||||
|
||||
WWFCMsgProfileRestrictedCustom = WWFCErrorMessage{
|
||||
ErrorCode: 22002,
|
||||
MessageRMC: map[byte]string{
|
||||
LangEnglish: "" +
|
||||
"You have been banned from WiiLink WFC\n" +
|
||||
"Error Code: %[1]d\n" +
|
||||
"Support Info: NG%08[2]x\n" +
|
||||
"Reason: %s",
|
||||
},
|
||||
}
|
||||
|
||||
WWFCMsgKickedGeneric = WWFCErrorMessage{
|
||||
ErrorCode: 22004,
|
||||
MessageRMC: map[byte]string{
|
||||
|
|
@ -281,6 +293,17 @@ var (
|
|||
},
|
||||
}
|
||||
|
||||
WWFCMsgKickedCustom = WWFCErrorMessage{
|
||||
ErrorCode: 22002,
|
||||
MessageRMC: map[byte]string{
|
||||
LangEnglish: "" +
|
||||
"You have been kicked from WiiLink WFC\n" +
|
||||
"Error Code: %[1]d\n" +
|
||||
"Support Info: NG%08[2]x\n" +
|
||||
"Reason: %s",
|
||||
},
|
||||
}
|
||||
|
||||
WWFCMsgConsoleMismatch = WWFCErrorMessage{
|
||||
ErrorCode: 22005,
|
||||
MessageRMC: map[byte]string{
|
||||
|
|
@ -405,7 +428,7 @@ func (err GPError) GetMessageTranslate(gameName string, region byte, lang byte,
|
|||
errMsg = err.WWFCMessage.MessageRMC[LangEnglish]
|
||||
}
|
||||
|
||||
errMsg = fmt.Sprintf(errMsg, err.WWFCMessage.ErrorCode, ngid)
|
||||
errMsg = fmt.Sprintf(errMsg, err.WWFCMessage.ErrorCode, ngid, err.Reason)
|
||||
errMsgUTF16 := utf16.Encode([]rune(errMsg))
|
||||
errMsgByteArray := common.UTF16ToByteArray(errMsgUTF16)
|
||||
|
||||
|
|
|
|||
15
gpcm/kick.go
15
gpcm/kick.go
|
|
@ -49,3 +49,18 @@ func KickPlayer(profileID uint32, reason string) {
|
|||
|
||||
kickPlayer(profileID, reason)
|
||||
}
|
||||
|
||||
func KickPlayerCustomMessage(profileID uint32, reason string, message WWFCErrorMessage) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if session, exists := sessions[profileID]; exists {
|
||||
session.replyError(GPError{
|
||||
ErrorCode: ErrConnectionClosed.ErrorCode,
|
||||
ErrorString: "The player was kicked from the server. Reason: " + reason,
|
||||
Fatal: true,
|
||||
WWFCMessage: message,
|
||||
Reason: reason,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -474,9 +474,10 @@ func (g *GameSpySession) performLoginWithDatabase(userId uint64, gsbrCode string
|
|||
} else if err == database.ErrProfileBannedTOS {
|
||||
g.replyError(GPError{
|
||||
ErrorCode: ErrLogin.ErrorCode,
|
||||
ErrorString: "The profile is banned from the service.",
|
||||
ErrorString: "The profile is banned from the service. Reason: " + user.BanReason,
|
||||
Fatal: true,
|
||||
WWFCMessage: WWFCMsgProfileBannedTOS,
|
||||
WWFCMessage: WWFCMsgKickedCustom,
|
||||
Reason: user.BanReason,
|
||||
})
|
||||
} else {
|
||||
g.replyError(GPError{
|
||||
|
|
|
|||
|
|
@ -14,3 +14,4 @@ func GetMessageOfTheDay() (string, error) {
|
|||
|
||||
return string(contents), nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user