25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

118 satır
3.0KB

  1. package templatesvc
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "sort"
  7. "strings"
  8. "qctextbuilder/internal/domain"
  9. "qctextbuilder/internal/qcclient"
  10. "qctextbuilder/internal/store"
  11. )
  12. type Service struct {
  13. qc qcclient.Client
  14. templateStore store.TemplateStore
  15. manifestStore store.ManifestStore
  16. }
  17. type TemplateDetail struct {
  18. Template *domain.Template `json:"template"`
  19. Manifest *domain.TemplateManifest `json:"manifest,omitempty"`
  20. Fields []domain.TemplateField `json:"fields"`
  21. }
  22. func New(qc qcclient.Client, templateStore store.TemplateStore, manifestStore store.ManifestStore) *Service {
  23. return &Service{
  24. qc: qc,
  25. templateStore: templateStore,
  26. manifestStore: manifestStore,
  27. }
  28. }
  29. func (s *Service) SyncAITemplates(ctx context.Context) ([]domain.Template, error) {
  30. templates, err := s.qc.ListAITemplates(ctx)
  31. if err != nil {
  32. return nil, err
  33. }
  34. out := make([]domain.Template, 0, len(templates))
  35. for _, t := range templates {
  36. raw, _ := json.Marshal(t)
  37. out = append(out, domain.Template{
  38. ID: t.ID,
  39. Name: t.Name,
  40. Description: t.Description,
  41. Locale: strings.ToUpper(t.Locale),
  42. ThumbnailURL: t.ThumbnailURL,
  43. TemplatePreviewURL: t.TemplatePreviewURL,
  44. Type: t.Type,
  45. PaletteReady: t.PaletteReady.Bool(),
  46. RawJSON: raw,
  47. IsAITemplate: strings.EqualFold(t.Type, "ai"),
  48. ManifestStatus: "missing",
  49. })
  50. }
  51. if err := s.templateStore.UpsertTemplates(ctx, out); err != nil {
  52. return nil, err
  53. }
  54. return out, nil
  55. }
  56. func (s *Service) ListTemplates(ctx context.Context) ([]domain.Template, error) {
  57. templates, err := s.templateStore.ListTemplates(ctx)
  58. if err != nil {
  59. return nil, fmt.Errorf("list templates: %w", err)
  60. }
  61. sort.Slice(templates, func(i, j int) bool {
  62. if templates[i].Name == templates[j].Name {
  63. return templates[i].ID < templates[j].ID
  64. }
  65. return templates[i].Name < templates[j].Name
  66. })
  67. return templates, nil
  68. }
  69. func (s *Service) GetTemplateDetail(ctx context.Context, templateID int64) (*TemplateDetail, error) {
  70. template, err := s.templateStore.GetTemplateByID(ctx, templateID)
  71. if err != nil {
  72. return nil, fmt.Errorf("get template: %w", err)
  73. }
  74. detail := &TemplateDetail{
  75. Template: template,
  76. Fields: []domain.TemplateField{},
  77. }
  78. manifest, err := s.manifestStore.GetActiveManifestByTemplateID(ctx, templateID)
  79. if err != nil {
  80. if isNotFoundErr(err) {
  81. return detail, nil
  82. }
  83. return nil, fmt.Errorf("get active manifest: %w", err)
  84. }
  85. fields, err := s.manifestStore.ListFieldsByManifestID(ctx, manifest.ID)
  86. if err != nil {
  87. return nil, fmt.Errorf("list fields: %w", err)
  88. }
  89. sort.Slice(fields, func(i, j int) bool {
  90. if fields[i].DisplayOrder == fields[j].DisplayOrder {
  91. return fields[i].Path < fields[j].Path
  92. }
  93. return fields[i].DisplayOrder < fields[j].DisplayOrder
  94. })
  95. detail.Manifest = manifest
  96. detail.Fields = fields
  97. return detail, nil
  98. }
  99. func isNotFoundErr(err error) bool {
  100. return strings.Contains(strings.ToLower(strings.TrimSpace(err.Error())), "not found")
  101. }