Skip to content

Commit

Permalink
支持外部请求更换cookie
Browse files Browse the repository at this point in the history
  • Loading branch information
disingn committed Mar 29, 2024
1 parent 3eebeef commit 3296850
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 27 deletions.
2 changes: 0 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package main
import (
"fksunoapi/cfg"
"fksunoapi/router"
"fksunoapi/serve"
"github.com/gofiber/fiber/v2"
)

func init() {
cfg.ConfigInit()
serve.Session = serve.GetSession()
}

func main() {
Expand Down
25 changes: 25 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,31 @@ App:
./sunoweb2api
```
#### 3. 使用方式

下列 api 都可以增加一个Header参数
```shell
Authorization : Bearer Client
```
其中Client为登录 suno.ai 后的 cookie中的__client=xxxxx 的值

如果不填写 默认使用config.yaml中的配置中的 Client

示例:
```shell
curl --location --request POST 'localhost:3560/v1/chat/completions' \
--header 'Authorization: Bearer client' \
--header 'Content-Type: application/json' \
--data-raw '{
"model": "chirp-v3-0",
"messages": [
{
"role": "user",
"content": "制作歌曲《万能的数字》"
}
]
}'
```

创建音乐任务
```shell
curl --location --request POST 'localhost:3560/v2/generate' \
Expand Down
34 changes: 29 additions & 5 deletions router/router.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package router

import (
"fksunoapi/cfg"
"fksunoapi/serve"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger"
)

