From 8953e4fbfd3102775b21910059ce46a974cc4d61 Mon Sep 17 00:00:00 2001 From: neosubhamoy Date: Fri, 20 Sep 2024 21:49:02 +0530 Subject: [PATCH] (feat): added support for common rhel (rpm) based linux distros --- linux/src-tauri/tauri.conf.json | 24 +++++++ linux/src/App.tsx | 107 +++++++++++++++++++++++++++----- linux/src/lib/utils.ts | 45 ++++++++++++-- linux/src/types.ts | 4 ++ 4 files changed, 159 insertions(+), 21 deletions(-) diff --git a/linux/src-tauri/tauri.conf.json b/linux/src-tauri/tauri.conf.json index bf4b7a2..1f4874f 100644 --- a/linux/src-tauri/tauri.conf.json +++ b/linux/src-tauri/tauri.conf.json @@ -18,11 +18,21 @@ "sidecar": true, "open": true, "scope": [ + { + "name": "detect-distro", + "cmd": "grep", + "args": ["^ID=", "/etc/os-release"] + }, { "name": "is-apt-installed", "cmd": "apt", "args": ["--version"] }, + { + "name": "is-dnf-installed", + "cmd": "dnf", + "args": ["--version"] + }, { "name": "is-python-installed", "cmd": "python3", @@ -99,6 +109,20 @@ "/usr/bin/pytubepp-helper-autostart": "./target/release/pytubepp-helper-autostart", "/etc/xdg/autostart/pytubepp-helper-autostart.desktop": "./autostart/pytubepp-helper-autostart.desktop" } + }, + "rpm": { + "epoch": 0, + "release": "1", + "license": "MIT", + "depends": ["python3-pip", "ffmpeg-free"], + "files": { + "/etc/opt/chrome/native-messaging-hosts/com.neosubhamoy.pytubepp.helper.json": "./msghost-manifest/chrome/com.neosubhamoy.pytubepp.helper.json", + "/etc/chromium/native-messaging-hosts/com.neosubhamoy.pytubepp.helper.json": "./msghost-manifest/chrome/com.neosubhamoy.pytubepp.helper.json", + "/usr/lib/mozilla/native-messaging-hosts/com.neosubhamoy.pytubepp.helper.json": "./msghost-manifest/firefox/com.neosubhamoy.pytubepp.helper.json", + "/usr/bin/pytubepp-helper-msghost": "./target/release/pytubepp-helper-msghost", + "/usr/bin/pytubepp-helper-autostart": "./target/release/pytubepp-helper-autostart", + "/etc/xdg/autostart/pytubepp-helper-autostart.desktop": "./autostart/pytubepp-helper-autostart.desktop" + } } }, "systemTray": { diff --git a/linux/src/App.tsx b/linux/src/App.tsx index 419fea8..51dd5d3 100644 --- a/linux/src/App.tsx +++ b/linux/src/App.tsx @@ -5,9 +5,9 @@ import { listen } from '@tauri-apps/api/event'; import { appWindow } from '@tauri-apps/api/window'; import { ThemeProvider } from "@/components/theme-provider"; import { Button } from "@/components/ui/button"; -import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" +import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { InstalledPrograms, WebSocketMessage, } from "./types"; -import { compareVersions, extract_version, is_installed, sendStreamInfo } from "./lib/utils"; +import { compareVersions, extractVersion, isInstalled, sendStreamInfo, extractDistroId, detectDistro, detectDistroBase } from "./lib/utils"; import { CircleCheck, TriangleAlert, CircleAlert } from 'lucide-react'; function App() { @@ -19,12 +19,18 @@ function App() { appWindow.onCloseRequested(handleCloseRequested); }, []); - + + const [distroId, setDistroId] = useState(null) + const [distroBase, setDistroBase] = useState(null) const [installedPrograms, setInstalledPrograms] = useState({ apt: { installed: false, version: null, }, + dnf: { + installed: false, + version: null, + }, python: { installed: false, version: null, @@ -71,56 +77,71 @@ function App() { }; }, []); - function check_all_programs() { - is_installed('apt', '--version').then((result) => { + function checkAllPrograms() { + isInstalled('apt', '--version').then((result) => { setInstalledPrograms((prevState) => ({ ...prevState, apt: { installed: result.installed, - version: result.output ? extract_version(result.output) : null, + version: result.output ? extractVersion(result.output) : null, } })); }); - is_installed('python', '--version').then((result) => { + isInstalled('dnf', '--version').then((result) => { + setInstalledPrograms((prevState) => ({ + ...prevState, + dnf: { + installed: result.installed, + version: result.output ? extractVersion(result.output) : null, + } + })); + }); + isInstalled('python', '--version').then((result) => { setInstalledPrograms((prevState) => ({ ...prevState, python: { installed: result.installed, - version: result.output ? extract_version(result.output) : null, + version: result.output ? extractVersion(result.output) : null, } })); }); - is_installed('pip', '--version').then((result) => { + isInstalled('pip', '--version').then((result) => { setInstalledPrograms((prevState) => ({ ...prevState, pip: { installed: result.installed, - version: result.output ? extract_version(result.output) : null, + version: result.output ? extractVersion(result.output) : null, } })); }); - is_installed('ffmpeg', '-version').then((result) => { + isInstalled('ffmpeg', '-version').then((result) => { setInstalledPrograms((prevState) => ({ ...prevState, ffmpeg: { installed: result.installed, - version: result.output ? extract_version(result.output) : null, + version: result.output ? extractVersion(result.output) : null, } })); }); - is_installed('pytubepp', '--version').then((result) => { + isInstalled('pytubepp', '--version').then((result) => { setInstalledPrograms((prevState) => ({ ...prevState, pytubepp: { installed: result.installed, - version: result.output ? extract_version(result.output) : null, + version: result.output ? extractVersion(result.output) : null, } })); }); } useEffect(() => { - check_all_programs(); + checkAllPrograms(); + detectDistro().then((result) => { + if(result) { + setDistroId(extractDistroId(result)) + setDistroBase(detectDistroBase(extractDistroId(result))) + } + }) } , []); @@ -129,8 +150,9 @@ function App() {

PytubePP Helper

- +
+ { distroId && distroBase && distroBase === 'debian' ?

Python: {installedPrograms.python.installed ? 'installed' : 'not installed'} {installedPrograms.python.version ? `(${installedPrograms.python.version})` : ''}

@@ -172,6 +194,59 @@ function App() { : null}
+ : distroId && distroBase && distroBase === 'rhel' ? +
+
+

Python: {installedPrograms.python.installed ? 'installed' : 'not installed'} {installedPrograms.python.version ? `(${installedPrograms.python.version})` : ''}

+ {installedPrograms.python.installed ? installedPrograms.python.version ? compareVersions(installedPrograms.python.version, '3.8') < 0 ? : : installedPrograms.dnf.installed ? : : null} +
+
+

FFmpeg: {installedPrograms.ffmpeg.installed ? 'installed' : 'not installed'} {installedPrograms.ffmpeg.version ? `(${installedPrograms.ffmpeg.version})` : ''}

+ {installedPrograms.ffmpeg.installed ? : installedPrograms.dnf.installed ? : null} +
+
+

PytubePP: {installedPrograms.pytubepp.installed ? 'installed' : 'not installed'} {installedPrograms.pytubepp.version ? `(${installedPrograms.pytubepp.version})` : ''}

+ {installedPrograms.pytubepp.installed ? : installedPrograms.pip.installed ? : null} +
+ {(!installedPrograms.dnf.installed && (!installedPrograms.python.installed || !installedPrograms.ffmpeg.installed)) ? + + + DNF Not Found + + DNF is required to install necessary debian packages. Please install it manually for your distro. + + + : null} + {(!installedPrograms.pip.installed && !installedPrograms.pytubepp.installed) ? + + + PIP Not Found + + PIP is required to install necessary python packages. Please install it now to continue: + + + : null} + {(installedPrograms.python.installed && installedPrograms.ffmpeg.installed && installedPrograms.pytubepp.installed) ? + + + Ready + + Everything looks ok! You can close this window now. Make sure it's always running in the background. + + + : null} +
+ : +
+ + + Unsupported Distro + + Sorry, your linux distro is currently not supported. If you think this is just a mistake or you want to request us to add support for your distro you can create a github issue here. + + +
+ }
); diff --git a/linux/src/lib/utils.ts b/linux/src/lib/utils.ts index c29f26f..31fbd02 100644 --- a/linux/src/lib/utils.ts +++ b/linux/src/lib/utils.ts @@ -4,7 +4,7 @@ import { Command } from '@tauri-apps/api/shell'; import { Stream } from "@/types"; import { invoke } from "@tauri-apps/api"; -export function extract_xml(input: string): string[] { +export function extractXml(input: string): string[] { const regex = /]+>/g; const matches = input.match(regex); return matches ? matches : []; @@ -27,7 +27,7 @@ function parseAttributes(attributesString: string): Partial { return attributes; } -export function convert_xml_to_json(xmlStrings: string[]): Stream[] { +export function convertXmlToJson(xmlStrings: string[]): Stream[] { return xmlStrings .map(xmlString => { const attributesString = xmlString.replace('', ''); @@ -40,7 +40,7 @@ export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } -export async function is_installed(program: string, arg: string): Promise<{ installed: boolean, output: string | null }> { +export async function isInstalled(program: string, arg: string): Promise<{ installed: boolean, output: string | null }> { try{ const output = await new Command('is-' + program + '-installed', [arg]).execute(); if (output.code === 0) { @@ -54,13 +54,42 @@ export async function is_installed(program: string, arg: string): Promise<{ inst } } -export function extract_version(output: string): string | null { +export async function detectDistro(): Promise { + try{ + const output = await new Command('detect-distro', ['^ID=', '/etc/os-release']).execute(); + if (output.code === 0) { + return output.stdout; + } else { + return output.stdout; + } + } catch (error) { + console.error(error); + return null; + } +} + +export function detectDistroBase(distro: string | null): string | null{ + if(distro) { + if(['debian', 'ubuntu', 'pop', 'kali'].includes(distro)) { + return 'debian'; + } else if (['rhel', 'fedora', 'centos', 'rocky'].includes(distro)) { + return 'rhel'; + } else { + return 'other'; + } + } else { + return null; + } +} + +export function extractVersion(output: string): string | null { const versionPatterns = [ /ffmpeg version (\d+\.\d+)/, // Pattern for ffmpeg /Python (\d+\.\d+\.\d+)/, // Pattern for Python /pytubefix (\d+\.\d+\.\d+)/, // Pattern for pytubefix /pytubepp (\d+\.\d+\.\d+)/, // Pattern for pytubepp /apt (\d+\.\d+\.\d+)/, // Pattern for apt + /(\d+\.\d+\.\d+)/, // Pattern for dnf /pip (\d+\.\d+)/, // Pattern for pip ]; @@ -73,6 +102,12 @@ export function extract_version(output: string): string | null { return null; } +export function extractDistroId(input: string): string | null { + const regex = /ID=([a-zA-Z]+)/; + const match = input.match(regex); + return match ? match[1] : null; +} + export async function sendStreamInfo(url: string) { const fetchData = async () => { try { @@ -81,7 +116,7 @@ export async function sendStreamInfo(url: string) { console.log(output.stdout); const sendStreamData = async () => { try { - const streamsstr = JSON.stringify(convert_xml_to_json(extract_xml(output.stdout))) + const streamsstr = JSON.stringify(convertXmlToJson(extractXml(output.stdout))) await invoke('receive_frontend_response', { response: streamsstr }); } catch (error) { console.error(error); diff --git a/linux/src/types.ts b/linux/src/types.ts index b47bd11..bfc5c91 100644 --- a/linux/src/types.ts +++ b/linux/src/types.ts @@ -3,6 +3,10 @@ export interface InstalledPrograms { installed: boolean; version: string | null; }; + dnf: { + installed: boolean; + version: string | null; + } python: { installed: boolean; version: string | null;