mirror of
https://github.com/neosubhamoy/neodlp.git
synced 2026-03-23 04:15:49 +05:30
Compare commits
14 Commits
v0.4.1
...
b3d99f3334
@@ -83,9 +83,10 @@ After installing the extension you can do the following directly from the browse
|
|||||||
| Platform (OS) | Distribution Channel | Installation Command / Instruction |
|
| Platform (OS) | Distribution Channel | Installation Command / Instruction |
|
||||||
| :---- | :---- | :---- |
|
| :---- | :---- | :---- |
|
||||||
| Windows x86_64 / ARM64 | WinGet | `winget install neosubhamoy.neodlp` |
|
| Windows x86_64 / ARM64 | WinGet | `winget install neosubhamoy.neodlp` |
|
||||||
|
| MacOS x86_64 / ARM64 | Homebrew | `brew install neosubhamoy/tap/neodlp` |
|
||||||
| MacOS x86_64 / ARM64 | Curl-Bash Installer | `curl -sSL https://neodlp.neosubhamoy.com/macos_installer.sh \| bash` |
|
| MacOS x86_64 / ARM64 | Curl-Bash Installer | `curl -sSL https://neodlp.neosubhamoy.com/macos_installer.sh \| bash` |
|
||||||
| Linux x86_64 / ARM64 | Curl-Bash Installer | `curl -sSL https://neodlp.neosubhamoy.com/linux_installer.sh \| bash` |
|
| Linux x86_64 / ARM64 | Curl-Bash Installer | `curl -sSL https://neodlp.neosubhamoy.com/linux_installer.sh \| bash` |
|
||||||
| Arch Linux x86_64 / ARM64 | AUR | `yay -S neodlp` |
|
| Arch Linux x86_64 / ARM64 | AUR | `yay -S neodlp` or `paru -S neodlp` |
|
||||||
|
|
||||||
## 🧪 Package Testing Status
|
## 🧪 Package Testing Status
|
||||||
|
|
||||||
|
|||||||
10
com.neosubhamoy.neodlp.desktop
Normal file
10
com.neosubhamoy.neodlp.desktop
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
|
||||||
|
Name=NeoDLP
|
||||||
|
Comment=Modern video/audio downloader based on yt-dlp with browser integration.
|
||||||
|
Icon=com.neosubhamoy.neodlp
|
||||||
|
Exec=neodlp
|
||||||
|
Terminal=false
|
||||||
|
Categories=Utility;
|
||||||
|
Keywords=neodlp;downloader;yt-dlp-gui;
|
||||||
31
com.neosubhamoy.neodlp.metainfo.xml
Normal file
31
com.neosubhamoy.neodlp.metainfo.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<component type="desktop-application">
|
||||||
|
<id>com.neosubhamoy.neodlp</id>
|
||||||
|
<name>NeoDLP</name>
|
||||||
|
<summary>Modern video/audio downloader based on yt-dlp with browser integration</summary>
|
||||||
|
<developer_name>Subhamoy Biswas</developer_name>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>MIT</project_license>
|
||||||
|
<url type="homepage">https://neodlp.neosubhamoy.com</url>
|
||||||
|
<url type="bugtracker">https://github.com/neosubhamoy/neodlp/issues</url>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
NeoDLP is a cross-platform desktop application designed for downloading videos and audio from various online sources based on yt-dlp.
|
||||||
|
|
||||||
|
It offers modern user interface, lots of customization options and seamless browser integration.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
<launchable type="desktop-id">com.neosubhamoy.neodlp.desktop</launchable>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">
|
||||||
|
<image>https://raw.githubusercontent.com/neosubhamoy/neodlp/main/.github/images/downloader.png</image>
|
||||||
|
<caption>NeoDLP Downloader</caption>
|
||||||
|
</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<content_rating type="oars-1.1" />
|
||||||
|
<releases>
|
||||||
|
<release version="0.4.2" date="2026-02-23">
|
||||||
|
<url type="details">https://github.com/neosubhamoy/neodlp/releases/tag/v0.4.2</url>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
|
</component>
|
||||||
@@ -64,6 +64,16 @@
|
|||||||
"name": "powershell",
|
"name": "powershell",
|
||||||
"cmd": "powershell",
|
"cmd": "powershell",
|
||||||
"args": true
|
"args": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cp",
|
||||||
|
"cmd": "cp",
|
||||||
|
"args": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "echo",
|
||||||
|
"cmd": "echo",
|
||||||
|
"args": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -184,6 +184,16 @@ fn get_current_app_path() -> Result<String, String> {
|
|||||||
.into_owned())
|
.into_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn is_flatpak() -> bool {
|
||||||
|
std::env::var("FLATPAK").is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn get_appimage_path() -> Option<String> {
|
||||||
|
std::env::var("APPDIR").ok()
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn update_config(
|
async fn update_config(
|
||||||
new_config: Config,
|
new_config: Config,
|
||||||
@@ -604,6 +614,8 @@ pub async fn run() {
|
|||||||
get_config_file_path,
|
get_config_file_path,
|
||||||
restart_websocket_server,
|
restart_websocket_server,
|
||||||
get_current_app_path,
|
get_current_app_path,
|
||||||
|
is_flatpak,
|
||||||
|
get_appimage_path
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
|||||||
51
src-tauri/tauri.linux-flatpak.conf.json
Normal file
51
src-tauri/tauri.linux-flatpak.conf.json
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"identifier": "com.neosubhamoy.neodlp",
|
||||||
|
"build": {
|
||||||
|
"beforeDevCommand": "npm run dev",
|
||||||
|
"beforeBuildCommand": "npm run build",
|
||||||
|
"devUrl": "http://localhost:1420",
|
||||||
|
"frontendDist": "../dist"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"windows": [
|
||||||
|
{
|
||||||
|
"title": "NeoDLP",
|
||||||
|
"width": 1080,
|
||||||
|
"height": 680,
|
||||||
|
"decorations": false,
|
||||||
|
"visible": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"security": {
|
||||||
|
"csp": null,
|
||||||
|
"capabilities": [
|
||||||
|
"default",
|
||||||
|
"shell-scope"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bundle": {
|
||||||
|
"active": true,
|
||||||
|
"targets": ["deb"],
|
||||||
|
"createUpdaterArtifacts": true,
|
||||||
|
"licenseFile": "../LICENSE",
|
||||||
|
"icon": [
|
||||||
|
"icons/32x32.png",
|
||||||
|
"icons/128x128.png",
|
||||||
|
"icons/128x128@2x.png",
|
||||||
|
"icons/icon.icns",
|
||||||
|
"icons/icon.ico"
|
||||||
|
],
|
||||||
|
"externalBin": [
|
||||||
|
"binaries/yt-dlp",
|
||||||
|
"binaries/ffmpeg",
|
||||||
|
"binaries/ffprobe",
|
||||||
|
"binaries/aria2c",
|
||||||
|
"binaries/deno",
|
||||||
|
"binaries/neodlp-pot"
|
||||||
|
],
|
||||||
|
"resources": {
|
||||||
|
"resources/plugins/yt-dlp-plugins/": "yt-dlp-plugins/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,28 +2,83 @@ import { join, resourceDir, homeDir } from "@tauri-apps/api/path";
|
|||||||
import * as fs from "@tauri-apps/plugin-fs";
|
import * as fs from "@tauri-apps/plugin-fs";
|
||||||
import { useKvPairs } from "@/helpers/use-kvpairs";
|
import { useKvPairs } from "@/helpers/use-kvpairs";
|
||||||
import { useSettingsPageStatesStore } from "@/services/store";
|
import { useSettingsPageStatesStore } from "@/services/store";
|
||||||
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
|
import { useLogger } from "@/helpers/use-logger";
|
||||||
|
import { Command } from "@tauri-apps/plugin-shell";
|
||||||
|
|
||||||
interface FileMap {
|
interface FileMap {
|
||||||
source: string;
|
source: string;
|
||||||
destination: string;
|
destination: string;
|
||||||
dir: string;
|
dir: string;
|
||||||
|
content?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useLinuxRegisterer() {
|
export function useLinuxRegisterer() {
|
||||||
const { saveKvPair } = useKvPairs();
|
const { saveKvPair } = useKvPairs();
|
||||||
const appVersion = useSettingsPageStatesStore(state => state.appVersion);
|
const appVersion = useSettingsPageStatesStore(state => state.appVersion);
|
||||||
|
const LOG = useLogger();
|
||||||
|
|
||||||
const registerToLinux = async () => {
|
const registerToLinux = async () => {
|
||||||
try {
|
try {
|
||||||
|
const isFlatpak = await invoke<boolean>('is_flatpak');
|
||||||
|
const resourceDirPath = isFlatpak ? '/app/lib/neodlp' : await resourceDir();
|
||||||
|
const homeDirPath = await homeDir();
|
||||||
|
const flatpakChromeManifestContent = {
|
||||||
|
name: "com.neosubhamoy.neodlp",
|
||||||
|
description: "NeoDLP MsgHost",
|
||||||
|
path: `${homeDirPath}/.local/bin/neodlp-msghost`,
|
||||||
|
type: "stdio",
|
||||||
|
allowed_origins: ["chrome-extension://mehopeailfjmiloiiohgicphlcgpompf/"]
|
||||||
|
};
|
||||||
|
const flatpakFirefoxManifestContent = {
|
||||||
|
name: "com.neosubhamoy.neodlp",
|
||||||
|
description: "NeoDLP MsgHost",
|
||||||
|
path: `${homeDirPath}/.local/bin/neodlp-msghost`,
|
||||||
|
type: "stdio",
|
||||||
|
allowed_extension: ["neodlp@neosubhamoy.com"]
|
||||||
|
};
|
||||||
|
|
||||||
const filesToCopy: FileMap[] = [
|
const filesToCopy: FileMap[] = [
|
||||||
{ source: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil.py', destination: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil.py', dir: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/' },
|
{ source: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil.py', destination: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil.py', dir: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/' },
|
||||||
{ source: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil_cli.py', destination: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil_cli.py', dir: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/' },
|
{ source: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil_cli.py', destination: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil_cli.py', dir: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/' },
|
||||||
{ source: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil_http.py', destination: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil_http.py', dir: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/' },
|
{ source: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil_http.py', destination: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/getpot_bgutil_http.py', dir: 'yt-dlp-plugins/bgutil-ytdlp-pot-provider/yt_dlp_plugins/extractor/' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const resourceDirPath = await resourceDir();
|
const filesToCopyFlatpak: FileMap[] = [
|
||||||
const homeDirPath = await homeDir();
|
{ source: 'chrome.json', destination: '.config/google-chrome/NativeMessagingHosts/com.neosubhamoy.neodlp.json', dir: '.config/google-chrome/NativeMessagingHosts/', content: JSON.stringify(flatpakChromeManifestContent, null, 2) },
|
||||||
|
{ source: 'chrome.json', destination: '.config/chromium/NativeMessagingHosts/com.neosubhamoy.neodlp.json', dir: '.config/chromium/NativeMessagingHosts/', content: JSON.stringify(flatpakChromeManifestContent, null, 2) },
|
||||||
|
{ source: 'firefox.json', destination: '.mozilla/native-messaging-hosts/com.neosubhamoy.neodlp.json', dir: '.mozilla/native-messaging-hosts/', content: JSON.stringify(flatpakFirefoxManifestContent, null, 2) },
|
||||||
|
];
|
||||||
|
|
||||||
|
LOG.info("LINUX REGISTERER", `Is Flatpak: ${isFlatpak}, Resource dir: ${resourceDirPath}, Home dir: ${homeDirPath}`);
|
||||||
|
|
||||||
|
if (isFlatpak) {
|
||||||
|
for (const file of filesToCopyFlatpak) {
|
||||||
|
const sourcePath = await join(resourceDirPath, file.source);
|
||||||
|
const destinationPath = await join(homeDirPath, file.destination);
|
||||||
|
const copyCommand = Command.create('cp', [sourcePath, destinationPath]);
|
||||||
|
|
||||||
|
const copyOutput = await copyCommand.execute();
|
||||||
|
if (copyOutput.code === 0) {
|
||||||
|
console.log(`File ${file.source} copied successfully to ${destinationPath}`);
|
||||||
|
LOG.info("LINUX REGISTERER", `File ${file.source} copied successfully to ${destinationPath}`);
|
||||||
|
if (file.content) {
|
||||||
|
const writeCommand = Command.create('echo', [file.content, '>', destinationPath]);
|
||||||
|
const writeOutput = await writeCommand.execute();
|
||||||
|
if (writeOutput.code === 0) {
|
||||||
|
console.log(`Content written successfully to ${destinationPath}`);
|
||||||
|
LOG.info("LINUX REGISTERER", `Content written successfully to ${destinationPath}`);
|
||||||
|
} else {
|
||||||
|
console.error(`Failed to write content to ${destinationPath}:`, writeOutput.stderr);
|
||||||
|
LOG.error("LINUX REGISTERER", `Failed to write content to ${destinationPath}: ${writeOutput.stderr}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(`Failed to copy file ${file.source} to ${destinationPath}:`, copyOutput.stderr);
|
||||||
|
LOG.error("LINUX REGISTERER", `Failed to copy file ${file.source} to ${destinationPath}: ${copyOutput.stderr}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (const file of filesToCopy) {
|
for (const file of filesToCopy) {
|
||||||
const sourcePath = await join(resourceDirPath, file.source);
|
const sourcePath = await join(resourceDirPath, file.source);
|
||||||
const destinationDir = await join(homeDirPath, file.dir);
|
const destinationDir = await join(homeDirPath, file.dir);
|
||||||
@@ -33,17 +88,22 @@ export function useLinuxRegisterer() {
|
|||||||
if (dirExists) {
|
if (dirExists) {
|
||||||
await fs.copyFile(sourcePath, destinationPath);
|
await fs.copyFile(sourcePath, destinationPath);
|
||||||
console.log(`File ${file.source} copied successfully to ${destinationPath}`);
|
console.log(`File ${file.source} copied successfully to ${destinationPath}`);
|
||||||
|
LOG.info("LINUX REGISTERER", `File ${file.source} copied successfully to ${destinationPath}`);
|
||||||
} else {
|
} else {
|
||||||
await fs.mkdir(destinationDir, { recursive: true })
|
await fs.mkdir(destinationDir, { recursive: true })
|
||||||
console.log(`Created dir ${destinationDir}`);
|
console.log(`Created dir ${destinationDir}`);
|
||||||
|
LOG.info("LINUX REGISTERER", `Created dir ${destinationDir}`);
|
||||||
await fs.copyFile(sourcePath, destinationPath);
|
await fs.copyFile(sourcePath, destinationPath);
|
||||||
console.log(`File ${file.source} copied successfully to ${destinationPath}`);
|
console.log(`File ${file.source} copied successfully to ${destinationPath}`);
|
||||||
|
LOG.info("LINUX REGISTERER", `File ${file.source} copied successfully to ${destinationPath}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveKvPair('linux_registered_version', appVersion);
|
saveKvPair('linux_registered_version', appVersion);
|
||||||
return { success: true, message: 'Registered successfully' }
|
return { success: true, message: 'Registered successfully' }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error copying files:', error);
|
console.error('Error copying files:', error);
|
||||||
|
LOG.error("LINUX REGISTERER", `Error copying files: ${error}`);
|
||||||
return { success: false, message: 'Failed to register' }
|
return { success: false, message: 'Failed to register' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,11 @@ export function useYtDlpUpdater() {
|
|||||||
|
|
||||||
const updateYtDlp = async () => {
|
const updateYtDlp = async () => {
|
||||||
const CURRENT_TIMESTAMP = Date.now();
|
const CURRENT_TIMESTAMP = Date.now();
|
||||||
|
const isFlatpak = await invoke<boolean>('is_flatpak');
|
||||||
setIsUpdatingYtDlp(true);
|
setIsUpdatingYtDlp(true);
|
||||||
LOG.info('NEODLP', 'Updating yt-dlp to latest version');
|
LOG.info('NEODLP', 'Updating yt-dlp to latest version');
|
||||||
try {
|
try {
|
||||||
const command = currentPlatform === 'linux' ? Command.create('pkexec', ['yt-dlp', '--update-to', ytDlpUpdateChannel]) : Command.sidecar('binaries/yt-dlp', ['--update-to', ytDlpUpdateChannel]);
|
const command = currentPlatform === 'linux' && !isFlatpak ? Command.create('pkexec', ['yt-dlp', '--update-to', ytDlpUpdateChannel]) : Command.sidecar('binaries/yt-dlp', ['--update-to', ytDlpUpdateChannel]);
|
||||||
const output = await command.execute();
|
const output = await command.execute();
|
||||||
if (output.code === 0) {
|
if (output.code === 0) {
|
||||||
console.log("yt-dlp updated successfully:", output.stdout);
|
console.log("yt-dlp updated successfully:", output.stdout);
|
||||||
|
|||||||
Reference in New Issue
Block a user