110 lines
3.0 KiB
Go
110 lines
3.0 KiB
Go
|
|
package placement
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"encoding/json"
|
|||
|
|
"strings"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
type CtaType string
|
|||
|
|
|
|||
|
|
const (
|
|||
|
|
CtaNone CtaType = "none"
|
|||
|
|
CtaLink CtaType = "link"
|
|||
|
|
CtaDM CtaType = "dm"
|
|||
|
|
CtaFollow CtaType = "follow"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
type ProductContextFields struct {
|
|||
|
|
Brand string `json:"brand"`
|
|||
|
|
Product string `json:"product"`
|
|||
|
|
Features string `json:"features"`
|
|||
|
|
PlacementTone string `json:"placementTone,omitempty"`
|
|||
|
|
CtaType CtaType `json:"ctaType,omitempty"`
|
|||
|
|
CtaUrl string `json:"ctaUrl,omitempty"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ParseProductContext(raw string) ProductContextFields {
|
|||
|
|
raw = strings.TrimSpace(raw)
|
|||
|
|
if raw == "" {
|
|||
|
|
return ProductContextFields{CtaType: CtaNone}
|
|||
|
|
}
|
|||
|
|
var parsed ProductContextFields
|
|||
|
|
if err := json.Unmarshal([]byte(raw), &parsed); err != nil {
|
|||
|
|
return ProductContextFields{CtaType: CtaNone, Features: raw}
|
|||
|
|
}
|
|||
|
|
parsed.Brand = strings.TrimSpace(parsed.Brand)
|
|||
|
|
parsed.Product = strings.TrimSpace(parsed.Product)
|
|||
|
|
parsed.Features = strings.TrimSpace(parsed.Features)
|
|||
|
|
parsed.PlacementTone = strings.TrimSpace(parsed.PlacementTone)
|
|||
|
|
parsed.CtaUrl = strings.TrimSpace(parsed.CtaUrl)
|
|||
|
|
if parsed.CtaType == "" {
|
|||
|
|
parsed.CtaType = CtaNone
|
|||
|
|
}
|
|||
|
|
return parsed
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func SerializeProductContext(fields ProductContextFields) string {
|
|||
|
|
brand := strings.TrimSpace(fields.Brand)
|
|||
|
|
product := strings.TrimSpace(fields.Product)
|
|||
|
|
features := strings.TrimSpace(fields.Features)
|
|||
|
|
tone := strings.TrimSpace(fields.PlacementTone)
|
|||
|
|
ctaType := fields.CtaType
|
|||
|
|
if ctaType == "" {
|
|||
|
|
ctaType = CtaNone
|
|||
|
|
}
|
|||
|
|
ctaUrl := strings.TrimSpace(fields.CtaUrl)
|
|||
|
|
if brand == "" && product == "" && features == "" && tone == "" && ctaType == CtaNone && ctaUrl == "" {
|
|||
|
|
return ""
|
|||
|
|
}
|
|||
|
|
payload, _ := json.Marshal(ProductContextFields{
|
|||
|
|
Brand: brand,
|
|||
|
|
Product: product,
|
|||
|
|
Features: features,
|
|||
|
|
PlacementTone: tone,
|
|||
|
|
CtaType: ctaType,
|
|||
|
|
CtaUrl: ctaUrl,
|
|||
|
|
})
|
|||
|
|
return string(payload)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func FormatProductContextForPrompt(raw string) string {
|
|||
|
|
fields := ParseProductContext(raw)
|
|||
|
|
lines := []string{}
|
|||
|
|
if fields.Brand != "" {
|
|||
|
|
lines = append(lines, "品牌:"+fields.Brand)
|
|||
|
|
}
|
|||
|
|
if fields.Product != "" {
|
|||
|
|
lines = append(lines, "產品:"+fields.Product)
|
|||
|
|
}
|
|||
|
|
if fields.Features != "" {
|
|||
|
|
lines = append(lines, "特色/能幫上忙的地方:"+fields.Features)
|
|||
|
|
}
|
|||
|
|
if fields.PlacementTone != "" {
|
|||
|
|
lines = append(lines, "置入語氣偏好:"+fields.PlacementTone)
|
|||
|
|
}
|
|||
|
|
if fields.CtaType == CtaLink && fields.CtaUrl != "" {
|
|||
|
|
lines = append(lines, "留言 CTA 連結:"+fields.CtaUrl)
|
|||
|
|
} else if fields.CtaType == CtaDM {
|
|||
|
|
lines = append(lines, "留言 CTA:引導私訊")
|
|||
|
|
} else if fields.CtaType == CtaFollow {
|
|||
|
|
lines = append(lines, "留言 CTA:引導追蹤")
|
|||
|
|
}
|
|||
|
|
if len(lines) == 0 {
|
|||
|
|
return ""
|
|||
|
|
}
|
|||
|
|
return strings.Join(lines, "\n")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func ProductBriefFromContext(raw string) string {
|
|||
|
|
formatted := FormatProductContextForPrompt(raw)
|
|||
|
|
if formatted != "" {
|
|||
|
|
return formatted
|
|||
|
|
}
|
|||
|
|
return strings.TrimSpace(raw)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func HasProductContext(raw string) bool {
|
|||
|
|
fields := ParseProductContext(raw)
|
|||
|
|
return fields.Brand != "" || fields.Product != "" || fields.Features != ""
|
|||
|
|
}
|