diff options
| author | soler_j <soler_j@etna-alternance.net> | 2025-04-29 03:07:48 +0200 | 
|---|---|---|
| committer | soler_j <soler_j@etna-alternance.net> | 2025-04-29 03:07:48 +0200 | 
| commit | 2a58d43c3b820eb8ffec01bb51905146a7278533 (patch) | |
| tree | d05b0b815aee8520ae1375b69a503511f7b260fa /app | |
| parent | 0c53f3e452830b300c598c9370946ae54f443a78 (diff) | |
Ajout de la prise en charge de ZeroMQ dans le bot, mise à jour des dépendances et réorganisation du Dockerfile. Suppression de l'implémentation de serveur Unix obsolète et amélioration de la gestion des messages.
Diffstat (limited to 'app')
| -rw-r--r-- | app/cmd/main.go | 55 | ||||
| -rw-r--r-- | app/go.mod | 5 | ||||
| -rw-r--r-- | app/go.sum | 4 | ||||
| -rw-r--r-- | app/internal/create_bot.go | 74 | 
4 files changed, 95 insertions, 43 deletions
diff --git a/app/cmd/main.go b/app/cmd/main.go index 14980b7..87212ef 100644 --- a/app/cmd/main.go +++ b/app/cmd/main.go @@ -2,7 +2,6 @@ package main  import (  	"encoding/json" -	"fmt"  	"log"  	"net/http"  	"os" @@ -10,6 +9,7 @@ import (  	"syscall"  	"github.com/ketsuna-org/bot-creator-api/internal" +	zmq "github.com/pebbe/zmq4"  )  func init() { @@ -23,18 +23,33 @@ func main() {  	mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {  		w.Write([]byte("Hello, World!"))  	}) -	botId := "xxxxx" -	botToken := "xxxxx" +	botToken := "XXXXXXXXXXXX" // Replace with your bot token + +	ctx, err := zmq.NewContext() +	if err != nil { +		log.Fatalf("[SERVER] Failed to create context: %v", err) +	} +	defer ctx.Term() + +	dealer, err := ctx.NewSocket(zmq.REP) +	if err != nil { +		log.Fatalf("[SERVER] Failed to create dealer: %v", err) +	} +	defer dealer.Close() + +	err = dealer.Bind("tcp://*:5555") +	if err != nil { +		log.Fatalf("[SERVER] Failed to bind dealer: %v", err) +	}  	bot := &internal.Bot{ -		BotID:    botId,  		BotToken: botToken,  	} -	conn, err := internal.Start(bot) + +	bot, err = internal.Start(bot, dealer)  	if err != nil { -		log.Fatalf("Error starting bot: %v", err) +		log.Fatalf("[SERVER] Error starting bot: %v", err)  	} -	defer conn.Close()  	// Handle the bot connection  	data, err := json.Marshal(map[string]interface{}{  		"command": "update", @@ -45,10 +60,22 @@ func main() {  		},  	})  	if err != nil { -		log.Fatalf("Error marshaling JSON: %v", err) +		log.Fatalf("[SERVER] Error marshaling JSON: %v", err)  	} -	conn.Write(data) +	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 !", +			}, +		}, +	}) +	if err != nil { +		log.Fatalf("[SERVER] Error marshaling JSON: %v", err) +	} +	go bot.SendMessage(string(dataX))  	// Handle if signal is received  	signals := make(chan os.Signal, 1) @@ -60,18 +87,12 @@ func main() {  		// let's kill the bot  		if bot.Cmd != nil {  			if err := bot.Cmd.Process.Kill(); err != nil { -				log.Printf("Error killing bot process: %v", err) +				log.Printf("[SERVER] Error killing bot process: %v", err)  			} else { -				log.Printf("Bot process killed successfully") +				log.Printf("[SERVER] Bot process killed successfully")  			}  		}  		// let's remove the socket -		socketPath := fmt.Sprintf("/tmp/%s.sock", bot.BotID) -		if err := os.RemoveAll(socketPath); err != nil { -			log.Printf("Error removing socket: %v", err) -		} else { -			log.Printf("Socket removed successfully") -		}  		os.Exit(0)  	}()  	panic(http.ListenAndServe(":2030", mux)) @@ -2,4 +2,7 @@ module github.com/ketsuna-org/bot-creator-api  go 1.23.3 -require github.com/arangodb/go-driver/v2 v2.1.3 // indirect +require ( +	github.com/arangodb/go-driver/v2 v2.1.3 // indirect +	github.com/pebbe/zmq4 v1.3.1 // indirect +) @@ -1,2 +1,6 @@  github.com/arangodb/go-driver/v2 v2.1.3 h1:PpLSe8E2RalFuqTGi2yfHDe3ltOomfFCIToB66p1lr8=  github.com/arangodb/go-driver/v2 v2.1.3/go.mod h1:aoDzrsO7PQEFat3Q9pp4zfv6W+WotA7GcCeJQJfX+tc= +github.com/pebbe/zmq4 v1.3.1 h1:WmGnjErIFjb43M6hq5nB/g9cUx9YQAXurAwfZV2Cgeo= +github.com/pebbe/zmq4 v1.3.1/go.mod h1:nqnPueOapVhE2wItZ0uOErngczsJdLOGkebMxaO8r48= +gopkg.in/zeromq/goczmq.v4 v4.1.0 h1:CE+FE81mGVs2aSlnbfLuS1oAwdcVywyMM2AC1g33imI= +gopkg.in/zeromq/goczmq.v4 v4.1.0/go.mod h1:h4IlfePEYMpFdywGr5gAwKhBBj+hiBl/nF4VoSE4k+0= diff --git a/app/internal/create_bot.go b/app/internal/create_bot.go index 7f9aa15..4bbe5ae 100644 --- a/app/internal/create_bot.go +++ b/app/internal/create_bot.go @@ -2,30 +2,26 @@ package internal  import (  	"fmt" -	"net" +	"log"  	"os"  	"os/exec"  	"syscall" -	"time" + +	zmq "github.com/pebbe/zmq4"  )  type Bot struct { -	BotID     string    `json:"bot_id"`  	BotToken  string    `json:"bot_token"`  	Cmd       *exec.Cmd // Ajouter une référence à la commande -	processID int       // Stocker le PGID (Process Group ID) +	processID int +	dealer    *zmq.Socket // Stocker le PGID (Process Group ID) +	read      bool  } -func Start(b *Bot) (net.Conn, error) { -	socketPath := fmt.Sprintf("/tmp/%s.sock", b.BotID) - -	// Nettoyage préalable du socket -	if err := os.RemoveAll(socketPath); err != nil && !os.IsNotExist(err) { -		return nil, fmt.Errorf("error cleaning socket: %w", err) -	} +func Start(b *Bot, dealer *zmq.Socket) (*Bot, error) {  	// Configuration du bot -	cmd := exec.Command("./bot/build/discord-bot", b.BotToken) +	cmd := exec.Command("../bot/build/discord-bot", b.BotToken)  	cmd.SysProcAttr = &syscall.SysProcAttr{  		Setpgid: true, // Permet de kill le processus enfant si nécessaire  	} @@ -39,23 +35,51 @@ func Start(b *Bot) (net.Conn, error) {  	}  	b.Cmd = cmd  	b.processID = cmd.Process.Pid - -	// Mécanisme d'attente intelligente pour le socket -	var conn net.Conn -	maxRetries := 10 -	for i := 0; i < maxRetries; i++ { -		var err error -		conn, err = net.Dial("unix", socketPath) -		if err == nil { +	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  		} -		time.Sleep(500 * time.Millisecond) +	} +	return b, nil +} + +func (b *Bot) Stop() error { +	if b.Cmd != nil && b.processID != 0 { +		if err := syscall.Kill(-b.processID, syscall.SIGTERM); err != nil { +			return fmt.Errorf("[SERVER] failed to stop bot: %w", err) +		} +	} +	return nil +} + +func (b *Bot) SendMessage(message string) error { +	if b.dealer == nil { +		return fmt.Errorf("[SERVER] sender socket is not initialized") +	} +	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 !  	} -	if conn == nil { -		return nil, fmt.Errorf("failed to connect to bot socket after %d attempts", maxRetries) +	_, err := b.dealer.Send(message, 0) +	if err != nil { +		return fmt.Errorf("[SERVER] failed to send message: %w", err)  	} +	log.Printf("[SERVER] sent message: %s", message) -	fmt.Printf("Bot %s started successfully\n", b.BotID) -	return conn, nil +	b.read = false +	return nil  }  | 
