package main import ( "time" ) // AttachmentMeta holds attachment metadata (content fetched on demand) type AttachmentMeta struct { Name string `json:"name"` Mime string `json:"mime"` Size int `json:"size"` } // UnifiedMessage is the canonical message format across all sources type UnifiedMessage struct { ID string `json:"id"` // source:unique_id Source string `json:"source"` // proton, whatsapp, etc. From string `json:"from"` FromName string `json:"from_name,omitempty"` To string `json:"to"` Timestamp time.Time `json:"timestamp"` Subject string `json:"subject,omitempty"` Body string `json:"body"` Attachments []AttachmentMeta `json:"attachments"` Seen bool `json:"seen"` // Internal fields (not exposed in JSON) SourceUID string `json:"-"` // Original UID/ID from source SourceExtra any `json:"-"` // Source-specific data (e.g., folder for email) } // Connector defines the interface for message sources type Connector interface { // Name returns the connector identifier (e.g., "proton", "whatsapp") Name() string // FetchNew returns unseen/new messages FetchNew() ([]UnifiedMessage, error) // FetchSince returns messages since the given time FetchSince(since time.Time) ([]UnifiedMessage, error) // FetchOne returns a single message by its source-specific ID FetchOne(sourceID string) (*UnifiedMessage, error) // Archive marks a message as archived Archive(sourceID string) error // Delete permanently removes a message Delete(sourceID string) error // Reply sends a reply to a message Reply(sourceID string, body string, attachments []string) error // MarkSeen marks a message as seen/read MarkSeen(sourceID string) error // GetAttachment retrieves attachment content (base64) GetAttachment(sourceID string, filename string) ([]byte, error) // Start begins watching for new messages (calls callback on new) Start(callback func()) error // Stop stops the connector Stop() }