feat
This commit is contained in:
parent
4ff47f5cf2
commit
309b259515
20 changed files with 600 additions and 92 deletions
|
|
@ -256,6 +256,10 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
|||
case 'isCat': {
|
||||
return user.isCat;
|
||||
}
|
||||
// Auto TTS
|
||||
case 'isVI': {
|
||||
return user.isVI;
|
||||
}
|
||||
// 「ユーザを見つけやすくする」が有効なアカウント
|
||||
case 'isExplorable': {
|
||||
return user.isExplorable;
|
||||
|
|
|
|||
|
|
@ -490,6 +490,7 @@ export class UserEntityService implements OnModuleInit {
|
|||
}))) : [],
|
||||
isBot: user.isBot,
|
||||
isCat: user.isCat,
|
||||
isVI: user.isVI,
|
||||
instance: user.host ? this.federatedInstanceService.federatedInstanceCache.fetch(user.host).then(instance => instance ? {
|
||||
name: instance.name,
|
||||
softwareName: instance.softwareName,
|
||||
|
|
|
|||
|
|
@ -355,6 +355,72 @@ export class MiMeta {
|
|||
})
|
||||
public hfAuthKey: string | null;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
public hfSpace: boolean;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public hfSpaceName: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public hfexampleAudioURL: string;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public hfexampleText: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
})
|
||||
public hfexampleLang: string;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
default: 'Slice once every 4 sentences',
|
||||
nullable: true,
|
||||
})
|
||||
public hfslice: string;
|
||||
|
||||
@Column('varchar', {
|
||||
default: 15,
|
||||
})
|
||||
public hftopK: number;
|
||||
|
||||
@Column('varchar', {
|
||||
default: 1.00,
|
||||
})
|
||||
public hftopP: number;
|
||||
|
||||
@Column('varchar', {
|
||||
default: 1.00,
|
||||
})
|
||||
public hfTemperature: number;
|
||||
|
||||
@Column('varchar', {
|
||||
default: false,
|
||||
})
|
||||
public hfnrm: boolean;
|
||||
|
||||
@Column('varchar', {
|
||||
default: 1.25,
|
||||
})
|
||||
public hfSpeedRate: number;
|
||||
|
||||
@Column('varchar', {
|
||||
default: false,
|
||||
})
|
||||
public hfdas: boolean;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 1024,
|
||||
nullable: true,
|
||||
|
|
|
|||
|
|
@ -83,6 +83,13 @@ type CondFormulaValueIsCat = {
|
|||
type: 'isCat';
|
||||
};
|
||||
|
||||
/**
|
||||
* Auto TTS
|
||||
*/
|
||||
type CondFormulaValueIsVI = {
|
||||
type: 'isVI';
|
||||
};
|
||||
|
||||
/**
|
||||
* 「ユーザを見つけやすくする」が有効なアカウントの場合のみ成立とする
|
||||
*/
|
||||
|
|
@ -164,6 +171,7 @@ export type RoleCondFormulaValue = { id: string } & (
|
|||
CondFormulaValueIsLocked |
|
||||
CondFormulaValueIsBot |
|
||||
CondFormulaValueIsCat |
|
||||
CondFormulaValueIsVI |
|
||||
CondFormulaValueIsExplorable |
|
||||
CondFormulaValueRoleAssignedTo |
|
||||
CondFormulaValueCreatedLessThan |
|
||||
|
|
|
|||
|
|
@ -184,6 +184,12 @@ export class MiUser {
|
|||
})
|
||||
public isCat: boolean;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
comment: 'Whether the User needs auto TTS.',
|
||||
})
|
||||
public isVI: boolean;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
comment: 'Whether the User is the root.',
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export const packedRoleCondFormulaValueUserSettingBooleanSchema = {
|
|||
type: {
|
||||
type: 'string',
|
||||
nullable: false, optional: false,
|
||||
enum: ['isSuspended', 'isLocked', 'isBot', 'isCat', 'isExplorable'],
|
||||
enum: ['isSuspended', 'isLocked', 'isBot', 'isCat','isVI' , 'isExplorable'],
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
|
|
|||
|
|
@ -115,6 +115,10 @@ export const packedUserLiteSchema = {
|
|||
type: 'boolean',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
isVI: {
|
||||
type: 'boolean',
|
||||
nullable: false, optional: true,
|
||||
},
|
||||
instance: {
|
||||
type: 'object',
|
||||
nullable: false, optional: true,
|
||||
|
|
|
|||
|
|
@ -93,6 +93,18 @@ export const paramDef = {
|
|||
deeplAuthKey: { type: 'string', nullable: true },
|
||||
deeplIsPro: { type: 'boolean' },
|
||||
hfAuthKey: { type: 'string', nullable: true },
|
||||
hfSpace: { type: 'boolean', default: false },
|
||||
hfSpaceName: { type: 'string', length: 1024, nullable: true },
|
||||
hfexampleAudioURL: { type: 'string', length: 1024, nullable: true },
|
||||
hfexampleText: { type: 'string', length: 1024, nullable: true },
|
||||
hfexampleLang: { type: 'string', length: 1024, nullable: true },
|
||||
hfslice: { type: 'string', length: 1024, default: 'Slice once every 4 sentences', nullable: true },
|
||||
hftopK: { type: 'integer', default: 15 },
|
||||
hftopP: { type: 'numeric', precision: 4, scale: 2, default: 1.00 },
|
||||
hfTemperature: { type: 'numeric', precision: 4, scale: 2, default: 1.00 },
|
||||
hfnrm: { type: 'boolean', default: false },
|
||||
hfSpeedRate: { type: 'numeric', precision: 4, scale: 2, default: 1.25 },
|
||||
hfdas: { type: 'boolean', default: false },
|
||||
enableEmail: { type: 'boolean' },
|
||||
email: { type: 'string', nullable: true },
|
||||
smtpSecure: { type: 'boolean' },
|
||||
|
|
@ -525,6 +537,74 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
set.hfAuthKey = ps.hfAuthKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.hfSpace !== undefined) {
|
||||
set.hfSpace = ps.hfSpace;
|
||||
}
|
||||
|
||||
if (ps.hfSpaceName !== undefined) {
|
||||
if (ps.hfSpaceName === '') {
|
||||
set.hfSpaceName = null;
|
||||
} else {
|
||||
set.hfSpaceName = ps.hfSpaceName;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.hfexampleAudioURL !== undefined) {
|
||||
if (ps.hfexampleAudioURL === '') {
|
||||
set.hfexampleAudioURL = null;
|
||||
} else {
|
||||
set.hfexampleAudioURL = ps.hfexampleAudioURL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.hfexampleText !== undefined) {
|
||||
if (ps.hfexampleText === '') {
|
||||
set.hfexampleText = null;
|
||||
} else {
|
||||
set.hfexampleText = ps.hfexampleText;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.hfexampleLang !== undefined) {
|
||||
if (ps.hfexampleLang === '') {
|
||||
set.hfexampleLang = null;
|
||||
} else {
|
||||
set.hfexampleLang = ps.hfexampleLang;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.hfslice !== undefined) {
|
||||
if (ps.hfslice === '') {
|
||||
set.hfslice = null;
|
||||
} else {
|
||||
set.hfslice = ps.hfslice;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.hftopK !== undefined) {
|
||||
set.hftopK = ps.hftopK;
|
||||
}
|
||||
|
||||
if (ps.hftopP !== undefined) {
|
||||
set.hftopP = ps.hftopP;
|
||||
}
|
||||
|
||||
if (ps.hfTemperature !== undefined) {
|
||||
set.hfTemperature = ps.hfTemperature;
|
||||
}
|
||||
|
||||
if (ps.hfnrm !== undefined) {
|
||||
set.hfnrm = ps.hfnrm;
|
||||
}
|
||||
|
||||
if (ps.hfSpeedRate !== undefined) {
|
||||
set.hfSpeedRate = ps.hfSpeedRate;
|
||||
}
|
||||
|
||||
if (ps.hfdas !== undefined) {
|
||||
set.hfdas = ps.hfdas;
|
||||
}
|
||||
|
||||
if (ps.enableIpLogging !== undefined) {
|
||||
set.enableIpLogging = ps.enableIpLogging;
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ export const paramDef = {
|
|||
preventAiLearning: { type: 'boolean' },
|
||||
isBot: { type: 'boolean' },
|
||||
isCat: { type: 'boolean' },
|
||||
isVI: { type: 'boolean' },
|
||||
injectFeaturedNote: { type: 'boolean' },
|
||||
receiveAnnouncementEmail: { type: 'boolean' },
|
||||
alwaysMarkNsfw: { type: 'boolean' },
|
||||
|
|
@ -323,6 +324,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
if (typeof ps.noCrawle === 'boolean') profileUpdates.noCrawle = ps.noCrawle;
|
||||
if (typeof ps.preventAiLearning === 'boolean') profileUpdates.preventAiLearning = ps.preventAiLearning;
|
||||
if (typeof ps.isCat === 'boolean') updates.isCat = ps.isCat;
|
||||
if (typeof ps.isVI === 'boolean') updates.isVI = ps.isVI;
|
||||
if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
|
||||
if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;
|
||||
if (typeof ps.alwaysMarkNsfw === 'boolean') {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Client } from "@gradio/client";
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
|
|
@ -25,6 +26,11 @@ export const meta = {
|
|||
},
|
||||
|
||||
errors: {
|
||||
incorrectconfig: {
|
||||
message: 'Incorrect configuration.',
|
||||
code: 'INCORRECT_CONFIG',
|
||||
id: '8d171e60-83b8-11ef-b98c-a7506d6c1de4',
|
||||
},
|
||||
unavailable: {
|
||||
message: 'Convert of notes unavailable.',
|
||||
code: 'UNAVAILABLE',
|
||||
|
|
@ -85,29 +91,85 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
throw new ApiError(meta.errors.unavailable);
|
||||
}
|
||||
|
||||
const endpoint = 'https://api-inference.huggingface.co/models/suno/bark';
|
||||
if (instance.hfSpace) {
|
||||
const langlist = ['Chinese', 'English', 'Japanese', 'Yue', 'Korean', 'Chinese-English Mixed', 'Japanese-English Mixed', 'Yue-English Mixed', 'Korean-English Mixed', 'Multilingual Mixed', 'Multilingual Mixed(Yue)'];
|
||||
const slicelist = ['No slice', 'Slice once every 4 sentences', 'Slice per 50 characters', 'Slice by Chinese punct', 'Slice by English punct', 'Slice by every punct'];
|
||||
let exampleAudio;
|
||||
let app;
|
||||
|
||||
const res = await this.httpRequestService.send(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + instance.hfAuthKey,
|
||||
Accept: 'audio/flac, */*',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
inputs: note.text,
|
||||
}),
|
||||
timeout: 60000,
|
||||
});
|
||||
try {
|
||||
const example = await fetch(instance.hfexampleAudioURL);
|
||||
exampleAudio = await example.blob();
|
||||
} catch {
|
||||
throw new ApiError(meta.errors.unavailable);
|
||||
}
|
||||
|
||||
let contentType = res.headers.get('Content-Type') || 'application/octet-stream';
|
||||
if (((!instance.hfnrm) && (!instance.hfexampleText)) || (!langlist.includes(instance.hfexampleLang)) || (!slicelist.includes(instance.hfslice)) || (!instance.hfSpaceName) || (!(instance.hfSpeedRate >= 0.6 && instance.hfSpeedRate <= 1.65)) || (!(instance.hfTemperature >= 0 && instance.hfTemperature <= 1)) || (!(instance.hftopK >= 0 && instance.hftopK <= 100)) || (!(instance.hftopP >= 0 && instance.hftopP <= 1))) {
|
||||
throw new ApiError(meta.errors.incorrectconfig);
|
||||
}
|
||||
|
||||
if (contentType === 'audio/flac') {
|
||||
return res.body;
|
||||
try {
|
||||
app = await Client.connect(instance.hfSpaceName, { hf_token: instance.hfAuthKey });
|
||||
} catch {
|
||||
throw new ApiError(meta.errors.unavailable);
|
||||
}
|
||||
|
||||
const result = await app.predict("/get_tts_wav", [
|
||||
exampleAudio,
|
||||
instance.hfexampleText,
|
||||
instance.hfexampleLang,
|
||||
note.text,
|
||||
"Multilingual Mixed",
|
||||
instance.hfslice,
|
||||
instance.hftopK,
|
||||
instance.hftopP,
|
||||
instance.hfTemperature,
|
||||
instance.hfnrm,
|
||||
instance.hfSpeedRate,
|
||||
instance.hfdas,
|
||||
]);
|
||||
|
||||
let resurl = JSON.parse(result)[0].url;
|
||||
|
||||
const res = await this.httpRequestService.send(resurl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + instance.hfAuthKey,
|
||||
},
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
let contentType = res.headers.get('Content-Type') || 'application/octet-stream';
|
||||
|
||||
if (contentType === 'audio/flac') {
|
||||
return res.body;
|
||||
} else {
|
||||
throw new ApiError(meta.errors.unavailable);
|
||||
}
|
||||
} else {
|
||||
throw new ApiError(meta.errors.unavailable);
|
||||
const endpoint = 'https://api-inference.huggingface.co/models/suno/bark';
|
||||
|
||||
const res = await this.httpRequestService.send(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + instance.hfAuthKey,
|
||||
Accept: 'audio/flac, */*',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
inputs: note.text,
|
||||
}),
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
let contentType = res.headers.get('Content-Type') || 'application/octet-stream';
|
||||
|
||||
if (contentType === 'audio/flac') {
|
||||
return res.body;
|
||||
} else {
|
||||
throw new ApiError(meta.errors.unavailable);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue