From ae14ac145d38607a9be20835614f5db38f16b516 Mon Sep 17 00:00:00 2001 From: ArabCoders Date: Tue, 9 Jul 2024 23:40:44 +0300 Subject: [PATCH 1/2] Updated terminal window --- Pipfile.lock | 6 +- app/main.py | 69 ++++++--- frontend/package.json | 4 +- frontend/src/App.vue | 10 +- frontend/src/components/CLI-Console.vue | 188 +++++++++++++++++------ frontend/src/components/CLI-Terminal.vue | 142 +++++++++++++++++ frontend/src/components/Page-Header.vue | 2 +- frontend/src/main.js | 6 +- 8 files changed, 343 insertions(+), 84 deletions(-) create mode 100644 frontend/src/components/CLI-Terminal.vue diff --git a/Pipfile.lock b/Pipfile.lock index d4b2dc6d..c81e79ae 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1098,12 +1098,12 @@ }, "yt-dlp": { "hashes": [ - "sha256:2b0c86b579d4a044eaf3c4b00e3d7b24d82e6e26869fa11c288ea4395b387f41", - "sha256:4f76b48244c783e6ac06e8d7627bcf62cbeb4f6d79ba7e3cfc8249e680d4e691" + "sha256:b50a595abde523b5cc84d788f97e69c642503bd673ba740f709ebf65b5ec6592", + "sha256:e19f00f9e55e90bca1c94bcaf809aa33e51634be9f0de2df84a72d3206934f94" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2024.7.2" + "version": "==2024.7.9" } }, "develop": {} diff --git a/app/main.py b/app/main.py index 94150f00..77f88e2c 100644 --- a/app/main.py +++ b/app/main.py @@ -140,7 +140,7 @@ class Main: # get directory listing dlDir: str = self.config.download_path - data['directories'] = [ name for name in os.listdir(dlDir) if os.path.isdir(os.path.join(dlDir, name)) ] + data['directories'] = [name for name in os.listdir(dlDir) if os.path.isdir(os.path.join(dlDir, name))] await self.sio.emit('initial_data', self.serializer.encode(data), to=sid) @@ -500,36 +500,55 @@ class Main: @self.sio.event() async def cli_post(sid, data): if not data: + await self.sio.emit('cli_close', {'exitcode': 0}) return - async def _read_stream(streamType, stream): - while True: - line = await stream.readline() - if line: - await self.sio.emit('cli_output', { - 'type': streamType, - 'line': line.decode('utf-8') - }) - else: - break + proc = None - proc = await asyncio.subprocess.create_subprocess_exec( - 'yt-dlp', data, - cwd=self.config.download_path, - stdin=asyncio.subprocess.DEVNULL, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE - ) + try: + async def _read_stream(streamType, stream): + while True: + line = await stream.readline() + if line: + await self.sio.emit('cli_output', { + 'type': streamType, + 'line': line.decode('utf-8') + }) + else: + break - await asyncio.gather( - _read_stream('stdout', proc.stdout), - _read_stream('stderr', proc.stderr), - ) + LOG.info(f'CLI: {data}') + proc = await asyncio.subprocess.create_subprocess_exec( + 'yt-dlp', data, + cwd=self.config.download_path, + stdin=asyncio.subprocess.DEVNULL, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + env=os.environ.copy().update({ + "TERM": "xterm-256color", + "LANG": "en_US.UTF-8", + "SHELL": "/bin/bash", + "LC_ALL": "en_US.UTF-8", + "PWD": self.config.download_path, + }), + ) - while proc.returncode is None: - await asyncio.sleep(0.1) + await asyncio.gather( + _read_stream('stdout', proc.stdout), + _read_stream('stderr', proc.stderr), + ) - await self.sio.emit('cli_close', {'exitcode': proc.returncode}) + while proc.returncode is None: + await asyncio.sleep(0.1) + + await self.sio.emit('cli_close', {'exitcode': proc.returncode}) + except Exception as e: + LOG.error(f'CLI Error: {str(e)}') + await self.sio.emit('cli_output', { + 'type': 'stderr', + 'line': str(e), + }) + await self.sio.emit('cli_close', {'exitcode': -1}) @self.sio.event() async def connect(sid, environ): diff --git a/frontend/package.json b/frontend/package.json index a7b4dea9..e3235457 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,7 +22,9 @@ "plyr": "^3.7.8", "socket.io-client": "^4.7.2", "vue": "^3.4.27", - "vue-toastification": "^2.0.0-rc.5" + "vue-toastification": "^2.0.0-rc.5", + "@xterm/addon-fit": "^0.10.0", + "@xterm/xterm": "^5.5.0" }, "devDependencies": { "@babel/core": "^7.12.16", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index b4d42167..beecf9d0 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,6 +1,6 @@ diff --git a/frontend/src/components/CLI-Terminal.vue b/frontend/src/components/CLI-Terminal.vue new file mode 100644 index 00000000..51f9fd08 --- /dev/null +++ b/frontend/src/components/CLI-Terminal.vue @@ -0,0 +1,142 @@ + + + diff --git a/frontend/src/components/Page-Header.vue b/frontend/src/components/Page-Header.vue index c59c6ff5..8565b1af 100644 --- a/frontend/src/components/Page-Header.vue +++ b/frontend/src/components/Page-Header.vue @@ -51,7 +51,7 @@ import { useStorage } from '@vueuse/core' const selectedTheme = useStorage('theme', (() => window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')()); -defineEmits(['toggleForm', 'toggleTasks']) +defineEmits(['toggleForm', 'toggleTasks', 'toggleConsole', 'reload']) defineProps({ config: { diff --git a/frontend/src/main.js b/frontend/src/main.js index af5e92a5..50f3f290 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -10,7 +10,8 @@ import { faTerminal, faBroom, faServer, - faPowerOff + faPowerOff, + faPaperPlane } from '@fortawesome/free-solid-svg-icons' import { faSquare, faSquareCheck } from '@fortawesome/free-regular-svg-icons' @@ -22,7 +23,8 @@ import 'floating-vue/dist/style.css' library.add(faCog, faTrash, faLink, faPlus, faTrashCan, faCircleXmark, faCircleCheck, faRotateRight, faDownload, faUpRightFromSquare, faSquare, faSquareCheck, faSpinner, faArrowUp, faArrowDown, faTasks, faCalendar, faArrowUpAZ, - faArrowDownAZ, faEject, faGlobe, faMoon, faSun, faTerminal, faBroom, faServer, faPowerOff) + faArrowDownAZ, faEject, faGlobe, faMoon, faSun, faTerminal, faBroom, faServer, faPowerOff, faBroom, faServer, + faPowerOff, faPaperPlane) const app = createApp(App); app.config.globalProperties.capitalize = s => s && s[0].toUpperCase() + s.slice(1); From 81bb0d9ee37b809afe11aac08b567ac0fe9418ec Mon Sep 17 00:00:00 2001 From: ArabCoders Date: Wed, 10 Jul 2024 01:51:18 +0300 Subject: [PATCH 2/2] fixes. --- frontend/package-lock.json | 58 +++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 45f89920..aaa75098 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,6 +13,8 @@ "@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/vue-fontawesome": "^3.0.5", "@vueuse/core": "^10.6.1", + "@xterm/addon-fit": "^0.10.0", + "@xterm/xterm": "^5.5.0", "core-js": "^3.8.3", "cron-parser": "^4.9.0", "floating-vue": "^5.0.2", @@ -3477,6 +3479,19 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@xterm/addon-fit": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz", + "integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==", + "peerDependencies": { + "@xterm/xterm": "^5.0.0" + } + }, + "node_modules/@xterm/xterm": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz", + "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==" + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -5393,14 +5408,14 @@ } }, "node_modules/engine.io-client": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", - "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0", + "ws": "~8.17.1", "xmlhttprequest-ssl": "~2.0.0" } }, @@ -11428,9 +11443,9 @@ } }, "node_modules/webpack-bundle-analyzer/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, "engines": { "node": ">=8.3.0" @@ -11650,27 +11665,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", @@ -11844,15 +11838,15 @@ "dev": true }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": {