Merge branch 'v2' into v2

This commit is contained in:
ifeif 2023-05-20 11:51:49 +08:00 committed by GitHub
commit f1ca8e2d6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 404 additions and 263 deletions

View file

@ -358,6 +358,9 @@ export default class SydneyAIClient {
'responsible_ai_policy_235',
'enablemm',
toneOption,
'clgalileo',
'gencontentv3',
'rai267',
'dtappid',
'cricinfo',
'cricinfov2',
@ -625,7 +628,11 @@ export default class SydneyAIClient {
adaptiveCards: adaptiveCardsSoFar,
text: replySoFar.join('')
}
message.text = messages.filter(m => m.author === 'bot').map(m => m.text).join('')
// 获取到图片内容
if (message.contentType === 'IMAGE') {
message.imageTag = messages.filter(m => m.contentType === 'IMAGE').map(m => m.text).join('')
}
message.text = messages.filter(m => m.author === 'bot' && m.contentType != 'IMAGE').map(m => m.text).join('')
if (!message) {
reject('No message was generated.')
return

View file

@ -1,141 +0,0 @@
import md5 from 'md5-node'
import axios from 'axios'
// noinspection NonAsciiCharacters
export const transMap = { : 'zh', : 'jp', : 'wyw', : 'en', : 'ru', : 'kr' }
const errOr = {
52001: '请求超时,请重试。',
52002: '系统错误,请重试。',
52003: '未授权用户请检查appid是否正确或者服务是否开通。',
54000: '必填参数为空,请检查是否少传参数。',
54001: '签名错误,请检查您的签名生成方法。',
54003: '访问频率受限,请降低您的调用频率,或进行身份认证后切换为高级版/尊享版。',
54004: '账户余额不足,请前往管理控制台为账户充值。',
54005: '长query请求频繁请降低长query的发送频率3s后再试。',
58000: '客户端IP非法检查个人资料里填写的IP地址是否正确可前往开发者信息-基本信息修改。',
58001: '译文语言方向不支持,检查译文语言是否在语言列表里。',
58002: '服务当前已关闭,请前往管理控制台开启服务。',
90107: '认证未通过或未生效,请前往我的认证查看认证进度。'
}
function Translate (config) {
this.requestNumber = 0 // 请求次数
this.config = {
showProgress: 1, // 是否显示进度
requestNumber: 1, // 最大请求次数
agreement: 'http', // 协议
...config
}
this.baiduApi = `${this.config.agreement}://api.fanyi.baidu.com/api/trans/vip/translate`
// 拼接url
this.createUrl = (domain, form) => {
let result = domain + '?'
for (let key in form) {
result += `${key}=${form[key]}&`
}
return result.slice(0, result.length - 1)
}
this.translate = async (value, ...params) => {
let result = ''
let from = 'auto'
let to = 'en'
if (params.length === 1) {
to = transMap[params[0]] || to
} else if (params.length === 2) {
from = transMap[params[0]] || from
to = transMap[params[1]] || to
}
if (typeof value === 'string') {
const res = await this.requestApi(value, { from, to })
result = res[0].dst
}
if (Array.isArray(value) || Object.prototype.toString.call(value) === '[object Object]') {
result = await this._createObjValue(value, { from, to })
}
return result
}
this.requestApi = (value, params) => {
if (this.requestNumber >= this.config.requestNumber) {
return new Promise((resolve) => {
setTimeout(() => {
this.requestApi(value, params).then((res) => {
resolve(res)
})
}, 1000)
})
}
this.requestNumber++
const { appid, secret } = this.config
const q = value
const salt = Math.random()
const sign = md5(`${appid}${q}${salt}${secret}`)
const fromData = {
q: encodeURIComponent(q),
sign,
appid,
salt,
from: params.from || 'auto',
to: params.to || 'en'
}
const fanyiApi = this.createUrl(this.baiduApi, fromData)
return new Promise((resolve, reject) => {
axios
.get(fanyiApi)
.then(({ data: res }) => {
if (!res.error_code) {
const resList = res.trans_result
resolve(resList)
} else {
const errCode = res.error_code
if (errOr[errCode]) {
reject(new Error('翻译出错了~' + errOr[errCode]))
} else {
reject(new Error('翻译出错了~' + errCode))
}
}
})
.finally(() => {
setTimeout(() => {
this.requestNumber--
}, 1000)
})
})
}
// 递归翻译数组或对象
this._createObjValue = async (value, parames) => {
let index = 0
const obj = Array.isArray(value) ? [] : {}
const strDatas = Array.isArray(value) ? value : Object.values(value)
const reqData = strDatas
.filter((item) => typeof item === 'string') // 过滤字符串
.join('\n')
const res = reqData ? await this.requestApi(reqData, parames) : []
for (let key in value) {
if (typeof value[key] === 'string') {
obj[key] = res[index].dst
index++
}
if (
Array.isArray(value[key]) ||
Object.prototype.toString.call(value[key]) === '[object Object]'
) {
obj[key] = await this.translate(value[key], parames) // 递归翻译
}
}
return obj
}
return this.translate
}
export default Translate

View file

@ -120,8 +120,6 @@ const defaultConfig = {
azureTTSSpeaker: 'zh-CN-XiaochenNeural',
voicevoxSpace: '',
voicevoxTTSSpeaker: '护士机器子T',
baiduTranslateAppId: '',
baiduTranslateSecret: '',
azureTTSEmotion: false,
enhanceAzureTTSEmotion: false,
autoJapanese: false,

View file

@ -468,7 +468,7 @@ export async function convertFaces (msg, handleAt = false, e) {
handleAt = e?.isGroup && handleAt
let groupMembers
let groupCardQQMap = {}
if (handleAt) {
if (handleAt && typeof e.group.getMemberMap === 'function') {
groupMembers = await e.group.getMemberMap()
for (let key of groupMembers.keys()) {
groupCardQQMap[groupMembers.get(key).card || groupMembers.get(key).nickname] = groupMembers.get(key).user_id

97
utils/translate.js Normal file
View file

@ -0,0 +1,97 @@
import md5 from 'md5'
import _ from 'lodash'
// 代码参考https://github.com/yeyang52/yenai-plugin/blob/b50b11338adfa5a4ef93912eefd2f1f704e8b990/model/api/funApi.js#L25
export const translateLangSupports = [
{ code: 'ar', label: '阿拉伯语', abbr: '阿', alphabet: 'A' },
{ code: 'de', label: '德语', abbr: '德', alphabet: 'D' },
{ code: 'ru', label: '俄语', abbr: '俄', alphabet: 'E' },
{ code: 'fr', label: '法语', abbr: '法', alphabet: 'F' },
{ code: 'ko', label: '韩语', abbr: '韩', alphabet: 'H' },
{ code: 'nl', label: '荷兰语', abbr: '荷', alphabet: 'H' },
{ code: 'pt', label: '葡萄牙语', abbr: '葡', alphabet: 'P' },
{ code: 'ja', label: '日语', abbr: '日', alphabet: 'R' },
{ code: 'th', label: '泰语', abbr: '泰', alphabet: 'T' },
{ code: 'es', label: '西班牙语', abbr: '西', alphabet: 'X' },
{ code: 'en', label: '英语', abbr: '英', alphabet: 'Y' },
{ code: 'it', label: '意大利语', abbr: '意', alphabet: 'Y' },
{ code: 'vi', label: '越南语', abbr: '越', alphabet: 'Y' },
{ code: 'id', label: '印度尼西亚语', abbr: '印', alphabet: 'Y' },
{ code: 'zh-CHS', label: '中文', abbr: '中', alphabet: 'Z' }
]
const API_ERROR = '出了点小问题,待会再试试吧'
export async function translate (msg, to = 'auto') {
let from = 'auto'
if (to !== 'auto') to = translateLangSupports.find(item => item.abbr == to)?.code
if (!to) return `未找到翻译的语种,支持的语言为:\n${translateLangSupports.map(item => item.abbr).join('')}\n`
// 翻译结果为空的提示
const RESULT_ERROR = '找不到翻译结果'
// API 请求错误提示
const API_ERROR = '翻译服务暂不可用,请稍后再试'
const qs = (obj) => {
let res = ''
for (const [k, v] of Object.entries(obj)) { res += `${k}=${encodeURIComponent(v)}&` }
return res.slice(0, res.length - 1)
}
const appVersion = '5.0 (Windows NT 10.0; Win64; x64) Chrome/98.0.4750.0'
const payload = {
from,
to,
bv: md5(appVersion),
client: 'fanyideskweb',
doctype: 'json',
version: '2.1',
keyfrom: 'fanyi.web',
action: 'FY_BY_DEFAULT',
smartresult: 'dict'
}
const headers = {
Host: 'fanyi.youdao.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/98.0.4758.102',
Referer: 'https://fanyi.youdao.com/',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Cookie: 'OUTFOX_SEARCH_USER_ID_NCOO=133190305.98519628; OUTFOX_SEARCH_USER_ID="2081065877@10.169.0.102";'
}
const api = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
const key = 'Ygy_4c=r#e#4EX^NUGUc5'
try {
if (Array.isArray(msg)) {
const results = []
for (let i = 0; i < msg.length; i++) {
const item = msg[i]
const lts = '' + new Date().getTime()
const salt = lts + parseInt(String(10 * Math.random()), 10)
const sign = md5(payload.client + item + salt + key)
const postData = qs(Object.assign({ i: item, lts, sign, salt }, payload))
let { errorCode, translateResult } = await fetch(api, {
method: 'POST',
body: postData,
headers
}).then(res => res.json()).catch(err => console.error(err))
if (errorCode !== 0) return API_ERROR
translateResult = _.flattenDeep(translateResult)?.map(item => item.tgt).join('\n')
if (!translateResult) results.push(RESULT_ERROR)
else results.push(translateResult)
}
return results
} else {
const i = msg // 翻译的内容
const lts = '' + new Date().getTime()
const salt = lts + parseInt(String(10 * Math.random()), 10)
const sign = md5(payload.client + i + salt + key)
const postData = qs(Object.assign({ i, lts, sign, salt }, payload))
let { errorCode, translateResult } = await fetch(api, {
method: 'POST',
body: postData,
headers
}).then(res => res.json()).catch(err => console.error(err))
if (errorCode !== 0) return API_ERROR
translateResult = _.flattenDeep(translateResult)?.map(item => item.tgt).join('\n')
if (!translateResult) return RESULT_ERROR
return translateResult
}
} catch (err) {
return API_ERROR
}
}

View file

@ -66,6 +66,10 @@ async function uploadRecord (recordUrl, ttsMode = 'vits-uma-genshin-honkai') {
recordUrl = tmpFile
}
if (recordType === 'file' || Config.cloudMode === 'file') {
if (!recordUrl) {
logger.error('云转码错误recordUrl 异常')
return false
}
const formData = new FormData()
let buffer
if (!recordUrl.startsWith('http')) {
@ -87,9 +91,13 @@ async function uploadRecord (recordUrl, ttsMode = 'vits-uma-genshin-honkai') {
method: 'POST',
body: formData
})
let t = await resultres.text()
let t = await resultres.arrayBuffer()
try {
result = JSON.parse(t)
result = {
buffer: {
data: t
}
}
} catch (e) {
logger.error(t)
throw e