Expand All @@ -12,12 +14,19 @@ func CreateTask() fiber.Handler {
if err := c.BodyParser(&data); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(serve.NewErrorResponse(serve.ErrCodeJsonFailed, "Cannot parse JSON"))
}
ck := c.Get("Authorization")
if ck == "" {
ck = cfg.Config.App.Client
} else {
ck = serve.ParseToken(ck)
}
serve.Session = serve.GetSession(ck)
var body []byte
var errResp *serve.ErrorResponse
if c.Path() == "/v2/generate" {
body, errResp = serve.V2Generate(data)
body, errResp = serve.V2Generate(data, ck)
} else if c.Path() == "/v2/lyrics/create" {
body, errResp = serve.GenerateLyrics(data)
body, errResp = serve.GenerateLyrics(data, ck)
}
if errResp != nil {
return c.Status(fiber.StatusInternalServerError).JSON(errResp)
Expand All @@ -36,12 +45,19 @@ func GetTask() fiber.Handler {
if len(data["ids"]) == 0 {
return c.Status(fiber.StatusBadRequest).JSON(serve.NewErrorResponse(serve.ErrCodeRequestFailed, "Cannot find ids"))
}
ck := c.Get("Authorization")
if ck == "" {
ck = cfg.Config.App.Client
} else {
ck = serve.ParseToken(ck)
}
serve.Session = serve.GetSession(ck)
var body []byte
var errResp *serve.ErrorResponse
if c.Path() == "/v2/feed" {
body, errResp = serve.V2GetFeedTask(data["ids"])
body, errResp = serve.V2GetFeedTask(data["ids"], ck)
} else if c.Path() == "/v2/lyrics/task" {
body, errResp = serve.GetLyricsTask(data["ids"])
body, errResp = serve.GetLyricsTask(data["ids"], ck)
}
if errResp != nil {
return c.Status(fiber.StatusInternalServerError).JSON(errResp)
Expand All @@ -56,7 +72,14 @@ func SunoChat() fiber.Handler {
if err := c.BodyParser(&data); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(serve.NewErrorResponse(serve.ErrCodeJsonFailed, "Cannot parse JSON"))
}
res, errResp := serve.SunoChat(data)
ck := c.Get("Authorization")
if ck == "" {
ck = cfg.Config.App.Client
} else {
ck = serve.ParseToken(ck)
}
serve.Session = serve.GetSession(ck)
res, errResp := serve.SunoChat(data, ck)
if errResp != nil {
return c.Status(fiber.StatusInternalServerError).JSON(errResp)
}
Expand All @@ -66,6 +89,7 @@ func SunoChat() fiber.Handler {

func SetupRoutes(app *fiber.App) {
app.Use(logger.New(logger.ConfigDefault))
app.Use(cors.New(cors.ConfigDefault))
app.Post("/v2/generate", CreateTask())
app.Post("/v2/feed", GetTask())
app.Post("/v2/lyrics/create", CreateTask())
Expand Down
39 changes: 19 additions & 20 deletions serve/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package serve
import (
"bytes"
"encoding/json"
"fksunoapi/cfg"
"fksunoapi/models"
"fmt"
"io"
Expand Down Expand Up @@ -45,13 +44,13 @@ func NewErrorResponseWithError(errorCode int, err error) *ErrorResponse {
}
}

func GetSession() string {
func GetSession(c string) string {
_url := "https://clerk.suno.ai/v1/client?_clerk_js_version=4.70.5"
method := "GET"
client := &http.Client{}
req, err := http.NewRequest(method, _url, nil)
req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36")
req.Header.Add("Cookie", "__client="+cfg.Config.App.Client)
req.Header.Add("Cookie", "__client="+c)
res, err := client.Do(req)
if err != nil {
log.Printf("GetSession failed, error: %v", err)
Expand All @@ -72,9 +71,9 @@ func GetSession() string {
return data.Response.Sessions[0].Id
}

func GetJwtToken() (string, *ErrorResponse) {
if time.Now().After(time.Unix(SessionExp, 0)) {
Session = GetSession()
func GetJwtToken(c string) (string, *ErrorResponse) {
if time.Now().After(time.Unix(SessionExp/1000, 0)) {
Session = GetSession(c)
}
_url := fmt.Sprintf("https://clerk.suno.ai/v1/client/sessions/%s/tokens?_clerk_js_version=4.70.5", Session)
method := "POST"
Expand All @@ -87,7 +86,7 @@ func GetJwtToken() (string, *ErrorResponse) {
return "", NewErrorResponse(ErrCodeRequestFailed, "create request failed")
}
req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36")
req.Header.Add("Cookie", "__client="+cfg.Config.App.Client)
req.Header.Add("Cookie", "__client="+c)

res, err := client.Do(req)
if err != nil {
Expand Down Expand Up @@ -115,8 +114,8 @@ func GetJwtToken() (string, *ErrorResponse) {
return data.Jwt, nil
}

func sendRequest(url, method string, data []byte) ([]byte, *ErrorResponse) {
jwt, errResp := GetJwtToken()
func sendRequest(url, method, c string, data []byte) ([]byte, *ErrorResponse) {
jwt, errResp := GetJwtToken(c)
if errResp != nil {
errMsg := fmt.Sprintf("error getting JWT: %s", errResp.ErrorMsg)
log.Printf("sendRequest failed, %s", errMsg)
Expand Down Expand Up @@ -155,62 +154,62 @@ func sendRequest(url, method string, data []byte) ([]byte, *ErrorResponse) {
return body, nil
}

func V2Generate(d map[string]interface{}) ([]byte, *ErrorResponse) {
func V2Generate(d map[string]interface{}, c string) ([]byte, *ErrorResponse) {
_url := "https://studio-api.suno.ai/api/generate/v2/"
jsonData, err := json.Marshal(d)
if err != nil {
log.Printf("V2Generate failed, error marshalling request data: %v", err)
return nil, NewErrorResponseWithError(ErrCodeJsonFailed, err)
}
body, errResp := sendRequest(_url, "POST", jsonData)
body, errResp := sendRequest(_url, "POST", c, jsonData)
if errResp != nil {
return body, errResp
}
return body, nil
}

func V2GetFeedTask(ids string) ([]byte, *ErrorResponse) {
func V2GetFeedTask(ids, c string) ([]byte, *ErrorResponse) {
ids = url.QueryEscape(ids)
_url := "https://studio-api.suno.ai/api/feed/?ids=" + ids
body, errResp := sendRequest(_url, "GET", nil)
body, errResp := sendRequest(_url, "GET", c, nil)
if errResp != nil {
return body, errResp
}
return body, nil
}

func GenerateLyrics(d map[string]interface{}) ([]byte, *ErrorResponse) {
func GenerateLyrics(d map[string]interface{}, c string) ([]byte, *ErrorResponse) {
_url := "https://studio-api.suno.ai/api/generate/lyrics/"
jsonData, err := json.Marshal(d)
if err != nil {
log.Printf("GenerateLyrics failed, error marshalling request data: %v", err)
return nil, NewErrorResponseWithError(ErrCodeJsonFailed, err)
}
body, errResp := sendRequest(_url, "POST", jsonData)
body, errResp := sendRequest(_url, "POST", c, jsonData)
if errResp != nil {
return body, errResp
}
return body, nil
}

func GetLyricsTask(ids string) ([]byte, *ErrorResponse) {
func GetLyricsTask(ids, c string) ([]byte, *ErrorResponse) {
_url := "https://studio-api.suno.ai/api/generate/lyrics/" + ids
body, errResp := sendRequest(_url, "GET", nil)
body, errResp := sendRequest(_url, "GET", c, nil)
if errResp != nil {
return body, errResp
}
return body, nil
}

func SunoChat(c map[string]interface{}) (interface{}, *ErrorResponse) {
func SunoChat(c map[string]interface{}, ck string) (interface{}, *ErrorResponse) {
lastUserContent := getLastUserContent(c)
d := map[string]interface{}{
"mv": c["model"].(string),
"gpt_description_prompt": lastUserContent,
"prompt": "",
"make_instrumental": false,
}
body, errResp := V2Generate(d)
body, errResp := V2Generate(d, ck)
if errResp != nil {
return nil, errResp
}
Expand All @@ -235,7 +234,7 @@ func SunoChat(c map[string]interface{}) (interface{}, *ErrorResponse) {
case <-timeout:
return nil, NewErrorResponse(ErrCodeTimeout, "get feed task timeout")
case <-tick:
body, errResp = V2GetFeedTask(ids)
body, errResp = V2GetFeedTask(ids, ck)
if errResp != nil {
return nil, errResp
}
Expand Down
16 changes: 16 additions & 0 deletions serve/u.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package serve

import (
"strings"
)

type Claims struct {
Exp int64 `json:"exp"`
}
Expand Down Expand Up @@ -32,3 +36,15 @@ func getLastUserContent(data map[string]interface{}) string {

return lastUserContent
}

func ParseToken(authorizationHeader string) string {
if authorizationHeader == "" {
return ""
}
parts := strings.Split(authorizationHeader, " ")
if len(parts) == 2 && parts[0] == "Bearer" {
return parts[1]
}

return ""
}

0 comments on commit 3296850

Please sign in to comment.