178 lines
4.7 KiB
Go
178 lines
4.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/gofiber/fiber/v2/middleware/logger"
|
|
"github.com/gofiber/template/django/v3"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
var mongoClient *mongo.Client
|
|
|
|
type Message struct {
|
|
ID primitive.ObjectID `bson:"_id"`
|
|
Content string `bson:"message"`
|
|
Role string `bson:"role"`
|
|
Date time.Time `bson:"date"`
|
|
}
|
|
|
|
type Conversation struct {
|
|
ID string
|
|
Messages []Message
|
|
}
|
|
|
|
func connectToMongoDB(uri string) {
|
|
serverAPI := options.ServerAPI(options.ServerAPIVersion1)
|
|
opts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPI)
|
|
client, err := mongo.Connect(context.TODO(), opts)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
mongoClient = client
|
|
|
|
if err := mongoClient.Ping(context.TODO(), nil); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
// Import HTML using django engine/template
|
|
engine := django.New("./templates", ".html")
|
|
|
|
// Create new Fiber instance. Can use any framework. I use fiber for speed and simplicity
|
|
app := fiber.New(fiber.Config{
|
|
Views: engine,
|
|
AppName: "JADE 2.0",
|
|
EnablePrintRoutes: true,
|
|
})
|
|
|
|
// Initialize
|
|
go connectToMongoDB("mongodb://localhost:27017")
|
|
|
|
// Add default logger
|
|
app.Use(logger.New())
|
|
|
|
// Add static files
|
|
app.Static("/", "./static")
|
|
|
|
// Add routes
|
|
app.Get("/", indexHandler)
|
|
app.Get("/isMongoDBConnected", isMongoDBConnectedHandler)
|
|
|
|
app.Get("/chat", chatPageHandler)
|
|
app.Post("/chat", addMessageHandler)
|
|
app.Delete("/chat", deleteMessageHandler)
|
|
|
|
// Start server
|
|
app.Listen(":3000")
|
|
}
|
|
|
|
func indexHandler(c *fiber.Ctx) error {
|
|
return c.Render("welcome_page", fiber.Map{})
|
|
}
|
|
|
|
func chatPageHandler(c *fiber.Ctx) error {
|
|
return c.Render("chat/page", fiber.Map{})
|
|
}
|
|
|
|
func addMessageHandler(c *fiber.Ctx) error {
|
|
message := c.FormValue("message")
|
|
|
|
collection := mongoClient.Database("chat").Collection("messages")
|
|
collection.InsertOne(context.Background(), bson.M{"message": message, "role": "user", "date": time.Now()})
|
|
collection.InsertOne(context.Background(), bson.M{"message": "I did something!", "role": "bot", "date": time.Now()})
|
|
|
|
return generateChatHTML(c)
|
|
}
|
|
|
|
func deleteMessageHandler(c *fiber.Ctx) error {
|
|
messageId := c.FormValue("messageId")
|
|
|
|
// Convert the string ID to a MongoDB ObjectID
|
|
objID, err := primitive.ObjectIDFromHex(messageId)
|
|
if err != nil {
|
|
// If the conversion fails, return an error response
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
|
"error": "Invalid message ID format",
|
|
})
|
|
}
|
|
|
|
// Delete messages in the database. This one and all the following ones
|
|
collection := mongoClient.Database("chat").Collection("messages")
|
|
|
|
// Get the date of the message
|
|
var message Message
|
|
err = collection.FindOne(context.TODO(), bson.M{"_id": objID}).Decode(&message)
|
|
if err != nil {
|
|
if err == mongo.ErrNoDocuments {
|
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
|
|
"error": "Message not found",
|
|
})
|
|
}
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "Failed to find message",
|
|
})
|
|
}
|
|
|
|
// Delete the message and all messages with a date after the specified date
|
|
filter := bson.M{
|
|
"$or": []bson.M{
|
|
{"_id": objID},
|
|
{"date": bson.M{"$gt": message.Date}},
|
|
},
|
|
}
|
|
_, err = collection.DeleteMany(context.TODO(), filter)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "Failed to delete messages",
|
|
})
|
|
}
|
|
|
|
return c.SendString("") // TODO Main loog that return the all chat
|
|
}
|
|
|
|
func generateChatHTML(c *fiber.Ctx) error {
|
|
// Get the messages from the database
|
|
collection := mongoClient.Database("chat").Collection("messages")
|
|
|
|
// Get all messages
|
|
cursor, err := collection.Find(context.TODO(), bson.D{})
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "Failed to find messages",
|
|
})
|
|
}
|
|
|
|
// Convert the cursor to an array of messages
|
|
var messages []Message
|
|
if err = cursor.All(context.TODO(), &messages); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
|
"error": "Failed to convert cursor to array",
|
|
})
|
|
}
|
|
|
|
// Print messages
|
|
for _, message := range messages {
|
|
log.Println(message)
|
|
}
|
|
|
|
// Render the HTML template with the messages
|
|
return c.Render("chat/messages", fiber.Map{
|
|
"messages": messages,
|
|
})
|
|
}
|
|
|
|
func isMongoDBConnectedHandler(c *fiber.Ctx) error {
|
|
if mongoClient != nil {
|
|
return c.SendString("<h1>Connected</h1>")
|
|
}
|
|
return c.SendString("<h1 id='isMongoDBConnected' hx-get='/isMongoDBConnected' hx-trigger='every 1s' hx-swap='outerHTM'>Not connected</h1>")
|
|
}
|