Files
story/internal/memoir/illustrator.go
T
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
2026-10-08 10:06:44 +08:00

63 lines
2.0 KiB
Go

package memoir
import (
"bytes"
"context"
"data-terminal-cloud/internal/extraction"
"encoding/base64"
"encoding/json"
"errors"
"io"
"net/http"
"strings"
"time"
)
type ArkIllustrator struct {
BaseURL, APIKey, Model string
Client *http.Client
}
func NewIllustrator(base, key, model string) *ArkIllustrator {
return &ArkIllustrator{strings.TrimRight(base, "/"), key, model, &http.Client{Timeout: 120 * time.Second}}
}
func (a *ArkIllustrator) Generate(ctx context.Context, prompt string) ([]byte, error) {
body, _ := json.Marshal(map[string]any{"model": a.Model, "prompt": prompt + "。温暖的水彩情景插画,米色纸张肌理,禁止文字和水印以外的标记。这是基于叙述的想象性插画,不是真实历史照片。", "size": "2K", "output_format": "jpeg", "response_format": "b64_json", "watermark": true})
req, e := http.NewRequestWithContext(ctx, "POST", a.BaseURL+"/images/generations", bytes.NewReader(body))
if e != nil {
return nil, e
}
req.Header.Set("Authorization", "Bearer "+a.APIKey)
req.Header.Set("Content-Type", "application/json")
resp, e := a.Client.Do(req)
if e != nil {
return nil, errors.New("MEMOIR_IMAGE_UNAVAILABLE")
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
var failure struct {
Error struct {
Code string `json:"code"`
} `json:"error"`
}
_ = json.NewDecoder(io.LimitReader(resp.Body, 64<<10)).Decode(&failure)
if failure.Error.Code == "AccountOverdueError" {
return nil, extraction.ErrModelAccountOverdue
}
return nil, errors.New("MEMOIR_IMAGE_REJECTED")
}
var out struct {
Data []struct {
Base64 string `json:"b64_json"`
} `json:"data"`
}
if json.NewDecoder(io.LimitReader(resp.Body, 16<<20)).Decode(&out) != nil || len(out.Data) != 1 {
return nil, errors.New("MEMOIR_IMAGE_INVALID")
}
b, e := base64.StdEncoding.DecodeString(out.Data[0].Base64)
if e != nil || len(b) > 10<<20 || http.DetectContentType(b) != "image/jpeg" {
return nil, errors.New("MEMOIR_IMAGE_INVALID")
}
return b, nil
}