334 lines
No EOL
11 KiB
JavaScript
334 lines
No EOL
11 KiB
JavaScript
const path = require('path'); // get directory path
|
|
const {
|
|
ipcRenderer,
|
|
} = require('electron'); // necessary electron libraries to send data to the app
|
|
const say = require('say');
|
|
const request = require('request');
|
|
const langdetect = require('langdetect');
|
|
const io = require('socket.io-client');
|
|
|
|
const fs = require('fs');
|
|
|
|
const util = require('util');
|
|
const exec = util.promisify(require('child_process').exec);
|
|
|
|
const GoogleTTS = require('node-google-tts-api');
|
|
|
|
const tts = new GoogleTTS();
|
|
const { Socket } = require('socket.io-client');
|
|
|
|
const ini = require('ini');
|
|
|
|
let envInfo = (ipcRenderer.sendSync('environment'))
|
|
|
|
// TODO: remove gooogle voices txt and use api instead
|
|
const googleVoices = fs.readFileSync(path.join(__dirname, './config/googleVoices.txt')).toString().split('\r\n');
|
|
// TODO: remove amazon voices txt and use api instead (sakura project has it)
|
|
const amazonVoices = fs.readFileSync(path.join(__dirname, './config/amazonVoices.txt')).toString().split('\r\n');
|
|
|
|
const languagesObject = fs.readFileSync(path.join(__dirname, './config/languages.txt')).toString().split('\r\n');
|
|
|
|
// html elements
|
|
const root = document.documentElement;
|
|
const ttsSelector = document.body.querySelector('#TTSSelector');
|
|
const amazonVoiceSelect = document.querySelector('#amazonVoice'); // obtain the html reference of the amazon voices comboBox
|
|
const notificationAudioDevices = document.querySelector('#notificationAudioDevice'); // obtain the html reference of the installedTTS comboBox
|
|
const devicesDropdown = document.querySelector('#devicesDropdown');
|
|
const notificationSound = document.querySelector('#notification'); // obtain the html reference of the sound comboBox
|
|
const ttsAudioDevices = document.querySelector('#ttsAudioDevice'); // obtain the html reference of the installedTTS comboBox
|
|
|
|
|
|
// laod local javascript files
|
|
const chat = require(path.join(__dirname, './js/chat'));
|
|
|
|
const messageTemplates = require(path.join(__dirname, './js/messageTemplates'));
|
|
const logger = require(path.join(__dirname, './js/logger'));
|
|
const sound = require(path.join(__dirname, './js/sound'));
|
|
const talk = require(path.join(__dirname, './js/voiceQueue')); // Voice queue system
|
|
const config = require(path.join(__dirname, './js/settings'));
|
|
|
|
let notificationSounds = undefined;
|
|
if (envInfo.env) {
|
|
notificationSounds = path.join(envInfo.path, './sounds/notifications');
|
|
} else {
|
|
notificationSounds = path.join(__dirname, './sounds/notifications');
|
|
}
|
|
|
|
const twitch = config.settings.TWITCH.USE_TWITCH ? require(path.join(__dirname, './js/twitch')) : '';
|
|
|
|
let server;
|
|
let socket;
|
|
|
|
if (config.settings.SERVER.USE_SERVER) {
|
|
server = require(path.join(__dirname, './js/server'));
|
|
socket = io(`http://localhost:${config.settings.SERVER.PORT}`); // Connect to your Socket.IO server
|
|
}
|
|
|
|
const Polly = config.settings.AMAZON.USE_AMAZON ? require(path.join(__dirname, './js/amazon')) : '';
|
|
const google = config.settings.GOOGLE.USE_GOOGLE ? require(path.join(__dirname, './js/amazon')) : '';
|
|
|
|
const theme = require(path.join(__dirname, './js/theme'));
|
|
|
|
// initialize values
|
|
config.getGeneralSettings();
|
|
config.setCustomThemeToggle();
|
|
|
|
|
|
let selectedVoiceIndex;
|
|
let selectedEncodingIndex;
|
|
let selectedTtsAudioDeviceIndex;
|
|
const TTSVolume = 1;
|
|
|
|
const notificationSoundVolume = 1;
|
|
// const slider = document.body.querySelector('#slider');
|
|
const StartDateAndTime = Date.now();
|
|
const speakButton = document.querySelector('#speakBtn');
|
|
|
|
const amazonCredentials = {
|
|
accessKeyId: config.settings.AMAZON.ACCESS_KEY,
|
|
secretAccessKey: config.settings.AMAZON.ACCESS_SECRET,
|
|
};
|
|
|
|
// Check for installed sounds
|
|
fs.readdir(notificationSounds, (err, files) => {
|
|
files.forEach((file, i) => {
|
|
// Create a new option element.
|
|
const option = document.createElement('option');
|
|
|
|
// Set the options value and text.
|
|
option.value = i;
|
|
option.innerHTML = file;
|
|
|
|
// Add the option to the sound selector.
|
|
notificationSound.appendChild(option);
|
|
});
|
|
|
|
// set the saved notification sound
|
|
notificationSound.selectedIndex = config.settings.AUDIO.NOTIFICATION_SOUND;
|
|
});
|
|
|
|
async function getAudioDevices() {
|
|
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
|
|
// logger.info('enumerateDevices() not supported.');
|
|
return;
|
|
}
|
|
|
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
const audioOutputDevices = devices.filter((device) => device.kind === 'audiooutput');
|
|
|
|
audioOutputDevices.forEach((device) => {
|
|
const option = document.createElement('option');
|
|
option.text = device.label || `Output ${device.deviceId}`;
|
|
option.value = device.deviceId;
|
|
ttsAudioDevices.appendChild(option);
|
|
});
|
|
|
|
ttsAudioDevices.selectedIndex = config.settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE;
|
|
}
|
|
|
|
getAudioDevices();
|
|
|
|
function setLanguagesinSelect(languageSelector, setting) {
|
|
let languageSelect = document.querySelector(languageSelector); // obtain the html reference of the google voices comboBox
|
|
|
|
const languages = Object.keys(languagesObject);
|
|
languages.forEach((language) => {
|
|
const option = document.createElement('option');
|
|
|
|
option.value = language;
|
|
option.innerHTML = languagesObject[language];
|
|
|
|
languageSelect.appendChild(option);
|
|
});
|
|
|
|
languageSelect.selectedIndex = setting;
|
|
}
|
|
|
|
setLanguagesinSelect("#primaryLanguage", config.settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX);
|
|
setLanguagesinSelect("#secondaryLanguage", config.settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX);
|
|
|
|
function getInstalledVoices(callback) {
|
|
say.getInstalledVoices((err, voices) => {
|
|
|
|
function setVoicesinSelect(voiceSelector) {
|
|
let voiceSelect = document.querySelector(voiceSelector); // obtain the html reference of the google voices comboBox
|
|
|
|
const internalTTSHeader = document.createElement('optgroup');
|
|
internalTTSHeader.label = "Internal TTS";
|
|
voiceSelect.appendChild(internalTTSHeader);
|
|
|
|
// const installedTTS = document.querySelector('#installedTTS'); // obtain the html reference of the installedTTS comboBox
|
|
voices.forEach((voice, i) => {
|
|
const option = document.createElement('option');
|
|
|
|
option.value = i;
|
|
option.innerHTML = voice;
|
|
|
|
// installedTTS.appendChild(option);
|
|
internalTTSHeader.appendChild(option);
|
|
});
|
|
}
|
|
setVoicesinSelect("#primaryVoice");
|
|
setVoicesinSelect("#secondaryVoice");
|
|
|
|
callback();
|
|
});
|
|
}
|
|
|
|
function getAmazonVoices(callback) {
|
|
if (!config.settings.AMAZON.USE_AMAZON) {
|
|
callback();
|
|
return;
|
|
}
|
|
|
|
function setVoicesinSelect(voiceSelector) {
|
|
let voiceSelect = document.querySelector(voiceSelector); // obtain the html reference of the google voices comboBox
|
|
|
|
const internalTTSHeader = document.createElement('optgroup');
|
|
internalTTSHeader.label = "Amazon TTS";
|
|
voiceSelect.appendChild(internalTTSHeader);
|
|
|
|
const voices = Object.keys(amazonVoices);
|
|
voices.forEach((voice) => {
|
|
const option = document.createElement('option');
|
|
|
|
option.value = voice;
|
|
option.innerHTML = amazonVoices[voice];
|
|
|
|
internalTTSHeader.appendChild(option);
|
|
});
|
|
}
|
|
|
|
setVoicesinSelect("#primaryVoice");
|
|
setVoicesinSelect("#secondaryVoice");
|
|
|
|
callback();
|
|
}
|
|
|
|
function getGoogleVoices(callback) {
|
|
if (!config.settings.GOOGLE.USE_GOOGLE) {
|
|
callback();
|
|
return;
|
|
}
|
|
|
|
function setVoicesinSelect(voiceSelector) {
|
|
let voiceSelect = document.querySelector(voiceSelector); // obtain the html reference of the google voices comboBox
|
|
|
|
const internalTTSHeader = document.createElement('optgroup');
|
|
internalTTSHeader.label = "Google TTS";
|
|
voiceSelect.appendChild(internalTTSHeader);
|
|
|
|
const googleVoiceSelect = document.querySelector('#googleVoice'); // obtain the html reference of the google voices comboBox
|
|
const voices = Object.keys(googleVoices);
|
|
voices.forEach((voice) => {
|
|
const option = document.createElement('option');
|
|
option.classList.add("option");
|
|
|
|
option.value = voice;
|
|
option.innerHTML = googleVoices[voice];
|
|
|
|
internalTTSHeader.appendChild(option);
|
|
});
|
|
}
|
|
setVoicesinSelect("#primaryVoice");
|
|
setVoicesinSelect("#secondaryVoice");
|
|
|
|
callback();
|
|
}
|
|
|
|
getGoogleVoices(function () {
|
|
getAmazonVoices(function () {
|
|
getInstalledVoices(function () {
|
|
let primaryVoice = document.querySelector("#primaryVoice");
|
|
primaryVoice.selectedIndex = config.settings.TTS.PRIMARY_TTS_VOICE;
|
|
|
|
let secondaryVoice = document.querySelector("#secondaryVoice");
|
|
secondaryVoice.selectedIndex = config.settings.TTS.SECONDARY_TTS_VOICE;
|
|
});
|
|
});
|
|
});
|
|
|
|
// Small tooltip
|
|
Array.from(document.body.querySelectorAll('[tip]')).forEach((el) => {
|
|
const tip = document.createElement('div');
|
|
const body = document.querySelector('.container');
|
|
const element = el;
|
|
tip.classList.add('tooltip');
|
|
tip.classList.add('tooltiptext');
|
|
tip.innerText = el.getAttribute('tip');
|
|
tip.style.transform = `translate(${el.hasAttribute('tip-left') ? 'calc(-100% - 5px)' : '15px'}, ${el.hasAttribute('tip-top') ? '-100%' : '15px'
|
|
})`;
|
|
body.appendChild(tip);
|
|
element.onmousemove = (e) => {
|
|
tip.style.left = `${e.x}px`;
|
|
tip.style.top = `${e.y}px`;
|
|
tip.style.zIndex = 1;
|
|
tip.style.visibility = "visible";
|
|
};
|
|
element.onmouseleave = (e) => {
|
|
tip.style.visibility = "hidden";
|
|
};
|
|
});
|
|
|
|
function showChatMessage(article) {
|
|
document.querySelector('#chatBox').appendChild(article);
|
|
const messages = Array.from(document.body.querySelectorAll('.msg-container'));
|
|
const lastMessage = messages[messages.length - 1];
|
|
lastMessage.scrollIntoView({ behavior: 'smooth' });
|
|
}
|
|
|
|
function getPostTime() {
|
|
const date = new Date();
|
|
document.body.querySelectorAll('.container').innerHTML = date.getHours();
|
|
const hours = date.getHours();
|
|
const minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
|
|
const time = `${hours}:${minutes}`;
|
|
|
|
return time;
|
|
}
|
|
|
|
function showPreviewChatMessage() {
|
|
const message = messageTemplates.messageTemplate;
|
|
document.querySelector('#mini-mid').innerHTML += message;
|
|
const messages = Array.from(document.body.querySelectorAll('#mini-mid'));
|
|
const lastMessage = messages[messages.length - 1];
|
|
lastMessage.scrollIntoView({ behavior: 'smooth' });
|
|
}
|
|
|
|
showPreviewChatMessage();
|
|
|
|
function hideText(button, field) {
|
|
document.body.querySelector(button).addEventListener('click', () => {
|
|
const passwordInput = document.querySelector(field);
|
|
if (passwordInput.type === 'password') {
|
|
passwordInput.type = 'lol';
|
|
} else {
|
|
passwordInput.type = 'password';
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
hideText('.password-toggle-btn1', "#TWITCH_OAUTH_TOKEN");
|
|
hideText('.password-toggle-btn2', "#TWITCH_CLIENT_ID");
|
|
hideText('.password-toggle-btn3', "#TWITCH_CLIENT_SECRET");
|
|
hideText('.password-toggle-btn4', "#AMAZON_ACCESS_KEY");
|
|
hideText('.password-toggle-btn5', "#AMAZON_ACCESS_SECRET");
|
|
hideText('.password-toggle-btn6', "#GOOGLE_API_KEY");
|
|
|
|
// Amazon TTS
|
|
// const polly = new Polly(amazonCredentials);
|
|
// const options = {
|
|
// text: 'Hallo mijn naam is KEES',
|
|
// voiceId: 'Lotte',
|
|
// };
|
|
|
|
// const fileStream = fs.createWriteStream(path.join(__dirname, '/public/sounds/tts/Amazon_audio.mp3'));
|
|
|
|
// polly.textToSpeech(options, (err, audioStream) => {
|
|
// if (err) {
|
|
// return console.warn(err.message);
|
|
// }
|
|
// audioStream.pipe(fileStream);
|
|
// return 1;
|
|
// });
|