From d121f399ed31e27da0d32f48adbea667c4884ebb Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Thu, 21 May 2026 22:52:24 -0500 Subject: [PATCH] up --- pkg/models/servidor.go | 5 ++-- pkg/services/hostinger_service.go | 35 ++++++++++++++++++------- resources/views/servidor.html | 20 +++++++++----- resources/views/servidor_dashboard.html | 10 +++++++ rest/controllers/servidor_controller.go | 33 +++++++++++++++++------ 5 files changed, 77 insertions(+), 26 deletions(-) diff --git a/pkg/models/servidor.go b/pkg/models/servidor.go index f2a8581..b9189dd 100755 --- a/pkg/models/servidor.go +++ b/pkg/models/servidor.go @@ -27,8 +27,9 @@ type Servidor struct { AgentLastSeen *time.Time `json:"agent_last_seen" gorm:"column:agent_last_seen"` MetricasJson string `json:"metricas_json" gorm:"column:metricas_json;type:text"` // Integración Hostinger - HostingerVpsID *int `json:"hostinger_vps_id" gorm:"column:hostinger_vps_id"` - HostingerState string `json:"hostinger_state" gorm:"column:hostinger_state"` + HostingerVpsID *int `json:"hostinger_vps_id" gorm:"column:hostinger_vps_id"` + HostingerState string `json:"hostinger_state" gorm:"column:hostinger_state"` + HostingerSubscriptionID string `json:"hostinger_subscription_id" gorm:"column:hostinger_subscription_id"` } func (Servidor) TableName() string { diff --git a/pkg/services/hostinger_service.go b/pkg/services/hostinger_service.go index 6b35a77..2d6eace 100644 --- a/pkg/services/hostinger_service.go +++ b/pkg/services/hostinger_service.go @@ -111,16 +111,17 @@ type HostingerIPAddress struct { // HostingerVPS representa una máquina virtual VPS. type HostingerVPS struct { - ID int `json:"id"` - Hostname string `json:"hostname"` - State string `json:"state"` - Plan string `json:"plan"` - DataCenter string `json:"data_center"` - CPU int `json:"cpus"` - RAMBytes int64 `json:"memory"` - DiskBytes int64 `json:"disk"` - IPV4 []HostingerIPAddress `json:"ipv4"` - IPV6 []HostingerIPAddress `json:"ipv6"` + ID int `json:"id"` + Hostname string `json:"hostname"` + State string `json:"state"` + Plan string `json:"plan"` + DataCenter string `json:"data_center"` + CPU int `json:"cpus"` + RAMBytes int64 `json:"memory"` + DiskBytes int64 `json:"disk"` + IPV4 []HostingerIPAddress `json:"ipv4"` + IPV6 []HostingerIPAddress `json:"ipv6"` + SubscriptionID string `json:"subscription_id"` } // HostingerDomain representa un dominio en el portafolio. @@ -303,6 +304,20 @@ func (c *HostingerClient) GetDomainNameServers(domain string) (*HostingerNameSer return &resp.NameServers, nil } +// GetSubscriptionByID obtiene una suscripción de billing por su ID. +func (c *HostingerClient) GetSubscriptionByID(subID string) (*HostingerSubscription, error) { + path := fmt.Sprintf("/billing/v1/subscriptions/%s", subID) + body, err := c.getRaw(context.Background(), path) + if err != nil { + return nil, err + } + var sub HostingerSubscription + if err := json.Unmarshal(body, &sub); err != nil { + return nil, fmt.Errorf("hostinger: no se pudo interpretar suscripción: %w", err) + } + return &sub, nil +} + // GetOrders obtiene las suscripciones de facturación. func (c *HostingerClient) GetOrders() ([]HostingerSubscription, error) { body, err := c.getRaw(context.Background(), "/billing/v1/subscriptions") diff --git a/resources/views/servidor.html b/resources/views/servidor.html index 264cf5f..2545bc0 100755 --- a/resources/views/servidor.html +++ b/resources/views/servidor.html @@ -275,15 +275,21 @@ -
🔗 Hostinger VPS
++ ID: + + Sub: + +
+📡 Último Ping
diff --git a/rest/controllers/servidor_controller.go b/rest/controllers/servidor_controller.go index bfe4787..9736426 100755 --- a/rest/controllers/servidor_controller.go +++ b/rest/controllers/servidor_controller.go @@ -232,14 +232,31 @@ func SyncServidorFromHostinger(c *fiber.Ctx) error { updates["disco"] = fmt.Sprintf("%d GB", vps.DiskBytes) } - // Vencimiento: buscar suscripción cuyo nombre contenga el hostname del VPS - if subs, sErr := client.GetOrders(); sErr == nil { - for _, sub := range subs { - if sub.ExpiresAt != "" && len(sub.ExpiresAt) >= 10 && - (strings.Contains(strings.ToLower(sub.Name), strings.ToLower(vps.Hostname)) || - strings.Contains(strings.ToLower(sub.Name), "vps")) { - updates["vencimiento"] = sub.ExpiresAt[:10] - break + // Vencimiento: resolución en cascada + // 1) subscription_id que viene directo del VPS (el más confiable) + // 2) subscription_id ya guardado en el servidor local + // 3) fallback fuzzy por nombre + subID := vps.SubscriptionID + if subID == "" && servidor.HostingerSubscriptionID != "" { + subID = servidor.HostingerSubscriptionID + } + + if subID != "" { + // Lookup directo — sin ambigüedad + if sub, sErr := client.GetSubscriptionByID(subID); sErr == nil && sub.ExpiresAt != "" && len(sub.ExpiresAt) >= 10 { + updates["vencimiento"] = sub.ExpiresAt[:10] + updates["hostinger_subscription_id"] = subID + } + } else { + // Fallback: buscar por nombre si aún no tenemos subscription_id + if subs, sErr := client.GetOrders(); sErr == nil { + for _, sub := range subs { + if sub.ExpiresAt != "" && len(sub.ExpiresAt) >= 10 && + strings.Contains(strings.ToLower(sub.Name), strings.ToLower(vps.Hostname)) { + updates["vencimiento"] = sub.ExpiresAt[:10] + updates["hostinger_subscription_id"] = sub.ID + break + } } } }