diff --git a/package-lock.json b/package-lock.json index e247c1a..88b67d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "loquendo-bot", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "loquendo-bot", - "version": "2.0.0", + "version": "2.1.0", "license": "ISC", "dependencies": { "axios": "^1.4.0", @@ -15,6 +15,7 @@ "franc": "^6.1.0", "i18next-electron-language-detector": "^0.0.10", "ini": "^2.0.0", + "kill-port": "^2.0.1", "langdetect": "^0.2.1", "node-google-tts-api": "^1.1.1", "querystring": "^0.2.1", @@ -3331,6 +3332,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-them-args": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/get-them-args/-/get-them-args-1.3.2.tgz", + "integrity": "sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw==" + }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -4013,6 +4019,18 @@ "json-buffer": "3.0.1" } }, + "node_modules/kill-port": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/kill-port/-/kill-port-2.0.1.tgz", + "integrity": "sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ==", + "dependencies": { + "get-them-args": "1.3.2", + "shell-exec": "1.0.2" + }, + "bin": { + "kill-port": "cli.js" + } + }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -5899,6 +5917,11 @@ "node": ">=8" } }, + "node_modules/shell-exec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shell-exec/-/shell-exec-1.0.2.tgz", + "integrity": "sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg==" + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", diff --git a/package.json b/package.json index a4fca9f..b88cd65 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "franc": "^6.1.0", "i18next-electron-language-detector": "^0.0.10", "ini": "^2.0.0", + "kill-port": "^2.0.1", "langdetect": "^0.2.1", "node-google-tts-api": "^1.1.1", "querystring": "^0.2.1", @@ -45,4 +46,4 @@ "@electron-forge/plugin-auto-unpack-natives": "^6.2.1", "electron": "25.4.0" } -} \ No newline at end of file +} diff --git a/src/css/chat.css b/src/css/chat.css index b205162..b41a751 100644 --- a/src/css/chat.css +++ b/src/css/chat.css @@ -369,7 +369,7 @@ select { .AdvancedMenu { border: 1px var(--main-color2) solid; margin-top: 10px; - width: 300px; + min-width: 555px; border-radius: 5px; border-radius: 5px; } @@ -377,6 +377,8 @@ select { .legendStyle { margin-left: 1em; padding: 0.2em 0.8em; + display: flex; + align-items: center; } .AdvancedMenuRow { diff --git a/src/css/logger.css b/src/css/logger.css index 5deb96a..6b40515 100644 --- a/src/css/logger.css +++ b/src/css/logger.css @@ -14,15 +14,15 @@ td { } .info { - background-color: lightblue; + background-color: lightblue !important; } .warn { - background-color: yellow; + background-color: #f39c12 !important; } .error { - background-color: lightcoral; + background-color: #e74c3c !important; } #logTable { diff --git a/src/css/menu.css b/src/css/menu.css index 640884b..0a5b65d 100644 --- a/src/css/menu.css +++ b/src/css/menu.css @@ -28,6 +28,7 @@ .OptionPanel.show { display: block; + overflow: auto; } .menu { diff --git a/src/css/sliders.css b/src/css/sliders.css index fed7173..f9eea45 100644 --- a/src/css/sliders.css +++ b/src/css/sliders.css @@ -1,184 +1,179 @@ /*generated with Input range slider CSS style generator (version 20211225) https://toughengineer.github.io/demo/slider-styler*/ -input[type=range].styled-slider { - /* height: 500px; */ - background: transparent; - -webkit-appearance: none; - width: 300px; +input[type='range'].styled-slider { + /* height: 500px; */ + background: transparent; + -webkit-appearance: none; + width: 300px; } /*progress support*/ -input[type=range].styled-slider.slider-progress1 { - --range: calc(var(--max) - var(--min)); - --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); - --sx: calc(0.5* 2em + var(--ratio) * (100% - 2em)); +input[type='range'].styled-slider.slider-progress1 { + --range: calc(var(--max) - var(--min)); + --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); + --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); } -input[type=range].styled-slider.slider-progress2 { - --range: calc(var(--max) - var(--min)); - --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); - --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); +input[type='range'].styled-slider.slider-progress2 { + --range: calc(var(--max) - var(--min)); + --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); + --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); } -input[type=range].styled-slider.slider-progress3 { - --range: calc(var(--max) - var(--min)); - --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); - --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); +input[type='range'].styled-slider.slider-progress3 { + --range: calc(var(--max) - var(--min)); + --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); + --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); } -input[type=range].styled-slider.slider-progress4 { - --range: calc(var(--max) - var(--min)); - --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); - --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); +input[type='range'].styled-slider.slider-progress4 { + --range: calc(var(--max) - var(--min)); + --ratio: calc((var(--tiempotemporal) - var(--min)) / var(--range)); + --sx: calc(0.5 * 2em + var(--ratio) * (100% - 2em)); } /*webkit*/ -input[type=range].styled-slider::-webkit-slider-thumb { - -webkit-appearance: none; - width: 2em; - height: 40px; - border-radius: 20px; - background: #FFFFFF; - border: none; - box-shadow: 0 0 2px black; - margin-top: calc(2em * 0.5 - 2em * 0.5); +input[type='range'].styled-slider::-webkit-slider-thumb { + -webkit-appearance: none; + width: 2em; + height: 40px; + border-radius: 20px; + background: #ffffff; + border: none; + box-shadow: 0 0 2px black; + margin-top: calc(2em * 0.5 - 2em * 0.5); } -input[type=range].styled-slider::-webkit-slider-runnable-track { - height: 40px; - border: none; - border-radius: 20px; - background: #1a1a1a; - box-shadow: none; +input[type='range'].styled-slider::-webkit-slider-runnable-track { + height: 40px; + border: none; + border-radius: 20px; + background: #1a1a1a; + box-shadow: none; } -input[type=range].styled-slider.slider-progress1::-webkit-slider-runnable-track { - background: linear-gradient(#7b2cbf, #7b2cbf) 0/var(--sx) 100% no-repeat, #1a1a1a; - ; +input[type='range'].styled-slider.slider-progress1::-webkit-slider-runnable-track { + background: linear-gradient(#7b2cbf, #7b2cbf) 0 / var(--sx) 100% no-repeat, #1a1a1a; } -input[type=range].styled-slider.slider-progress2::-webkit-slider-runnable-track { - background: linear-gradient(#7b2cbf, #7b2cbf) 0/var(--sx) 100% no-repeat, #1a1a1a; - ; +input[type='range'].styled-slider.slider-progress2::-webkit-slider-runnable-track { + background: linear-gradient(#7b2cbf, #7b2cbf) 0 / var(--sx) 100% no-repeat, #1a1a1a; } -input[type=range].styled-slider.slider-progress3::-webkit-slider-runnable-track { - background: linear-gradient(#7b2cbf, #7b2cbf) 0/var(--sx) 100% no-repeat, #1a1a1a; - ; +input[type='range'].styled-slider.slider-progress3::-webkit-slider-runnable-track { + background: linear-gradient(#7b2cbf, #7b2cbf) 0 / var(--sx) 100% no-repeat, #1a1a1a; } -input[type=range].styled-slider.slider-progress4::-webkit-slider-runnable-track { - background: linear-gradient(#7b2cbf, #7b2cbf) 0/var(--sx) 100% no-repeat, #1a1a1a; - ; +input[type='range'].styled-slider.slider-progress4::-webkit-slider-runnable-track { + background: linear-gradient(#7b2cbf, #7b2cbf) 0 / var(--sx) 100% no-repeat, #1a1a1a; } /*mozilla*/ -input[type=range].styled-slider::-moz-range-thumb { - width: 2em; - height: 40px; - border-radius: 20px; - background: #FFFFFF; - border: none; - box-shadow: 0 0 2px black; +input[type='range'].styled-slider::-moz-range-thumb { + width: 2em; + height: 40px; + border-radius: 20px; + background: #ffffff; + border: none; + box-shadow: 0 0 2px black; } -input[type=range].styled-slider::-moz-range-track { - height: 40px; - border: none; - border-radius: 20px; - background: #1a1a1a; - box-shadow: none; +input[type='range'].styled-slider::-moz-range-track { + height: 40px; + border: none; + border-radius: 20px; + background: #1a1a1a; + box-shadow: none; } -input[type=range].styled-slider.slider-progress1::-moz-range-track { - background: linear-gradient(#7b2cbf, #7b2cbf) 0/var(--sx) 100% no-repeat, #464646; +input[type='range'].styled-slider.slider-progress1::-moz-range-track { + background: linear-gradient(#7b2cbf, #7b2cbf) 0 / var(--sx) 100% no-repeat, #464646; } -input[type=range].styled-slider.slider-progress2::-moz-range-track { - background: linear-gradient(#7b2cbf, #7b2cbf) 0/var(--sx) 100% no-repeat, #464646; +input[type='range'].styled-slider.slider-progress2::-moz-range-track { + background: linear-gradient(#7b2cbf, #7b2cbf) 0 / var(--sx) 100% no-repeat, #464646; } -input[type=range].styled-slider.slider-progress3::-moz-range-track { - background: linear-gradient(#7b2cbf, #7b2cbf) 0/var(--sx) 100% no-repeat, #464646; +input[type='range'].styled-slider.slider-progress3::-moz-range-track { + background: linear-gradient(#7b2cbf, #7b2cbf) 0 / var(--sx) 100% no-repeat, #464646; } -input[type=range].styled-slider.slider-progress4::-moz-range-track { - background: linear-gradient(#7b2cbf, #7b2cbf) 0/var(--sx) 100% no-repeat, #464646; +input[type='range'].styled-slider.slider-progress4::-moz-range-track { + background: linear-gradient(#7b2cbf, #7b2cbf) 0 / var(--sx) 100% no-repeat, #464646; } /*ms*/ -input[type=range].styled-slider::-ms-fill-upper { - background: transparent; - border-color: transparent; +input[type='range'].styled-slider::-ms-fill-upper { + background: transparent; + border-color: transparent; } -input[type=range].styled-slider::-ms-fill-lower { - background: transparent; - border-color: transparent; +input[type='range'].styled-slider::-ms-fill-lower { + background: transparent; + border-color: transparent; } -input[type=range].styled-slider::-ms-thumb { - width: 2em; - height: 40px; - border-radius: 20px; - background: #FFFFFF; - border: none; - box-shadow: 0 0 2px black; - margin-top: 0; - box-sizing: border-box; +input[type='range'].styled-slider::-ms-thumb { + width: 2em; + height: 40px; + border-radius: 20px; + background: #ffffff; + border: none; + box-shadow: 0 0 2px black; + margin-top: 0; + box-sizing: border-box; } -input[type=range].styled-slider::-ms-track { - height: 40px; - border-radius: 20px; - background: #1a1a1a; - border: none; - box-shadow: none; - box-sizing: border-box; +input[type='range'].styled-slider::-ms-track { + height: 40px; + border-radius: 20px; + background: #1a1a1a; + border: none; + box-shadow: none; + box-sizing: border-box; } -input[type=range].styled-slider.slider-progress1::-ms-fill-lower { - height: 40px; - border-radius: 1em 0 0 1em; - margin: -undefined 0 -undefined -undefined; - background: #7b2cbf; - border: none; - border-right-width: 0; +input[type='range'].styled-slider.slider-progress1::-ms-fill-lower { + height: 40px; + border-radius: 1em 0 0 1em; + margin: -undefined 0 -undefined -undefined; + background: #7b2cbf; + border: none; + border-right-width: 0; } -input[type=range].styled-slider.slider-progress2::-ms-fill-lower { - height: 40px; - border-radius: 1em 0 0 1em; - margin: -undefined 0 -undefined -undefined; - background: #7b2cbf; - border: none; - border-right-width: 0; +input[type='range'].styled-slider.slider-progress2::-ms-fill-lower { + height: 40px; + border-radius: 1em 0 0 1em; + margin: -undefined 0 -undefined -undefined; + background: #7b2cbf; + border: none; + border-right-width: 0; } -input[type=range].styled-slider.slider-progress3::-ms-fill-lower { - height: 40px; - border-radius: 1em 0 0 1em; - margin: -undefined 0 -undefined -undefined; - background: #7b2cbf; - border: none; - border-right-width: 0; +input[type='range'].styled-slider.slider-progress3::-ms-fill-lower { + height: 40px; + border-radius: 1em 0 0 1em; + margin: -undefined 0 -undefined -undefined; + background: #7b2cbf; + border: none; + border-right-width: 0; } -input[type=range].styled-slider.slider-progress4::-ms-fill-lower { - height: 40px; - border-radius: 1em 0 0 1em; - margin: -undefined 0 -undefined -undefined; - background: #7b2cbf; - border: none; - border-right-width: 0; +input[type='range'].styled-slider.slider-progress4::-ms-fill-lower { + height: 40px; + border-radius: 1em 0 0 1em; + margin: -undefined 0 -undefined -undefined; + background: #7b2cbf; + border: none; + border-right-width: 0; } .inputBox { - border: none; - width: 50px; - border-radius: 10px; - text-align: center; - font-size: 14pt; - font-weight: bold; - margin-left: 10px; -} \ No newline at end of file + border: none; + width: 38px; + border-radius: 10px; + text-align: center; + font-size: 14pt; + font-weight: bold; +} diff --git a/src/css/tabs.css b/src/css/tabs.css index 7d147fe..47cef1b 100644 --- a/src/css/tabs.css +++ b/src/css/tabs.css @@ -73,7 +73,7 @@ section { .scale { height: 2em; width: 2em; - vertical-align: bottom + vertical-align: bottom; } .tab { @@ -83,15 +83,14 @@ section { cursor: pointer; } -input:checked+label { - border-top-color: #FFB03D; - border-right-color: #DDD; - border-left-color: #DDD; +input:checked + label { + border-top-color: #ffb03d; + border-right-color: #ddd; + border-left-color: #ddd; border-bottom-color: transparent; text-decoration: none; } - /* --------------------------------- */ .radius { @@ -129,13 +128,13 @@ input:checked+label { .tabx-bar .tabx::before { position: absolute; - content: ""; + content: ''; width: 26%; height: 13%; border-top-left-radius: 200px; border-top-right-radius: 200px; border-bottom: none; - background-color: #607D8B; + background-color: #607d8b; /* bottom: -8px; */ opacity: 0; transition: all 0.3s ease-in-out; @@ -153,7 +152,8 @@ input:checked+label { bottom: 0px; } -.tabx-bar .tabx::after {} +.tabx-bar .tabx::after { +} .tabx-bar .tabx:hover { padding-bottom: 10px; @@ -192,7 +192,7 @@ input:checked+label { } select { - font-size: .9rem; + font-size: 0.9rem; height: 40px; border-radius: 20px; background-color: var(--main-color3); @@ -258,7 +258,7 @@ select { padding-left: 10px; } -input[type="password"] { +input[type='password'] { background: var(--main-color3); border: none; height: 40px; @@ -272,7 +272,19 @@ input[type="password"] { /* To make space for the reveal button */ } -input[type="lol"] { +input[type='url'] { + background: var(--main-color3); + border: none; + height: 40px; + border-radius: 40px; + width: 260px; + outline: none; + color: var(--main-color2); + font-size: 10pt; + margin-left: 10px; +} + +input[type='lol'] { background: var(--main-color3); border: none; height: 40px; @@ -292,7 +304,7 @@ input[type="lol"] { background-color: transparent; border: none; cursor: pointer; - left: 450px; + left: 425px; } /* Hide the default appearance of the button */ @@ -331,20 +343,20 @@ input[type="lol"] { } /* Apply different colors based on the toast type */ -.toast.info { - background-color: #3498db; +.info { + background-color: lightblue !important; } -.toast.success { - background-color: #2ecc71; +.success { + background-color: #2ecc71 !important; } -.toast.warning { - background-color: #f39c12; +.warning { + background-color: #f39c12 !important; } -.toast.error { - background-color: #e74c3c; +.error { + background-color: #e74c3c !important; } /* CSS animation for the toast appearance */ @@ -413,19 +425,30 @@ input[type="lol"] { visibility: visible; } */ -input[type=text]:disabled { - background: #dddddd; +div[type='text']:disabled { + background: #4b4b4b; + display: none; } -input[type2=text]:disabled { - background: #dddddd; +input[type='text']:disabled { + background: #4b4b4b; } -button[type=text]:disabled { - background: #dddddd; +button[type='text']:disabled { + background: #4b4b4b; + display: none; +} + +input[type2='text']:disabled { + background: #4b4b4b; } div:disabled { - background: #dddddd; + background: #4b4b4b; filter: brightness(200%); -} \ No newline at end of file +} + +div:disabled { + background: #4b4b4b; + filter: brightness(200%); +} diff --git a/src/css/tts-menu.css b/src/css/tts-menu.css index c204953..a44cfe8 100644 --- a/src/css/tts-menu.css +++ b/src/css/tts-menu.css @@ -22,9 +22,10 @@ #volume-icon { color: var(--main-color2); - width: 50px; + scale: 0.75; cursor: pointer; text-align: center; + align-self: center; } #image { @@ -131,4 +132,4 @@ textarea { /* filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%); */ align-items: flex-start; margin: auto; -} \ No newline at end of file +} diff --git a/src/css/volume-slider.css b/src/css/volume-slider.css index e96a86f..15fc8d9 100644 --- a/src/css/volume-slider.css +++ b/src/css/volume-slider.css @@ -67,11 +67,14 @@ box-shadow: 0 0 0 3px rgba(255, 255, 255, 1); } -.volume-icon-container { +.option-icon-container { display: flex; flex-direction: column; - justify-content: center; + /* justify-content: center; */ align-items: center; + /* width: 78px; */ + /* float: right; */ + flex-grow: 1; } .brush-icon-container { @@ -81,4 +84,4 @@ .icon { fill: var(--main-color2); -} \ No newline at end of file +} diff --git a/src/images/icon.ico b/src/images/icon.ico index ed9c83b..7303011 100644 Binary files a/src/images/icon.ico and b/src/images/icon.ico differ diff --git a/src/images/icon.png b/src/images/icon.png index be75fe1..c145646 100644 Binary files a/src/images/icon.png and b/src/images/icon.png differ diff --git a/src/images/note.svg b/src/images/note.svg new file mode 100644 index 0000000..8f060d3 --- /dev/null +++ b/src/images/note.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/images/stt.svg b/src/images/stt.svg new file mode 100644 index 0000000..2b35389 --- /dev/null +++ b/src/images/stt.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + +Icon_24px_SpeechtoText_Color + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/images/theme.svg b/src/images/theme.svg new file mode 100644 index 0000000..eaa9401 --- /dev/null +++ b/src/images/theme.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/images/tts.svg b/src/images/tts.svg new file mode 100644 index 0000000..6d20ed6 --- /dev/null +++ b/src/images/tts.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + +Icon_24px_TexttoSpeech_Color + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/index.html b/src/index.html index f869de2..55a4d06 100644 --- a/src/index.html +++ b/src/index.html @@ -1,47 +1,44 @@ - - - - + + + LoquendoBot - - - - - - - - - - + + + + + + + + + - + crossorigin="anonymous" + referrerpolicy="no-referrer" + /> + -
-
🇬🇧 EN
-
🇳🇱 - NL
-
🇪🇸 - ES
-
🇬🇧 - EN
+
🇳🇱 NL
+
🇪🇸 ES
+
🇬🇧 EN
@@ -60,7 +57,6 @@
-
@@ -72,22 +68,16 @@
  • -
  • - -
  • -
  • +
  • -
  • +
  • -
  • +
  • @@ -102,74 +92,6 @@
    - - -
    -
    -
    -
    -

    Primary TTS Voice

    -
    - - - -
    -

    Secondary TTS Voice

    -
    - - - -
    -
    - -

    TTS Volume

    -
    -
    -
    - - - -
    -
    - - - -
    -
    -
    -

    Test TTS

    -
    - -
    - - -
    -
    -

    TTS Output Device

    -
    - -
    -
    -
    -
    - -
    @@ -187,335 +109,263 @@ -
    -
    +
    -
    -
    +
    -

    Theme

    - +
    -

    Notification Sound

    -
    - -
    - -
    - - - -
    -
    -
    - -
    - - - - - - -
    -
    - -
    - -
    -
    -
    - -  - -
    -
    -

    Moderators

    -
      -
    -

    Viewers

    -
      -
    -
    -
    -
      -
    • a
    • -
    • b
    • -
    • c
    • -
    -
    -
    -
      -
    • 1
    • -
    • 2
    • -
    • 3
    • -
    -
    -
    -
    -
    -
    - -
    -
    - -
    - - - - + +
    +
    + +
    + + - \ No newline at end of file + + +
    +
    + +
    + + + +
    +
    +
    + +  + +
    +
    +

    Moderators

    +
      +

      Viewers

      +
        +
        +
        +
          +
        • a
        • +
        • b
        • +
        • c
        • +
        +
        +
        +
          +
        • 1
        • +
        • 2
        • +
        • 3
        • +
        +
        +
        +
        +
        +
        + +
        +
        + +
        + + + + + diff --git a/src/js/auth.js b/src/js/auth.js new file mode 100644 index 0000000..d80933c --- /dev/null +++ b/src/js/auth.js @@ -0,0 +1,65 @@ +console.log("kees"); +// const clientId = 'YOUR_TWITCH_CLIENT_ID'; +// const redirectUri = 'http://localhost:1989/auth'; +// const scopes = ['chat:edit', 'chat:read']; + +// const express = require('express'); +// const tempAuthServer = express(); +// const port = 1989; + +// const { parse: parseQueryString } = require('querystring'); + +// tempAuthServer.use(function (req, res, next) { +// if (req.url !== "/auth") { +// let token = parseQueryString(req.query.auth) +// res.json(token["#access_token"]); +// // settings.TWITCH.OAUTH_TOKEN = token["#access_token"]; +// // fs.writeFileSync(settingsPath, ini.stringify(settings)); +// // settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); +// // tempAuthServer.close(); +// } +// next(); +// }); + +// const htmlString = ` +// +// +// +// Authentication +// +// +//

        Authentication successful! You can close this window now.

        +// +// +// +// +// +// +// `; + +// tempAuthServer.get('/auth', (req, res) => { +// // res.send(htmlString); +// }); + +// tempAuthServer.post('/auth', (req, res) => { +// res.render('authentication', { name: req.body.name }); +// }); + +// tempAuthServer.listen(port, () => { }); + +// const authURL = `https://id.twitch.tv/oauth2/authorize?client_id=${settings.TWITCH.CLIENT_ID}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=token&scope=${scopes.join(' ')}`; +// shell.openExternal(authURL); +onsole.log('ExecPath', process.execPath); + +process.on('message', (m) => { + console.log('Got message:', m); + + process.send("message", "lol"); +}); \ No newline at end of file diff --git a/src/js/chat.js b/src/js/chat.js index c96dd05..5925b9a 100644 --- a/src/js/chat.js +++ b/src/js/chat.js @@ -117,7 +117,6 @@ displayPanel('.OptionPanel', '#Configuration', '#btnConfiguration'); displayPanel('.OptionPanel', '#Logs', '#btnLogs'); displayPanel('.OptionPanel', '#BrowsersourceChat', '#btnBrowsersourceChat'); displayPanel('.OptionPanel', '#BrowsersourceVtuber', '#btnBrowsersourceVtuber'); -displayPanel('.OptionPanel', '#TTS', '#btnTTS'); displayPanel('.OptionPanel', '#Chat', '#btnChat'); // #endregion @@ -142,25 +141,12 @@ const displayPanelX = (panelSelectorClass, panelSelectorID, btnSelectorID) => { }); }; -displayPanelX('.item', '#btnTTS', '#btnTTS'); displayPanelX('.item', '#btnChat', '#btnChat'); displayPanelX('.item', '#btnBrowsersourceChat', '#btnBrowsersourceChat'); displayPanelX('.item', '#btnBrowsersourceVtuber', '#btnBrowsersourceVtuber'); displayPanelX('.item', '#btnLogs', '#btnLogs'); displayPanelX('.item', '#btnConfiguration', '#btnConfiguration'); - -// #region Show/Hide Advanced Menu -document.body.querySelector('#ShowAdvancedMenu').addEventListener('click', () => { - document.getElementById('AdvancedMenu_mask').style.visibility = 'visible'; -}); - -document.body.querySelector('#HideAdvancedMenu').addEventListener('click', () => { - document.getElementById('AdvancedMenu_mask').style.visibility = 'hidden'; -}); - -// #endregion - // #region Show/Hide Theme Creator document.body.querySelector('#ShowThemeCreator').addEventListener('click', () => { document.getElementById('ThemeCreator_mask').style.visibility = 'visible'; diff --git a/src/js/logger.js b/src/js/logger.js index 408cdcf..0f36c94 100644 --- a/src/js/logger.js +++ b/src/js/logger.js @@ -24,11 +24,11 @@ const logger = createLogger({ format: fileFormat, transports: [ new transports.File({ - filename: path.join(__dirname, '../logs/error.log'), + filename: path.join(resourcesPath, '../logs/error.log'), level: 'error', }), new transports.File({ - filename: path.join(__dirname, '../logs/activity.log'), + filename: path.join(resourcesPath, '../logs/activity.log'), maxsize: 5242880, maxFiles: 5, }), @@ -44,7 +44,7 @@ if (process.env.NODE_ENV !== 'production') { ); } -fetch(path.join(__dirname, '../logs/activity.log')) +fetch(path.join(resourcesPath, '../logs/activity.log')) .then((response) => response.text()) .then((logData) => { const logLines = logData.trim().split('\n'); diff --git a/src/js/renderer.js b/src/js/renderer.js index 71a510d..112f7c9 100644 --- a/src/js/renderer.js +++ b/src/js/renderer.js @@ -1,14 +1,13 @@ +const fs = require('fs'); +const ini = require('ini'); const path = require('path'); // get directory path -const { - ipcRenderer, -} = require('electron'); // necessary electron libraries to send data to the app + +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); @@ -17,16 +16,18 @@ const GoogleTTS = require('node-google-tts-api'); const tts = new GoogleTTS(); const { Socket } = require('socket.io-client'); -const ini = require('ini'); +const main = ipcRenderer.sendSync('environment'); -let envInfo = (ipcRenderer.sendSync('environment')) +const resourcesPath = main.resourcesPath; +const settingsPath = main.settingsPath.toString(); +const settings = main.settings; // TODO: remove gooogle voices txt and use api instead -const googleVoices = fs.readFileSync(path.join(__dirname, './config/googleVoices.txt')).toString().split('\r\n'); +const googleVoices = fs.readFileSync(path.join(resourcesPath, './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 amazonVoices = fs.readFileSync(path.join(resourcesPath, './config/amazonVoices.txt')).toString().split('\r\n'); -const languagesObject = fs.readFileSync(path.join(__dirname, './config/languages.txt')).toString().split('\r\n'); +const languagesObject = fs.readFileSync(path.join(resourcesPath, './config/languages.txt')).toString().split('\r\n'); // html elements const root = document.documentElement; @@ -37,46 +38,44 @@ 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 chat = require(path.join(resourcesPath, './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')); +const messageTemplates = require(path.join(resourcesPath, './js/messageTemplates')); +const logger = require(path.join(resourcesPath, './js/logger')); +const sound = require(path.join(resourcesPath, './js/sound')); +const talk = require(path.join(resourcesPath, './js/voiceQueue')); // Voice queue system +const config = require(path.join(resourcesPath, './js/settings')); -let notificationSounds = undefined; -if (envInfo.env) { - notificationSounds = path.join(envInfo.path, './sounds/notifications'); -} else { - notificationSounds = path.join(__dirname, './sounds/notifications'); +let notificationSounds = path.join(resourcesPath, './sounds/notifications'); + +let twitch = require(path.join(resourcesPath, './js/twitch')); + +function reset() { + ipcRenderer.send('restart'); } -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 +function setServer() { + if (!settings.SERVER.USE_SERVER) { + return; + } + server = require(path.join(resourcesPath, './js/server')); + socket = io(`http://localhost:${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')) : ''; +setServer(); -const theme = require(path.join(__dirname, './js/theme')); +const Polly = settings.AMAZON.USE_AMAZON ? require(path.join(resourcesPath, './js/amazon')) : ''; +const google = settings.GOOGLE.USE_GOOGLE ? require(path.join(resourcesPath, './js/amazon')) : ''; + +const theme = require(path.join(resourcesPath, './js/theme')); // initialize values config.getGeneralSettings(); -config.setCustomThemeToggle(); - -let selectedVoiceIndex; -let selectedEncodingIndex; -let selectedTtsAudioDeviceIndex; const TTSVolume = 1; const notificationSoundVolume = 1; @@ -85,236 +84,233 @@ const StartDateAndTime = Date.now(); const speakButton = document.querySelector('#speakBtn'); const amazonCredentials = { - accessKeyId: config.settings.AMAZON.ACCESS_KEY, - secretAccessKey: config.settings.AMAZON.ACCESS_SECRET, + accessKeyId: settings.AMAZON.ACCESS_KEY, + secretAccessKey: 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'); + 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; + // Set the options value and text. + option.value = i; + option.innerHTML = file; - // Add the option to the sound selector. - notificationSound.appendChild(option); - }); + // Add the option to the sound selector. + notificationSound.appendChild(option); + }); - // set the saved notification sound - notificationSound.selectedIndex = config.settings.AUDIO.NOTIFICATION_SOUND; + // set the saved notification sound + notificationSound.selectedIndex = settings.AUDIO.NOTIFICATION_SOUND; }); async function getAudioDevices() { - if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { - // logger.info('enumerateDevices() not supported.'); - return; - } + 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'); + 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); - }); + 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; + ttsAudioDevices.selectedIndex = 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 + 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'); + const languages = Object.keys(languagesObject); + languages.forEach((language) => { + const option = document.createElement('option'); - option.value = language; - option.innerHTML = languagesObject[language]; + option.value = language; + option.innerHTML = languagesObject[language]; - languageSelect.appendChild(option); - }); + languageSelect.appendChild(option); + }); - languageSelect.selectedIndex = setting; + languageSelect.selectedIndex = setting; } -setLanguagesinSelect("#primaryLanguage", config.settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX); -setLanguagesinSelect("#secondaryLanguage", config.settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX); +setLanguagesinSelect('#primaryLanguage', settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX); +setLanguagesinSelect('#secondaryLanguage', settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX); function getInstalledVoices(callback) { - say.getInstalledVoices((err, voices) => { + say.getInstalledVoices((err, voices) => { + function setVoicesinSelect(voiceSelector) { + let voiceSelect = document.querySelector(voiceSelector); // obtain the html reference of the google voices comboBox - 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 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'); - // 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; - option.value = i; - option.innerHTML = voice; + // installedTTS.appendChild(option); + internalTTSHeader.appendChild(option); + }); + } + setVoicesinSelect('#primaryVoice'); + setVoicesinSelect('#secondaryVoice'); - // installedTTS.appendChild(option); - internalTTSHeader.appendChild(option); - }); - } - setVoicesinSelect("#primaryVoice"); - setVoicesinSelect("#secondaryVoice"); - - callback(); - }); + callback(); + }); } function getAmazonVoices(callback) { - if (!config.settings.AMAZON.USE_AMAZON) { - callback(); - return; - } + if (!settings.AMAZON.USE_AMAZON) { + callback(); + return; + } - function setVoicesinSelect(voiceSelector) { - let voiceSelect = document.querySelector(voiceSelector); // obtain the html reference of the google voices comboBox + 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 internalTTSHeader = document.createElement('optgroup'); + internalTTSHeader.label = 'Amazon TTS'; + voiceSelect.appendChild(internalTTSHeader); - const voices = Object.keys(amazonVoices); - voices.forEach((voice) => { - const option = document.createElement('option'); + const voices = Object.keys(amazonVoices); + voices.forEach((voice) => { + const option = document.createElement('option'); - option.value = voice; - option.innerHTML = amazonVoices[voice]; + option.value = voice; + option.innerHTML = amazonVoices[voice]; - internalTTSHeader.appendChild(option); - }); - } + internalTTSHeader.appendChild(option); + }); + } - setVoicesinSelect("#primaryVoice"); - setVoicesinSelect("#secondaryVoice"); + setVoicesinSelect('#primaryVoice'); + setVoicesinSelect('#secondaryVoice'); - callback(); + callback(); } function getGoogleVoices(callback) { - if (!config.settings.GOOGLE.USE_GOOGLE) { - callback(); - return; - } + if (!settings.GOOGLE.USE_GOOGLE) { + callback(); + return; + } - function setVoicesinSelect(voiceSelector) { - let voiceSelect = document.querySelector(voiceSelector); // obtain the html reference of the google voices comboBox + 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 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"); + 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]; + option.value = voice; + option.innerHTML = googleVoices[voice]; - internalTTSHeader.appendChild(option); - }); - } - setVoicesinSelect("#primaryVoice"); - setVoicesinSelect("#secondaryVoice"); + internalTTSHeader.appendChild(option); + }); + } + setVoicesinSelect('#primaryVoice'); + setVoicesinSelect('#secondaryVoice'); - callback(); + callback(); } getGoogleVoices(function () { - getAmazonVoices(function () { - getInstalledVoices(function () { - let primaryVoice = document.querySelector("#primaryVoice"); - primaryVoice.selectedIndex = config.settings.TTS.PRIMARY_TTS_VOICE; + getAmazonVoices(function () { + getInstalledVoices(function () { + let primaryVoice = document.querySelector('#primaryVoice'); + primaryVoice.selectedIndex = settings.TTS.PRIMARY_TTS_VOICE; - let secondaryVoice = document.querySelector("#secondaryVoice"); - secondaryVoice.selectedIndex = config.settings.TTS.SECONDARY_TTS_VOICE; - }); - }); + let secondaryVoice = document.querySelector('#secondaryVoice'); + secondaryVoice.selectedIndex = 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"; - }; + 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' }); + 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}`; + 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; + 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' }); + 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'; - } - }); - + 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"); +hideText('.password-toggle-btn1', '#TWITCH_OAUTH_TOKEN'); +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); @@ -323,7 +319,7 @@ hideText('.password-toggle-btn6', "#GOOGLE_API_KEY"); // voiceId: 'Lotte', // }; -// const fileStream = fs.createWriteStream(path.join(__dirname, '/public/sounds/tts/Amazon_audio.mp3')); +// const fileStream = fs.createWriteStream(path.join(resourcesPath, '/public/sounds/tts/Amazon_audio.mp3')); // polly.textToSpeech(options, (err, audioStream) => { // if (err) { @@ -331,4 +327,4 @@ hideText('.password-toggle-btn6', "#GOOGLE_API_KEY"); // } // audioStream.pipe(fileStream); // return 1; -// }); \ No newline at end of file +// }); diff --git a/src/js/server.js b/src/js/server.js index 7abd032..4eef702 100644 --- a/src/js/server.js +++ b/src/js/server.js @@ -1,54 +1,81 @@ const express = require('express'); - const app = express(); const path = require('path'); const http = require('http').createServer(app); const io = require('socket.io')(http); -if (!config.settings.SERVER.USE_SERVER) { - return; +if (!settings.SERVER.USE_SERVER) { + return; } -const PORT = config.settings.SERVER.PORT; +const PORT = settings.SERVER.PORT; + +let isVtuberEnabled = true; +let isChatBubbleEnabled = true; + +function startVtuber() { + if (!settings.SERVER.USE_VTUBER) { + isVtuberEnabled = false; + return; + } + + app.use('/vtuber', express.static(path.join(resourcesPath, './modules/vtuber/'))); + + let vtuber = document.body.querySelector('#BrowsersourceVtuber'); + let vtuberframe = document.createElement('iframe'); + vtuberframe.class = 'frame'; + vtuberframe.src = `http://localhost:${PORT}/vtuber`; + vtuberframe.style.width = '100%'; + vtuberframe.style.height = '100%'; + vtuberframe.frameBorder = 0; + vtuber.appendChild(vtuberframe); +} + +function startChatBubble() { + if (!settings.SERVER.USE_CHATBUBBLE) { + isChatBubbleEnabled = false; + return; + } + + app.use('/chat', express.static(path.join(resourcesPath, './modules/chat'))); + + let chat = document.body.querySelector('#BrowsersourceChat'); + let chatframe = document.createElement('iframe'); + chatframe.class = 'frame'; + chatframe.src = `http://localhost:${PORT}/chat`; + chatframe.style.width = '100%'; + chatframe.style.height = '100%'; + chatframe.frameBorder = 0; + chat.appendChild(chatframe); +} + +// Middleware to conditionally serve routes +app.use((req, res, next) => { + if (!isVtuberEnabled && req.path === '/vtuber') { + res.sendStatus(404); // Return a 404 status for /vtuber when it's disabled + } else if (!isChatBubbleEnabled && req.path === '/chat') { + res.sendStatus(404); // Return a 404 status for /chat when it's disabled + } else { + next(); // Proceed to the next middleware or route handler + } +}); http.listen(PORT, () => { - if (config.settings.SERVER.USE_VTUBER) { - app.use('/vtuber', express.static(path.join(__dirname, '../modules/vtuber/'))); - - let vtuber = document.body.querySelector('#BrowsersourceVtuber'); - let vtuberframe = document.createElement('iframe'); - vtuberframe.class = "frame"; - vtuberframe.src = `http://localhost:${PORT}/vtuber`; - vtuberframe.style.width = "100%"; - vtuberframe.style.height = "100%"; - vtuberframe.frameBorder = 0; - vtuber.appendChild(vtuberframe); - } - - if (config.settings.SERVER.USE_CHATBUBBLE) { - app.use('/chat', express.static(path.join(__dirname, '../modules/chat'))); - - let chat = document.body.querySelector('#BrowsersourceChat'); - let chatframe = document.createElement('iframe'); - chatframe.class = "frame"; - chatframe.src = `http://localhost:${PORT}/chat`; - chatframe.style.width = "100%"; - chatframe.style.height = "100%"; - chatframe.frameBorder = 0; - chat.appendChild(chatframe); - } + startVtuber(); + startChatBubble(); }); // Handle socket connections io.on('connection', (socket) => { + // Receive data from the client + socket.on('message', (data) => {}); - // Receive data from the client - socket.on('message', (data) => { }); + // Receive data from the client + socket.on('xxx', (logoUrl, username, message) => { + socket.broadcast.emit('message', logoUrl, username, message); + }); - // Receive data from the client - socket.on('xxx', (logoUrl, username, message) => { - socket.broadcast.emit('message', logoUrl, username, message); - }); - - socket.on('disconnect', () => { }); + socket.on('disconnect', () => {}); }); + +module.exports = { startVtuber, startChatBubble }; diff --git a/src/js/settings.js b/src/js/settings.js index 2ea5873..387a944 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -1,394 +1,478 @@ -let resourcesPath = path.join(__dirname, '../config/settings.ini'); -let settings = ini.parse(fs.readFileSync(resourcesPath, 'utf-8')); - -if (envInfo.env) { - resourcesPath = path.join(envInfo.path, './settings.ini'); - settings = ini.parse(fs.readFileSync(resourcesPath, 'utf-8')); -} - document.body.querySelector('#primaryVoice').addEventListener('change', () => { - var select = document.querySelector("#primaryVoice"); - settings.TTS.PRIMARY_TTS_VOICE = select.selectedIndex; - settings.TTS.PRIMARY_TTS_NAME = select.options[select.selectedIndex].text; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + var select = document.querySelector('#primaryVoice'); + settings.TTS.PRIMARY_TTS_VOICE = select.selectedIndex; + settings.TTS.PRIMARY_TTS_NAME = select.options[select.selectedIndex].text; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved primary voice!', 'success'); }); document.body.querySelector('#primaryLanguage').addEventListener('change', () => { - var select = document.querySelector("#primaryLanguage"); - settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX = select.selectedIndex; - settings.TTS.PRIMARY_TTS_LANGUAGE = select.options[select.selectedIndex].text; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + var select = document.querySelector('#primaryLanguage'); + settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX = select.selectedIndex; + settings.TTS.PRIMARY_TTS_LANGUAGE = select.options[select.selectedIndex].text; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved primary language!', 'success'); }); document.body.querySelector('#secondaryVoice').addEventListener('change', () => { - var select = document.querySelector("#secondaryVoice"); - settings.TTS.SECONDARY_TTS_VOICE = select.selectedIndex; - settings.TTS.SECONDARY_TTS_NAME = select.options[select.selectedIndex].text; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + var select = document.querySelector('#secondaryVoice'); + settings.TTS.SECONDARY_TTS_VOICE = select.selectedIndex; + settings.TTS.SECONDARY_TTS_NAME = select.options[select.selectedIndex].text; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved secondary voice!', 'success'); }); document.body.querySelector('#secondaryLanguage').addEventListener('change', () => { - var select = document.querySelector("#secondaryLanguage"); - settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX = select.selectedIndex; - settings.TTS.SECONDARY_TTS_LANGUAGE = select.options[select.selectedIndex].text; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + var select = document.querySelector('#secondaryLanguage'); + settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX = select.selectedIndex; + settings.TTS.SECONDARY_TTS_LANGUAGE = select.options[select.selectedIndex].text; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved secondary language!', 'success'); }); document.body.querySelector('#ttsAudioDevice').addEventListener('change', () => { - settings.AUDIO.TTS_AUDIO_DEVICE = ttsAudioDevices.value; - settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE = ttsAudioDevices.selectedIndex; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + settings.AUDIO.TTS_AUDIO_DEVICE = ttsAudioDevices.value; + settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE = ttsAudioDevices.selectedIndex; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved audio device!', 'success'); }); document.body.querySelector('#TWITCH_CHANNEL_NAME').addEventListener('change', () => { - settings.TWITCH.CHANNEL_NAME = document.body.querySelector('#TWITCH_CHANNEL_NAME').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); -}); + settings.TWITCH.CHANNEL_NAME = document.body.querySelector('#TWITCH_CHANNEL_NAME').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); -document.body.querySelector('#TWITCH_USERNAME').addEventListener('change', () => { - settings.TWITCH.USERNAME = document.body.querySelector('#TWITCH_USERNAME').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + let button = document.body.querySelector('#TestTwitchCredentials'); + button.className = 'AdvancedMenuButton'; + createNotification('Saved Channel name, please restart the application to reset twitch service', 'warning'); }); document.body.querySelector('#TWITCH_OAUTH_TOKEN').addEventListener('change', () => { - settings.TWITCH.OAUTH_TOKEN = document.body.querySelector('#TWITCH_OAUTH_TOKEN').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); -}); + settings.TWITCH.OAUTH_TOKEN = document.body.querySelector('#TWITCH_OAUTH_TOKEN').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved OAuth token!', 'success'); -document.body.querySelector('#TWITCH_CLIENT_ID').addEventListener('change', () => { - settings.TWITCH.CLIENT_ID = document.body.querySelector('#TWITCH_CLIENT_ID').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); -}); - -document.body.querySelector('#TWITCH_CLIENT_SECRET').addEventListener('change', () => { - settings.TWITCH.CLIENT_SECRET = document.body.querySelector('#TWITCH_CLIENT_SECRET').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + let button = document.body.querySelector('#TestTwitchCredentials'); + button.className = 'AdvancedMenuButton'; + createNotification('Saved OAuth token, please restart the application to reset twitch service', 'warning'); }); document.body.querySelector('#PORT').addEventListener('change', () => { - settings.SERVER.PORT = document.body.querySelector('#PORT').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + settings.SERVER.PORT = document.body.querySelector('#PORT').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved port, please restart the application to reset the port', 'warning'); }); document.body.querySelector('#AMAZON_ACCESS_KEY').addEventListener('change', () => { - settings.AMAZON.ACCESS_KEY = document.body.querySelector('#AMAZON_ACCESS_KEY').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + settings.AMAZON.ACCESS_KEY = document.body.querySelector('#AMAZON_ACCESS_KEY').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Amazon access key!', 'success'); }); document.body.querySelector('#AMAZON_ACCESS_SECRET').addEventListener('change', () => { - settings.AMAZON.ACCESS_SECRET = document.body.querySelector('#AMAZON_ACCESS_SECRET').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + settings.AMAZON.ACCESS_SECRET = document.body.querySelector('#AMAZON_ACCESS_SECRET').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Amazon access secret!', 'success'); }); document.body.querySelector('#GOOGLE_API_KEY').addEventListener('change', () => { - settings.GOOGLE.API_KEY = document.body.querySelector('#GOOGLE_API_KEY').value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + settings.GOOGLE.API_KEY = document.body.querySelector('#GOOGLE_API_KEY').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved Google api key!', 'success'); }); -// document.body.querySelector('#sliderX').addEventListener('change', () => { -// // TODO: resolve volume control of TTS -// config.SETTINGS.VOICE_VOLUME; -// fs.writeFileSync(path.join(__dirname, '/public/config/settings.ini'), ini.stringify(config)); -// }); - -// #region Test/change/Save Configuration document.body.querySelector('#notification').addEventListener('change', () => { - settings.AUDIO.NOTIFICATION_SOUND = notificationSound.selectedIndex; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + settings.AUDIO.NOTIFICATION_SOUND = notificationSound.selectedIndex; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + createNotification('Saved notification sound!', 'success'); }); -// document.body.querySelector('#slider').addEventListener('change', () => { -// settings.SETTINGS.NOTIFICATION_VOLUME = parseInt(document.getElementById('SoundVolume'). -// innerText); -// fs.writeFileSync(path.join(__dirname, '/public/config/settings.ini'), ini.stringify(settings)); -// }); - function getGeneralSettings() { - // Theme - document.querySelector('#USE_CUSTOM_THEME').value = settings.THEME.USE_CUSTOM_THEME; - const USE_CUSTOM_THEME = settings.THEME.USE_CUSTOM_THEME; + // Theme + document.querySelector('#USE_CUSTOM_THEME').value = settings.THEME.USE_CUSTOM_THEME; + document.body.querySelector('#USE_CUSTOM_THEME').checked = settings.THEME.USE_CUSTOM_THEME === true ? 1 : 0; + theme.setTheme(); - document.body.querySelector('#USE_CUSTOM_THEME').checked = settings.THEME.USE_CUSTOM_THEME === true ? 1 : 0; - theme.setTheme(USE_CUSTOM_THEME); + // TTS + document.body.querySelector('#USE_TTS').checked = settings.TTS.USE_TTS; - // Twitch - document.body.querySelector('#USE_TWITCH').checked = settings.TWITCH.USE_TWITCH; - document.body.querySelector('#TWITCH_CHANNEL_NAME').value = settings.TWITCH.CHANNEL_NAME; - document.body.querySelector('#TWITCH_USERNAME').value = settings.TWITCH.USERNAME; - document.body.querySelector('#TWITCH_OAUTH_TOKEN').value = settings.TWITCH.OAUTH_TOKEN; - document.body.querySelector('#TWITCH_CLIENT_ID').value = settings.TWITCH.CLIENT_ID; - document.body.querySelector('#TWITCH_CLIENT_SECRET').value = settings.TWITCH.CLIENT_SECRET; + // Notification sounds + document.body.querySelector('#USE_NOTIFICATION_SOUNDS').checked = settings.AUDIO.USE_NOTIFICATION_SOUNDS; - // Server - document.body.querySelector('#USE_SERVER').checked = settings.SERVER.USE_SERVER; - document.body.querySelector('#PORT').value = settings.SERVER.PORT; - document.body.querySelector('#USE_VTUBER').checked = settings.SERVER.USE_VTUBER; - showMenuButton("#btnBrowsersourceVtuber", settings.SERVER.USE_VTUBER) - document.body.querySelector('#USE_CHATBUBBLE').checked = settings.SERVER.USE_CHATBUBBLE; - showMenuButton("#btnBrowsersourceChat", settings.SERVER.USE_CHATBUBBLE) + // Twitch + document.body.querySelector('#USE_TWITCH').checked = settings.TWITCH.USE_TWITCH; + document.body.querySelector('#TWITCH_CHANNEL_NAME').value = settings.TWITCH.CHANNEL_NAME; + document.body.querySelector('#TWITCH_OAUTH_TOKEN').value = settings.TWITCH.OAUTH_TOKEN; - // Amazon - document.body.querySelector('#USE_AMAZON').checked = settings.AMAZON.USE_AMAZON; - document.body.querySelector('#AMAZON_ACCESS_KEY').value = settings.AMAZON.ACCESS_KEY; - document.body.querySelector('#AMAZON_ACCESS_SECRET').value = settings.AMAZON.ACCESS_SECRET; + // Server + document.body.querySelector('#USE_SERVER').checked = settings.SERVER.USE_SERVER; + document.body.querySelector('#PORT').value = settings.SERVER.PORT; + document.body.querySelector('#USE_VTUBER').checked = settings.SERVER.USE_VTUBER; + document.body.querySelector('#VTUBER_URL').value = `http://localhost:${settings.SERVER.PORT}/vtuber/`; + showMenuButton('#btnBrowsersourceVtuber', settings.SERVER.USE_VTUBER); + document.body.querySelector('#USE_CHATBUBBLE').checked = settings.SERVER.USE_CHATBUBBLE; + document.body.querySelector('#CHATBUBBLE_URL').value = `http://localhost:${settings.SERVER.PORT}/chat/`; + showMenuButton('#btnBrowsersourceChat', settings.SERVER.USE_CHATBUBBLE); - // Google - document.body.querySelector('#USE_GOOGLE').checked = settings.GOOGLE.USE_GOOGLE; - document.body.querySelector('#GOOGLE_API_KEY').value = settings.GOOGLE.API_KEY; + // Amazon + document.body.querySelector('#USE_AMAZON').checked = settings.AMAZON.USE_AMAZON; + document.body.querySelector('#AMAZON_ACCESS_KEY').value = settings.AMAZON.ACCESS_KEY; + document.body.querySelector('#AMAZON_ACCESS_SECRET').value = settings.AMAZON.ACCESS_SECRET; + // Google + document.body.querySelector('#USE_GOOGLE').checked = settings.GOOGLE.USE_GOOGLE; + document.body.querySelector('#GOOGLE_API_KEY').value = settings.GOOGLE.API_KEY; } function showMenuButton(menuButton, toggle) { - let option = document.body.querySelector(menuButton); - if (!toggle) { - option.style.display = "none"; - } else { - option.style.display = ""; - } + let option = document.body.querySelector(menuButton); + if (!toggle) { + option.style.display = 'none'; + } else { + option.style.display = ''; + } } const notificationToasts = document.querySelector('#toasts'); // toast messages function createNotification(message = null, type = null) { - const notification = document.createElement('div'); - notification.classList.add('toast'); - notification.classList.add(type); - notification.innerText = message; - notificationToasts.appendChild(notification); - let notfication = undefined; + const notification = document.createElement('div'); + notification.classList.add('toast'); + notification.classList.add(type); + notification.innerText = message; + notificationToasts.appendChild(notification); - let alertSound = "info.mp3"; - if (type === "error") { - alertSound = "error.mp3"; - } + let alertSound = 'info.mp3'; + if (type === 'error') { + alertSound = 'error.mp3'; + } - if (envInfo.env) { - notfication = new Audio(path.join(envInfo.path, `./sounds/notifications/${alertSound}`)); - } else { - notfication = new Audio(path.join(__dirname, `../sounds/notifications/${alertSound}`)); - } - notfication.play(); - setTimeout(() => notification.remove(), 10000); + let notfication = new Audio(path.join(resourcesPath, `./sounds/notifications/${alertSound}`)); + notfication.volume = settings.AUDIO.NOTIFICATION_VOLUME / 100; + notfication.play(); + setTimeout(() => notification.remove(), 10000); } // Check for configs if (!settings.TWITCH.USE_TWITCH) { - const text = 'Please setup a service to connect to in Configuration > Show Advanced'; - createNotification(text, 'warning'); + const text = 'Please setup a service to connect to in Configuration > Show Advanced'; + createNotification(text, 'warning'); } if (settings.TWITCH.USE_TWITCH && !settings.TWITCH.CHANNEL_NAME) { - const text = 'No channel name inserted in the Twitch service'; - createNotification(text, 'alert'); + const text = 'No channel name inserted in the Twitch service'; + createNotification(text, 'warning'); } if (settings.TWITCH.USE_TWITCH && !settings.TWITCH.USERNAME) { - const text = 'No username inserted in the Twitch service'; - createNotification(text, 'alert'); + const text = 'No username inserted in the Twitch service'; + createNotification(text, 'warning'); } function toggleRadio(toggle, inputs) { - const element = inputs; - if (toggle === true) { - for (let i = 0; i < inputs.length; i += 1) { element[i].disabled = false; } - } else { - for (let i = 0; i < inputs.length; i += 1) { element[i].disabled = true; } - } -} - -function setCustomThemeToggle() { - const toggle = document.getElementById('USE_CUSTOM_THEME').checked; - const inputs = document.getElementsByClassName('inputTheme'); - toggleRadio(toggle, inputs); - theme.setTheme(toggle); + const element = inputs; + if (toggle === true) { + for (let i = 0; i < inputs.length; i += 1) { + element[i].style.display = ''; + } + } else { + for (let i = 0; i < inputs.length; i += 1) { + element[i].style.display = 'none'; + } + } } // #region Use Custom theme toggle logic document.body.querySelector('#USE_CUSTOM_THEME').addEventListener('click', () => { - setCustomThemeToggle(); + const toggle = document.getElementById('USE_CUSTOM_THEME').checked; + const inputs = document.getElementsByClassName('inputTheme'); + toggleRadio(toggle, inputs); - const toggle = document.getElementById('USE_CUSTOM_THEME').checked; - settings.THEME.USE_CUSTOM_THEME = toggle; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); + settings.THEME.USE_CUSTOM_THEME = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + theme.setTheme(); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} custom theme!`, 'success'); }); // #region Top bar buttons document.body.querySelector('#min-button').addEventListener('click', () => { - ipcRenderer.send('minimize-window'); + ipcRenderer.send('minimize-window'); +}); + +// #region Top bar buttons +document.body.querySelector('#Info_USERNAME').addEventListener('click', () => { + const key = ipcRenderer.sendSync('twitch'); + + let element = document.body.querySelector('#TWITCH_OAUTH_TOKEN'); + element.value = key; +}); + +document.body.querySelector('#Info_VTUBER').addEventListener('click', () => { + ipcRenderer.send('vtuber'); +}); + +document.body.querySelector('#Info_CHATBUBBLE').addEventListener('click', () => { + ipcRenderer.send('chatBubble'); }); document.body.querySelector('#max-button').addEventListener('click', () => { - ipcRenderer.send('maximize-window'); + ipcRenderer.send('maximize-window'); }); document.body.querySelector('#close-button').addEventListener('click', (event) => { - ipcRenderer.send('close-window'); + ipcRenderer.send('close-window'); }); + // #endregion // #region Notification sound test document.body.querySelector('#SoundTestButton').addEventListener('click', () => { - sound.playAudio(); + sound.playAudio(); +}); + +document.body.querySelector('#TestTwitchCredentials').addEventListener('click', () => { + twitch.ping('#TestTwitchCredentials'); + // resetTwitch(; }); function toggleTwitch() { - const toggle = settings.TWITCH.USE_TWITCH; - const inputs = document.getElementsByClassName('inputTwitch'); - toggleRadio(toggle, inputs); + const toggle = settings.TWITCH.USE_TWITCH; + const inputs = document.getElementsByClassName('inputTwitch'); + toggleRadio(toggle, inputs); } -document.body.querySelector('#USE_TWITCH').addEventListener('click', () => { - const toggle = document.getElementById('USE_TWITCH').checked; - settings.TWITCH.USE_TWITCH = toggle; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputTwitch'); - toggleRadio(toggle, inputs); -}); - toggleTwitch(); -function toggleGoogle() { - const toggle = settings.GOOGLE.USE_GOOGLE; - const inputs = document.getElementsByClassName('inputGoogle'); - toggleRadio(toggle, inputs); -} - -document.body.querySelector('#USE_GOOGLE').addEventListener('click', () => { - const toggle = document.getElementById('USE_GOOGLE').checked; - settings.GOOGLE.USE_GOOGLE = toggle; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputGoogle'); - toggleRadio(toggle, inputs); +document.body.querySelector('#USE_TWITCH').addEventListener('click', () => { + const toggle = document.getElementById('USE_TWITCH').checked; + settings.TWITCH.USE_TWITCH = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputTwitch'); + toggleRadio(toggle, inputs); + twitch = settings.TWITCH.USE_TWITCH ? require(path.join(resourcesPath, './js/twitch')) : null; + createNotification(`${toggle ? 'Enabled' : 'Disabled'} Twitch settings!`, 'success'); }); +function toggleGoogle() { + const toggle = settings.GOOGLE.USE_GOOGLE; + const inputs = document.getElementsByClassName('inputGoogle'); + toggleRadio(toggle, inputs); +} + toggleGoogle(); -function toggleAmazon() { - const toggle = settings.AMAZON.USE_AMAZON; - const inputs = document.getElementsByClassName('inputAmazon'); - toggleRadio(toggle, inputs); -} - -document.body.querySelector('#USE_AMAZON').addEventListener('click', () => { - const toggle = document.getElementById('USE_AMAZON').checked; - settings.AMAZON.USE_AMAZON = toggle; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputAmazon'); - toggleRadio(toggle, inputs); +document.body.querySelector('#USE_GOOGLE').addEventListener('click', () => { + const toggle = document.getElementById('USE_GOOGLE').checked; + settings.GOOGLE.USE_GOOGLE = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputGoogle'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} Google settings!`, 'success'); }); +function toggleAmazon() { + const toggle = settings.AMAZON.USE_AMAZON; + const inputs = document.getElementsByClassName('inputAmazon'); + toggleRadio(toggle, inputs); +} + toggleAmazon(); -function toggleServer() { - const toggle = settings.SERVER.USE_SERVER; - const inputs = document.getElementsByClassName('inputServer'); - toggleRadio(toggle, inputs); -} - -document.body.querySelector('#USE_SERVER').addEventListener('click', () => { - const toggle = document.getElementById('USE_SERVER').checked; - settings.SERVER.USE_SERVER = toggle; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - const inputs = document.getElementsByClassName('inputServer'); - toggleRadio(toggle, inputs); +document.body.querySelector('#USE_AMAZON').addEventListener('click', () => { + const toggle = document.getElementById('USE_AMAZON').checked; + settings.AMAZON.USE_AMAZON = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputAmazon'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} Amazon settings!`, 'success'); }); +function toggleServer() { + const toggle = settings.SERVER.USE_SERVER; + const inputs = document.getElementsByClassName('inputServer'); + toggleRadio(toggle, inputs); +} + toggleServer(); +document.body.querySelector('#USE_SERVER').addEventListener('click', () => { + const toggle = document.getElementById('USE_SERVER').checked; + settings.SERVER.USE_SERVER = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputServer'); + toggleRadio(toggle, inputs); + setServer(); + createNotification( + `${toggle ? 'Enabled' : 'Disabled'} server settings!, the service will stop working after restarting the application`, + 'success', + ); +}); + document.body.querySelector('#USE_VTUBER').addEventListener('change', () => { - const toggle = document.getElementById('USE_VTUBER').checked; - settings.SERVER.USE_VTUBER = toggle; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - showMenuButton("#btnBrowsersourceVtuber", toggle); + const toggle = document.getElementById('USE_VTUBER').checked; + settings.SERVER.USE_VTUBER = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + showMenuButton('#btnBrowsersourceVtuber', toggle); + createNotification( + `${toggle ? 'Enabled' : 'Disabled'} Vtuber setting!, the service will stop working after restarting the application`, + 'success', + ); + server.startVtuber(); }); document.body.querySelector('#USE_CHATBUBBLE').addEventListener('change', () => { - const toggle = document.getElementById('USE_CHATBUBBLE').checked; - settings.SERVER.USE_CHATBUBBLE = toggle; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - showMenuButton("#btnBrowsersourceChat", toggle); + const toggle = document.getElementById('USE_CHATBUBBLE').checked; + settings.SERVER.USE_CHATBUBBLE = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + showMenuButton('#btnBrowsersourceChat', toggle); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} chatbubble setting!`, 'success'); + server.startChatBubble(); }); -// Get the selected TTS -const currentlySelectedTTS = ttsSelector.querySelector(`#${settings.TTS.SELECTED_TTS}`); - -if (currentlySelectedTTS) { - currentlySelectedTTS.checked = true; - - // Dispatch the event to initialize logic. - currentlySelectedTTS.dispatchEvent(new Event('change')); +function toggleTTS() { + const toggle = settings.TTS.USE_TTS; + const inputs = document.getElementsByClassName('inputTTS'); + toggleRadio(toggle, inputs); } -document.body.querySelector('#notificationVolumeSlider').addEventListener('change', () => { - const e = document.querySelector('#notificationVolumeSlider'); - e.style.setProperty('--tiempotemporal', e.value); - e.style.setProperty('--min', e.min === '' ? '0' : e.min); - e.style.setProperty('--max', e.max === '' ? '100' : e.max); - document.querySelector('#notificationVolume').value = e.value; +toggleTTS(); - e.addEventListener('input', () => { - e.style.setProperty('--tiempotemporal', e.value); - document.querySelector('#notificationVolume').value = e.value; - settings.AUDIO.NOTIFICATION_VOLUME = e.value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - }); +document.body.querySelector('#USE_TTS').addEventListener('change', () => { + const toggle = document.getElementById('USE_TTS').checked; + settings.TTS.USE_TTS = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputTTS'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} text to speech!`, 'success'); +}); + +function toggleNotificationSounds() { + const toggle = settings.AUDIO.USE_NOTIFICATION_SOUNDS; + const inputs = document.getElementsByClassName('inputNotificationSound'); + toggleRadio(toggle, inputs); +} + +toggleNotificationSounds(); + +document.body.querySelector('#USE_NOTIFICATION_SOUNDS').addEventListener('change', () => { + const toggle = document.getElementById('USE_NOTIFICATION_SOUNDS').checked; + settings.AUDIO.USE_NOTIFICATION_SOUNDS = toggle; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + const inputs = document.getElementsByClassName('inputNotificationSound'); + toggleRadio(toggle, inputs); + createNotification(`${toggle ? 'Enabled' : 'Disabled'} notification sounds!`, 'success'); +}); + +document.body.querySelector('#notificationVolume').addEventListener('change', () => { + let element = document.body.querySelector('#notificationVolume'); + settings.AUDIO.NOTIFICATION_VOLUME = element.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + + const slider = document.querySelector('#notificationVolumeSlider'); + slider.value = settings.AUDIO.NOTIFICATION_VOLUME; + slider.style.setProperty('--tiempotemporal', settings.AUDIO.NOTIFICATION_VOLUME); + + createNotification('Saved notification volume!', 'success'); +}); + +document.body.querySelector('#notificationVolumeSlider').addEventListener('change', () => { + const e = document.querySelector('#notificationVolumeSlider'); + e.style.setProperty('--tiempotemporal', e.value); + e.style.setProperty('--min', e.min === '' ? '0' : e.min); + e.style.setProperty('--max', e.max === '' ? '100' : e.max); + document.querySelector('#notificationVolume').value = e.value; + + e.addEventListener('input', () => { + e.style.setProperty('--tiempotemporal', e.value); + document.querySelector('#notificationVolume').value = e.value; + settings.AUDIO.NOTIFICATION_VOLUME = e.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + }); +}); + +document.body.querySelector('#notificationVolumeSlider').addEventListener('mouseup', () => { + createNotification('Saved notification volume!', 'success'); }); if (settings.AUDIO.NOTIFICATION_VOLUME) { - document.querySelector('#notificationVolumeSlider').value = settings.AUDIO.NOTIFICATION_VOLUME; - document.querySelector('#notificationVolumeSlider').dispatchEvent(new Event('change')); + document.querySelector('#notificationVolumeSlider').value = settings.AUDIO.NOTIFICATION_VOLUME; + document.querySelector('#notificationVolumeSlider').dispatchEvent(new Event('change')); } else { - document.querySelector('#notificationVolumeSlider').dispatchEvent(new Event('change', { value: 50 })); + document.querySelector('#notificationVolumeSlider').dispatchEvent(new Event('change', { value: 50 })); } -document.body.querySelector('#ttsVolumeSlider').addEventListener('change', () => { - const e = document.querySelector('#ttsVolumeSlider'); - e.style.setProperty('--tiempotemporal', e.value); - e.style.setProperty('--min', e.min === '' ? '0' : e.min); - e.style.setProperty('--max', e.max === '' ? '100' : e.max); - document.querySelector('#ttsVolume').value = e.value; +document.body.querySelector('#ttsVolume').addEventListener('change', () => { + let element = document.body.querySelector('#ttsVolume'); + settings.TTS.TTS_VOLUME = element.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); - e.addEventListener('input', () => { - e.style.setProperty('--tiempotemporal', e.value); - document.querySelector('#ttsVolume').value = e.value; - settings.AUDIO.TTS_VOLUME = e.value; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - }); + const slider = document.querySelector('#ttsVolumeSlider'); + slider.value = settings.TTS.TTS_VOLUME; + slider.style.setProperty('--tiempotemporal', settings.TTS.TTS_VOLUME); + + createNotification('Saved TTS volume!', 'success'); }); -if (settings.AUDIO.TTS_VOLUME) { - document.querySelector('#ttsVolumeSlider').value = settings.AUDIO.TTS_VOLUME; - document.querySelector('#ttsVolumeSlider').dispatchEvent(new Event('change')); +document.body.querySelector('#ttsVolumeSlider').addEventListener('change', () => { + const e = document.querySelector('#ttsVolumeSlider'); + e.style.setProperty('--tiempotemporal', e.value); + e.style.setProperty('--min', e.min === '' ? '0' : e.min); + e.style.setProperty('--max', e.max === '' ? '100' : e.max); + document.querySelector('#ttsVolume').value = e.value; + + e.addEventListener('input', () => { + e.style.setProperty('--tiempotemporal', e.value); + document.querySelector('#ttsVolume').value = e.value; + settings.TTS.TTS_VOLUME = e.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + }); +}); + +document.body.querySelector('#ttsVolumeSlider').addEventListener('mouseup', () => { + createNotification('Saved TTS volume!', 'success'); +}); + +if (settings.TTS.TTS_VOLUME) { + document.querySelector('#ttsVolumeSlider').value = settings.TTS.TTS_VOLUME; + document.querySelector('#ttsVolumeSlider').dispatchEvent(new Event('change')); } else { - document.querySelector('#ttsVolumeSlider').dispatchEvent(new Event('change', { value: 50 })); + document.querySelector('#ttsVolumeSlider').dispatchEvent(new Event('change', { value: 50 })); } +document.body.querySelector('#ttsVolume').addEventListener('change', () => { + let element = document.body.querySelector('#ttsVolume'); + settings.TTS.TTS_VOLUME = element.value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + + const slider = document.querySelector('#ttsVolumeSlider'); + slider.value = settings.TTS.TTS_VOLUME; + slider.style.setProperty('--tiempotemporal', settings.TTS.TTS_VOLUME); +}); + document.body.querySelector('.language-selector').addEventListener('click', () => { - var dropdown = document.body.querySelector('.language-dropdown'); - dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block'; + var dropdown = document.body.querySelector('.language-dropdown'); + dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block'; }); document.body.querySelector('.language-dropdown').addEventListener('mouseleave', () => { - hideDropdown(); + hideDropdown(); }); -let languageSelector = document.querySelectorAll(".language-item"); -languageSelector.forEach(item => { - item.addEventListener('click', (event) => { - const el = event.target; - // tip.innerText = el.getAttribute('language'); - document.getElementById('selected-language').innerText = el.getAttribute('language'); - document.getElementById('selected-flag').innerText = el.getAttribute('flag'); - hideDropdown(); - }); +let languageSelector = document.querySelectorAll('.language-item'); +languageSelector.forEach((item) => { + item.addEventListener('click', (event) => { + const el = event.target; + // tip.innerText = el.getAttribute('language'); + document.getElementById('selected-language').innerText = el.getAttribute('language'); + document.getElementById('selected-flag').innerText = el.getAttribute('flag'); + hideDropdown(); + }); }); function hideDropdown() { - var dropdown = document.body.querySelector('.language-dropdown'); - dropdown.style.display = 'none'; + var dropdown = document.body.querySelector('.language-dropdown'); + dropdown.style.display = 'none'; } - // let primaryTTSSelector = document.body.querySelector(".optgroup"); // primaryTTSSelector.forEach(item => { // item.addEventListener('hover', (event) => { @@ -398,10 +482,6 @@ function hideDropdown() { // }); // }); - module.exports = { - ini, - settings, - getGeneralSettings, - setCustomThemeToggle + getGeneralSettings, }; diff --git a/src/js/sound.js b/src/js/sound.js index bf4ecc2..9f5e18c 100644 --- a/src/js/sound.js +++ b/src/js/sound.js @@ -4,26 +4,33 @@ let currentUsername = ''; let voiceSoundArray = []; let status = 0; -const playTTS = (ttsData) => new Promise((resolve) => { - const tts = new Audio(ttsData.path); +const playTTS = (ttsData) => + new Promise((resolve) => { + const tts = new Audio(ttsData.path); - tts.addEventListener('ended', () => { - fs.unlink(ttsData.path, (err) => { - if (err) { - console.error(err); - return; - } - resolve('finished'); + tts.addEventListener('ended', () => { + fs.unlink(ttsData.path, (err) => { + if (err) { + console.error(err); + return; + } + resolve('finished'); + }); }); - }); - tts.setSinkId(config.settings.AUDIO.TTS_AUDIO_DEVICE).then(() => { - tts.play(); - socket.emit('xxx', currentLogoUrl, currentUsername, ttsData.message); - }).catch((error) => { - console.error('Failed to set audio output device:', error); + tts.setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE) + .then(() => { + tts.volume = settings.TTS.TTS_VOLUME / 100; + tts.play(); + + if (settings.SERVER.USE_SERVER) { + socket.emit('xxx', currentLogoUrl, currentUsername, ttsData.message); + } + }) + .catch((error) => { + console.error('Failed to set audio output device:', error); + }); }); -}); async function shiftVoice() { status = 1; @@ -41,18 +48,19 @@ function add(ttsData) { } // Play sound function -function playAudio(ttsData = undefined) { - let audioPath; - if (!ttsData) { - let notfication = undefined; - if (envInfo.env) { - notfication = new Audio(path.join(envInfo.path, `./sounds/notifications/${notificationSound.options[config.settings.AUDIO.NOTIFICATION_SOUND].text}`)); - } else { - notfication = new Audio(path.join(__dirname, `../sounds/notifications/${notificationSound.options[config.settings.AUDIO.NOTIFICATION_SOUND].text}`)); - } +function playAudio(data) { + if (settings.AUDIO.USE_NOTIFICATION_SOUNDS) { + let notfication = new Audio( + path.join(resourcesPath, `../src/sounds/notifications/${notificationSound.options[settings.AUDIO.NOTIFICATION_SOUND].text}`), + ); + notfication.volume = settings.AUDIO.NOTIFICATION_VOLUME / 100; notfication.play(); - } else { - add(ttsData); + } + + if (settings.TTS.USE_TTS) { + add(data); + } else if (settings.SERVER.USE_SERVER) { + socket.emit('xxx', currentLogoUrl, currentUsername, data); } } @@ -60,19 +68,26 @@ function playVoice(filteredMessage, logoUrl, username, message) { trueMessage = filteredMessage; currentLogoUrl = logoUrl; currentUsername = username; - let textObject = { "filtered": filteredMessage, "formatted": message }; + let textObject = { filtered: filteredMessage, formatted: message }; let voice; const language = langdetect.detect(filteredMessage); - if (language[0].lang === config.settings.TTS.SECONDARY_TTS_LANGUAGE.toLowerCase()) { - voice = config.settings.TTS.SECONDARY_TTS_NAME; + if ( + settings.TTS.PRIMARY_TTS_LANGUAGE.toLowerCase() !== settings.TTS.SECONDARY_TTS_LANGUAGE.toLowerCase() || + language[0].lang === settings.TTS.SECONDARY_TTS_LANGUAGE.toLowerCase() + ) { + voice = settings.TTS.SECONDARY_TTS_NAME; textObject.filtered = `${username}: ${filteredMessage}`; } else { - voice = config.settings.TTS.PRIMARY_TTS_NAME; + voice = settings.TTS.PRIMARY_TTS_NAME; textObject.filtered = `${username}: ${filteredMessage}`; } - talk.add(textObject, voice); + if (settings.TTS.USE_TTS) { + talk.add(textObject, voice); + } else { + playAudio(textObject); + } } module.exports = { playAudio, playVoice }; diff --git a/src/js/theme.js b/src/js/theme.js index 77e7601..68e8519 100644 --- a/src/js/theme.js +++ b/src/js/theme.js @@ -1,89 +1,49 @@ -function setTheme(USE_CUSTOM_THEME) { - document.querySelector('#MAIN_COLOR_1').value = config.settings.THEME.MAIN_COLOR_1; - const MAIN_COLOR_1 = document.querySelector('#MAIN_COLOR_1').value; - root.style.setProperty('--main-color1-temp', MAIN_COLOR_1); - - document.querySelector('#MAIN_COLOR_2').value = config.settings.THEME.MAIN_COLOR_2; - const MAIN_COLOR_2 = document.querySelector('#MAIN_COLOR_2').value; - root.style.setProperty('--main-color2-temp', MAIN_COLOR_2); - - document.querySelector('#MAIN_COLOR_3').value = config.settings.THEME.MAIN_COLOR_3; - const MAIN_COLOR_3 = document.querySelector('#MAIN_COLOR_3').value; - root.style.setProperty('--main-color3-temp', MAIN_COLOR_3); - - document.querySelector('#MAIN_COLOR_4').value = config.settings.THEME.MAIN_COLOR_4; - const MAIN_COLOR_4 = document.querySelector('#MAIN_COLOR_4').value; - root.style.setProperty('--main-color4-temp', MAIN_COLOR_4); - - document.querySelector('#TOP_BAR').value = config.settings.THEME.TOP_BAR; - const TOP_BAR = document.querySelector('#TOP_BAR').value; - root.style.setProperty('--top-bar-temp', TOP_BAR); - - document.querySelector('#MID_SECTION').value = config.settings.THEME.MID_SECTION; - const MID_SECTION = document.querySelector('#MID_SECTION').value; - root.style.setProperty('--mid-section-temp', MID_SECTION); - - document.querySelector('#CHAT_BUBBLE_BG').value = config.settings.THEME.CHAT_BUBBLE_BG; - const CHAT_BUBBLE_BG = document.querySelector('#CHAT_BUBBLE_BG').value; - root.style.setProperty('--chat-bubble-temp', CHAT_BUBBLE_BG); - - document.querySelector('#CHAT_BUBBLE_HEADER').value = config.settings.THEME.CHAT_BUBBLE_HEADER; - const CHAT_BUBBLE_HEADER = document.querySelector('#CHAT_BUBBLE_HEADER').value; - root.style.setProperty('--chat-bubble-header-temp', CHAT_BUBBLE_HEADER); - - document.querySelector('#CHAT_BUBBLE_MESSAGE').value = config.settings.THEME.CHAT_BUBBLE_MESSAGE; - const CHAT_BUBBLE_MESSAGE = document.querySelector('#CHAT_BUBBLE_MESSAGE').value; - root.style.setProperty('--chat-bubble-message-temp', CHAT_BUBBLE_MESSAGE); - - if (USE_CUSTOM_THEME) { - root.style.setProperty('--main-color1', MAIN_COLOR_1); - - root.style.setProperty('--main-color2', MAIN_COLOR_2); - - root.style.setProperty('--main-color3', MAIN_COLOR_3); - - root.style.setProperty('--main-color4', MAIN_COLOR_4); - - root.style.setProperty('--top-bar', TOP_BAR); - - root.style.setProperty('--mid-section', MID_SECTION); - - root.style.setProperty('--chat-bubble', CHAT_BUBBLE_BG); - - root.style.setProperty('--chat-bubble-header', CHAT_BUBBLE_HEADER); - - root.style.setProperty('--chat-bubble-message', CHAT_BUBBLE_MESSAGE); - } else { - root.style.setProperty('--main-color1', '#6e2c8c'); - - root.style.setProperty('--main-color2', 'white'); - - root.style.setProperty('--main-color3', '#211E1E'); - - root.style.setProperty('--main-color4', '#2f2c34'); - - root.style.setProperty('--top-bar', '#100B12'); - - root.style.setProperty('--mid-section', '#352d3d'); - - root.style.setProperty('--chat-bubble', ' #7A6D7F'); - - root.style.setProperty('--chat-bubble-header', '#141414'); - - root.style.setProperty('--chat-bubble-message', 'white'); - } +function changeColor(section, setting, tempSection) { + document.querySelector(section).value = setting; + const value = document.querySelector(section).value; + root.style.setProperty(tempSection, value); +} + +function setCurrentTheme(adjustTemp = false) { + changeColor("#MAIN_COLOR_1", settings.THEME.MAIN_COLOR_1, adjustTemp ? "--main-color1-temp" : "--main-color1"); + changeColor("#MAIN_COLOR_2", settings.THEME.MAIN_COLOR_2, adjustTemp ? "--main-color2-temp" : "--main-color2"); + changeColor("#MAIN_COLOR_3", settings.THEME.MAIN_COLOR_3, adjustTemp ? "--main-color3-temp" : "--main-color3"); + changeColor("#MAIN_COLOR_4", settings.THEME.MAIN_COLOR_4, adjustTemp ? "--main-color4-temp" : "--main-color4"); + changeColor("#TOP_BAR", settings.THEME.TOP_BAR, adjustTemp ? "--top-bar-temp" : "--top-bar"); + changeColor("#MID_SECTION", settings.THEME.MID_SECTION, adjustTemp ? "--mid-section-temp" : "--mid-section"); + changeColor("#CHAT_BUBBLE_BG", settings.THEME.CHAT_BUBBLE_BG, adjustTemp ? "--chat-bubble-temp" : "--chat-bubble"); + changeColor("#CHAT_BUBBLE_HEADER", settings.THEME.CHAT_BUBBLE_HEADER, adjustTemp ? "--chat-bubble-header-temp" : "--chat-bubble-header"); + changeColor("#CHAT_BUBBLE_MESSAGE", settings.THEME.CHAT_BUBBLE_MESSAGE, adjustTemp ? "--chat-bubble-message-temp" : "--chat-bubble-message"); +} + +setCurrentTheme(true); + +function setTheme() { + if (settings.THEME.USE_CUSTOM_THEME) { + setCurrentTheme(); + } else { + root.style.setProperty('--main-color1', '#6e2c8c'); + root.style.setProperty('--main-color2', 'white'); + root.style.setProperty('--main-color3', '#211E1E'); + root.style.setProperty('--main-color4', '#2f2c34'); + root.style.setProperty('--top-bar', '#100B12'); + root.style.setProperty('--mid-section', '#352d3d'); + root.style.setProperty('--chat-bubble', ' #7A6D7F'); + root.style.setProperty('--chat-bubble-header', '#141414'); + root.style.setProperty('--chat-bubble-message', 'white'); + }; } -// #region Save Theme document.body.querySelector('#MAIN_COLOR_1').addEventListener('input', () => { const x = document.getElementById('MAIN_COLOR_1').value; root.style.setProperty('--main-color1-temp', x); + console.log(x); }); document.body.querySelector('#MAIN_COLOR_1').addEventListener('change', () => { - config.settings.THEME.MAIN_COLOR_1 = document.getElementById('MAIN_COLOR_1').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.MAIN_COLOR_1 = document.getElementById('MAIN_COLOR_1').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#MAIN_COLOR_1", settings.THEME.MAIN_COLOR_1, "--main-color1"); }); document.body.querySelector('#MAIN_COLOR_2').addEventListener('input', () => { @@ -92,9 +52,9 @@ document.body.querySelector('#MAIN_COLOR_2').addEventListener('input', () => { }); document.body.querySelector('#MAIN_COLOR_2').addEventListener('change', () => { - config.settings.THEME.MAIN_COLOR_2 = document.getElementById('MAIN_COLOR_2').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.MAIN_COLOR_2 = document.getElementById('MAIN_COLOR_2').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#MAIN_COLOR_2", settings.THEME.MAIN_COLOR_2, "--main-color2"); }); document.body.querySelector('#MAIN_COLOR_3').addEventListener('input', () => { @@ -103,9 +63,9 @@ document.body.querySelector('#MAIN_COLOR_3').addEventListener('input', () => { }); document.body.querySelector('#MAIN_COLOR_3').addEventListener('change', () => { - config.settings.THEME.MAIN_COLOR_3 = document.getElementById('MAIN_COLOR_3').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.MAIN_COLOR_3 = document.getElementById('MAIN_COLOR_3').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#MAIN_COLOR_3", settings.THEME.MAIN_COLOR_3, "--main-color3"); }); document.body.querySelector('#MAIN_COLOR_4').addEventListener('input', () => { @@ -114,9 +74,9 @@ document.body.querySelector('#MAIN_COLOR_4').addEventListener('input', () => { }); document.body.querySelector('#MAIN_COLOR_4').addEventListener('change', () => { - config.settings.THEME.MAIN_COLOR_4 = document.getElementById('MAIN_COLOR_4').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.MAIN_COLOR_4 = document.getElementById('MAIN_COLOR_4').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#MAIN_COLOR_4", settings.THEME.MAIN_COLOR_4, "--main-color4"); }); document.body.querySelector('#TOP_BAR').addEventListener('input', () => { @@ -125,9 +85,9 @@ document.body.querySelector('#TOP_BAR').addEventListener('input', () => { }); document.body.querySelector('#TOP_BAR').addEventListener('change', () => { - config.settings.THEME.TOP_BAR = document.getElementById('TOP_BAR').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.TOP_BAR = document.getElementById('TOP_BAR').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#TOP_BAR", settings.THEME.TOP_BAR, "--top-bar"); }); document.body.querySelector('#MID_SECTION').addEventListener('input', () => { @@ -136,9 +96,9 @@ document.body.querySelector('#MID_SECTION').addEventListener('input', () => { }); document.body.querySelector('#MID_SECTION').addEventListener('change', () => { - config.settings.THEME.MID_SECTION = document.getElementById('MID_SECTION').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.MID_SECTION = document.getElementById('MID_SECTION').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#MID_SECTION", settings.THEME.MID_SECTION, "--mid-section"); }); document.body.querySelector('#CHAT_BUBBLE_BG').addEventListener('input', () => { @@ -147,9 +107,9 @@ document.body.querySelector('#CHAT_BUBBLE_BG').addEventListener('input', () => { }); document.body.querySelector('#CHAT_BUBBLE_BG').addEventListener('change', () => { - config.settings.THEME.CHAT_BUBBLE_BG = document.getElementById('CHAT_BUBBLE_BG').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.CHAT_BUBBLE_BG = document.getElementById('CHAT_BUBBLE_BG').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#CHAT_BUBBLE_BG", settings.THEME.CHAT_BUBBLE_BG, "--chat-bubble"); }); document.body.querySelector('#CHAT_BUBBLE_HEADER').addEventListener('input', () => { @@ -158,9 +118,9 @@ document.body.querySelector('#CHAT_BUBBLE_HEADER').addEventListener('input', () }); document.body.querySelector('#CHAT_BUBBLE_HEADER').addEventListener('change', () => { - config.settings.THEME.CHAT_BUBBLE_HEADER = document.getElementById('CHAT_BUBBLE_HEADER').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.CHAT_BUBBLE_HEADER = document.getElementById('CHAT_BUBBLE_HEADER').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#CHAT_BUBBLE_HEADER", settings.THEME.CHAT_BUBBLE_HEADER, "--chat-bubble-header"); }); document.body.querySelector('#CHAT_BUBBLE_MESSAGE').addEventListener('input', () => { @@ -169,11 +129,9 @@ document.body.querySelector('#CHAT_BUBBLE_MESSAGE').addEventListener('input', () }); document.body.querySelector('#CHAT_BUBBLE_MESSAGE').addEventListener('change', () => { - config.settings.THEME.CHAT_BUBBLE_MESSAGE = document.getElementById('CHAT_BUBBLE_MESSAGE').value; - fs.writeFileSync(path.join(__dirname, '../config/settings.ini'), config.ini.stringify(config.settings)); - setTheme(config.settings.THEME.USE_CUSTOM_THEME); + settings.THEME.CHAT_BUBBLE_MESSAGE = document.getElementById('CHAT_BUBBLE_MESSAGE').value; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + changeColor("#CHAT_BUBBLE_MESSAGE", settings.THEME.CHAT_BUBBLE_MESSAGE, "--chat-bubble-message"); }); -// #endregion - module.exports = { setTheme }; diff --git a/src/js/twitch.js b/src/js/twitch.js index f9f0a1a..32c35c4 100644 --- a/src/js/twitch.js +++ b/src/js/twitch.js @@ -1,146 +1,151 @@ const tmi = require('tmi.js'); const axios = require('axios'); -const client = new tmi.Client({ - options: { - skipUpdatingEmotesets: true, - }, - identity: { - username: config.settings.TWITCH.USERNAME, - password: config.settings.TWITCH.OAUTH_TOKEN, - }, - channels: [config.settings.TWITCH.CHANNEL_NAME], -}); +let client; function sendMessage(message) { - client.say(config.settings.TWITCH.CHANNEL_NAME, message).catch(console.error); + client.say(settings.TWITCH.CHANNEL_NAME, message).catch(console.error); } -client.connect().catch(console.error); +client = new tmi.Client({ + options: { + skipUpdatingEmotesets: true, + }, + identity: { + username: settings.TWITCH.USERNAME, + password: settings.TWITCH.OAUTH_TOKEN, + }, + channels: [settings.TWITCH.CHANNEL_NAME], +}); + +client + .connect() + .then((data) => {}) + .catch(console.error); + +function ping(element) { + let value = document.body.querySelector(element); + + client + .ping() + .then((data) => { + console.log(client.readyState()); + console.log(data); + value.classList.add('success'); + value.innerText = 'Success!'; + }) + .catch((e) => { + console.log(e); + value.classList.add('error'); + value.innerText = 'Failed!'; + }); +} function displayTwitchMessage(logoUrl, username, messageObject, fileteredMessage) { - const article = document.createElement('article'); - article.className = 'msg-container msg-remote'; + const article = document.createElement('article'); + article.className = 'msg-container msg-remote'; - article.innerHTML = messageTemplates.twitchTemplate; + article.innerHTML = messageTemplates.twitchTemplate; - const userImg = article.querySelector('.icon-container > .user-img'); - if (userImg) { - userImg.src = logoUrl; - } + const userImg = article.querySelector('.icon-container > .user-img'); + if (userImg) { + userImg.src = logoUrl; + } - const usernameHtml = article.querySelector('.username'); - if (usernameHtml) { - usernameHtml.innerText = username; - } + const usernameHtml = article.querySelector('.username'); + if (usernameHtml) { + usernameHtml.innerText = username; + } - const postTime = article.querySelector('.post-time'); - if (postTime) { - postTime.innerText = getPostTime(); - } + const postTime = article.querySelector('.post-time'); + if (postTime) { + postTime.innerText = getPostTime(); + } - const msg = article.querySelector('.msg'); - if (msg) { - msg.innerHTML = ""; + const msg = article.querySelector('.msg'); + if (msg) { + msg.innerHTML = ''; - const messageElement = document.createElement("div"); + const messageElement = document.createElement('div'); - messageObject.forEach((entry) => { - const messageElement = document.createElement("div"); - if (entry.text) { - messageElement.innerText = entry.text; - msg.appendChild(messageElement); - } else { - messageElement.innerHTML = entry.html; - msg.appendChild(messageElement); - } - }) - } + messageObject.forEach((entry) => { + const messageElement = document.createElement('div'); + if (entry.text) { + messageElement.innerText = entry.text; + msg.appendChild(messageElement); + } else { + messageElement.innerHTML = entry.html; + msg.appendChild(messageElement); + } + }); + } - // Appends the message to the main chat box (shows the message) - showChatMessage(article); + // Appends the message to the main chat box (shows the message) + showChatMessage(article); - if (fileteredMessage) { - sound.playVoice(fileteredMessage, logoUrl, username, msg); - } + if (fileteredMessage) { + sound.playVoice(fileteredMessage, logoUrl, username, msg); + } - window.article = article; + window.article = article; } function getProfileImage(userid, username, message, fileteredMessage) { - // Get Access Token - let options = { - method: 'POST', - url: 'https://id.twitch.tv/oauth2/token', - data: { - grant_type: 'client_credentials', - client_Id: config.settings.TWITCH.CLIENT_ID, - client_Secret: config.settings.TWITCH.CLIENT_SECRET, - audience: 'YOUR_API_IDENTIFIER', - }, - }; + // Get user Logo with access token + options = { + method: 'GET', + url: `https://api.twitch.tv/helix/users?id=${userid}`, + headers: { 'Client-ID': settings.TWITCH.CLIENT_ID, Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` }, + }; - axios.request(options).then((responseAccessToken) => { - const accessToken = responseAccessToken.data.access_token; - - // Get user Logo with access token - options = { - method: 'GET', - url: `https://api.twitch.tv/helix/users?id=${userid}`, - headers: { 'Client-ID': config.settings.TWITCH.CLIENT_ID, Authorization: `Bearer ${accessToken}` }, - }; - - axios.request(options).then((responseLogoUrl) => { - const logoUrl = responseLogoUrl.data.data[0].profile_image_url; - displayTwitchMessage(logoUrl, username, message, fileteredMessage); - }).catch((error) => { - console.error(error); - }); - }).catch((error) => { - console.error(error); - }); + axios + .request(options) + .then((responseLogoUrl) => { + const logoUrl = responseLogoUrl.data.data[0].profile_image_url; + displayTwitchMessage(logoUrl, username, message, fileteredMessage); + }) + .catch((error) => { + console.error(error); + }); } function parseString(inputString) { - const regex = /()|([^<]+)/g; - const matches = inputString.match(regex) || []; - const result = []; + const regex = /()|([^<]+)/g; + const matches = inputString.match(regex) || []; + const result = []; - for (let i = 0; i < matches.length; i++) { - const match = matches[i].trim(); - if (match.startsWith(" { - if (self) { - return; - } + if (self) { + return; + } + const emotes = tags.emotes || {}; + const emoteValues = Object.entries(emotes); + let fileteredMessage = message; + let emoteMessage = message; - const emotes = tags.emotes || {}; - const emoteValues = Object.entries(emotes); - let fileteredMessage = message; - let emoteMessage = message; + emoteValues.forEach((entry) => { + entry[1].forEach((lol) => { + const [start, end] = lol.split('-'); + let emote = ``; + emoteMessage = emoteMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), emote); + fileteredMessage = fileteredMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), ''); + }); + }); - emoteValues.forEach((entry) => { - entry[1].forEach((lol) => { - const [start, end] = lol.split('-'); - let emote = ``; - emoteMessage = emoteMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), emote); - fileteredMessage = fileteredMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), ''); - }) - }); - - let messageObject = parseString(emoteMessage) - - sound.playAudio(); - getProfileImage(tags['user-id'], tags['display-name'], messageObject, fileteredMessage); + let messageObject = parseString(emoteMessage); + getProfileImage(tags['user-id'], tags['display-name'], messageObject, fileteredMessage); }); - -module.exports = { sendMessage }; +module.exports = { sendMessage, ping, client }; diff --git a/src/js/voiceQueue.js b/src/js/voiceQueue.js index c276b24..0dd9c98 100644 --- a/src/js/voiceQueue.js +++ b/src/js/voiceQueue.js @@ -2,26 +2,21 @@ let SelectedVoice = ''; let Encoding = ''; let counter = 0; // wrap in promise -const speak = (textObject) => new Promise((resolve) => { - // say.setEncoding(Encoding); - counter += 1; - let savePath = ''; +const speak = (textObject) => + new Promise((resolve) => { + // say.setEncoding(Encoding); + counter += 1; + let savePath = path.join(resourcesPath, '../src/sounds/tts/internal_audio_' + counter + '.mp3'); - if (envInfo.env) { - savePath = path.join(envInfo.path, './sounds/tts/internal_audio_' + counter + '.mp3') - } else { - savePath = path.join(__dirname, '../sounds/tts/internal_audio_' + counter + '.mp3') - } - - say.export(textObject.filtered, SelectedVoice, 1, savePath, (err) => { - if (err) { - console.error(err); - } else { - sound.playAudio({ "path": savePath, "message": textObject }); - } - resolve('finished'); + say.export(textObject.filtered, SelectedVoice, 1, savePath, (err) => { + if (err) { + console.error(err); + } else { + sound.playAudio({ path: savePath, message: textObject }); + } + resolve('finished'); + }); }); -}); // queue system class SayQueue { @@ -41,7 +36,9 @@ class SayQueue { add(message, selectedVoice) { this.messages.push(message); SelectedVoice = selectedVoice; - if (this.status === 0) { this.shift(); } + if (this.status === 0) { + this.shift(); + } } } diff --git a/src/main.js b/src/main.js index 68d132b..7353f0f 100644 --- a/src/main.js +++ b/src/main.js @@ -1,179 +1,273 @@ -const { app, BrowserWindow, ipcMain } = require('electron'); -const { writeIniFile } = require('write-ini-file') +const { app, shell, BrowserWindow, ipcMain } = require('electron'); +const writeIniFile = require('write-ini-file'); const path = require('path'); const ini = require('ini'); const fs = require('fs'); let resourcesPath; +let settingsPath; let settings; let window; if (app.isPackaged) { - resourcesPath = path.join(process.resourcesPath, './settings.ini'); + resourcesPath = process.resourcesPath; } else { - resourcesPath = path.join(__dirname, './config/settings.ini'); + resourcesPath = __dirname; } // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (require('electron-squirrel-startup')) { - app.quit(); + app.quit(); } async function createWindow() { - if (!fs.existsSync(resourcesPath)) { - await createIniFile(resourcesPath); - } else { - settings = ini.parse(fs.readFileSync(resourcesPath, 'utf-8')); - } + if (!fs.existsSync(resourcesPath)) { + await createIniFile(path.join(resourcesPath, '../config/settings.ini')); + } else { + settingsPath = path.join(resourcesPath, './config/settings.ini'); + settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); + } - window = new BrowserWindow({ - icon: path.join(__dirname, '/images/icon.png'), - width: parseInt(settings.SETTINGS.WIDTH), - height: parseInt(settings.SETTINGS.HEIGHT), - x: parseInt(settings.SETTINGS.POSITION_X), - y: parseInt(settings.SETTINGS.POSITION_Y), - frame: false, - webPreferences: { - nodeIntegration: true, - contextIsolation: false, - enableRemoteModule: true, - }, - }); - window.loadURL('https://github.com') + window = new BrowserWindow({ + icon: path.join(resourcesPath, '/images/icon.png'), + width: parseInt(settings.SETTINGS.WIDTH), + height: parseInt(settings.SETTINGS.HEIGHT), + x: parseInt(settings.SETTINGS.POSITION_X), + y: parseInt(settings.SETTINGS.POSITION_Y), + frame: false, + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + enableRemoteModule: true, + }, + }); + window.loadURL('https://github.com'); - window.loadFile(path.join(__dirname, 'index.html')); + window.loadFile(path.join(resourcesPath, 'index.html')); - if (!app.isPackaged) { - window.webContents.openDevTools(); - } + if (!app.isPackaged) { + window.webContents.openDevTools(); + } - window.on('close', e => { - settings = ini.parse(fs.readFileSync(resourcesPath, 'utf-8')); // load newest settings in case anything changed after starting the program - const bounds = window.getBounds(); + window.on('close', (e) => { + settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); // load newest settings in case anything changed after starting the program + const bounds = window.getBounds(); - settings.SETTINGS.WIDTH = bounds.width; - settings.SETTINGS.HEIGHT = bounds.height; - settings.SETTINGS.POSITION_X = bounds.x; - settings.SETTINGS.POSITION_Y = bounds.y; + settings.SETTINGS.WIDTH = bounds.width; + settings.SETTINGS.HEIGHT = bounds.height; + settings.SETTINGS.POSITION_X = bounds.x; + settings.SETTINGS.POSITION_Y = bounds.y; - fs.writeFileSync(resourcesPath, ini.stringify(settings)); - }) -}; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + }); +} app.whenReady().then(() => { - createWindow(); -}) + createWindow(); +}); app.on('window-all-closed', (event) => { - if (process.platform !== 'darwin') { - app.quit(); - } + if (process.platform !== 'darwin') { + app.quit(); + } }); app.on('activate', () => { - // On OS X it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (BrowserWindow.getAllWindows().length === 0) { - createWindow(); - } + // On OS X it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } }); ipcMain.on('resize-window', (event, width, height) => { - const browserWindow = BrowserWindow.fromWebContents(event.sender); - browserWindow.setSize(width, height); + const browserWindow = BrowserWindow.fromWebContents(event.sender); + browserWindow.setSize(width, height); }); ipcMain.on('minimize-window', (event) => { - const browserWindow = BrowserWindow.fromWebContents(event.sender); - browserWindow.minimize(); + const browserWindow = BrowserWindow.fromWebContents(event.sender); + browserWindow.minimize(); }); ipcMain.on('maximize-window', (event) => { - const browserWindow = BrowserWindow.fromWebContents(event.sender); + const browserWindow = BrowserWindow.fromWebContents(event.sender); - if (!browserWindow.isMaximized()) { - browserWindow.maximize(); - } else { - browserWindow.unmaximize(); - } + if (!browserWindow.isMaximized()) { + browserWindow.maximize(); + } else { + browserWindow.unmaximize(); + } }); ipcMain.on('close-window', (event) => { - const browserWindow = BrowserWindow.fromWebContents(event.sender); - browserWindow.close(); - app.quit(); + const browserWindow = BrowserWindow.fromWebContents(event.sender); + browserWindow.close(); + app.quit(); +}); + +ipcMain.on('restart', (event) => { + app.relaunch(); }); ipcMain.on('environment', (event) => { - event.returnValue = { "env": app.isPackaged, "path": process.resourcesPath }; + event.returnValue = { resourcesPath: resourcesPath, settingsPath: settingsPath, settings: settings }; +}); + +let twitchAuthentication = () => + new Promise((resolve) => { + const http = require('http'); + const redirectUri = 'http://localhost:1989/auth'; + const scopes = ['chat:edit', 'chat:read']; + + const express = require('express'); + let tempAuthServer = express(); + const port = 1989; + + const { parse: parseQueryString } = require('querystring'); + + tempAuthServer.use(function (req, res, next) { + if (req.url !== '/auth') { + let token = parseQueryString(req.query.auth); + settings.TWITCH.OAUTH_TOKEN = token['#access_token']; + fs.writeFileSync(settingsPath, ini.stringify(settings)); + settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8')); + resolve('finished'); + stopServer(); + } + next(); + }); + + function stopServer() { + tempAuthServer.close(); + } + + const htmlString = ` + + + + Authentication + + +

        Authentication successful! You can close this window now.

        +
        + + + + + + + `; + + tempAuthServer.get('/auth', (req, res) => { + res.send(htmlString); + }); + + tempAuthServer.post('/auth', (req, res) => { + res.render('authentication', { name: req.body.name }); + }); + + const server = http.createServer(tempAuthServer); + + server.listen(port, () => { + const authURL = `https://id.twitch.tv/oauth2/authorize?client_id=${settings.TWITCH.CLIENT_ID}&redirect_uri=${encodeURIComponent( + redirectUri, + )}&response_type=token&scope=${scopes.join(' ')}`; + shell.openExternal(authURL); + }); + + function stopServer() { + server.close(() => {}); + } + }); + +ipcMain.on('twitch', async (event) => { + await twitchAuthentication(); + event.returnValue = settings.TWITCH.OAUTH_TOKEN; +}); + +ipcMain.on('vtuber', async (event) => { + shell.openExternal(`http://localhost:${settings.SERVER.PORT}/vtuber/`); +}); + +ipcMain.on('chatBubble', async (event) => { + shell.openExternal(`http://localhost:${settings.SERVER.PORT}/chat/`); }); async function createIniFile() { - await writeIniFile(resourcesPath, { - SETTINGS: { - VOICE_ENABLED: true, - NOTIFICATION_ENABLED: true, - POSITION_X: 0, - POSITION_Y: 0, - WIDTH: 1024, - HEIGHT: 768, - LANGUAGE: "EN" - }, - TTS: { - PRIMARY_TTS_VOICE: 0, - PRIMARY_TTS_NAME: "", - PRIMARY_TTS_LANGUAGE: "EN", - PRIMARY_TTS_LANGUAGE_INDEX: 0, - SECONDARY_TTS_VOICE: 0, - SECONDARY_TTS_NAME: "", - SECONDARY_TTS_LANGUAGE: "EN", - SECONDARY_TTS_LANGUAGE_INDEX: 0 - }, - AUDIO: { - NOTIFICATION_AUDIO_DEVICE: 0, - NOTIFICATION_SOUND: 0, - NOTIFICATION_VOLUME: 100, - SELECTED_TTS_AUDIO_DEVICE: 0, - TTS_AUDIO_DEVICE: "default", - TTS_VOLUME: 100 - }, - THEME: { - USE_CUSTOM_THEME: false, - MAIN_COLOR_1: "\#cdc1c1", - MAIN_COLOR_2: "\#b12020", - MAIN_COLOR_3: "\#6c4104", - MAIN_COLOR_4: "\#532d2d", - TOP_BAR: "\#c8ff00", - MID_SECTION: "\#6b8578", - CHAT_BUBBLE_BG: "\#447466", - CHAT_BUBBLE_HEADER: "\#ffffff", - CHAT_BUBBLE_MESSAGE: "\#b5b5b5", - }, - TWITCH: { - USE_TWITCH: false, - CHANNEL_NAME: "khyretos", - USERNAME: "loquendo", - OAUTH_TOKEN: "", - CLIENT_ID: "", - CLIENT_SECRET: "", - }, - SERVER: { - USE_SERVER: false, - PORT: "9000", - USE_VTUBER: false, - USE_CHATBUBBLE: false, - }, - AMAZON: { - USE_TWITCH: false, - ACCESS_KEY: "", - ACCESS_SECRET: "", - }, - GOOGLE: { - USE_GOOGLE: false, - API_KEY: "", - } - }).then(() => { - settings = ini.parse(fs.readFileSync(resourcesPath, 'utf-8')); - }) -} \ No newline at end of file + await writeIniFile(resourcesPath, { + SETTINGS: { + VOICE_ENABLED: true, + NOTIFICATION_ENABLED: true, + POSITION_X: 0, + POSITION_Y: 0, + WIDTH: 1024, + HEIGHT: 768, + LANGUAGE: 'EN', + }, + TTS: { + USE_TTS: true, + PRIMARY_TTS_VOICE: 0, + PRIMARY_TTS_NAME: '', + PRIMARY_TTS_LANGUAGE: 'EN', + PRIMARY_TTS_LANGUAGE_INDEX: 0, + SECONDARY_TTS_VOICE: 0, + SECONDARY_TTS_NAME: '', + SECONDARY_TTS_LANGUAGE: 'EN', + SECONDARY_TTS_LANGUAGE_INDEX: 0, + TTS_VOLUME: 50, + }, + AUDIO: { + USE_NOTIFICATION_SOUNDS: true, + NOTIFICATION_AUDIO_DEVICE: 0, + NOTIFICATION_SOUND: 0, + NOTIFICATION_VOLUME: 50, + SELECTED_TTS_AUDIO_DEVICE: 0, + TTS_AUDIO_DEVICE: 'default', + }, + THEME: { + USE_CUSTOM_THEME: false, + MAIN_COLOR_1: '#cdc1c1', + MAIN_COLOR_2: '#b12020', + MAIN_COLOR_3: '#6c4104', + MAIN_COLOR_4: '#532d2d', + TOP_BAR: '#c8ff00', + MID_SECTION: '#6b8578', + CHAT_BUBBLE_BG: '#447466', + CHAT_BUBBLE_HEADER: '#ffffff', + CHAT_BUBBLE_MESSAGE: '#b5b5b5', + }, + TWITCH: { + USE_TWITCH: false, + CHANNEL_NAME: '', + USERNAME: 'loquendo', + OAUTH_TOKEN: '', + CLIENT_ID: '2t206sj7rvtr1rutob3p627d13jch9', + }, + SERVER: { + USE_SERVER: false, + PORT: '9000', + USE_VTUBER: false, + USE_CHATBUBBLE: false, + }, + AMAZON: { + USE_TWITCH: false, + ACCESS_KEY: '', + ACCESS_SECRET: '', + }, + GOOGLE: { + USE_GOOGLE: false, + API_KEY: '', + }, + }).then(() => { + settings = ini.parse(fs.readFileSync(resourcesPath, 'utf-8')); + }); +} diff --git a/src/modules/chat/main.js b/src/modules/chat/main.js index 1f501b8..6da62ef 100644 --- a/src/modules/chat/main.js +++ b/src/modules/chat/main.js @@ -1,3 +1,4 @@ + // Connect to the Socket.IO server const socket = io(); diff --git a/src/sounds/tts/internal_audio_6.mp3 b/src/sounds/tts/internal_audio_6.mp3 new file mode 100644 index 0000000..8c2ff6b Binary files /dev/null and b/src/sounds/tts/internal_audio_6.mp3 differ