Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
221d2b55
authored
Jun 20, 2025
by
skynono
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add video channel jimeng
parent
e234ad07
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
171 additions
and
97 deletions
+171
-97
common/constants.go
+2
-0
constant/task.go
+1
-0
controller/channel-test.go
+3
-0
controller/task.go
+2
-2
controller/task_video.go
+47
-50
middleware/distributor.go
+15
-5
relay/channel/adapter.go
+1
-1
relay/channel/task/jimeng/adaptor.go
+0
-0
relay/channel/task/kling/adaptor.go
+47
-33
relay/channel/task/suno/adaptor.go
+2
-2
relay/common/relay_info.go
+19
-0
relay/constant/relay_mode.go
+13
-0
relay/relay_adaptor.go
+3
-0
relay/relay_task.go
+1
-1
web/src/components/table/TaskLogsTable.js
+9
-3
web/src/constants/channel.constants.js
+5
-0
web/src/i18n/locales/en.json
+1
-0
No files found.
common/constants.go
View file @
221d2b55
...
@@ -242,6 +242,7 @@ const (
...
@@ -242,6 +242,7 @@ const (
ChannelTypeXai
=
48
ChannelTypeXai
=
48
ChannelTypeCoze
=
49
ChannelTypeCoze
=
49
ChannelTypeKling
=
50
ChannelTypeKling
=
50
ChannelTypeJimeng
=
51
ChannelTypeDummy
// this one is only for count, do not add any channel after this
ChannelTypeDummy
// this one is only for count, do not add any channel after this
)
)
...
@@ -298,4 +299,5 @@ var ChannelBaseURLs = []string{
...
@@ -298,4 +299,5 @@ var ChannelBaseURLs = []string{
"https://api.x.ai"
,
//48
"https://api.x.ai"
,
//48
"https://api.coze.cn"
,
//49
"https://api.coze.cn"
,
//49
"https://api.klingai.com"
,
//50
"https://api.klingai.com"
,
//50
"https://visual.volcengineapi.com"
,
//51
}
}
constant/task.go
View file @
221d2b55
...
@@ -6,6 +6,7 @@ const (
...
@@ -6,6 +6,7 @@ const (
TaskPlatformSuno
TaskPlatform
=
"suno"
TaskPlatformSuno
TaskPlatform
=
"suno"
TaskPlatformMidjourney
=
"mj"
TaskPlatformMidjourney
=
"mj"
TaskPlatformKling
TaskPlatform
=
"kling"
TaskPlatformKling
TaskPlatform
=
"kling"
TaskPlatformJimeng
TaskPlatform
=
"jimeng"
)
)
const
(
const
(
...
...
controller/channel-test.go
View file @
221d2b55
...
@@ -43,6 +43,9 @@ func testChannel(channel *model.Channel, testModel string) (err error, openAIErr
...
@@ -43,6 +43,9 @@ func testChannel(channel *model.Channel, testModel string) (err error, openAIErr
if
channel
.
Type
==
common
.
ChannelTypeKling
{
if
channel
.
Type
==
common
.
ChannelTypeKling
{
return
errors
.
New
(
"kling channel test is not supported"
),
nil
return
errors
.
New
(
"kling channel test is not supported"
),
nil
}
}
if
channel
.
Type
==
common
.
ChannelTypeJimeng
{
return
errors
.
New
(
"jimeng channel test is not supported"
),
nil
}
w
:=
httptest
.
NewRecorder
()
w
:=
httptest
.
NewRecorder
()
c
,
_
:=
gin
.
CreateTestContext
(
w
)
c
,
_
:=
gin
.
CreateTestContext
(
w
)
...
...
controller/task.go
View file @
221d2b55
...
@@ -74,8 +74,8 @@ func UpdateTaskByPlatform(platform constant.TaskPlatform, taskChannelM map[int][
...
@@ -74,8 +74,8 @@ func UpdateTaskByPlatform(platform constant.TaskPlatform, taskChannelM map[int][
//_ = UpdateMidjourneyTaskAll(context.Background(), tasks)
//_ = UpdateMidjourneyTaskAll(context.Background(), tasks)
case
constant
.
TaskPlatformSuno
:
case
constant
.
TaskPlatformSuno
:
_
=
UpdateSunoTaskAll
(
context
.
Background
(),
taskChannelM
,
taskM
)
_
=
UpdateSunoTaskAll
(
context
.
Background
(),
taskChannelM
,
taskM
)
case
constant
.
TaskPlatformKling
:
case
constant
.
TaskPlatformKling
,
constant
.
TaskPlatformJimeng
:
_
=
UpdateVideoTaskAll
(
context
.
Background
(),
taskChannelM
,
taskM
)
_
=
UpdateVideoTaskAll
(
context
.
Background
(),
platform
,
taskChannelM
,
taskM
)
default
:
default
:
common
.
SysLog
(
"未知平台"
)
common
.
SysLog
(
"未知平台"
)
}
}
...
...
controller/task_video.go
View file @
221d2b55
...
@@ -2,27 +2,26 @@ package controller
...
@@ -2,27 +2,26 @@ package controller
import
(
import
(
"context"
"context"
"encoding/json"
"fmt"
"fmt"
"io"
"io"
"net/http"
"one-api/common"
"one-api/common"
"one-api/constant"
"one-api/constant"
"one-api/model"
"one-api/model"
"one-api/relay"
"one-api/relay"
"one-api/relay/channel"
"one-api/relay/channel"
"time"
)
)
func
UpdateVideoTaskAll
(
ctx
context
.
Context
,
taskChannelM
map
[
int
][]
string
,
taskM
map
[
string
]
*
model
.
Task
)
error
{
func
UpdateVideoTaskAll
(
ctx
context
.
Context
,
platform
constant
.
TaskPlatform
,
taskChannelM
map
[
int
][]
string
,
taskM
map
[
string
]
*
model
.
Task
)
error
{
for
channelId
,
taskIds
:=
range
taskChannelM
{
for
channelId
,
taskIds
:=
range
taskChannelM
{
if
err
:=
updateVideoTaskAll
(
ctx
,
channelId
,
taskIds
,
taskM
);
err
!=
nil
{
if
err
:=
updateVideoTaskAll
(
ctx
,
platform
,
channelId
,
taskIds
,
taskM
);
err
!=
nil
{
common
.
LogError
(
ctx
,
fmt
.
Sprintf
(
"Channel #%d failed to update video async tasks: %s"
,
channelId
,
err
.
Error
()))
common
.
LogError
(
ctx
,
fmt
.
Sprintf
(
"Channel #%d failed to update video async tasks: %s"
,
channelId
,
err
.
Error
()))
}
}
}
}
return
nil
return
nil
}
}
func
updateVideoTaskAll
(
ctx
context
.
Context
,
channelId
int
,
taskIds
[]
string
,
taskM
map
[
string
]
*
model
.
Task
)
error
{
func
updateVideoTaskAll
(
ctx
context
.
Context
,
platform
constant
.
TaskPlatform
,
channelId
int
,
taskIds
[]
string
,
taskM
map
[
string
]
*
model
.
Task
)
error
{
common
.
LogInfo
(
ctx
,
fmt
.
Sprintf
(
"Channel #%d pending video tasks: %d"
,
channelId
,
len
(
taskIds
)))
common
.
LogInfo
(
ctx
,
fmt
.
Sprintf
(
"Channel #%d pending video tasks: %d"
,
channelId
,
len
(
taskIds
)))
if
len
(
taskIds
)
==
0
{
if
len
(
taskIds
)
==
0
{
return
nil
return
nil
...
@@ -39,7 +38,7 @@ func updateVideoTaskAll(ctx context.Context, channelId int, taskIds []string, ta
...
@@ -39,7 +38,7 @@ func updateVideoTaskAll(ctx context.Context, channelId int, taskIds []string, ta
}
}
return
fmt
.
Errorf
(
"CacheGetChannel failed: %w"
,
err
)
return
fmt
.
Errorf
(
"CacheGetChannel failed: %w"
,
err
)
}
}
adaptor
:=
relay
.
GetTaskAdaptor
(
constant
.
TaskPlatformKling
)
adaptor
:=
relay
.
GetTaskAdaptor
(
platform
)
if
adaptor
==
nil
{
if
adaptor
==
nil
{
return
fmt
.
Errorf
(
"video adaptor not found"
)
return
fmt
.
Errorf
(
"video adaptor not found"
)
}
}
...
@@ -67,60 +66,53 @@ func updateVideoSingleTask(ctx context.Context, adaptor channel.TaskAdaptor, cha
...
@@ -67,60 +66,53 @@ func updateVideoSingleTask(ctx context.Context, adaptor channel.TaskAdaptor, cha
"action"
:
task
.
Action
,
"action"
:
task
.
Action
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"FetchTask failed for task %s: %w"
,
taskId
,
err
)
return
fmt
.
Errorf
(
"fetchTask failed for task %s: %w"
,
taskId
,
err
)
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
fmt
.
Errorf
(
"Get Video Task status code: %d"
,
resp
.
StatusCode
)
}
}
//if resp.StatusCode != http.StatusOK {
//return fmt.Errorf("get Video Task status code: %d", resp.StatusCode)
//}
defer
resp
.
Body
.
Close
()
defer
resp
.
Body
.
Close
()
responseBody
,
err
:=
io
.
ReadAll
(
resp
.
Body
)
responseBody
,
err
:=
io
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"
R
eadAll failed for task %s: %w"
,
taskId
,
err
)
return
fmt
.
Errorf
(
"
r
eadAll failed for task %s: %w"
,
taskId
,
err
)
}
}
var
responseItem
map
[
string
]
interface
{}
taskResult
,
err
:=
adaptor
.
ParseTaskResult
(
responseBody
)
err
=
json
.
Unmarshal
(
responseBody
,
&
responseItem
)
if
err
!=
nil
{
if
err
!=
nil
{
common
.
LogError
(
ctx
,
fmt
.
Sprintf
(
"Failed to parse video task response body: %v, body: %s"
,
err
,
string
(
responseBody
)))
return
fmt
.
Errorf
(
"parseTaskResult failed for task %s: %w"
,
taskId
,
err
)
return
fmt
.
Errorf
(
"Unmarshal failed for task %s: %w"
,
taskId
,
err
)
}
code
,
_
:=
responseItem
[
"code"
]
.
(
float64
)
if
code
!=
0
{
return
fmt
.
Errorf
(
"video task fetch failed for task %s"
,
taskId
)
}
}
//if taskResult.Code != 0 {
// return fmt.Errorf("video task fetch failed for task %s", taskId)
//}
data
,
ok
:=
responseItem
[
"data"
]
.
(
map
[
string
]
interface
{})
now
:=
time
.
Now
()
.
Unix
()
if
!
ok
{
if
taskResult
.
Status
==
""
{
common
.
LogError
(
ctx
,
fmt
.
Sprintf
(
"Video task data format error: %s"
,
string
(
responseBody
)))
return
fmt
.
Errorf
(
"task %s status is empty"
,
taskId
)
return
fmt
.
Errorf
(
"video task data format error for task %s"
,
taskId
)
}
}
task
.
Status
=
model
.
TaskStatus
(
taskResult
.
Status
)
switch
taskResult
.
Status
{
if
status
,
ok
:=
data
[
"task_status"
]
.
(
string
);
ok
{
case
model
.
TaskStatusSubmitted
:
switch
status
{
task
.
Progress
=
"10%"
case
"submitted"
,
"queued"
:
case
model
.
TaskStatusQueued
:
task
.
Status
=
model
.
TaskStatusSubmitted
task
.
Progress
=
"20%"
case
"processing"
:
case
model
.
TaskStatusInProgress
:
task
.
Status
=
model
.
TaskStatusInProgress
task
.
Progress
=
"30%"
case
"succeed"
:
if
task
.
StartTime
==
0
{
task
.
Status
=
model
.
TaskStatusSuccess
task
.
StartTime
=
now
task
.
Progress
=
"100%"
if
url
,
err
:=
adaptor
.
ParseResultUrl
(
responseItem
);
err
==
nil
{
task
.
FailReason
=
url
}
else
{
common
.
LogWarn
(
ctx
,
fmt
.
Sprintf
(
"Failed to get url from body for task %s: %s"
,
task
.
TaskID
,
err
.
Error
()))
}
case
"failed"
:
task
.
Status
=
model
.
TaskStatusFailure
task
.
Progress
=
"100%"
if
reason
,
ok
:=
data
[
"fail_reason"
]
.
(
string
);
ok
{
task
.
FailReason
=
reason
}
}
}
}
case
model
.
TaskStatusSuccess
:
task
.
Progress
=
"100%"
// If task failed, refund quota
if
task
.
FinishTime
==
0
{
if
task
.
Status
==
model
.
TaskStatusFailure
{
task
.
FinishTime
=
now
}
task
.
FailReason
=
taskResult
.
Url
case
model
.
TaskStatusFailure
:
task
.
Status
=
model
.
TaskStatusFailure
task
.
Progress
=
"100%"
if
task
.
FinishTime
==
0
{
task
.
FinishTime
=
now
}
task
.
FailReason
=
taskResult
.
Reason
common
.
LogInfo
(
ctx
,
fmt
.
Sprintf
(
"Task %s failed: %s"
,
task
.
TaskID
,
task
.
FailReason
))
common
.
LogInfo
(
ctx
,
fmt
.
Sprintf
(
"Task %s failed: %s"
,
task
.
TaskID
,
task
.
FailReason
))
quota
:=
task
.
Quota
quota
:=
task
.
Quota
if
quota
!=
0
{
if
quota
!=
0
{
...
@@ -130,6 +122,11 @@ func updateVideoSingleTask(ctx context.Context, adaptor channel.TaskAdaptor, cha
...
@@ -130,6 +122,11 @@ func updateVideoSingleTask(ctx context.Context, adaptor channel.TaskAdaptor, cha
logContent
:=
fmt
.
Sprintf
(
"Video async task failed %s, refund %s"
,
task
.
TaskID
,
common
.
LogQuota
(
quota
))
logContent
:=
fmt
.
Sprintf
(
"Video async task failed %s, refund %s"
,
task
.
TaskID
,
common
.
LogQuota
(
quota
))
model
.
RecordLog
(
task
.
UserId
,
model
.
LogTypeSystem
,
logContent
)
model
.
RecordLog
(
task
.
UserId
,
model
.
LogTypeSystem
,
logContent
)
}
}
default
:
return
fmt
.
Errorf
(
"unknown task status %s for task %s"
,
taskResult
.
Status
,
taskId
)
}
if
taskResult
.
Progress
!=
""
{
task
.
Progress
=
taskResult
.
Progress
}
}
task
.
Data
=
responseBody
task
.
Data
=
responseBody
...
...
middleware/distributor.go
View file @
221d2b55
...
@@ -171,13 +171,23 @@ func getModelRequest(c *gin.Context) (*ModelRequest, bool, error) {
...
@@ -171,13 +171,23 @@ func getModelRequest(c *gin.Context) (*ModelRequest, bool, error) {
c
.
Set
(
"platform"
,
string
(
constant
.
TaskPlatformSuno
))
c
.
Set
(
"platform"
,
string
(
constant
.
TaskPlatformSuno
))
c
.
Set
(
"relay_mode"
,
relayMode
)
c
.
Set
(
"relay_mode"
,
relayMode
)
}
else
if
strings
.
Contains
(
c
.
Request
.
URL
.
Path
,
"/v1/video/generations"
)
{
}
else
if
strings
.
Contains
(
c
.
Request
.
URL
.
Path
,
"/v1/video/generations"
)
{
relayMode
:=
relayconstant
.
Path2RelayKling
(
c
.
Request
.
Method
,
c
.
Request
.
URL
.
Path
)
err
=
common
.
UnmarshalBodyReusable
(
c
,
&
modelRequest
)
if
relayMode
==
relayconstant
.
RelayModeKlingFetchByID
{
var
platform
string
shouldSelectChannel
=
false
var
relayMode
int
if
strings
.
HasPrefix
(
modelRequest
.
Model
,
"jimeng"
)
{
platform
=
string
(
constant
.
TaskPlatformJimeng
)
relayMode
=
relayconstant
.
Path2RelayJimeng
(
c
.
Request
.
Method
,
c
.
Request
.
URL
.
Path
)
if
relayMode
==
relayconstant
.
RelayModeJimengFetchByID
{
shouldSelectChannel
=
false
}
}
else
{
}
else
{
err
=
common
.
UnmarshalBodyReusable
(
c
,
&
modelRequest
)
platform
=
string
(
constant
.
TaskPlatformKling
)
relayMode
=
relayconstant
.
Path2RelayKling
(
c
.
Request
.
Method
,
c
.
Request
.
URL
.
Path
)
if
relayMode
==
relayconstant
.
RelayModeKlingFetchByID
{
shouldSelectChannel
=
false
}
}
}
c
.
Set
(
"platform"
,
string
(
constant
.
TaskPlatformKling
)
)
c
.
Set
(
"platform"
,
platform
)
c
.
Set
(
"relay_mode"
,
relayMode
)
c
.
Set
(
"relay_mode"
,
relayMode
)
}
else
if
strings
.
HasPrefix
(
c
.
Request
.
URL
.
Path
,
"/v1beta/models/"
)
||
strings
.
HasPrefix
(
c
.
Request
.
URL
.
Path
,
"/v1/models/"
)
{
}
else
if
strings
.
HasPrefix
(
c
.
Request
.
URL
.
Path
,
"/v1beta/models/"
)
||
strings
.
HasPrefix
(
c
.
Request
.
URL
.
Path
,
"/v1/models/"
)
{
// Gemini API 路径处理: /v1beta/models/gemini-2.0-flash:generateContent
// Gemini API 路径处理: /v1beta/models/gemini-2.0-flash:generateContent
...
...
relay/channel/adapter.go
View file @
221d2b55
...
@@ -45,5 +45,5 @@ type TaskAdaptor interface {
...
@@ -45,5 +45,5 @@ type TaskAdaptor interface {
// FetchTask
// FetchTask
FetchTask
(
baseUrl
,
key
string
,
body
map
[
string
]
any
)
(
*
http
.
Response
,
error
)
FetchTask
(
baseUrl
,
key
string
,
body
map
[
string
]
any
)
(
*
http
.
Response
,
error
)
Parse
ResultUrl
(
resp
map
[
string
]
any
)
(
string
,
error
)
Parse
TaskResult
(
respBody
[]
byte
)
(
*
relaycommon
.
TaskInfo
,
error
)
}
}
relay/channel/task/jimeng/adaptor.go
0 → 100644
View file @
221d2b55
This diff is collapsed.
Click to expand it.
relay/channel/task/kling/adaptor.go
View file @
221d2b55
...
@@ -2,12 +2,12 @@ package kling
...
@@ -2,12 +2,12 @@ package kling
import
(
import
(
"bytes"
"bytes"
"context"
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"github.com/samber/lo"
"github.com/samber/lo"
"io"
"io"
"net/http"
"net/http"
"one-api/model"
"strings"
"strings"
"time"
"time"
...
@@ -47,10 +47,22 @@ type requestPayload struct {
...
@@ -47,10 +47,22 @@ type requestPayload struct {
}
}
type
responsePayload
struct
{
type
responsePayload
struct
{
Code
int
`json:"code"`
Code
int
`json:"code"`
Message
string
`json:"message"`
Message
string
`json:"message"`
Data
struct
{
RequestId
string
`json:"request_id"`
TaskID
string
`json:"task_id"`
Data
struct
{
TaskId
string
`json:"task_id"`
TaskStatus
string
`json:"task_status"`
TaskStatusMsg
string
`json:"task_status_msg"`
TaskResult
struct
{
Videos
[]
struct
{
Id
string
`json:"id"`
Url
string
`json:"url"`
Duration
string
`json:"duration"`
}
`json:"videos"`
}
`json:"task_result"`
CreatedAt
int64
`json:"created_at"`
UpdatedAt
int64
`json:"updated_at"`
}
`json:"data"`
}
`json:"data"`
}
}
...
@@ -94,7 +106,7 @@ func (a *TaskAdaptor) ValidateRequestAndSetAction(c *gin.Context, info *relaycom
...
@@ -94,7 +106,7 @@ func (a *TaskAdaptor) ValidateRequestAndSetAction(c *gin.Context, info *relaycom
}
}
// Store into context for later usage
// Store into context for later usage
c
.
Set
(
"
kling
_request"
,
req
)
c
.
Set
(
"
task
_request"
,
req
)
return
nil
return
nil
}
}
...
@@ -120,7 +132,7 @@ func (a *TaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info
...
@@ -120,7 +132,7 @@ func (a *TaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info
// BuildRequestBody converts request into Kling specific format.
// BuildRequestBody converts request into Kling specific format.
func
(
a
*
TaskAdaptor
)
BuildRequestBody
(
c
*
gin
.
Context
,
info
*
relaycommon
.
TaskRelayInfo
)
(
io
.
Reader
,
error
)
{
func
(
a
*
TaskAdaptor
)
BuildRequestBody
(
c
*
gin
.
Context
,
info
*
relaycommon
.
TaskRelayInfo
)
(
io
.
Reader
,
error
)
{
v
,
exists
:=
c
.
Get
(
"
kling
_request"
)
v
,
exists
:=
c
.
Get
(
"
task
_request"
)
if
!
exists
{
if
!
exists
{
return
nil
,
fmt
.
Errorf
(
"request not found in context"
)
return
nil
,
fmt
.
Errorf
(
"request not found in context"
)
}
}
...
@@ -156,8 +168,8 @@ func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *rela
...
@@ -156,8 +168,8 @@ func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *rela
// Attempt Kling response parse first.
// Attempt Kling response parse first.
var
kResp
responsePayload
var
kResp
responsePayload
if
err
:=
json
.
Unmarshal
(
responseBody
,
&
kResp
);
err
==
nil
&&
kResp
.
Code
==
0
{
if
err
:=
json
.
Unmarshal
(
responseBody
,
&
kResp
);
err
==
nil
&&
kResp
.
Code
==
0
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"task_id"
:
kResp
.
Data
.
TaskI
D
})
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"task_id"
:
kResp
.
Data
.
TaskI
d
})
return
kResp
.
Data
.
TaskI
D
,
responseBody
,
nil
return
kResp
.
Data
.
TaskI
d
,
responseBody
,
nil
}
}
// Fallback generic task response.
// Fallback generic task response.
...
@@ -199,10 +211,6 @@ func (a *TaskAdaptor) FetchTask(baseUrl, key string, body map[string]any) (*http
...
@@ -199,10 +211,6 @@ func (a *TaskAdaptor) FetchTask(baseUrl, key string, body map[string]any) (*http
token
=
key
token
=
key
}
}
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
15
*
time
.
Second
)
defer
cancel
()
req
=
req
.
WithContext
(
ctx
)
req
.
Header
.
Set
(
"Accept"
,
"application/json"
)
req
.
Header
.
Set
(
"Accept"
,
"application/json"
)
req
.
Header
.
Set
(
"Authorization"
,
"Bearer "
+
token
)
req
.
Header
.
Set
(
"Authorization"
,
"Bearer "
+
token
)
req
.
Header
.
Set
(
"User-Agent"
,
"kling-sdk/1.0"
)
req
.
Header
.
Set
(
"User-Agent"
,
"kling-sdk/1.0"
)
...
@@ -305,27 +313,33 @@ func (a *TaskAdaptor) createJWTTokenWithKeys(accessKey, secretKey string) (strin
...
@@ -305,27 +313,33 @@ func (a *TaskAdaptor) createJWTTokenWithKeys(accessKey, secretKey string) (strin
return
token
.
SignedString
([]
byte
(
secretKey
))
return
token
.
SignedString
([]
byte
(
secretKey
))
}
}
// ParseResultUrl 提取视频任务结果的 url
func
(
a
*
TaskAdaptor
)
ParseTaskResult
(
respBody
[]
byte
)
(
*
relaycommon
.
TaskInfo
,
error
)
{
func
(
a
*
TaskAdaptor
)
ParseResultUrl
(
resp
map
[
string
]
any
)
(
string
,
error
)
{
resPayload
:=
responsePayload
{}
data
,
ok
:=
resp
[
"data"
]
.
(
map
[
string
]
any
)
err
:=
json
.
Unmarshal
(
respBody
,
&
resPayload
)
if
!
ok
{
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"data field not found or invalid"
)
return
nil
,
errors
.
Wrap
(
err
,
"failed to unmarshal response body"
)
}
taskResult
,
ok
:=
data
[
"task_result"
]
.
(
map
[
string
]
any
)
if
!
ok
{
return
""
,
fmt
.
Errorf
(
"task_result field not found or invalid"
)
}
videos
,
ok
:=
taskResult
[
"videos"
]
.
([]
interface
{})
if
!
ok
||
len
(
videos
)
==
0
{
return
""
,
fmt
.
Errorf
(
"videos field not found or empty"
)
}
}
video
,
ok
:=
videos
[
0
]
.
(
map
[
string
]
interface
{})
taskInfo
:=
&
relaycommon
.
TaskInfo
{}
if
!
ok
{
taskInfo
.
Code
=
resPayload
.
Code
return
""
,
fmt
.
Errorf
(
"video item invalid"
)
taskInfo
.
TaskID
=
resPayload
.
Data
.
TaskId
taskInfo
.
Reason
=
resPayload
.
Message
//任务状态,枚举值:submitted(已提交)、processing(处理中)、succeed(成功)、failed(失败)
status
:=
resPayload
.
Data
.
TaskStatus
switch
status
{
case
"submitted"
:
taskInfo
.
Status
=
model
.
TaskStatusSubmitted
case
"processing"
:
taskInfo
.
Status
=
model
.
TaskStatusInProgress
case
"succeed"
:
taskInfo
.
Status
=
model
.
TaskStatusSuccess
case
"failed"
:
taskInfo
.
Status
=
model
.
TaskStatusFailure
default
:
return
nil
,
fmt
.
Errorf
(
"unknown task status: %s"
,
status
)
}
}
url
,
ok
:=
video
[
"url"
]
.
(
string
)
if
videos
:=
resPayload
.
Data
.
TaskResult
.
Videos
;
len
(
videos
)
>
0
{
if
!
ok
||
url
==
""
{
video
:=
videos
[
0
]
return
""
,
fmt
.
Errorf
(
"url field not found or invalid"
)
taskInfo
.
Url
=
video
.
Url
}
}
return
url
,
nil
return
taskInfo
,
nil
}
}
relay/channel/task/suno/adaptor.go
View file @
221d2b55
...
@@ -22,8 +22,8 @@ type TaskAdaptor struct {
...
@@ -22,8 +22,8 @@ type TaskAdaptor struct {
ChannelType
int
ChannelType
int
}
}
func
(
a
*
TaskAdaptor
)
Parse
ResultUrl
(
resp
map
[
string
]
any
)
(
string
,
error
)
{
func
(
a
*
TaskAdaptor
)
Parse
TaskResult
([]
byte
)
(
*
relaycommon
.
TaskInfo
,
error
)
{
return
""
,
nil
// todo implement this method if needed
return
nil
,
fmt
.
Errorf
(
"not implement"
)
// todo implement this method if needed
}
}
func
(
a
*
TaskAdaptor
)
Init
(
info
*
relaycommon
.
TaskRelayInfo
)
{
func
(
a
*
TaskAdaptor
)
Init
(
info
*
relaycommon
.
TaskRelayInfo
)
{
...
...
relay/common/relay_info.go
View file @
221d2b55
...
@@ -313,3 +313,22 @@ func GenTaskRelayInfo(c *gin.Context) *TaskRelayInfo {
...
@@ -313,3 +313,22 @@ func GenTaskRelayInfo(c *gin.Context) *TaskRelayInfo {
}
}
return
info
return
info
}
}
type
TaskSubmitReq
struct
{
Prompt
string
`json:"prompt"`
Model
string
`json:"model,omitempty"`
Mode
string
`json:"mode,omitempty"`
Image
string
`json:"image,omitempty"`
Size
string
`json:"size,omitempty"`
Duration
int
`json:"duration,omitempty"`
Metadata
map
[
string
]
interface
{}
`json:"metadata,omitempty"`
}
type
TaskInfo
struct
{
Code
int
`json:"code"`
TaskID
string
`json:"task_id"`
Status
string
`json:"status"`
Reason
string
`json:"reason,omitempty"`
Url
string
`json:"url,omitempty"`
Progress
string
`json:"progress,omitempty"`
}
relay/constant/relay_mode.go
View file @
221d2b55
...
@@ -41,6 +41,9 @@ const (
...
@@ -41,6 +41,9 @@ const (
RelayModeKlingFetchByID
RelayModeKlingFetchByID
RelayModeKlingSubmit
RelayModeKlingSubmit
RelayModeJimengFetchByID
RelayModeJimengSubmit
RelayModeRerank
RelayModeRerank
RelayModeResponses
RelayModeResponses
...
@@ -146,3 +149,13 @@ func Path2RelayKling(method, path string) int {
...
@@ -146,3 +149,13 @@ func Path2RelayKling(method, path string) int {
}
}
return
relayMode
return
relayMode
}
}
func
Path2RelayJimeng
(
method
,
path
string
)
int
{
relayMode
:=
RelayModeUnknown
if
method
==
http
.
MethodPost
&&
strings
.
HasSuffix
(
path
,
"/video/generations"
)
{
relayMode
=
RelayModeJimengSubmit
}
else
if
method
==
http
.
MethodGet
&&
strings
.
Contains
(
path
,
"/video/generations/"
)
{
relayMode
=
RelayModeJimengFetchByID
}
return
relayMode
}
relay/relay_adaptor.go
View file @
221d2b55
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"one-api/relay/channel/palm"
"one-api/relay/channel/palm"
"one-api/relay/channel/perplexity"
"one-api/relay/channel/perplexity"
"one-api/relay/channel/siliconflow"
"one-api/relay/channel/siliconflow"
"one-api/relay/channel/task/jimeng"
"one-api/relay/channel/task/kling"
"one-api/relay/channel/task/kling"
"one-api/relay/channel/task/suno"
"one-api/relay/channel/task/suno"
"one-api/relay/channel/tencent"
"one-api/relay/channel/tencent"
...
@@ -104,6 +105,8 @@ func GetTaskAdaptor(platform commonconstant.TaskPlatform) channel.TaskAdaptor {
...
@@ -104,6 +105,8 @@ func GetTaskAdaptor(platform commonconstant.TaskPlatform) channel.TaskAdaptor {
return
&
suno
.
TaskAdaptor
{}
return
&
suno
.
TaskAdaptor
{}
case
commonconstant
.
TaskPlatformKling
:
case
commonconstant
.
TaskPlatformKling
:
return
&
kling
.
TaskAdaptor
{}
return
&
kling
.
TaskAdaptor
{}
case
commonconstant
.
TaskPlatformJimeng
:
return
&
jimeng
.
TaskAdaptor
{}
}
}
return
nil
return
nil
}
}
relay/relay_task.go
View file @
221d2b55
...
@@ -245,7 +245,7 @@ func sunoFetchByIDRespBodyBuilder(c *gin.Context) (respBody []byte, taskResp *dt
...
@@ -245,7 +245,7 @@ func sunoFetchByIDRespBodyBuilder(c *gin.Context) (respBody []byte, taskResp *dt
}
}
func
videoFetchByIDRespBodyBuilder
(
c
*
gin
.
Context
)
(
respBody
[]
byte
,
taskResp
*
dto
.
TaskError
)
{
func
videoFetchByIDRespBodyBuilder
(
c
*
gin
.
Context
)
(
respBody
[]
byte
,
taskResp
*
dto
.
TaskError
)
{
taskId
:=
c
.
Param
(
"id"
)
taskId
:=
c
.
Param
(
"
task_
id"
)
userId
:=
c
.
GetInt
(
"id"
)
userId
:=
c
.
GetInt
(
"id"
)
originTask
,
exist
,
err
:=
model
.
GetByTaskId
(
userId
,
taskId
)
originTask
,
exist
,
err
:=
model
.
GetByTaskId
(
userId
,
taskId
)
...
...
web/src/components/table/TaskLogsTable.js
View file @
221d2b55
...
@@ -230,8 +230,8 @@ const LogsTable = () => {
...
@@ -230,8 +230,8 @@ const LogsTable = () => {
}
}
};
};
const
renderPlatform
=
(
type
)
=>
{
const
renderPlatform
=
(
platform
)
=>
{
switch
(
type
)
{
switch
(
platform
)
{
case
'suno'
:
case
'suno'
:
return
(
return
(
<
Tag
color
=
'green'
size
=
'large'
shape
=
'circle'
prefixIcon
=
{
<
Music
size
=
{
14
}
/>}
>
<
Tag
color
=
'green'
size
=
'large'
shape
=
'circle'
prefixIcon
=
{
<
Music
size
=
{
14
}
/>}
>
...
@@ -240,10 +240,16 @@ const LogsTable = () => {
...
@@ -240,10 +240,16 @@ const LogsTable = () => {
);
);
case
'kling'
:
case
'kling'
:
return
(
return
(
<
Tag
color
=
'
blu
e'
size
=
'large'
shape
=
'circle'
prefixIcon
=
{
<
Video
size
=
{
14
}
/>}
>
<
Tag
color
=
'
orang
e'
size
=
'large'
shape
=
'circle'
prefixIcon
=
{
<
Video
size
=
{
14
}
/>}
>
Kling
Kling
<
/Tag
>
<
/Tag
>
);
);
case
'jimeng'
:
return
(
<
Tag
color
=
'purple'
size
=
'large'
shape
=
'circle'
prefixIcon
=
{
<
Video
size
=
{
14
}
/>}
>
Jimeng
<
/Tag
>
);
default
:
default
:
return
(
return
(
<
Tag
color
=
'white'
size
=
'large'
shape
=
'circle'
prefixIcon
=
{
<
HelpCircle
size
=
{
14
}
/>}
>
<
Tag
color
=
'white'
size
=
'large'
shape
=
'circle'
prefixIcon
=
{
<
HelpCircle
size
=
{
14
}
/>}
>
...
...
web/src/constants/channel.constants.js
View file @
221d2b55
...
@@ -130,6 +130,11 @@ export const CHANNEL_OPTIONS = [
...
@@ -130,6 +130,11 @@ export const CHANNEL_OPTIONS = [
color
:
'green'
,
color
:
'green'
,
label
:
'可灵'
,
label
:
'可灵'
,
},
},
{
value
:
51
,
color
:
'blue'
,
label
:
'即梦'
,
},
];
];
export
const
MODEL_TABLE_PAGE_SIZE
=
10
;
export
const
MODEL_TABLE_PAGE_SIZE
=
10
;
web/src/i18n/locales/en.json
View file @
221d2b55
...
@@ -801,6 +801,7 @@
...
@@ -801,6 +801,7 @@
"获取无水印"
:
"Get no watermark"
,
"获取无水印"
:
"Get no watermark"
,
"生成图片"
:
"Generate pictures"
,
"生成图片"
:
"Generate pictures"
,
"可灵"
:
"Kling"
,
"可灵"
:
"Kling"
,
"即梦"
:
"Jimeng"
,
"正在提交"
:
"Submitting"
,
"正在提交"
:
"Submitting"
,
"执行中"
:
"processing"
,
"执行中"
:
"processing"
,
"平台"
:
"platform"
,
"平台"
:
"platform"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment