diff --git a/.DS_Store b/.DS_Store index c435fb7..94ae348 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.env.example b/.env.example deleted file mode 100644 index fbe1127..0000000 --- a/.env.example +++ /dev/null @@ -1,6 +0,0 @@ -TOKEN= -GUILD= -CHANNEL=
-VOICE_TMP_PATH=./voice_tmp/ -DB_FILE=./database/tardis.db -PREFIX=! \ No newline at end of file diff --git a/index.js b/index.js index f7114be..0358e33 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,5 @@ const Discord = require('discord.js'); require('dotenv').config(); -const tts = require('google-tts-api'); const fetch = require('node-fetch'); const fs = require('fs'); const sha1 = require('sha1'); @@ -16,7 +15,19 @@ const db = new sqlite.Database(process.env.DB_FILE); const api = { db: db, - + ttsEngines: (() => { + let engines={}; + console.log(`Registering TTS engines...`); + const engineDirectories = fs.readdirSync('./tts'); + engineDirectories.forEach((dir) => { + if(dir.startsWith('.')) return; + eng=require(`./tts/${dir}/index.js`); + engines[dir]=new eng; + console.log(`Loading ./tts/${dir}/index.js`) + }) + return engines; + })(), + isInVoiceChannel: (channel) => { return joinedVoiceChannels.includes(channel); }, @@ -25,16 +36,11 @@ const api = { return bot.voice.connections.find((conn) => conn.channel === channel); }, - generateVoice: async (string) => { - const hash = sha1(string); - const filepath = process.env.VOICE_TMP_PATH + hash + ".mp3"; + generateVoice: async (string, engine, voice, params) => { + const hash = sha1(voice+string); + const filepath = process.env.VOICE_TMP_PATH + hash + '.' + engine.fileExtension; if (!fs.existsSync(filepath)) { - const url = tts.getAudioUrl(string, {lang: "en-us"}); - console.log("Generated url: " + url); - const data = await fetch(url); - const contents = await data.arrayBuffer(); - const buf = Buffer.from(contents); - fs.writeFileSync(filepath, buf); + await engine.getSpeechFile(string, filepath, voice, params); } return filepath; }, @@ -53,9 +59,9 @@ const api = { } }, - speak: async (channel, message) => { + speak: async (channel, message, engine=api.ttsEngines.gtranslate, voice='en-us', params={}) => { const conn = api.getConnectionForVoiceChannel(channel); - const filepath = await api.generateVoice(message); + const filepath = await api.generateVoice(message, engine, voice, params); if (conn) conn.play(filepath); }, @@ -65,9 +71,10 @@ const api = { } function registerModules() { - console.log(`Registering modules...`); + console.log(`Registering modules...`); const moduleDirectories = fs.readdirSync('./modules'); moduleDirectories.forEach((dir) => { + if(dir.startsWith('.')) return; modules.push(require(`./modules/${dir}/index.js`)); console.log(`Loading ./modules/${dir}/index.js`) }) diff --git a/modules/.DS_Store b/modules/.DS_Store new file mode 100644 index 0000000..7861607 Binary files /dev/null and b/modules/.DS_Store differ diff --git a/modules/welcomer/index.js b/modules/welcomer/index.js index edd4001..684aba2 100644 --- a/modules/welcomer/index.js +++ b/modules/welcomer/index.js @@ -5,6 +5,6 @@ module.exports = function(bot, api) { const channel = await bot.channels.fetch(process.env.CHANNEL); await api.joinChannel(channel); - api.speak(channel, `Hi! I'm alive. It is now ${new Date().toLocaleTimeString()} on ${new Date().toLocaleDateString()}`); + api.speak(channel, `Hi! I'm alive. It is now ${new Date().toLocaleTimeString()} on ${new Date().toLocaleDateString()}`,api.ttsEngines.watson); }) } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index fe09d29..68ff3b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1046,7 +1046,6 @@ "hasInstallScript": true, "dependencies": { "node-addon-api": "^3.0.0", - "node-gyp": "3.x", "node-pre-gyp": "^0.11.0" }, "optionalDependencies": { diff --git a/tts/.DS_Store b/tts/.DS_Store new file mode 100644 index 0000000..1256189 Binary files /dev/null and b/tts/.DS_Store differ diff --git a/tts/BaseEngine/index.js b/tts/BaseEngine/index.js new file mode 100644 index 0000000..4a9aa73 --- /dev/null +++ b/tts/BaseEngine/index.js @@ -0,0 +1,16 @@ +const fs=require('fs'); + +module.exports=class { + constructor(longName, fileExtension, supportedParameters=[]) { + this.longName=longName; + this.fileExtension=fileExtension; + } + async getSpeech(text, voice, params) {} + async getSpeechFile(text, filepath, voice, params) { + const data = await this.getSpeech(text, voice, params); + const contents = await data.arrayBuffer(); + const buf = Buffer.from(contents); + fs.writeFileSync(filepath, buf); + return filepath; + } +} \ No newline at end of file diff --git a/tts/espeak/index.js b/tts/espeak/index.js new file mode 100644 index 0000000..ca4acb2 --- /dev/null +++ b/tts/espeak/index.js @@ -0,0 +1,11 @@ +const BaseEngine=require('../BaseEngine') +const {spawn} = require('child_process') + +module.exports=class extends BaseEngine { + constructor() { + super('ESpeak','wav') + } + async getSpeechFile(text, filepath, voice='en', params={}) { + await spawn('espeak', ['-v', voice, '-w',filepath, text]); + } +} \ No newline at end of file diff --git a/tts/gtranslate/index.js b/tts/gtranslate/index.js new file mode 100644 index 0000000..5847aba --- /dev/null +++ b/tts/gtranslate/index.js @@ -0,0 +1,13 @@ +const BaseEngine=require('../BaseEngine'); +const fetch = require('node-fetch'); +const tts = require('google-tts-api'); + +module.exports= class extends BaseEngine { + constructor() { + super("Google Translate TTS","mp3"); + } + async getSpeech(text, voice='en-us', params={}) { + const url = tts.getAudioUrl(text, {lang: voice}); + return fetch(url); + } +}; \ No newline at end of file diff --git a/tts/watson/index.js b/tts/watson/index.js new file mode 100644 index 0000000..3900e5a --- /dev/null +++ b/tts/watson/index.js @@ -0,0 +1,26 @@ +const BaseEngine=require('../BaseEngine'); +const fetch = require('node-fetch'); +const querystring = require('querystring'); + +module.exports= class extends BaseEngine { + constructor() { + super("IBM Watson TTS","ogg"); + } + async getSpeech(text, voice='en-us', params={}) { + const url = process.env.watsonURL+"/v1/synthesize"; + let buff=new Buffer('apikey:'+process.env.watsonAPIKey); + let b64auth=buff.toString('base64'); + const authorization='Basic '+b64auth; + const opts={ + method: "post", + headers: { + 'Content-Type': 'application/json', + 'Authorization': authorization + }, + body: { + text: text + } + }; + return fetch(url); + } +}; \ No newline at end of file