Skip to content

Commit d18fd80

Browse files
Merge pull request #20 from Corentin-cott/palworldTriggersIntegration
Palworld triggers integration
2 parents ad163ba + cc21246 commit d18fd80

File tree

2 files changed

+212
-50
lines changed

2 files changed

+212
-50
lines changed

internal/triggers/actions.go

Lines changed: 166 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,98 +31,227 @@ func WriteToLogFile(logPath string, line string) error {
3131
return nil
3232
}
3333

34-
// Action when a player message is detected
35-
func PlayerMessageAction(line string, serverID int) error {
36-
// Player name
34+
// Define the functions for each game, here is Minecraft
35+
func handleMinecraftPlayerMessage(line string) (string, string, string, string, error) {
3736
playerChatRegex := regexp.MustCompile(`\[(\d{2}:\d{2}:\d{2})\] \[Server thread/INFO](?: \[.+?/MinecraftServer])?: <(.+?)> (.+)`)
3837
matches := playerChatRegex.FindStringSubmatch(line)
3938
if len(matches) < 4 {
40-
return fmt.Errorf("ERROR WHILE EXTRACTING CHAT PLAYER NAME... MAYBE IT'S NOT A PLAYER MESSAGE ? LINE: %v", line)
39+
return "", "", "", "", fmt.Errorf("ERROR WHILE EXTRACTING CHAT PLAYER NAME FOR MINECRAFT")
40+
}
41+
playerName := matches[2]
42+
message := matches[3]
43+
44+
// Get player UUID and head URL for Minecraft
45+
playerUUID, err := services.GetMinecraftPlayerUUID(playerName)
46+
if err != nil {
47+
return "", "", "", "", fmt.Errorf("ERROR WHILE GETTING PLAYER UUID: %v", err)
48+
}
49+
50+
playerHeadURL, err := services.GetMinecraftPlayerHeadURL(playerUUID)
51+
if err != nil {
52+
return "", "", "", "", fmt.Errorf("ERROR WHILE GETTING PLAYER HEAD URL: %v", err)
4153
}
54+
55+
titleURL := "https://fr.namemc.com/profile/" + playerUUID
56+
return playerName, message, playerHeadURL, titleURL, nil
57+
}
58+
59+
// Define the functions for each game, here is Palworld
60+
func handlePalworldPlayerMessage(line string) (string, string, string, string, error) {
61+
playerChatRegex := regexp.MustCompile(`\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] \[CHAT\] <(.+?)> (.+)`)
62+
matches := playerChatRegex.FindStringSubmatch(line)
63+
if len(matches) < 3 {
64+
return "", "", "", "", fmt.Errorf("ERROR WHILE EXTRACTING CHAT PLAYER NAME FOR PALWORLD")
65+
}
66+
playerName := matches[1]
67+
message := matches[2]
68+
return playerName, message, "", "", nil
69+
}
70+
71+
// Create a map for game-specific actions
72+
var gameActionsMap = map[string]func(string) (string, string, string, string, error){
73+
"Minecraft": handleMinecraftPlayerMessage,
74+
"Palworld": handlePalworldPlayerMessage,
75+
}
76+
77+
// Action when a player message is detected
78+
func PlayerMessageAction(line string, serverID int) error {
4279
// Server infos
4380
server, err := db.GetServerById(serverID)
4481
if err != nil {
4582
return fmt.Errorf("ERROR WHILE GETTING SERVER BY ID FOR PLAYER MESSAGE: %v", err)
4683
}
47-
// Action
48-
playerName := matches[2]
49-
message := matches[3]
5084

51-
playerUUID, err := services.GetMinecraftPlayerUUID(playerName) // Get player UUID
52-
if err != nil {
53-
return fmt.Errorf("ERROR WHILE GETTING PLAYER UUID: %v", err)
85+
// Get the appropriate game action function from the map
86+
actionFunc, exists := gameActionsMap[server.Jeu]
87+
if !exists {
88+
return fmt.Errorf("ERROR: SERVER GAME %v IS NOT SUPPORTED", server.Jeu)
5489
}
5590

56-
playerHeadURL, err := services.GetMinecraftPlayerHeadURL(playerUUID) // Get player head URL
91+
// Call the specific action function for the game
92+
playerName, message, playerHeadURL, titleURL, err := actionFunc(line)
5793
if err != nil {
58-
return fmt.Errorf("ERROR WHILE GETTING PLAYER HEAD URL: %v", err)
94+
return err
5995
}
6096

97+
// Bot config
98+
botName := "mineotterBot" // Can be extended similarly using the mappage if needed
99+
100+
// Send the Discord embed message
61101
embed := models.EmbedConfig{
62102
Title: playerName,
63-
TitleURL: "https://fr.namemc.com/profile/" + playerUUID,
103+
TitleURL: titleURL,
64104
Description: message,
65105
Color: server.EmbedColor,
66106
Thumbnail: playerHeadURL,
67-
MainImage: "",
68107
Footer: "Message venant de " + server.Nom,
69-
Author: "",
70-
AuthorIcon: "",
71-
Timestamp: false,
72108
}
73-
err = discord.SendDiscordEmbedWithModel(config.AppConfig.Bots["mineotterBot"], config.AppConfig.DiscordChannels.MinecraftChatChannelID, embed)
109+
110+
err = discord.SendDiscordEmbedWithModel(config.AppConfig.Bots[botName], config.AppConfig.DiscordChannels.MinecraftChatChannelID, embed)
74111
if err != nil {
75112
return fmt.Errorf("ERROR WHILE SENDING DISCORD EMBED: %v", err)
76113
}
77114
return nil
78115
}
79116

80-
// Action when a player joined the server
81-
func PlayerJoinedAction(line string, serverID int) error {
82-
// Player name
117+
// Define the functions for each game, here is Minecraft
118+
func handleMinecraftPlayerJoined(line string) (string, error) {
83119
playerJoinedRegex := regexp.MustCompile(`\[(\d{2}:\d{2}:\d{2})\] \[Server thread/INFO](?: \[.+?/MinecraftServer])?: (.+) joined the game`)
84120
matches := playerJoinedRegex.FindStringSubmatch(line)
85121
if len(matches) < 3 {
86-
return fmt.Errorf("ERROR WHILE EXTRACTING JOINED PLAYER NAME")
122+
return "", fmt.Errorf("ERROR WHILE EXTRACTING JOINED PLAYER NAME FOR MINECRAFT SERVER")
123+
}
124+
return matches[2], nil
125+
}
126+
127+
// Define the functions for each game, here is Palworld
128+
func handlePalworldPlayerJoined(line string) (string, error) {
129+
playerJoinedRegex := regexp.MustCompile(`\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] \[LOG\] (.+?) \d{1,3}(?:\.\d{1,3}){3} connected the server`)
130+
matches := playerJoinedRegex.FindStringSubmatch(line)
131+
if len(matches) < 2 {
132+
return "", fmt.Errorf("ERROR WHILE EXTRACTING JOINED PLAYER NAME FOR PALWORLD SERVER")
87133
}
134+
return matches[1], nil
135+
}
136+
137+
// Create a map for game-specific actions for joined and left actions
138+
var gameJoinActionsMap = map[string]func(string) (string, error){
139+
"Minecraft": handleMinecraftPlayerJoined,
140+
"Palworld": handlePalworldPlayerJoined,
141+
}
142+
143+
// Action when a player joined the server
144+
func PlayerJoinedAction(line string, serverID int) error {
88145
// Server infos
89146
server, err := db.GetServerById(serverID)
90147
if err != nil {
91-
return fmt.Errorf("ERROR WHILE GETTING SERVER BY ID FOR MINECRAFT SERVER STOPPED: %v", err)
148+
return fmt.Errorf("ERROR WHILE GETTING SERVER BY ID FOR PLAYER JOINED: %v", err)
92149
}
93-
// Action
94-
discord.SendDiscordEmbed(config.AppConfig.Bots["mineotterBot"], config.AppConfig.DiscordChannels.MinecraftChatChannelID, matches[2]+" à rejoint "+server.Nom, "", server.EmbedColor)
95-
playerID, err := db.CheckAndInsertPlayerWithPlayerName(matches[2], 1, "now")
150+
151+
// Get the appropriate game action function from the map for "joined" action
152+
actionFunc, exists := gameJoinActionsMap[server.Jeu]
153+
if !exists {
154+
return fmt.Errorf("ERROR: SERVER GAME %v IS NOT SUPPORTED", server.Jeu)
155+
}
156+
157+
// Call the specific action function for the game
158+
playerName, err := actionFunc(line)
159+
if err != nil {
160+
return err
161+
}
162+
163+
// Bot config
164+
var botName string
165+
if server.Jeu == "Minecraft" {
166+
botName = "mineotterBot"
167+
} else {
168+
botName = "multiloutreBot"
169+
}
170+
171+
// Send the Discord embed message
172+
discord.SendDiscordEmbed(config.AppConfig.Bots[botName], config.AppConfig.DiscordChannels.MinecraftChatChannelID, playerName+" a rejoint "+server.Nom, "", server.EmbedColor)
173+
174+
// Handle player connection log in DB
175+
playerID, err := db.CheckAndInsertPlayerWithPlayerName(playerName, 1, "now")
96176
if err != nil {
97177
return fmt.Errorf("ERROR WHILE CHECKING OR INSERTING PLAYER: %v", err)
98178
}
179+
99180
err = db.SaveConnectionLog(playerID, serverID)
100181
if err != nil {
101-
return fmt.Errorf("ERROR WHILE SAVING CONNECTION LOG: FOR PLAYER %v IN DATABASE: %v", matches[2], err)
182+
return fmt.Errorf("ERROR WHILE SAVING CONNECTION LOG: FOR PLAYER %v IN DATABASE: %v", playerName, err)
102183
}
184+
103185
err = db.UpdatePlayerLastConnection(playerID)
104186
if err != nil {
105-
return fmt.Errorf("ERROR WHILE UPDATING LAST CONNECTION FOR PLAYER %v IN DATABASE: %v", matches[2], err)
187+
return fmt.Errorf("ERROR WHILE UPDATING LAST CONNECTION FOR PLAYER %v IN DATABASE: %v", playerName, err)
106188
}
107-
WriteToLogFile("/var/log/serversentinel/playerjoined.log", matches[2])
189+
190+
// Log to file
191+
WriteToLogFile("/var/log/serversentinel/playerjoined.log", playerName)
192+
108193
return nil
109194
}
110195

111-
// Action when a player left the server
112-
func PlayerLeftAction(line string, serverID int) error {
113-
// Player name
196+
// Define the functions for each game, here is Minecraft
197+
func handleMinecraftPlayerLeft(line string) (string, error) {
114198
playerDisconnectedRegex := regexp.MustCompile(`\[\d{2}:\d{2}:\d{2}\] \[Server thread/INFO\].*?: ([^\s]+) (?:left the game|disconnected|lost connection)`)
115199
matches := playerDisconnectedRegex.FindStringSubmatch(line)
116200
if len(matches) < 2 || len(matches[1]) < 3 { // Minecraft player names are at least 3 characters long, so this filter prevents false positives
117-
return fmt.Errorf("ERROR WHILE EXTRACTING DISCONNECTED PLAYER NAME")
201+
return "", fmt.Errorf("ERROR WHILE EXTRACTING DISCONNECTED PLAYER NAME FOR MINECRAFT SERVER")
118202
}
203+
return matches[1], nil
204+
}
205+
206+
// Define the functions for each game, here is Palworld
207+
func handlePalworldPlayerLeft(line string) (string, error) {
208+
playerDisconnectedRegex := regexp.MustCompile(`\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] \[LOG\] (.+?) left the server`)
209+
matches := playerDisconnectedRegex.FindStringSubmatch(line)
210+
if len(matches) < 2 {
211+
return "", fmt.Errorf("ERROR WHILE EXTRACTING LEFT PLAYER NAME FOR PALWORLD SERVER")
212+
}
213+
return matches[1], nil
214+
}
215+
216+
// Create a map for game-specific actions for joined and left actions
217+
var gameLeaveActionsMap = map[string]func(string) (string, error){
218+
"Minecraft": handleMinecraftPlayerLeft,
219+
"Palworld": handlePalworldPlayerLeft,
220+
}
221+
222+
// Action when a player left the server
223+
func PlayerLeftAction(line string, serverID int) error {
119224
// Server infos
120225
server, err := db.GetServerById(serverID)
121226
if err != nil {
122-
return fmt.Errorf("ERROR WHILE GETTING SERVER BY ID FOR MINECRAFT SERVER STOPPED: %v", err)
227+
return fmt.Errorf("ERROR WHILE GETTING SERVER BY ID FOR PLAYER LEFT: %v", err)
228+
}
229+
230+
// Get the appropriate game action function from the map for "left" action
231+
actionFunc, exists := gameLeaveActionsMap[server.Jeu]
232+
if !exists {
233+
return fmt.Errorf("ERROR: SERVER GAME %v IS NOT SUPPORTED", server.Jeu)
234+
}
235+
236+
// Call the specific action function for the game
237+
playerName, err := actionFunc(line)
238+
if err != nil {
239+
return err
123240
}
124-
// Action
125-
discord.SendDiscordEmbed(config.AppConfig.Bots["mineotterBot"], config.AppConfig.DiscordChannels.MinecraftChatChannelID, matches[1]+" à quitté "+server.Nom, "", server.EmbedColor)
126-
WriteToLogFile("/var/log/serversentinel/playerdisconnected.log", matches[1])
241+
242+
// Bot config
243+
var botName string
244+
if server.Jeu == "Minecraft" {
245+
botName = "mineotterBot"
246+
} else {
247+
botName = "multiloutreBot"
248+
}
249+
250+
// Send the Discord embed message
251+
discord.SendDiscordEmbed(config.AppConfig.Bots[botName], config.AppConfig.DiscordChannels.MinecraftChatChannelID, playerName+" a quitté "+server.Nom, "", server.EmbedColor)
252+
253+
// Log to file
254+
WriteToLogFile("/var/log/serversentinel/playerdisconnected.log", playerName)
255+
127256
return nil
128257
}

internal/triggers/triggers.go

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ func GetTriggers(selectedTriggers []string) []models.Trigger {
2727
fmt.Println("Example trigger action executed")
2828
},
2929
},
30+
{
31+
// This trigger is used to detect when a player sends a message in any server chat
32+
Name: "PlayerChatInServer",
33+
Condition: func(line string) bool {
34+
return isPlayerMessage(line)
35+
},
36+
Action: func(line string, serverID int) {
37+
err := PlayerMessageAction(line, serverID)
38+
if err != nil {
39+
fmt.Println("ERROR WHILE PROCESSING PLAYER MESSAGE: " + err.Error())
40+
}
41+
},
42+
},
3043
{
3144
// This trigger is used to detect when a minecraft server is started
3245
Name: "MinecraftServerStarted",
@@ -47,19 +60,6 @@ func GetTriggers(selectedTriggers []string) []models.Trigger {
4760
discord.SendDiscordEmbed(config.AppConfig.Bots["mineotterBot"], config.AppConfig.DiscordChannels.MinecraftChatChannelID, server.Nom+" viens d'ouvrir !", "Connectez-vous !\nLe serveur "+server.Jeu+" est en ligne !", server.EmbedColor)
4861
},
4962
},
50-
{
51-
// This trigger is used to detect when a player sends a message in the Minecraft chat
52-
Name: "PlayerChatMinecraftServer",
53-
Condition: func(line string) bool {
54-
return isPlayerMessage(line)
55-
},
56-
Action: func(line string, serverID int) {
57-
err := PlayerMessageAction(line, serverID)
58-
if err != nil {
59-
fmt.Println("ERROR WHILE PROCESSING PLAYER MESSAGE: " + err.Error())
60-
}
61-
},
62-
},
6363
{
6464
// This trigger is used to detect when a player joins a Minecraft server
6565
Name: "PlayerJoinedMinecraftServer",
@@ -112,6 +112,39 @@ func GetTriggers(selectedTriggers []string) []models.Trigger {
112112
discord.SendDiscordEmbed(config.AppConfig.Bots["multiloutreBot"], config.AppConfig.DiscordChannels.PalworldChatChannelID, server.Nom+" viens d'ouvrir !", "Connectez-vous !\nLe serveur "+server.Jeu+" est en ligne !", server.EmbedColor)
113113
},
114114
},
115+
{
116+
// This trigger is used to detect when a player joins a Palworld server
117+
Name: "PlayerJoinedPalworldServer",
118+
Condition: func(line string) bool {
119+
if isPlayerMessage(line) {
120+
return false
121+
}
122+
match, _ := regexp.MatchString(`\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] \[LOG\] .*? \d{1,3}(\.\d{1,3}){3} connected the server\. \(User id: .*?\)`, line)
123+
return match
124+
},
125+
Action: func(line string, serverID int) {
126+
err := PlayerJoinedAction(line, serverID)
127+
if err != nil {
128+
fmt.Println("ERROR WHILE PROCESSING PLAYER JOINED: " + err.Error())
129+
}
130+
},
131+
},
132+
{
133+
// This trigger is used to detect when a player disconnects from a Palworld server
134+
Name: "PlayerDisconnectedPalworldServer",
135+
Condition: func(line string) bool {
136+
if isPlayerMessage(line) {
137+
return false
138+
}
139+
return strings.Contains(line, "left the server.")
140+
},
141+
Action: func(line string, serverID int) {
142+
err := PlayerLeftAction(line, serverID)
143+
if err != nil {
144+
fmt.Println("ERROR WHILE PROCESSING PLAYER DISCONNECTED: " + err.Error())
145+
}
146+
},
147+
},
115148
}
116149

117150
// If no specific triggers are requested, return all triggers

0 commit comments

Comments
 (0)