mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-08-05 18:01:11 -05:00
GPCM: Report events for profile actions
This commit is contained in:
parent
e30d89cd1e
commit
1c44f521f3
|
|
@ -3,6 +3,7 @@ package common
|
|||
import (
|
||||
"encoding/xml"
|
||||
"os"
|
||||
"wwfc/logging"
|
||||
|
||||
"github.com/linkdata/deadlock"
|
||||
)
|
||||
|
|
@ -53,15 +54,8 @@ type Config struct {
|
|||
}
|
||||
|
||||
type EventReportingConfig struct {
|
||||
LogToDatabase bool `xml:"logToDatabase"`
|
||||
Webhooks []WebhookConfig `xml:"discord>webhook"`
|
||||
}
|
||||
|
||||
type WebhookConfig struct {
|
||||
Enabled bool `xml:"enabled"`
|
||||
URL string `xml:"url"`
|
||||
Author string `xml:"author,omitempty"`
|
||||
EventTypes []string `xml:"eventTypes>event"`
|
||||
LogToDatabase bool `xml:"logToDatabase"`
|
||||
Webhooks []logging.WebhookConfig `xml:"discord>webhook"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -157,6 +151,6 @@ func GetConfig() Config {
|
|||
|
||||
func (c Config) RegisterWebhooks() {
|
||||
for _, webhook := range c.EventReporting.Webhooks {
|
||||
webhook.RegisterEventReporting()
|
||||
webhook.RegisterWebhook()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package common
|
|||
|
||||
import "reflect"
|
||||
|
||||
func UNUSED(v ...interface{}) {
|
||||
func MaybeUnused(v ...interface{}) {
|
||||
}
|
||||
|
||||
func ReverseMap(m interface{}) interface{} {
|
||||
|
|
|
|||
|
|
@ -33,5 +33,7 @@ func Start(config common.Config) Connection {
|
|||
}
|
||||
|
||||
func (c *Connection) Close() {
|
||||
c.pool.Close()
|
||||
if c != nil && c.pool != nil {
|
||||
c.pool.Close()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ func (c *Connection) InsertEvent(eventType string, eventData map[string]any) (in
|
|||
return eventId, nil
|
||||
}
|
||||
|
||||
func (c *Connection) RegisterEventLogging(config common.Config, eventTypes []string) {
|
||||
func (c *Connection) RegisterEvents(config common.Config, eventTypes []string) {
|
||||
if !config.EventReporting.LogToDatabase {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ func (c *Connection) LoginUserToGPCM(userId uint64, gsbrcd string, profileId uin
|
|||
}
|
||||
|
||||
logging.Notice("DATABASE", "Created new GPCM user:", aurora.Cyan(userId), aurora.Cyan(gsbrcd), aurora.Cyan(user.ProfileId))
|
||||
user.Created = true
|
||||
} else {
|
||||
var firstName *string
|
||||
var lastName *string
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ type User struct {
|
|||
OpenHost bool
|
||||
LastInGameSn string
|
||||
LastIPAddress string
|
||||
Created bool
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ func HandlePacket(index uint64, data []byte) {
|
|||
|
||||
commands = session.handleCommand("getpd", commands, session.getpd)
|
||||
commands = session.handleCommand("setpd", commands, session.setpd)
|
||||
common.UNUSED(session.ignoreCommand)
|
||||
common.MaybeUnused(session.ignoreCommand)
|
||||
|
||||
for _, command := range commands {
|
||||
logging.Error(session.ModuleName, "Unknown command:", aurora.Cyan(command))
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ func printHex(data []byte) {
|
|||
}
|
||||
|
||||
func verifyECDSA(publicKey []byte, signature []byte, hash []byte) bool {
|
||||
common.UNUSED(printHex)
|
||||
common.MaybeUnused(printHex)
|
||||
|
||||
r := big.NewInt(0).SetBytes(signature[0x00:0x1E])
|
||||
s := big.NewInt(0).SetBytes(signature[0x1E:0x3C])
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ func (err GPError) GetMessage() string {
|
|||
return common.CreateGameSpyMessage(command)
|
||||
}
|
||||
|
||||
func (err GPError) GetMessageTranslate(gameName string, region byte, lang byte, cfc uint64, ngid uint32) string {
|
||||
func (err GPError) GetMessageTranslate(gameName string, region byte, lang byte, cfc uint64, ngid uint32) (string, int) {
|
||||
command := common.GameSpyCommand{
|
||||
Command: "error",
|
||||
CommandValue: "",
|
||||
|
|
@ -462,7 +462,7 @@ func (err GPError) GetMessageTranslate(gameName string, region byte, lang byte,
|
|||
command.OtherValues["wl:err"] = strconv.Itoa(err.WWFCMessage.ErrorCode)
|
||||
}
|
||||
|
||||
return common.CreateGameSpyMessage(command)
|
||||
return common.CreateGameSpyMessage(command), err.WWFCMessage.ErrorCode
|
||||
}
|
||||
|
||||
func (g *GameSpySession) replyError(err GPError) {
|
||||
|
|
@ -474,6 +474,12 @@ func (g *GameSpySession) replyError(err GPError) {
|
|||
if err.Fatal {
|
||||
common.CloseConnection(ServerName, g.ConnIndex)
|
||||
}
|
||||
logging.Event("gpcm_returned_error", map[string]any{
|
||||
"profile_id": g.User.ProfileId,
|
||||
"error_code": err.ErrorCode,
|
||||
"error_string": err.ErrorString,
|
||||
"fatal": err.Fatal,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -482,10 +488,18 @@ func (g *GameSpySession) replyError(err GPError) {
|
|||
deviceId = g.User.NgDeviceId[0]
|
||||
}
|
||||
|
||||
msg := err.GetMessageTranslate(g.GameName, g.Region, g.Language, g.ConsoleFriendCode, deviceId)
|
||||
msg, wwfcErrorCode := err.GetMessageTranslate(g.GameName, g.Region, g.Language, g.ConsoleFriendCode, deviceId)
|
||||
// logging.Info(g.ModuleName, "Sending error message:", msg)
|
||||
common.SendPacket(ServerName, g.ConnIndex, []byte(msg))
|
||||
if err.Fatal {
|
||||
common.CloseConnection(ServerName, g.ConnIndex)
|
||||
}
|
||||
|
||||
logging.Event("gpcm_returned_error", map[string]any{
|
||||
"profile_id": g.User.ProfileId,
|
||||
"error_code": err.ErrorCode,
|
||||
"error_string": err.ErrorString,
|
||||
"fatal": err.Fatal,
|
||||
"wiilink_error_code": wwfcErrorCode,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ func sendMessageToProfileId(msgType string, from uint32, to uint32, msg string)
|
|||
}
|
||||
|
||||
func (g *GameSpySession) sendFriendStatus(profileId uint32) {
|
||||
common.UNUSED(sendMessageToProfileId)
|
||||
common.MaybeUnused(sendMessageToProfileId)
|
||||
|
||||
if !g.isFriendAuthorized(profileId) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -226,6 +226,18 @@ func (g *GameSpySession) login(command common.GameSpyCommand) {
|
|||
|
||||
g.LoginInfoSet = true
|
||||
|
||||
logging.Event(
|
||||
"received_login_info",
|
||||
map[string]any{
|
||||
"user_id": userId,
|
||||
"game_name": g.GameName,
|
||||
"wii_number": cfc,
|
||||
"in_game_name": ingamesn,
|
||||
"unit_code": unitcd,
|
||||
"ip_address": g.RemoteAddr,
|
||||
},
|
||||
)
|
||||
|
||||
expectedUnitCode := common.GetExpectedUnitCode(g.GameName)
|
||||
if (g.UnitCode != UnitCodeDS && g.UnitCode != UnitCodeWii) || (g.UnitCode != expectedUnitCode && expectedUnitCode != UnitCodeDSAndWii) {
|
||||
logging.Error(g.ModuleName, "Incorrect unit code specified:", aurora.Cyan(unitcd))
|
||||
|
|
@ -294,6 +306,18 @@ func (g *GameSpySession) login(command common.GameSpyCommand) {
|
|||
return
|
||||
}
|
||||
|
||||
if g.User.Created {
|
||||
logging.Event(
|
||||
"profile_created",
|
||||
map[string]any{
|
||||
"user_id": g.User.UserId,
|
||||
"profile_id": g.User.ProfileId,
|
||||
"ip_address": g.RemoteAddr,
|
||||
},
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
g.ModuleName = "GPCM:" + strconv.FormatInt(int64(g.User.ProfileId), 10) + "*"
|
||||
g.ModuleName += "/" + common.CalcFriendCodeString(g.User.ProfileId, g.User.GsbrCode[:4]) + "*"
|
||||
|
||||
|
|
@ -369,6 +393,19 @@ func (g *GameSpySession) login(command common.GameSpyCommand) {
|
|||
})
|
||||
|
||||
common.SendPacket(ServerName, g.ConnIndex, []byte(payload))
|
||||
|
||||
logging.Event(
|
||||
"logged_in",
|
||||
map[string]any{
|
||||
"user_id": g.User.UserId,
|
||||
"profile_id": g.User.ProfileId,
|
||||
"game_name": g.GameName,
|
||||
"wii_number": g.ConsoleFriendCode,
|
||||
"in_game_name": g.InGameName,
|
||||
"unit_code": g.UnitCode,
|
||||
"ip_address": g.RemoteAddr,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (g *GameSpySession) exLogin(command common.GameSpyCommand) {
|
||||
|
|
@ -446,6 +483,14 @@ func (g *GameSpySession) verifyExLoginInfo(command common.GameSpyCommand, authTo
|
|||
}
|
||||
|
||||
g.DeviceId = deviceId
|
||||
logging.Event(
|
||||
"device_authenticated",
|
||||
map[string]any{
|
||||
"profile_id": g.User.ProfileId,
|
||||
"ng_device_id": g.User.NgDeviceId,
|
||||
"payload_version": payloadVer,
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
15
gpcm/main.go
15
gpcm/main.go
|
|
@ -88,6 +88,17 @@ func StartServer(reload bool) {
|
|||
|
||||
logging.Notice("GPCM", "Loaded", aurora.Cyan(len(sessions)), "sessions")
|
||||
}
|
||||
|
||||
db.RegisterEvents(config, []string{
|
||||
"profile_created",
|
||||
"logged_in",
|
||||
"logged_out",
|
||||
"received_login_info",
|
||||
"device_authenticated",
|
||||
"reported_bad_packet",
|
||||
"reported_stall",
|
||||
"gpcm_returned_error",
|
||||
})
|
||||
}
|
||||
|
||||
func Shutdown() {
|
||||
|
|
@ -120,6 +131,10 @@ func CloseConnection(index uint64) {
|
|||
qr2.ProcessGPStatusUpdate(session.User.ProfileId, session.QR2IP, "0")
|
||||
}
|
||||
session.sendLogoutStatus()
|
||||
|
||||
logging.Event("logged_out", map[string]any{
|
||||
"profile_id": session.User.ProfileId,
|
||||
})
|
||||
}
|
||||
|
||||
mutex.Lock()
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ func (g *GameSpySession) handleWWFCReport(command common.GameSpyCommand) {
|
|||
}
|
||||
|
||||
logging.Warn(g.ModuleName, "Report bad packet from", aurora.BrightCyan(strconv.FormatUint(profileId, 10)))
|
||||
logging.Event("reported_bad_packet", map[string]any{
|
||||
"profile_id": g.User.ProfileId,
|
||||
"sender_id": profileId,
|
||||
})
|
||||
|
||||
case "wl:stall":
|
||||
profileId, err := strconv.ParseUint(value, 10, 32)
|
||||
|
|
@ -36,6 +40,10 @@ func (g *GameSpySession) handleWWFCReport(command common.GameSpyCommand) {
|
|||
}
|
||||
|
||||
logging.Warn(g.ModuleName, "Room stall caused by", aurora.BrightCyan(strconv.FormatUint(profileId, 10)))
|
||||
logging.Event("reported_stall", map[string]any{
|
||||
"profile_id": g.User.ProfileId,
|
||||
"stalling_id": profileId,
|
||||
})
|
||||
|
||||
case "wl:mkw_user":
|
||||
if g.GameName != "mariokartwii" {
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ func Event(eventType string, eventData map[string]any) {
|
|||
defer mutex.RUnlock()
|
||||
for _, callback := range eventCallbacks {
|
||||
if callback.AllEvents {
|
||||
callback.Function(eventType, eventData)
|
||||
go callback.Function(eventType, eventData)
|
||||
} else if _, ok := callback.EventTypes[eventType]; ok {
|
||||
callback.Function(eventType, eventData)
|
||||
go callback.Function(eventType, eventData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
package common
|
||||
package logging
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"wwfc/logging"
|
||||
)
|
||||
|
||||
func contains(slice []string, item string) bool {
|
||||
|
|
@ -17,6 +16,13 @@ func contains(slice []string, item string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
type WebhookConfig struct {
|
||||
Enabled bool `xml:"enabled"`
|
||||
URL string `xml:"url"`
|
||||
Author string `xml:"author,omitempty"`
|
||||
EventTypes []string `xml:"eventTypes>event"`
|
||||
}
|
||||
|
||||
type webhookAuthor struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
}
|
||||
|
|
@ -79,19 +85,20 @@ func (w WebhookConfig) ReportEvent(eventType string, eventData map[string]any) {
|
|||
}
|
||||
resp, err := http.Post(w.URL, "application/json", strings.NewReader(string(jsonData)))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
Error("LOGGING", "Failed to send webhook request:", err)
|
||||
return
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
panic("received non-2xx response: " + resp.Status)
|
||||
Error("LOGGING", "Received non-2xx response from webhook:", resp.Status)
|
||||
}
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
func (w WebhookConfig) RegisterEventReporting() {
|
||||
func (w WebhookConfig) RegisterWebhook() {
|
||||
if !w.Enabled {
|
||||
return
|
||||
}
|
||||
logging.RegisterEventCallback(w.EventTypes, func(eventType string, eventData map[string]any) {
|
||||
RegisterEventCallback(w.EventTypes, func(eventType string, eventData map[string]any) {
|
||||
w.ReportEvent(eventType, eventData)
|
||||
})
|
||||
}
|
||||
15
main.go
15
main.go
|
|
@ -72,16 +72,11 @@ type RPCPacket struct {
|
|||
}
|
||||
|
||||
func connectAndLogEvent(eventType string) {
|
||||
var db *database.Connection
|
||||
defer func() {
|
||||
logging.Event(eventType, map[string]any{})
|
||||
if db != nil {
|
||||
db.Close()
|
||||
}
|
||||
}()
|
||||
dbObject := database.Start(config)
|
||||
db = &dbObject
|
||||
dbObject.RegisterEventLogging(config, []string{eventType})
|
||||
var db database.Connection
|
||||
defer db.Close()
|
||||
defer logging.Event(eventType, map[string]any{})
|
||||
db = database.Start(config)
|
||||
db.RegisterEvents(config, []string{eventType})
|
||||
}
|
||||
|
||||
// backendMain starts all the servers and creates an RPC server to communicate with the frontend
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user