mirror of
https://git.femboyfinancial.jp/james/FemScoreboard.git
synced 2025-01-17 21:29:01 -08:00
Add TTS
This commit is contained in:
parent
a8b6d834f8
commit
cf601a72fb
@ -4,8 +4,7 @@ CLIENT="123456789012345678"
|
|||||||
GUILD="123456789012345678"
|
GUILD="123456789012345678"
|
||||||
ADMIN="123456789012345678"
|
ADMIN="123456789012345678"
|
||||||
|
|
||||||
LLM_HOST="127.0.0.1"
|
LLM_HOST="http://127.0.0.1:8000"
|
||||||
LLM_PORT=8000
|
|
||||||
LLM_TOKEN="dfsl;kjsdl;kfja"
|
LLM_TOKEN="dfsl;kjsdl;kfja"
|
||||||
REPLY_CHANCE=0.2
|
REPLY_CHANCE=0.2
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import {
|
|||||||
openDb,
|
openDb,
|
||||||
reactionEmojis,
|
reactionEmojis,
|
||||||
recordReaction,
|
recordReaction,
|
||||||
|
requestTTSResponse,
|
||||||
sync
|
sync
|
||||||
} from './util';
|
} from './util';
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
@ -166,11 +167,16 @@ async function onNewMessage(message: Message)
|
|||||||
|
|
||||||
async function fetchMotd()
|
async function fetchMotd()
|
||||||
{
|
{
|
||||||
const res = await fetch(process.env.MOTD_HREF);
|
try {
|
||||||
const xml = await res.text();
|
const res = await fetch(process.env.MOTD_HREF);
|
||||||
const parser = new JSDOM(xml);
|
const xml = await res.text();
|
||||||
const doc = parser.window.document;
|
const parser = new JSDOM(xml);
|
||||||
return doc.querySelector(process.env.MOTD_QUERY).textContent;
|
const doc = parser.window.document;
|
||||||
|
const el = doc.querySelector(process.env.MOTD_QUERY);
|
||||||
|
return el ? el.textContent : null;
|
||||||
|
} catch (err) {
|
||||||
|
logWarn('[bot] Failed to fetch MOTD; is the booru down?');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function requestRVCResponse(src: Attachment): Promise<Blob>
|
async function requestRVCResponse(src: Attachment): Promise<Blob>
|
||||||
@ -189,7 +195,7 @@ async function requestRVCResponse(src: Attachment): Promise<Blob>
|
|||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('file', fs.readFileSync(tmpFileName), 'voice-message.ogg');
|
fd.append('file', fs.readFileSync(tmpFileName), 'voice-message.ogg');
|
||||||
|
|
||||||
const rvcEndpoint = `http://${process.env.LLM_HOST}:${process.env.LLM_PORT}/rvc?${queryParams.toString()}`;
|
const rvcEndpoint = `${process.env.LLM_HOST}/rvc?${queryParams.toString()}`;
|
||||||
logInfo(`[bot] Requesting RVC response for ${src.id}`);
|
logInfo(`[bot] Requesting RVC response for ${src.id}`);
|
||||||
const res = await fetch(rvcEndpoint, {
|
const res = await fetch(rvcEndpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -206,7 +212,7 @@ async function requestLLMResponse(messages)
|
|||||||
for (const field of Object.keys(config["llmconf"].llmSettings)) {
|
for (const field of Object.keys(config["llmconf"].llmSettings)) {
|
||||||
queryParams.append(field, config["llmconf"].llmSettings[field]);
|
queryParams.append(field, config["llmconf"].llmSettings[field]);
|
||||||
}
|
}
|
||||||
const llmEndpoint = `http://${process.env.LLM_HOST}:${process.env.LLM_PORT}/?${queryParams.toString()}`;
|
const llmEndpoint = `${process.env.LLM_HOST}/?${queryParams.toString()}`;
|
||||||
const messageList = messages.map((m: Message) => ({
|
const messageList = messages.map((m: Message) => ({
|
||||||
role: m.author.bot ? "assistant" : "user",
|
role: m.author.bot ? "assistant" : "user",
|
||||||
content: m.cleanContent,
|
content: m.cleanContent,
|
||||||
@ -244,8 +250,18 @@ async function scheduleRandomMessage(firstTime = false)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const randomMessage = await fetchMotd();
|
const randomMessage = await fetchMotd();
|
||||||
await channel.send(randomMessage);
|
if (randomMessage) {
|
||||||
logInfo(`[bot] Sent MOTD: ${randomMessage}`);
|
const audio = await requestTTSResponse(randomMessage);
|
||||||
|
const audioBuf = await audio.arrayBuffer();
|
||||||
|
const audioFile = new AttachmentBuilder(Buffer.from(audioBuf)).setName('mikuified.wav');
|
||||||
|
await channel.send({
|
||||||
|
content: randomMessage,
|
||||||
|
files: [audioFile]
|
||||||
|
});
|
||||||
|
logInfo(`[bot] Sent MOTD: ${randomMessage}`);
|
||||||
|
} else {
|
||||||
|
logWarn(`[bot] Could not fetch MOTD.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// wait between 2-8 hours
|
// wait between 2-8 hours
|
||||||
const timeoutMins = Math.random() * 360 + 120;
|
const timeoutMins = Math.random() * 360 + 120;
|
||||||
|
43
discord/commands/tts/tts.ts
Normal file
43
discord/commands/tts/tts.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
AttachmentBuilder,
|
||||||
|
ChatInputCommandInteraction,
|
||||||
|
SlashCommandBuilder
|
||||||
|
} from 'discord.js';
|
||||||
|
import 'dotenv/config';
|
||||||
|
import { logError, logInfo, logWarn } from '../../../logging';
|
||||||
|
import { requestTTSResponse } from '../../util';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
ttsSettings: {
|
||||||
|
pitch_change_oct: 1,
|
||||||
|
pitch_change_sem: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function ttsCommand(interaction: ChatInputCommandInteraction)
|
||||||
|
{
|
||||||
|
const text = interaction.options.getString('text');
|
||||||
|
await interaction.reply(`generating audio for "${text}"...`);
|
||||||
|
try {
|
||||||
|
const audio = await requestTTSResponse(text);
|
||||||
|
const audioBuf = await audio.arrayBuffer();
|
||||||
|
const audioFile = new AttachmentBuilder(Buffer.from(audioBuf)).setName('mikuified.wav');
|
||||||
|
await interaction.editReply({
|
||||||
|
files: [audioFile]
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
await interaction.editReply(`Error: ${err}`);
|
||||||
|
logError(`Error while generating TTS: ${err}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export = {
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName('tts')
|
||||||
|
.setDescription('Read text in Miku\'s voice')
|
||||||
|
.addStringOption(
|
||||||
|
opt => opt.setName('text').setDescription('Text').setRequired(true)
|
||||||
|
),
|
||||||
|
execute: ttsCommand,
|
||||||
|
config: config
|
||||||
|
};
|
@ -9,6 +9,7 @@ import { get as httpGet } from 'https';
|
|||||||
import { Database, open } from 'sqlite';
|
import { Database, open } from 'sqlite';
|
||||||
import { Database as Database3 } from 'sqlite3';
|
import { Database as Database3 } from 'sqlite3';
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
import { logError, logInfo, logWarn } from '../logging';
|
import { logError, logInfo, logWarn } from '../logging';
|
||||||
import { ScoreboardMessageRow } from '../models';
|
import { ScoreboardMessageRow } from '../models';
|
||||||
|
|
||||||
@ -163,4 +164,19 @@ async function sync(guilds: GuildManager) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { db, clearDb, openDb, reactionEmojis, recordReaction, sync };
|
async function requestTTSResponse(txt: string): Promise<Blob>
|
||||||
|
{
|
||||||
|
const queryParams = new URLSearchParams();
|
||||||
|
queryParams.append("token", process.env.LLM_TOKEN);
|
||||||
|
queryParams.append("text", txt);
|
||||||
|
|
||||||
|
const ttsEndpoint = `${process.env.LLM_HOST}/tts?${queryParams.toString()}`;
|
||||||
|
logInfo(`[bot] Requesting TTS response for "${txt}"`);
|
||||||
|
const res = await fetch(ttsEndpoint, {
|
||||||
|
method: 'POST'
|
||||||
|
});
|
||||||
|
const resContents = await res.blob();
|
||||||
|
return resContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { db, clearDb, openDb, reactionEmojis, recordReaction, requestTTSResponse, sync };
|
||||||
|
Loading…
Reference in New Issue
Block a user