194 lines
7.7 KiB
Go
194 lines
7.7 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/gochat/gochat/internal/model"
|
|
"github.com/gochat/gochat/internal/repository"
|
|
applogger "github.com/gochat/gochat/pkg/logger"
|
|
)
|
|
|
|
// LinearIntegrationService implements Linear integration business logic.
|
|
// Reference: Chatwoot Integrations::LinearController
|
|
// Linear integration creates and links issues from conversations.
|
|
type LinearIntegrationService struct {
|
|
hookRepo *repository.IntegrationHookRepo
|
|
}
|
|
|
|
// NewLinearIntegrationService creates a new LinearIntegrationService.
|
|
func NewLinearIntegrationService(hookRepo *repository.IntegrationHookRepo) *LinearIntegrationService {
|
|
return &LinearIntegrationService{hookRepo: hookRepo}
|
|
}
|
|
|
|
// Delete removes a Linear integration hook for an account.
|
|
func (s *LinearIntegrationService) Delete(ctx context.Context, accountID uint) error {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeLinear)
|
|
if err != nil || len(hooks) == 0 {
|
|
return fmt.Errorf("Linear integration not found for account %d", accountID)
|
|
}
|
|
|
|
for _, hook := range hooks {
|
|
if err := s.hookRepo.Delete(ctx, hook.ID); err != nil {
|
|
return fmt.Errorf("failed to delete Linear integration: %w", err)
|
|
}
|
|
}
|
|
|
|
applogger.L().Infof("Linear integration deleted: account=%d", accountID)
|
|
return nil
|
|
}
|
|
|
|
// GetTeams retrieves available Linear teams (proxy to Linear API).
|
|
// GET /api/v1/accounts/:account_id/integrations/linear/teams
|
|
func (s *LinearIntegrationService) GetTeams(ctx context.Context, accountID uint) ([]map[string]interface{}, error) {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeLinear)
|
|
if err != nil || len(hooks) == 0 {
|
|
return nil, fmt.Errorf("Linear integration not found for account %d", accountID)
|
|
}
|
|
|
|
var settings model.LinearSettings
|
|
if err := json.Unmarshal(hooks[0].Settings, &settings); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal Linear settings: %w", err)
|
|
}
|
|
|
|
// In production, this would call the Linear API.
|
|
applogger.L().Infof("Listing Linear teams for account=%d", accountID)
|
|
return []map[string]interface{}{
|
|
{"id": settings.TeamID, "name": settings.TeamName},
|
|
}, nil
|
|
}
|
|
|
|
// GetTeamEntities retrieves entities from a Linear team.
|
|
// GET /api/v1/accounts/:account_id/integrations/linear/team_entities
|
|
func (s *LinearIntegrationService) GetTeamEntities(ctx context.Context, accountID uint) ([]map[string]interface{}, error) {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeLinear)
|
|
if err != nil || len(hooks) == 0 {
|
|
return nil, fmt.Errorf("Linear integration not found for account %d", accountID)
|
|
}
|
|
|
|
applogger.L().Infof("Listing Linear team entities for account=%d", accountID)
|
|
return []map[string]interface{}{}, nil
|
|
}
|
|
|
|
// CreateIssueRequest is the DTO for creating a Linear issue.
|
|
type CreateIssueRequest struct {
|
|
Title string `json:"title" validate:"required"`
|
|
Description string `json:"description,omitempty"`
|
|
TeamID string `json:"team_id,omitempty"`
|
|
}
|
|
|
|
// CreateIssue creates a Linear issue from a conversation.
|
|
// POST /api/v1/accounts/:account_id/integrations/linear/create_issue
|
|
func (s *LinearIntegrationService) CreateIssue(ctx context.Context, accountID uint, req CreateIssueRequest) (map[string]interface{}, error) {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeLinear)
|
|
if err != nil || len(hooks) == 0 {
|
|
return nil, fmt.Errorf("Linear integration not found for account %d", accountID)
|
|
}
|
|
|
|
applogger.L().Infof("Creating Linear issue for account=%d: title=%s", accountID, req.Title)
|
|
// In production, this would call the Linear API to create an issue.
|
|
return map[string]interface{}{
|
|
"status": "created",
|
|
"title": req.Title,
|
|
"team_id": req.TeamID,
|
|
}, nil
|
|
}
|
|
|
|
// LinkIssueRequest is the DTO for linking a Linear issue to a conversation.
|
|
type LinkIssueRequest struct {
|
|
IssueID string `json:"issue_id" validate:"required"`
|
|
ConversationID uint `json:"conversation_id,omitempty"`
|
|
}
|
|
|
|
// LinkIssue links a Linear issue to a conversation.
|
|
// POST /api/v1/accounts/:account_id/integrations/linear/link_issue
|
|
func (s *LinearIntegrationService) LinkIssue(ctx context.Context, accountID uint, req LinkIssueRequest) (map[string]interface{}, error) {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeLinear)
|
|
if err != nil || len(hooks) == 0 {
|
|
return nil, fmt.Errorf("Linear integration not found for account %d", accountID)
|
|
}
|
|
|
|
applogger.L().Infof("Linking Linear issue %s for account=%d", req.IssueID, accountID)
|
|
return map[string]interface{}{
|
|
"status": "linked",
|
|
"issue_id": req.IssueID,
|
|
}, nil
|
|
}
|
|
|
|
// UnlinkIssueRequest is the DTO for unlinking a Linear issue from a conversation.
|
|
type UnlinkIssueRequest struct {
|
|
IssueID string `json:"issue_id" validate:"required"`
|
|
ConversationID uint `json:"conversation_id,omitempty"`
|
|
}
|
|
|
|
// UnlinkIssue unlinks a Linear issue from a conversation.
|
|
// POST /api/v1/accounts/:account_id/integrations/linear/unlink_issue
|
|
func (s *LinearIntegrationService) UnlinkIssue(ctx context.Context, accountID uint, req UnlinkIssueRequest) (map[string]interface{}, error) {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeLinear)
|
|
if err != nil || len(hooks) == 0 {
|
|
return nil, fmt.Errorf("Linear integration not found for account %d", accountID)
|
|
}
|
|
|
|
applogger.L().Infof("Unlinking Linear issue %s for account=%d", req.IssueID, accountID)
|
|
return map[string]interface{}{
|
|
"status": "unlinked",
|
|
"issue_id": req.IssueID,
|
|
}, nil
|
|
}
|
|
|
|
// SearchIssue searches Linear issues.
|
|
// GET /api/v1/accounts/:account_id/integrations/linear/search_issue
|
|
func (s *LinearIntegrationService) SearchIssue(ctx context.Context, accountID uint, query string) ([]map[string]interface{}, error) {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeLinear)
|
|
if err != nil || len(hooks) == 0 {
|
|
return nil, fmt.Errorf("Linear integration not found for account %d", accountID)
|
|
}
|
|
|
|
applogger.L().Infof("Searching Linear issues for account=%d, query=%s", accountID, query)
|
|
return []map[string]interface{}{}, nil
|
|
}
|
|
|
|
// GetLinkedIssues retrieves Linear issues linked to a conversation.
|
|
// GET /api/v1/accounts/:account_id/integrations/linear/linked_issues
|
|
func (s *LinearIntegrationService) GetLinkedIssues(ctx context.Context, accountID uint, conversationID uint) ([]map[string]interface{}, error) {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeLinear)
|
|
if err != nil || len(hooks) == 0 {
|
|
return nil, fmt.Errorf("Linear integration not found for account %d", accountID)
|
|
}
|
|
|
|
applogger.L().Infof("Listing linked Linear issues for account=%d, conversation=%d", accountID, conversationID)
|
|
return []map[string]interface{}{}, nil
|
|
}
|
|
|
|
// ---- Notion Integration Service ----
|
|
|
|
// NotionIntegrationService implements Notion integration business logic.
|
|
// Reference: Chatwoot Integrations::NotionController
|
|
// Notion integration creates notes/pages from conversations.
|
|
type NotionIntegrationService struct {
|
|
hookRepo *repository.IntegrationHookRepo
|
|
}
|
|
|
|
// NewNotionIntegrationService creates a new NotionIntegrationService.
|
|
func NewNotionIntegrationService(hookRepo *repository.IntegrationHookRepo) *NotionIntegrationService {
|
|
return &NotionIntegrationService{hookRepo: hookRepo}
|
|
}
|
|
|
|
// Delete removes a Notion integration hook for an account.
|
|
func (s *NotionIntegrationService) Delete(ctx context.Context, accountID uint) error {
|
|
hooks, err := s.hookRepo.FindByAccountAndType(ctx, accountID, model.HookTypeNotion)
|
|
if err != nil || len(hooks) == 0 {
|
|
return fmt.Errorf("Notion integration not found for account %d", accountID)
|
|
}
|
|
|
|
for _, hook := range hooks {
|
|
if err := s.hookRepo.Delete(ctx, hook.ID); err != nil {
|
|
return fmt.Errorf("failed to delete Notion integration: %w", err)
|
|
}
|
|
}
|
|
|
|
applogger.L().Infof("Notion integration deleted: account=%d", accountID)
|
|
return nil
|
|
}
|