diff --git a/rest/controllers/hostinger_controller.go b/rest/controllers/hostinger_controller.go index 226fe57..445cec6 100644 --- a/rest/controllers/hostinger_controller.go +++ b/rest/controllers/hostinger_controller.go @@ -1,9 +1,11 @@ package controllers import ( + "fmt" "time" "github.com/gofiber/fiber/v2" + "github.com/sujit-baniya/fiber-boilerplate/app" "github.com/sujit-baniya/fiber-boilerplate/pkg/models" "github.com/sujit-baniya/fiber-boilerplate/pkg/services" ) @@ -63,7 +65,8 @@ func hostingerClient() (*services.HostingerClient, error) { // ─── Endpoints de datos ─────────────────────────────────────────────────────── -// GetHostingerVPS devuelve la lista de VPS/VMs. +// GetHostingerVPS devuelve la lista de VPS/VMs y actualiza automáticamente +// los servidores vinculados (IP, RAM, CPU, disco, estado, vencimiento). func GetHostingerVPS(c *fiber.Ctx) error { client, err := hostingerClient() if err != nil { @@ -75,6 +78,8 @@ func GetHostingerVPS(c *fiber.Ctx) error { if err != nil { return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{"error": err.Error()}) } + // Auto-sync: actualizar servidores vinculados por hostinger_vps_id + go syncServidoresFromVPSList(client, data) return c.JSON(fiber.Map{"data": data}) } @@ -114,7 +119,8 @@ func GetHostingerDNS(c *fiber.Ctx) error { return c.JSON(fiber.Map{"data": records, "name_servers": ns, "domain": domain}) } -// GetHostingerOrders devuelve las órdenes de facturación. +// GetHostingerOrders devuelve las órdenes de facturación y actualiza +// automáticamente el vencimiento de los servidores vinculados. func GetHostingerOrders(c *fiber.Ctx) error { client, err := hostingerClient() if err != nil { @@ -126,6 +132,8 @@ func GetHostingerOrders(c *fiber.Ctx) error { if err != nil { return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{"error": err.Error()}) } + // Auto-sync: actualizar vencimiento de servidores que ya tienen subscription_id vinculado + go syncVencimientoFromOrders(data) return c.JSON(fiber.Map{"data": data}) } @@ -384,3 +392,97 @@ func hostingerAutoRenewalToggle(c *fiber.Ctx, enable bool) error { return c.JSON(fiber.Map{"data": sub}) } +// ─── Auto-sync background ──────────────────────────────────────────────────── + +// syncVencimientoFromOrders actualiza el campo vencimiento de todos los servidores +// que tienen hostinger_subscription_id vinculado, usando los datos de billing ya +// descargados (sin llamadas adicionales a la API). +func syncVencimientoFromOrders(orders []services.HostingerSubscription) { + db := app.Http.Database.DB + + // Indexar suscripciones por ID para búsqueda O(1) + subMap := make(map[string]services.HostingerSubscription, len(orders)) + for _, sub := range orders { + subMap[sub.ID] = sub + } + + var servidores []models.Servidor + db.Where("hostinger_subscription_id != '' AND hostinger_subscription_id IS NOT NULL").Find(&servidores) + + for _, srv := range servidores { + sub, ok := subMap[srv.HostingerSubscriptionID] + if !ok { + continue + } + venc := sub.ExpiresAt + if venc == "" { + venc = sub.NextBillingAt + } + if venc == "" || len(venc) < 10 { + continue + } + db.Model(&models.Servidor{}).Where("id = ?", srv.ID).Update("vencimiento", venc[:10]) + } +} + +// syncServidoresFromVPSList actualiza specs y vencimiento de todos los servidores +// que tienen hostinger_vps_id vinculado, usando la lista de VPS ya descargada. +// El vencimiento se obtiene con una llamada al billing de cada VPS (por subscription_id). +func syncServidoresFromVPSList(client *services.HostingerClient, vpsList []services.HostingerVPS) { + db := app.Http.Database.DB + + // Indexar VPS por ID + vpsMap := make(map[int]services.HostingerVPS, len(vpsList)) + for _, vps := range vpsList { + vpsMap[vps.ID] = vps + } + + var servidores []models.Servidor + db.Where("hostinger_vps_id IS NOT NULL").Find(&servidores) + + for _, srv := range servidores { + if srv.HostingerVpsID == nil { + continue + } + vps, ok := vpsMap[*srv.HostingerVpsID] + if !ok { + continue + } + + updates := map[string]interface{}{ + "hostinger_state": vps.State, + } + if len(vps.IPV4) > 0 && vps.IPV4[0].Address != "" { + updates["ip_servidor"] = vps.IPV4[0].Address + } + if vps.RAMBytes > 0 { + updates["ram"] = fmt.Sprintf("%.0f GB", float64(vps.RAMBytes)/1024.0) + } + if vps.CPU > 0 { + updates["nucleos"] = fmt.Sprintf("%d", vps.CPU) + } + if vps.DiskBytes > 0 { + updates["disco"] = fmt.Sprintf("%d GB", vps.DiskBytes/1024) + } + + // Vencimiento: usar subscription_id del VPS o el ya guardado + subID := vps.SubscriptionID + if subID == "" { + subID = srv.HostingerSubscriptionID + } + if subID != "" { + if sub, err := client.GetSubscriptionByID(subID); err == nil { + venc := sub.ExpiresAt + if venc == "" { + venc = sub.NextBillingAt + } + if venc != "" && len(venc) >= 10 { + updates["vencimiento"] = venc[:10] + } + updates["hostinger_subscription_id"] = subID + } + } + + db.Model(&models.Servidor{}).Where("id = ?", srv.ID).Updates(updates) + } +}