117 lines
4.1 KiB
Go
117 lines
4.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"errors"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
"github.com/gochat/gochat/internal/repository"
|
|
applogger "github.com/gochat/gochat/pkg/logger"
|
|
pkgvalidator "github.com/gochat/gochat/pkg/validator"
|
|
)
|
|
|
|
// ContactInboxService implements business logic for ContactInbox operations.
|
|
// Reference: Chatwoot app/models/contact_inbox.rb
|
|
type ContactInboxService struct {
|
|
repo *repository.ContactInboxRepo
|
|
}
|
|
|
|
// NewContactInboxService creates a new ContactInbox service.
|
|
func NewContactInboxService(repo *repository.ContactInboxRepo) *ContactInboxService {
|
|
return &ContactInboxService{repo: repo}
|
|
}
|
|
|
|
// GetByID retrieves a single contact_inbox.
|
|
func (s *ContactInboxService) GetByID(ctx context.Context, id uint) (*model.ContactInbox, error) {
|
|
return s.repo.FindByID(ctx, id)
|
|
}
|
|
|
|
// GetByContactAndInbox retrieves a contact_inbox by contact and inbox.
|
|
func (s *ContactInboxService) GetByContactAndInbox(ctx context.Context, contactID, inboxID uint) (*model.ContactInbox, error) {
|
|
return s.repo.FindByContactAndInbox(ctx, contactID, inboxID)
|
|
}
|
|
|
|
// ListByContact retrieves all contact_inboxes for a contact.
|
|
func (s *ContactInboxService) ListByContact(ctx context.Context, contactID uint) ([]model.ContactInbox, error) {
|
|
return s.repo.FindByContact(ctx, contactID)
|
|
}
|
|
|
|
// ListByInbox retrieves all contact_inboxes for an inbox (paginated).
|
|
func (s *ContactInboxService) ListByInbox(ctx context.Context, inboxID uint, offset, limit int) ([]model.ContactInbox, int64, error) {
|
|
return s.repo.FindByInbox(ctx, inboxID, offset, limit)
|
|
}
|
|
|
|
// GetBySourceID retrieves a contact_inbox by source_id and inbox.
|
|
func (s *ContactInboxService) GetBySourceID(ctx context.Context, inboxID uint, sourceID string) (*model.ContactInbox, error) {
|
|
return s.repo.FindBySourceID(ctx, inboxID, sourceID)
|
|
}
|
|
|
|
// CreateContactInboxRequest is the DTO for creating a contact_inbox.
|
|
type CreateContactInboxRequest struct {
|
|
ContactID uint `json:"contact_id" validate:"required"`
|
|
InboxID uint `json:"inbox_id" validate:"required"`
|
|
SourceID string `json:"source_id" validate:"required"`
|
|
}
|
|
|
|
// Create adds a new contact_inbox join record.
|
|
func (s *ContactInboxService) Create(ctx context.Context, req CreateContactInboxRequest) (*model.ContactInbox, error) {
|
|
if err := pkgvalidator.ValidateStruct(req); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Check for duplicate
|
|
existing, err := s.repo.FindByContactAndInbox(ctx, req.ContactID, req.InboxID)
|
|
if err == nil && existing != nil {
|
|
return nil, errors.New("contact_inbox already exists for this contact and inbox")
|
|
}
|
|
|
|
hmacToken, err := generateToken(24)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pubsubToken, err := generateToken(24)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ci := &model.ContactInbox{
|
|
ContactID: req.ContactID,
|
|
InboxID: req.InboxID,
|
|
SourceID: req.SourceID,
|
|
HMACToken: hmacToken,
|
|
PubsubToken: pubsubToken,
|
|
}
|
|
if err := s.repo.Create(ctx, ci); err != nil {
|
|
applogger.L().Errorf("ContactInboxService.Create failed: %v", err)
|
|
return nil, err
|
|
}
|
|
return ci, nil
|
|
}
|
|
|
|
// Delete removes a contact_inbox by ID.
|
|
func (s *ContactInboxService) Delete(ctx context.Context, id uint) error {
|
|
return s.repo.Delete(ctx, id)
|
|
}
|
|
|
|
// DeleteByContactAndInbox removes the join record.
|
|
func (s *ContactInboxService) DeleteByContactAndInbox(ctx context.Context, contactID, inboxID uint) error {
|
|
return s.repo.DeleteByContactAndInbox(ctx, contactID, inboxID)
|
|
}
|
|
|
|
// FilterContactInboxes retrieves contact_inboxes by account with optional filters.
|
|
// GET /api/v1/accounts/:id/contact_inboxes/filter
|
|
// Reference: Chatwoot contact_inboxes_controller#filter
|
|
func (s *ContactInboxService) FilterContactInboxes(ctx context.Context, accountID uint, inboxID, contactID *uint, sourceID string, offset, limit int) ([]model.ContactInbox, int64, error) {
|
|
return s.repo.Filter(ctx, accountID, inboxID, contactID, sourceID, offset, limit)
|
|
}
|
|
|
|
// generateToken creates a random hex token of the specified byte length.
|
|
func generateToken(byteLen int) (string, error) {
|
|
b := make([]byte, byteLen)
|
|
if _, err := rand.Read(b); err != nil {
|
|
return "", err
|
|
}
|
|
return hex.EncodeToString(b), nil
|
|
} |