package channel import ( "github.com/gochat/gochat/internal/model" ) // ChannelWhatsApp represents a WhatsApp Business channel configuration. // Reference: Chatwoot app/models/channel/whatsapp.rb // // Chatwoot's ChannelWhatsApp (Channel::Whatsapp) model attributes: // - account_id: FK to Account // - phone_number: WhatsApp phone number in international format // - phone_number_id: WhatsApp Business Phone Number ID (from Meta Business Manager) // - business_account_id: WhatsApp Business Account ID (WABA ID) // - provider: WhatsApp provider backend (whatsapp_cloud or 360dialog) // - message_templates: Cached WhatsApp message templates JSON // - template_namespace: WhatsApp template namespace (deprecated, retained for migration) // - provider_config: Provider-specific configuration JSON // - reauthorization_required: Flag when token/API connection fails // // Chatwoot lifecycle hooks: // - before_create :validate_provider_config (checks provider-specific setup) // - after_create :setup_webhook (registers webhook with provider) // - after_destroy :delete_webhook (removes webhook registration) // // gochat enhancements beyond Chatwoot: // - webhook_verify_token: Token for WhatsApp webhook verification (Cloud API hub.mode=subscribe) // - auto_create_contact: Whether to auto-create contacts from incoming messages // - provider_config stored as typed JSON rather than serialized hash // // WhatsApp supports two provider backends: // - whatsapp_cloud: Meta WhatsApp Business Cloud API (https://developers.facebook.com/docs/whatsapp/cloud-api) // - 360dialog: 360dialog WhatsApp Business API (https://docs.360dialog.com/docs/whatsapp-api) type ChannelWhatsApp struct { model.Base // ID, CreatedAt, UpdatedAt, DeletedAt (soft delete via GORM) // Account foreign key AccountID uint `gorm:"index;not null" json:"account_id"` // Inbox foreign key — links to the Inbox that wraps this channel InboxID uint `gorm:"not null;uniqueIndex" json:"inbox_id"` // WhatsApp phone number in international format (e.g., "+1234567890") PhoneNumber string `gorm:"size:50;not null;index" json:"phone_number"` // WhatsApp Business Phone Number ID — from Meta Business Manager or 360dialog dashboard // Used as the sender identifier in Cloud API calls PhoneNumberID string `gorm:"size:255" json:"phone_number_id"` // WhatsApp Business Account ID (WABA ID) — identifies the WhatsApp Business Account BusinessAccountID string `gorm:"size:255" json:"business_account_id"` // Display name of the WhatsApp Business account WhatsAppAccountName string `gorm:"size:255" json:"whatsapp_account_name"` // Access token for WhatsApp Business API (Cloud API or 360dialog API) // For Cloud API: permanent access token from Meta App dashboard // For 360dialog: API key from 360dialog hub AccessToken string `gorm:"size:512;not null" json:"access_token"` // WhatsApp provider backend — determines which API to use // Reference: model.WhatsAppProvider enum (whatsapp_cloud / 360dialog) Provider string `gorm:"size:50" json:"provider"` // Cached WhatsApp message templates (JSON blob) // Reference: Chatwoot caches templates locally for quick lookup MessageTemplates string `gorm:"type:text" json:"message_templates"` // Template namespace (deprecated by WhatsApp, retained for backward compatibility) TemplateNamespace string `gorm:"size:255" json:"template_namespace"` // Provider-specific configuration (JSON blob) // For 360dialog: { "api_key": "...", "namespace": "..." } // For Cloud API: { "app_id": "...", "webhook_verify_token": "..." } ProviderConfig string `gorm:"type:text" json:"provider_config"` // Webhook verify token — used during WhatsApp webhook subscription verification // Reference: Cloud API GET webhook with hub.mode=subscribe, hub.verify_token WebhookVerifyToken string `gorm:"size:255" json:"webhook_verify_token"` // Whether to auto-create contacts from incoming WhatsApp messages AutoCreateContact bool `gorm:"default:false" json:"auto_create_contact"` // Flag indicating the channel needs re-authorization (token expired or API failure) ReauthorizationRequired bool `gorm:"default:false" json:"reauthorization_required"` // Inbox relationship Inbox model.Inbox `gorm:"foreignKey:InboxID" json:"inbox,omitempty"` } // TableName returns the GORM table name for ChannelWhatsApp. func (ChannelWhatsApp) TableName() string { return "channel_whatsapps" } // GetChannelBase returns a ChannelBase populated from ChannelWhatsApp fields. // Required by the Channelable interface. func (c *ChannelWhatsApp) GetChannelBase() ChannelBase { return ChannelBase{ ID: c.ID, AccountID: c.AccountID, InboxID: c.InboxID, ChannelType: c.GetChannelType(), CreatedAt: c.CreatedAt, UpdatedAt: c.UpdatedAt, DeletedAt: c.DeletedAt, } } // GetChannelType returns the channel type identifier. func (c *ChannelWhatsApp) GetChannelType() string { return "whatsapp" } // GetInboxID returns the inbox ID for this channel. func (c *ChannelWhatsApp) GetInboxID() uint { return c.InboxID } // IsCloudAPI returns true if this channel uses the WhatsApp Cloud API provider. func (c *ChannelWhatsApp) IsCloudAPI() bool { return c.Provider == "whatsapp_cloud" } // Is360Dialog returns true if this channel uses the 360dialog provider. func (c *ChannelWhatsApp) Is360Dialog() bool { return c.Provider == "360dialog" }