feat: sync all features to image2api
This commit is contained in:
@@ -279,6 +279,38 @@ func (h *ProviderAdminHandler) ImportAdobeCookie(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func (h *ProviderAdminHandler) ImportCreativeFabricaCookie(c *gin.Context) {
|
||||
var body struct {
|
||||
Cookie string `json:"cookie"`
|
||||
Value string `json:"value"`
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"detail": "invalid request body"})
|
||||
return
|
||||
}
|
||||
cookie := body.Cookie
|
||||
if cookie == "" {
|
||||
cookie = body.Value
|
||||
}
|
||||
name := body.Name
|
||||
if name == "" {
|
||||
name = body.ID
|
||||
}
|
||||
item, err := h.tokens.ImportCreativeFabricaCookie(c.Request.Context(), cookie, name)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"detail": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"ok": true,
|
||||
"id": item.ID,
|
||||
"status": item.Status,
|
||||
"pending": item.Status == "pending",
|
||||
})
|
||||
}
|
||||
|
||||
func (h *ProviderAdminHandler) TokenUpdate(c *gin.Context) {
|
||||
var body map[string]any
|
||||
if err := c.ShouldBindJSON(&body); err != nil {
|
||||
@@ -392,7 +424,7 @@ func (h *ProviderAdminHandler) AccountsList(c *gin.Context) {
|
||||
// accountsStats reproduces the 账号 KPI strip: per-type 正常/失效/限额 counts plus a
|
||||
// grand total and total dead count (drives 「删除异常账号 (N)」).
|
||||
func accountsStats(rows []map[string]any) gin.H {
|
||||
types := []string{"openai", "adobe", "runway", "leonardo", "krea", "imagine", "grok"}
|
||||
types := []string{"openai", "adobe", "runway", "leonardo", "krea", "imagine", "grok", "creativefabrica"}
|
||||
by := map[string]*struct{ N, Ok, Dead, Quota int }{}
|
||||
for _, t := range types {
|
||||
by[t] = &struct{ N, Ok, Dead, Quota int }{}
|
||||
|
||||
@@ -439,7 +439,7 @@ func (h *UserGenerationHandler) VideoPresets(c *gin.Context) {
|
||||
"resolutions": []string{"720p", "1080p"},
|
||||
},
|
||||
{
|
||||
"key": "seedance-2.0-fast",
|
||||
"key": "adobe-seedance-2.0-fast",
|
||||
"label": "Seedance 2.0 Fast",
|
||||
"type": "video",
|
||||
"provider": "adobe",
|
||||
@@ -450,7 +450,7 @@ func (h *UserGenerationHandler) VideoPresets(c *gin.Context) {
|
||||
"reference_mode": "style",
|
||||
},
|
||||
{
|
||||
"key": "seedance-2.0",
|
||||
"key": "adobe-seedance-2.0",
|
||||
"label": "Seedance 2.0",
|
||||
"type": "video",
|
||||
"provider": "adobe",
|
||||
@@ -460,6 +460,36 @@ func (h *UserGenerationHandler) VideoPresets(c *gin.Context) {
|
||||
"max_reference_images": 9,
|
||||
"reference_mode": "style",
|
||||
},
|
||||
{
|
||||
"key": "seedance-2.0-fast",
|
||||
"label": "Seedance 2.0 Fast (Creative Fabrica)",
|
||||
"type": "video",
|
||||
"provider": "creativefabrica",
|
||||
"durations": []string{"14s"},
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
"resolutions": []string{"720p"},
|
||||
// Creative Fabrica 上游只有普通参考图(VIDEO_FRAME_TYPE_REFERENCE),
|
||||
// 没有首尾帧,也不收视频/音频参考。
|
||||
"max_reference_images": 9,
|
||||
"reference_mode": "asset",
|
||||
"max_videos": 0,
|
||||
"max_audios": 0,
|
||||
},
|
||||
{
|
||||
"key": "seedance-2.0",
|
||||
"label": "Seedance 2.0 (Creative Fabrica)",
|
||||
"type": "video",
|
||||
"provider": "creativefabrica",
|
||||
"durations": []string{"10s"},
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
"resolutions": []string{"720p"},
|
||||
// Creative Fabrica 上游只有普通参考图(VIDEO_FRAME_TYPE_REFERENCE),
|
||||
// 没有首尾帧,也不收视频/音频参考。
|
||||
"max_reference_images": 9,
|
||||
"reference_mode": "asset",
|
||||
"max_videos": 0,
|
||||
"max_audios": 0,
|
||||
},
|
||||
{
|
||||
"key": "seedance-2.0-不卡人脸",
|
||||
"label": "Seedance 2.0 (Leonardo 私有)",
|
||||
@@ -675,7 +705,7 @@ func (h *UserGenerationHandler) catalogEntries(c *gin.Context) ([]gin.H, error)
|
||||
"description": "Adobe Firefly Video",
|
||||
},
|
||||
{
|
||||
"id": "seedance-2.0-fast",
|
||||
"id": "adobe-seedance-2.0-fast",
|
||||
"provider": "adobe",
|
||||
"type": "video",
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
@@ -687,7 +717,7 @@ func (h *UserGenerationHandler) catalogEntries(c *gin.Context) ([]gin.H, error)
|
||||
"description": "Seedance 2.0 Fast",
|
||||
},
|
||||
{
|
||||
"id": "seedance-2.0",
|
||||
"id": "adobe-seedance-2.0",
|
||||
"provider": "adobe",
|
||||
"type": "video",
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
@@ -698,6 +728,32 @@ func (h *UserGenerationHandler) catalogEntries(c *gin.Context) ([]gin.H, error)
|
||||
"reference_mode": "style",
|
||||
"description": "Seedance 2.0",
|
||||
},
|
||||
{
|
||||
"id": "seedance-2.0-fast",
|
||||
"provider": "creativefabrica",
|
||||
"type": "video",
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
"resolutions": []string{"720p"},
|
||||
// 一次性账号:积分刚好够一次生成,时长固定 14 秒。
|
||||
"durations": []string{"14s"},
|
||||
// Creative Fabrica 上游只有普通参考图,没有首尾帧,也不收视频/音频参考。
|
||||
"max_reference_images": 9,
|
||||
"reference_mode": "asset",
|
||||
"description": "Seedance 2.0 Fast (Creative Fabrica)",
|
||||
},
|
||||
{
|
||||
"id": "seedance-2.0",
|
||||
"provider": "creativefabrica",
|
||||
"type": "video",
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
"resolutions": []string{"720p"},
|
||||
// 一次性账号:积分刚好够一次生成,时长固定 10 秒。
|
||||
"durations": []string{"10s"},
|
||||
// Creative Fabrica 上游只有普通参考图,没有首尾帧,也不收视频/音频参考。
|
||||
"max_reference_images": 9,
|
||||
"reference_mode": "asset",
|
||||
"description": "Seedance 2.0 (Creative Fabrica)",
|
||||
},
|
||||
{
|
||||
"id": "runway-gen4-turbo",
|
||||
"provider": "runway",
|
||||
@@ -932,7 +988,7 @@ func (h *UserGenerationHandler) publicModels() ([]gin.H, error) {
|
||||
"stub": false,
|
||||
},
|
||||
{
|
||||
"id": "seedance-2.0-fast",
|
||||
"id": "adobe-seedance-2.0-fast",
|
||||
"provider": "adobe",
|
||||
"kind": "video",
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
@@ -941,7 +997,7 @@ func (h *UserGenerationHandler) publicModels() ([]gin.H, error) {
|
||||
"stub": false,
|
||||
},
|
||||
{
|
||||
"id": "seedance-2.0",
|
||||
"id": "adobe-seedance-2.0",
|
||||
"provider": "adobe",
|
||||
"kind": "video",
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
@@ -949,6 +1005,24 @@ func (h *UserGenerationHandler) publicModels() ([]gin.H, error) {
|
||||
"description": "Seedance 2.0",
|
||||
"stub": false,
|
||||
},
|
||||
{
|
||||
"id": "seedance-2.0-fast",
|
||||
"provider": "creativefabrica",
|
||||
"kind": "video",
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
"resolutions": []string{"720p"},
|
||||
"description": "Seedance 2.0 Fast (Creative Fabrica)",
|
||||
"stub": false,
|
||||
},
|
||||
{
|
||||
"id": "seedance-2.0",
|
||||
"provider": "creativefabrica",
|
||||
"kind": "video",
|
||||
"ratios": []string{"16:9", "9:16"},
|
||||
"resolutions": []string{"720p"},
|
||||
"description": "Seedance 2.0 (Creative Fabrica)",
|
||||
"stub": false,
|
||||
},
|
||||
{
|
||||
"id": "runway-gen4-turbo",
|
||||
"provider": "runway",
|
||||
|
||||
@@ -292,19 +292,24 @@ func rawToString(raw json.RawMessage) string {
|
||||
}
|
||||
|
||||
// videoSizeToInternal maps OpenAI's "WxH" size to our aspect ratio + resolution
|
||||
// tier (height ≥1080 → 1080p, else 720p).
|
||||
// tier. An absent/unparsable size leaves the resolution empty so the caller can
|
||||
// fall back to whatever tier the model actually prices — hardcoding 720p here
|
||||
// rejects models that only offer 1440p.
|
||||
func videoSizeToInternal(size string) (ratio, resolution string) {
|
||||
var w, h int
|
||||
if s := strings.TrimSpace(strings.ToLower(size)); s != "" {
|
||||
_, _ = fmt.Sscanf(s, "%dx%d", &w, &h)
|
||||
}
|
||||
if w == 0 || h == 0 {
|
||||
return "16:9", "720p"
|
||||
return "16:9", ""
|
||||
}
|
||||
// The "p" resolution is the SHORT edge (720p = 1280×720, 1080p = 1920×1080),
|
||||
// so a standard 1280×720 must read as 720p — not 1080p off the long edge.
|
||||
resolution = "720p"
|
||||
if min(w, h) >= 1080 {
|
||||
switch {
|
||||
case min(w, h) >= 1440:
|
||||
resolution = "1440p"
|
||||
case min(w, h) >= 1080:
|
||||
resolution = "1080p"
|
||||
}
|
||||
return guessRatioWH(w, h), resolution
|
||||
|
||||
@@ -129,6 +129,7 @@ func New(cfg *config.Config, auth *service.AuthService, handlers Handlers) *gin.
|
||||
authed.POST("/tokens", handlers.ProviderAdmin.TokensCreate)
|
||||
authed.POST("/tokens/import-chatgpt-token", handlers.ProviderAdmin.ImportChatGPTToken)
|
||||
authed.POST("/tokens/import-adobe-cookie", handlers.ProviderAdmin.ImportAdobeCookie)
|
||||
authed.POST("/tokens/import-creativefabrica-cookie", handlers.ProviderAdmin.ImportCreativeFabricaCookie)
|
||||
authed.POST("/tokens/import-runway-token", handlers.ProviderAdmin.ImportRunwayToken)
|
||||
authed.POST("/tokens/import-leonardo-cookie", handlers.ProviderAdmin.ImportLeonardoCookie)
|
||||
authed.POST("/tokens/import-krea-cookie", handlers.ProviderAdmin.ImportKreaCookie)
|
||||
|
||||
Reference in New Issue
Block a user