summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsoler_j <soler_j@etna-alternance.net>2025-04-29 03:57:44 +0200
committersoler_j <soler_j@etna-alternance.net>2025-04-29 03:57:44 +0200
commit6ccd5f23c68bf6d8eb212e4c0cb3b887fff993a8 (patch)
tree04ce0804bb914764751c5c5fc278282267368760
parente3a3437f65b4470b8042a37ccd48f399b250a77b (diff)
Implement multiple code changes for optimization and refactoring
-rw-r--r--Dockerfile19
-rw-r--r--app/cmd/main.go132
-rwxr-xr-xapp/discord-botbin0 -> 425120 bytes
-rw-r--r--app/internal/create_bot.go53
-rw-r--r--devenv.nix2
5 files changed, 134 insertions, 72 deletions
diff --git a/Dockerfile b/Dockerfile
index 804cd4b..a8e9c9c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -55,17 +55,24 @@ FROM ubuntu:24.04
WORKDIR /app
# Install runtime deps
-RUN apt-get update && apt-get install -y libssl3 zlib1g libopus0 && apt-get clean
-
+RUN apt-get update && apt-get install -y \
+ libssl3 \
+ zlib1g \
+ libopus0 \
+ libsodium23 \
+ libzmq5 \
+ && apt-get clean
# Copie des binaires
-COPY --from=go-builder /api ./api
-COPY --from=cpp-builder /src/build/discord-bot ./bot/build/discord-bot
+COPY --from=go-builder /api/app ./app
+COPY --from=cpp-builder /src/build/discord-bot ./discord-bot
COPY --from=cpp-builder /usr/local/lib/ /usr/local/lib/
# Make sure executables are runnable
-RUN chmod +x ./api/app ./bot/build/discord-bot
+RUN chmod +x ./app ./discord-bot
# Pour être sûr que libdpp.so soit trouvée
ENV LD_LIBRARY_PATH=/usr/local/lib
-ENTRYPOINT ["./api/app"]
+EXPOSE 2030
+
+ENTRYPOINT ["./app"]
diff --git a/app/cmd/main.go b/app/cmd/main.go
index 87212ef..7d8ffa0 100644
--- a/app/cmd/main.go
+++ b/app/cmd/main.go
@@ -12,25 +12,30 @@ import (
zmq "github.com/pebbe/zmq4"
)
+var botList = make(map[string]*internal.Bot)
+
func init() {
- // Initialize the application
+ // Initialisation de l'application
}
func main() {
+ // Créer un ServeMux
mux := http.NewServeMux()
- // Start the application
- mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
+
+ // Route principale
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
})
- botToken := "XXXXXXXXXXXX" // Replace with your bot token
+ // Contexte ZeroMQ
ctx, err := zmq.NewContext()
if err != nil {
log.Fatalf("[SERVER] Failed to create context: %v", err)
}
defer ctx.Term()
+ // Socket dealer ZeroMQ
dealer, err := ctx.NewSocket(zmq.REP)
if err != nil {
log.Fatalf("[SERVER] Failed to create dealer: %v", err)
@@ -42,58 +47,97 @@ func main() {
log.Fatalf("[SERVER] Failed to bind dealer: %v", err)
}
- bot := &internal.Bot{
- BotToken: botToken,
- }
+ // Route POST /create/{bot_token}
+ mux.HandleFunc("POST /create/{bot_token}", func(w http.ResponseWriter, r *http.Request) {
+ // Extraire le token du bot de l'URL
+ botToken := r.URL.Query().Get("bot_token")
- bot, err = internal.Start(bot, dealer)
- if err != nil {
- log.Fatalf("[SERVER] Error starting bot: %v", err)
- }
- // Handle the bot connection
- data, err := json.Marshal(map[string]interface{}{
- "command": "update",
- "data": map[string]interface{}{
- "ping": map[string]string{
- "response": "pong ((userName))",
- },
- },
+ bot := &internal.Bot{
+ BotToken: botToken,
+ }
+ bot, err := internal.Start(bot, dealer)
+ if err != nil {
+ log.Printf("[SERVER] Error starting bot: %v", err)
+ http.Error(w, "Error starting bot", http.StatusInternalServerError)
+ return
+ }
+ botList[botToken] = bot
+ log.Printf("[SERVER] Bot started successfully")
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte("Bot started successfully"))
})
- if err != nil {
- log.Fatalf("[SERVER] Error marshaling JSON: %v", err)
- }
- go bot.SendMessage(string(data))
-
- dataX, err := json.Marshal(map[string]interface{}{
- "command": "update",
- "data": map[string]interface{}{
- "ping": map[string]string{
- "response": "pong ((userName)) avec une modif !",
- },
- },
+
+ // Route POST /stop/{bot_token}
+ mux.HandleFunc("POST /stop/{bot_token}", func(w http.ResponseWriter, r *http.Request) {
+ // Extraire le token du bot de l'URL
+ botToken := r.URL.Query().Get("bot_token")
+
+ bot, ok := botList[botToken]
+ if !ok {
+ http.Error(w, "Bot not found", http.StatusNotFound)
+ return
+ }
+ if err := bot.Stop(); err != nil {
+ log.Printf("[SERVER] Error stopping bot: %v", err)
+ http.Error(w, "Error stopping bot", http.StatusInternalServerError)
+ return
+ }
+ delete(botList, botToken)
+ log.Printf("[SERVER] Bot stopped successfully")
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte("Bot stopped successfully"))
})
- if err != nil {
- log.Fatalf("[SERVER] Error marshaling JSON: %v", err)
- }
- go bot.SendMessage(string(dataX))
- // Handle if signal is received
+ // Route POST /update/{bot_token}
+ mux.HandleFunc("POST /update/{bot_token}", func(w http.ResponseWriter, r *http.Request) {
+ // Extraire le token du bot de l'URL
+ botToken := r.URL.Query().Get("bot_token")
+ bot, ok := botList[botToken]
+ if !ok {
+ http.Error(w, "Bot not found", http.StatusNotFound)
+ return
+ }
+ body := make(map[string]interface{})
+ if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
+ log.Printf("[SERVER] Error decoding JSON: %v", err)
+ http.Error(w, "Invalid JSON", http.StatusBadRequest)
+ return
+ }
+ data, err := json.Marshal(body)
+ if err != nil {
+ log.Printf("[SERVER] Error marshaling JSON: %v", err)
+ http.Error(w, "Error marshaling JSON", http.StatusInternalServerError)
+ return
+ }
+ if err := bot.SendMessage(string(data)); err != nil {
+ log.Printf("[SERVER] Error sending message: %v", err)
+ http.Error(w, "Error sending message", http.StatusInternalServerError)
+ return
+ }
+ log.Printf("[SERVER] Bot updated successfully")
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte("Bot updated successfully"))
+ })
+
+ // Gestion des signaux pour l'arrêt propre
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt)
signal.Notify(signals, syscall.SIGTERM)
go func() {
sig := <-signals
log.Printf("Received signal: %s", sig)
- // let's kill the bot
- if bot.Cmd != nil {
- if err := bot.Cmd.Process.Kill(); err != nil {
- log.Printf("[SERVER] Error killing bot process: %v", err)
- } else {
- log.Printf("[SERVER] Bot process killed successfully")
+ // Arrêter tous les bots en cours
+ for _, bot := range botList {
+ if err := bot.Stop(); err != nil {
+ log.Printf("[SERVER] Error stopping bot: %v", err)
}
+ delete(botList, bot.BotToken)
}
- // let's remove the socket
+ // Quitter l'application
os.Exit(0)
}()
- panic(http.ListenAndServe(":2030", mux))
+
+ // Démarrer le serveur HTTP
+ log.Printf("[SERVER] Starting server on :2030")
+ log.Fatal(http.ListenAndServe(":2030", mux))
}
diff --git a/app/discord-bot b/app/discord-bot
new file mode 100755
index 0000000..61a01e1
--- /dev/null
+++ b/app/discord-bot
Binary files differ
diff --git a/app/internal/create_bot.go b/app/internal/create_bot.go
index 4bbe5ae..0f47818 100644
--- a/app/internal/create_bot.go
+++ b/app/internal/create_bot.go
@@ -16,12 +16,13 @@ type Bot struct {
processID int
dealer *zmq.Socket // Stocker le PGID (Process Group ID)
read bool
+ readyChan chan bool // Canal pour indiquer que le bot est prêt
}
func Start(b *Bot, dealer *zmq.Socket) (*Bot, error) {
// Configuration du bot
- cmd := exec.Command("../bot/build/discord-bot", b.BotToken)
+ cmd := exec.Command("./discord-bot", b.BotToken)
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true, // Permet de kill le processus enfant si nécessaire
}
@@ -36,18 +37,27 @@ func Start(b *Bot, dealer *zmq.Socket) (*Bot, error) {
b.Cmd = cmd
b.processID = cmd.Process.Pid
b.dealer = dealer
- // Here we will receive messages from the bot in a separate goroutine
- for {
- msg, err := dealer.Recv(0)
- if err != nil {
- return nil, fmt.Errorf("[SERVER] failed to receive message: %w", err)
- }
- if msg == "ready" {
- log.Printf("[SERVER] Bot is ready")
- b.read = true
- break
+ b.readyChan = make(chan bool)
+
+ // Goroutine pour écouter les messages du bot
+ go func() {
+ // Boucle de réception des messages du bot via ZeroMQ
+ for {
+ msg, err := dealer.Recv(0)
+ if err != nil {
+ log.Printf("[SERVER] Failed to receive message from bot %s: %v", b.BotToken, err)
+ continue // Continue à recevoir les messages même si une erreur se produit
+ }
+
+ if msg == "ready" {
+ log.Printf("[SERVER] Bot %s is ready", b.BotToken)
+ b.read = true
+ b.readyChan <- true // Indiquer que le bot est prêt
+ break
+ }
}
- }
+ }()
+
return b, nil
}
@@ -56,6 +66,7 @@ func (b *Bot) Stop() error {
if err := syscall.Kill(-b.processID, syscall.SIGTERM); err != nil {
return fmt.Errorf("[SERVER] failed to stop bot: %w", err)
}
+ log.Printf("[SERVER] Bot %s stopped successfully", b.BotToken)
}
return nil
}
@@ -64,22 +75,20 @@ func (b *Bot) SendMessage(message string) error {
if b.dealer == nil {
return fmt.Errorf("[SERVER] sender socket is not initialized")
}
+
+ // Attendre que le bot soit prêt si ce n'est pas déjà fait
if !b.read {
- // Let's read the message before sending
- msg, err := b.dealer.Recv(0)
- if err != nil {
- return fmt.Errorf("[SERVER] failed to receive message: %w", err)
- }
- log.Printf("[SERVER] received message: %s", msg)
- b.read = true // Fix ici !
+ log.Printf("[SERVER] Waiting for bot %s to be ready...", b.BotToken)
+ <-b.readyChan // Attendre que le bot soit prêt
}
+ // Envoi du message
_, err := b.dealer.Send(message, 0)
if err != nil {
- return fmt.Errorf("[SERVER] failed to send message: %w", err)
+ return fmt.Errorf("[SERVER] failed to send message to bot %s: %w", b.BotToken, err)
}
- log.Printf("[SERVER] sent message: %s", message)
+ log.Printf("[SERVER] Sent message to bot %s: %s", b.BotToken, message)
- b.read = false
+ b.read = false // Réinitialiser l'état de lecture après l'envoi
return nil
}
diff --git a/devenv.nix b/devenv.nix
index 357702d..6744be6 100644
--- a/devenv.nix
+++ b/devenv.nix
@@ -48,6 +48,8 @@
'';
scripts.start.exec = ''
+ build
+ mv bot/build/discord-bot ./app
cd app
go run cmd/main.go
'';