WIP
This commit is contained in:
parent
44f62160cb
commit
a481f00cab
24 changed files with 406 additions and 4 deletions
|
|
@ -301,6 +301,7 @@ import * as ep___notes_threadMuting_create from './endpoints/notes/thread-muting
|
|||
import * as ep___notes_threadMuting_delete from './endpoints/notes/thread-muting/delete.js';
|
||||
import * as ep___notes_timeline from './endpoints/notes/timeline.js';
|
||||
import * as ep___notes_translate from './endpoints/notes/translate.js';
|
||||
import * as ep___notes_tts from './endpoints/notes/tts.js';
|
||||
import * as ep___notes_unrenote from './endpoints/notes/unrenote.js';
|
||||
import * as ep___notes_userListTimeline from './endpoints/notes/user-list-timeline.js';
|
||||
import * as ep___notifications_create from './endpoints/notifications/create.js';
|
||||
|
|
@ -684,6 +685,7 @@ const $notes_threadMuting_create: Provider = { provide: 'ep:notes/thread-muting/
|
|||
const $notes_threadMuting_delete: Provider = { provide: 'ep:notes/thread-muting/delete', useClass: ep___notes_threadMuting_delete.default };
|
||||
const $notes_timeline: Provider = { provide: 'ep:notes/timeline', useClass: ep___notes_timeline.default };
|
||||
const $notes_translate: Provider = { provide: 'ep:notes/translate', useClass: ep___notes_translate.default };
|
||||
const $notes_tts: Provider = { provide: 'ep:notes/tts', useClass: ep___notes_tts.default };
|
||||
const $notes_unrenote: Provider = { provide: 'ep:notes/unrenote', useClass: ep___notes_unrenote.default };
|
||||
const $notes_userListTimeline: Provider = { provide: 'ep:notes/user-list-timeline', useClass: ep___notes_userListTimeline.default };
|
||||
const $notifications_create: Provider = { provide: 'ep:notifications/create', useClass: ep___notifications_create.default };
|
||||
|
|
@ -1071,6 +1073,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
|
|||
$notes_threadMuting_delete,
|
||||
$notes_timeline,
|
||||
$notes_translate,
|
||||
$notes_tts,
|
||||
$notes_unrenote,
|
||||
$notes_userListTimeline,
|
||||
$notifications_create,
|
||||
|
|
@ -1452,6 +1455,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__
|
|||
$notes_threadMuting_delete,
|
||||
$notes_timeline,
|
||||
$notes_translate,
|
||||
$notes_tts,
|
||||
$notes_unrenote,
|
||||
$notes_userListTimeline,
|
||||
$notifications_create,
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ import * as ep___notes_threadMuting_create from './endpoints/notes/thread-muting
|
|||
import * as ep___notes_threadMuting_delete from './endpoints/notes/thread-muting/delete.js';
|
||||
import * as ep___notes_timeline from './endpoints/notes/timeline.js';
|
||||
import * as ep___notes_translate from './endpoints/notes/translate.js';
|
||||
import * as ep___notes_tts from './endpoints/notes/tts.js';
|
||||
import * as ep___notes_unrenote from './endpoints/notes/unrenote.js';
|
||||
import * as ep___notes_userListTimeline from './endpoints/notes/user-list-timeline.js';
|
||||
import * as ep___notifications_create from './endpoints/notifications/create.js';
|
||||
|
|
@ -688,6 +689,7 @@ const eps = [
|
|||
['notes/thread-muting/delete', ep___notes_threadMuting_delete],
|
||||
['notes/timeline', ep___notes_timeline],
|
||||
['notes/translate', ep___notes_translate],
|
||||
['notes/tts', ep___notes_tts],
|
||||
['notes/unrenote', ep___notes_unrenote],
|
||||
['notes/user-list-timeline', ep___notes_userListTimeline],
|
||||
['notifications/create', ep___notifications_create],
|
||||
|
|
|
|||
|
|
@ -118,6 +118,10 @@ export const meta = {
|
|||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
ttsAvailable: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
silencedHosts: {
|
||||
type: 'array',
|
||||
optional: true,
|
||||
|
|
@ -556,6 +560,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
enableEmail: instance.enableEmail,
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
translatorAvailable: instance.deeplAuthKey != null,
|
||||
ttsAvailable: instance.hfAuthKey != null,
|
||||
cacheRemoteFiles: instance.cacheRemoteFiles,
|
||||
cacheRemoteSensitiveFiles: instance.cacheRemoteSensitiveFiles,
|
||||
pinnedUsers: instance.pinnedUsers,
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ export const paramDef = {
|
|||
},
|
||||
deeplAuthKey: { type: 'string', nullable: true },
|
||||
deeplIsPro: { type: 'boolean' },
|
||||
hfAuthKey: { type: 'string', nullable: true },
|
||||
enableEmail: { type: 'boolean' },
|
||||
email: { type: 'string', nullable: true },
|
||||
smtpSecure: { type: 'boolean' },
|
||||
|
|
@ -506,6 +507,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
set.deeplIsPro = ps.deeplIsPro;
|
||||
}
|
||||
|
||||
if (ps.hfAuthKey !== undefined) {
|
||||
if (ps.hfAuthKey === '') {
|
||||
set.hfAuthKey = null;
|
||||
} else {
|
||||
set.hfAuthKey = ps.hfAuthKey;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.enableIpLogging !== undefined) {
|
||||
set.enableIpLogging = ps.enableIpLogging;
|
||||
}
|
||||
|
|
|
|||
109
packages/backend/src/server/api/endpoints/notes/tts.ts
Normal file
109
packages/backend/src/server/api/endpoints/notes/tts.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { HttpRequestService } from '@/core/HttpRequestService.js';
|
||||
import { GetterService } from '@/server/api/GetterService.js';
|
||||
import { RoleService } from '@/core/RoleService.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
|
||||
requireCredential: true,
|
||||
kind: 'read:account',
|
||||
|
||||
res: {
|
||||
type: 'string',
|
||||
optional: true, nullable: false,
|
||||
contentMediaType: 'audio/flac',
|
||||
},
|
||||
|
||||
errors: {
|
||||
unavailable: {
|
||||
message: 'Convert of notes unavailable.',
|
||||
code: 'UNAVAILABLE',
|
||||
id: '97a0826c-6393-11ef-a650-67972d710975',
|
||||
},
|
||||
noSuchNote: {
|
||||
message: 'No such note.',
|
||||
code: 'NO_SUCH_NOTE',
|
||||
id: 'bea9b03f-36e0-49c5-a4db-627a029f8971',
|
||||
},
|
||||
cannotConvertInvisibleNote: {
|
||||
message: 'Cannot convert invisible note.',
|
||||
code: 'CANNOT_CONVERT_INVISIBLE_NOTE',
|
||||
id: 'f57caae0-6394-11ef-8e2a-d706932c1030',
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
noteId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['noteId'],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
private noteEntityService: NoteEntityService,
|
||||
private getterService: GetterService,
|
||||
private metaService: MetaService,
|
||||
private httpRequestService: HttpRequestService,
|
||||
private roleService: RoleService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const policies = await this.roleService.getUserPolicies(me.id);
|
||||
if (!policies.canUseTTS) {
|
||||
throw new ApiError(meta.errors.unavailable);
|
||||
}
|
||||
|
||||
const note = await this.getterService.getNote(ps.noteId).catch(err => {
|
||||
if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
|
||||
throw err;
|
||||
});
|
||||
|
||||
if (!(await this.noteEntityService.isVisibleForMe(note, me.id))) {
|
||||
throw new ApiError(meta.errors.cannotConvertInvisibleNote);
|
||||
}
|
||||
|
||||
if (note.text == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const instance = await this.metaService.fetch();
|
||||
|
||||
if (instance.hfAuthKey == null) {
|
||||
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,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
inputs: note.text,
|
||||
}),
|
||||
timeout: 60000,
|
||||
});
|
||||
|
||||
if (res.headers.get('content-type') === 'audio/flac') {
|
||||
return res.body;
|
||||
} else {
|
||||
throw new ApiError(meta.errors.unavailable);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue