diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..3dce414
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..241edf9
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,5 @@
+node_modules
+docs
+dist
+out
+build
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..4a51dd8
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,16 @@
+module.exports = {
+ root: true,
+ env: {
+ es6: true,
+ node: true
+ },
+ parserOptions: {
+ sourceType: 'module',
+ ecmaVersion: 2021
+ },
+ extends: ['eslint:recommended', '@electron-internal', '@electron-toolkit'],
+ rules: {
+ 'space-before-function-paren': 'off',
+ vendorPrefix: 'off'
+ }
+};
diff --git a/.prettierrc.yaml b/.prettierrc.yaml
new file mode 100644
index 0000000..80c0f12
--- /dev/null
+++ b/.prettierrc.yaml
@@ -0,0 +1,5 @@
+singleQuote: true
+semi: true
+printWidth: 140
+trailingComma: none
+arrowParens: avoid
diff --git a/package.json b/package.json
index eb8957b..7e63f61 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"dependencies": {
"axios": "^1.4.0",
"electron-squirrel-startup": "^1.0.0",
+ "emoji-picker-element": "^1.21.0",
"express": "^4.18.2",
"ini": "^2.0.0",
"kill-process-by-name": "^1.0.5",
@@ -38,6 +39,12 @@
"@electron-forge/maker-squirrel": "^6.2.1",
"@electron-forge/maker-zip": "^6.2.1",
"@electron-forge/plugin-auto-unpack-natives": "^6.2.1",
- "electron": "^25.9.8"
+ "@electron-internal/eslint-config": "^1.0.1",
+ "@electron-toolkit/eslint-config": "^1.0.2",
+ "electron": "^25.9.8",
+ "eslint": "^8.56.0",
+ "eslint-config-prettier": "^9.1.0",
+ "eslint-plugin-prettier": "^5.1.2",
+ "prettier": "^3.1.1"
}
}
diff --git a/src/backend/loquendoBot_backend.py b/src/backend/loquendoBot_backend.py
index f539204..43e472d 100644
--- a/src/backend/loquendoBot_backend.py
+++ b/src/backend/loquendoBot_backend.py
@@ -1,7 +1,15 @@
+# from wsgiref.simple_server import WSGIServer
from flask import Flask, Response, jsonify, request
import gevent
+
+import re
import gevent.monkey
import json
+from waitress import serve
+import logging
+
+logger = logging.getLogger("waitress")
+logger.setLevel(logging.INFO)
gevent.monkey.patch_all()
import gevent.queue
@@ -40,6 +48,7 @@ q = queue.Queue()
# gobal functions
+
# classes
class LanguageDetection:
def __init__(self):
@@ -55,10 +64,8 @@ class LanguageDetection:
language_detection_model = os.path.join(
resources_folder, "language_detection_model", f"lid.176.bin"
)
-
- language_detection_model = (
- rf"{language_detection_model}"
- )
+
+ language_detection_model = rf"{language_detection_model}"
self.model = fasttext.load_model(language_detection_model)
def predict_lang(self, text):
@@ -69,6 +76,7 @@ class LanguageDetection:
return language_codes
+
class STT:
samplerate = None
args = ""
@@ -92,9 +100,7 @@ class STT:
resources_folder, "speech_to_text_models", settings["STT"]["LANGUAGE"]
)
- self.model = Model(
- rf"{vosk_model}"
- )
+ self.model = Model(rf"{vosk_model}")
self.dump_fn = None
self.q = gevent.queue.Queue()
@@ -180,6 +186,7 @@ text_to_speech_service = TTS()
# endpoints
+
@app.route("/stream", methods=["GET"])
def stream_recognition():
def generate():
@@ -239,9 +246,14 @@ def trigger_backend_event():
try:
request_data = request.json
message = request_data.get("message", "")
+ filteredMessage = re.sub(
+ r"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)",
+ "a link",
+ message,
+ )
voice = request_data.get("voice")
count = request_data.get("count")
- text_to_speech_service.say(message, voice, count)
+ text_to_speech_service.say(filteredMessage, voice, count)
except Exception as e:
return jsonify({"error": "An error occurred"}), 500
return jsonify({"message": "Audio triggered"}), 200
@@ -257,14 +269,14 @@ def get_voices():
if __name__ == "__main__":
- LANGUAGE = LanguageDetection()
- lang = LANGUAGE.predict_lang("hola cómo estás")
- print(lang)
- text = "Keep it up. You are awesome"
- translated = MyMemoryTranslator(
- source="english", target="spanish latin america"
- ).translate(text)
- print(translated)
+ # LANGUAGE = LanguageDetection()
+ # lang = LANGUAGE.predict_lang("hola cómo estás")
+ # print(lang)
+ # text = "Keep it up. You are awesome"
+ # translated = MyMemoryTranslator(
+ # source="english", target="spanish latin america"
+ # ).translate(text)
+ # print(translated)
if len(sys.argv) > 1:
settings.read(settingsPath)
port = int(settings["GENERAL"]["PORT"])
@@ -273,5 +285,4 @@ if __name__ == "__main__":
port = 9000
stream_recognition()
- app.run(host="127.0.0.1", port=port)
- app.terminate()
+ serve(app, host="0.0.0.0", port=port)
diff --git a/src/css/chat.css b/src/css/chat.css
index bcc1767..53042b2 100644
--- a/src/css/chat.css
+++ b/src/css/chat.css
@@ -1,462 +1,469 @@
@font-face {
- font-family: 'FRAMDCN';
+ font-family: 'FRAMDCN';
+ src: url(../fonts/FRAMCDN/FRAMDCN.woff);
}
h1 {
- font-family: 'FRAMDCN';
+ font-family: 'FRAMDCN';
}
.message-window {
- height: calc(100% - 60px);
- overflow: hidden;
- overflow-y: auto;
- display: flex;
- align-items: center;
- flex-direction: column;
- background-color: var(--mid-section);
- padding-left: 50px;
- padding-right: 50px;
- font-family: 'FRAMDCN';
- position: relative;
- z-index: 1;
+ height: calc(100% - 60px);
+ overflow: hidden;
+ overflow-y: auto;
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ background-color: var(--mid-section);
+ padding-left: 50px;
+ padding-right: 50px;
+ font-family: 'FRAMDCN';
+ position: relative;
+ z-index: 1;
}
.input-box {
- display: flex;
- border: none;
- width: 100%;
- height: 30px;
- font-size: 16px;
+ display: flex;
+ border: none;
+ width: 100%;
+ height: 30px;
+ font-size: 16px;
}
.userText {
- color: var(--chat-bubble-message);
- font-family: Helvetica;
- font-size: 16px;
- text-align: right;
- clear: both;
+ color: var(--chat-bubble-message);
+ font-family: Helvetica;
+ font-size: 16px;
+ text-align: right;
+ clear: both;
}
.userText span {
- line-height: 1.5em;
- display: inline-block;
- background: #5ca6fa;
- padding: 10px;
- border-radius: 8px;
- border-bottom-right-radius: 2px;
- max-width: 80%;
- margin-right: 10px;
- animation: floatup 0.5s forwards;
+ line-height: 1.5em;
+ display: inline-block;
+ background: #5ca6fa;
+ padding: 10px;
+ border-radius: 8px;
+ border-bottom-right-radius: 2px;
+ max-width: 80%;
+ margin-right: 10px;
+ animation: floatup 0.5s forwards;
}
.botText {
- color: #000;
- font-family: Helvetica;
- font-weight: normal;
- font-size: 16px;
- text-align: left;
+ color: #000;
+ font-family: Helvetica;
+ font-weight: normal;
+ font-size: 16px;
+ text-align: left;
}
.botText span {
- line-height: 1.5em;
- display: inline-block;
- background: #e0e0e0;
- padding: 10px;
- border-radius: 8px;
- border-bottom-left-radius: 2px;
- max-width: 80%;
- margin-left: 10px;
- animation: floatup 0.5s forwards;
+ line-height: 1.5em;
+ display: inline-block;
+ background: #e0e0e0;
+ padding: 10px;
+ border-radius: 8px;
+ border-bottom-left-radius: 2px;
+ max-width: 80%;
+ margin-left: 10px;
+ animation: floatup 0.5s forwards;
}
@keyframes floatup {
- from {
- transform: translateY(14px);
- opacity: 0;
- }
+ from {
+ transform: translateY(14px);
+ opacity: 0;
+ }
- to {
- transform: translateY(0px);
- opacity: 1;
- }
+ to {
+ transform: translateY(0px);
+ opacity: 1;
+ }
}
@media screen and (max-width: 600px) {
- .full-chat-block {
- width: 100%;
- border-radius: 0px;
- }
+ .full-chat-block {
+ width: 100%;
+ border-radius: 0px;
+ }
- .chat-bar-collapsible {
- position: fixed;
- bottom: 0;
- right: 0;
- width: 100%;
- }
+ .chat-bar-collapsible {
+ position: fixed;
+ bottom: 0;
+ right: 0;
+ width: 100%;
+ }
- .collapsible {
- width: 100%;
- border: 0px;
- border-radius: 0px;
- }
+ .collapsible {
+ width: 100%;
+ border: 0px;
+ border-radius: 0px;
+ }
}
::-webkit-scrollbar {
- width: 4px;
+ width: 4px;
}
::-webkit-scrollbar-thumb {
- background-color: #4c4c6a;
- border-radius: 2px;
+ background-color: #4c4c6a;
+ border-radius: 2px;
}
.chatBox {
- width: 300px;
- height: 400px;
- max-height: 400px;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- box-shadow: 0 0 4px var(--main-color4);
+ width: 300px;
+ height: 400px;
+ max-height: 400px;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ box-shadow: 0 0 4px var(--main-color4);
}
.chat-window {
- flex: auto;
- max-height: calc(100% - 60px);
- background: #2f323b;
- overflow: auto;
+ flex: auto;
+ max-height: calc(100% - 60px);
+ background: #2f323b;
+ overflow: auto;
}
.chat-input {
- height: 30px;
- display: flex;
- flex: 0 0 auto;
- height: 60px;
- background: var(--main-color3);
+ height: 30px;
+ display: flex;
+ flex: 0 0 auto;
+ height: 60px;
+ background: var(--main-color3);
}
.chat-input input {
- height: 59px;
- line-height: 60px;
- outline: 0 none;
- border: none;
- width: calc(100% - 60px);
- color: var(--chat-bubble-message);
- text-indent: 10px;
- font-size: 12pt;
- padding: 0;
- background: var(--main-color3);
+ height: 59px;
+ line-height: 60px;
+ outline: 0 none;
+ border: none;
+ width: calc(100% - 60px);
+ color: var(--chat-bubble-message);
+ text-indent: 10px;
+ font-size: 12pt;
+ padding: 0;
+ background: var(--main-color3);
}
.chat-input button {
- float: right;
- outline: 0 none;
- border: none;
- background: var(--main-color3);
- height: 40px;
- width: 40px;
- border-radius: 50%;
- padding: 2px 0 0 0;
- margin: 10px;
+ float: right;
+ outline: 0 none;
+ border: none;
+ background: var(--main-color3);
+ height: 40px;
+ width: 40px;
+ border-radius: 50%;
+ padding: 2px 0 0 0;
+ margin: 10px;
}
.chat-input input[good] + button {
- box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24);
+ box-shadow:
+ 0 0 2px rgba(0, 0, 0, 0.12),
+ 0 2px 4px rgba(0, 0, 0, 0.24);
}
.chat-input input[good] + button:hover {
- box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
- /* filter: brightness(150%); */
+ box-shadow:
+ 0 8px 17px 0 rgba(0, 0, 0, 0.2),
+ 0 6px 20px 0 rgba(0, 0, 0, 0.19);
+ /* filter: brightness(150%); */
}
.chat-input input[good] + button path {
- fill: var(--chat-bubble-message);
+ fill: var(--chat-bubble-message);
}
.msg-container {
- direction: ltr;
- position: static;
- width: 100%;
- padding: 10px 0px 0px 0px;
- display: grid;
- grid-template: 1fr / 1fr;
- align-self: start;
+ direction: ltr;
+ position: static;
+ width: 100%;
+ padding: 10px 0px 0px 0px;
+ display: grid;
+ grid-template: 1fr / 1fr;
+ align-self: start;
}
.msg-container > * {
- grid-column: 1 / 1;
- grid-row: 1 / 1;
+ grid-column: 1 / 1;
+ grid-row: 1 / 1;
}
.msg-container.sender {
- place-items: self-start;
+ place-items: self-start;
}
.msg-container.user {
- place-items: self-end;
+ place-items: self-end;
}
.msg-box {
- background: var(--chat-bubble);
- color: white;
- min-width: 100px;
- border-radius: 5px;
- padding: 18px 5px 5px 5px;
- box-shadow: 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24);
- width: fit-content;
- position: relative;
- align-self: start;
+ background: var(--chat-bubble);
+ color: white;
+ min-width: 100px;
+ border-radius: 5px;
+ padding: 18px 5px 5px 5px;
+ box-shadow:
+ 0 0 2px rgba(0, 0, 0, 0.12),
+ 0 2px 4px rgba(0, 0, 0, 0.24);
+ width: fit-content;
+ position: relative;
+ align-self: start;
}
.msg-box.sender {
- margin: 25px 25px 0px 35px;
+ margin: 25px 25px 0px 35px;
}
.msg-box.user {
- text-align: left;
- margin: 25px 35px 0px 0px;
+ text-align: left;
+ margin: 25px 35px 0px 0px;
}
.msg-box-user-temp {
- background: var(--chat-bubble-temp);
+ background: var(--chat-bubble-temp);
}
.user-img {
- display: inline-block;
- position: relative;
- border-radius: 50%;
- height: 50px;
- width: 50px;
- z-index: 5;
- align-self: start;
+ display: inline-block;
+ position: relative;
+ border-radius: 50%;
+ height: 50px;
+ width: 50px;
+ z-index: 5;
+ align-self: start;
}
.messages.user {
- margin-right: 20px;
+ margin-right: 20px;
}
.msg {
- font-size: 12pt;
- color: var(--chat-bubble-message);
- margin: 0 0 0 0;
+ font-size: 12pt;
+ color: var(--chat-bubble-message);
+ margin: 0 0 0 0;
}
.msg-temp {
- color: var(--chat-bubble-message-temp);
+ color: var(--chat-bubble-message-temp);
}
.timestamp {
- color: var(--chat-bubble-header);
- font-size: 10pt;
- align-items: center;
- font-family: 'xxii_avenmedium';
+ color: var(--chat-bubble-header);
+ font-size: 10pt;
+ align-items: center;
+ font-family: 'xxii_avenmedium';
}
.timestamp-temp {
- color: var(--chat-bubble-header-temp);
+ color: var(--chat-bubble-header-temp);
}
.username {
- background-color: var(--main-color4);
- color: white;
- position: relative;
- border-radius: 5px;
- z-index: 3;
- align-self: start;
+ background-color: var(--main-color4);
+ color: white;
+ position: relative;
+ border-radius: 5px;
+ z-index: 3;
+ align-self: start;
}
.username.sender {
- padding: 0px 5px 5px 30px;
- margin: 20px 5px 5px 30px;
+ padding: 0px 5px 5px 30px;
+ margin: 20px 5px 5px 30px;
}
.username.user {
- padding: 0px 30px 5px 5px;
- margin: 20px 30px 5px 5px;
+ padding: 0px 30px 5px 5px;
+ margin: 20px 30px 5px 5px;
}
.username-temp {
- color: var(--chat-bubble-header-temp);
+ color: var(--chat-bubble-header-temp);
}
.post-time {
- font-size: 8pt;
- color: white;
- display: inline-block;
- background-color: var(--main-color4);
- position: relative;
- z-index: 2;
- border-radius: 5px;
- align-self: start;
+ font-size: 8pt;
+ color: white;
+ display: inline-block;
+ background-color: var(--main-color4);
+ position: relative;
+ z-index: 2;
+ border-radius: 5px;
+ align-self: start;
}
.post-time.sender {
- padding: 5px 5px 0px 15px;
- margin: 0px 0px 0px 50px;
+ padding: 5px 5px 0px 15px;
+ margin: 0px 0px 0px 50px;
}
.post-time.user {
- padding: 5px 15px 0px 5px;
- margin: 0px 50px 0px 0px;
+ padding: 5px 15px 0px 5px;
+ margin: 0px 50px 0px 0px;
}
.mmg {
- display: flex;
+ display: flex;
}
.img {
- height: 100%;
- width: 100%;
- border-radius: 50%;
+ height: 100%;
+ width: 100%;
+ border-radius: 50%;
}
.status-circle {
- width: 20px;
- border-radius: 50%;
- z-index: 6;
- position: relative;
- align-self: start;
+ width: 20px;
+ border-radius: 50%;
+ z-index: 6;
+ position: relative;
+ align-self: start;
}
.status-circle.sender {
- margin-left: 40px;
+ margin-left: 40px;
}
.status-circle.user {
- margin-right: 40px;
+ margin-right: 40px;
}
.menu-select {
- font-size: 0.9rem;
- height: 40px;
- border-radius: 20px;
- background-color: var(--main-color3);
- color: var(--main-color2);
- align-items: center;
- border: 0px;
- padding-left: 10px;
- width: 300px;
- font-size: 100%;
- padding: 10px;
- padding-right: 25px;
- outline: none;
- -webkit-appearance: none;
- -moz-appearance: none;
- background-image: url("data:image/svg+xml;utf8,");
- background-repeat: no-repeat;
- background-position-x: 100%;
- background-position-y: 5px;
+ font-size: 0.9rem;
+ height: 40px;
+ border-radius: 20px;
+ background-color: var(--main-color3);
+ color: var(--main-color2);
+ align-items: center;
+ border: 0px;
+ padding-left: 10px;
+ width: 300px;
+ font-size: 100%;
+ padding: 10px;
+ padding-right: 25px;
+ outline: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ background-image: url("data:image/svg+xml;utf8,");
+ background-repeat: no-repeat;
+ background-position-x: 100%;
+ background-position-y: 5px;
}
.top-select {
- width: auto;
- height: 24px;
- padding: 0px;
- margin: 0px;
- background-color: transparent;
- color: white;
- -webkit-appearance: none;
- -moz-appearance: none;
- border: none;
+ width: auto;
+ height: 24px;
+ padding: 0px;
+ margin: 0px;
+ background-color: transparent;
+ color: white;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ border: none;
}
.info-image {
- width: 50px;
- height: 50px;
+ width: 50px;
+ height: 50px;
}
.top-select option {
- margin: 40px;
- background: rgba(0, 0, 0, 0.3);
- color: #fff;
- text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
- background-color: var(--top-bar);
+ margin: 40px;
+ background: rgba(0, 0, 0, 0.3);
+ color: #fff;
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
+ background-color: var(--top-bar);
}
.AdvancedMenu {
- border: 1px var(--main-color2) solid;
- margin-top: 10px;
- min-width: 555px;
- border-radius: 5px;
- border-radius: 5px;
+ border: 1px var(--main-color2) solid;
+ margin-top: 10px;
+ min-width: 555px;
+ border-radius: 5px;
+ border-radius: 5px;
}
.legendStyle {
- margin-left: 1em;
- padding: 0.2em 0.8em;
- display: flex;
- align-items: center;
+ margin-left: 1em;
+ padding: 0.2em 0.8em;
+ display: flex;
+ align-items: center;
}
.AdvancedMenuRow {
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: center;
- justify-content: left;
- margin-bottom: 10px;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ justify-content: left;
+ margin-bottom: 10px;
}
.AdvancedMenuLabel {
- font-size: 10pt;
- padding-right: 5px;
- margin-left: 10px;
- width: 125px;
+ font-size: 10pt;
+ padding-right: 5px;
+ margin-left: 10px;
+ width: 125px;
}
.AdvancedMenuLabel2 {
- font-size: 10pt;
- padding-right: 5px;
- margin-left: 10px;
+ font-size: 10pt;
+ padding-right: 5px;
+ margin-left: 10px;
}
.AdvancedMenuLabel3 {
- font-size: 12pt;
- padding-right: 5px;
- margin-left: 10px;
+ font-size: 12pt;
+ padding-right: 5px;
+ margin-left: 10px;
}
#SaveAdvancedSettingsButton {
- margin-left: 10px;
+ margin-left: 10px;
}
.toggle {
- position: relative;
- display: inline-block;
- width: 60px;
- height: 40px;
- background-color: var(--main-color3);
- border-radius: 20px;
+ position: relative;
+ display: inline-block;
+ width: 60px;
+ height: 40px;
+ background-color: var(--main-color3);
+ border-radius: 20px;
}
/* After slide changes */
.toggle:after {
- content: '';
- position: absolute;
- width: 30px;
- height: 30px;
- border-radius: 50%;
- background-color: var(--main-color2);
- left: 5px;
- top: 5px;
+ content: '';
+ position: absolute;
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ background-color: var(--main-color2);
+ left: 5px;
+ top: 5px;
}
/* Checkbox checked effect */
.checkbox:checked + .toggle::after {
- left: 25px;
+ left: 25px;
}
/* Checkbox checked toggle label bg color */
.checkbox:checked + .toggle {
- background-color: var(--main-color1);
+ background-color: var(--main-color1);
}
/* Checkbox vanished */
.checkbox {
- display: none;
+ display: none;
}
/* Small toggle */
@@ -464,36 +471,45 @@ h1 {
/* toggle in label designing */
.toggle-small {
- position: relative;
- display: inline-block;
- width: 30px;
- height: 20px;
- background-color: var(--main-color3);
- border-radius: 10px;
- margin-left: 10px;
+ position: relative;
+ display: inline-block;
+ width: 30px;
+ height: 20px;
+ background-color: var(--main-color3);
+ border-radius: 10px;
+ margin-left: 10px;
}
/* After slide changes */
.toggle-small:after {
- content: '';
- position: absolute;
- width: 15px;
- height: 15px;
- border-radius: 50%;
- background-color: white;
- left: 2px;
- top: 2px;
+ content: '';
+ position: absolute;
+ width: 15px;
+ height: 15px;
+ border-radius: 50%;
+ background-color: white;
+ left: 2px;
+ top: 2px;
}
/* Checkbox checked effect */
.checkbox:checked + .toggle-small::after {
- left: 13px;
+ left: 13px;
}
/* Checkbox checked toggle label bg color */
.checkbox:checked + .toggle-small {
- background-color: var(--main-color1);
+ background-color: var(--main-color1);
+}
+
+.emoji-picker {
+ margin-left: auto;
+ visibility: hidden;
+ bottom: 50px;
+ left: 0px;
+ position: absolute;
+ z-index: 1;
}
diff --git a/src/css/checkbox.css b/src/css/checkbox.css
index 2a01657..15b2bdb 100644
--- a/src/css/checkbox.css
+++ b/src/css/checkbox.css
@@ -1,62 +1,62 @@
-input[type="radio"]:checked {
- visibility: hidden;
- position: absolute;
+input[type='radio']:checked {
+ visibility: hidden;
+ position: absolute;
}
-input[type="radio"] {
- visibility: hidden;
- position: absolute;
+input[type='radio'] {
+ visibility: hidden;
+ position: absolute;
}
label.btn span {
- font-size: 1.5em;
+ font-size: 1.5em;
}
-label input[type="radio"]~i.fa.fa-square {
- color: var(--main-color3);
- display: inline;
+label input[type='radio'] ~ i.fa.fa-square {
+ color: var(--main-color3);
+ display: inline;
}
-label input[type="radio"]~i.fa.fa-check-square {
- display: none;
+label input[type='radio'] ~ i.fa.fa-check-square {
+ display: none;
}
-label input[type="radio"]:checked~i.fa.fa-square {
- display: none;
+label input[type='radio']:checked ~ i.fa.fa-square {
+ display: none;
}
-label input[type="radio"]:checked~i.fa.fa-check-square {
- display: inline;
- color: var(--main-color2);
+label input[type='radio']:checked ~ i.fa.fa-check-square {
+ display: inline;
+ color: var(--main-color2);
}
-label:hover input[type="radio"]~i.fa {
- color: var(--main-color1);
- /* filter: brightness(150%); */
+label:hover input[type='radio'] ~ i.fa {
+ color: var(--main-color1);
+ /* filter: brightness(150%); */
}
-div[data-toggle="buttons"] label {
- display: inline-block;
- padding: 3px 12px;
- margin-bottom: 0;
- font-size: 20px;
- font-weight: normal;
- line-height: 2em;
- text-align: left;
- white-space: nowrap;
- vertical-align: top;
- cursor: pointer;
- background-color: none;
- border-radius: 3px;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- -o-user-select: none;
- user-select: none;
+div[data-toggle='buttons'] label {
+ display: inline-block;
+ padding: 3px 12px;
+ margin-bottom: 0;
+ font-size: 20px;
+ font-weight: normal;
+ line-height: 2em;
+ text-align: left;
+ white-space: nowrap;
+ vertical-align: top;
+ cursor: pointer;
+ background-color: none;
+ border-radius: 3px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ user-select: none;
}
-div[data-toggle="buttons"] label:active,
-div[data-toggle="buttons"] label.active {
- -webkit-box-shadow: none;
- box-shadow: none;
-}
\ No newline at end of file
+div[data-toggle='buttons'] label:active,
+div[data-toggle='buttons'] label.active {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
diff --git a/src/css/home.css b/src/css/home.css
index b612164..5dcccf6 100644
--- a/src/css/home.css
+++ b/src/css/home.css
@@ -1,253 +1,273 @@
/* Basic styling */
:root {
- overflow: hidden;
- --main-color1: #6e2c8c;
- --main-color1-temp: #6e2c8c;
- /*Left bar and top right bar*/
- --main-color2: white;
- --main-color2-temp: white;
- /*Icons and text*/
- --main-color3: #211e1e;
- --main-color3-temp: #211e1e;
- /*Buttons and input*/
- --main-color4: #2f2c34;
- --main-color4-temp: #2f2c34;
- --top-bar: #100b12;
- --top-bar-temp: #100b12;
- --mid-section: #352d3d;
- --mid-section-temp: #352d3d;
- --chat-bubble: #7a6d7f;
- --chat-bubble-header: #141414;
- --chat-bubble-username: white;
- --chat-bubble-message: white;
- --chat-bubble-temp: #7a6d7f;
- --chat-bubble-header-temp: #141414;
- --chat-bubble-message-temp: white;
+ overflow: hidden;
+ --main-color1: #6e2c8c;
+ --main-color1-temp: #6e2c8c;
+ /*Left bar and top right bar*/
+ --main-color2: white;
+ --main-color2-temp: white;
+ /*Icons and text*/
+ --main-color3: #211e1e;
+ --main-color3-temp: #211e1e;
+ /*Buttons and input*/
+ --main-color4: #2f2c34;
+ --main-color4-temp: #2f2c34;
+ --top-bar: #100b12;
+ --top-bar-temp: #100b12;
+ --mid-section: #352d3d;
+ --mid-section-temp: #352d3d;
+ --chat-bubble: #7a6d7f;
+ --chat-bubble-header: #141414;
+ --chat-bubble-username: white;
+ --chat-bubble-message: white;
+ --chat-bubble-temp: #7a6d7f;
+ --chat-bubble-header-temp: #141414;
+ --chat-bubble-message-temp: white;
}
html {
- box-sizing: border-box;
+ box-sizing: border-box;
}
*,
*:before,
*:after {
- box-sizing: inherit;
+ box-sizing: inherit;
}
html,
body {
- height: 100%;
- margin: 0;
- /* border-top-left-radius: 20px; */
- /* border-top-right-radius: 20px; */
- overflow-x: hidden;
+ height: 100%;
+ margin: 0;
+ /* border-top-left-radius: 20px; */
+ /* border-top-right-radius: 20px; */
+ overflow-x: hidden;
}
body {
- font-family: 'Segoe UI', sans-serif;
- background: transparent;
+ font-family: 'Segoe UI', sans-serif;
+ background: transparent;
}
/* Styling of window frame and titlebar */
body {
- /* border: 1px solid #48545c; */
- overflow-y: hidden;
+ /* border: 1px solid #48545c; */
+ overflow-y: hidden;
}
#titlebar {
- display: block;
- /* position: fixed; */
- height: 32px;
- width: calc(100%);
- background-color: var(--top-bar);
- /* border-top-left-radius: 20px;
+ display: block;
+ /* position: fixed; */
+ height: 32px;
+ width: calc(100%);
+ background-color: var(--top-bar);
+ /* border-top-left-radius: 20px;
border-top-right-radius: 20px; */
}
.maximized #titlebar {
- width: 100%;
- padding: 0;
+ width: 100%;
+ padding: 0;
}
#main {
- height: calc(100% - 32px);
- margin-top: 32px;
- padding: 20px;
- overflow-y: auto;
- display: flex;
+ height: calc(100% - 32px);
+ margin-top: 32px;
+ padding: 20px;
+ overflow-y: auto;
+ display: flex;
}
#titlebar {
- padding: 4px;
+ padding: 4px;
}
#titlebar #drag-region {
- width: 100%;
- height: 100%;
- -webkit-app-region: drag;
- display: inline-flex;
+ width: 100%;
+ height: 100%;
+ -webkit-app-region: drag;
+ display: inline-flex;
}
#titlebar {
- color: var(--main-color2);
+ color: var(--main-color2);
}
#window-title {
- grid-column: 1;
- display: flex;
- align-items: center;
- margin-left: 8px;
- overflow: hidden;
- font-family: 'Segoe UI', sans-serif;
- font-size: 12px;
+ grid-column: 1;
+ display: flex;
+ align-items: center;
+ margin-left: 8px;
+ overflow: hidden;
+ font-family: 'Segoe UI', sans-serif;
+ font-size: 12px;
}
.maximized #window-title {
- margin-left: 12px;
+ margin-left: 12px;
}
#window-title span {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- line-height: 1.5;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ line-height: 1.5;
}
#window-controls {
- display: grid;
- grid-template-columns: repeat(3, 46px);
- position: absolute;
- top: 0;
- right: 0;
- height: 32px;
- -webkit-app-region: no-drag;
+ display: grid;
+ grid-template-columns: repeat(3, 46px);
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 32px;
+ -webkit-app-region: no-drag;
}
#window-controls .button {
- grid-row: 1 / span 1;
- display: flex;
- justify-content: center;
- align-items: center;
- width: 100%;
- height: 32px;
+ grid-row: 1 / span 1;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ height: 32px;
}
@media (-webkit-device-pixel-ratio: 1.5),
- (device-pixel-ratio: 1.5),
- (-webkit-device-pixel-ratio: 2),
- (device-pixel-ratio: 2),
- (-webkit-device-pixel-ratio: 3),
- (device-pixel-ratio: 3) {
- #window-controls .icon {
- width: 10px;
- height: 10px;
- }
+ (device-pixel-ratio: 1.5),
+ (-webkit-device-pixel-ratio: 2),
+ (device-pixel-ratio: 2),
+ (-webkit-device-pixel-ratio: 3),
+ (device-pixel-ratio: 3) {
+ #window-controls .icon {
+ width: 10px;
+ height: 10px;
+ }
}
#window-controls .button {
- user-select: none;
+ user-select: none;
}
#window-controls .button:hover {
- background: rgba(255, 255, 255, 0.1);
- /* filter: brightness(150%); */
+ background: rgba(255, 255, 255, 0.1);
+ /* filter: brightness(150%); */
}
#window-controls .button:active {
- background: rgba(255, 255, 255, 0.2);
+ background: rgba(255, 255, 255, 0.2);
}
#close-button:hover {
- background: rgba(255, 255, 255, 0.1);
- /* border-top-right-radius: 20px; */
- background: #f1707a !important;
+ background: rgba(255, 255, 255, 0.1);
+ /* border-top-right-radius: 20px; */
+ background: #f1707a !important;
}
#close-button:active {
- background: #f1707a !important;
+ background: #f1707a !important;
}
#close-button:active .icon {
- filter: invert(1);
- background: #f1707a !important;
+ filter: invert(1);
+ background: #f1707a !important;
}
#min-button {
- grid-column: 1;
+ grid-column: 1;
}
#max-button,
#restore-button {
- grid-column: 2;
+ grid-column: 2;
}
#close-button {
- grid-column: 3;
+ grid-column: 3;
}
#restore-button {
- display: none !important;
+ display: none !important;
}
.maximized #restore-button {
- display: flex !important;
+ display: flex !important;
}
.maximized #max-button {
- display: none;
+ display: none;
}
.active-mic {
- position: absolute;
- bottom: 0;
+ position: absolute;
+ bottom: 0;
}
.about {
- -webkit-app-region: no-drag;
- position: absolute;
- left: 0;
- width: 32px;
- text-align: -webkit-center;
+ -webkit-app-region: no-drag;
+ position: absolute;
+ left: 0;
+ width: 32px;
+ text-align: -webkit-center;
}
.language-selector {
- position: absolute;
- -webkit-app-region: no-drag;
- display: inline-block;
- background-color: transparent;
- cursor: pointer;
- font-family: 'NotoColorEmojiLimited', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
- 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
- left: 50%;
- transform: translateX(-50%);
+ position: absolute;
+ -webkit-app-region: no-drag;
+ display: inline-block;
+ background-color: transparent;
+ cursor: pointer;
+ font-family:
+ 'NotoColorEmojiLimited',
+ -apple-system,
+ BlinkMacSystemFont,
+ 'Segoe UI',
+ Roboto,
+ Helvetica,
+ Arial,
+ sans-serif,
+ 'Apple Color Emoji',
+ 'Segoe UI Emoji',
+ 'Segoe UI Symbol';
+ left: 50%;
+ transform: translateX(-50%);
}
.language-dropdown {
- display: none;
- position: absolute;
- background-color: #fff;
- width: 55px;
- box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
- z-index: 2;
- font-family: 'NotoColorEmojiLimited', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
- 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
+ display: none;
+ position: absolute;
+ background-color: #fff;
+ width: 55px;
+ box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
+ z-index: 2;
+ font-family:
+ 'NotoColorEmojiLimited',
+ -apple-system,
+ BlinkMacSystemFont,
+ 'Segoe UI',
+ Roboto,
+ Helvetica,
+ Arial,
+ sans-serif,
+ 'Apple Color Emoji',
+ 'Segoe UI Emoji',
+ 'Segoe UI Symbol';
}
.language-item {
- padding: 5px;
- cursor: pointer;
- background-color: var(--top-bar);
+ padding: 5px;
+ cursor: pointer;
+ background-color: var(--top-bar);
}
-.language-item:hover {
- /* filter: brightness(150%); */
-}
+/* .language-item:hover {
+ filter: brightness(150%);
+} */
@font-face {
- font-family: NotoColorEmojiLimited;
- unicode-range: U+1F1E6-1F1FF;
- src: url(https://raw.githack.com/googlefonts/noto-emoji/main/fonts/NotoColorEmoji.ttf);
+ font-family: NotoColorEmojiLimited;
+ unicode-range: U+1F1E6-1F1FF;
+ src: url(https://raw.githack.com/googlefonts/noto-emoji/main/fonts/NotoColorEmoji.ttf);
}
diff --git a/src/css/logger.css b/src/css/logger.css
index 6b40515..4e2fae4 100644
--- a/src/css/logger.css
+++ b/src/css/logger.css
@@ -1,34 +1,34 @@
table {
- margin-left: 10px;
- background-color: white;
- border-collapse: collapse;
- width: 100%;
- margin-top: 60px;
+ margin-left: 10px;
+ background-color: white;
+ border-collapse: collapse;
+ width: 100%;
+ margin-top: 60px;
}
th,
td {
- border: 1px solid black;
- padding: 8px;
- text-align: left;
+ border: 1px solid black;
+ padding: 8px;
+ text-align: left;
}
.info {
- background-color: lightblue !important;
+ background-color: lightblue !important;
}
.warn {
- background-color: #f39c12 !important;
+ background-color: #f39c12 !important;
}
.error {
- background-color: #e74c3c !important;
+ background-color: #e74c3c !important;
}
#logTable {
- width: 95%;
+ width: 95%;
}
#Logs {
- overflow: auto;
-}
\ No newline at end of file
+ overflow: auto;
+}
diff --git a/src/css/menu.css b/src/css/menu.css
index d34ca4f..0c17438 100644
--- a/src/css/menu.css
+++ b/src/css/menu.css
@@ -1,226 +1,230 @@
.container {
- display: flex;
- height: calc(100vh - 32px);
- width: 100%;
- display: -webkit-box;
- display: -ms-flexbox;
- display: flex;
- /* will contain if #first is longer than #second */
+ display: flex;
+ height: calc(100vh - 32px);
+ width: 100%;
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ /* will contain if #first is longer than #second */
}
.mid {
- flex: 3;
- display: block;
- position: relative;
+ flex: 3;
+ display: block;
+ position: relative;
}
.OptionPanel {
- /* visibility: hidden; */
- background-color: var(--mid-section);
- flex: 3;
- display: none;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
+ /* visibility: hidden; */
+ background-color: var(--mid-section);
+ flex: 3;
+ display: none;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
}
.OptionPanel.show {
- display: block;
- overflow: auto;
+ display: block;
+ overflow: auto;
}
.menu {
- height: 100%;
- display: block;
- width: 100%;
- background: var(--main-color1);
- z-index: 1;
- position: relative;
+ height: 100%;
+ display: block;
+ width: 100%;
+ background: var(--main-color1);
+ z-index: 1;
+ position: relative;
}
.menu .items {
- list-style: none;
- margin: auto;
- padding: 0;
+ list-style: none;
+ margin: auto;
+ padding: 0;
}
#rpe {
- font-size: 8pt;
- margin: 2px 0px 0px 0px;
+ font-size: 8pt;
+ margin: 2px 0px 0px 0px;
}
.menu .items .item {
- width: 100%;
- height: 50px;
- display: flex;
- justify-content: center;
- align-items: center;
- background: var(--main-color1);
- color: var(--main-color2);
+ width: 100%;
+ height: 50px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background: var(--main-color1);
+ color: var(--main-color2);
}
.hdp:hover {
- position: fixed;
- /* filter: brightness(150%); */
+ position: fixed;
+ /* filter: brightness(150%); */
}
.menu .items .item-active {
- background: -webkit-linear-gradient(left, var(--main-color2) 10%, var(--main-color2), var(--main-color1) 10%, var(--main-color1) 10%);
- color: var(--main-color2);
- filter: brightness(90%);
+ background: -webkit-linear-gradient(left, var(--main-color2) 10%, var(--main-color2), var(--main-color1) 10%, var(--main-color1) 10%);
+ color: var(--main-color2);
+ filter: brightness(90%);
}
.menu .items .item:hover {
- cursor: pointer;
- color: var(--main-color2);
- filter: brightness(120%);
+ cursor: pointer;
+ color: var(--main-color2);
+ filter: brightness(120%);
}
.sidepanel-left {
- position: relative;
- width: 50px;
- font-size: 1.5em;
- line-height: 1.5em;
- font-family: Helvetica;
- text-align: center;
- box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px;
- transition: 0.3s ease-in-out;
+ position: relative;
+ width: 50px;
+ font-size: 1.5em;
+ line-height: 1.5em;
+ font-family: Helvetica;
+ text-align: center;
+ box-shadow:
+ rgba(0, 0, 0, 0.16) 0px 3px 6px,
+ rgba(0, 0, 0, 0.23) 0px 3px 6px;
+ transition: 0.3s ease-in-out;
}
.sidepanel-right {
- position: relative;
- width: 200px;
- font-size: 1.5em;
- line-height: 1.5em;
- font-family: Helvetica;
- text-align: center;
- box-shadow: rgba(0, 0, 0, 0.16) 0px 3px 6px, rgba(0, 0, 0, 0.23) 0px 3px 6px;
- transition: 0.3s ease-in-out;
+ position: relative;
+ width: 200px;
+ font-size: 1.5em;
+ line-height: 1.5em;
+ font-family: Helvetica;
+ text-align: center;
+ box-shadow:
+ rgba(0, 0, 0, 0.16) 0px 3px 6px,
+ rgba(0, 0, 0, 0.23) 0px 3px 6px;
+ transition: 0.3s ease-in-out;
}
.collapse-menu-left {
- margin-left: -50px;
+ margin-left: -50px;
}
.collapse-menu-right {
- margin-right: -200px;
+ margin-right: -200px;
}
.sidepanel-left span {
- position: relative;
- display: block;
+ position: relative;
+ display: block;
}
.sidepanel-right span {
- position: relative;
- display: block;
+ position: relative;
+ display: block;
}
.circle-left {
- position: absolute;
- width: 50px;
- height: 50px;
- -webkit-clip-path: polygon(100% 0, 0 0, 0 100%);
- clip-path: ellipse(68% 50% at 6% 50%);
- font-size: 20px;
- background-color: var(--main-color3);
- color: var(--main-color2);
- justify-content: left;
- top: 32px;
- left: 50px;
- cursor: pointer;
- display: flex;
- z-index: 2;
- transition: 0.3s ease-in-out;
+ position: absolute;
+ width: 50px;
+ height: 50px;
+ -webkit-clip-path: polygon(100% 0, 0 0, 0 100%);
+ clip-path: ellipse(68% 50% at 6% 50%);
+ font-size: 20px;
+ background-color: var(--main-color3);
+ color: var(--main-color2);
+ justify-content: left;
+ top: 32px;
+ left: 50px;
+ cursor: pointer;
+ display: flex;
+ z-index: 2;
+ transition: 0.3s ease-in-out;
}
.collapse-circle-left {
- left: 0px;
+ left: 0px;
}
.circle-right {
- position: absolute;
- width: 50px;
- height: 50px;
- -webkit-clip-path: polygon(100% 100%, 0 0, 100% 0);
- clip-path: ellipse(68% 50% at 94% 50%);
- font-size: 20px;
- background-color: var(--main-color3);
- color: var(--main-color2);
- justify-content: right;
- top: 32px;
- right: 199px;
- cursor: pointer;
- display: flex;
- z-index: 1;
- transition: 0.3s ease-in-out;
+ position: absolute;
+ width: 50px;
+ height: 50px;
+ -webkit-clip-path: polygon(100% 100%, 0 0, 100% 0);
+ clip-path: ellipse(68% 50% at 94% 50%);
+ font-size: 20px;
+ background-color: var(--main-color3);
+ color: var(--main-color2);
+ justify-content: right;
+ top: 32px;
+ right: 199px;
+ cursor: pointer;
+ display: flex;
+ z-index: 1;
+ transition: 0.3s ease-in-out;
}
.collapse-circle-right {
- right: 0px;
+ right: 0px;
}
.fa-cog {
- align-items: center;
- align-self: center;
- margin-left: 7px;
+ align-items: center;
+ align-self: center;
+ margin-left: 7px;
}
.fa-eye {
- align-self: center;
- margin-right: 7px;
+ align-self: center;
+ margin-right: 7px;
}
#min-button {
- grid-column: 1;
+ grid-column: 1;
}
#max-button,
#restore-button {
- grid-column: 2;
+ grid-column: 2;
}
#close-button {
- grid-column: 3;
+ grid-column: 3;
}
#mini-container {
- width: 100%;
- height: 300px;
- display: flex;
- flex-direction: column;
- margin-bottom: 25px;
+ width: 100%;
+ height: 300px;
+ display: flex;
+ flex-direction: column;
+ margin-bottom: 25px;
}
#mini-main {
- display: flex;
- height: 100%;
- flex-direction: row;
+ display: flex;
+ height: 100%;
+ flex-direction: row;
}
#mini-top-bar {
- height: 30px;
- background-color: var(--top-bar-temp);
- /* border-top-left-radius: 20px;
+ height: 30px;
+ background-color: var(--top-bar-temp);
+ /* border-top-left-radius: 20px;
border-top-right-radius: 20px; */
}
#mini-left {
- flex: 1;
- background-color: var(--main-color1-temp);
- height: 100%;
+ flex: 1;
+ background-color: var(--main-color1-temp);
+ height: 100%;
}
#mini-mid {
- flex: 8;
- background-color: var(--mid-section-temp);
- height: 100%;
+ flex: 8;
+ background-color: var(--mid-section-temp);
+ height: 100%;
}
#mini-right {
- flex: 2;
- background-color: var(--main-color4-temp);
- height: 100%;
+ flex: 2;
+ background-color: var(--main-color4-temp);
+ height: 100%;
}
diff --git a/src/css/sliders.css b/src/css/sliders.css
index ce80bf7..3742d78 100644
--- a/src/css/sliders.css
+++ b/src/css/sliders.css
@@ -1,179 +1,195 @@
/*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;
+ /* 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));
+ --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));
+ --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));
+ --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));
+ --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);
+ -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;
+ 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(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #1a1a1a;
+ background:
+ linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat,
+ #1a1a1a;
}
input[type='range'].styled-slider.slider-progress2::-webkit-slider-runnable-track {
- background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #1a1a1a;
+ background:
+ linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat,
+ #1a1a1a;
}
input[type='range'].styled-slider.slider-progress3::-webkit-slider-runnable-track {
- background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #1a1a1a;
+ background:
+ linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat,
+ #1a1a1a;
}
input[type='range'].styled-slider.slider-progress4::-webkit-slider-runnable-track {
- background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #1a1a1a;
+ background:
+ linear-gradient(var(--main-color1), var(--main-color1)) 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;
+ 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: var(--main-color3);
- box-shadow: none;
+ height: 40px;
+ border: none;
+ border-radius: 20px;
+ background: var(--main-color3);
+ box-shadow: none;
}
input[type='range'].styled-slider.slider-progress1::-moz-range-track {
- background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #464646;
+ background:
+ linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat,
+ #464646;
}
input[type='range'].styled-slider.slider-progress2::-moz-range-track {
- background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #464646;
+ background:
+ linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat,
+ #464646;
}
input[type='range'].styled-slider.slider-progress3::-moz-range-track {
- background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #464646;
+ background:
+ linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat,
+ #464646;
}
input[type='range'].styled-slider.slider-progress4::-moz-range-track {
- background: linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat, #464646;
+ background:
+ linear-gradient(var(--main-color1), var(--main-color1)) 0 / var(--sx) 100% no-repeat,
+ #464646;
}
/*ms*/
input[type='range'].styled-slider::-ms-fill-upper {
- background: transparent;
- border-color: transparent;
+ background: transparent;
+ border-color: transparent;
}
input[type='range'].styled-slider::-ms-fill-lower {
- background: transparent;
- border-color: transparent;
+ 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;
+ 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: var(--main-color3);
- border: none;
- box-shadow: none;
- box-sizing: border-box;
+ height: 40px;
+ border-radius: 20px;
+ background: var(--main-color3);
+ 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: var(--main-color1);
- border: none;
- border-right-width: 0;
+ height: 40px;
+ border-radius: 1em 0 0 1em;
+ margin: -undefined 0 -undefined -undefined;
+ background: var(--main-color1);
+ 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: var(--main-color1);
- border: none;
- border-right-width: 0;
+ height: 40px;
+ border-radius: 1em 0 0 1em;
+ margin: -undefined 0 -undefined -undefined;
+ background: var(--main-color1);
+ 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: var(--main-color1);
- border: none;
- border-right-width: 0;
+ height: 40px;
+ border-radius: 1em 0 0 1em;
+ margin: -undefined 0 -undefined -undefined;
+ background: var(--main-color1);
+ 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: var(--main-color1);
- border: none;
- border-right-width: 0;
+ height: 40px;
+ border-radius: 1em 0 0 1em;
+ margin: -undefined 0 -undefined -undefined;
+ background: var(--main-color1);
+ border: none;
+ border-right-width: 0;
}
.inputBox {
- border: none;
- width: 38px;
- border-radius: 10px;
- text-align: center;
- font-size: 14pt;
- font-weight: bold;
+ 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 e0eaaff..8e71345 100644
--- a/src/css/tabs.css
+++ b/src/css/tabs.css
@@ -1,394 +1,398 @@
.viewer-list {
- background-color: var(--main-color4);
- height: 100%;
- flex: 1;
- font-size: 14px;
- height: 100%;
- display: block;
+ background-color: var(--main-color4);
+ height: 100%;
+ flex: 1;
+ font-size: 14px;
+ height: 100%;
+ display: block;
}
ul.no-bullets {
- list-style-type: none;
- list-style-position: outside;
- margin: 0%;
- padding: 0%;
- padding-left: 5px;
- text-align: left;
+ list-style-type: none;
+ list-style-position: outside;
+ margin: 0%;
+ padding: 0%;
+ padding-left: 5px;
+ text-align: left;
}
li {
- line-height: 1em;
+ line-height: 1em;
}
h1.titles {
- margin: 0px;
- padding: 0%;
- text-align: left;
- padding-left: 5px;
+ margin: 0px;
+ padding: 0%;
+ text-align: left;
+ padding-left: 5px;
}
main {
- background: var(--main-color1);
- box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
- display: flex;
- justify-content: space-between;
- height: 32px;
+ background: var(--main-color1);
+ box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
+ display: flex;
+ justify-content: space-between;
+ height: 32px;
}
main label {
- text-align: center;
- display: flex;
- justify-content: center;
- align-items: center;
+ text-align: center;
+ display: flex;
+ justify-content: center;
+ align-items: center;
}
p {
- font-size: 13px;
+ font-size: 13px;
}
main input {
- display: none;
+ display: none;
}
section {
- clear: both;
- padding-top: 10px;
- display: none;
- height: calc(100% - 60px);
+ clear: both;
+ padding-top: 10px;
+ display: none;
+ height: calc(100% - 60px);
}
.Basiclabel {
- font-weight: bold;
- font-size: 14px;
- display: block;
- float: left;
- flex: auto;
- font-size: 20px;
- padding: 0px 10px;
- width: 50px;
- align-self: baseline;
- text-align: center;
+ font-weight: bold;
+ font-size: 14px;
+ display: block;
+ float: left;
+ flex: auto;
+ font-size: 20px;
+ padding: 0px 10px;
+ width: 50px;
+ align-self: baseline;
+ text-align: center;
}
.scale {
- height: 2em;
- width: 2em;
- vertical-align: bottom;
+ height: 2em;
+ width: 2em;
+ vertical-align: bottom;
}
.tab {
- /* filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%); */
- align-items: flex-start;
- margin: auto;
- cursor: pointer;
+ /* filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%); */
+ align-items: flex-start;
+ margin: auto;
+ cursor: pointer;
}
input:checked + label {
- border-top-color: #ffb03d;
- border-right-color: #ddd;
- border-left-color: #ddd;
- border-bottom-color: transparent;
- text-decoration: none;
+ border-top-color: #ffb03d;
+ border-right-color: #ddd;
+ border-left-color: #ddd;
+ border-bottom-color: transparent;
+ text-decoration: none;
}
/* --------------------------------- */
.radius {
- border-radius: 5px;
+ border-radius: 5px;
}
.radius .tabx:active::before {
- border-radius: 5px !important;
+ border-radius: 5px !important;
}
.tabx-bar {
- background-color: var(--main-color1);
- /* padding: 5px; */
- box-shadow: 1px 4px 20px rgba(0, 0, 0, 0.2);
- display: flex;
- /* margin: 10px; */
- color: black;
- height: 50px;
+ background-color: var(--main-color1);
+ /* padding: 5px; */
+ box-shadow: 1px 4px 20px rgba(0, 0, 0, 0.2);
+ display: flex;
+ /* margin: 10px; */
+ color: black;
+ height: 50px;
}
.tabx-bar .tabx {
- box-sizing: border-box;
- text-decoration: none;
- color: inherit;
- width: 70px;
- height: 50px;
- background: inherit;
- display: inherit;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- position: relative;
- transition: all 0.3s;
+ box-sizing: border-box;
+ text-decoration: none;
+ color: inherit;
+ width: 70px;
+ height: 50px;
+ background: inherit;
+ display: inherit;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ position: relative;
+ transition: all 0.3s;
}
.tabx-bar .tabx::before {
- position: absolute;
- content: '';
- width: 26%;
- height: 13%;
- border-top-left-radius: 200px;
- border-top-right-radius: 200px;
- border-bottom: none;
- background-color: #607d8b;
- /* bottom: -8px; */
- opacity: 0;
- transition: all 0.3s ease-in-out;
+ position: absolute;
+ content: '';
+ width: 26%;
+ height: 13%;
+ border-top-left-radius: 200px;
+ border-top-right-radius: 200px;
+ border-bottom: none;
+ background-color: #607d8b;
+ /* bottom: -8px; */
+ opacity: 0;
+ transition: all 0.3s ease-in-out;
}
.tabx-bar .tabx:active::before {
- width: 100%;
- height: 100%;
- background-color: #5fef8d;
- border-radius: 0;
+ width: 100%;
+ height: 100%;
+ background-color: #5fef8d;
+ border-radius: 0;
}
.tabx-bar .tabx:hover::before {
- opacity: 1;
- bottom: 0px;
+ opacity: 1;
+ bottom: 0px;
}
-.tabx-bar .tabx::after {
-}
+/* .tabx-bar .tabx::after {
+} */
.tabx-bar .tabx:hover {
- padding-bottom: 10px;
+ padding-bottom: 10px;
}
.tabx-bar .tabx:hover::after {
- opacity: 1;
- top: 6px;
+ opacity: 1;
+ top: 6px;
}
.tabx-bar .tabx.selected {
- background-color: rgba(0, 0, 0, 0.1);
- border-radius: inherit;
- padding-top: 0px;
+ background-color: rgba(0, 0, 0, 0.1);
+ border-radius: inherit;
+ padding-top: 0px;
}
.tabx-bar .tabx.selected::after {
- opacity: 1;
- top: -10px;
+ opacity: 1;
+ top: -10px;
}
.tabx-bar .tabx.selected::before {
- opacity: 1;
- bottom: 0px;
+ opacity: 1;
+ bottom: 0px;
}
.tabx-bar .tabx .icon {
- color: inherit;
- font-size: 24px;
- display: inherit;
+ color: inherit;
+ font-size: 24px;
+ display: inherit;
}
.tabx-bar .tabx .icon img {
- margin: auto;
- height: 32 px;
+ margin: auto;
+ height: 32 px;
}
.language {
- width: 80px;
- text-align: center;
+ width: 80px;
+ text-align: center;
}
#AdvancedMenu_mask {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- margin-top: 0px;
- width: 100%;
- height: 100%;
- visibility: hidden;
- overflow: auto;
- overflow-x: hidden;
- background-color: var(--mid-section);
- font-family: 'xxii_avenmedium';
- padding-left: 50px;
- padding-right: 50px;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ margin-top: 0px;
+ width: 100%;
+ height: 100%;
+ visibility: hidden;
+ overflow: auto;
+ overflow-x: hidden;
+ background-color: var(--mid-section);
+ font-family: 'xxii_avenmedium';
+ padding-left: 50px;
+ padding-right: 50px;
}
#ThemeCreator_mask {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- margin-top: 0px;
- width: 100%;
- height: 100%;
- visibility: hidden;
- flex-direction: column;
- justify-content: center;
- overflow: auto;
- overflow-x: hidden;
- background-color: var(--mid-section);
- font-family: 'xxii_avenmedium';
- padding-left: 50px;
- padding-right: 50px;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ margin-top: 0px;
+ width: 100%;
+ height: 100%;
+ visibility: hidden;
+ flex-direction: column;
+ justify-content: center;
+ overflow: auto;
+ overflow-x: hidden;
+ background-color: var(--mid-section);
+ font-family: 'xxii_avenmedium';
+ padding-left: 50px;
+ padding-right: 50px;
}
.fname {
- background: var(--main-color3);
- border: none;
- height: 40px;
- border-radius: 40px;
- width: 300px;
- outline: none;
- color: var(--main-color2);
- font-size: 10pt;
- padding-left: 10px;
+ background: var(--main-color3);
+ border: none;
+ height: 40px;
+ border-radius: 40px;
+ width: 300px;
+ outline: none;
+ color: var(--main-color2);
+ font-size: 10pt;
+ padding-left: 10px;
}
input[type='password'] {
- background: var(--main-color3);
- border: none;
- height: 40px;
- border-radius: 40px;
- width: 300px;
- outline: none;
- color: var(--main-color2);
- font-size: 10pt;
- padding-left: 10px;
- padding-right: 40px;
- /* To make space for the reveal button */
+ background: var(--main-color3);
+ border: none;
+ height: 40px;
+ border-radius: 40px;
+ width: 300px;
+ outline: none;
+ color: var(--main-color2);
+ font-size: 10pt;
+ padding-left: 10px;
+ padding-right: 40px;
+ /* To make space for the reveal button */
}
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;
+ 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;
- border-radius: 40px;
- width: 300px;
- outline: none;
- color: var(--main-color2);
- font-size: 10pt;
- padding-left: 10px;
- padding-right: 40px;
- /* To make space for the reveal button */
+ background: var(--main-color3);
+ border: none;
+ height: 40px;
+ border-radius: 40px;
+ width: 300px;
+ outline: none;
+ color: var(--main-color2);
+ font-size: 10pt;
+ padding-left: 10px;
+ padding-right: 40px;
+ /* To make space for the reveal button */
}
/* Style for the reveal button */
.password-toggle-btn {
- position: absolute;
- background-color: transparent;
- border: none;
- cursor: pointer;
- left: 450px;
+ position: absolute;
+ background-color: transparent;
+ border: none;
+ cursor: pointer;
+ left: 450px;
}
/* Hide the default appearance of the button */
.password-toggle-btn::-moz-focus-inner {
- border: 0;
+ border: 0;
}
/* Style the reveal icon (you can use your preferred icon or font) */
.password-toggle-icon {
- font-size: 16px;
- color: var(--main-color2);
+ font-size: 16px;
+ color: var(--main-color2);
}
#toasts {
- position: absolute;
- bottom: 20px;
- /* Adjust the distance from the bottom of the screen */
- right: 0%;
- /* Center the toasts horizontally */
- display: flex;
- flex-direction: column;
- z-index: 999;
+ position: absolute;
+ bottom: 20px;
+ /* Adjust the distance from the bottom of the screen */
+ right: 0%;
+ /* Center the toasts horizontally */
+ display: flex;
+ flex-direction: column;
+ z-index: 999;
}
.toast {
- background-color: #333;
- color: white;
- border-radius: 5px;
- padding: 1rem 2rem;
- margin: 0.5rem;
- opacity: 0;
- transform: translateY(100%);
- animation: toastAnimation 0.5s ease-in-out forwards, toastDisappear 0.5s ease-in-out 9s forwards;
+ background-color: #333;
+ color: white;
+ border-radius: 5px;
+ padding: 1rem 2rem;
+ margin: 0.5rem;
+ opacity: 0;
+ transform: translateY(100%);
+ animation:
+ toastAnimation 0.5s ease-in-out forwards,
+ toastDisappear 0.5s ease-in-out 9s forwards;
}
/* Apply different colors based on the toast type */
.info {
- background-color: lightblue !important;
+ background-color: lightblue !important;
}
.success {
- background-color: #2ecc71 !important;
+ background-color: #2ecc71 !important;
}
.warning {
- background-color: #f39c12 !important;
+ background-color: #f39c12 !important;
}
.error {
- background-color: #e74c3c !important;
+ background-color: #e74c3c !important;
}
/* CSS animation for the toast appearance */
@keyframes toastAnimation {
- from {
- opacity: 0;
- transform: translateY(100%);
- }
+ from {
+ opacity: 0;
+ transform: translateY(100%);
+ }
- to {
- opacity: 1;
- transform: translateY(0);
- }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
/* CSS animation for the toast disappearance */
@keyframes toastDisappear {
- from {
- opacity: 1;
- }
+ from {
+ opacity: 1;
+ }
- to {
- opacity: 0;
- }
+ to {
+ opacity: 0;
+ }
}
.menu-icon {
- font-size: 17pt;
+ font-size: 17pt;
}
.tooltip {
- position: absolute;
- display: inline-block;
- visibility: hidden;
- font-size: 12px;
- line-height: 20px;
- padding: 5px;
- background: var(--main-color3);
- border-radius: 5px;
- visibility: hidden;
- opacity: 1;
- box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.2);
- transition: opacity 0.3s, visibility 0s;
- color: var(--main-color2);
- font-family: 'xxii_avenmedium';
- z-index: 999;
+ position: absolute;
+ display: inline-block;
+ visibility: hidden;
+ font-size: 12px;
+ line-height: 20px;
+ padding: 5px;
+ background: var(--main-color3);
+ border-radius: 5px;
+ visibility: hidden;
+ opacity: 1;
+ box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.2);
+ transition:
+ opacity 0.3s,
+ visibility 0s;
+ color: var(--main-color2);
+ font-family: 'xxii_avenmedium';
+ z-index: 999;
}
/* .tooltip .tooltiptext {
@@ -413,29 +417,29 @@ input[type='lol'] {
} */
div[type='text']:disabled {
- background: #4b4b4b;
- display: none;
+ background: #4b4b4b;
+ display: none;
}
input[type='text']:disabled {
- background: #4b4b4b;
+ background: #4b4b4b;
}
button[type='text']:disabled {
- background: #4b4b4b;
- display: none;
+ background: #4b4b4b;
+ display: none;
}
input[type2='text']:disabled {
- background: #4b4b4b;
+ background: #4b4b4b;
}
div:disabled {
- background: #4b4b4b;
- filter: brightness(200%);
+ background: #4b4b4b;
+ filter: brightness(200%);
}
div:disabled {
- background: #4b4b4b;
- filter: brightness(200%);
+ background: #4b4b4b;
+ filter: brightness(200%);
}
diff --git a/src/css/tts-menu.css b/src/css/tts-menu.css
index fd36954..77f8b99 100644
--- a/src/css/tts-menu.css
+++ b/src/css/tts-menu.css
@@ -1,161 +1,169 @@
#tstx {
- display: flex;
- flex-direction: row;
- margin-left: 40px;
+ display: flex;
+ flex-direction: row;
+ margin-left: 40px;
}
.optionrow {
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: center;
- justify-content: left;
- margin-bottom: 10px;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ justify-content: left;
+ margin-bottom: 10px;
}
.LabelText {
- margin-bottom: 5px;
- color: var(--main-color2);
- margin: 0px 0px 5px 0px;
+ margin-bottom: 5px;
+ color: var(--main-color2);
+ margin: 0px 0px 5px 0px;
}
#volume-icon {
- color: var(--main-color2);
- scale: 0.75;
- cursor: pointer;
- text-align: center;
- align-self: center;
+ color: var(--main-color2);
+ scale: 0.75;
+ cursor: pointer;
+ text-align: center;
+ align-self: center;
}
#image {
- width: 100px;
- height: 100px;
- margin-bottom: 10px;
+ width: 100px;
+ height: 100px;
+ margin-bottom: 10px;
}
.TTSVolume {
- color: var(--main-color2);
- font-size: 12pt;
- text-align: center;
+ color: var(--main-color2);
+ font-size: 12pt;
+ text-align: center;
}
#SoundVolume {
- color: var(--main-color2);
- font-size: 12pt;
+ color: var(--main-color2);
+ font-size: 12pt;
}
.testLabel {
- color: var(--main-color2);
- font-size: 12pt;
+ color: var(--main-color2);
+ font-size: 12pt;
}
textarea {
- height: 60px;
- padding: 5px;
- width: 300px;
- resize: none;
- border-radius: 5px;
- background: var(--main-color3);
- color: var(--main-color2);
- font-family: 'xxii_avenmedium';
- border: none;
+ height: 60px;
+ padding: 5px;
+ width: 300px;
+ resize: none;
+ border-radius: 5px;
+ background: var(--main-color3);
+ color: var(--main-color2);
+ font-family: 'xxii_avenmedium';
+ border: none;
}
.SaveConfig {
- align-content: center;
- display: flex;
- flex-direction: column;
- justify-content: center;
- color: var(--main-color2);
- margin-bottom: 10px;
+ align-content: center;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ color: var(--main-color2);
+ margin-bottom: 10px;
}
.SmallButton {
- color: var(--main-color2);
- width: 50px;
- cursor: pointer;
- text-shadow: 0 0 5px #070607, 0 0 5px #070607, 0 0 5px #070607;
- /* transition: all 0.15s ease-in-out; */
- text-align: center;
+ color: var(--main-color2);
+ width: 50px;
+ cursor: pointer;
+ text-shadow:
+ 0 0 5px #070607,
+ 0 0 5px #070607,
+ 0 0 5px #070607;
+ /* transition: all 0.15s ease-in-out; */
+ text-align: center;
}
.SmallButton:hover {
- /* color: var(--main-color1); */
- width: 50px;
- cursor: pointer;
- /* filter: brightness(150%); */
+ /* color: var(--main-color1); */
+ width: 50px;
+ cursor: pointer;
+ /* filter: brightness(150%); */
}
.SmallButton:active {
- color: var(--main-color1);
- transform: translateY(4px);
- text-shadow: 0 0 5px #000, 0 0 5px #000, 0 0 5px #000;
+ color: var(--main-color1);
+ transform: translateY(4px);
+ text-shadow:
+ 0 0 5px #000,
+ 0 0 5px #000,
+ 0 0 5px #000;
}
.AdvancedMenuButton {
- width: 300px;
- height: 40px;
- border-radius: 20px;
- background-color: var(--main-color3);
- color: var(--main-color2);
- padding: 0;
- border: none;
- font-family: 'xxii_avenmedium';
- font-size: 14pt;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
- transition: box-shadow 0.3s ease, background-color 0.3s ease;
- /* Add a smooth transition for box-shadow and background-color */
+ width: 300px;
+ height: 40px;
+ border-radius: 20px;
+ background-color: var(--main-color3);
+ color: var(--main-color2);
+ padding: 0;
+ border: none;
+ font-family: 'xxii_avenmedium';
+ font-size: 14pt;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ transition:
+ box-shadow 0.3s ease,
+ background-color 0.3s ease;
+ /* Add a smooth transition for box-shadow and background-color */
}
.AdvancedMenuButton:hover {
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
- background-color: var(--main-color3);
- filter: brightness(150%);
- /* Darken the background color on hover */
- cursor: pointer;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
+ background-color: var(--main-color3);
+ filter: brightness(150%);
+ /* Darken the background color on hover */
+ cursor: pointer;
}
.AdvancedMenuButton:active {
- transform: translateY(2px);
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
- background-color: var(--main-color3);
- /* Reset the background color on click */
+ transform: translateY(2px);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ background-color: var(--main-color3);
+ /* Reset the background color on click */
}
.AdvancedMenuIcon {
- filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%);
- align-items: flex-start;
- margin: auto;
- height: 24px;
- width: 24px;
+ filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(350deg) brightness(104%) contrast(101%);
+ align-items: flex-start;
+ margin: auto;
+ height: 24px;
+ width: 24px;
}
.AdvancedMenuIcon2 {
- align-items: flex-start;
- margin: auto;
- height: 24px;
- width: 24px;
+ align-items: flex-start;
+ margin: auto;
+ height: 24px;
+ width: 24px;
}
input:hover {
- filter: brightness(120%);
+ filter: brightness(120%);
}
select:hover {
- filter: brightness(120%);
+ filter: brightness(120%);
}
textarea:hover {
- filter: brightness(120%);
+ filter: brightness(120%);
}
label:hover {
- filter: brightness(120%);
+ filter: brightness(120%);
}
.circle-right:hover {
- filter: brightness(120%);
+ filter: brightness(120%);
}
.circle-left:hover {
- filter: brightness(120%);
+ filter: brightness(120%);
}
diff --git a/src/css/volume-slider.css b/src/css/volume-slider.css
index 15fc8d9..ff7242f 100644
--- a/src/css/volume-slider.css
+++ b/src/css/volume-slider.css
@@ -1,87 +1,87 @@
.middle {
- width: 100%;
- height: 50px;
- border-radius: 10px;
- display: flex;
- align-items: center;
+ width: 100%;
+ height: 50px;
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
}
.slider-container {
- width: 300px;
- height: 100%;
- position: relative;
+ width: 300px;
+ height: 100%;
+ position: relative;
}
.slider-container .bar {
- display: block;
- width: 100%;
- height: 100%;
- border-radius: 10px;
- background-color: var(--main-color3);
+ display: block;
+ width: 100%;
+ height: 100%;
+ border-radius: 10px;
+ background-color: var(--main-color3);
}
.slider-container .bar .fill {
- display: block;
- width: 50%;
- height: 100%;
- border-radius: inherit;
- background-color: var(--main-color1);
+ display: block;
+ width: 50%;
+ height: 100%;
+ border-radius: inherit;
+ background-color: var(--main-color1);
}
.slider-container .slider {
- position: absolute;
- top: 50%;
- -webkit-appearance: none;
- margin: 0;
- width: 100%;
- height: 0;
- border-radius: 5px;
- outline: none;
- background-color: transparent;
+ position: absolute;
+ top: 50%;
+ -webkit-appearance: none;
+ margin: 0;
+ width: 100%;
+ height: 0;
+ border-radius: 5px;
+ outline: none;
+ background-color: transparent;
}
.slider-container .slider::-webkit-slider-thumb {
- -webkit-appearance: none;
- width: 30px;
- height: 30px;
- background-color: var(--main-color2);
- border-top-left-radius: 50%;
- border-top-right-radius: 50%;
- border-bottom-right-radius: 50%;
- border-bottom-left-radius: 50%;
- transform: rotate(-45deg) translate(0%, 0%);
- cursor: pointer;
- outline: none;
- /* box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); */
- box-shadow: 0 0 3px rgb(0 0 0 / 10%);
- /* transition: .3s ease-in-out; */
+ -webkit-appearance: none;
+ width: 30px;
+ height: 30px;
+ background-color: var(--main-color2);
+ border-top-left-radius: 50%;
+ border-top-right-radius: 50%;
+ border-bottom-right-radius: 50%;
+ border-bottom-left-radius: 50%;
+ transform: rotate(-45deg) translate(0%, 0%);
+ cursor: pointer;
+ outline: none;
+ /* box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); */
+ box-shadow: 0 0 3px rgb(0 0 0 / 10%);
+ /* transition: .3s ease-in-out; */
}
.slider-container .slider:active::-webkit-slider-thumb,
.slider-container .slider::-webkit-slider-thumb:hover {
- border-bottom-left-radius: 0;
- transform: rotate(-45deg) translate(50%, -50%);
+ border-bottom-left-radius: 0;
+ transform: rotate(-45deg) translate(50%, -50%);
}
.slider-container .slider:active::-webkit-slider-thumb {
- box-shadow: 0 0 0 3px rgba(255, 255, 255, 1);
+ box-shadow: 0 0 0 3px rgba(255, 255, 255, 1);
}
.option-icon-container {
- display: flex;
- flex-direction: column;
- /* justify-content: center; */
- align-items: center;
- /* width: 78px; */
- /* float: right; */
- flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ /* justify-content: center; */
+ align-items: center;
+ /* width: 78px; */
+ /* float: right; */
+ flex-grow: 1;
}
.brush-icon-container {
- margin-left: -20px;
- font-size: 20pt;
+ margin-left: -20px;
+ font-size: 20pt;
}
.icon {
- fill: var(--main-color2);
+ fill: var(--main-color2);
}
diff --git a/src/index.html b/src/index.html
index 4a0caef..89111e2 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1,652 +1,670 @@
-
+
-
-
-
-
- LoquendoBot
+
+
+
+
+ LoquendoBot
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | Level |
- Message |
- Metadata |
- Timestamp |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Moderators
-
- Viewers
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | Level |
+ Message |
+ Metadata |
+ Timestamp |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Moderators
+
+ Viewers
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/js/amazon.js b/src/js/amazon.js
index fd2de7a..0ec9b52 100644
--- a/src/js/amazon.js
+++ b/src/js/amazon.js
@@ -1,118 +1,118 @@
+/* global settings, callback, addVoiceService, amazonVoices, */
+
const https = require('https');
const querystring = require('querystring');
const aws4 = require('aws4');
function getAmazonVoices() {
- if (!settings.AMAZON.USE_AMAZON) {
- callback();
- return;
- }
+ if (!settings.AMAZON.USE_AMAZON) {
+ callback();
+ return;
+ }
- addVoiceService('Amazon');
+ addVoiceService('Amazon');
- let primaryVoice = document.querySelector('#primaryAmazonVoice');
- let secondaryVoice = document.querySelector('#secondaryAmazonVoice');
+ const primaryVoice = document.querySelector('#primaryAmazonVoice');
+ const secondaryVoice = document.querySelector('#secondaryAmazonVoice');
- function setVoicesinSelect(voiceSelect) {
- const voices = Object.values(amazonVoices);
- voices.forEach((voice) => {
- const option = document.createElement('option');
- option.classList.add('option');
+ function setVoicesinSelect(voiceSelect) {
+ const voices = Object.values(amazonVoices);
+ voices.forEach(voice => {
+ const option = document.createElement('option');
+ option.classList.add('option');
- option.value = voice;
- option.innerHTML = voice;
+ option.value = voice;
+ option.innerHTML = voice;
- voiceSelect.appendChild(option);
- });
- }
- setVoicesinSelect(primaryVoice);
- primaryVoice.value = settings.AMAZON.PRIMARY_VOICE;
- setVoicesinSelect(secondaryVoice);
- secondaryVoice.value = settings.AMAZON.SECONDARY_VOICE;
+ voiceSelect.appendChild(option);
+ });
+ }
+ setVoicesinSelect(primaryVoice);
+ primaryVoice.value = settings.AMAZON.PRIMARY_VOICE;
+ setVoicesinSelect(secondaryVoice);
+ secondaryVoice.value = settings.AMAZON.SECONDARY_VOICE;
}
if (settings.AMAZON.USE_AMAZON) {
- getAmazonVoices();
+ getAmazonVoices();
}
class PollyTTS {
- constructor() {}
+ textToSpeech(options, callback) {
+ if (!options) {
+ return callback(new Error('Options are missing'));
+ }
- textToSpeech(options, callback) {
- if (!options) {
- return callback(new Error('Options are missing'));
+ const qs = {
+ Text: options.text,
+ TextType: options.textType || 'text',
+ VoiceId: options.voiceId || 'Mia',
+ SampleRate: options.sampleRate || 22050,
+ OutputFormat: options.outputFormat || 'mp3',
+ Engine: options.engine || 'neural'
+ };
+
+ const opts = {
+ service: 'polly',
+ region: options.region || 'us-east-1',
+ path: `/v1/speech?${querystring.stringify(qs)}`,
+ signQuery: true
+ };
+
+ // you can also pass AWS credentials in explicitly (otherwise taken from process.env)
+ aws4.sign(opts, this.credentials);
+ https
+ .get(opts, res => {
+ if (res.statusCode !== 200) {
+ return callback(new Error(`Request Failed. Status Code: ${res.statusCode}`));
+ }
+ callback(null, res);
+ return true;
+ })
+ .on('error', e => {
+ callback(e);
+ });
+
+ return null;
+ }
+
+ describeVoices(callback, credentials) {
+ this.credentials = credentials;
+ const qs = {
+ Engine: 'neural'
+ };
+
+ const opts = {
+ service: 'polly',
+ region: 'us-east-1',
+ path: `/v1/voices?${querystring.stringify(qs)}`,
+ signQuery: true
+ };
+
+ // you can also pass AWS credentials in explicitly (otherwise taken from process.env)
+ aws4.sign(opts, this.credentials);
+ https
+ .get(opts, res => {
+ if (res.statusCode !== 200) {
+ return callback(new Error(`Request Failed. Status Code: ${res.statusCode}`));
}
- const qs = {
- Text: options.text,
- TextType: options.textType || 'text',
- VoiceId: options.voiceId || 'Mia',
- SampleRate: options.sampleRate || 22050,
- OutputFormat: options.outputFormat || 'mp3',
- Engine: options.engine || 'neural',
- };
+ let body = '';
+ res.on('readable', () => {
+ body += res.read();
+ });
+ res.on('end', () => {
+ callback(null, body);
+ });
- const opts = {
- service: 'polly',
- region: options.region || 'us-east-1',
- path: `/v1/speech?${querystring.stringify(qs)}`,
- signQuery: true,
- };
+ return undefined;
+ })
+ .on('error', e => {
+ callback(e);
+ });
- // you can also pass AWS credentials in explicitly (otherwise taken from process.env)
- aws4.sign(opts, this.credentials);
- https
- .get(opts, (res) => {
- if (res.statusCode !== 200) {
- return callback(new Error(`Request Failed. Status Code: ${res.statusCode}`));
- }
- callback(null, res);
- return true;
- })
- .on('error', (e) => {
- callback(e);
- });
-
- return null;
- }
-
- describeVoices(callback, credentials) {
- this.credentials = credentials;
- const qs = {
- Engine: 'neural',
- };
-
- const opts = {
- service: 'polly',
- region: 'us-east-1',
- path: `/v1/voices?${querystring.stringify(qs)}`,
- signQuery: true,
- };
-
- // you can also pass AWS credentials in explicitly (otherwise taken from process.env)
- aws4.sign(opts, this.credentials);
- https
- .get(opts, (res) => {
- if (res.statusCode !== 200) {
- return callback(new Error(`Request Failed. Status Code: ${res.statusCode}`));
- }
-
- let body = '';
- res.on('readable', () => {
- body += res.read();
- });
- res.on('end', () => {
- callback(null, body);
- });
-
- return undefined;
- })
- .on('error', (e) => {
- callback(e);
- });
-
- return null;
- }
+ return null;
+ }
}
const pollyTTS = new PollyTTS();
diff --git a/src/js/auth.js b/src/js/auth.js
index ec2d6a8..926ea4b 100644
--- a/src/js/auth.js
+++ b/src/js/auth.js
@@ -1,103 +1,217 @@
+/* global settings, fs, settingsPath, ini, shell, options, axios */
+
const twitchAuthentication = () =>
- new Promise((resolve) => {
- const http = require('http');
- const redirectUri = 'http://localhost:1989/auth';
- const scopes = ['chat:edit', 'chat:read'];
+ 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 express = require('express');
+ const tempAuthServer = express();
+ const port = 1989;
- const { parse: parseQueryString } = require('querystring');
+ 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));
+ tempAuthServer.use(function (req, res, next) {
+ if (req.url !== '/auth') {
+ const token = parseQueryString(req.query.auth);
+ settings.TWITCH.OAUTH_TOKEN = token['#access_token'];
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
- resolve(token['#access_token']);
- 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(() => {});
- }
+ resolve(token['#access_token']);
+ 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(() => {});
+ }
+ });
+
function getTwitchUserId() {
- // Get user Logo with access token
- options = {
- method: 'GET',
- url: `https://api.twitch.tv/helix/users`,
- headers: { 'Client-ID': settings.TWITCH.CLIENT_ID, Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}` },
- };
+ // Get user Logo with access token
+ options = {
+ method: 'GET',
+ url: 'https://api.twitch.tv/helix/users',
+ headers: {
+ 'Client-ID': settings.TWITCH.CLIENT_ID,
+ Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}`
+ }
+ };
- axios
- .request(options)
- .then((responseLogoUrl) => {
- console.log(responseLogoUrl.data.data[0]);
- settings.TWITCH.USERNAME = responseLogoUrl.data.data[0].display_name;
- settings.TWITCH.USER_LOGO_URL = responseLogoUrl.data.data[0].profile_image_url;
- settings.TWITCH.USER_ID = responseLogoUrl.data.data[0].id;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- })
- .catch((error) => {
- console.error(error);
- });
-}
-function getTwitchOauthToken() {
- return twitchAuthentication().then((res) => {
- getTwitchUserId();
- return res;
+ axios
+ .request(options)
+ .then(responseLogoUrl => {
+ console.log(responseLogoUrl.data.data[0]);
+ settings.TWITCH.USERNAME = responseLogoUrl.data.data[0].display_name;
+ settings.TWITCH.USER_LOGO_URL = responseLogoUrl.data.data[0].profile_image_url;
+ settings.TWITCH.USER_ID = responseLogoUrl.data.data[0].id;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ })
+ .catch(error => {
+ console.error(error);
});
}
+function getTwitchSubscriptions(channelId) {
+ // Get user Logo with access token
+ options = {
+ method: 'GET',
+ url: `https://api.twitch.tv/helix/chat/emotes?broadcaster_id=${channelId}`,
+ headers: {
+ 'Client-ID': settings.TWITCH.CLIENT_ID,
+ Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}`
+ }
+ };
+
+ axios
+ .request(options)
+ .then(responseLogoUrl => {
+ console.log(responseLogoUrl);
+ })
+ .catch(error => {
+ console.error(error);
+ });
+}
+
+function getTwitchChannelEmotes(channelId) {
+ // Get user Logo with access token
+ options = {
+ method: 'GET',
+ url: `https://api.twitch.tv/helix/chat/emotes?broadcaster_id=${channelId}`,
+ headers: {
+ 'Client-ID': settings.TWITCH.CLIENT_ID,
+ Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}`
+ }
+ };
+
+ axios
+ .request(options)
+ .then(responseLogoUrl => {
+ console.log(responseLogoUrl);
+ })
+ .catch(error => {
+ console.error(error);
+ });
+}
+
+function getTwitchChannelFollows(channelId) {
+ // Get user Logo with access token
+ options = {
+ method: 'GET',
+ url: 'https://api.twitch.tv/helix/streams/followed',
+ headers: {
+ 'Client-ID': settings.TWITCH.CLIENT_ID,
+ Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}`
+ }
+ };
+
+ axios
+ .request(options)
+ .then(responseLogoUrl => {
+ console.log(responseLogoUrl);
+ })
+ .catch(error => {
+ console.error(error);
+ });
+}
+
+function getTwitchChannelSubscriptions(channelId) {
+ // Get user Logo with access token
+ options = {
+ method: 'GET',
+ url: `https://api.twitch.tv/helix/chat/emotes?broadcaster_id=${channelId}`,
+ headers: {
+ 'Client-ID': settings.TWITCH.CLIENT_ID,
+ Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}`
+ }
+ };
+
+ axios
+ .request(options)
+ .then(responseLogoUrl => {
+ console.log(responseLogoUrl);
+ })
+ .catch(error => {
+ console.error(error);
+ });
+}
+
+function getTwitchChannelId() {
+ // Get user Logo with access token
+ options = {
+ method: 'GET',
+ url: 'https://api.twitch.tv/helix/users?login=MelvyCoral',
+ headers: {
+ 'Client-ID': settings.TWITCH.CLIENT_ID,
+ Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}`
+ }
+ };
+
+ axios
+ .request(options)
+ .then(responseLogoUrl => {
+ // console.log(responseLogoUrl);
+ getTwitchChannelEmotes(responseLogoUrl.data.data[0].id);
+ })
+ .catch(error => {
+ console.error(error);
+ });
+}
+
+function getTwitchOauthToken() {
+ // getTwitchChannelId();
+ getTwitchGLobalEmotes();
+ // return twitchAuthentication().then(res => {
+ // getTwitchUserId();
+ // return res;
+ // });
+}
+
module.exports = { getTwitchOauthToken };
diff --git a/src/js/backend.js b/src/js/backend.js
index e576585..8e5281e 100644
--- a/src/js/backend.js
+++ b/src/js/backend.js
@@ -1,167 +1,178 @@
+/* global settings, addVoiceService, internalVoices, ttsRequestCount, main, path, pythonPath, settingsPath, ipcRenderer */
+
const spawn = require('child_process').spawn;
-var kill = require('kill-process-by-name');
+const kill = require('kill-process-by-name');
let python;
async function getInstalledVoices() {
- if (!settings.TTS.USE_TTS) {
- return;
+ if (!settings.TTS.USE_TTS) {
+ return;
+ }
+ addVoiceService('Internal');
+
+ try {
+ const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/voices`, { method: 'GET' });
+ if (response.ok) {
+ const responseData = await response.json();
+ console.log('Response:', responseData);
+ internalVoices = responseData;
+ } else {
+ console.error('Failed to send termination signal to Flask server.');
}
- addVoiceService('Internal');
+ } catch (error) {
+ console.error('Error sending termination signal:', error);
+ }
- try {
- const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/voices`, { method: 'GET' });
- if (response.ok) {
- const responseData = await response.json();
- console.log('Response:', responseData);
- internalVoices = responseData;
- } else {
- console.error('Failed to send termination signal to Flask server.');
- }
- } catch (error) {
- console.error('Error sending termination signal:', error);
- }
+ const primaryVoice = document.querySelector('#primaryVoice');
+ const secondaryVoice = document.querySelector('#secondaryVoice');
- let primaryVoice = document.querySelector('#primaryVoice');
- let secondaryVoice = document.querySelector('#secondaryVoice');
+ function setVoicesinSelect(voiceSelect) {
+ const voices = Object.values(internalVoices.voices);
+ voices.forEach(voice => {
+ const option = document.createElement('option');
+ option.classList.add('option');
- function setVoicesinSelect(voiceSelect) {
- const voices = Object.values(internalVoices.voices);
- voices.forEach((voice) => {
- const option = document.createElement('option');
- option.classList.add('option');
+ option.value = voice;
+ option.innerHTML = voice;
- option.value = voice;
- option.innerHTML = voice;
-
- voiceSelect.appendChild(option);
- });
- }
- setVoicesinSelect(primaryVoice);
- primaryVoice.value = settings.TTS.PRIMARY_VOICE;
- setVoicesinSelect(secondaryVoice);
- secondaryVoice.value = settings.TTS.SECONDARY_VOICE;
+ voiceSelect.appendChild(option);
+ });
+ }
+ setVoicesinSelect(primaryVoice);
+ primaryVoice.value = settings.TTS.PRIMARY_VOICE;
+ setVoicesinSelect(secondaryVoice);
+ secondaryVoice.value = settings.TTS.SECONDARY_VOICE;
}
async function getBackendServerStatus() {
- try {
- const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/status`, { method: 'GET' });
- if (response.ok) {
- const responseData = await response.json();
- console.log('Response:', responseData);
- } else {
- console.error('Failed to send termination signal to Flask server.');
- }
- } catch (error) {
- console.error('Error sending termination signal:', error);
+ console.log('getting status');
+ try {
+ const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/status`, { method: 'GET' });
+ if (response.ok) {
+ const responseData = await response.json();
+ console.log('Response:', responseData);
+ } else {
+ console.error('Failed to send termination signal to Flask server.');
}
+ } catch (error) {
+ console.error('Error sending termination signal:', error);
+ }
}
function startSTT() {
- const eventSource = new EventSource('http://127.0.0.1:9000/stream');
+ const eventSource = new EventSource('http://127.0.0.1:9000/stream');
- eventSource.addEventListener('message', (event) => {
- const result = event.data;
- console.log(result); // Log the received data
- });
+ eventSource.addEventListener('message', event => {
+ const result = event.data;
+ console.log(result); // Log the received data
+ });
- eventSource.addEventListener('error', (event) => {
- console.error('EventSource failed:', event);
+ eventSource.addEventListener('error', event => {
+ console.error('EventSource failed:', event);
- eventSource.close();
- });
+ eventSource.close();
+ });
- window.addEventListener('beforeunload', () => {
- eventSource.close();
- });
+ window.addEventListener('beforeunload', () => {
+ eventSource.close();
+ });
}
async function getInternalTTSAudio(requestData) {
- ttsRequestCount++;
- requestData.count = ttsRequestCount;
- const requestOptions = {
- method: 'POST', // HTTP method
- headers: {
- 'Content-Type': 'application/json', // Specify the content type
- },
- body: JSON.stringify(requestData), // Convert the data to JSON and include it in the request body
- };
+ ttsRequestCount++;
+ requestData.count = ttsRequestCount;
+ const requestOptions = {
+ method: 'POST', // HTTP method
+ headers: {
+ 'Content-Type': 'application/json' // Specify the content type
+ },
+ body: JSON.stringify(requestData) // Convert the data to JSON and include it in the request body
+ };
- try {
- const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/audio`, requestOptions);
- if (response.ok) {
- const responseData = await response.json();
- console.log('Response:', responseData);
- return ttsRequestCount;
- } else {
- console.error('Failed to send termination signal to Flask server.');
- }
- } catch (error) {
- console.error('Error sending termination signal:', error);
+ try {
+ const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/audio`, requestOptions);
+ if (response.ok) {
+ const responseData = await response.json();
+ console.log('Response:', responseData);
+ return ttsRequestCount;
+ } else {
+ console.error('Failed to send termination signal to Flask server.');
}
+ } catch (error) {
+ console.error('Error sending termination signal:', error);
+ }
}
const createBackendServer = () =>
- new Promise((resolve) => {
- if (main.isPackaged) {
- python = spawn(path.join(pythonPath, './loquendoBot_backend.exe'), [settingsPath, 'prod']);
- } else {
- python = spawn('python', ['-u', path.join(pythonPath, './loquendoBot_backend.py'), settingsPath, 'dev']);
- }
- // Capture the stdout of the Python process
- python.stdout.on('data', (data) => {
- console.info(`${data}`);
- });
-
- // Capture the stderr of the Python process
- python.stderr.on('data', (data) => {
- console.error(`${data}`);
- resolve('finished'); // cannot get it to resolve with stdout
- });
-
- // Listen for the Python process to exit
- python.on('close', (code) => {
- console.log(`Python process exited with code ${code}`);
- });
-
- if (typeof python.pid !== 'number') {
- console.log('failed');
- } else {
- console.log(`Spawned subprocess correctly!, PID = ${python.pid}`);
- }
+ new Promise(resolve => {
+ if (main.isPackaged) {
+ python = spawn(path.join(pythonPath, './loquendoBot_backend.exe'), [settingsPath, 'prod']);
+ } else {
+ python = spawn('python', ['-u', path.join(pythonPath, './loquendoBot_backend.py'), settingsPath, 'dev']);
+ }
+ // Capture the stdout of the Python process
+ python.stdout.on('data', data => {
+ console.info(`${data}`);
+ if (data.toString().startsWith('kees')) {
+ console.log('yess');
+ // getBackendServerStatus();
+ }
});
-async function initiateBackend() {
- try {
- createBackendServer().then(() => {
- getBackendServerStatus();
- getInstalledVoices();
- if (settings.STT.USE_STT) {
- startSTT();
- }
- });
- } catch (error) {
- console.error('Error during backend initialization:', error);
+ // Capture the stderr of the Python process
+ python.stderr.on('data', data => {
+ // console.error(`${data}`);
+ if (data.toString().startsWith('INFO:waitress:Serving on')) {
+ resolve('finished');
+ } else {
+ console.error(`${data}`);
+ }
+ });
+
+ // Listen for the Python process to exit
+ python.on('close', code => {
+ console.log(`Python process exited with code ${code}`);
+ });
+
+ if (typeof python.pid !== 'number') {
+ console.log('failed');
+ } else {
+ // console.log(`Spawned subprocess correctly!, PID = ${python.pid}`);
}
+ });
+
+async function initiateBackend() {
+ try {
+ createBackendServer().then(() => {
+ getBackendServerStatus();
+ getInstalledVoices();
+ if (settings.STT.USE_STT) {
+ startSTT();
+ }
+ });
+ } catch (error) {
+ console.error('Error during backend initialization:', error);
+ }
}
initiateBackend();
-//TODO: convert to restartServer function
+// TODO: convert to restartServer function
ipcRenderer.on('quit-event', async () => {
- try {
- const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/terminate`, { method: 'GET' });
- if (response.ok) {
- const responseData = await response.json();
- console.log('Response:', responseData);
- kill('loquendoBot_backend');
- } else {
- console.error('Failed to send termination signal to Flask server.');
- kill('loquendoBot_backend');
- }
- } catch (error) {
- console.error('Error sending termination signal:', error);
- kill('loquendoBot_backend');
+ try {
+ const response = await fetch(`http://127.0.0.1:${settings.GENERAL.PORT}/terminate`, { method: 'GET' });
+ if (response.ok) {
+ const responseData = await response.json();
+ console.log('Response:', responseData);
+ kill('loquendoBot_backend');
+ } else {
+ console.error('Failed to send termination signal to Flask server.');
+ kill('loquendoBot_backend');
}
+ } catch (error) {
+ console.error('Error sending termination signal:', error);
+ kill('loquendoBot_backend');
+ }
});
module.exports = { getInternalTTSAudio };
diff --git a/src/js/chat.js b/src/js/chat.js
index e4ad9de..ebc8eda 100644
--- a/src/js/chat.js
+++ b/src/js/chat.js
@@ -1,54 +1,76 @@
-function getResponse() {
- const userText = document.querySelector('#textInput').value;
+/* global messageTemplates, emojiPicker, settings, getPostTime, showChatMessage, twitch */
- // If nothing is written don't do anything
- if (userText === '') {
- return;
- }
+async function getResponse() {
+ const userText = document.querySelector('#textInput').value;
- // Create chat message from received data
- const article = document.createElement('article');
- article.className = 'msg-container user';
+ // If nothing is written don't do anything
+ if (userText === '') {
+ return;
+ }
- article.innerHTML = messageTemplates.userTemplate;
+ // Create chat message from received data
+ const article = document.createElement('article');
+ article.className = 'msg-container user';
- const userImg = article.querySelector('.user-img');
- if (userImg) {
- userImg.src = settings.TWITCH.USER_LOGO_URL;
- }
+ article.innerHTML = messageTemplates.userTemplate;
- const postTime = article.querySelector('.post-time');
+ const userImg = article.querySelector('.user-img');
+ if (userImg) {
+ userImg.src = settings.TWITCH.USER_LOGO_URL;
+ }
- if (postTime) {
- postTime.innerText = getPostTime();
- }
+ const postTime = article.querySelector('.post-time');
- article.appendChild(postTime);
+ if (postTime) {
+ postTime.innerText = getPostTime();
+ }
- const msg = article.querySelector('.msg-box');
- if (msg) {
- msg.innerText = userText;
- }
+ article.appendChild(postTime);
- // Appends the message to the main chat box (shows the message)
- showChatMessage(article, true);
+ const msg = article.querySelector('.msg-box');
+ if (msg) {
+ console.log(0);
+ await replaceChatMessageWithCustomEmojis(userText).then(data => {
+ // console.log(data);
+ msg.innerHTML = data;
- twitch.sendMessage(userText);
+ // Appends the message to the main chat box (shows the message)
+ showChatMessage(article);
- // Empty input box after sending message
- document.body.querySelector('#textInput').value = '';
+ twitch.sendMessage(userText);
+
+ // Empty input box after sending message
+ document.body.querySelector('#textInput').value = '';
+ });
+ }
}
+const replaceChatMessageWithCustomEmojis = message =>
+ new Promise(resolve => {
+ const words = message.split(' ');
+ words.forEach(async word => {
+ if (word !== '') {
+ await emojiPicker.database.getEmojiByUnicodeOrName(word).then(data => {
+ if (data && data.name === word) {
+ const url = `
`;
+ message = message.replace(word, url);
+ }
+ });
+ resolve(message);
+ }
+ });
+ });
+
// Function that will execute when you press 'enter' in the message box
-document.body.querySelector('#textInput').addEventListener('keydown', (e) => {
- if (e.which === 13) {
- getResponse();
- }
+document.body.querySelector('#textInput').addEventListener('keydown', e => {
+ if (e.which === 13) {
+ getResponse();
+ }
});
// Function that will execute when you click the 'send' button
document.body.querySelector('#SendButton').addEventListener('click', () => {
- getResponse();
+ getResponse();
});
// #endregion
@@ -57,21 +79,21 @@ document.body.querySelector('#SendButton').addEventListener('click', () => {
// Left panel
document.body.querySelector('.circle-left').addEventListener('click', () => {
- const menu = document.body.querySelector('.sidepanel-left');
+ const menu = document.body.querySelector('.sidepanel-left');
- if (menu.classList.contains('collapse-menu-left')) {
- menu.classList.remove('collapse-menu-left');
- } else {
- menu.classList.add('collapse-menu-left');
- }
+ if (menu.classList.contains('collapse-menu-left')) {
+ menu.classList.remove('collapse-menu-left');
+ } else {
+ menu.classList.add('collapse-menu-left');
+ }
- const leftCircle = document.body.querySelector('.circle-left');
+ const leftCircle = document.body.querySelector('.circle-left');
- if (leftCircle.classList.contains('collapse-circle-left')) {
- leftCircle.classList.remove('collapse-circle-left');
- } else {
- leftCircle.classList.add('collapse-circle-left');
- }
+ if (leftCircle.classList.contains('collapse-circle-left')) {
+ leftCircle.classList.remove('collapse-circle-left');
+ } else {
+ leftCircle.classList.add('collapse-circle-left');
+ }
});
// #region Show panels
@@ -80,27 +102,26 @@ document.body.querySelector('.circle-left').addEventListener('click', () => {
// TODO : optimize show panels
// Function that shows and hides the option panels. (TTS, Configuration, Commands)
const displayPanel = (panelSelectorClass, panelSelectorID, btnSelectorID) => {
- const btn = document.querySelector(btnSelectorID);
- const panel = document.querySelector(panelSelectorID);
- const panels = document.querySelectorAll(panelSelectorClass);
+ const btn = document.querySelector(btnSelectorID);
+ const panel = document.querySelector(panelSelectorID);
+ const panels = document.querySelectorAll(panelSelectorClass);
- btn.addEventListener(
- 'click',
- (event) => {
- event.stopPropagation();
- panels.forEach((el) => {
- if (el === panel) return;
- el.classList.remove('show');
- });
- if (panel.classList.contains('show')) {
- } else {
- panel.classList.add('show');
- }
- },
- {
- capture: true,
- },
- );
+ btn.addEventListener(
+ 'click',
+ event => {
+ event.stopPropagation();
+ panels.forEach(el => {
+ if (el === panel) return;
+ el.classList.remove('show');
+ });
+ if (!panel.classList.contains('show')) {
+ panel.classList.add('show');
+ }
+ },
+ {
+ capture: true
+ }
+ );
};
displayPanel('.OptionPanel', '#Configuration', '#btnConfiguration');
@@ -113,27 +134,26 @@ displayPanel('.OptionPanel', '#ChatCreator', '#btnChatCreator');
// #endregion
const displayPanelX = (panelSelectorClass, panelSelectorID, btnSelectorID) => {
- const btn = document.querySelector(btnSelectorID);
- const panel = document.querySelector(panelSelectorID);
- const panels = document.querySelectorAll(panelSelectorClass);
+ const btn = document.querySelector(btnSelectorID);
+ const panel = document.querySelector(panelSelectorID);
+ const panels = document.querySelectorAll(panelSelectorClass);
- btn.addEventListener(
- 'click',
- (event) => {
- event.stopPropagation();
- panels.forEach((el) => {
- if (el === panel) return;
- el.classList.remove('item-active');
- });
- if (panel.classList.contains('item-active')) {
- } else {
- panel.classList.add('item-active');
- }
- },
- {
- capture: true,
- },
- );
+ btn.addEventListener(
+ 'click',
+ event => {
+ event.stopPropagation();
+ panels.forEach(el => {
+ if (el === panel) return;
+ el.classList.remove('item-active');
+ });
+ if (!panel.classList.contains('item-active')) {
+ panel.classList.add('item-active');
+ }
+ },
+ {
+ capture: true
+ }
+ );
};
displayPanelX('.item', '#btnChat', '#btnChat');
diff --git a/src/js/customEmojis.js b/src/js/customEmojis.js
new file mode 100644
index 0000000..a1a951a
--- /dev/null
+++ b/src/js/customEmojis.js
@@ -0,0 +1,9 @@
+const customEmojis = [
+ {
+ name: 'sakuraestaKleefeliz',
+ shortcodes: ['sakuraestaKleefeliz'],
+ url: 'https://static-cdn.jtvnw.net/emoticons/v2/emotesv2_0cb536ddb6e143ab87ffeccb160a4d45/default/dark/1.0'
+ }
+];
+
+module.exports = { customEmojis };
diff --git a/src/js/google.js b/src/js/google.js
index 9edfa68..81774e6 100644
--- a/src/js/google.js
+++ b/src/js/google.js
@@ -1,31 +1,33 @@
+/* global settings, addVoiceService, googleVoices */
+
function getGoogleVoices() {
- if (!settings.GOOGLE.USE_GOOGLE) {
- return;
- }
+ if (!settings.GOOGLE.USE_GOOGLE) {
+ return;
+ }
- addVoiceService('Google');
+ addVoiceService('Google');
- let primaryVoice = document.querySelector('#primaryGoogleVoice');
- let secondaryVoice = document.querySelector('#secondaryGoogleVoice');
+ const primaryVoice = document.querySelector('#primaryGoogleVoice');
+ const secondaryVoice = document.querySelector('#secondaryGoogleVoice');
- function setVoicesinSelect(voiceSelect) {
- const voices = Object.values(googleVoices);
- voices.forEach((voice) => {
- const option = document.createElement('option');
- option.classList.add('option');
+ function setVoicesinSelect(voiceSelect) {
+ const voices = Object.values(googleVoices);
+ voices.forEach(voice => {
+ const option = document.createElement('option');
+ option.classList.add('option');
- option.value = voice;
- option.innerHTML = voice;
+ option.value = voice;
+ option.innerHTML = voice;
- voiceSelect.appendChild(option);
- });
- }
- setVoicesinSelect(primaryVoice);
- primaryVoice.value = settings.GOOGLE.PRIMARY_VOICE;
- setVoicesinSelect(secondaryVoice);
- secondaryVoice.value = settings.GOOGLE.SECONDARY_VOICE;
+ voiceSelect.appendChild(option);
+ });
+ }
+ setVoicesinSelect(primaryVoice);
+ primaryVoice.value = settings.GOOGLE.PRIMARY_VOICE;
+ setVoicesinSelect(secondaryVoice);
+ secondaryVoice.value = settings.GOOGLE.SECONDARY_VOICE;
}
if (settings.GOOGLE.USE_GOOGLE) {
- getGoogleVoices();
+ getGoogleVoices();
}
diff --git a/src/js/languages.js b/src/js/languages.js
index 3f7e0fc..91a16d9 100644
--- a/src/js/languages.js
+++ b/src/js/languages.js
@@ -1,331 +1,332 @@
// TODO: Enable STT:
-// Output STT to TTS? *TTS service selection* (for now, later add the option to choose a specific voice with mega dropdowns)
+// Output STT to TTS? *TTS service selection* (for now, later add the option to choose a specific voice with mega dropdowns)
// *automatic translation: make an translation.js and add ALL the texts and have it translated if user chooses a language in top bar
// *info page with credits, version and more info
const languages = {
- acehnese: { IETF: 'ace-ID', 'ISO-639': 'ace' },
- afrikaans: { IETF: 'af-ZA', 'ISO-639': 'af' },
- akan: { IETF: 'ak-GH', 'ISO-639': 'ak' },
- albanian: { IETF: 'sq-AL', 'ISO-639': 'sq' },
- amharic: { IETF: 'am-ET', 'ISO-639': 'am' },
- 'antigua and barbuda creole english': { IETF: 'aig-AG', 'ISO-639': 'aig' },
- arabic: { IETF: 'ar-SA', 'ISO-639': 'ar' },
- 'arabic egyptian': { IETF: 'ar-EG', 'ISO-639': 'ar' },
- aragonese: { IETF: 'an-ES', 'ISO-639': 'an' },
- armenian: { IETF: 'hy-AM', 'ISO-639': 'hy' },
- assamese: { IETF: 'as-IN', 'ISO-639': 'as' },
- asturian: { IETF: 'ast-ES', 'ISO-639': 'ast' },
- 'austrian german': { IETF: 'de-AT', 'ISO-639': 'de' },
- awadhi: { IETF: 'awa-IN', 'ISO-639': 'awa' },
- 'ayacucho quechua': { IETF: 'quy-PE', 'ISO-639': 'quy' },
- azerbaijani: { IETF: 'az-AZ', 'ISO-639': 'az' },
- 'bahamas creole english': { IETF: 'bah-BS', 'ISO-639': 'bah' },
- bajan: { IETF: 'bjs-BB', 'ISO-639': 'bjs' },
- balinese: { IETF: 'ban-ID', 'ISO-639': 'ban' },
- 'balkan gipsy': { IETF: 'rm-RO', 'ISO-639': 'rm' },
- bambara: { IETF: 'bm-ML', 'ISO-639': 'bm' },
- banjar: { IETF: 'bjn-ID', 'ISO-639': 'bjn' },
- bashkir: { IETF: 'ba-RU', 'ISO-639': 'ba' },
- basque: { IETF: 'eu-ES', 'ISO-639': 'eu' },
- belarusian: { IETF: 'be-BY', 'ISO-639': 'be' },
- 'belgian french': { IETF: 'fr-BE', 'ISO-639': 'fr' },
- bemba: { IETF: 'bem-ZM', 'ISO-639': 'bem' },
- bengali: { IETF: 'bn-IN', 'ISO-639': 'bn' },
- bhojpuri: { IETF: 'bho-IN', 'ISO-639': 'bho' },
- bihari: { IETF: 'bh-IN', 'ISO-639': 'bh' },
- bislama: { IETF: 'bi-VU', 'ISO-639': 'bi' },
- borana: { IETF: 'gax-KE', 'ISO-639': 'gax' },
- bosnian: { IETF: 'bs-BA', 'ISO-639': 'bs' },
- 'bosnian (cyrillic)': { IETF: 'bs-Cyrl-BA', 'ISO-639': 'bs' },
- breton: { IETF: 'br-FR', 'ISO-639': 'br' },
- buginese: { IETF: 'bug-ID', 'ISO-639': 'bug' },
- bulgarian: { IETF: 'bg-BG', 'ISO-639': 'bg' },
- burmese: { IETF: 'my-MM', 'ISO-639': 'my' },
- catalan: { IETF: 'ca-ES', 'ISO-639': 'ca' },
- 'catalan valencian': { IETF: 'cav-ES', 'ISO-639': 'cav' },
- cebuano: { IETF: 'ceb-PH', 'ISO-639': 'ceb' },
- 'central atlas tamazight': { IETF: 'tzm-MA', 'ISO-639': 'tzm' },
- 'central aymara': { IETF: 'ayr-BO', 'ISO-639': 'ayr' },
- 'central kanuri (latin script)': { IETF: 'knc-NG', 'ISO-639': 'knc' },
- 'chadian arabic': { IETF: 'shu-TD', 'ISO-639': 'shu' },
- chamorro: { IETF: 'ch-GU', 'ISO-639': 'ch' },
- cherokee: { IETF: 'chr-US', 'ISO-639': 'chr' },
- chhattisgarhi: { IETF: 'hne-IN', 'ISO-639': 'hne' },
- 'chinese simplified': { IETF: 'zh-CN', 'ISO-639': 'zh' },
- 'chinese trad. (hong kong)': { IETF: 'zh-HK', 'ISO-639': 'zh' },
- 'chinese traditional': { IETF: 'zh-TW', 'ISO-639': 'zh' },
- 'chinese traditional macau': { IETF: 'zh-MO', 'ISO-639': 'zh' },
- chittagonian: { IETF: 'ctg-BD', 'ISO-639': 'ctg' },
- chokwe: { IETF: 'cjk-AO', 'ISO-639': 'cjk' },
- 'classical greek': { IETF: 'grc-GR', 'ISO-639': 'grc' },
- 'comorian ngazidja': { IETF: 'zdj-KM', 'ISO-639': 'zdj' },
- coptic: { IETF: 'cop-EG', 'ISO-639': 'cop' },
- 'crimean tatar': { IETF: 'crh-RU', 'ISO-639': 'crh' },
- 'crioulo upper guinea': { IETF: 'pov-GW', 'ISO-639': 'pov' },
- croatian: { IETF: 'hr-HR', 'ISO-639': 'hr' },
- czech: { IETF: 'cs-CZ', 'ISO-639': 'cs' },
- danish: { IETF: 'da-DK', 'ISO-639': 'da' },
- dari: { IETF: 'prs-AF', 'ISO-639': 'prs' },
- dimli: { IETF: 'diq-TR', 'ISO-639': 'diq' },
- dutch: { IETF: 'nl-NL', 'ISO-639': 'nl' },
- dyula: { IETF: 'dyu-CI', 'ISO-639': 'dyu' },
- dzongkha: { IETF: 'dz-BT', 'ISO-639': 'dz' },
- 'eastern yiddish': { IETF: 'ydd-US', 'ISO-639': 'ydd' },
- emakhuwa: { IETF: 'vmw-MZ', 'ISO-639': 'vmw' },
- english: { IETF: 'en-GB', 'ISO-639': 'en' },
- 'english australia': { IETF: 'en-AU', 'ISO-639': 'en' },
- 'english canada': { IETF: 'en-CA', 'ISO-639': 'en' },
- 'english india': { IETF: 'en-IN', 'ISO-639': 'en' },
- 'english ireland': { IETF: 'en-IE', 'ISO-639': 'en' },
- 'english new zealand': { IETF: 'en-NZ', 'ISO-639': 'en' },
- 'english singapore': { IETF: 'en-SG', 'ISO-639': 'en' },
- 'english south africa': { IETF: 'en-ZA', 'ISO-639': 'en' },
- 'english us': { IETF: 'en-US', 'ISO-639': 'en' },
- esperanto: { IETF: 'eo-EU', 'ISO-639': 'eo' },
- estonian: { IETF: 'et-EE', 'ISO-639': 'et' },
- ewe: { IETF: 'ee-GH', 'ISO-639': 'ee' },
- fanagalo: { IETF: 'fn-FNG', 'ISO-639': 'fn' },
- faroese: { IETF: 'fo-FO', 'ISO-639': 'fo' },
- fijian: { IETF: 'fj-FJ', 'ISO-639': 'fj' },
- filipino: { IETF: 'fil-PH', 'ISO-639': 'fil' },
- finnish: { IETF: 'fi-FI', 'ISO-639': 'fi' },
- flemish: { IETF: 'nl-BE', 'ISO-639': 'nl' },
- fon: { IETF: 'fon-BJ', 'ISO-639': 'fon' },
- french: { IETF: 'fr-FR', 'ISO-639': 'fr' },
- 'french canada': { IETF: 'fr-CA', 'ISO-639': 'fr' },
- 'french swiss': { IETF: 'fr-CH', 'ISO-639': 'fr' },
- friulian: { IETF: 'fur-IT', 'ISO-639': 'fur' },
- fula: { IETF: 'ff-FUL', 'ISO-639': 'ff' },
- galician: { IETF: 'gl-ES', 'ISO-639': 'gl' },
- gamargu: { IETF: 'mfi-NG', 'ISO-639': 'mfi' },
- garo: { IETF: 'grt-IN', 'ISO-639': 'grt' },
- georgian: { IETF: 'ka-GE', 'ISO-639': 'ka' },
- german: { IETF: 'de-DE', 'ISO-639': 'de' },
- gilbertese: { IETF: 'gil-KI', 'ISO-639': 'gil' },
- glavda: { IETF: 'glw-NG', 'ISO-639': 'glw' },
- greek: { IETF: 'el-GR', 'ISO-639': 'el' },
- 'grenadian creole english': { IETF: 'gcl-GD', 'ISO-639': 'gcl' },
- guarani: { IETF: 'gn-PY', 'ISO-639': 'gn' },
- gujarati: { IETF: 'gu-IN', 'ISO-639': 'gu' },
- 'guyanese creole english': { IETF: 'gyn-GY', 'ISO-639': 'gyn' },
- 'haitian creole french': { IETF: 'ht-HT', 'ISO-639': 'ht' },
- 'halh mongolian': { IETF: 'khk-MN', 'ISO-639': 'khk' },
- hausa: { IETF: 'ha-NE', 'ISO-639': 'ha' },
- hawaiian: { IETF: 'haw-US', 'ISO-639': 'haw' },
- hebrew: { IETF: 'he-IL', 'ISO-639': 'he' },
- higi: { IETF: 'hig-NG', 'ISO-639': 'hig' },
- hiligaynon: { IETF: 'hil-PH', 'ISO-639': 'hil' },
- 'hill mari': { IETF: 'mrj-RU', 'ISO-639': 'mrj' },
- hindi: { IETF: 'hi-IN', 'ISO-639': 'hi' },
- hmong: { IETF: 'hmn-CN', 'ISO-639': 'hmn' },
- hungarian: { IETF: 'hu-HU', 'ISO-639': 'hu' },
- icelandic: { IETF: 'is-IS', 'ISO-639': 'is' },
- 'igbo ibo': { IETF: 'ibo-NG', 'ISO-639': 'ibo' },
- 'igbo ig': { IETF: 'ig-NG', 'ISO-639': 'ig' },
- ilocano: { IETF: 'ilo-PH', 'ISO-639': 'ilo' },
- indonesian: { IETF: 'id-ID', 'ISO-639': 'id' },
- 'inuktitut greenlandic': { IETF: 'kl-GL', 'ISO-639': 'kl' },
- 'irish gaelic': { IETF: 'ga-IE', 'ISO-639': 'ga' },
- italian: { IETF: 'it-IT', 'ISO-639': 'it' },
- 'italian swiss': { IETF: 'it-CH', 'ISO-639': 'it' },
- 'jamaican creole english': { IETF: 'jam-JM', 'ISO-639': 'jam' },
- japanese: { IETF: 'ja-JP', 'ISO-639': 'ja' },
- javanese: { IETF: 'jv-ID', 'ISO-639': 'jv' },
- jingpho: { IETF: 'kac-MM', 'ISO-639': 'kac' },
- "k'iche'": { IETF: 'quc-GT', 'ISO-639': 'quc' },
- 'kabiy�': { IETF: 'kbp-TG', 'ISO-639': 'kbp' },
- kabuverdianu: { IETF: 'kea-CV', 'ISO-639': 'kea' },
- kabylian: { IETF: 'kab-DZ', 'ISO-639': 'kab' },
- kalenjin: { IETF: 'kln-KE', 'ISO-639': 'kln' },
- kamba: { IETF: 'kam-KE', 'ISO-639': 'kam' },
- kannada: { IETF: 'kn-IN', 'ISO-639': 'kn' },
- kanuri: { IETF: 'kr-KAU', 'ISO-639': 'kr' },
- karen: { IETF: 'kar-MM', 'ISO-639': 'kar' },
- 'kashmiri (devanagari script)': { IETF: 'ks-IN', 'ISO-639': 'ks' },
- 'kashmiri (arabic script)': { IETF: 'kas-IN', 'ISO-639': 'kas' },
- kazakh: { IETF: 'kk-KZ', 'ISO-639': 'kk' },
- khasi: { IETF: 'kha-IN', 'ISO-639': 'kha' },
- khmer: { IETF: 'km-KH', 'ISO-639': 'km' },
- 'kikuyu kik': { IETF: 'kik-KE', 'ISO-639': 'kik' },
- 'kikuyu ki': { IETF: 'ki-KE', 'ISO-639': 'ki' },
- kimbundu: { IETF: 'kmb-AO', 'ISO-639': 'kmb' },
- kinyarwanda: { IETF: 'rw-RW', 'ISO-639': 'rw' },
- kirundi: { IETF: 'rn-BI', 'ISO-639': 'rn' },
- kisii: { IETF: 'guz-KE', 'ISO-639': 'guz' },
- kongo: { IETF: 'kg-CG', 'ISO-639': 'kg' },
- konkani: { IETF: 'kok-IN', 'ISO-639': 'kok' },
- korean: { IETF: 'ko-KR', 'ISO-639': 'ko' },
- 'northern kurdish': { IETF: 'kmr-TR', 'ISO-639': 'kmr' },
- 'kurdish sorani': { IETF: 'ckb-IQ', 'ISO-639': 'ckb' },
- kyrgyz: { IETF: 'ky-KG', 'ISO-639': 'ky' },
- lao: { IETF: 'lo-LA', 'ISO-639': 'lo' },
- latgalian: { IETF: 'ltg-LV', 'ISO-639': 'ltg' },
- latin: { IETF: 'la-XN', 'ISO-639': 'la' },
- latvian: { IETF: 'lv-LV', 'ISO-639': 'lv' },
- ligurian: { IETF: 'lij-IT', 'ISO-639': 'lij' },
- limburgish: { IETF: 'li-NL', 'ISO-639': 'li' },
- lingala: { IETF: 'ln-LIN', 'ISO-639': 'ln' },
- lithuanian: { IETF: 'lt-LT', 'ISO-639': 'lt' },
- lombard: { IETF: 'lmo-IT', 'ISO-639': 'lmo' },
- 'luba-kasai': { IETF: 'lua-CD', 'ISO-639': 'lua' },
- luganda: { IETF: 'lg-UG', 'ISO-639': 'lg' },
- luhya: { IETF: 'luy-KE', 'ISO-639': 'luy' },
- luo: { IETF: 'luo-KE', 'ISO-639': 'luo' },
- luxembourgish: { IETF: 'lb-LU', 'ISO-639': 'lb' },
- maa: { IETF: 'mas-KE', 'ISO-639': 'mas' },
- macedonian: { IETF: 'mk-MK', 'ISO-639': 'mk' },
- magahi: { IETF: 'mag-IN', 'ISO-639': 'mag' },
- maithili: { IETF: 'mai-IN', 'ISO-639': 'mai' },
- malagasy: { IETF: 'mg-MG', 'ISO-639': 'mg' },
- malay: { IETF: 'ms-MY', 'ISO-639': 'ms' },
- malayalam: { IETF: 'ml-IN', 'ISO-639': 'ml' },
- maldivian: { IETF: 'dv-MV', 'ISO-639': 'dv' },
- maltese: { IETF: 'mt-MT', 'ISO-639': 'mt' },
- mandara: { IETF: 'mfi-CM', 'ISO-639': 'mfi' },
- manipuri: { IETF: 'mni-IN', 'ISO-639': 'mni' },
- 'manx gaelic': { IETF: 'gv-IM', 'ISO-639': 'gv' },
- maori: { IETF: 'mi-NZ', 'ISO-639': 'mi' },
- marathi: { IETF: 'mr-IN', 'ISO-639': 'mr' },
- margi: { IETF: 'mrt-NG', 'ISO-639': 'mrt' },
- mari: { IETF: 'mhr-RU', 'ISO-639': 'mhr' },
- marshallese: { IETF: 'mh-MH', 'ISO-639': 'mh' },
- mende: { IETF: 'men-SL', 'ISO-639': 'men' },
- meru: { IETF: 'mer-KE', 'ISO-639': 'mer' },
- mijikenda: { IETF: 'nyf-KE', 'ISO-639': 'nyf' },
- minangkabau: { IETF: 'min-ID', 'ISO-639': 'min' },
- mizo: { IETF: 'lus-IN', 'ISO-639': 'lus' },
- mongolian: { IETF: 'mn-MN', 'ISO-639': 'mn' },
- montenegrin: { IETF: 'sr-ME', 'ISO-639': 'sr' },
- morisyen: { IETF: 'mfe-MU', 'ISO-639': 'mfe' },
- 'moroccan arabic': { IETF: 'ar-MA', 'ISO-639': 'ar' },
- mossi: { IETF: 'mos-BF', 'ISO-639': 'mos' },
- ndau: { IETF: 'ndc-MZ', 'ISO-639': 'ndc' },
- ndebele: { IETF: 'nr-ZA', 'ISO-639': 'nr' },
- nepali: { IETF: 'ne-NP', 'ISO-639': 'ne' },
- 'nigerian fulfulde': { IETF: 'fuv-NG', 'ISO-639': 'fuv' },
- niuean: { IETF: 'niu-NU', 'ISO-639': 'niu' },
- 'north azerbaijani': { IETF: 'azj-AZ', 'ISO-639': 'azj' },
- sesotho: { IETF: 'nso-ZA', 'ISO-639': 'nso' },
- 'northern uzbek': { IETF: 'uzn-UZ', 'ISO-639': 'uzn' },
- 'norwegian bokm�l': { IETF: 'nb-NO', 'ISO-639': 'nb' },
- 'norwegian nynorsk': { IETF: 'nn-NO', 'ISO-639': 'nn' },
- nuer: { IETF: 'nus-SS', 'ISO-639': 'nus' },
- nyanja: { IETF: 'ny-MW', 'ISO-639': 'ny' },
- occitan: { IETF: 'oc-FR', 'ISO-639': 'oc' },
- 'occitan aran': { IETF: 'oc-ES', 'ISO-639': 'oc' },
- odia: { IETF: 'or-IN', 'ISO-639': 'or' },
- oriya: { IETF: 'ory-IN', 'ISO-639': 'ory' },
- urdu: { IETF: 'ur-PK', 'ISO-639': 'ur' },
- palauan: { IETF: 'pau-PW', 'ISO-639': 'pau' },
- pali: { IETF: 'pi-IN', 'ISO-639': 'pi' },
- pangasinan: { IETF: 'pag-PH', 'ISO-639': 'pag' },
- papiamentu: { IETF: 'pap-CW', 'ISO-639': 'pap' },
- pashto: { IETF: 'ps-PK', 'ISO-639': 'ps' },
- persian: { IETF: 'fa-IR', 'ISO-639': 'fa' },
- pijin: { IETF: 'pis-SB', 'ISO-639': 'pis' },
- 'plateau malagasy': { IETF: 'plt-MG', 'ISO-639': 'plt' },
- polish: { IETF: 'pl-PL', 'ISO-639': 'pl' },
- portuguese: { IETF: 'pt-PT', 'ISO-639': 'pt' },
- 'portuguese brazil': { IETF: 'pt-BR', 'ISO-639': 'pt' },
- potawatomi: { IETF: 'pot-US', 'ISO-639': 'pot' },
- punjabi: { IETF: 'pa-IN', 'ISO-639': 'pa' },
- 'punjabi (pakistan)': { IETF: 'pnb-PK', 'ISO-639': 'pnb' },
- quechua: { IETF: 'qu-PE', 'ISO-639': 'qu' },
- rohingya: { IETF: 'rhg-MM', 'ISO-639': 'rhg' },
- rohingyalish: { IETF: 'rhl-MM', 'ISO-639': 'rhl' },
- romanian: { IETF: 'ro-RO', 'ISO-639': 'ro' },
- romansh: { IETF: 'roh-CH', 'ISO-639': 'roh' },
- rundi: { IETF: 'run-BI', 'ISO-639': 'run' },
- russian: { IETF: 'ru-RU', 'ISO-639': 'ru' },
- 'saint lucian creole french': { IETF: 'acf-LC', 'ISO-639': 'acf' },
- samoan: { IETF: 'sm-WS', 'ISO-639': 'sm' },
- sango: { IETF: 'sg-CF', 'ISO-639': 'sg' },
- sanskrit: { IETF: 'sa-IN', 'ISO-639': 'sa' },
- santali: { IETF: 'sat-IN', 'ISO-639': 'sat' },
- sardinian: { IETF: 'sc-IT', 'ISO-639': 'sc' },
- 'scots gaelic': { IETF: 'gd-GB', 'ISO-639': 'gd' },
- sena: { IETF: 'seh-ZW', 'ISO-639': 'seh' },
- 'serbian cyrillic': { IETF: 'sr-Cyrl-RS', 'ISO-639': 'sr' },
- 'serbian latin': { IETF: 'sr-Latn-RS', 'ISO-639': 'sr' },
- 'seselwa creole french': { IETF: 'crs-SC', 'ISO-639': 'crs' },
- 'setswana (south africa)': { IETF: 'tn-ZA', 'ISO-639': 'tn' },
- shan: { IETF: 'shn-MM', 'ISO-639': 'shn' },
- shona: { IETF: 'sn-ZW', 'ISO-639': 'sn' },
- sicilian: { IETF: 'scn-IT', 'ISO-639': 'scn' },
- silesian: { IETF: 'szl-PL', 'ISO-639': 'szl' },
- 'sindhi snd': { IETF: 'snd-PK', 'ISO-639': 'snd' },
- 'sindhi sd': { IETF: 'sd-PK', 'ISO-639': 'sd' },
- sinhala: { IETF: 'si-LK', 'ISO-639': 'si' },
- slovak: { IETF: 'sk-SK', 'ISO-639': 'sk' },
- slovenian: { IETF: 'sl-SI', 'ISO-639': 'sl' },
- somali: { IETF: 'so-SO', 'ISO-639': 'so' },
- 'sotho southern': { IETF: 'st-LS', 'ISO-639': 'st' },
- 'south azerbaijani': { IETF: 'azb-AZ', 'ISO-639': 'azb' },
- 'southern pashto': { IETF: 'pbt-PK', 'ISO-639': 'pbt' },
- 'southwestern dinka': { IETF: 'dik-SS', 'ISO-639': 'dik' },
- spanish: { IETF: 'es-ES', 'ISO-639': 'es' },
- 'spanish argentina': { IETF: 'es-AR', 'ISO-639': 'es' },
- 'spanish colombia': { IETF: 'es-CO', 'ISO-639': 'es' },
- 'spanish latin america': { IETF: 'es-419', 'ISO-639': 'es' },
- 'spanish mexico': { IETF: 'es-MX', 'ISO-639': 'es' },
- 'spanish united states': { IETF: 'es-US', 'ISO-639': 'es' },
- 'sranan tongo': { IETF: 'srn-SR', 'ISO-639': 'srn' },
- 'standard latvian': { IETF: 'lvs-LV', 'ISO-639': 'lvs' },
- 'standard malay': { IETF: 'zsm-MY', 'ISO-639': 'zsm' },
- sundanese: { IETF: 'su-ID', 'ISO-639': 'su' },
- swahili: { IETF: 'sw-KE', 'ISO-639': 'sw' },
- swati: { IETF: 'ss-SZ', 'ISO-639': 'ss' },
- swedish: { IETF: 'sv-SE', 'ISO-639': 'sv' },
- 'swiss german': { IETF: 'de-CH', 'ISO-639': 'de' },
- 'syriac (aramaic)': { IETF: 'syc-TR', 'ISO-639': 'syc' },
- tagalog: { IETF: 'tl-PH', 'ISO-639': 'tl' },
- tahitian: { IETF: 'ty-PF', 'ISO-639': 'ty' },
- tajik: { IETF: 'tg-TJ', 'ISO-639': 'tg' },
- 'tamashek (tuareg)': { IETF: 'tmh-DZ', 'ISO-639': 'tmh' },
- tamasheq: { IETF: 'taq-ML', 'ISO-639': 'taq' },
- 'tamil india': { IETF: 'ta-IN', 'ISO-639': 'ta' },
- 'tamil sri lanka': { IETF: 'ta-LK', 'ISO-639': 'ta' },
- taroko: { IETF: 'trv-TW', 'ISO-639': 'trv' },
- tatar: { IETF: 'tt-RU', 'ISO-639': 'tt' },
- telugu: { IETF: 'te-IN', 'ISO-639': 'te' },
- tetum: { IETF: 'tet-TL', 'ISO-639': 'tet' },
- thai: { IETF: 'th-TH', 'ISO-639': 'th' },
- tibetan: { IETF: 'bo-CN', 'ISO-639': 'bo' },
- tigrinya: { IETF: 'ti-ET', 'ISO-639': 'ti' },
- 'tok pisin': { IETF: 'tpi-PG', 'ISO-639': 'tpi' },
- tokelauan: { IETF: 'tkl-TK', 'ISO-639': 'tkl' },
- tongan: { IETF: 'to-TO', 'ISO-639': 'to' },
- 'tosk albanian': { IETF: 'als-AL', 'ISO-639': 'als' },
- tsonga: { IETF: 'ts-ZA', 'ISO-639': 'ts' },
- tswa: { IETF: 'tsc-MZ', 'ISO-639': 'tsc' },
- tswana: { IETF: 'tn-BW', 'ISO-639': 'tn' },
- tumbuka: { IETF: 'tum-MW', 'ISO-639': 'tum' },
- turkish: { IETF: 'tr-TR', 'ISO-639': 'tr' },
- turkmen: { IETF: 'tk-TM', 'ISO-639': 'tk' },
- tuvaluan: { IETF: 'tvl-TV', 'ISO-639': 'tvl' },
- twi: { IETF: 'tw-GH', 'ISO-639': 'tw' },
- udmurt: { IETF: 'udm-RU', 'ISO-639': 'udm' },
- ukrainian: { IETF: 'uk-UA', 'ISO-639': 'uk' },
- uma: { IETF: 'ppk-ID', 'ISO-639': 'ppk' },
- umbundu: { IETF: 'umb-AO', 'ISO-639': 'umb' },
- 'uyghur uig': { IETF: 'uig-CN', 'ISO-639': 'uig' },
- 'uyghur ug': { IETF: 'ug-CN', 'ISO-639': 'ug' },
- uzbek: { IETF: 'uz-UZ', 'ISO-639': 'uz' },
- venetian: { IETF: 'vec-IT', 'ISO-639': 'vec' },
- vietnamese: { IETF: 'vi-VN', 'ISO-639': 'vi' },
- 'vincentian creole english': { IETF: 'svc-VC', 'ISO-639': 'svc' },
- 'virgin islands creole english': { IETF: 'vic-US', 'ISO-639': 'vic' },
- wallisian: { IETF: 'wls-WF', 'ISO-639': 'wls' },
- 'waray (philippines)': { IETF: 'war-PH', 'ISO-639': 'war' },
- welsh: { IETF: 'cy-GB', 'ISO-639': 'cy' },
- 'west central oromo': { IETF: 'gaz-ET', 'ISO-639': 'gaz' },
- 'western persian': { IETF: 'pes-IR', 'ISO-639': 'pes' },
- wolof: { IETF: 'wo-SN', 'ISO-639': 'wo' },
- xhosa: { IETF: 'xh-ZA', 'ISO-639': 'xh' },
- yiddish: { IETF: 'yi-YD', 'ISO-639': 'yi' },
- yoruba: { IETF: 'yo-NG', 'ISO-639': 'yo' },
- zulu: { IETF: 'zu-ZA', 'ISO-639': 'zu' },
+ none: { IETF: 'none', 'ISO-639': 'none' },
+ acehnese: { IETF: 'ace-ID', 'ISO-639': 'ace' },
+ afrikaans: { IETF: 'af-ZA', 'ISO-639': 'af' },
+ akan: { IETF: 'ak-GH', 'ISO-639': 'ak' },
+ albanian: { IETF: 'sq-AL', 'ISO-639': 'sq' },
+ amharic: { IETF: 'am-ET', 'ISO-639': 'am' },
+ 'antigua and barbuda creole english': { IETF: 'aig-AG', 'ISO-639': 'aig' },
+ arabic: { IETF: 'ar-SA', 'ISO-639': 'ar' },
+ 'arabic egyptian': { IETF: 'ar-EG', 'ISO-639': 'ar' },
+ aragonese: { IETF: 'an-ES', 'ISO-639': 'an' },
+ armenian: { IETF: 'hy-AM', 'ISO-639': 'hy' },
+ assamese: { IETF: 'as-IN', 'ISO-639': 'as' },
+ asturian: { IETF: 'ast-ES', 'ISO-639': 'ast' },
+ 'austrian german': { IETF: 'de-AT', 'ISO-639': 'de' },
+ awadhi: { IETF: 'awa-IN', 'ISO-639': 'awa' },
+ 'ayacucho quechua': { IETF: 'quy-PE', 'ISO-639': 'quy' },
+ azerbaijani: { IETF: 'az-AZ', 'ISO-639': 'az' },
+ 'bahamas creole english': { IETF: 'bah-BS', 'ISO-639': 'bah' },
+ bajan: { IETF: 'bjs-BB', 'ISO-639': 'bjs' },
+ balinese: { IETF: 'ban-ID', 'ISO-639': 'ban' },
+ 'balkan gipsy': { IETF: 'rm-RO', 'ISO-639': 'rm' },
+ bambara: { IETF: 'bm-ML', 'ISO-639': 'bm' },
+ banjar: { IETF: 'bjn-ID', 'ISO-639': 'bjn' },
+ bashkir: { IETF: 'ba-RU', 'ISO-639': 'ba' },
+ basque: { IETF: 'eu-ES', 'ISO-639': 'eu' },
+ belarusian: { IETF: 'be-BY', 'ISO-639': 'be' },
+ 'belgian french': { IETF: 'fr-BE', 'ISO-639': 'fr' },
+ bemba: { IETF: 'bem-ZM', 'ISO-639': 'bem' },
+ bengali: { IETF: 'bn-IN', 'ISO-639': 'bn' },
+ bhojpuri: { IETF: 'bho-IN', 'ISO-639': 'bho' },
+ bihari: { IETF: 'bh-IN', 'ISO-639': 'bh' },
+ bislama: { IETF: 'bi-VU', 'ISO-639': 'bi' },
+ borana: { IETF: 'gax-KE', 'ISO-639': 'gax' },
+ bosnian: { IETF: 'bs-BA', 'ISO-639': 'bs' },
+ 'bosnian (cyrillic)': { IETF: 'bs-Cyrl-BA', 'ISO-639': 'bs' },
+ breton: { IETF: 'br-FR', 'ISO-639': 'br' },
+ buginese: { IETF: 'bug-ID', 'ISO-639': 'bug' },
+ bulgarian: { IETF: 'bg-BG', 'ISO-639': 'bg' },
+ burmese: { IETF: 'my-MM', 'ISO-639': 'my' },
+ catalan: { IETF: 'ca-ES', 'ISO-639': 'ca' },
+ 'catalan valencian': { IETF: 'cav-ES', 'ISO-639': 'cav' },
+ cebuano: { IETF: 'ceb-PH', 'ISO-639': 'ceb' },
+ 'central atlas tamazight': { IETF: 'tzm-MA', 'ISO-639': 'tzm' },
+ 'central aymara': { IETF: 'ayr-BO', 'ISO-639': 'ayr' },
+ 'central kanuri (latin script)': { IETF: 'knc-NG', 'ISO-639': 'knc' },
+ 'chadian arabic': { IETF: 'shu-TD', 'ISO-639': 'shu' },
+ chamorro: { IETF: 'ch-GU', 'ISO-639': 'ch' },
+ cherokee: { IETF: 'chr-US', 'ISO-639': 'chr' },
+ chhattisgarhi: { IETF: 'hne-IN', 'ISO-639': 'hne' },
+ 'chinese simplified': { IETF: 'zh-CN', 'ISO-639': 'zh' },
+ 'chinese trad. (hong kong)': { IETF: 'zh-HK', 'ISO-639': 'zh' },
+ 'chinese traditional': { IETF: 'zh-TW', 'ISO-639': 'zh' },
+ 'chinese traditional macau': { IETF: 'zh-MO', 'ISO-639': 'zh' },
+ chittagonian: { IETF: 'ctg-BD', 'ISO-639': 'ctg' },
+ chokwe: { IETF: 'cjk-AO', 'ISO-639': 'cjk' },
+ 'classical greek': { IETF: 'grc-GR', 'ISO-639': 'grc' },
+ 'comorian ngazidja': { IETF: 'zdj-KM', 'ISO-639': 'zdj' },
+ coptic: { IETF: 'cop-EG', 'ISO-639': 'cop' },
+ 'crimean tatar': { IETF: 'crh-RU', 'ISO-639': 'crh' },
+ 'crioulo upper guinea': { IETF: 'pov-GW', 'ISO-639': 'pov' },
+ croatian: { IETF: 'hr-HR', 'ISO-639': 'hr' },
+ czech: { IETF: 'cs-CZ', 'ISO-639': 'cs' },
+ danish: { IETF: 'da-DK', 'ISO-639': 'da' },
+ dari: { IETF: 'prs-AF', 'ISO-639': 'prs' },
+ dimli: { IETF: 'diq-TR', 'ISO-639': 'diq' },
+ dutch: { IETF: 'nl-NL', 'ISO-639': 'nl' },
+ dyula: { IETF: 'dyu-CI', 'ISO-639': 'dyu' },
+ dzongkha: { IETF: 'dz-BT', 'ISO-639': 'dz' },
+ 'eastern yiddish': { IETF: 'ydd-US', 'ISO-639': 'ydd' },
+ emakhuwa: { IETF: 'vmw-MZ', 'ISO-639': 'vmw' },
+ english: { IETF: 'en-GB', 'ISO-639': 'en' },
+ 'english australia': { IETF: 'en-AU', 'ISO-639': 'en' },
+ 'english canada': { IETF: 'en-CA', 'ISO-639': 'en' },
+ 'english india': { IETF: 'en-IN', 'ISO-639': 'en' },
+ 'english ireland': { IETF: 'en-IE', 'ISO-639': 'en' },
+ 'english new zealand': { IETF: 'en-NZ', 'ISO-639': 'en' },
+ 'english singapore': { IETF: 'en-SG', 'ISO-639': 'en' },
+ 'english south africa': { IETF: 'en-ZA', 'ISO-639': 'en' },
+ 'english us': { IETF: 'en-US', 'ISO-639': 'en' },
+ esperanto: { IETF: 'eo-EU', 'ISO-639': 'eo' },
+ estonian: { IETF: 'et-EE', 'ISO-639': 'et' },
+ ewe: { IETF: 'ee-GH', 'ISO-639': 'ee' },
+ fanagalo: { IETF: 'fn-FNG', 'ISO-639': 'fn' },
+ faroese: { IETF: 'fo-FO', 'ISO-639': 'fo' },
+ fijian: { IETF: 'fj-FJ', 'ISO-639': 'fj' },
+ filipino: { IETF: 'fil-PH', 'ISO-639': 'fil' },
+ finnish: { IETF: 'fi-FI', 'ISO-639': 'fi' },
+ flemish: { IETF: 'nl-BE', 'ISO-639': 'nl' },
+ fon: { IETF: 'fon-BJ', 'ISO-639': 'fon' },
+ french: { IETF: 'fr-FR', 'ISO-639': 'fr' },
+ 'french canada': { IETF: 'fr-CA', 'ISO-639': 'fr' },
+ 'french swiss': { IETF: 'fr-CH', 'ISO-639': 'fr' },
+ friulian: { IETF: 'fur-IT', 'ISO-639': 'fur' },
+ fula: { IETF: 'ff-FUL', 'ISO-639': 'ff' },
+ galician: { IETF: 'gl-ES', 'ISO-639': 'gl' },
+ gamargu: { IETF: 'mfi-NG', 'ISO-639': 'mfi' },
+ garo: { IETF: 'grt-IN', 'ISO-639': 'grt' },
+ georgian: { IETF: 'ka-GE', 'ISO-639': 'ka' },
+ german: { IETF: 'de-DE', 'ISO-639': 'de' },
+ gilbertese: { IETF: 'gil-KI', 'ISO-639': 'gil' },
+ glavda: { IETF: 'glw-NG', 'ISO-639': 'glw' },
+ greek: { IETF: 'el-GR', 'ISO-639': 'el' },
+ 'grenadian creole english': { IETF: 'gcl-GD', 'ISO-639': 'gcl' },
+ guarani: { IETF: 'gn-PY', 'ISO-639': 'gn' },
+ gujarati: { IETF: 'gu-IN', 'ISO-639': 'gu' },
+ 'guyanese creole english': { IETF: 'gyn-GY', 'ISO-639': 'gyn' },
+ 'haitian creole french': { IETF: 'ht-HT', 'ISO-639': 'ht' },
+ 'halh mongolian': { IETF: 'khk-MN', 'ISO-639': 'khk' },
+ hausa: { IETF: 'ha-NE', 'ISO-639': 'ha' },
+ hawaiian: { IETF: 'haw-US', 'ISO-639': 'haw' },
+ hebrew: { IETF: 'he-IL', 'ISO-639': 'he' },
+ higi: { IETF: 'hig-NG', 'ISO-639': 'hig' },
+ hiligaynon: { IETF: 'hil-PH', 'ISO-639': 'hil' },
+ 'hill mari': { IETF: 'mrj-RU', 'ISO-639': 'mrj' },
+ hindi: { IETF: 'hi-IN', 'ISO-639': 'hi' },
+ hmong: { IETF: 'hmn-CN', 'ISO-639': 'hmn' },
+ hungarian: { IETF: 'hu-HU', 'ISO-639': 'hu' },
+ icelandic: { IETF: 'is-IS', 'ISO-639': 'is' },
+ 'igbo ibo': { IETF: 'ibo-NG', 'ISO-639': 'ibo' },
+ 'igbo ig': { IETF: 'ig-NG', 'ISO-639': 'ig' },
+ ilocano: { IETF: 'ilo-PH', 'ISO-639': 'ilo' },
+ indonesian: { IETF: 'id-ID', 'ISO-639': 'id' },
+ 'inuktitut greenlandic': { IETF: 'kl-GL', 'ISO-639': 'kl' },
+ 'irish gaelic': { IETF: 'ga-IE', 'ISO-639': 'ga' },
+ italian: { IETF: 'it-IT', 'ISO-639': 'it' },
+ 'italian swiss': { IETF: 'it-CH', 'ISO-639': 'it' },
+ 'jamaican creole english': { IETF: 'jam-JM', 'ISO-639': 'jam' },
+ japanese: { IETF: 'ja-JP', 'ISO-639': 'ja' },
+ javanese: { IETF: 'jv-ID', 'ISO-639': 'jv' },
+ jingpho: { IETF: 'kac-MM', 'ISO-639': 'kac' },
+ "k'iche'": { IETF: 'quc-GT', 'ISO-639': 'quc' },
+ 'kabiy�': { IETF: 'kbp-TG', 'ISO-639': 'kbp' },
+ kabuverdianu: { IETF: 'kea-CV', 'ISO-639': 'kea' },
+ kabylian: { IETF: 'kab-DZ', 'ISO-639': 'kab' },
+ kalenjin: { IETF: 'kln-KE', 'ISO-639': 'kln' },
+ kamba: { IETF: 'kam-KE', 'ISO-639': 'kam' },
+ kannada: { IETF: 'kn-IN', 'ISO-639': 'kn' },
+ kanuri: { IETF: 'kr-KAU', 'ISO-639': 'kr' },
+ karen: { IETF: 'kar-MM', 'ISO-639': 'kar' },
+ 'kashmiri (devanagari script)': { IETF: 'ks-IN', 'ISO-639': 'ks' },
+ 'kashmiri (arabic script)': { IETF: 'kas-IN', 'ISO-639': 'kas' },
+ kazakh: { IETF: 'kk-KZ', 'ISO-639': 'kk' },
+ khasi: { IETF: 'kha-IN', 'ISO-639': 'kha' },
+ khmer: { IETF: 'km-KH', 'ISO-639': 'km' },
+ 'kikuyu kik': { IETF: 'kik-KE', 'ISO-639': 'kik' },
+ 'kikuyu ki': { IETF: 'ki-KE', 'ISO-639': 'ki' },
+ kimbundu: { IETF: 'kmb-AO', 'ISO-639': 'kmb' },
+ kinyarwanda: { IETF: 'rw-RW', 'ISO-639': 'rw' },
+ kirundi: { IETF: 'rn-BI', 'ISO-639': 'rn' },
+ kisii: { IETF: 'guz-KE', 'ISO-639': 'guz' },
+ kongo: { IETF: 'kg-CG', 'ISO-639': 'kg' },
+ konkani: { IETF: 'kok-IN', 'ISO-639': 'kok' },
+ korean: { IETF: 'ko-KR', 'ISO-639': 'ko' },
+ 'northern kurdish': { IETF: 'kmr-TR', 'ISO-639': 'kmr' },
+ 'kurdish sorani': { IETF: 'ckb-IQ', 'ISO-639': 'ckb' },
+ kyrgyz: { IETF: 'ky-KG', 'ISO-639': 'ky' },
+ lao: { IETF: 'lo-LA', 'ISO-639': 'lo' },
+ latgalian: { IETF: 'ltg-LV', 'ISO-639': 'ltg' },
+ latin: { IETF: 'la-XN', 'ISO-639': 'la' },
+ latvian: { IETF: 'lv-LV', 'ISO-639': 'lv' },
+ ligurian: { IETF: 'lij-IT', 'ISO-639': 'lij' },
+ limburgish: { IETF: 'li-NL', 'ISO-639': 'li' },
+ lingala: { IETF: 'ln-LIN', 'ISO-639': 'ln' },
+ lithuanian: { IETF: 'lt-LT', 'ISO-639': 'lt' },
+ lombard: { IETF: 'lmo-IT', 'ISO-639': 'lmo' },
+ 'luba-kasai': { IETF: 'lua-CD', 'ISO-639': 'lua' },
+ luganda: { IETF: 'lg-UG', 'ISO-639': 'lg' },
+ luhya: { IETF: 'luy-KE', 'ISO-639': 'luy' },
+ luo: { IETF: 'luo-KE', 'ISO-639': 'luo' },
+ luxembourgish: { IETF: 'lb-LU', 'ISO-639': 'lb' },
+ maa: { IETF: 'mas-KE', 'ISO-639': 'mas' },
+ macedonian: { IETF: 'mk-MK', 'ISO-639': 'mk' },
+ magahi: { IETF: 'mag-IN', 'ISO-639': 'mag' },
+ maithili: { IETF: 'mai-IN', 'ISO-639': 'mai' },
+ malagasy: { IETF: 'mg-MG', 'ISO-639': 'mg' },
+ malay: { IETF: 'ms-MY', 'ISO-639': 'ms' },
+ malayalam: { IETF: 'ml-IN', 'ISO-639': 'ml' },
+ maldivian: { IETF: 'dv-MV', 'ISO-639': 'dv' },
+ maltese: { IETF: 'mt-MT', 'ISO-639': 'mt' },
+ mandara: { IETF: 'mfi-CM', 'ISO-639': 'mfi' },
+ manipuri: { IETF: 'mni-IN', 'ISO-639': 'mni' },
+ 'manx gaelic': { IETF: 'gv-IM', 'ISO-639': 'gv' },
+ maori: { IETF: 'mi-NZ', 'ISO-639': 'mi' },
+ marathi: { IETF: 'mr-IN', 'ISO-639': 'mr' },
+ margi: { IETF: 'mrt-NG', 'ISO-639': 'mrt' },
+ mari: { IETF: 'mhr-RU', 'ISO-639': 'mhr' },
+ marshallese: { IETF: 'mh-MH', 'ISO-639': 'mh' },
+ mende: { IETF: 'men-SL', 'ISO-639': 'men' },
+ meru: { IETF: 'mer-KE', 'ISO-639': 'mer' },
+ mijikenda: { IETF: 'nyf-KE', 'ISO-639': 'nyf' },
+ minangkabau: { IETF: 'min-ID', 'ISO-639': 'min' },
+ mizo: { IETF: 'lus-IN', 'ISO-639': 'lus' },
+ mongolian: { IETF: 'mn-MN', 'ISO-639': 'mn' },
+ montenegrin: { IETF: 'sr-ME', 'ISO-639': 'sr' },
+ morisyen: { IETF: 'mfe-MU', 'ISO-639': 'mfe' },
+ 'moroccan arabic': { IETF: 'ar-MA', 'ISO-639': 'ar' },
+ mossi: { IETF: 'mos-BF', 'ISO-639': 'mos' },
+ ndau: { IETF: 'ndc-MZ', 'ISO-639': 'ndc' },
+ ndebele: { IETF: 'nr-ZA', 'ISO-639': 'nr' },
+ nepali: { IETF: 'ne-NP', 'ISO-639': 'ne' },
+ 'nigerian fulfulde': { IETF: 'fuv-NG', 'ISO-639': 'fuv' },
+ niuean: { IETF: 'niu-NU', 'ISO-639': 'niu' },
+ 'north azerbaijani': { IETF: 'azj-AZ', 'ISO-639': 'azj' },
+ sesotho: { IETF: 'nso-ZA', 'ISO-639': 'nso' },
+ 'northern uzbek': { IETF: 'uzn-UZ', 'ISO-639': 'uzn' },
+ 'norwegian bokm�l': { IETF: 'nb-NO', 'ISO-639': 'nb' },
+ 'norwegian nynorsk': { IETF: 'nn-NO', 'ISO-639': 'nn' },
+ nuer: { IETF: 'nus-SS', 'ISO-639': 'nus' },
+ nyanja: { IETF: 'ny-MW', 'ISO-639': 'ny' },
+ occitan: { IETF: 'oc-FR', 'ISO-639': 'oc' },
+ 'occitan aran': { IETF: 'oc-ES', 'ISO-639': 'oc' },
+ odia: { IETF: 'or-IN', 'ISO-639': 'or' },
+ oriya: { IETF: 'ory-IN', 'ISO-639': 'ory' },
+ urdu: { IETF: 'ur-PK', 'ISO-639': 'ur' },
+ palauan: { IETF: 'pau-PW', 'ISO-639': 'pau' },
+ pali: { IETF: 'pi-IN', 'ISO-639': 'pi' },
+ pangasinan: { IETF: 'pag-PH', 'ISO-639': 'pag' },
+ papiamentu: { IETF: 'pap-CW', 'ISO-639': 'pap' },
+ pashto: { IETF: 'ps-PK', 'ISO-639': 'ps' },
+ persian: { IETF: 'fa-IR', 'ISO-639': 'fa' },
+ pijin: { IETF: 'pis-SB', 'ISO-639': 'pis' },
+ 'plateau malagasy': { IETF: 'plt-MG', 'ISO-639': 'plt' },
+ polish: { IETF: 'pl-PL', 'ISO-639': 'pl' },
+ portuguese: { IETF: 'pt-PT', 'ISO-639': 'pt' },
+ 'portuguese brazil': { IETF: 'pt-BR', 'ISO-639': 'pt' },
+ potawatomi: { IETF: 'pot-US', 'ISO-639': 'pot' },
+ punjabi: { IETF: 'pa-IN', 'ISO-639': 'pa' },
+ 'punjabi (pakistan)': { IETF: 'pnb-PK', 'ISO-639': 'pnb' },
+ quechua: { IETF: 'qu-PE', 'ISO-639': 'qu' },
+ rohingya: { IETF: 'rhg-MM', 'ISO-639': 'rhg' },
+ rohingyalish: { IETF: 'rhl-MM', 'ISO-639': 'rhl' },
+ romanian: { IETF: 'ro-RO', 'ISO-639': 'ro' },
+ romansh: { IETF: 'roh-CH', 'ISO-639': 'roh' },
+ rundi: { IETF: 'run-BI', 'ISO-639': 'run' },
+ russian: { IETF: 'ru-RU', 'ISO-639': 'ru' },
+ 'saint lucian creole french': { IETF: 'acf-LC', 'ISO-639': 'acf' },
+ samoan: { IETF: 'sm-WS', 'ISO-639': 'sm' },
+ sango: { IETF: 'sg-CF', 'ISO-639': 'sg' },
+ sanskrit: { IETF: 'sa-IN', 'ISO-639': 'sa' },
+ santali: { IETF: 'sat-IN', 'ISO-639': 'sat' },
+ sardinian: { IETF: 'sc-IT', 'ISO-639': 'sc' },
+ 'scots gaelic': { IETF: 'gd-GB', 'ISO-639': 'gd' },
+ sena: { IETF: 'seh-ZW', 'ISO-639': 'seh' },
+ 'serbian cyrillic': { IETF: 'sr-Cyrl-RS', 'ISO-639': 'sr' },
+ 'serbian latin': { IETF: 'sr-Latn-RS', 'ISO-639': 'sr' },
+ 'seselwa creole french': { IETF: 'crs-SC', 'ISO-639': 'crs' },
+ 'setswana (south africa)': { IETF: 'tn-ZA', 'ISO-639': 'tn' },
+ shan: { IETF: 'shn-MM', 'ISO-639': 'shn' },
+ shona: { IETF: 'sn-ZW', 'ISO-639': 'sn' },
+ sicilian: { IETF: 'scn-IT', 'ISO-639': 'scn' },
+ silesian: { IETF: 'szl-PL', 'ISO-639': 'szl' },
+ 'sindhi snd': { IETF: 'snd-PK', 'ISO-639': 'snd' },
+ 'sindhi sd': { IETF: 'sd-PK', 'ISO-639': 'sd' },
+ sinhala: { IETF: 'si-LK', 'ISO-639': 'si' },
+ slovak: { IETF: 'sk-SK', 'ISO-639': 'sk' },
+ slovenian: { IETF: 'sl-SI', 'ISO-639': 'sl' },
+ somali: { IETF: 'so-SO', 'ISO-639': 'so' },
+ 'sotho southern': { IETF: 'st-LS', 'ISO-639': 'st' },
+ 'south azerbaijani': { IETF: 'azb-AZ', 'ISO-639': 'azb' },
+ 'southern pashto': { IETF: 'pbt-PK', 'ISO-639': 'pbt' },
+ 'southwestern dinka': { IETF: 'dik-SS', 'ISO-639': 'dik' },
+ spanish: { IETF: 'es-ES', 'ISO-639': 'es' },
+ 'spanish argentina': { IETF: 'es-AR', 'ISO-639': 'es' },
+ 'spanish colombia': { IETF: 'es-CO', 'ISO-639': 'es' },
+ 'spanish latin america': { IETF: 'es-419', 'ISO-639': 'es' },
+ 'spanish mexico': { IETF: 'es-MX', 'ISO-639': 'es' },
+ 'spanish united states': { IETF: 'es-US', 'ISO-639': 'es' },
+ 'sranan tongo': { IETF: 'srn-SR', 'ISO-639': 'srn' },
+ 'standard latvian': { IETF: 'lvs-LV', 'ISO-639': 'lvs' },
+ 'standard malay': { IETF: 'zsm-MY', 'ISO-639': 'zsm' },
+ sundanese: { IETF: 'su-ID', 'ISO-639': 'su' },
+ swahili: { IETF: 'sw-KE', 'ISO-639': 'sw' },
+ swati: { IETF: 'ss-SZ', 'ISO-639': 'ss' },
+ swedish: { IETF: 'sv-SE', 'ISO-639': 'sv' },
+ 'swiss german': { IETF: 'de-CH', 'ISO-639': 'de' },
+ 'syriac (aramaic)': { IETF: 'syc-TR', 'ISO-639': 'syc' },
+ tagalog: { IETF: 'tl-PH', 'ISO-639': 'tl' },
+ tahitian: { IETF: 'ty-PF', 'ISO-639': 'ty' },
+ tajik: { IETF: 'tg-TJ', 'ISO-639': 'tg' },
+ 'tamashek (tuareg)': { IETF: 'tmh-DZ', 'ISO-639': 'tmh' },
+ tamasheq: { IETF: 'taq-ML', 'ISO-639': 'taq' },
+ 'tamil india': { IETF: 'ta-IN', 'ISO-639': 'ta' },
+ 'tamil sri lanka': { IETF: 'ta-LK', 'ISO-639': 'ta' },
+ taroko: { IETF: 'trv-TW', 'ISO-639': 'trv' },
+ tatar: { IETF: 'tt-RU', 'ISO-639': 'tt' },
+ telugu: { IETF: 'te-IN', 'ISO-639': 'te' },
+ tetum: { IETF: 'tet-TL', 'ISO-639': 'tet' },
+ thai: { IETF: 'th-TH', 'ISO-639': 'th' },
+ tibetan: { IETF: 'bo-CN', 'ISO-639': 'bo' },
+ tigrinya: { IETF: 'ti-ET', 'ISO-639': 'ti' },
+ 'tok pisin': { IETF: 'tpi-PG', 'ISO-639': 'tpi' },
+ tokelauan: { IETF: 'tkl-TK', 'ISO-639': 'tkl' },
+ tongan: { IETF: 'to-TO', 'ISO-639': 'to' },
+ 'tosk albanian': { IETF: 'als-AL', 'ISO-639': 'als' },
+ tsonga: { IETF: 'ts-ZA', 'ISO-639': 'ts' },
+ tswa: { IETF: 'tsc-MZ', 'ISO-639': 'tsc' },
+ tswana: { IETF: 'tn-BW', 'ISO-639': 'tn' },
+ tumbuka: { IETF: 'tum-MW', 'ISO-639': 'tum' },
+ turkish: { IETF: 'tr-TR', 'ISO-639': 'tr' },
+ turkmen: { IETF: 'tk-TM', 'ISO-639': 'tk' },
+ tuvaluan: { IETF: 'tvl-TV', 'ISO-639': 'tvl' },
+ twi: { IETF: 'tw-GH', 'ISO-639': 'tw' },
+ udmurt: { IETF: 'udm-RU', 'ISO-639': 'udm' },
+ ukrainian: { IETF: 'uk-UA', 'ISO-639': 'uk' },
+ uma: { IETF: 'ppk-ID', 'ISO-639': 'ppk' },
+ umbundu: { IETF: 'umb-AO', 'ISO-639': 'umb' },
+ 'uyghur uig': { IETF: 'uig-CN', 'ISO-639': 'uig' },
+ 'uyghur ug': { IETF: 'ug-CN', 'ISO-639': 'ug' },
+ uzbek: { IETF: 'uz-UZ', 'ISO-639': 'uz' },
+ venetian: { IETF: 'vec-IT', 'ISO-639': 'vec' },
+ vietnamese: { IETF: 'vi-VN', 'ISO-639': 'vi' },
+ 'vincentian creole english': { IETF: 'svc-VC', 'ISO-639': 'svc' },
+ 'virgin islands creole english': { IETF: 'vic-US', 'ISO-639': 'vic' },
+ wallisian: { IETF: 'wls-WF', 'ISO-639': 'wls' },
+ 'waray (philippines)': { IETF: 'war-PH', 'ISO-639': 'war' },
+ welsh: { IETF: 'cy-GB', 'ISO-639': 'cy' },
+ 'west central oromo': { IETF: 'gaz-ET', 'ISO-639': 'gaz' },
+ 'western persian': { IETF: 'pes-IR', 'ISO-639': 'pes' },
+ wolof: { IETF: 'wo-SN', 'ISO-639': 'wo' },
+ xhosa: { IETF: 'xh-ZA', 'ISO-639': 'xh' },
+ yiddish: { IETF: 'yi-YD', 'ISO-639': 'yi' },
+ yoruba: { IETF: 'yo-NG', 'ISO-639': 'yo' },
+ zulu: { IETF: 'zu-ZA', 'ISO-639': 'zu' }
};
module.exports = { languages };
diff --git a/src/js/logger.js b/src/js/logger.js
index d7ea220..60bc0de 100644
--- a/src/js/logger.js
+++ b/src/js/logger.js
@@ -6,73 +6,75 @@ const path = require('path');
const consoleloggerLevel = process.env.WINSTON_LOGGER_LEVEL || 'info';
const consoleFormat = format.combine(
- format.colorize(),
- format.timestamp(),
- format.align(),
- format.printf((info) => `${info.timestamp} - ${info.level}: ${info.message} ${JSON.stringify(info.metadata)}`),
+ format.colorize(),
+ format.timestamp(),
+ format.align(),
+ format.printf(info => `${info.timestamp} - ${info.level}: ${info.message} ${JSON.stringify(info.metadata)}`)
);
const fileFormat = format.combine(
- format.timestamp(),
- format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }),
- format.json(),
+ format.timestamp(),
+ format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }),
+ format.json()
);
const logger = createLogger({
- level: 'info',
- format: fileFormat,
- transports: [
- new transports.File({
- filename: path.join(__dirname, '../logs/error.log'),
- level: 'error',
- }),
- new transports.File({
- filename: path.join(__dirname, '../logs/activity.log'),
- maxsize: 5242880,
- maxFiles: 5,
- }),
- ],
+ level: 'info',
+ format: fileFormat,
+ transports: [
+ new transports.File({
+ filename: path.join(__dirname, '../logs/error.log'),
+ level: 'error'
+ }),
+ new transports.File({
+ filename: path.join(__dirname, '../logs/activity.log'),
+ maxsize: 5242880,
+ maxFiles: 5
+ })
+ ]
});
if (process.env.NODE_ENV !== 'production') {
- logger.add(
- new transports.Console({
- level: consoleloggerLevel,
- format: consoleFormat,
- }),
- );
+ logger.add(
+ new transports.Console({
+ level: consoleloggerLevel,
+ format: consoleFormat
+ })
+ );
}
fetch(path.join(__dirname, '../logs/activity.log'))
- .then((response) => response.text())
- .then((logData) => {
- const logLines = logData.trim().split('\n');
- const tableBody = document.getElementById('logContent');
+ .then(response => response.text())
+ .then(logData => {
+ const logLines = logData.trim().split('\n');
+ const tableBody = document.getElementById('logContent');
- logLines.forEach((logLine) => {
- const logObject = JSON.parse(logLine);
- const row = document.createElement('tr');
+ logLines.forEach(logLine => {
+ const logObject = JSON.parse(logLine);
+ const row = document.createElement('tr');
- const levelCell = document.createElement('td');
- levelCell.textContent = logObject.level;
- levelCell.classList.add(logObject.level); // Add class for styling
- row.appendChild(levelCell);
+ const levelCell = document.createElement('td');
+ levelCell.textContent = logObject.level;
+ levelCell.classList.add(logObject.level); // Add class for styling
+ row.appendChild(levelCell);
- const messageCell = document.createElement('td');
- messageCell.textContent = logObject.message;
- row.appendChild(messageCell);
+ const messageCell = document.createElement('td');
+ messageCell.textContent = logObject.message;
+ row.appendChild(messageCell);
- const metadataCell = document.createElement('td');
- metadataCell.textContent = JSON.stringify(logObject.metadata, null, 2);
- row.appendChild(metadataCell);
+ const metadataCell = document.createElement('td');
+ metadataCell.textContent = JSON.stringify(logObject.metadata, null, 2);
+ row.appendChild(metadataCell);
- const timestampCell = document.createElement('td');
- timestampCell.textContent = logObject.timestamp;
- row.appendChild(timestampCell);
+ const timestampCell = document.createElement('td');
+ timestampCell.textContent = logObject.timestamp;
+ row.appendChild(timestampCell);
- tableBody.appendChild(row);
- });
- })
- .catch((error) => {});
+ tableBody.appendChild(row);
+ });
+ })
+ .catch(error => {
+ console.error(error);
+ });
module.exports = logger;
diff --git a/src/js/mediaDevices.js b/src/js/mediaDevices.js
index ee21c35..d2a1ef8 100644
--- a/src/js/mediaDevices.js
+++ b/src/js/mediaDevices.js
@@ -1,49 +1,51 @@
-let micSelect = document.querySelector('#microphone');
+/* global settings, */
+
+const micSelect = document.querySelector('#microphone');
let selectedMic;
function getAvailableMediaDevices(type) {
- return new Promise((resolve, reject) => {
- navigator.mediaDevices
- .enumerateDevices()
- .then((devices) => {
- const microphones = devices.filter((device) => device.kind === type);
- resolve(microphones);
- })
- .catch((error) => {
- reject(error);
- });
- });
+ return new Promise((resolve, reject) => {
+ navigator.mediaDevices
+ .enumerateDevices()
+ .then(devices => {
+ const microphones = devices.filter(device => device.kind === type);
+ resolve(microphones);
+ })
+ .catch(error => {
+ reject(error);
+ });
+ });
}
// Microphones
getAvailableMediaDevices('audioinput')
- .then((microphones) => {
- let i = 0;
- let tempname = '';
- for (let mic of microphones) {
- if (mic.deviceId === 'default') {
- tempname = mic.label.slice(10); // remove "default -" from the label to get the default device name.
- }
+ .then(microphones => {
+ let i = 0;
+ let tempname = '';
+ for (const mic of microphones) {
+ if (mic.deviceId === 'default') {
+ tempname = mic.label.slice(10); // remove "default -" from the label to get the default device name.
+ }
- if (mic.deviceId === 'communications' || mic.label === tempname) {
- continue;
- }
+ if (mic.deviceId === 'communications' || mic.label === tempname) {
+ continue;
+ }
- const option = document.createElement('option');
+ const option = document.createElement('option');
- // Set the options value and text.
- option.value = i;
- option.innerHTML = `${mic.label}`;
+ // Set the options value and text.
+ option.value = i;
+ option.innerHTML = `${mic.label}`;
- // Add the option to the voice selector.
- micSelect.appendChild(option);
+ // Add the option to the voice selector.
+ micSelect.appendChild(option);
- if (i === microphones.length - 1) {
- document.getElementById('microphone').value = settings.STT.SELECTED_MICROPHONE;
- }
- i++;
- }
- })
- .catch((error) => {
- console.error('Error retrieving microphones:', error);
- });
+ if (i === microphones.length - 1) {
+ document.getElementById('microphone').value = settings.STT.SELECTED_MICROPHONE;
+ }
+ i++;
+ }
+ })
+ .catch(error => {
+ console.error('Error retrieving microphones:', error);
+ });
diff --git a/src/js/messageTemplates.js b/src/js/messageTemplates.js
index 34e6cc4..c8a626a 100644
--- a/src/js/messageTemplates.js
+++ b/src/js/messageTemplates.js
@@ -1,26 +1,26 @@
const twitchTemplate = `
-
-
-
-
-
+
+
+
+
+
`.trim();
const userTemplate = `
-
-
-
- You
-
+
+
+
+ You
+
`.trim();
const messageTemplate = `
-
-
- 12:00 PM
- You
- Hello there
+
+
+ 12:00 PM
+ You
+ Hello there
`.trim();
diff --git a/src/js/renderer.js b/src/js/renderer.js
index 0128a5d..16ba76b 100644
--- a/src/js/renderer.js
+++ b/src/js/renderer.js
@@ -3,7 +3,7 @@ const ini = require('ini');
const path = require('path'); // get directory path
const axios = require('axios');
-const { ipcRenderer, shell } = require('electron'); // necessary electron libraries to send data to the app
+const { webFrame, ipcRenderer, shell } = require('electron'); // necessary electron libraries to send data to the app
const io = require('socket.io-client');
const util = require('util');
@@ -17,8 +17,8 @@ const { Socket } = require('socket.io-client');
const main = ipcRenderer.sendSync('environment');
const resourcesPath = main.resourcesPath;
-let settingsPath = main.settingsPath.toString();
-let pythonPath = main.pythonPath.toString();
+const settingsPath = main.settingsPath.toString();
+const pythonPath = main.pythonPath.toString();
const settings = main.settings;
// TODO: remove gooogle voices txt and use api instead
@@ -35,6 +35,8 @@ const devicesDropdown = document.querySelector('#devicesDropdown');
const notificationSound = document.querySelector('#notification'); // obtain the html reference of the sound comboBox
const sttModel = document.querySelector('#sttModel'); // obtain the html reference of the sound comboBox
const ttsAudioDevices = document.querySelector('#ttsAudioDevice'); // obtain the html reference of the installedTTS comboBox
+const notificationSoundAudioDevices = document.querySelector('#notificationSoundAudioDevice'); // obtain the html reference of the installedTTS comboBox
+const emojiPicker = document.body.querySelector('emoji-picker');
// laod local javascript files
const chat = require(path.join(__dirname, './js/chat'));
@@ -47,18 +49,18 @@ const config = require(path.join(__dirname, './js/settings'));
const mediaDevices = require(path.join(__dirname, './js/mediaDevices'));
-let notificationSounds = path.join(__dirname, './sounds/notifications');
-let sttModels = path.join(__dirname, '../speech_to_text_models');
+const notificationSounds = path.join(__dirname, './sounds/notifications');
+const sttModels = path.join(__dirname, '../speech_to_text_models');
function reset() {
- ipcRenderer.send('restart');
+ ipcRenderer.send('restart');
}
-let server = require(path.join(__dirname, './js/server'));
+const server = require(path.join(__dirname, './js/server'));
const backend = require(path.join(__dirname, './js/backend'));
-let socket = io(`http://localhost:${settings.GENERAL.PORT}`); // Connect to your Socket.IO server
+const socket = io(`http://localhost:${settings.GENERAL.PORT}`); // Connect to your Socket.IO server
-let twitch = settings.TWITCH.USE_TWITCH ? require(path.join(__dirname, './js/twitch')) : '';
+const twitch = settings.TWITCH.USE_TWITCH ? require(path.join(__dirname, './js/twitch')) : '';
const Polly = settings.AMAZON.USE_AMAZON ? require(path.join(__dirname, './js/amazon')) : '';
const google = settings.GOOGLE.USE_GOOGLE ? require(path.join(__dirname, './js/google')) : '';
@@ -66,6 +68,9 @@ const theme = require(path.join(__dirname, './js/theme'));
const auth = require(path.join(__dirname, './js/auth'));
let ttsRequestCount = 0;
+ttsRequestCount = 0;
+let customEmojis = [];
+customEmojis = [];
// initialize values
config.getGeneralSettings();
@@ -77,83 +82,93 @@ const StartDateAndTime = Date.now();
const speakButton = document.querySelector('#speakBtn');
const amazonCredentials = {
- accessKeyId: settings.AMAZON.ACCESS_KEY,
- secretAccessKey: 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');
+ if (err) {
+ console.error(err);
+ }
- // Set the options value and text.
- option.value = i;
- option.innerHTML = file;
+ files.forEach((file, i) => {
+ // Create a new option element.
+ const option = document.createElement('option');
- // Add the option to the sound selector.
- notificationSound.appendChild(option);
- });
+ // Set the options value and text.
+ option.value = i;
+ option.innerHTML = file;
- // set the saved notification sound
- notificationSound.selectedIndex = settings.AUDIO.NOTIFICATION_SOUND;
+ // Add the option to the sound selector.
+ notificationSound.appendChild(option);
+ });
+
+ // set the saved notification sound
+ notificationSound.selectedIndex = settings.AUDIO.NOTIFICATION_SOUND;
});
// Check for installed stt models
fs.readdir(sttModels, (err, files) => {
- for (let file of files) {
- if (file.includes('.txt')) {
- continue;
- }
- // Create a new option element.
- const option = document.createElement('option');
+ if (err) {
+ console.error(err);
+ }
- // Set the options value and text.
- option.value = file;
- option.innerHTML = file;
-
- // Add the option to the sound selector.
- sttModel.appendChild(option);
+ for (const file of files) {
+ if (file.includes('.txt')) {
+ continue;
}
+ // Create a new option element.
+ const option = document.createElement('option');
- // set the saved notification sound
- sttModel.value = settings.STT.LANGUAGE;
+ // Set the options value and text.
+ option.value = file;
+ option.innerHTML = file;
+
+ // Add the option to the sound selector.
+ sttModel.appendChild(option);
+ }
+
+ // set the saved notification sound
+ sttModel.value = settings.STT.LANGUAGE;
});
async function getAudioDevices() {
- if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
- return;
- }
+ if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
+ 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);
+ notificationSoundAudioDevices.appendChild(option);
+ });
- ttsAudioDevices.selectedIndex = settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE;
+ ttsAudioDevices.selectedIndex = settings.AUDIO.SELECTED_TTS_AUDIO_DEVICE;
+ notificationSoundAudioDevices.selectedIndex = settings.AUDIO.SELECTED_NOTIFICATION_AUDIO_DEVICE;
}
getAudioDevices();
function setLanguagesinSelect(languageSelector, setting) {
- let languageSelect = document.querySelector(languageSelector); // obtain the html reference of the google voices comboBox
+ const languageSelect = document.querySelector(languageSelector); // obtain the html reference of the google voices comboBox
- for (const language in languageObject.languages) {
- if (languageObject.languages.hasOwnProperty(language)) {
- const iso639 = languageObject.languages[language]['ISO-639'];
- const option = document.createElement('option');
- option.value = iso639;
- option.innerHTML = `${iso639} - ${language}`;
- languageSelect.appendChild(option);
- }
+ for (const language in languageObject.languages) {
+ if (Object.prototype.hasOwnProperty.call(languageObject.languages, language)) {
+ const iso639 = languageObject.languages[language]['ISO-639'];
+ const option = document.createElement('option');
+ option.value = iso639;
+ option.innerHTML = `${iso639} - ${language}`;
+ languageSelect.appendChild(option);
}
+ }
- languageSelect.selectedIndex = setting;
+ languageSelect.selectedIndex = setting;
}
setLanguagesinSelect('#language', settings.GENERAL.LANGUAGE);
@@ -161,95 +176,122 @@ setLanguagesinSelect('#defaultLanguage', settings.TTS.PRIMARY_TTS_LANGUAGE_INDEX
setLanguagesinSelect('#secondaryLanguage', settings.TTS.SECONDARY_TTS_LANGUAGE_INDEX);
function addVoiceService(name) {
- function addToselect(select) {
- let ttsService = document.querySelector(select);
- const option = document.createElement('option');
- ttsService.appendChild(option);
+ function addToselect(select) {
+ const ttsService = document.querySelector(select);
+ const option = document.createElement('option');
+ ttsService.appendChild(option);
- option.value = name;
- option.innerHTML = name;
- }
- addToselect('#primaryTTSService');
- addToselect('#secondaryTTSService');
+ option.value = name;
+ option.innerHTML = name;
+ }
+ addToselect('#primaryTTSService');
+ addToselect('#secondaryTTSService');
}
// 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';
- };
+Array.from(document.body.querySelectorAll('[tip]')).forEach(el => {
+ const tip = document.createElement('div');
+ const body = document.querySelector('.container');
+ const element = el;
+ tip.classList.add('tooltip');
+ tip.classList.add('tooltiptext');
+ tip.innerText = el.getAttribute('tip');
+ tip.style.transform = `translate(${el.hasAttribute('tip-left') ? 'calc(-100% - 5px)' : '15px'}, ${
+ el.hasAttribute('tip-top') ? '-100%' : '15px'
+ })`;
+ body.appendChild(tip);
+ element.onmousemove = e => {
+ tip.style.left = `${e.x}px`;
+ tip.style.top = `${e.y}px`;
+ tip.style.zIndex = 1;
+ tip.style.visibility = 'visible';
+ };
+ element.onmouseleave = e => {
+ tip.style.visibility = 'hidden';
+ };
});
-function showChatMessage(article, isUser) {
- document.querySelector('#chatBox').appendChild(article);
- let usernameHtml;
- let msg;
- let messages = Array.from(document.body.querySelectorAll('.msg-container'));
+function showChatMessage(article) {
+ document.querySelector('#chatBox').appendChild(article);
- if (isUser) {
- usernameHtml = article.querySelector('.username-user');
- msg = article.querySelector('.msg-box-user');
- } else {
- usernameHtml = article.querySelector('.username');
- msg = article.querySelector('.msg-box');
- }
+ const messages = Array.from(document.body.querySelectorAll('.msg-container'));
- // var style = getComputedStyle(usernameHtml);
- // var style2 = getComputedStyle(usernameHtml);
-
- const lastMessage = messages[messages.length - 1];
- lastMessage.scrollIntoView({ behavior: 'smooth' });
+ 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();
- var ampm = hours >= 12 ? 'PM' : 'AM';
- const minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
- const time = `${hours}:${minutes} ${ampm}`;
+ const date = new Date();
+ document.body.querySelectorAll('.container').innerHTML = date.getHours();
+ const hours = date.getHours();
+ const ampm = hours >= 12 ? 'PM' : 'AM';
+ const minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
+ const time = `${hours}:${minutes} ${ampm}`;
- 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-btn4', '#AMAZON_ACCESS_KEY');
hideText('.password-toggle-btn5', '#AMAZON_ACCESS_SECRET');
hideText('.password-toggle-btn6', '#GOOGLE_API_KEY');
+
+function setZoomLevel(currentZoom, zoomIn) {
+ let newZoom = currentZoom.toFixed(2);
+
+ if (zoomIn === true && currentZoom < 4.95) {
+ newZoom = (currentZoom + 0.05).toFixed(2);
+ }
+ if (zoomIn === false && currentZoom > 0.25) {
+ newZoom = (currentZoom - 0.05).toFixed(2);
+ }
+
+ webFrame.setZoomFactor(parseFloat(newZoom));
+ settings.GENERAL.ZOOMLEVEL = newZoom;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ document.body.querySelector('#ZOOMLEVEL').value = (settings.GENERAL.ZOOMLEVEL * 100).toFixed(0);
+}
+
+// const customEmojix = [
+// {
+// name: 'sakuraestaKleefeliz',
+// shortcodes: ['sakuraestaKleefeliz'],
+// url: 'https://static-cdn.jtvnw.net/emoticons/v2/emotesv2_0cb536ddb6e143ab87ffeccb160a4d45/default/dark/1.0',
+// category: 'Sakura'
+// }
+// ];
+
+// const customEmojiy = [
+// {
+// name: 'sakuraestaKleefeliz',
+// shortcodes: ['sakuraestaKleefeliz'],
+// url: 'https://static-cdn.jtvnw.net/emoticons/v2/emotesv2_0cb536ddb6e143ab87ffeccb160a4d45/default/dark/1.0',
+// category: 'Sakurax'
+// }
+// ];
+
+// emojiPicker.customEmoji = customEmojix;
+// emojiPicker.customEmoji = customEmojiy;
+
+// console.log(emojiPicker.database.getEmojiBySearchQuery('Kappa'));
diff --git a/src/js/responses.js b/src/js/responses.js
index 4c7c082..49bd1a2 100644
--- a/src/js/responses.js
+++ b/src/js/responses.js
@@ -1,18 +1,21 @@
function getBotResponse(input) {
- // rock paper scissors
- if (input === 'rock') {
- return 'paper';
- } if (input === 'paper') {
- return 'scissors';
- } if (input === 'scissors') {
- return 'rock';
- }
+ // rock paper scissors
+ if (input === 'rock') {
+ return 'paper';
+ }
+ if (input === 'paper') {
+ return 'scissors';
+ }
+ if (input === 'scissors') {
+ return 'rock';
+ }
- // Simple responses
- if (input === 'hello') {
- return 'Hello there!';
- } if (input === 'goodbye') {
- return 'Talk to you later!';
- }
- return 'Try asking something else!';
+ // Simple responses
+ if (input === 'hello') {
+ return 'Hello there!';
+ }
+ if (input === 'goodbye') {
+ return 'Talk to you later!';
+ }
+ return 'Try asking something else!';
}
diff --git a/src/js/server.js b/src/js/server.js
index 97d9ff8..772a946 100644
--- a/src/js/server.js
+++ b/src/js/server.js
@@ -1,3 +1,5 @@
+/* global settings */
+
const express = require('express');
const app = express();
const path = require('path');
@@ -5,42 +7,42 @@ const http = require('http');
const localServer = http.createServer(app);
const io = require('socket.io')(localServer);
-let requestCount = 0;
+const requestCount = 0;
function startVtuberModule() {
- if (!settings.MODULES.USE_VTUBER) {
- return;
- }
+ if (!settings.MODULES.USE_VTUBER) {
+ return;
+ }
- app.use('/vtuber', express.static(path.join(__dirname, '../modules/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:${settings.GENERAL.PORT}/vtuber`;
- vtuberframe.style.width = '100%';
- vtuberframe.style.height = '100%';
- vtuberframe.frameBorder = 0;
- vtuber.appendChild(vtuberframe);
+ const vtuber = document.body.querySelector('#BrowsersourceVtuber');
+ const vtuberframe = document.createElement('iframe');
+ vtuberframe.class = 'frame';
+ vtuberframe.src = `http://localhost:${settings.GENERAL.PORT}/vtuber`;
+ vtuberframe.style.width = '100%';
+ vtuberframe.style.height = '100%';
+ vtuberframe.frameBorder = 0;
+ vtuber.appendChild(vtuberframe);
}
startVtuberModule();
function startChatBubbleModule() {
- if (!settings.MODULES.USE_CHATBUBBLE) {
- return;
- }
+ if (!settings.MODULES.USE_CHATBUBBLE) {
+ return;
+ }
- app.use('/chat', express.static(path.join(__dirname, '../modules/chat')));
+ 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:${settings.GENERAL.PORT}/chat`;
- chatframe.style.width = '100%';
- chatframe.style.height = '100%';
- chatframe.frameBorder = 0;
- chat.appendChild(chatframe);
+ const chat = document.body.querySelector('#BrowsersourceChat');
+ const chatframe = document.createElement('iframe');
+ chatframe.class = 'frame';
+ chatframe.src = `http://localhost:${settings.GENERAL.PORT}/chat`;
+ chatframe.style.width = '100%';
+ chatframe.style.height = '100%';
+ chatframe.frameBorder = 0;
+ chat.appendChild(chatframe);
}
startChatBubbleModule();
@@ -49,34 +51,31 @@ function startSTT() {}
// Middleware to conditionally serve routes
app.use((req, res, next) => {
- if (!settings.MODULES.USE_VTUBER && req.path === '/vtuber') {
- res.sendStatus(404); // Return a 404 status for /vtuber when it's disabled
- } else if (!settings.MODULES.USE_CHATBUBBLE && 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
- }
+ if (!settings.MODULES.USE_VTUBER && req.path === '/vtuber') {
+ res.sendStatus(404); // Return a 404 status for /vtuber when it's disabled
+ } else if (!settings.MODULES.USE_CHATBUBBLE && 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
+ }
});
localServer.listen(settings.GENERAL.PORT, () => {
- startVtuberModule();
- startChatBubbleModule();
-
- if (settings.TTS.USE_TTS) {
- }
+ startVtuberModule();
+ startChatBubbleModule();
});
// Handle socket connections
-io.on('connection', (socket) => {
- // Receive data from the client
- socket.on('message', (data) => {});
+io.on('connection', socket => {
+ // 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 = { startVtuberModule, startChatBubbleModule };
diff --git a/src/js/settings.js b/src/js/settings.js
index 3e57ed7..ee3ddd0 100644
--- a/src/js/settings.js
+++ b/src/js/settings.js
@@ -1,600 +1,692 @@
+/* global settings, setZoomLevel, webFrame, theme, fs, settingsPath, ini, startVoiceRecognition,notificationSoundAudioDevices, ttsAudioDevices, notificationSound, path, resourcesPath, ipcRenderer, auth, shell, sound, twitch, server, backend */
+
function getGeneralSettings() {
- // General
- document.body.querySelector('#PORT').value = settings.GENERAL.PORT;
+ // General
+ document.body.querySelector('#PORT').value = settings.GENERAL.PORT;
+ document.body.querySelector('#ZOOMLEVEL').value = settings.GENERAL.ZOOMLEVEL * 100;
+ webFrame.setZoomFactor(parseFloat(settings.GENERAL.ZOOMLEVEL));
+ // 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();
- // 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();
+ // STT
+ document.body.querySelector('#USE_STT').checked = settings.STT.USE_STT;
- // STT
- document.body.querySelector('#USE_STT').checked = settings.STT.USE_STT;
+ // Language detection
+ document.body.querySelector('#USE_DETECTION').checked = settings.LANGUAGE.USE_DETECTION;
- // Language detection
- document.body.querySelector('#USE_DETECTION').checked = settings.LANGUAGE.USE_DETECTION;
+ // TTS
+ document.body.querySelector('#USE_TTS').checked = settings.TTS.USE_TTS;
- // TTS
- document.body.querySelector('#USE_TTS').checked = settings.TTS.USE_TTS;
+ // Notification sounds
+ document.body.querySelector('#USE_NOTIFICATION_SOUNDS').checked = settings.AUDIO.USE_NOTIFICATION_SOUNDS;
- // Notification sounds
- document.body.querySelector('#USE_NOTIFICATION_SOUNDS').checked = settings.AUDIO.USE_NOTIFICATION_SOUNDS;
+ // 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;
- // 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;
+ // Modules
+ document.body.querySelector('#USE_MODULES').checked = settings.MODULES.USE_MODULES;
+ document.body.querySelector('#USE_VTUBER').checked = settings.MODULES.USE_VTUBER;
+ document.body.querySelector('#VTUBER_URL').value = `http://localhost:${settings.GENERAL.PORT}/vtuber/`;
+ showMenuButton('#btnBrowsersourceVtuber', settings.MODULES.USE_VTUBER);
+ document.body.querySelector('#USE_CHATBUBBLE').checked = settings.MODULES.USE_CHATBUBBLE;
+ document.body.querySelector('#CHATBUBBLE_URL').value = `http://localhost:${settings.GENERAL.PORT}/chat/`;
+ showMenuButton('#btnBrowsersourceChat', settings.GENERAL.USE_CHATBUBBLE);
- // Modules
- document.body.querySelector('#USE_MODULES').checked = settings.MODULES.USE_MODULES;
- document.body.querySelector('#USE_VTUBER').checked = settings.MODULES.USE_VTUBER;
- document.body.querySelector('#VTUBER_URL').value = `http://localhost:${settings.GENERAL.PORT}/vtuber/`;
- showMenuButton('#btnBrowsersourceVtuber', settings.MODULES.USE_VTUBER);
- document.body.querySelector('#USE_CHATBUBBLE').checked = settings.MODULES.USE_CHATBUBBLE;
- document.body.querySelector('#CHATBUBBLE_URL').value = `http://localhost:${settings.GENERAL.PORT}/chat/`;
- showMenuButton('#btnBrowsersourceChat', settings.GENERAL.USE_CHATBUBBLE);
+ // 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;
- // 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;
+ // Google
+ document.body.querySelector('#USE_GOOGLE').checked = settings.GOOGLE.USE_GOOGLE;
+ document.body.querySelector('#GOOGLE_API_KEY').value = settings.GOOGLE.API_KEY;
}
document.body.querySelector('#primaryAmazonVoice').addEventListener('change', () => {
- var select = document.querySelector('#primaryAmazonVoice');
- settings.AMAZON.PRIMARY_VOICE = select.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved Amazon primary voice!', 'success');
+ const select = document.querySelector('#primaryAmazonVoice');
+ settings.AMAZON.PRIMARY_VOICE = select.value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved Amazon primary voice!', 'success');
});
document.body.querySelector('#secondaryAmazonVoice').addEventListener('change', () => {
- var select = document.querySelector('#secondaryAmazonVoice');
- settings.AMAZON.SECONDARY_VOICE = select.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved Amazon secondary voice!', 'success');
+ const select = document.querySelector('#secondaryAmazonVoice');
+ settings.AMAZON.SECONDARY_VOICE = select.value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved Amazon secondary voice!', 'success');
});
document.body.querySelector('#primaryGoogleVoice').addEventListener('change', () => {
- var select = document.querySelector('#primaryGoogleVoice');
- settings.GOOGLE.PRIMARY_VOICE = select.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved Google primary voice!', 'success');
+ const select = document.querySelector('#primaryGoogleVoice');
+ settings.GOOGLE.PRIMARY_VOICE = select.value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved Google primary voice!', 'success');
});
document.body.querySelector('#secondaryGoogleVoice').addEventListener('change', () => {
- var select = document.querySelector('#secondaryGoogleVoice');
- settings.GOOGLE.SECONDARY_VOICE = select.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved Google secondary voice!', 'success');
+ const select = document.querySelector('#secondaryGoogleVoice');
+ settings.GOOGLE.SECONDARY_VOICE = select.value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved Google secondary voice!', 'success');
});
document.body.querySelector('#primaryVoice').addEventListener('change', () => {
- var select = document.querySelector('#primaryVoice');
- settings.TTS.PRIMARY_VOICE = select.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved primary voice!', 'success');
+ const select = document.querySelector('#primaryVoice');
+ settings.TTS.PRIMARY_VOICE = select.value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved primary voice!', 'success');
});
document.body.querySelector('#microphone').addEventListener('change', () => {
- var select = document.querySelector('#microphone');
- settings.STT.MICROPHONE = select.value;
- settings.STT.MICROPHONE_ID = select.options[select.selectedIndex].text;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved microphone!', 'success');
- startVoiceRecognition();
+ const select = document.querySelector('#microphone');
+ settings.STT.MICROPHONE = select.value;
+ settings.STT.MICROPHONE_ID = select.options[select.selectedIndex].text;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved microphone!', 'success');
+ startVoiceRecognition();
});
document.body.querySelector('#sttModel').addEventListener('change', () => {
- var select = document.querySelector('#sttModel');
- settings.STT.LANGUAGE = select.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved voice detection language!', 'success');
+ const select = document.querySelector('#sttModel');
+ settings.STT.LANGUAGE = select.value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved voice detection language!', 'success');
});
document.body.querySelector('#defaultLanguage').addEventListener('change', () => {
- var select = document.querySelector('#defaultLanguage');
- 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 default language!', 'success');
+ const select = document.querySelector('#defaultLanguage');
+ 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 default language!', 'success');
});
document.body.querySelector('#secondaryVoice').addEventListener('change', () => {
- var select = document.querySelector('#secondaryVoice');
- settings.TTS.SECONDARY_VOICE = select.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved secondary voice!', 'success');
+ const select = document.querySelector('#secondaryVoice');
+ settings.TTS.SECONDARY_VOICE = select.value;
+ 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(settingsPath, ini.stringify(settings));
- createNotification('Saved secondary language!', 'success');
+ const 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(settingsPath, ini.stringify(settings));
- createNotification('Saved audio device!', 'success');
+ 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('#notificationSoundAudioDevice').addEventListener('change', () => {
+ settings.AUDIO.SELECTED_NOTIFICATION_AUDIO_DEVICE = notificationSoundAudioDevices.value;
+ settings.AUDIO.NOTIFICATION_AUDIO_DEVICE = notificationSoundAudioDevices.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(settingsPath, ini.stringify(settings));
+ settings.TWITCH.CHANNEL_NAME = document.body.querySelector('#TWITCH_CHANNEL_NAME').value;
+ fs.writeFileSync(settingsPath, 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');
+ const 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(settingsPath, ini.stringify(settings));
- createNotification('Saved OAuth token!', 'success');
+ settings.TWITCH.OAUTH_TOKEN = document.body.querySelector('#TWITCH_OAUTH_TOKEN').value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved OAuth token!', 'success');
- let button = document.body.querySelector('#TestTwitchCredentials');
- button.className = 'AdvancedMenuButton';
- createNotification('Saved OAuth token, please restart the application to reset twitch service', 'warning');
+ const button = document.body.querySelector('#TestTwitchCredentials');
+ button.className = 'AdvancedMenuButton';
+ createNotification('Saved OAuth token, please restart the application to reset twitch service', 'warning');
});
+setInputFilter(
+ document.body.querySelector('#PORT'),
+ function (value) {
+ return /^\d*\.?\d*$/.test(value); // Allow digits and '.' only, using a RegExp.
+ },
+ "Only digits and '.' are allowed"
+);
+
document.body.querySelector('#PORT').addEventListener('change', () => {
- settings.GENERAL.PORT = document.body.querySelector('#PORT').value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved port, please restart the application to reset the port', 'warning');
+ settings.GENERAL.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(settingsPath, ini.stringify(settings));
- createNotification('Saved Amazon access key!', 'success');
+ 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(settingsPath, ini.stringify(settings));
- createNotification('Saved Amazon access secret!', 'success');
+ 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(settingsPath, ini.stringify(settings));
- createNotification('Saved Google api key!', 'success');
+ 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('#notification').addEventListener('change', () => {
- settings.AUDIO.NOTIFICATION_SOUND = notificationSound.selectedIndex;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- createNotification('Saved notification sound!', 'success');
+ settings.AUDIO.NOTIFICATION_SOUND = notificationSound.selectedIndex;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ createNotification('Saved notification sound!', 'success');
});
function showMenuButton(menuButton, toggle) {
- let option = document.body.querySelector(menuButton);
- if (!toggle) {
- option.style.display = 'none';
- } else {
- option.style.display = '';
- }
+ const 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);
+ 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';
+ }
- let notfication = new Audio(path.join(resourcesPath, `./sounds/notifications/${alertSound}`));
- notfication.volume = settings.AUDIO.NOTIFICATION_VOLUME / 100;
- notfication.play();
- setTimeout(() => notification.remove(), 10000);
+ const 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, 'warning');
+ 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, 'warning');
+ 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].style.display = '';
- }
- } else {
- for (let i = 0; i < inputs.length; i += 1) {
- element[i].style.display = 'none';
- }
+ 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', () => {
- const toggle = document.getElementById('USE_CUSTOM_THEME').checked;
- const inputs = document.getElementsByClassName('inputTheme');
- toggleRadio(toggle, inputs);
+ const toggle = document.getElementById('USE_CUSTOM_THEME').checked;
+ const inputs = document.getElementsByClassName('inputTheme');
+ toggleRadio(toggle, inputs);
- settings.THEME.USE_CUSTOM_THEME = toggle;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- theme.setTheme();
- createNotification(`${toggle ? 'Enabled' : 'Disabled'} custom theme!`, 'success');
+ 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', async () => {
- let element = document.body.querySelector('#TWITCH_OAUTH_TOKEN');
- element.value = await auth.getTwitchOauthToken();
+ const element = document.body.querySelector('#TWITCH_OAUTH_TOKEN');
+ element.value = await auth.getTwitchOauthToken();
- createNotification('Saved OAuth token!', 'success');
+ createNotification('Saved OAuth token!', 'success');
});
-let hideInputToggleButton = document.body.querySelectorAll('.password-toggle-btn .password-toggle-icon .fa-eye-slash');
-hideInputToggleButton.forEach((item) => {
- item.addEventListener('click', () => {
- if (item.classList.contains('fa-eye')) {
- item.classList.remove('fa-eye');
- item.classList.add('fa-eye-slash');
- } else {
- item.classList.remove('fa-eye-slash');
- item.classList.add('fa-eye');
- }
- });
+const hideInputToggleButton = document.body.querySelectorAll('.password-toggle-btn .password-toggle-icon .fa-eye-slash');
+hideInputToggleButton.forEach(item => {
+ item.addEventListener('click', () => {
+ if (item.classList.contains('fa-eye')) {
+ item.classList.remove('fa-eye');
+ item.classList.add('fa-eye-slash');
+ } else {
+ item.classList.remove('fa-eye-slash');
+ item.classList.add('fa-eye');
+ }
+ });
});
function hideOrShowViewerPanel() {
- const menu = document.body.querySelector('.sidepanel-right');
- const leftCircle = document.body.querySelector('.circle-right');
+ const menu = document.body.querySelector('.sidepanel-right');
+ const leftCircle = document.body.querySelector('.circle-right');
- if (!settings.GENERAL.VIEWERS_PANEL) {
- menu.classList.add('collapse-menu-right');
- leftCircle.classList.add('collapse-circle-right');
- } else {
- menu.classList.remove('collapse-menu-right');
- leftCircle.classList.remove('collapse-circle-right');
- }
- fs.writeFileSync(settingsPath, ini.stringify(settings));
+ if (!settings.GENERAL.VIEWERS_PANEL) {
+ menu.classList.add('collapse-menu-right');
+ leftCircle.classList.add('collapse-circle-right');
+ } else {
+ menu.classList.remove('collapse-menu-right');
+ leftCircle.classList.remove('collapse-circle-right');
+ }
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
}
hideOrShowViewerPanel();
document.body.querySelector('#VIEWERS_PANEL').addEventListener('click', () => {
- if (settings.GENERAL.VIEWERS_PANEL) {
- settings.GENERAL.VIEWERS_PANEL = false;
- } else {
- settings.GENERAL.VIEWERS_PANEL = true;
- }
- hideOrShowViewerPanel();
+ if (settings.GENERAL.VIEWERS_PANEL) {
+ settings.GENERAL.VIEWERS_PANEL = false;
+ } else {
+ settings.GENERAL.VIEWERS_PANEL = true;
+ }
+ hideOrShowViewerPanel();
});
document.body.querySelector('#Info_VTUBER').addEventListener('click', () => {
- shell.openExternal(`http://localhost:${settings.GENERAL.PORT}/vtuber/`);
+ shell.openExternal(`http://localhost:${settings.GENERAL.PORT}/vtuber/`);
});
document.body.querySelector('#Info_CHATBUBBLE').addEventListener('click', () => {
- shell.openExternal(`http://localhost:${settings.GENERAL.PORT}/chat/`);
+ shell.openExternal(`http://localhost:${settings.GENERAL.PORT}/chat/`);
});
document.body.querySelector('#max-button').addEventListener('click', () => {
- ipcRenderer.send('maximize-window');
+ ipcRenderer.send('maximize-window');
});
document.body.querySelector('#close-button').addEventListener('click', () => {
- ipcRenderer.send('close-window');
+ ipcRenderer.send('close-window');
});
// #endregion
// #region Notification sound test
document.body.querySelector('#SoundTestButton').addEventListener('click', () => {
- sound.playNotificationSound();
+ sound.playNotificationSound();
});
document.body.querySelector('#TestTwitchCredentials').addEventListener('click', () => {
- twitch.ping('#TestTwitchCredentials');
- // resetTwitch(;
+ 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);
}
toggleTwitch();
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(__dirname, './twitch')) : null;
- createNotification(`${toggle ? 'Enabled' : 'Disabled'} Twitch settings!`, 'success');
+ 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(__dirname, './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);
+ const toggle = settings.GOOGLE.USE_GOOGLE;
+ const inputs = document.getElementsByClassName('inputGoogle');
+ toggleRadio(toggle, inputs);
}
toggleGoogle();
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');
+ 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);
+ const toggle = settings.AMAZON.USE_AMAZON;
+ const inputs = document.getElementsByClassName('inputAmazon');
+ toggleRadio(toggle, inputs);
}
toggleAmazon();
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');
+ 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.MODULES.USE_MODULES;
- const inputs = document.getElementsByClassName('inputServer');
- toggleRadio(toggle, inputs);
+ const toggle = settings.MODULES.USE_MODULES;
+ const inputs = document.getElementsByClassName('inputServer');
+ toggleRadio(toggle, inputs);
}
toggleServer();
document.body.querySelector('#USE_MODULES').addEventListener('click', () => {
- const toggle = document.getElementById('USE_MODULES').checked;
- settings.MODULES.USE_MODULES = toggle;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- const inputs = document.getElementsByClassName('inputServer');
- toggleRadio(toggle, inputs);
- createNotification(
- `${toggle ? 'Enabled' : 'Disabled'} server settings!, the service will stop working after restarting the application
+ const toggle = document.getElementById('USE_MODULES').checked;
+ settings.MODULES.USE_MODULES = toggle;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ const inputs = document.getElementsByClassName('inputServer');
+ toggleRadio(toggle, inputs);
+ createNotification(
+ `${toggle ? 'Enabled' : 'Disabled'} server settings!, the service will stop working after restarting the application
${toggle ? '' : ', the service will stop working after restarting the application'}`,
- 'success',
- );
+ 'success'
+ );
});
document.body.querySelector('#USE_VTUBER').addEventListener('change', () => {
- const toggle = document.getElementById('USE_VTUBER').checked;
- settings.MODULES.USE_VTUBER = toggle;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- showMenuButton('#btnBrowsersourceVtuber', toggle);
- createNotification(
- `${toggle ? 'Enabled' : 'Disabled'} Vtuber setting!
+ const toggle = document.getElementById('USE_VTUBER').checked;
+ settings.MODULES.USE_VTUBER = toggle;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ showMenuButton('#btnBrowsersourceVtuber', toggle);
+ createNotification(
+ `${toggle ? 'Enabled' : 'Disabled'} Vtuber setting!
${toggle ? '' : ', the service will stop working after restarting the application'}`,
- 'success',
- );
- server.startVtuberModule();
+ 'success'
+ );
+ server.startVtuberModule();
});
document.body.querySelector('#USE_CHATBUBBLE').addEventListener('change', () => {
- const toggle = document.getElementById('USE_CHATBUBBLE').checked;
- settings.MODULES.USE_CHATBUBBLE = toggle;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- showMenuButton('#btnBrowsersourceChat', toggle);
- createNotification(`${toggle ? 'Enabled' : 'Disabled'} chatbubble setting!`, 'success');
- server.startChatBubbleModule();
+ const toggle = document.getElementById('USE_CHATBUBBLE').checked;
+ settings.MODULES.USE_CHATBUBBLE = toggle;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ showMenuButton('#btnBrowsersourceChat', toggle);
+ createNotification(`${toggle ? 'Enabled' : 'Disabled'} chatbubble setting!`, 'success');
+ server.startChatBubbleModule();
});
function toggleTTS() {
- const toggle = settings.TTS.USE_TTS;
- const inputs = document.getElementsByClassName('inputTTS');
- toggleRadio(toggle, inputs);
+ const toggle = settings.TTS.USE_TTS;
+ const inputs = document.getElementsByClassName('inputTTS');
+ toggleRadio(toggle, inputs);
}
toggleTTS();
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');
+ 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 toggleSTT() {
- const toggle = settings.STT.USE_STT;
- const inputs = document.getElementsByClassName('inputSTT');
- toggleRadio(toggle, inputs);
+ const toggle = settings.STT.USE_STT;
+ const inputs = document.getElementsByClassName('inputSTT');
+ toggleRadio(toggle, inputs);
}
toggleSTT();
document.body.querySelector('#USE_STT').addEventListener('change', () => {
- const toggle = document.getElementById('USE_STT').checked;
- settings.STT.USE_STT = toggle;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- const inputs = document.getElementsByClassName('inputSTT');
- toggleRadio(toggle, inputs);
- createNotification(`${toggle ? 'Enabled' : 'Disabled'} speech to text!`, 'success');
+ const toggle = document.getElementById('USE_STT').checked;
+ settings.STT.USE_STT = toggle;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ const inputs = document.getElementsByClassName('inputSTT');
+ toggleRadio(toggle, inputs);
+ createNotification(`${toggle ? 'Enabled' : 'Disabled'} speech to text!`, 'success');
});
function toggleLanguageDetection() {
- const toggle = settings.LANGUAGE.USE_DETECTION;
- const inputs = document.getElementsByClassName('languageDetectionInput');
- toggleRadio(toggle, inputs);
+ const toggle = settings.LANGUAGE.USE_DETECTION;
+ const inputs = document.getElementsByClassName('languageDetectionInput');
+ toggleRadio(toggle, inputs);
}
toggleLanguageDetection();
document.body.querySelector('#USE_DETECTION').addEventListener('change', () => {
- const toggle = document.getElementById('USE_DETECTION').checked;
- settings.LANGUAGE.USE_DETECTION = toggle;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- const inputs = document.getElementsByClassName('languageDetectionInput');
- toggleRadio(toggle, inputs);
- createNotification(`${toggle ? 'Enabled' : 'Disabled'} Language detection!`, 'success');
+ const toggle = document.getElementById('USE_DETECTION').checked;
+ settings.LANGUAGE.USE_DETECTION = toggle;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ const inputs = document.getElementsByClassName('languageDetectionInput');
+ toggleRadio(toggle, inputs);
+ createNotification(`${toggle ? 'Enabled' : 'Disabled'} Language detection!`, 'success');
});
function toggleNotificationSounds() {
- const toggle = settings.AUDIO.USE_NOTIFICATION_SOUNDS;
- const inputs = document.getElementsByClassName('inputNotificationSound');
- toggleRadio(toggle, inputs);
+ 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');
+ 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 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);
+ const slider = document.querySelector('#notificationVolumeSlider');
+ slider.value = settings.AUDIO.NOTIFICATION_VOLUME;
+ slider.style.setProperty('--tiempotemporal', settings.AUDIO.NOTIFICATION_VOLUME);
- createNotification('Saved notification volume!', 'success');
+ 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;
+ 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));
- });
+ 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');
+ 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('#ttsVolume').addEventListener('change', () => {
- let element = document.body.querySelector('#ttsVolume');
- settings.AUDIO.TTS_VOLUME = element.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
+ const element = document.body.querySelector('#ttsVolume');
+ settings.AUDIO.TTS_VOLUME = element.value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
- const slider = document.querySelector('#ttsVolumeSlider');
- slider.value = settings.AUDIO.TTS_VOLUME;
- slider.style.setProperty('--tiempotemporal', settings.AUDIO.TTS_VOLUME);
+ const slider = document.querySelector('#ttsVolumeSlider');
+ slider.value = settings.AUDIO.TTS_VOLUME;
+ slider.style.setProperty('--tiempotemporal', settings.AUDIO.TTS_VOLUME);
- createNotification('Saved TTS volume!', 'success');
+ createNotification('Saved TTS volume!', 'success');
});
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;
+ 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.AUDIO.TTS_VOLUME = e.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(settingsPath, ini.stringify(settings));
+ });
});
document.body.querySelector('#ttsVolumeSlider').addEventListener('mouseup', () => {
- createNotification('Saved TTS volume!', 'success');
+ 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.querySelector('#ttsVolumeSlider').value = settings.AUDIO.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.AUDIO.TTS_VOLUME = element.value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
+ const element = document.body.querySelector('#ttsVolume');
+ settings.AUDIO.TTS_VOLUME = element.value;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
- const slider = document.querySelector('#ttsVolumeSlider');
- slider.value = settings.AUDIO.TTS_VOLUME;
- slider.style.setProperty('--tiempotemporal', settings.AUDIO.TTS_VOLUME);
+ const slider = document.querySelector('#ttsVolumeSlider');
+ slider.value = settings.AUDIO.TTS_VOLUME;
+ slider.style.setProperty('--tiempotemporal', settings.AUDIO.TTS_VOLUME);
});
document.body.querySelector('#TestDefaultTTSButton').addEventListener('click', async () => {
- const text = document.getElementById('testPrimaryTTS').value;
- const requestData = {
- message: `user: ${text}`,
- voice: settings.TTS.PRIMARY_VOICE,
- };
- let count = await backend.getInternalTTSAudio(requestData);
- let textObject = { filtered: text, formatted: text };
- sound.playAudio({ service: 'Internal', message: textObject, count });
+ const text = document.getElementById('testPrimaryTTS').value;
+ const requestData = {
+ message: `user: ${text}`,
+ voice: settings.TTS.PRIMARY_VOICE
+ };
+ const count = await backend.getInternalTTSAudio(requestData);
+ const textObject = { filtered: text, formatted: text };
+ sound.playAudio({ service: 'Internal', message: textObject, count });
});
document.body.querySelector('#TestSecondaryTTSButton').addEventListener('click', async () => {
- const text = document.getElementById('testSecondaryTTS').value;
- const requestData = {
- message: `user: ${text}`,
- voice: settings.TTS.SECONDARY_VOICE,
- };
+ const text = document.getElementById('testSecondaryTTS').value;
+ const requestData = {
+ message: `user: ${text}`,
+ voice: settings.TTS.SECONDARY_VOICE
+ };
- let count = await backend.getInternalTTSAudio(requestData);
- let textObject = { filtered: text, formatted: text };
+ const count = await backend.getInternalTTSAudio(requestData);
+ const textObject = { filtered: text, formatted: text };
- sound.playAudio({ service: 'Internal', message: textObject, count });
+ sound.playAudio({ service: 'Internal', message: textObject, count });
+});
+
+// Restricts input for the given textbox to the given inputFilter function.
+function setInputFilter(textbox, inputFilter, errMsg) {
+ ['input', 'keydown', 'keyup', 'mousedown', 'mouseup', 'select', 'contextmenu', 'drop', 'focusout'].forEach(function (event) {
+ textbox.addEventListener(event, function (e) {
+ if (inputFilter(this.value)) {
+ // Accepted value.
+ if (['keydown', 'mousedown', 'focusout'].indexOf(e.type) >= 0) {
+ this.classList.remove('input-error');
+ this.setCustomValidity('');
+ }
+
+ this.oldValue = this.value;
+ this.oldSelectionStart = this.selectionStart;
+ this.oldSelectionEnd = this.selectionEnd;
+ } else if (Object.prototype.hasOwnProperty.call(this, 'oldValue')) {
+ // Rejected value: restore the previous one.
+ this.classList.add('input-error');
+ this.setCustomValidity(errMsg);
+ this.reportValidity();
+ this.value = this.oldValue;
+ this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
+ } else {
+ // Rejected value: nothing to restore.
+ this.value = '';
+ }
+ });
+ });
+}
+
+webFrame.setVisualZoomLevelLimits(1, 5);
+
+document.body.addEventListener('wheel', e => {
+ if (e.ctrlKey) {
+ const currentZoom = webFrame.getZoomFactor();
+ const zoomIn = Boolean(e.deltaY < 0);
+ setZoomLevel(currentZoom, zoomIn);
+ }
+});
+
+setInputFilter(
+ document.body.querySelector('#ZOOMLEVEL'),
+ function (value) {
+ return /^\d*\.?\d*$/.test(value); // Allow digits and '.' only, using a RegExp.
+ },
+ "Only digits and '.' are allowed"
+);
+
+document.body.querySelector('#ZOOMLEVEL').addEventListener('change', () => {
+ const newZoom = parseInt(document.body.querySelector('#ZOOMLEVEL').value) / 100;
+ settings.GENERAL.ZOOMLEVEL = newZoom;
+ fs.writeFileSync(settingsPath, ini.stringify(settings));
+ setZoomLevel(newZoom, null);
+ createNotification('Saved zoom new level', 'warning');
+});
+
+document.body.querySelector('emoji-picker').addEventListener('emoji-click', e => {
+ console.log(e.detail);
+ const div = document.getElementById('textInput');
+ if (e.detail.unicode === undefined) {
+ div.value += e.detail.name + ' ';
+ } else {
+ div.value += e.detail.unicode + ' ';
+ }
+
+ div.focus();
+});
+
+// #region Use Custom theme toggle logic
+document.body.querySelector('#emojis').addEventListener('click', () => {
+ const emojiPicker = document.body.querySelector('#emoji-picker');
+ // console.log(emojiPicker);
+ emojiPicker.style.visibility === 'visible' ? (emojiPicker.style.visibility = 'hidden') : (emojiPicker.style.visibility = 'visible');
});
module.exports = {
- getGeneralSettings,
+ getGeneralSettings
};
diff --git a/src/js/sound.js b/src/js/sound.js
index 679b2a3..1040ded 100644
--- a/src/js/sound.js
+++ b/src/js/sound.js
@@ -1,120 +1,139 @@
+/* global ttsAudioFile, path, resourcesPath, settings, fs, notificationSound, backend, socket, requestData */
+
let trueMessage = '';
let currentLogoUrl = '';
let currentUsername = '';
-let voiceSoundArray = [];
+const voiceSoundArray = [];
let status = 0;
-let counter = 0;
+const counter = 0;
-const playTTS = (data) =>
- new Promise((resolve) => {
- ttsAudioFile = path.join(resourcesPath, `./sounds/tts/${data.service}_${data.count}.mp3`);
- const tts = new Audio(ttsAudioFile);
- console.log(settings.AUDIO.TTS_AUDIO_DEVICE);
- tts.setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE);
+const playTTS = data =>
+ new Promise(resolve => {
+ ttsAudioFile = path.join(resourcesPath, `./sounds/tts/${data.service}_${data.count}.mp3`);
+ const tts = new Audio(ttsAudioFile);
+ // console.log(settings.AUDIO.TTS_AUDIO_DEVICE);
+ tts.setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE);
- tts.addEventListener('ended', () => {
- console.log('ended');
- fs.unlink(ttsAudioFile, (err) => {
- if (err) {
- console.error('TEST');
-
- resolve('finished');
- return;
- }
- resolve('finished');
- });
- });
-
- tts.setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE)
- .then(() => {
- console.log('playing');
- tts.volume = settings.AUDIO.TTS_VOLUME / 100;
- tts.play().catch((error) => {
- resolve('finished');
- });
- })
- .catch((error) => {
- console.error('Failed to set audio output device:', error);
- resolve('finished');
- });
+ tts.addEventListener('ended', () => {
+ // console.log('ended');
+ fs.unlink(ttsAudioFile, err => {
+ if (err) {
+ console.error(err);
+ resolve('finished');
+ return;
+ }
+ resolve('finished');
+ });
});
+ tts
+ .setSinkId(settings.AUDIO.TTS_AUDIO_DEVICE)
+ .then(() => {
+ // console.log('playing');
+ tts.volume = settings.AUDIO.TTS_VOLUME / 100;
+ tts.play().catch(error => {
+ if (error) {
+ console.error(error);
+ }
+ resolve('finished');
+ });
+ })
+ .catch(error => {
+ console.error('Failed to set audio output device:', error);
+ resolve('finished');
+ });
+ });
+
async function shiftVoice() {
- status = 1;
- while (voiceSoundArray.length > 0) {
- await playTTS(voiceSoundArray.shift());
- }
- status = 0;
+ status = 1;
+ while (voiceSoundArray.length > 0) {
+ await playTTS(voiceSoundArray.shift());
+ }
+ status = 0;
}
function add(data) {
- voiceSoundArray.push(data);
- if (status === 0) {
- shiftVoice();
- }
+ voiceSoundArray.push(data);
+ if (status === 0) {
+ shiftVoice();
+ }
}
function playNotificationSound() {
- if (settings.AUDIO.USE_NOTIFICATION_SOUNDS) {
- let notfication = new Audio(
- path.join(resourcesPath, `./sounds/notifications/${notificationSound.options[settings.AUDIO.NOTIFICATION_SOUND].text}`),
- );
+ if (settings.AUDIO.USE_NOTIFICATION_SOUNDS) {
+ const notfication = new Audio(
+ path.join(resourcesPath, `./sounds/notifications/${notificationSound.options[settings.AUDIO.NOTIFICATION_SOUND].text}`)
+ );
+
+ notfication
+ .setSinkId(settings.AUDIO.SELECTED_NOTIFICATION_AUDIO_DEVICE)
+ .then(() => {
+ // console.log('playing');
notfication.volume = settings.AUDIO.NOTIFICATION_VOLUME / 100;
- notfication.play();
- }
+ notfication.play().catch(error => {
+ if (error) {
+ console.error(error);
+ }
+ });
+ })
+ .catch(error => {
+ console.error('Failed to set audio output device:', error);
+ });
+ }
}
// Play sound function
function playAudio(data) {
- if (data.service !== '') {
- add(data);
- }
+ if (data.service !== '') {
+ add(data);
+ }
}
async function playVoice(filteredMessage, logoUrl, username, message) {
- trueMessage = filteredMessage;
- currentLogoUrl = logoUrl;
- currentUsername = username;
- let textObject = { filtered: filteredMessage, formatted: message };
- let voice;
- textObject.filtered = `${username}: ${filteredMessage}`;
+ trueMessage = filteredMessage;
+ currentLogoUrl = logoUrl;
+ currentUsername = username;
+ const textObject = { filtered: filteredMessage, formatted: message };
+ let voice;
+ textObject.filtered = `${username}: ${filteredMessage}`;
- // 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 = settings.TTS.PRIMARY_TTS_NAME;
- // textObject.filtered = `${username}: ${filteredMessage}`;
- // }
+ // 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 = settings.TTS.PRIMARY_TTS_NAME;
+ // textObject.filtered = `${username}: ${filteredMessage}`;
+ // }
- const service = document.getElementById('primaryTTSService').value;
+ const service = document.getElementById('primaryTTSService').value;
- switch (service) {
- case 'Internal':
- const requestData = {
- message: textObject.filtered,
- voice: settings.TTS.PRIMARY_VOICE,
- };
+ switch (service) {
+ case 'Internal': {
+ const requestData = {
+ message: textObject.filtered,
+ voice: settings.TTS.PRIMARY_VOICE
+ };
- let count = await backend.getInternalTTSAudio(requestData);
- playAudio({ service, message: textObject, count });
- break;
- case 'Amazon':
- // playAudio({ service: 'Amazon', message: textObject, count });
- break;
- case 'Google':
- // playAudio({ service: 'Google', message: textObject, count });
- break;
+ const count = await backend.getInternalTTSAudio(requestData);
+ playAudio({ service, message: textObject, count });
+ break;
}
+ case 'Amazon':
+ // playAudio({ service: 'Amazon', message: textObject, count });
+ break;
+ case 'Google':
+ // playAudio({ service: 'Google', message: textObject, count });
+ break;
+ }
- if (settings.MODULES.USE_CHATBUBBLE) {
- socket.emit('xxx', currentLogoUrl, currentUsername, textObject);
- }
+ if (settings.MODULES.USE_CHATBUBBLE) {
+ socket.emit('xxx', currentLogoUrl, currentUsername, textObject);
+ }
- playNotificationSound();
+ playNotificationSound();
}
module.exports = { playAudio, playVoice, playNotificationSound };
diff --git a/src/js/theme.js b/src/js/theme.js
index d324b87..8fb2653 100644
--- a/src/js/theme.js
+++ b/src/js/theme.js
@@ -1,145 +1,143 @@
+/* global settings, root, fs, settingsPath, ini */
+
function changeColor(section, setting, tempSection) {
- document.querySelector(section).value = setting;
- const value = document.querySelector(section).value;
- root.style.setProperty(tempSection, value);
+ 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',
- );
+ 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');
- }
+ 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');
+ }
}
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);
+ 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', () => {
- 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');
+ 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', () => {
- const x = document.getElementById('MAIN_COLOR_2').value;
- root.style.setProperty('--main-color2-temp', x);
+ const x = document.getElementById('MAIN_COLOR_2').value;
+ root.style.setProperty('--main-color2-temp', x);
});
document.body.querySelector('#MAIN_COLOR_2').addEventListener('change', () => {
- 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');
+ 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', () => {
- const x = document.getElementById('MAIN_COLOR_3').value;
- root.style.setProperty('--main-color3-temp', x);
+ const x = document.getElementById('MAIN_COLOR_3').value;
+ root.style.setProperty('--main-color3-temp', x);
});
document.body.querySelector('#MAIN_COLOR_3').addEventListener('change', () => {
- 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');
+ 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', () => {
- const x = document.getElementById('MAIN_COLOR_4').value;
- root.style.setProperty('--main-color4-temp', x);
+ const x = document.getElementById('MAIN_COLOR_4').value;
+ root.style.setProperty('--main-color4-temp', x);
});
document.body.querySelector('#MAIN_COLOR_4').addEventListener('change', () => {
- 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');
+ 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', () => {
- const x = document.getElementById('TOP_BAR').value;
- root.style.setProperty('--top-bar-temp', x);
+ const x = document.getElementById('TOP_BAR').value;
+ root.style.setProperty('--top-bar-temp', x);
});
document.body.querySelector('#TOP_BAR').addEventListener('change', () => {
- settings.THEME.TOP_BAR = document.getElementById('TOP_BAR').value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- changeColor('#TOP_BAR', settings.THEME.TOP_BAR, '--top-bar');
+ 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', () => {
- const x = document.getElementById('MID_SECTION').value;
- root.style.setProperty('--mid-section-temp', x);
+ const x = document.getElementById('MID_SECTION').value;
+ root.style.setProperty('--mid-section-temp', x);
});
document.body.querySelector('#MID_SECTION').addEventListener('change', () => {
- settings.THEME.MID_SECTION = document.getElementById('MID_SECTION').value;
- fs.writeFileSync(settingsPath, ini.stringify(settings));
- changeColor('#MID_SECTION', settings.THEME.MID_SECTION, '--mid-section');
+ 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', () => {
- const x = document.getElementById('CHAT_BUBBLE_BG').value;
- root.style.setProperty('--chat-bubble-temp', x);
+ const x = document.getElementById('CHAT_BUBBLE_BG').value;
+ root.style.setProperty('--chat-bubble-temp', x);
});
document.body.querySelector('#CHAT_BUBBLE_BG').addEventListener('change', () => {
- 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');
+ 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', () => {
- const x = document.getElementById('CHAT_BUBBLE_HEADER').value;
- root.style.setProperty('--chat-bubble-header-temp', x);
+ const x = document.getElementById('CHAT_BUBBLE_HEADER').value;
+ root.style.setProperty('--chat-bubble-header-temp', x);
});
document.body.querySelector('#CHAT_BUBBLE_HEADER').addEventListener('change', () => {
- 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');
+ 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', () => {
- const x = document.getElementById('CHAT_BUBBLE_MESSAGE').value;
- root.style.setProperty('--chat-bubble-message-temp', x);
+ const x = document.getElementById('CHAT_BUBBLE_MESSAGE').value;
+ root.style.setProperty('--chat-bubble-message-temp', x);
});
document.body.querySelector('#CHAT_BUBBLE_MESSAGE').addEventListener('change', () => {
- 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');
+ 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');
});
module.exports = { setTheme };
diff --git a/src/js/twitch.js b/src/js/twitch.js
index 6f3ec65..781a85a 100644
--- a/src/js/twitch.js
+++ b/src/js/twitch.js
@@ -1,144 +1,186 @@
+/* global client, customEmojis, emojiPicker, settings, options, sound, showChatMessage, messageTemplates, getPostTime */
+
const tmi = require('tmi.js');
const axios = require('axios');
-let client;
+let client = null;
+let logoUrl = null;
function sendMessage(message) {
- client.say(settings.TWITCH.CHANNEL_NAME, message).catch(console.error);
+ client.say(settings.TWITCH.CHANNEL_NAME, message).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],
+ 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);
+ .connect()
+ .then(data => {})
+ .catch(console.error);
function ping(element) {
- let value = document.body.querySelector(element);
+ const value = document.body.querySelector(element);
- client
- .ping()
- .then((data) => {
- value.classList.add('success');
- value.innerText = 'Success!';
- })
- .catch((e) => {
- value.classList.add('error');
- value.innerText = 'Failed!';
- });
+ client
+ .ping()
+ .then(data => {
+ value.classList.add('success');
+ value.innerText = 'Success!';
+ })
+ .catch(e => {
+ value.classList.add('error');
+ value.innerText = 'Failed!';
+ });
}
function displayTwitchMessage(logoUrl, username, messageObject, fileteredMessage) {
- const article = document.createElement('article');
- article.className = 'msg-container sender';
+ const article = document.createElement('article');
+ article.className = 'msg-container sender';
- article.innerHTML = messageTemplates.twitchTemplate;
+ article.innerHTML = messageTemplates.twitchTemplate;
- const userImg = article.querySelector('.user-img');
- if (userImg) {
- userImg.src = logoUrl;
- }
+ const userImg = article.querySelector('.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');
+ const postTime = article.querySelector('.post-time');
- if (postTime) {
- postTime.innerText = getPostTime();
- }
+ if (postTime) {
+ postTime.innerText = getPostTime();
+ }
- article.appendChild(postTime);
+ article.appendChild(postTime);
- const msg = article.querySelector('.msg-box');
- if (msg) {
- messageObject.forEach((entry) => {
- if (entry.text) {
- msg.innerHTML += entry.text;
- } else {
- msg.innerHTML += entry.html;
- }
- });
- }
+ const msg = article.querySelector('.msg-box');
+ if (msg) {
+ messageObject.forEach(entry => {
+ if (entry.text) {
+ msg.innerHTML += entry.text;
+ } else {
+ msg.innerHTML += entry.html;
+ }
+ });
+ }
- // Appends the message to the main chat box (shows the message)
- showChatMessage(article, false);
+ // 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 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}` },
- };
+ // 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((responseLogoUrl) => {
- const logoUrl = responseLogoUrl.data.data[0].profile_image_url;
- displayTwitchMessage(logoUrl, username, message, fileteredMessage);
- })
- .catch((error) => {
- console.error(error);
- });
+ axios
+ .request(options)
+ .then(responseLogoUrl => {
+ 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;
- }
- const emotes = tags.emotes || {};
- const emoteValues = Object.entries(emotes);
- let fileteredMessage = message;
- let emoteMessage = message;
+ if (self) {
+ return;
+ }
+ const emotes = tags.emotes || {};
+ const emoteValues = Object.entries(emotes);
+ let filteredMessage = 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('-');
+ const emote = `
`;
+ emoteMessage = emoteMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), emote);
+ filteredMessage = filteredMessage.replaceAll(message.slice(parseInt(start), parseInt(end) + 1), '');
});
+ });
- let messageObject = parseString(emoteMessage);
- getProfileImage(tags['user-id'], tags['display-name'], messageObject, fileteredMessage);
+ const messageObject = parseString(emoteMessage);
+ getProfileImage(tags['user-id'], tags['display-name'], messageObject, filteredMessage);
});
+function formatTwitchEmojis(emojis, name) {
+ emojis.forEach(emoji => {
+ const emojiToBeAdded = {
+ name: emoji.name,
+ shortcodes: [emoji.name],
+ url: emoji.images.url_1x,
+ category: name
+ };
+ customEmojis.push(emojiToBeAdded);
+ });
+ emojiPicker.customEmoji = customEmojis;
+}
+
+function getTwitchGLobalEmotes() {
+ // Get user Logo with access token
+ options = {
+ method: 'GET',
+ url: 'https://api.twitch.tv/helix/chat/emotes/global',
+ headers: {
+ 'Client-ID': settings.TWITCH.CLIENT_ID,
+ Authorization: `Bearer ${settings.TWITCH.OAUTH_TOKEN}`
+ }
+ };
+
+ axios
+ .request(options)
+ .then(responseLogoUrl => {
+ formatTwitchEmojis(responseLogoUrl.data.data, 'Twitch Global');
+ // console.log(responseLogoUrl);
+ })
+ .catch(error => {
+ console.error(error);
+ });
+}
+
+if (settings.TWITCH.OAUTH_TOKEN) {
+ getTwitchGLobalEmotes();
+}
+
module.exports = { sendMessage, ping, client };
diff --git a/src/main.js b/src/main.js
index 0bd5fab..b1a134f 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,3 +1,5 @@
+/* global pythonPath, a */
+
const { app, BrowserWindow, ipcMain } = require('electron');
const { writeIniFile } = require('write-ini-file');
const path = require('path');
@@ -14,197 +16,199 @@ let settings;
let window;
if (app.isPackaged) {
- settingsPath = path.join(process.resourcesPath, './settings.ini');
- pythonPath = path.join(process.resourcesPath, './backend');
- resourcesPath = process.resourcesPath;
+ settingsPath = path.join(process.resourcesPath, './settings.ini');
+ pythonPath = path.join(process.resourcesPath, './backend');
+ resourcesPath = process.resourcesPath;
} else {
- settingsPath = path.join(resourcesPath, './config/settings.ini');
- pythonPath = path.join(resourcesPath, './backend');
+ settingsPath = path.join(resourcesPath, './config/settings.ini');
+ pythonPath = path.join(resourcesPath, './backend');
}
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) {
- app.quit();
+ app.quit();
}
async function createWindow() {
- if (!fs.existsSync(settingsPath)) {
- console.log(resourcesPath);
- await createIniFile();
- } else {
- settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8'));
+ if (!fs.existsSync(settingsPath)) {
+ console.log(resourcesPath);
+ await createIniFile();
+ } else {
+ settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8'));
+ }
+
+ window = new BrowserWindow({
+ icon: path.join(__dirname, '/images/icon-512.png'),
+ width: parseInt(settings.GENERAL.WIDTH),
+ height: parseInt(settings.GENERAL.HEIGHT),
+ x: parseInt(settings.GENERAL.POSITION_X),
+ y: parseInt(settings.GENERAL.POSITION_Y),
+ frame: false,
+ webPreferences: {
+ nodeIntegration: true,
+ contextIsolation: false,
+ enableRemoteModule: true
}
+ });
- window = new BrowserWindow({
- icon: path.join(__dirname, '/images/icon-512.png'),
- width: parseInt(settings.GENERAL.WIDTH),
- height: parseInt(settings.GENERAL.HEIGHT),
- x: parseInt(settings.GENERAL.POSITION_X),
- y: parseInt(settings.GENERAL.POSITION_Y),
- frame: false,
- webPreferences: {
- nodeIntegration: true,
- contextIsolation: false,
- enableRemoteModule: true,
- },
- });
+ window.loadFile(path.join(__dirname, 'index.html'));
- window.loadFile(path.join(__dirname, 'index.html'));
+ if (!app.isPackaged) {
+ window.webContents.openDevTools();
+ }
- if (!app.isPackaged) {
- window.webContents.openDevTools();
- }
+ 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();
- 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.GENERAL.WIDTH = bounds.width;
+ settings.GENERAL.HEIGHT = bounds.height;
+ settings.GENERAL.POSITION_X = bounds.x;
+ settings.GENERAL.POSITION_Y = bounds.y;
- settings.GENERAL.WIDTH = bounds.width;
- settings.GENERAL.HEIGHT = bounds.height;
- settings.GENERAL.POSITION_X = bounds.x;
- settings.GENERAL.POSITION_Y = bounds.y;
-
- fs.writeFileSync(settingsPath, 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();
- }
+app.on('window-all-closed', event => {
+ if (process.platform !== 'darwin') {
+ app.quit();
+ }
});
app.on('activate', () => {
- if (BrowserWindow.getAllWindows().length === 0) {
- createWindow();
- }
+ if (BrowserWindow.getAllWindows().length === 0) {
+ createWindow();
+ }
});
app.on('before-quit', () => {
- window.webContents.send('quit-event');
+ window.webContents.send('quit-event');
});
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();
+ipcMain.on('minimize-window', event => {
+ const browserWindow = BrowserWindow.fromWebContents(event.sender);
+ browserWindow.minimize();
});
-ipcMain.on('maximize-window', (event) => {
- const browserWindow = BrowserWindow.fromWebContents(event.sender);
+ipcMain.on('maximize-window', event => {
+ 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);
- kill('loquendoBot_backend');
- browserWindow.close();
- app.quit();
+ipcMain.on('close-window', event => {
+ const browserWindow = BrowserWindow.fromWebContents(event.sender);
+ kill('loquendoBot_backend');
+ browserWindow.close();
+ app.quit();
});
-ipcMain.on('restart', (event) => {
- app.relaunch();
+ipcMain.on('restart', event => {
+ app.relaunch();
});
-ipcMain.on('environment', (event) => {
- event.returnValue = { resourcesPath, pythonPath, settingsPath, settings, isPackaged: app.isPackaged };
+ipcMain.on('environment', event => {
+ event.returnValue = { resourcesPath, pythonPath, settingsPath, settings, isPackaged: app.isPackaged };
});
async function createIniFile() {
- await writeIniFile(settingsPath, {
- GENERAL: {
- VOICE_ENABLED: true,
- NOTIFICATION_ENABLED: true,
- POSITION_X: 0,
- POSITION_Y: 0,
- WIDTH: 1024,
- HEIGHT: 768,
- LANGUAGE: 'EN',
- PORT: 9000,
- VIEWERS_PANEL: false,
- LOCATION: pythonPath,
- },
- LANGUAGE: {
- USE_DETECTION: false,
- },
- TTS: {
- USE_TTS: true,
- PRIMARY_VOICE: '',
- PRIMARY_TTS_LANGUAGE: 'EN',
- SECONDARY_VOICE: '',
- SECONDARY_TTS_LANGUAGE: 'EN',
- },
- STT: {
- USE_STT: false,
- MICROPHONE_ID: 'default',
- SELECTED_MICROPHONE: 'default',
- MICROPHONE: 0,
- LANGUAGE: 'vosk-model-small-es-0.42',
- },
- AUDIO: {
- USE_NOTIFICATION_SOUNDS: true,
- NOTIFICATION_AUDIO_DEVICE: 0,
- NOTIFICATION_SOUND: 0,
- NOTIFICATION_VOLUME: 50,
- SELECTED_TTS_AUDIO_DEVICE: 0,
- TTS_AUDIO_DEVICE: 'default',
- TTS_VOLUME: 50,
- },
- 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: '',
- USER_ID: '',
- USER_LOGO_URL: '',
- OAUTH_TOKEN: '',
- CLIENT_ID: '2t206sj7rvtr1rutob3p627d13jch9',
- },
- MODULES: {
- USE_MODULES: false,
- USE_VTUBER: false,
- USE_CHATBUBBLE: false,
- },
- AMAZON: {
- USE_AMAZON: false,
- ACCESS_KEY: '',
- ACCESS_SECRET: '',
- PRIMARY_VOICE: '',
- SECONDARY_VOICE: '',
- CHARACTERS_USED: 0,
- },
- GOOGLE: {
- USE_GOOGLE: false,
- API_KEY: '',
- PRIMARY_VOICE: '',
- SECONDARY_VOICE: '',
- CHARACTERS_USED: 0,
- },
- }).then(() => {
- settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8'));
- });
+ await writeIniFile(settingsPath, {
+ GENERAL: {
+ VOICE_ENABLED: true,
+ NOTIFICATION_ENABLED: true,
+ POSITION_X: 0,
+ POSITION_Y: 0,
+ WIDTH: 1024,
+ HEIGHT: 768,
+ LANGUAGE: 'EN',
+ PORT: 9000,
+ VIEWERS_PANEL: false,
+ LOCATION: pythonPath,
+ ZOOMLEVEL: 1
+ },
+ LANGUAGE: {
+ USE_DETECTION: false
+ },
+ TTS: {
+ USE_TTS: true,
+ PRIMARY_VOICE: '',
+ PRIMARY_TTS_LANGUAGE: 'EN',
+ SECONDARY_VOICE: '',
+ SECONDARY_TTS_LANGUAGE: 'EN'
+ },
+ STT: {
+ USE_STT: false,
+ MICROPHONE_ID: 'default',
+ SELECTED_MICROPHONE: 'default',
+ MICROPHONE: 0,
+ LANGUAGE: 'vosk-model-small-es-0.42'
+ },
+ AUDIO: {
+ USE_NOTIFICATION_SOUNDS: true,
+ SELECTED_NOTIFICATION_AUDIO_DEVICE: 'default',
+ NOTIFICATION_AUDIO_DEVICE: 0,
+ NOTIFICATION_SOUND: 0,
+ NOTIFICATION_VOLUME: 50,
+ SELECTED_TTS_AUDIO_DEVICE: 0,
+ TTS_AUDIO_DEVICE: 'default',
+ TTS_VOLUME: 50
+ },
+ 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: '',
+ USER_ID: '',
+ USER_LOGO_URL: '',
+ OAUTH_TOKEN: '',
+ CLIENT_ID: '2t206sj7rvtr1rutob3p627d13jch9'
+ },
+ MODULES: {
+ USE_MODULES: false,
+ USE_VTUBER: false,
+ USE_CHATBUBBLE: false
+ },
+ AMAZON: {
+ USE_AMAZON: false,
+ ACCESS_KEY: '',
+ ACCESS_SECRET: '',
+ PRIMARY_VOICE: '',
+ SECONDARY_VOICE: '',
+ CHARACTERS_USED: 0
+ },
+ GOOGLE: {
+ USE_GOOGLE: false,
+ API_KEY: '',
+ PRIMARY_VOICE: '',
+ SECONDARY_VOICE: '',
+ CHARACTERS_USED: 0
+ }
+ }).then(() => {
+ settings = ini.parse(fs.readFileSync(settingsPath, 'utf-8'));
+ });
}
diff --git a/src/modules/chat/index.html b/src/modules/chat/index.html
index c961cd4..81150e7 100644
--- a/src/modules/chat/index.html
+++ b/src/modules/chat/index.html
@@ -1,23 +1,23 @@
-
+
-
- Chat
-
-
-
-
-
-
-
-
-
-
+
+ Chat
+
+
+
+
+
+
+
+
+
+
diff --git a/src/modules/chat/main.css b/src/modules/chat/main.css
index bea4e5b..ff681e4 100644
--- a/src/modules/chat/main.css
+++ b/src/modules/chat/main.css
@@ -1,171 +1,171 @@
body {
- background-color: transparent;
- font-family: 'FRAMDCN';
+ background-color: transparent;
+ font-family: 'FRAMDCN';
}
:root {
- --variable: 2s;
- --buttonBackground: #bf2c2c;
+ --variable: 2s;
+ --buttonBackground: #bf2c2c;
}
.thomas {
- position: relative;
- float: center;
- display: inline-block;
+ position: relative;
+ float: center;
+ /* display: inline-block; */
}
.speechbubble {
- display: block;
- bottom: 0;
- position: absolute;
- z-index: -1;
+ display: block;
+ bottom: 0;
+ position: absolute;
+ z-index: -1;
}
.fade-outx {
- animation: fade-outx var(--variable) linear;
+ animation: fade-outx var(--variable) linear;
}
@keyframes fade-outx {
- from {
- opacity: 1;
- }
+ from {
+ opacity: 1;
+ }
- to {
- opacity: 0;
- }
+ to {
+ opacity: 0;
+ }
}
.fade-outxx {
- animation: fade-outxx var(--variable) linear;
+ animation: fade-outxx var(--variable) linear;
}
@keyframes fade-outxx {
- from {
- opacity: 1;
- }
+ from {
+ opacity: 1;
+ }
- to {
- opacity: 0;
- }
+ to {
+ opacity: 0;
+ }
}
.bounce-in {
- animation: bounce-in 1s ease;
+ animation: bounce-in 1s ease;
}
@keyframes bounce-in {
- 0% {
- opacity: 0;
- transform: scale(0.3);
- }
+ 0% {
+ opacity: 0;
+ transform: scale(0.3);
+ }
- 50% {
- opacity: 1;
- transform: scale(1.05);
- }
+ 50% {
+ opacity: 1;
+ transform: scale(1.05);
+ }
- 70% {
- transform: scale(0.9);
- }
+ 70% {
+ transform: scale(0.9);
+ }
- 100% {
- transform: scale(1);
- }
+ 100% {
+ transform: scale(1);
+ }
}
.bounce-inx {
- animation: bounce-inx 1s ease;
+ animation: bounce-inx 1s ease;
}
@keyframes bounce-inx {
- 0% {
- opacity: 0;
- }
+ 0% {
+ opacity: 0;
+ }
- 50% {
- opacity: 1;
- }
+ 50% {
+ opacity: 1;
+ }
}
.msg-container {
- position: static;
- display: inline-block;
- width: 100%;
- padding-top: 10px;
+ position: static;
+ display: inline-block;
+ width: 100%;
+ padding-top: 10px;
}
.message-window {
- height: calc(100% - 50px);
- overflow: hidden;
- overflow-y: hidden;
- display: flex;
- flex-direction: column;
- width: 80%;
- margin: auto;
- background: transparent;
+ height: calc(100% - 50px);
+ overflow: hidden;
+ overflow-y: hidden;
+ display: flex;
+ flex-direction: column;
+ width: 80%;
+ margin: auto;
+ background: transparent;
}
.message-window::before {
- content: '';
- flex: 1 0 0px;
+ content: '';
+ flex: 1 0 0px;
}
.OptionPanel {
- flex: 3;
- display: none;
- position: absolute;
- top: 10px;
- left: 0;
- width: 100%;
- height: calc(100% - 25px);
- background: transparent;
+ flex: 3;
+ display: none;
+ position: absolute;
+ top: 10px;
+ left: 0;
+ width: 100%;
+ height: calc(100% - 25px);
+ background: transparent;
}
.OptionPanel.show {
- display: block;
+ display: block;
}
.message {
- text-align: left;
- max-width: 100%;
- height: auto;
- min-width: 125px;
- hyphens: auto;
- bottom: 0;
- right: 0;
- float: right;
- overflow-wrap: break-word;
+ text-align: left;
+ max-width: 100%;
+ height: auto;
+ min-width: 125px;
+ hyphens: auto;
+ bottom: 0;
+ right: 0;
+ float: right;
+ overflow-wrap: break-word;
}
.message {
- position: relative;
- border: 2px solid #ff80e1;
- box-shadow: 0 2px 10px rgba(255, 128, 225, 0.5);
- background: linear-gradient(45deg, rgb(15, 12, 41, 0.7), rgb(48, 43, 99, 0.7));
- /* background: linear-gradient(45deg, rgba(72, 0, 154, 0.7), rgba(138, 43, 226, 0.7)); */
+ position: relative;
+ border: 2px solid #ff80e1;
+ box-shadow: 0 2px 10px rgba(255, 128, 225, 0.5);
+ background: linear-gradient(45deg, rgb(15, 12, 41, 0.7), rgb(48, 43, 99, 0.7));
+ /* background: linear-gradient(45deg, rgba(72, 0, 154, 0.7), rgba(138, 43, 226, 0.7)); */
- color: white;
- padding: 15px;
- border-radius: 20px;
+ color: white;
+ padding: 15px;
+ border-radius: 20px;
}
-
+/*
.message::after {
-}
+} */
.arrow {
- content: '';
- border: 2px solid #ff80e1;
- position: absolute;
- left: 50%;
- top: 100%;
- transform: translateX(-50%) rotate(180deg);
- border-width: 10px;
- border-style: solid;
- border-color: transparent transparent rgb(255, 128, 225, 0.7) transparent;
- color: #ff80e1;
+ content: '';
+ border: 2px solid #ff80e1;
+ position: absolute;
+ left: 50%;
+ top: 100%;
+ transform: translateX(-50%) rotate(180deg);
+ border-width: 10px;
+ border-style: solid;
+ border-color: transparent transparent rgb(255, 128, 225, 0.7) transparent;
+ color: #ff80e1;
}
.sender {
- color: #ff80e1;
- font-size: 14pt;
+ color: #ff80e1;
+ font-size: 14pt;
}
diff --git a/src/modules/chat/main.js b/src/modules/chat/main.js
index d4e92b9..5d01727 100644
--- a/src/modules/chat/main.js
+++ b/src/modules/chat/main.js
@@ -1,3 +1,5 @@
+/* global io */
+
// Connect to the Socket.IO server
const socket = io();
@@ -5,18 +7,18 @@ const socket = io();
socket.emit('message', 'Hello, Server!');
function getPostTime() {
- const d = new Date();
- document.body.querySelectorAll('.container').innerHTML = d.getHours();
- const hours = d.getHours();
- const minutes = (d.getMinutes() < 10 ? '0' : '') + d.getMinutes();
- const time = `${hours}:${minutes}`;
- return time;
+ const d = new Date();
+ document.body.querySelectorAll('.container').innerHTML = d.getHours();
+ const hours = d.getHours();
+ const minutes = (d.getMinutes() < 10 ? '0' : '') + d.getMinutes();
+ const time = `${hours}:${minutes}`;
+ return time;
}
function showChatMessage(article) {
- const main = document.querySelector('#chatBox');
- main.appendChild(article);
- main.scrollTop = main.scrollHeight;
+ const main = document.querySelector('#chatBox');
+ main.appendChild(article);
+ main.scrollTop = main.scrollHeight;
}
let textStreamContainer;
@@ -28,96 +30,96 @@ let x;
let currentIndex = 0;
let messageStream = '';
-let tempMessageObject = '';
-let fullMessageLength = 0;
+const tempMessageObject = '';
+const fullMessageLength = 0;
function getFullMessageLength(text) {
- let fullMessageLength = 0;
- text.forEach((element) => {
- if (element.text) {
- fullMessageLength += element.text.length;
- }
- element.html;
- fullMessageLength += 1;
- });
+ let fullMessageLength = 0;
+ text.forEach(element => {
+ if (element.text) {
+ fullMessageLength += element.text.length;
+ }
+ // element.html;
+ fullMessageLength += 1;
+ });
- return fullMessageLength;
+ return fullMessageLength;
}
function streamText() {
- // if (currentIndex < fullMessageLength) {
+ // if (currentIndex < fullMessageLength) {
- // textStreamContainer.innerHTML += messageStream.filtered.charAt(currentIndex);
- // currentIndex++;
- // setTimeout(streamText, 50);
- // }
- if (currentIndex < messageStream.length) {
- textStreamContainer.innerHTML += messageStream.charAt(currentIndex);
- currentIndex++;
- setTimeout(streamText, 50);
- } else {
- currentIndex = 0;
- x.classList.add('fade-outx');
- }
+ // textStreamContainer.innerHTML += messageStream.filtered.charAt(currentIndex);
+ // currentIndex++;
+ // setTimeout(streamText, 50);
+ // }
+ if (currentIndex < messageStream.length) {
+ textStreamContainer.innerHTML += messageStream.charAt(currentIndex);
+ currentIndex++;
+ setTimeout(streamText, 50);
+ } else {
+ currentIndex = 0;
+ x.classList.add('fade-outx');
+ }
}
function displayTwitchMessage(logoUrl, username, messageObject) {
- if (!messageObject) {
- return;
+ if (!messageObject) {
+ return;
+ }
+
+ const root = document.querySelector(':root');
+ root.style.setProperty('--variable', '5s');
+
+ const article = document.createElement('article');
+ x = article;
+
+ article.className = 'msg-container';
+
+ const placeMessage = `
+
+ `.trim();
+
+ article.innerHTML = placeMessage;
+ const msg = article.querySelector('.message');
+
+ msg.innerHTML = `${username}
`; // \n${message}`;
+
+ msg.style.fontSize = '12pt';
+
+ showChatMessage(article);
+
+ const elements = document.getElementsByClassName('msg-container');
+ if (elements.length > 1) {
+ elements[0].remove();
+ }
+
+ article.addEventListener('animationend', e => {
+ if (e.animationName === 'fade-outx') {
+ article.remove();
}
+ });
- const root = document.querySelector(':root');
- root.style.setProperty('--variable', '5s');
-
- const article = document.createElement('article');
- x = article;
-
- article.className = 'msg-container';
-
- const placeMessage = `
-
- `.trim();
-
- article.innerHTML = placeMessage;
- const msg = article.querySelector('.message');
-
- msg.innerHTML = `${username}
`; //\n${message}`;
-
- msg.style.fontSize = '12pt';
-
- showChatMessage(article);
-
- const elements = document.getElementsByClassName('msg-container');
- if (elements.length > 1) {
+ if (elements.length > 1) {
+ elements[0].classList.add('fade-outxx');
+ elements[0].addEventListener('animationend', e => {
+ if (e.animationName === 'fade-outxx') {
elements[0].remove();
- }
-
- article.addEventListener('animationend', (e) => {
- if (e.animationName == 'fade-outx') {
- article.remove();
- }
+ }
});
-
- if (elements.length > 1) {
- elements[0].classList.add('fade-outxx');
- elements[0].addEventListener('animationend', (e) => {
- if (e.animationName == 'fade-outxx') {
- elements[0].remove();
- }
- });
- }
- // fullMessageLength = getFullMessageLength(messageObject);
- messageStream = messageObject.filtered;
- textStreamContainer = document.querySelector('.message');
- streamText();
+ }
+ // fullMessageLength = getFullMessageLength(messageObject);
+ messageStream = messageObject.filtered;
+ textStreamContainer = document.querySelector('.message');
+ streamText();
}
// // Receive a message from the server
socket.on('message', (logoUrl, username, message, messageDuration) => {
- displayTwitchMessage(logoUrl, username, message);
+ displayTwitchMessage(logoUrl, username, message);
});
diff --git a/src/modules/vtuber/css/about.css b/src/modules/vtuber/css/about.css
index 768ed15..8db9f7a 100644
--- a/src/modules/vtuber/css/about.css
+++ b/src/modules/vtuber/css/about.css
@@ -20,8 +20,8 @@ body {
padding-left: 40dip;
padding-right: 10dip;
vertical-align: top;
- foreground-repeat: no-repeat;
- foreground-position: 16dip 50%;
+ /* foreground-repeat: no-repeat;
+ foreground-position: 16dip 50%; */
background-repeat: no-repeat;
background-position: 10dip 50%;
background-size: 64dip 64dip;
@@ -37,7 +37,7 @@ body {
.title {
font-weight: bold !important;
- flow: column !important;
+ /* flow: column !important; */
text-align: left !important;
margin: auto !important;
width: min-content !important;
@@ -86,12 +86,12 @@ img {
}
#button-bar {
- flow: horizontal;
+ /* flow: horizontal; */
padding: 10dip;
border-spacing: 10dip;
margin: 0;
- flow: horizontal;
- horizontal-align: right;
+ /* flow: horizontal; */
+ /* horizontal-align: right; */
}
label {
@@ -103,7 +103,7 @@ label {
text-shadow: #fff 0px 1px;
min-width: 4em;
line-height: 2em;
- vertical-align: middle;
+ /* vertical-align: middle; */
width: min-intrinsic;
text-align: center;
-}
\ No newline at end of file
+}
diff --git a/src/modules/vtuber/css/main.css b/src/modules/vtuber/css/main.css
index daf7def..59c2c06 100644
--- a/src/modules/vtuber/css/main.css
+++ b/src/modules/vtuber/css/main.css
@@ -1,386 +1,380 @@
* {
- box-sizing: border-box;
- image-rendering: optimize-quality;
+ box-sizing: border-box;
+ image-rendering: optimize-quality;
}
:disabled {
- display: none;
+ display: none;
}
html {
- overflow: hidden;
+ overflow: hidden;
}
body {
- margin: 0;
- padding: 16dip;
- position: relative;
- background-image: url('../png/grid.png');
- background-size: 70px;
- background-repeat: repeat;
+ margin: 0;
+ padding: 16dip;
+ position: relative;
+ background-image: url('../png/grid.png');
+ background-size: 70px;
+ background-repeat: repeat;
}
#controls {
- height: 100%;
- width: 100%;
- /* flow: horizontal; */
- overflow: hidden;
- display: flex;
+ height: 100%;
+ width: 100%;
+ /* flow: horizontal; */
+ overflow: hidden;
+ display: flex;
}
#controls-left {
- order: 2px solid cyan;
- width: 7%;
- height: 10%;
- /* flow: vertical; */
- border-spacing: 1%;
+ order: 2px solid cyan;
+ width: 7%;
+ height: 10%;
+ /* flow: vertical; */
+ border-spacing: 1%;
}
#controls-top {
- height: 10%;
- width: 100%;
- /* flow: horizontal; */
- border-spacing: 1%;
- margin-left: 10px;
+ height: 10%;
+ width: 100%;
+ /* flow: horizontal; */
+ border-spacing: 1%;
+ margin-left: 10px;
}
#meters {
- display: flex;
- height: 50vh;
- /* flow: horizontal; */
- /* border-spacing: *; */
- position: relative;
+ display: flex;
+ height: 50vh;
+ /* flow: horizontal; */
+ /* border-spacing: *; */
+ position: relative;
}
#meter-microphone {
- margin-left: 10%;
- margin-right: 10%;
+ margin-left: 10%;
+ margin-right: 10%;
}
#meter-delay {
- margin-right: 20%;
+ margin-right: 20%;
}
#meter-microphone,
#meter-delay {
- height: 45vh;
- width: 25%;
- background-repeat: no-repeat;
+ height: 45vh;
+ width: 25%;
+ background-repeat: no-repeat;
}
-input[type='vslider']>button.slider {
- background-size: 100% auto;
- border-radius: 0;
- width: 275%;
- height: 5%;
- background-position: 0 50%;
- border-width: 0;
+input[type='vslider'] > button.slider {
+ background-size: 100% auto;
+ border-radius: 0;
+ width: 275%;
+ height: 5%;
+ background-position: 0 50%;
+ border-width: 0;
}
button {
- height: 50px;
- width: 50px;
- background-size: cover;
- overflow: hidden;
- border-style: none;
- background-color: transparent;
+ height: 50px;
+ width: 50px;
+ background-size: cover;
+ overflow: hidden;
+ border-style: none;
+ background-color: transparent;
}
-#meter-microphone>button.slider {
- background-image: url('../png/controls/meters/left.png');
+#meter-microphone > button.slider {
+ background-image: url('../png/controls/meters/left.png');
}
-#meter-delay>button.slider {
- background-image: url('../png/controls/meters/right.png');
+#meter-delay > button.slider {
+ background-image: url('../png/controls/meters/right.png');
}
#meter-microphone {
- color: #2ebe38;
+ color: #2ebe38;
}
#meter-delay {
- color: #453be2;
+ color: #453be2;
}
#slider-left {
- left: -25%;
+ left: -25%;
}
#slider-right {
- right: -25%;
+ right: -25%;
}
#buttons-left {
- width: 100%;
- height: 100%;
- box-shadow: none;
+ width: 100%;
+ height: 100%;
+ box-shadow: none;
}
#buttons-top {
- height: 50px;
- width: 100%;
- display: flex;
+ height: 50px;
+ width: 100%;
+ display: flex;
}
#buttons-left button {
- width: 50;
- height: 50px;
- display: flex;
- background-size: cover;
- overflow: hidden;
+ width: 50;
+ height: 50px;
+ display: flex;
+ background-size: cover;
+ overflow: hidden;
}
#buttons-top button {
- background-size: auto 100%;
- background-position: 50% 50%;
- border-width: 0;
- border-radius: 0;
+ background-size: auto 100%;
+ background-position: 50% 50%;
+ border-width: 0;
+ border-radius: 0;
}
#buttons-left button:active,
#about:active,
#close:active {
- filter: brightness(-10%);
+ filter: brightness(-10%);
}
popup[role='tooltip'] {
- color: white;
- background: rgba(0, 0, 0, 0.666);
- border-width: 0;
- padding: 0.333em;
- font-size: 1.25em;
- font-family: Calibri;
+ color: white;
+ background: rgba(0, 0, 0, 0.666);
+ border-width: 0;
+ padding: 0.333em;
+ font-size: 1.25em;
+ font-family: Calibri;
}
#microphone-device {
- background-image: url('../png/controls/buttons/left/mic.png');
+ background-image: url('../png/controls/buttons/left/mic.png');
}
#background-color {
- background-image: url('../png/controls/buttons/left/bg.png');
+ background-image: url('../png/controls/buttons/left/bg.png');
}
#open-file {
- background-image: url('../png/controls/buttons/left/open.png');
+ background-image: url('../png/controls/buttons/left/open.png');
}
#save-file {
- background-image: url('../png/controls/buttons/left/save.png');
+ background-image: url('../png/controls/buttons/left/save.png');
}
/* TOP ROW BUTTONS */
button.mouth-image.border-default {
- background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
- position: absolute;
- width: 50px;
- height: 50px;
- top: 0;
- bottom: 0;
+ background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
+ position: absolute;
+ width: 50px;
+ height: 50px;
+ top: 0;
+ bottom: 0;
}
button.mouth-image.border-add {
- background-image: url('../png/controls/buttons/top/avatar-change/border/add.png');
+ background-image: url('../png/controls/buttons/top/avatar-change/border/add.png');
}
button.mouth-image:active {
- filter: brightness(-10%);
+ filter: brightness(-10%);
}
button.mouth-image::before {
- position: absolute;
- top: 5%;
- right: 10%;
- width: 50px;
- height: 66%;
- background-size: 100% 100%;
- z-index: -1;
+ position: absolute;
+ top: 5%;
+ right: 10%;
+ width: 50px;
+ height: 66%;
+ background-size: 100% 100%;
+ z-index: -1;
}
button.mouth-image::after {
- position: absolute;
- top: 69%;
- left: 37%;
- width: 50px;
- height: 35%;
- transform: translate(-50%, -50%);
- background-size: 100% 100%;
+ position: absolute;
+ top: 69%;
+ left: 37%;
+ width: 50px;
+ height: 35%;
+ transform: translate(-50%, -50%);
+ background-size: 100% 100%;
}
#closed-mouth-image.border-default::before {
- background-image: url('../png/avatars/crab/closed.png');
+ background-image: url('../png/avatars/crab/closed.png');
}
#closed-mouth-image::after {
- background-image: url('../png/controls/buttons/top/avatar-change/closed.png');
+ background-image: url('../png/controls/buttons/top/avatar-change/closed.png');
}
#open-mouth-image.border-default::before {
- background-image: url('../png/avatars/crab/open.png');
+ background-image: url('../png/avatars/crab/open.png');
}
#open-mouth-image::after {
- background-image: url('../png/controls/buttons/top/avatar-change/open.png');
+ background-image: url('../png/controls/buttons/top/avatar-change/open.png');
}
#closed-mouth-blinking-image.border-default::before {
- background-image: url('../png/avatars/crab/closed-blink.png');
+ background-image: url('../png/avatars/crab/closed-blink.png');
}
#closed-mouth-blinking-image::after {
- background-image: url('../png/controls/buttons/top/avatar-change/closed-blink.png');
+ background-image: url('../png/controls/buttons/top/avatar-change/closed-blink.png');
}
#open-mouth-blinking-image.border-default::before {
- background-image: url('../png/avatars/crab/open-blink.png');
+ background-image: url('../png/avatars/crab/open-blink.png');
}
#open-mouth-blinking-image::after {
- background-image: url('../png/controls/buttons/top/avatar-change/open-blink.png');
+ background-image: url('../png/controls/buttons/top/avatar-change/open-blink.png');
}
button.motion {
- /* background-image: url('../png/controls/buttons/top/motion/template.png'); */
- position: relative;
- /* var(x): 0dip;
+ /* background-image: url('../png/controls/buttons/top/motion/template.png'); */
+ position: relative;
+ /* var(x): 0dip;
var(y): height(33%); */
- height: 50px;
- width: 50px;
+ height: 50px;
+ width: 50px;
}
-
.closed-mouth-motion {
- background-image: url('../png/controls/buttons/top/motion/closed.png');
- box-sizing: border-box;
- image-rendering: optimize-quality;
- height: 50px;
- width: 50px;
- background-color: #9bccd4;
+ background-image: url('../png/controls/buttons/top/motion/closed.png');
+ box-sizing: border-box;
+ image-rendering: optimize-quality;
+ height: 50px;
+ width: 50px;
+ background-color: #9bccd4;
}
.test {
- width: 50px;
- height: 50px;
- background-size: cover;
- overflow: hidden;
+ width: 50px;
+ height: 50px;
+ background-size: cover;
+ overflow: hidden;
}
.avatar-change {
- background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
- background-size: cover;
- width: 50px;
- height: 50px;
- position: relative;
- left: -5px;
+ background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
+ background-size: cover;
+ width: 50px;
+ height: 50px;
+ position: relative;
+ left: -5px;
}
.border {
- background-image: url('../png/controls/buttons/top/motion/border.png');
- background-size: cover;
- width: 50px;
- height: 50px;
- position: relative;
- top: -50px;
+ background-image: url('../png/controls/buttons/top/motion/border.png');
+ background-size: cover;
+ width: 50px;
+ height: 50px;
+ position: relative;
+ top: -50px;
}
.open-mouth-motion {
- background-image: url('../png/controls/buttons/top/motion/open.png');
- box-sizing: border-box;
- image-rendering: optimize-quality;
- height: 50px;
- width: 50px;
+ background-image: url('../png/controls/buttons/top/motion/open.png');
+ box-sizing: border-box;
+ image-rendering: optimize-quality;
+ height: 50px;
+ width: 50px;
}
.mouth-transition {
- background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
- box-sizing: border-box;
- image-rendering: optimize-quality;
- height: 50px;
- width: 50px;
- background-position: 50% 50%;
- background-color: yellow;
+ background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
+ box-sizing: border-box;
+ image-rendering: optimize-quality;
+ height: 50px;
+ width: 50px;
+ background-position: 50% 50%;
+ background-color: yellow;
}
.mouth-transitionx {
- background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
- box-sizing: border-box;
- image-rendering: optimize-quality;
- height: 50px;
- width: 50px;
- background-position: 50% 50%;
- background-color: red;
+ background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
+ box-sizing: border-box;
+ image-rendering: optimize-quality;
+ height: 50px;
+ width: 50px;
+ background-position: 50% 50%;
+ background-color: red;
}
-
#mouth-transition::before {
- background-color: red;
- background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
+ background-color: red;
+ background-image: url('../png/controls/buttons/top/avatar-change/border/default.png');
}
button.motion::before {
- position: absolute;
- width: 50px;
- height: 90%;
- background-size: 105% 105%;
- transform: translate(-11%, -11%);
- /* background-position: -50% -50%; */
- overflow: hidden;
- z-index: -1;
- /* hit-margin: -999px; */
+ position: absolute;
+ width: 50px;
+ height: 90%;
+ background-size: 105% 105%;
+ transform: translate(-11%, -11%);
+ /* background-position: -50% -50%; */
+ overflow: hidden;
+ z-index: -1;
+ /* hit-margin: -999px; */
}
#closed-mouth-motion::before {
- background-color: #2ebe38;
+ background-color: #2ebe38;
}
#open-mouth-motion::before {
- background-image: url('../png/controls/buttons/top/motion/open.png');
- height: 50px;
- width: 50px;
- pointer-events: none;
- background-color: yellow;
+ background-image: url('../png/controls/buttons/top/motion/open.png');
+ height: 50px;
+ width: 50px;
+ pointer-events: none;
+ background-color: yellow;
}
button.motion::after {
- position: absolute;
- width: 80%;
- height: 80%;
- background-color: red;
- overflow: hidden;
- z-index: -1;
- transform: translate(11%, 11%);
- /* hit-margin: -999px; */
+ position: absolute;
+ width: 80%;
+ height: 80%;
+ background-color: red;
+ overflow: hidden;
+ z-index: -1;
+ transform: translate(11%, 11%);
+ /* hit-margin: -999px; */
}
#set-hotkey {
- background-image: url('../png/controls/buttons/top/hotkey/set/default.png');
+ background-image: url('../png/controls/buttons/top/hotkey/set/default.png');
}
#hotkey-mode {
- background-image: url('../png/controls/buttons/top/hotkey/mode/0.png');
+ background-image: url('../png/controls/buttons/top/hotkey/mode/0.png');
}
#delete-state {
- background-image: url('../png/controls/buttons/right/delete.png');
+ background-image: url('../png/controls/buttons/right/delete.png');
}
#about {
- background-image: url('../png/controls/buttons/top/info.png');
+ background-image: url('../png/controls/buttons/top/info.png');
}
#close {
- background-image: url('../png/controls/buttons/top/close.png');
+ background-image: url('../png/controls/buttons/top/close.png');
}
#avatar {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- width: 40%;
- height: width(100%);
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ width: 40%;
+ height: width(100%);
}
-
-menu.popup {
- /* box-shadow: 3px 3px 1px rgba(0, 0, 0, 0.692); */
-}
\ No newline at end of file
diff --git a/src/modules/vtuber/html/about.html b/src/modules/vtuber/html/about.html
index 5a1d1a6..36cf9cb 100644
--- a/src/modules/vtuber/html/about.html
+++ b/src/modules/vtuber/html/about.html
@@ -38,4 +38,4 @@