mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-17 13:57:10 +00:00
commit
07831d6108
6 changed files with 217 additions and 70 deletions
|
|
@ -253,16 +253,20 @@ class Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
opt.onSunoCreateRequest = prompt => {
|
opt.onSunoCreateRequest = prompt => {
|
||||||
logger.mark(`开始生成内容:Suno ${prompt.songtId}`)
|
logger.mark(`开始生成内容:Suno ${prompt.songtId || ''}`)
|
||||||
let client = new BingSunoClient({
|
let client = new BingSunoClient({
|
||||||
cookies: cookies
|
cookies: cookies
|
||||||
})
|
})
|
||||||
redis.set(`CHATGPT:SUNO:${e.sender.user_id}`, 'c', { EX: 30 }).then(() => {
|
redis.set(`CHATGPT:SUNO:${e.sender.user_id}`, 'c', { EX: 30 }).then(() => {
|
||||||
try {
|
try {
|
||||||
if (Config.bingLocalSuno) {
|
if (Config.bingSuno == 'local') {
|
||||||
// 调用本地Suno配置进行歌曲生成
|
// 调用本地Suno配置进行歌曲生成
|
||||||
client.getLocalSuno(prompt, e)
|
client.getLocalSuno(prompt, e)
|
||||||
|
} else if (Config.bingSuno == 'api' && Config.bingSunoApi) {
|
||||||
|
// 调用第三方Suno配置进行歌曲生成
|
||||||
|
client.getApiSuno(prompt, e)
|
||||||
} else {
|
} else {
|
||||||
|
// 调用Bing Suno进行歌曲生成
|
||||||
client.getSuno(prompt, e)
|
client.getSuno(prompt, e)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
||||||
|
|
@ -575,6 +575,16 @@
|
||||||
"label": "允许生成图像等内容",
|
"label": "允许生成图像等内容",
|
||||||
"data": "enableGenerateContents"
|
"data": "enableGenerateContents"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "check",
|
||||||
|
"label": "允许生成歌曲等内容",
|
||||||
|
"data": "enableGenerateSuno"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "check",
|
||||||
|
"label": "伪造歌曲生成",
|
||||||
|
"data": "enableGenerateSunoForger"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "url",
|
"type": "url",
|
||||||
"label": "必应验证码pass服务",
|
"label": "必应验证码pass服务",
|
||||||
|
|
@ -588,10 +598,16 @@
|
||||||
"data": "bingAPDraw"
|
"data": "bingAPDraw"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "check",
|
"type": "select",
|
||||||
"label": "第三方歌曲生成",
|
"label": "歌曲生成模式",
|
||||||
"placeholder": "使用AP插件代替Bing进行绘图",
|
"data": "bingSuno",
|
||||||
"data": "bingLocalSuno"
|
"items": [ { "label": "Bing", "value": "bing" }, { "label": "本地", "value": "local" }, { "label": "第三方", "value": "api" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "url",
|
||||||
|
"label": "第三方歌曲生成API地址",
|
||||||
|
"placeholder": "https://github.com/gcui-art/suno-api的api地址",
|
||||||
|
"data": "bingSunoApi"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "textarea",
|
"type": "textarea",
|
||||||
|
|
@ -1118,7 +1134,14 @@
|
||||||
"label": "Sydney模式接受首条信息超时时间",
|
"label": "Sydney模式接受首条信息超时时间",
|
||||||
"placeholder": "超过该时间阈值未收到Bing的任何消息,则断开本次连接并重试",
|
"placeholder": "超过该时间阈值未收到Bing的任何消息,则断开本次连接并重试",
|
||||||
"data": "sydneyFirstMessageTimeout"
|
"data": "sydneyFirstMessageTimeout"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number",
|
||||||
|
"label": "SunoApi获取超时时间",
|
||||||
|
"placeholder": "使用sunoApi获取数据时超时时间,单位秒",
|
||||||
|
"data": "sunoApiTimeout"
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import common from '../../../lib/common/common.js'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
import fetch from 'node-fetch'
|
import fetch from 'node-fetch'
|
||||||
import lodash from 'lodash'
|
|
||||||
|
|
||||||
export default class BingSunoClient {
|
export default class BingSunoClient {
|
||||||
constructor(opts) {
|
constructor(opts) {
|
||||||
|
|
@ -14,14 +13,14 @@ export default class BingSunoClient {
|
||||||
|
|
||||||
async replyMsg(song, e) {
|
async replyMsg(song, e) {
|
||||||
let messages = []
|
let messages = []
|
||||||
messages.push(`歌名:${song.title}\n风格: ${song.musicalStyle}\n长度: ${song.duration}秒\n歌词:\n${song.prompt}\n`)
|
messages.push(`歌名:${song.title}\n风格: ${song.musicalStyle}\n歌词:\n${song.prompt}\n`)
|
||||||
messages.push(`音频链接:${song.audioURL}\n视频链接:${song.videoURL}\n封面链接:${song.imageURL}\n`)
|
messages.push(`音频链接:${song.audioURL}\n视频链接:${song.videoURL}\n封面链接:${song.imageURL}\n`)
|
||||||
messages.push(segment.image(song.imageURL))
|
messages.push(segment.image(song.imageURL))
|
||||||
let retry = 3
|
let retry = 3
|
||||||
let videoPath
|
let videoPath
|
||||||
while (!videoPath && retry >= 0) {
|
while (!videoPath && retry >= 0) {
|
||||||
try {
|
try {
|
||||||
videoPath = await downloadFile(song.video_url, `suno/${song.title}.mp4`, false, false, {
|
videoPath = await downloadFile(song.videoURL, `suno/${song.title}.mp4`, false, false, {
|
||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -47,7 +46,6 @@ export default class BingSunoClient {
|
||||||
if (prompt.cookie) {
|
if (prompt.cookie) {
|
||||||
this.opts.cookies = prompt.cookie
|
this.opts.cookies = prompt.cookie
|
||||||
}
|
}
|
||||||
|
|
||||||
const sunoResult = await this.getSunoResult(prompt.songtId)
|
const sunoResult = await this.getSunoResult(prompt.songtId)
|
||||||
if (sunoResult) {
|
if (sunoResult) {
|
||||||
const {
|
const {
|
||||||
|
|
@ -72,78 +70,154 @@ export default class BingSunoClient {
|
||||||
prompt: prompt.songPrompt
|
prompt: prompt.songPrompt
|
||||||
}
|
}
|
||||||
await e.reply('Bing Suno 生成中,请稍后')
|
await e.reply('Bing Suno 生成中,请稍后')
|
||||||
replyMsg(sunoDisplayResult, e)
|
this.replyMsg(sunoDisplayResult, e)
|
||||||
} else {
|
} else {
|
||||||
await e.reply('Bing Suno 数据获取失败')
|
await e.reply('Bing Suno 数据获取失败')
|
||||||
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||||
}
|
}
|
||||||
|
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLocalSuno(prompt, e) {
|
async getLocalSuno(prompt, e) {
|
||||||
if (!Config.sunoClientToken || !Config.sunoSessToken) {
|
if (!Config.sunoClientToken || !Config.sunoSessToken) {
|
||||||
await e.reply('未配置Suno Token')
|
await e.reply('未配置Suno Token')
|
||||||
|
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
let description = prompt.songPrompt
|
let description = prompt.songPrompt
|
||||||
await e.reply('正在生成,请稍后')
|
await e.reply('正在生成,请稍后')
|
||||||
try {
|
try {
|
||||||
let sessTokens = Config.sunoSessToken.split(',')
|
let sessTokens = Config.sunoSessToken.split(',')
|
||||||
let clientTokens = Config.sunoClientToken.split(',')
|
let clientTokens = Config.sunoClientToken.split(',')
|
||||||
let tried = 0
|
let tried = 0
|
||||||
while (tried < sessTokens.length) {
|
while (tried < sessTokens.length) {
|
||||||
let index = tried
|
let index = tried
|
||||||
let sess = sessTokens[index]
|
let sess = sessTokens[index]
|
||||||
let clientToken = clientTokens[index]
|
let clientToken = clientTokens[index]
|
||||||
let client = new SunoClient({ sessToken: sess, clientToken })
|
let client = new SunoClient({ sessToken: sess, clientToken })
|
||||||
let { credit, email } = await client.queryCredit()
|
let { credit, email } = await client.queryCredit()
|
||||||
logger.info({ credit, email })
|
logger.info({ credit, email })
|
||||||
if (credit < 10) {
|
if (credit < 10) {
|
||||||
tried++
|
tried++
|
||||||
logger.info(`账户${email}余额不足,尝试下一个账户`)
|
logger.info(`账户${email}余额不足,尝试下一个账户`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let songs = await client.createSong(description)
|
let songs = await client.createSong(description)
|
||||||
if (!songs || songs.length === 0) {
|
if (!songs || songs.length === 0) {
|
||||||
e.reply('生成失败,可能是提示词太长或者违规,请检查日志')
|
e.reply('生成失败,可能是提示词太长或者违规,请检查日志')
|
||||||
return
|
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||||
}
|
return
|
||||||
let messages = ['提示词:' + description]
|
|
||||||
for (let song of songs) {
|
|
||||||
messages.push(`歌名:${song.title}\n风格: ${song.metadata.tags}\n长度: ${lodash.round(song.metadata.duration, 0)}秒\n歌词:\n${song.metadata.prompt}\n`)
|
|
||||||
messages.push(`音频链接:${song.audio_url}\n视频链接:${song.video_url}\n封面链接:${song.image_url}\n`)
|
|
||||||
messages.push(segment.image(song.image_url))
|
|
||||||
let retry = 3
|
|
||||||
let videoPath
|
|
||||||
while (!videoPath && retry >= 0) {
|
|
||||||
try {
|
|
||||||
videoPath = await downloadFile(song.video_url, `suno/${song.title}.mp4`, false, false, {
|
|
||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
retry--
|
|
||||||
await common.sleep(1000)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (videoPath) {
|
let messages = ['提示词:' + description]
|
||||||
const data = fs.readFileSync(videoPath)
|
for (let song of songs) {
|
||||||
messages.push(segment.video(`base64://${data.toString('base64')}`))
|
messages.push(`歌名:${song.title}\n风格: ${song.metadata.tags}\n歌词:\n${song.metadata.prompt}\n`)
|
||||||
// 60秒后删除文件避免占用体积
|
messages.push(`音频链接:${song.audio_url}\n视频链接:${song.video_url}\n封面链接:${song.image_url}\n`)
|
||||||
setTimeout(() => {
|
messages.push(segment.image(song.image_url))
|
||||||
fs.unlinkSync(videoPath)
|
let retry = 3
|
||||||
}, 60000)
|
let videoPath
|
||||||
} else {
|
while (!videoPath && retry >= 0) {
|
||||||
logger.warn(`${song.title}下载视频失败,仅发送视频链接`)
|
try {
|
||||||
|
videoPath = await downloadFile(song.video_url, `suno/${song.title}.mp4`, false, false, {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36'
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
retry--
|
||||||
|
await common.sleep(1000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (videoPath) {
|
||||||
|
const data = fs.readFileSync(videoPath)
|
||||||
|
messages.push(segment.video(`base64://${data.toString('base64')}`))
|
||||||
|
// 60秒后删除文件避免占用体积
|
||||||
|
setTimeout(() => {
|
||||||
|
fs.unlinkSync(videoPath)
|
||||||
|
}, 60000)
|
||||||
|
} else {
|
||||||
|
logger.warn(`${song.title}下载视频失败,仅发送视频链接`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
await e.reply(await common.makeForwardMsg(e, messages, '音乐合成结果'))
|
||||||
await e.reply(await common.makeForwardMsg(e, messages, '音乐合成结果'))
|
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
await e.reply('所有账户余额不足')
|
await e.reply('所有账户余额不足')
|
||||||
} catch (err) {
|
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||||
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
await e.reply('生成失败,请查看日志')
|
await e.reply('生成失败,请查看日志')
|
||||||
}
|
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getApiSuno(prompt, e) {
|
||||||
|
if (!Config.bingSunoApi) {
|
||||||
|
await e.reply('未配置 Suno API')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const responseId = await fetch(`${Config.bingSunoApi}/api/custom_generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
"prompt": prompt.songPrompt || prompt.lyrics,
|
||||||
|
"tags": prompt.tags || "pop",
|
||||||
|
"title": prompt.title || e.sender.card || e.sender.nickname,
|
||||||
|
"make_instrumental": false,
|
||||||
|
"wait_audio": false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const sunoId = await responseId.json()
|
||||||
|
if (sunoId[0]?.id) {
|
||||||
|
await e.reply('Bing Suno 生成中,请稍后')
|
||||||
|
let timeoutTimes = Config.sunoApiTimeout
|
||||||
|
let timer = setInterval(async () => {
|
||||||
|
const response = await fetch(`${Config.bingSunoApi}/api/get?ids=${sunoId[0]?.id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!response.ok) {
|
||||||
|
await e.reply('Bing Suno 数据获取失败')
|
||||||
|
logger.error(response.error.message)
|
||||||
|
redis.del(`CHATGPT:SUNO:${e.sender.user_id}`)
|
||||||
|
clearInterval(timer)
|
||||||
|
timer = null
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`)
|
||||||
|
}
|
||||||
|
const result = await response.json()
|
||||||
|
if (result[0].status == 'complete') {
|
||||||
|
const sunoResult = result[0]
|
||||||
|
const title = sunoResult.title
|
||||||
|
const audioURL = sunoResult.audio_url
|
||||||
|
const imageURL = sunoResult.image_url
|
||||||
|
const videoURL = sunoResult.video_url
|
||||||
|
const musicalStyle = sunoResult.tags
|
||||||
|
const prompt = sunoResult.lyric
|
||||||
|
const sunoURL = `https://cdn1.suno.ai/${sunoResult.id}.mp4`
|
||||||
|
const sunoDisplayResult = {
|
||||||
|
title,
|
||||||
|
musicalStyle,
|
||||||
|
audioURL,
|
||||||
|
imageURL,
|
||||||
|
videoURL,
|
||||||
|
sunoURL,
|
||||||
|
prompt
|
||||||
|
}
|
||||||
|
this.replyMsg(sunoDisplayResult, e)
|
||||||
|
clearInterval(timer)
|
||||||
|
} else if (timeoutTimes === 0) {
|
||||||
|
await e.reply('❌Suno 生成超时', true)
|
||||||
|
clearInterval(timer)
|
||||||
|
timer = null
|
||||||
|
} else {
|
||||||
|
logger.info('等待Suno生成中: ' + timeoutTimes)
|
||||||
|
timeoutTimes--
|
||||||
|
}
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSunoResult(requestId) {
|
async getSunoResult(requestId) {
|
||||||
|
|
@ -210,7 +284,6 @@ export default class BingSunoClient {
|
||||||
sfx: sfx.toString(),
|
sfx: sfx.toString(),
|
||||||
})
|
})
|
||||||
fetchURL.search = searchParams.toString()
|
fetchURL.search = searchParams.toString()
|
||||||
|
|
||||||
const response = await fetch(fetchURL, {
|
const response = await fetch(fetchURL, {
|
||||||
headers: {
|
headers: {
|
||||||
accept: '*/*',
|
accept: '*/*',
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import fetch, {
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
import WebSocket from 'ws'
|
import WebSocket from 'ws'
|
||||||
import { Config } from './config.js'
|
import { Config } from './config.js'
|
||||||
import { formatDate, getMasterQQ, isCN, getUserData, limitString } from './common.js'
|
import { formatDate, getMasterQQ, isCN, getUserData, limitString, extractMarkdownJson } from './common.js'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { getProxy } from './proxy.js'
|
import { getProxy } from './proxy.js'
|
||||||
import common from '../../../lib/common/common.js'
|
import common from '../../../lib/common/common.js'
|
||||||
|
|
@ -337,7 +337,8 @@ export default class SydneyAIClient {
|
||||||
const text = (useCast?.bing || Config.sydney).replaceAll(namePlaceholder, botName || defaultBotName) +
|
const text = (useCast?.bing || Config.sydney).replaceAll(namePlaceholder, botName || defaultBotName) +
|
||||||
((Config.enableGroupContext && groupId) ? groupContextTip : '') +
|
((Config.enableGroupContext && groupId) ? groupContextTip : '') +
|
||||||
((Config.enforceMaster && master) ? masterTip : '') +
|
((Config.enforceMaster && master) ? masterTip : '') +
|
||||||
(Config.sydneyMood ? moodTip : '')
|
(Config.sydneyMood ? moodTip : '') +
|
||||||
|
((!Config.enableGenerateSuno && Config.bingSuno != 'bing' && Config.enableGenerateSunoForger) ? 'If I ask you to generate music or write songs, you need to reply with information suitable for Suno to generate music. The returned message is in JSON format, with a structure of {"option": "Suno", "tags": "style", "title": "title of the song", "lyrics": "lyrics"}.' : '')
|
||||||
if (!text) {
|
if (!text) {
|
||||||
previousMessages = pm
|
previousMessages = pm
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -387,7 +388,7 @@ export default class SydneyAIClient {
|
||||||
}
|
}
|
||||||
let optionsSets = getOptionSet(Config.toneStyle, Config.enableGenerateContents)
|
let optionsSets = getOptionSet(Config.toneStyle, Config.enableGenerateContents)
|
||||||
let source = 'cib-ccp'; let gptId = 'copilot'
|
let source = 'cib-ccp'; let gptId = 'copilot'
|
||||||
if ((!Config.sydneyEnableSearch && !Config.enableGenerateContents) || toSummaryFileContent?.content) {
|
if ((!Config.sydneyEnableSearch && !Config.enableGenerateContents && !Config.enableGenerateSuno) || toSummaryFileContent?.content) {
|
||||||
optionsSets.push(...['nosearchall'])
|
optionsSets.push(...['nosearchall'])
|
||||||
}
|
}
|
||||||
if (isPro) {
|
if (isPro) {
|
||||||
|
|
@ -504,7 +505,7 @@ export default class SydneyAIClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Config.enableGenerateContents){
|
if (Config.enableGenerateSuno){
|
||||||
argument0.plugins.push({
|
argument0.plugins.push({
|
||||||
"id": "22b7f79d-8ea4-437e-b5fd-3e21f09f7bc1",
|
"id": "22b7f79d-8ea4-437e-b5fd-3e21f09f7bc1",
|
||||||
"category": 1
|
"category": 1
|
||||||
|
|
@ -714,7 +715,6 @@ export default class SydneyAIClient {
|
||||||
suggestedResponsesSoFar = message.suggestedResponses
|
suggestedResponsesSoFar = message.suggestedResponses
|
||||||
}
|
}
|
||||||
if (messages[0].contentType === 'SUNO') {
|
if (messages[0].contentType === 'SUNO') {
|
||||||
console.log()
|
|
||||||
onSunoCreateRequest({
|
onSunoCreateRequest({
|
||||||
songtId: messages[0]?.hiddenText.split('=')[1],
|
songtId: messages[0]?.hiddenText.split('=')[1],
|
||||||
songPrompt: messages[0]?.text,
|
songPrompt: messages[0]?.text,
|
||||||
|
|
@ -835,6 +835,16 @@ export default class SydneyAIClient {
|
||||||
message.adaptiveCards = adaptiveCardsSoFar
|
message.adaptiveCards = adaptiveCardsSoFar
|
||||||
message.text = replySoFar.join('')
|
message.text = replySoFar.join('')
|
||||||
}
|
}
|
||||||
|
// 伪造歌曲生成
|
||||||
|
if (Config.enableGenerateSunoForger) {
|
||||||
|
const sunoList = extractMarkdownJson(message.text)
|
||||||
|
for (let suno of sunoList) {
|
||||||
|
if (suno.option == 'Suno') {
|
||||||
|
logger.info(`开始生成歌曲${suno.tags}`)
|
||||||
|
onSunoCreateRequest(suno)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
resolve({
|
resolve({
|
||||||
message,
|
message,
|
||||||
conversationExpiryTime: event?.item?.conversationExpiryTime
|
conversationExpiryTime: event?.item?.conversationExpiryTime
|
||||||
|
|
@ -1046,7 +1056,7 @@ function getOptionSet (tone, generateContent = false) {
|
||||||
])
|
])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (Config.enableGenerateContents){
|
if (Config.enableGenerateSuno){
|
||||||
optionset.push(...[
|
optionset.push(...[
|
||||||
'014CB21D',
|
'014CB21D',
|
||||||
'B3FF9F21'
|
'B3FF9F21'
|
||||||
|
|
|
||||||
|
|
@ -1242,3 +1242,36 @@ function maskString (str) {
|
||||||
|
|
||||||
return firstThreeChars + maskedChars + lastThreeChars
|
return firstThreeChars + maskedChars + lastThreeChars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generated by ai
|
||||||
|
* @param text
|
||||||
|
* @returns {array}
|
||||||
|
*/
|
||||||
|
export function extractMarkdownJson(text) {
|
||||||
|
const lines = text.split('\n')
|
||||||
|
const mdJson = []
|
||||||
|
let currentObj = null
|
||||||
|
|
||||||
|
lines.forEach(line => {
|
||||||
|
if (line.startsWith('```json') && !currentObj) {
|
||||||
|
// 开始一个新的JSON对象
|
||||||
|
currentObj = { json: '' }
|
||||||
|
} else if (line.startsWith('```') && currentObj) {
|
||||||
|
// 结束当前的JSON对象
|
||||||
|
try {
|
||||||
|
// 尝试将JSON字符串转换为对象
|
||||||
|
currentObj.json = JSON.parse(currentObj.json)
|
||||||
|
mdJson.push(currentObj)
|
||||||
|
currentObj = null
|
||||||
|
} catch (e) {
|
||||||
|
console.error('JSON解析错误:', e)
|
||||||
|
}
|
||||||
|
} else if (currentObj) {
|
||||||
|
// 将行添加到当前的JSON对象
|
||||||
|
currentObj.json += line
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return mdJson.map(obj => obj.json)
|
||||||
|
}
|
||||||
|
|
@ -81,6 +81,7 @@ const defaultConfig = {
|
||||||
defaultTimeoutMs: 120000,
|
defaultTimeoutMs: 120000,
|
||||||
chromeTimeoutMS: 120000,
|
chromeTimeoutMS: 120000,
|
||||||
sydneyFirstMessageTimeout: 40000,
|
sydneyFirstMessageTimeout: 40000,
|
||||||
|
sunoApiTimeout: 60,
|
||||||
ttsSpace: '',
|
ttsSpace: '',
|
||||||
// https://114514.201666.xyz
|
// https://114514.201666.xyz
|
||||||
huggingFaceReverseProxy: '',
|
huggingFaceReverseProxy: '',
|
||||||
|
|
@ -104,7 +105,8 @@ const defaultConfig = {
|
||||||
sydneyApologyIgnored: true,
|
sydneyApologyIgnored: true,
|
||||||
enforceMaster: false,
|
enforceMaster: false,
|
||||||
bingAPDraw: false,
|
bingAPDraw: false,
|
||||||
bingLocalSuno: false,
|
bingSuno: 'bing',
|
||||||
|
bingSunoApi: '',
|
||||||
serverPort: 3321,
|
serverPort: 3321,
|
||||||
serverHost: '',
|
serverHost: '',
|
||||||
viewHost: '',
|
viewHost: '',
|
||||||
|
|
@ -151,6 +153,8 @@ const defaultConfig = {
|
||||||
enhanceAzureTTSEmotion: false,
|
enhanceAzureTTSEmotion: false,
|
||||||
autoJapanese: false,
|
autoJapanese: false,
|
||||||
enableGenerateContents: false,
|
enableGenerateContents: false,
|
||||||
|
enableGenerateSuno: false,
|
||||||
|
enableGenerateSunoForger: false,
|
||||||
amapKey: '',
|
amapKey: '',
|
||||||
azSerpKey: '',
|
azSerpKey: '',
|
||||||
serpSource: 'ikechan8370',
|
serpSource: 'ikechan8370',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue